Blender V5.0
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 }
97
98 norm = 0.0f;
99 for (int i = 0; i < 3; i++) {
100 norm = max(norm,
101 fabsf(R[i][0] - Rnext[i][0]) + fabsf(R[i][1] - Rnext[i][1]) +
102 fabsf(R[i][2] - Rnext[i][2]));
103 }
104
105 R = Rnext;
106 iteration++;
107 } while (iteration < 100 && norm > 1e-4f);
108
110 R = R * transform_scale(-1.0f, -1.0f, -1.0f);
111 }
112
113 decomp->x = transform_to_quat(R);
114
115 /* extract scale and pack it */
116 Transform scale = transform_inverse(R) * M;
117 decomp->y.w = scale.x.x;
118 decomp->z = make_float4(scale.x.y, scale.x.z, scale.y.x, scale.y.y);
119 decomp->w = make_float4(scale.y.z, scale.z.x, scale.z.y, scale.z.z);
120#else
121 float3 colx = transform_get_column(&M, 0);
122 float3 coly = transform_get_column(&M, 1);
123 float3 colz = transform_get_column(&M, 2);
124
125 /* extract scale and shear first */
126 float3 scale;
127 float3 shear;
128 scale.x = len(colx);
129 colx = safe_divide(colx, scale.x);
130 shear.z = dot(colx, coly);
131 coly -= shear.z * colx;
132 scale.y = len(coly);
133 coly = safe_divide(coly, scale.y);
134 shear.y = dot(colx, colz);
135 colz -= shear.y * colx;
136 shear.x = dot(coly, colz);
137 colz -= shear.x * coly;
138 scale.z = len(colz);
139 colz = safe_divide(colz, scale.z);
140
141 transform_set_column(&M, 0, colx);
142 transform_set_column(&M, 1, coly);
143 transform_set_column(&M, 2, colz);
144
146 scale *= -1.0f;
147 M = M * transform_scale(-1.0f, -1.0f, -1.0f);
148 }
149
150 decomp->x = transform_to_quat(M);
151
152 decomp->y.w = scale.x;
153 decomp->z = make_float4(shear.z, shear.y, 0.0f, scale.y);
154 decomp->w = make_float4(shear.x, 0.0f, 0.0f, scale.z);
155#endif
156}
157
159 const Transform *motion,
160 const size_t size)
161{
162 /* Decompose and correct rotation. */
163 for (size_t i = 0; i < size; i++) {
164 transform_decompose(decomp + i, motion + i);
165
166 if (i > 0) {
167 /* Ensure rotation around shortest angle, negated quaternions are the same
168 * but this means we don't have to do the check in quat_interpolate */
169 if (dot(decomp[i - 1].x, decomp[i].x) < 0.0f) {
170 decomp[i].x = -decomp[i].x;
171 }
172 }
173 }
174
175 /* Copy rotation to decomposed transform where scale is degenerate. This avoids weird object
176 * rotation interpolation when the scale goes to 0 for a time step.
177 *
178 * Note that this is very simple and naive implementation, which only deals with degenerated
179 * scale happening only on one frame. It is possible to improve it further by interpolating
180 * rotation into s degenerated range using rotation from time-steps from adjacent non-degenerated
181 * time steps. */
182 for (size_t i = 0; i < size; i++) {
183 const float3 scale = make_float3(decomp[i].y.w, decomp[i].z.w, decomp[i].w.w);
184 if (!is_zero(scale)) {
185 continue;
186 }
187
188 if (i > 0) {
189 decomp[i].x = decomp[i - 1].x;
190 }
191 else if (i < size - 1) {
192 decomp[i].x = decomp[i + 1].x;
193 }
194 }
195}
196
198{
199 return transform_scale(1.0f / (viewplane.right - viewplane.left),
200 1.0f / (viewplane.top - viewplane.bottom),
201 1.0f) *
202 transform_translate(-viewplane.left, -viewplane.bottom, 0.0f);
203}
204
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
nullptr float
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 float3 make_float3(const float x, const float y, const float z)
#define sqrt
ccl_device_inline bool is_zero(const float2 a)
#define M
#define R
#define fabsf
#define make_float4
float4 y
Definition transform.h:23
float4 x
Definition transform.h:23
float4 z
Definition transform.h:23
float z
Definition sky_math.h:136
float y
Definition sky_math.h:136
float x
Definition sky_math.h:136
float y
Definition sky_math.h:225
float z
Definition sky_math.h:225
float x
Definition sky_math.h:225
float w
Definition sky_math.h:225
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:354
ccl_device_inline bool transform_negative_scale(const Transform &tfm)
Definition transform.h:391
ccl_device_inline Transform transform_scale(const float3 s)
Definition transform.h:280
ccl_device_inline Transform transform_inverse(const Transform tfm)
Definition transform.h:525
ccl_device_inline Transform transform_translate(const float3 t)
Definition transform.h:270
ccl_device_inline void transform_set_column(Transform *t, const int column, const float3 value)
Definition transform.h:359
uint len