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