Blender V4.5
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
20
21/* Motion Transform */
22
24{
25 const double trace = (double)(tfm[0][0] + tfm[1][1] + tfm[2][2]);
26 float4 qt;
27
28 if (trace > 0.0) {
29 double s = sqrt(trace + 1.0);
30
31 qt.w = (float)(s / 2.0);
32 s = 0.5 / s;
33
34 qt.x = (float)((double)(tfm[2][1] - tfm[1][2]) * s);
35 qt.y = (float)((double)(tfm[0][2] - tfm[2][0]) * s);
36 qt.z = (float)((double)(tfm[1][0] - tfm[0][1]) * s);
37 }
38 else {
39 int i = 0;
40
41 if (tfm[1][1] > tfm[i][i]) {
42 i = 1;
43 }
44 if (tfm[2][2] > tfm[i][i]) {
45 i = 2;
46 }
47
48 const int j = (i + 1) % 3;
49 const int k = (j + 1) % 3;
50
51 double s = sqrt((double)(tfm[i][i] - (tfm[j][j] + tfm[k][k])) + 1.0);
52
53 double q[3];
54 q[i] = s * 0.5;
55 if (s != 0.0) {
56 s = 0.5 / s;
57 }
58
59 const double w = (double)(tfm[k][j] - tfm[j][k]) * s;
60 q[j] = (double)(tfm[j][i] + tfm[i][j]) * s;
61 q[k] = (double)(tfm[k][i] + tfm[i][k]) * s;
62
63 qt.x = (float)q[0];
64 qt.y = (float)q[1];
65 qt.z = (float)q[2];
66 qt.w = (float)w;
67 }
68
69 return qt;
70}
71
72static void transform_decompose(DecomposedTransform *decomp, const Transform *tfm)
73{
74 /* extract translation */
75 decomp->y = make_float4(tfm->x.w, tfm->y.w, tfm->z.w, 0.0f);
76
77 /* extract rotation */
78 Transform M = *tfm;
79 M.x.w = 0.0f;
80 M.y.w = 0.0f;
81 M.z.w = 0.0f;
82
83#if 0
84 Transform R = M;
85 float norm;
86 int iteration = 0;
87
88 do {
89 Transform Rnext;
91
92 for (int i = 0; i < 3; i++)
93 for (int j = 0; j < 4; j++)
94 Rnext[i][j] = 0.5f * (R[i][j] + Rit[i][j]);
95
96 norm = 0.0f;
97 for (int i = 0; i < 3; i++) {
98 norm = max(norm,
99 fabsf(R[i][0] - Rnext[i][0]) + fabsf(R[i][1] - Rnext[i][1]) +
100 fabsf(R[i][2] - Rnext[i][2]));
101 }
102
103 R = Rnext;
104 iteration++;
105 } while (iteration < 100 && norm > 1e-4f);
106
108 R = R * transform_scale(-1.0f, -1.0f, -1.0f);
109
110 decomp->x = transform_to_quat(R);
111
112 /* extract scale and pack it */
113 Transform scale = transform_inverse(R) * M;
114 decomp->y.w = scale.x.x;
115 decomp->z = make_float4(scale.x.y, scale.x.z, scale.y.x, scale.y.y);
116 decomp->w = make_float4(scale.y.z, scale.z.x, scale.z.y, scale.z.z);
117#else
118 float3 colx = transform_get_column(&M, 0);
119 float3 coly = transform_get_column(&M, 1);
120 float3 colz = transform_get_column(&M, 2);
121
122 /* extract scale and shear first */
123 float3 scale;
124 float3 shear;
125 scale.x = len(colx);
126 colx = safe_divide(colx, scale.x);
127 shear.z = dot(colx, coly);
128 coly -= shear.z * colx;
129 scale.y = len(coly);
130 coly = safe_divide(coly, scale.y);
131 shear.y = dot(colx, colz);
132 colz -= shear.y * colx;
133 shear.x = dot(coly, colz);
134 colz -= shear.x * coly;
135 scale.z = len(colz);
136 colz = safe_divide(colz, scale.z);
137
138 transform_set_column(&M, 0, colx);
139 transform_set_column(&M, 1, coly);
140 transform_set_column(&M, 2, colz);
141
143 scale *= -1.0f;
144 M = M * transform_scale(-1.0f, -1.0f, -1.0f);
145 }
146
147 decomp->x = transform_to_quat(M);
148
149 decomp->y.w = scale.x;
150 decomp->z = make_float4(shear.z, shear.y, 0.0f, scale.y);
151 decomp->w = make_float4(shear.x, 0.0f, 0.0f, scale.z);
152#endif
153}
154
156 const Transform *motion,
157 const size_t size)
158{
159 /* Decompose and correct rotation. */
160 for (size_t i = 0; i < size; i++) {
161 transform_decompose(decomp + i, motion + i);
162
163 if (i > 0) {
164 /* Ensure rotation around shortest angle, negated quaternions are the same
165 * but this means we don't have to do the check in quat_interpolate */
166 if (dot(decomp[i - 1].x, decomp[i].x) < 0.0f) {
167 decomp[i].x = -decomp[i].x;
168 }
169 }
170 }
171
172 /* Copy rotation to decomposed transform where scale is degenerate. This avoids weird object
173 * rotation interpolation when the scale goes to 0 for a time step.
174 *
175 * Note that this is very simple and naive implementation, which only deals with degenerated
176 * scale happening only on one frame. It is possible to improve it further by interpolating
177 * rotation into s degenerated range using rotation from time-steps from adjacent non-degenerated
178 * time steps. */
179 for (size_t i = 0; i < size; i++) {
180 const float3 scale = make_float3(decomp[i].y.w, decomp[i].z.w, decomp[i].w.w);
181 if (!is_zero(scale)) {
182 continue;
183 }
184
185 if (i > 0) {
186 decomp[i].x = decomp[i - 1].x;
187 }
188 else if (i < size - 1) {
189 decomp[i].x = decomp[i + 1].x;
190 }
191 }
192}
193
195{
196 return transform_scale(1.0f / (viewplane.right - viewplane.left),
197 1.0f / (viewplane.top - viewplane.bottom),
198 1.0f) *
199 transform_translate(-viewplane.left, -viewplane.bottom, 0.0f);
200}
201
MINLINE float safe_divide(float a, float b)
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:200
float top
Definition boundbox.h:201
float right
Definition boundbox.h:199
float left
Definition boundbox.h:198
dot(value.rgb, luminance_coefficients)") DEFINE_VALUE("REDUCE(lhs
ccl_device_inline Transform projection_to_transform(const ProjectionTransform &a)
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)
VecBase< float, 4 > float4
#define sqrt
ccl_device_inline bool is_zero(const float2 a)
#define M
#define R
float4 y
Definition transform.h:23
float4 x
Definition transform.h:23
float4 z
Definition transform.h:23
float z
Definition sky_float3.h:27
float y
Definition sky_float3.h:27
float x
Definition sky_float3.h:27
i
Definition text_draw.cc:230
max
Definition text_draw.cc:251
static void transform_decompose(DecomposedTransform *decomp, const Transform *tfm)
Definition transform.cpp:72
float4 transform_to_quat(const Transform &tfm)
Definition transform.cpp:23
void transform_motion_decompose(DecomposedTransform *decomp, const Transform *motion, const size_t size)
CCL_NAMESPACE_BEGIN Transform transform_transposed_inverse(const Transform &tfm)
Definition transform.cpp:15
Transform transform_from_viewplane(BoundBox2D &viewplane)
ccl_device_inline float3 transform_get_column(const Transform *t, const int column)
Definition transform.h:321
ccl_device_inline bool transform_negative_scale(const Transform &tfm)
Definition transform.h:358
ccl_device_inline Transform transform_scale(const float3 s)
Definition transform.h:247
ccl_device_inline Transform transform_inverse(const Transform tfm)
Definition transform.h:492
ccl_device_inline Transform transform_translate(const float3 t)
Definition transform.h:237
ccl_device_inline void transform_set_column(Transform *t, const int column, const float3 value)
Definition transform.h:326
uint len