Blender V4.3
transform.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#include "util/transform.h"
6#include "util/projection.h"
7
8#include "util/boundbox.h"
9#include "util/math.h"
10
12
13/* Transform Inverse */
14
15static bool projection_matrix4_inverse(float R[][4], float M[][4])
16{
17 /* SPDX-License-Identifier: BSD-3-Clause
18 * Adapted from code:
19 * Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
20 * Digital Ltd. LLC. All rights reserved. */
21
22 /* forward elimination */
23 for (int i = 0; i < 4; i++) {
24 int pivot = i;
25 float pivotsize = M[i][i];
26
27 if (pivotsize < 0) {
28 pivotsize = -pivotsize;
29 }
30
31 for (int j = i + 1; j < 4; j++) {
32 float tmp = M[j][i];
33
34 if (tmp < 0) {
35 tmp = -tmp;
36 }
37
38 if (tmp > pivotsize) {
39 pivot = j;
40 pivotsize = tmp;
41 }
42 }
43
44 if (UNLIKELY(pivotsize == 0.0f)) {
45 return false;
46 }
47
48 if (pivot != i) {
49 for (int j = 0; j < 4; j++) {
50 float tmp;
51
52 tmp = M[i][j];
53 M[i][j] = M[pivot][j];
54 M[pivot][j] = tmp;
55
56 tmp = R[i][j];
57 R[i][j] = R[pivot][j];
58 R[pivot][j] = tmp;
59 }
60 }
61
62 for (int j = i + 1; j < 4; j++) {
63 float f = M[j][i] / M[i][i];
64
65 for (int k = 0; k < 4; k++) {
66 M[j][k] -= f * M[i][k];
67 R[j][k] -= f * R[i][k];
68 }
69 }
70 }
71
72 /* backward substitution */
73 for (int i = 3; i >= 0; --i) {
74 float f;
75
76 if (UNLIKELY((f = M[i][i]) == 0.0f)) {
77 return false;
78 }
79
80 for (int j = 0; j < 4; j++) {
81 M[i][j] /= f;
82 R[i][j] /= f;
83 }
84
85 for (int j = 0; j < i; j++) {
86 f = M[j][i];
87
88 for (int k = 0; k < 4; k++) {
89 M[j][k] -= f * M[i][k];
90 R[j][k] -= f * R[i][k];
91 }
92 }
93 }
94
95 return true;
96}
97
99{
101 float M[4][4], R[4][4];
102
103 memcpy(R, &tfmR, sizeof(R));
104 memcpy(M, &tfm, sizeof(M));
105
107 return projection_identity();
108 }
109
110 memcpy(&tfmR.x[0], R, sizeof(R));
111
112 return tfmR;
113}
114
120
121/* Motion Transform */
122
123float4 transform_to_quat(const Transform &tfm)
124{
125 double trace = (double)(tfm[0][0] + tfm[1][1] + tfm[2][2]);
126 float4 qt;
127
128 if (trace > 0.0) {
129 double s = sqrt(trace + 1.0);
130
131 qt.w = (float)(s / 2.0);
132 s = 0.5 / s;
133
134 qt.x = (float)((double)(tfm[2][1] - tfm[1][2]) * s);
135 qt.y = (float)((double)(tfm[0][2] - tfm[2][0]) * s);
136 qt.z = (float)((double)(tfm[1][0] - tfm[0][1]) * s);
137 }
138 else {
139 int i = 0;
140
141 if (tfm[1][1] > tfm[i][i]) {
142 i = 1;
143 }
144 if (tfm[2][2] > tfm[i][i]) {
145 i = 2;
146 }
147
148 int j = (i + 1) % 3;
149 int k = (j + 1) % 3;
150
151 double s = sqrt((double)(tfm[i][i] - (tfm[j][j] + tfm[k][k])) + 1.0);
152
153 double q[3];
154 q[i] = s * 0.5;
155 if (s != 0.0) {
156 s = 0.5 / s;
157 }
158
159 double w = (double)(tfm[k][j] - tfm[j][k]) * s;
160 q[j] = (double)(tfm[j][i] + tfm[i][j]) * s;
161 q[k] = (double)(tfm[k][i] + tfm[i][k]) * s;
162
163 qt.x = (float)q[0];
164 qt.y = (float)q[1];
165 qt.z = (float)q[2];
166 qt.w = (float)w;
167 }
168
169 return qt;
170}
171
172static void transform_decompose(DecomposedTransform *decomp, const Transform *tfm)
173{
174 /* extract translation */
175 decomp->y = make_float4(tfm->x.w, tfm->y.w, tfm->z.w, 0.0f);
176
177 /* extract rotation */
178 Transform M = *tfm;
179 M.x.w = 0.0f;
180 M.y.w = 0.0f;
181 M.z.w = 0.0f;
182
183#if 0
184 Transform R = M;
185 float norm;
186 int iteration = 0;
187
188 do {
189 Transform Rnext;
191
192 for (int i = 0; i < 3; i++)
193 for (int j = 0; j < 4; j++)
194 Rnext[i][j] = 0.5f * (R[i][j] + Rit[i][j]);
195
196 norm = 0.0f;
197 for (int i = 0; i < 3; i++) {
198 norm = max(norm,
199 fabsf(R[i][0] - Rnext[i][0]) + fabsf(R[i][1] - Rnext[i][1]) +
200 fabsf(R[i][2] - Rnext[i][2]));
201 }
202
203 R = Rnext;
204 iteration++;
205 } while (iteration < 100 && norm > 1e-4f);
206
208 R = R * transform_scale(-1.0f, -1.0f, -1.0f);
209
210 decomp->x = transform_to_quat(R);
211
212 /* extract scale and pack it */
213 Transform scale = transform_inverse(R) * M;
214 decomp->y.w = scale.x.x;
215 decomp->z = make_float4(scale.x.y, scale.x.z, scale.y.x, scale.y.y);
216 decomp->w = make_float4(scale.y.z, scale.z.x, scale.z.y, scale.z.z);
217#else
218 float3 colx = transform_get_column(&M, 0);
219 float3 coly = transform_get_column(&M, 1);
220 float3 colz = transform_get_column(&M, 2);
221
222 /* extract scale and shear first */
223 float3 scale, shear;
224 scale.x = len(colx);
225 colx = safe_divide(colx, scale.x);
226 shear.z = dot(colx, coly);
227 coly -= shear.z * colx;
228 scale.y = len(coly);
229 coly = safe_divide(coly, scale.y);
230 shear.y = dot(colx, colz);
231 colz -= shear.y * colx;
232 shear.x = dot(coly, colz);
233 colz -= shear.x * coly;
234 scale.z = len(colz);
235 colz = safe_divide(colz, scale.z);
236
237 transform_set_column(&M, 0, colx);
238 transform_set_column(&M, 1, coly);
239 transform_set_column(&M, 2, colz);
240
242 scale *= -1.0f;
243 M = M * transform_scale(-1.0f, -1.0f, -1.0f);
244 }
245
246 decomp->x = transform_to_quat(M);
247
248 decomp->y.w = scale.x;
249 decomp->z = make_float4(shear.z, shear.y, 0.0f, scale.y);
250 decomp->w = make_float4(shear.x, 0.0f, 0.0f, scale.z);
251#endif
252}
253
254void transform_motion_decompose(DecomposedTransform *decomp, const Transform *motion, size_t size)
255{
256 /* Decompose and correct rotation. */
257 for (size_t i = 0; i < size; i++) {
258 transform_decompose(decomp + i, motion + i);
259
260 if (i > 0) {
261 /* Ensure rotation around shortest angle, negated quaternions are the same
262 * but this means we don't have to do the check in quat_interpolate */
263 if (dot(decomp[i - 1].x, decomp[i].x) < 0.0f) {
264 decomp[i].x = -decomp[i].x;
265 }
266 }
267 }
268
269 /* Copy rotation to decomposed transform where scale is degenerate. This avoids weird object
270 * rotation interpolation when the scale goes to 0 for a time step.
271 *
272 * Note that this is very simple and naive implementation, which only deals with degenerated
273 * scale happening only on one frame. It is possible to improve it further by interpolating
274 * rotation into s degenerated range using rotation from time-steps from adjacent non-degenerated
275 * time steps. */
276 for (size_t i = 0; i < size; i++) {
277 const float3 scale = make_float3(decomp[i].y.w, decomp[i].z.w, decomp[i].w.w);
278 if (!is_zero(scale)) {
279 continue;
280 }
281
282 if (i > 0) {
283 decomp[i].x = decomp[i - 1].x;
284 }
285 else if (i < size - 1) {
286 decomp[i].x = decomp[i + 1].x;
287 }
288 }
289}
290
292{
293 return transform_scale(1.0f / (viewplane.right - viewplane.left),
294 1.0f / (viewplane.top - viewplane.bottom),
295 1.0f) *
296 transform_translate(-viewplane.left, -viewplane.bottom, 0.0f);
297}
298
sqrt(x)+1/max(0
MINLINE float safe_divide(float a, float b)
#define UNLIKELY(x)
typedef double(DMatrix)[4][4]
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
SIMD_FORCE_INLINE btScalar norm() const
Return the norm (length) of the vector.
Definition btVector3.h:263
float bottom
Definition boundbox.h:194
float top
Definition boundbox.h:195
float right
Definition boundbox.h:193
float left
Definition boundbox.h:192
additional_info("compositor_sum_squared_difference_float_shared") .push_constant(Type output_img float dot(value.rgb, luminance_coefficients)") .define("LOAD(value)"
ccl_device_inline Transform projection_to_transform(const ProjectionTransform &a)
ccl_device_inline ProjectionTransform projection_identity()
ccl_device_inline ProjectionTransform projection_transpose(const ProjectionTransform &a)
#define CCL_NAMESPACE_END
ccl_device_forceinline float4 make_float4(const float x, const float y, const float z, const float w)
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
#define fabsf(x)
int len
draw_view in_light_buf[] float
ccl_device_inline bool is_zero(const float2 a)
#define M
#define R
float4 y
Definition transform.h:24
float4 x
Definition transform.h:24
float4 z
Definition transform.h:24
float z
Definition sky_float3.h:27
float y
Definition sky_float3.h:27
float x
Definition sky_float3.h:27
Transform transform_transposed_inverse(const Transform &tfm)
static void transform_decompose(DecomposedTransform *decomp, const Transform *tfm)
float4 transform_to_quat(const Transform &tfm)
void transform_motion_decompose(DecomposedTransform *decomp, const Transform *motion, size_t size)
Transform transform_from_viewplane(BoundBox2D &viewplane)
static CCL_NAMESPACE_BEGIN bool projection_matrix4_inverse(float R[][4], float M[][4])
Definition transform.cpp:15
ProjectionTransform projection_inverse(const ProjectionTransform &tfm)
Definition transform.cpp:98
ccl_device_inline void transform_set_column(Transform *t, int column, float3 value)
Definition transform.h:331
ccl_device_inline float3 transform_get_column(const Transform *t, int column)
Definition transform.h:326
ccl_device_inline bool transform_negative_scale(const Transform &tfm)
Definition transform.h:363
ccl_device_inline Transform transform_translate(float3 t)
Definition transform.h:244
ccl_device_inline Transform transform_inverse(const Transform tfm)
Definition transform.h:423
ccl_device_inline Transform transform_scale(float3 s)
Definition transform.h:254
float max