Blender V4.3
uvproject.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <cmath>
10
11#include "MEM_guardedalloc.h"
12
13#include "DNA_camera_types.h"
14#include "DNA_object_types.h"
15
16#include "BLI_math_matrix.h"
17#include "BLI_math_rotation.h"
18#include "BLI_math_vector.h"
19#include "BLI_uvproject.h"
20
22 float camangle;
23 float camsize;
24 float xasp, yasp;
25 float shiftx, shifty;
26 float rotmat[4][4];
27 float caminv[4][4];
29};
30
31void BLI_uvproject_from_camera(float target[2], float source[3], ProjCameraInfo *uci)
32{
33 float pv4[4];
34
35 copy_v3_v3(pv4, source);
36 pv4[3] = 1.0;
37
38 /* rotmat is the object matrix in this case */
39 if (uci->do_rotmat) {
40 mul_m4_v4(uci->rotmat, pv4);
41 }
42
43 /* caminv is the inverse camera matrix */
44 mul_m4_v4(uci->caminv, pv4);
45
46 if (uci->do_pano) {
47 float angle = atan2f(pv4[0], -pv4[2]) / (float(M_PI) * 2.0f); /* angle around the camera */
48 if (uci->do_persp == false) {
49 target[0] = angle; /* no correct method here, just map to 0-1 */
50 target[1] = pv4[1] / uci->camsize;
51 }
52 else {
53 float vec2d[2]; /* 2D position from the camera */
54 vec2d[0] = pv4[0];
55 vec2d[1] = pv4[2];
56 target[0] = angle * (float(M_PI) / uci->camangle);
57 target[1] = pv4[1] / (len_v2(vec2d) * (uci->camsize * 2.0f));
58 }
59 }
60 else {
61 if (pv4[2] == 0.0f) {
62 pv4[2] = 0.00001f; /* don't allow div by 0 */
63 }
64
65 if (uci->do_persp == false) {
66 target[0] = (pv4[0] / uci->camsize);
67 target[1] = (pv4[1] / uci->camsize);
68 }
69 else {
70 target[0] = (-pv4[0] * ((1.0f / uci->camsize) / pv4[2])) / 2.0f;
71 target[1] = (-pv4[1] * ((1.0f / uci->camsize) / pv4[2])) / 2.0f;
72 }
73 }
74
75 target[0] *= uci->xasp;
76 target[1] *= uci->yasp;
77
78 /* adds camera shift + 0.5 */
79 target[0] += uci->shiftx;
80 target[1] += uci->shifty;
81}
82
83void BLI_uvproject_from_view(float target[2],
84 float source[3],
85 float persmat[4][4],
86 float rotmat[4][4],
87 float winx,
88 float winy)
89{
90 float pv4[4], x = 0.0, y = 0.0;
91
92 copy_v3_v3(pv4, source);
93 pv4[3] = 1.0;
94
95 /* rotmat is the object matrix in this case */
96 mul_m4_v4(rotmat, pv4);
97
98 /* almost ED_view3d_project_short */
99 mul_m4_v4(persmat, pv4);
100 if (fabsf(pv4[3]) > 0.00001f) { /* avoid division by zero */
101 target[0] = winx / 2.0f + (winx / 2.0f) * pv4[0] / pv4[3];
102 target[1] = winy / 2.0f + (winy / 2.0f) * pv4[1] / pv4[3];
103 }
104 else {
105 /* scaling is lost but give a valid result */
106 target[0] = winx / 2.0f + (winx / 2.0f) * pv4[0];
107 target[1] = winy / 2.0f + (winy / 2.0f) * pv4[1];
108 }
109
110 /* v3d->persmat seems to do this funky scaling */
111 if (winx > winy) {
112 y = (winx - winy) / 2.0f;
113 winy = winx;
114 }
115 else {
116 x = (winy - winx) / 2.0f;
117 winx = winy;
118 }
119
120 target[0] = (x + target[0]) / winx;
121 target[1] = (y + target[1]) / winy;
122}
123
125 const float rotmat[4][4],
126 float winx,
127 float winy)
128{
129 ProjCameraInfo uci;
130 const Camera *camera = static_cast<Camera *>(ob->data);
131
132 uci.do_pano = (camera->type == CAM_PANO);
133 uci.do_persp = (camera->type == CAM_PERSP);
134
135 uci.camangle = focallength_to_fov(camera->lens, camera->sensor_x) / 2.0f;
136 uci.camsize = uci.do_persp ? tanf(uci.camangle) : camera->ortho_scale;
137
138 /* account for scaled cameras */
139 copy_m4_m4(uci.caminv, ob->object_to_world().ptr());
140 normalize_m4(uci.caminv);
141
142 if (invert_m4(uci.caminv)) {
143 ProjCameraInfo *uci_pt;
144
145 /* normal projection */
146 if (rotmat) {
147 copy_m4_m4(uci.rotmat, rotmat);
148 uci.do_rotmat = true;
149 }
150 else {
151 uci.do_rotmat = false;
152 }
153
154 /* also make aspect ratio adjustment factors */
155 if (winx > winy) {
156 uci.xasp = 1.0f;
157 uci.yasp = winx / winy;
158 }
159 else {
160 uci.xasp = winy / winx;
161 uci.yasp = 1.0f;
162 }
163
164 /* include 0.5f here to move the UVs into the center */
165 uci.shiftx = 0.5f - (camera->shiftx * uci.xasp);
166 uci.shifty = 0.5f - (camera->shifty * uci.yasp);
167
168 uci_pt = static_cast<ProjCameraInfo *>(MEM_mallocN(sizeof(ProjCameraInfo), __func__));
169 *uci_pt = uci;
170 return uci_pt;
171 }
172
173 return nullptr;
174}
175
176void BLI_uvproject_from_view_ortho(float target[2], float source[3], const float rotmat[4][4])
177{
178 float pv[3];
179
180 mul_v3_m4v3(pv, rotmat, source);
181
182 /* ortho projection */
183 target[0] = -pv[0];
184 target[1] = pv[2];
185}
186
187void BLI_uvproject_camera_info_scale(ProjCameraInfo *uci, float scale_x, float scale_y)
188{
189 uci->xasp *= scale_x;
190 uci->yasp *= scale_y;
191}
#define M_PI
void copy_m4_m4(float m1[4][4], const float m2[4][4])
void mul_v3_m4v3(float r[3], const float mat[4][4], const float vec[3])
void mul_m4_v4(const float mat[4][4], float r[4])
bool invert_m4(float mat[4][4])
void normalize_m4(float R[4][4]) ATTR_NONNULL()
float focallength_to_fov(float focal_length, float sensor)
MINLINE float len_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v3_v3(float r[3], const float a[3])
@ CAM_PERSP
@ CAM_PANO
Object is a sort of wrapper for general info.
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:125
Read Guarded memory(de)allocation.
#define tanf(x)
#define atan2f(x, y)
#define fabsf(x)
draw_view in_light_buf[] float
GREAL2 vec2d[2]
Double vector 2D.
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
float rotmat[4][4]
Definition uvproject.cc:26
float caminv[4][4]
Definition uvproject.cc:27
void BLI_uvproject_from_view(float target[2], float source[3], float persmat[4][4], float rotmat[4][4], float winx, float winy)
Definition uvproject.cc:83
void BLI_uvproject_from_camera(float target[2], float source[3], ProjCameraInfo *uci)
Definition uvproject.cc:31
void BLI_uvproject_camera_info_scale(ProjCameraInfo *uci, float scale_x, float scale_y)
Definition uvproject.cc:187
void BLI_uvproject_from_view_ortho(float target[2], float source[3], const float rotmat[4][4])
Definition uvproject.cc:176
ProjCameraInfo * BLI_uvproject_camera_info(const Object *ob, const float rotmat[4][4], float winx, float winy)
Definition uvproject.cc:124