Vuo 2.4.4
Loading...
Searching...
No Matches
VuoTransform.h
Go to the documentation of this file.
1
10#ifndef VuoTransform_h
11#define VuoTransform_h
12
13#ifdef __cplusplus
14extern "C" {
15#endif
16
17#include "VuoInteger.h"
18#include <math.h>
19#include <float.h>
20#include "VuoPoint3d.h"
21#include "VuoPoint4d.h"
22#include "VuoRectangle.h"
23#include "VuoTransform2d.h"
24#include <stdio.h>
25
38{
39 VuoTransformTypeEuler,
40 VuoTransformTypeQuaternion,
41 VuoTransformTypeTargeted
42};
43
50typedef struct
51{
52 VuoPoint3d translation;
53 float rotation[9];
54 VuoPoint3d scale;
55
56 // The following values are stored so we can display a meaningful summary.
57 enum VuoTransformType type;
58 struct
59 {
60 VuoPoint3d euler;
61 VuoPoint4d quaternion;
62 struct
63 {
64 VuoPoint3d target;
65 VuoPoint3d upDirection;
66 };
67 } rotationSource;
69
70void VuoTransform_getMatrix(const VuoTransform value, float *matrix) __attribute__((nonnull));
71void VuoTransform_getBillboardMatrix(VuoInteger imageWidth, VuoInteger imageHeight, VuoReal imageScaleFactor, VuoBoolean preservePhysicalSize, VuoReal translationX, VuoReal translationY, VuoInteger viewportWidth, VuoInteger viewportHeight, VuoReal backingScaleFactor, VuoPoint2d mesh0, float *billboardMatrix) __attribute__((nonnull));
72VuoPoint3d VuoTransform_getEuler(const VuoTransform transform);
73VuoPoint4d VuoTransform_getQuaternion(const VuoTransform transform);
74VuoPoint3d VuoTransform_getDirection(const VuoTransform transform);
76VuoTransform VuoTransform_makeEuler(VuoPoint3d translation, VuoPoint3d rotation, VuoPoint3d scale);
77VuoTransform VuoTransform_makeQuaternion(VuoPoint3d translation, VuoPoint4d rotation, VuoPoint3d scale);
78void VuoTransform_rotationMatrixFromQuaternion(const VuoPoint4d quaternion, float *matrix) __attribute__((nonnull));
79void VuoTransform_rotationMatrixFromEuler(const VuoPoint3d euler, float *matrix) __attribute__((nonnull));
80
83
84VuoTransform VuoTransform_makeFromTarget(VuoPoint3d position, VuoPoint3d target, VuoPoint3d upDirection);
85VuoTransform VuoTransform_makeFromMatrix4x4(const float *matrix) __attribute__((nonnull));
87
91static inline VuoPoint4d VuoTransform_quaternionComposite(VuoPoint4d a, VuoPoint4d b) __attribute__((const));
92static inline VuoPoint4d VuoTransform_quaternionComposite(VuoPoint4d a, VuoPoint4d b)
93{
94 VuoPoint4d q;
95 // Hamilton product (a.w, a.x, a.y, a.z) * (b.w, b.x, b.y, b.z)
96 q.x = a.w*b.x + a.x*b.w + a.y*b.z - a.z*b.y;
97 q.y = a.w*b.y + a.y*b.w + a.z*b.x - a.x*b.z;
98 q.z = a.w*b.z + a.z*b.w + a.x*b.y - a.y*b.x;
99 q.w = a.w*b.w - a.x*b.x - a.y*b.y - a.z*b.z;
100 return VuoPoint4d_normalize(q);
101}
102
106static inline VuoPoint4d VuoTransform_quaternionFromAxisAngle(VuoPoint3d axis, float angle) __attribute__((const));
107static inline VuoPoint4d VuoTransform_quaternionFromAxisAngle(VuoPoint3d axis, float angle)
108{
109 VuoPoint4d q;
110 VuoPoint3d axisNormalized = VuoPoint3d_normalize(axis);
111 q.x = axisNormalized.x * sinf(angle/2.f);
112 q.y = axisNormalized.y * sinf(angle/2.f);
113 q.z = axisNormalized.z * sinf(angle/2.f);
114 q.w = cosf(angle/2.f);
115 return VuoPoint4d_normalize(q);
116}
117
118VuoPoint4d VuoTransform_quaternionFromBasis(VuoPoint3d basis[3]);
119
125static inline VuoPoint4d VuoTransform_quaternionFromVectors(VuoPoint3d from, VuoPoint3d to) __attribute__((const));
126static inline VuoPoint4d VuoTransform_quaternionFromVectors(VuoPoint3d from, VuoPoint3d to)
127{
128 // http://books.google.com/books?id=hiBFUv_FT0wC&pg=PA214&lpg=PA214&dq=Stan+Melax's+article+in+Game+Programming+Gems&source=bl&ots=OCjDPwza1h&sig=6_bDSzTrnI3qCEG9vtVV_mDBgg8&hl=en&sa=X&ei=ffReUsSaBIrMqAGg6YD4Aw&ved=0CCsQ6AEwAA#v=onepage&q=Stan%20Melax's%20article%20in%20Game%20Programming%20Gems&f=false
129 VuoPoint4d q = { 0, 0, 0, 1 };
130
131 if (VuoPoint3d_magnitude(from) == 0 || VuoPoint3d_magnitude(to) == 0)
132 return q;
133
134 VuoPoint3d fromNormalized = VuoPoint3d_normalize(from);
135 VuoPoint3d toNormalized = VuoPoint3d_normalize(to);
136
137 VuoPoint3d c = VuoPoint3d_crossProduct(fromNormalized, toNormalized);
138 float d = VuoPoint3d_dotProduct(fromNormalized, toNormalized);
139 float s = sqrtf( (1+d)*2 );
140
141 q.x = c.x / s;
142 q.y = c.y / s;
143 q.z = c.z / s;
144 q.w = s / 2.f;
145
146 return q;
147}
148
153static inline VuoPoint4d VuoTransform_quaternionFromMatrix(const float *rotation) __attribute__((nonnull));
154static inline VuoPoint4d VuoTransform_quaternionFromMatrix(const float *rotation)
155{
156 float t;
157 VuoPoint4d q;
158
159 float m00 = rotation[0],
160 m01 = rotation[1],
161 m02 = rotation[2],
162 m10 = rotation[3],
163 m11 = rotation[4],
164 m12 = rotation[5],
165 m20 = rotation[6],
166 m21 = rotation[7],
167 m22 = rotation[8];
168
169 if (m22 < 0)
170 {
171 if (m00 > m11)
172 {
173 t = 1 + m00 - m11 - m22;
174 q = VuoPoint4d_make( t, m01+m10, m20+m02, m12-m21 );
175 }
176 else
177 {
178 t = 1 - m00 + m11 - m22;
179 q = VuoPoint4d_make( m01+m10, t, m12+m21, m20-m02 );
180 }
181 }
182 else
183 {
184 if (m00 < -m11)
185 {
186 t = 1 - m00 - m11 + m22;
187 q = VuoPoint4d_make( m20+m02, m12+m21, t, m01-m10 );
188 }
189 else
190 {
191 t = 1 + m00 + m11 + m22;
192 q = VuoPoint4d_make( m12-m21, m20-m02, m01-m10, t );
193 }
194 }
195
196 return VuoPoint4d_multiply(q, 0.5f / sqrt(t));
197}
198
203static inline VuoPoint4d VuoTransform_quaternionFromEuler(const VuoPoint3d euler) __attribute__((const));
204static inline VuoPoint4d VuoTransform_quaternionFromEuler(const VuoPoint3d euler)
205{
206 VuoPoint4d q;
207
208 double t0 = cos(euler.z * 0.5);
209 double t1 = sin(euler.z * 0.5);
210 double t2 = cos(euler.x * 0.5);
211 double t3 = sin(euler.x * 0.5);
212 double t4 = cos(euler.y * 0.5);
213 double t5 = sin(euler.y * 0.5);
214
215 q.w = t0 * t2 * t4 + t1 * t3 * t5;
216 q.x = t0 * t3 * t4 - t1 * t2 * t5;
217 q.y = t0 * t2 * t5 + t1 * t3 * t4;
218 q.z = t1 * t2 * t4 - t0 * t3 * t5;
219
220 return VuoPoint4d_normalize(q);
221}
222
227static inline VuoPoint3d VuoTransform_eulerFromQuaternion(const VuoPoint4d quaternion) __attribute__((const));
228static inline VuoPoint3d VuoTransform_eulerFromQuaternion(const VuoPoint4d quaternion)
229{
230 VuoPoint3d ea;
231
232 double ysqr = quaternion.y * quaternion.y;
233
234 // roll (x-axis rotation)
235 double t0 = + 2.0 * (quaternion.w * quaternion.x + quaternion.y * quaternion.z);
236 double t1 = + 1.0 - 2.0 * (quaternion.x * quaternion.x + ysqr);
237 ea.x = atan2(t0, t1);
238
239 // pitch (y-axis rotation)
240 double t2 = +2.0 * (quaternion.w * quaternion.y - quaternion.z * quaternion.x);
241 t2 = t2 > 1.0 ? 1.0 : t2;
242 t2 = t2 < -1.0 ? -1.0 : t2;
243 ea.y = asin(t2);
244
245 // yaw (z-axis rotation)
246 double t3 = +2.0 * (quaternion.w * quaternion.z + quaternion.x * quaternion.y);
247 double t4 = +1.0 - 2.0 * (ysqr + quaternion.z * quaternion.z);
248 ea.z = atan2(t3, t4);
249
250 return ea;
251}
252
256static inline VuoPoint3d VuoTransform_eulerFromMatrix(const float *matrix) __attribute__((nonnull));
257static inline VuoPoint3d VuoTransform_eulerFromMatrix(const float *matrix)
258{
259 // "Euler Angle Conversion" by Ken Shoemake. Graphics Gems IV, pp. 222–229.
260 VuoPoint3d ea;
261
262 double cy = sqrt(matrix[0] * matrix[0] + matrix[1] * matrix[1]);
263
264 if (cy > 16 * FLT_EPSILON)
265 {
266 ea.x = atan2f( matrix[5], matrix[8]);
267 ea.y = atan2f(-matrix[2], cy);
268 ea.z = atan2f( matrix[1], matrix[0]);
269 }
270 else
271 {
272 ea.x = atan2f(-matrix[7], matrix[4]);
273 ea.y = atan2f(-matrix[2], cy);
274 ea.z = 0;
275 }
276
277 return ea;
278}
279
283static inline VuoPoint3d VuoTransform_rotateVectorWithQuaternion(const VuoPoint3d v, const VuoPoint4d q) __attribute__((const));
284static inline VuoPoint3d VuoTransform_rotateVectorWithQuaternion(const VuoPoint3d v, const VuoPoint4d q)
285{
286 // https://math.stackexchange.com/questions/40164/how-do-you-rotate-a-vector-by-a-unit-quaternion/535223
287 VuoPoint4d vQuaternion = (VuoPoint4d){v.x, v.y, v.z, 0};
288 VuoPoint4d qConjugate = (VuoPoint4d){-q.x, -q.y, -q.z, q.w};
289 VuoPoint4d result = VuoTransform_quaternionComposite(VuoTransform_quaternionComposite(q, vQuaternion), qConjugate);
290 return (VuoPoint3d){result.x, result.y, result.z};
291}
292
296static inline bool VuoTransform_isIdentity(const VuoTransform transform)
297{
298 const float tolerance = 0.00001f;
299 return fabs(transform.translation.x) < tolerance
300 && fabs(transform.translation.y) < tolerance
301 && fabs(transform.translation.z) < tolerance
302 && fabs(transform.scale.x - 1.) < tolerance
303 && fabs(transform.scale.y - 1.) < tolerance
304 && fabs(transform.scale.z - 1.) < tolerance
305 && (
306 (transform.type == VuoTransformTypeEuler
307 && fabs(transform.rotationSource.euler.x) < tolerance
308 && fabs(transform.rotationSource.euler.y) < tolerance
309 && fabs(transform.rotationSource.euler.z) < tolerance
310 )
311 ||
312 (transform.type == VuoTransformTypeQuaternion
313 && fabs(transform.rotationSource.quaternion.x) < tolerance
314 && fabs(transform.rotationSource.quaternion.y) < tolerance
315 && fabs(transform.rotationSource.quaternion.z) < tolerance
316 && (fabs(transform.rotationSource.quaternion.w - 1.) < tolerance || fabs(transform.rotationSource.quaternion.w + 1.) < tolerance)
317 )
318 ||
319 (transform.type == VuoTransformTypeTargeted
320 && fabs(transform.rotationSource.target.x - 1.) < tolerance
321 && fabs(transform.rotationSource.target.y) < tolerance
322 && fabs(transform.rotationSource.target.z) < tolerance
323 )
324 );
325}
326
330static inline void VuoTransform_multiplyMatrices4x4(const float *a, const float *b, float *outputMatrix) __attribute__((nonnull));
331static inline void VuoTransform_multiplyMatrices4x4(const float *a, const float *b, float *outputMatrix)
332{
333 outputMatrix[0*4+0] = a[0*4+0] * b[0*4+0] + a[0*4+1] * b[1*4+0] + a[0*4+2] * b[2*4+0] + a[0*4+3] * b[3*4+0];
334 outputMatrix[0*4+1] = a[0*4+0] * b[0*4+1] + a[0*4+1] * b[1*4+1] + a[0*4+2] * b[2*4+1] + a[0*4+3] * b[3*4+1];
335 outputMatrix[0*4+2] = a[0*4+0] * b[0*4+2] + a[0*4+1] * b[1*4+2] + a[0*4+2] * b[2*4+2] + a[0*4+3] * b[3*4+2];
336 outputMatrix[0*4+3] = a[0*4+0] * b[0*4+3] + a[0*4+1] * b[1*4+3] + a[0*4+2] * b[2*4+3] + a[0*4+3] * b[3*4+3];
337 outputMatrix[1*4+0] = a[1*4+0] * b[0*4+0] + a[1*4+1] * b[1*4+0] + a[1*4+2] * b[2*4+0] + a[1*4+3] * b[3*4+0];
338 outputMatrix[1*4+1] = a[1*4+0] * b[0*4+1] + a[1*4+1] * b[1*4+1] + a[1*4+2] * b[2*4+1] + a[1*4+3] * b[3*4+1];
339 outputMatrix[1*4+2] = a[1*4+0] * b[0*4+2] + a[1*4+1] * b[1*4+2] + a[1*4+2] * b[2*4+2] + a[1*4+3] * b[3*4+2];
340 outputMatrix[1*4+3] = a[1*4+0] * b[0*4+3] + a[1*4+1] * b[1*4+3] + a[1*4+2] * b[2*4+3] + a[1*4+3] * b[3*4+3];
341 outputMatrix[2*4+0] = a[2*4+0] * b[0*4+0] + a[2*4+1] * b[1*4+0] + a[2*4+2] * b[2*4+0] + a[2*4+3] * b[3*4+0];
342 outputMatrix[2*4+1] = a[2*4+0] * b[0*4+1] + a[2*4+1] * b[1*4+1] + a[2*4+2] * b[2*4+1] + a[2*4+3] * b[3*4+1];
343 outputMatrix[2*4+2] = a[2*4+0] * b[0*4+2] + a[2*4+1] * b[1*4+2] + a[2*4+2] * b[2*4+2] + a[2*4+3] * b[3*4+2];
344 outputMatrix[2*4+3] = a[2*4+0] * b[0*4+3] + a[2*4+1] * b[1*4+3] + a[2*4+2] * b[2*4+3] + a[2*4+3] * b[3*4+3];
345 outputMatrix[3*4+0] = a[3*4+0] * b[0*4+0] + a[3*4+1] * b[1*4+0] + a[3*4+2] * b[2*4+0] + a[3*4+3] * b[3*4+0];
346 outputMatrix[3*4+1] = a[3*4+0] * b[0*4+1] + a[3*4+1] * b[1*4+1] + a[3*4+2] * b[2*4+1] + a[3*4+3] * b[3*4+1];
347 outputMatrix[3*4+2] = a[3*4+0] * b[0*4+2] + a[3*4+1] * b[1*4+2] + a[3*4+2] * b[2*4+2] + a[3*4+3] * b[3*4+2];
348 outputMatrix[3*4+3] = a[3*4+0] * b[0*4+3] + a[3*4+1] * b[1*4+3] + a[3*4+2] * b[2*4+3] + a[3*4+3] * b[3*4+3];
349}
350
354static inline void VuoTransform_copyMatrix4x4(const float *sourceMatrix, float *destMatrix) __attribute__((nonnull));
355static inline void VuoTransform_copyMatrix4x4(const float *sourceMatrix, float *destMatrix)
356{
357 for (int i=0; i<16; ++i)
358 destMatrix[i] = sourceMatrix[i];
359}
360
365static inline VuoPoint3d VuoTransform_getMatrix4x4Translation(const float *matrix) __attribute__((nonnull));
366static inline VuoPoint3d VuoTransform_getMatrix4x4Translation(const float *matrix)
367{
368 return (VuoPoint3d){matrix[12], matrix[13], matrix[14]};
369}
370
375static inline VuoPoint3d VuoTransform_getMatrix4x4Scale(const float *matrix) __attribute__((nonnull));
376static inline VuoPoint3d VuoTransform_getMatrix4x4Scale(const float *matrix)
377{
378 return (VuoPoint3d){
379 VuoPoint3d_magnitude((VuoPoint3d){matrix[0], matrix[1], matrix[ 2]}),
380 VuoPoint3d_magnitude((VuoPoint3d){matrix[4], matrix[5], matrix[ 6]}),
381 VuoPoint3d_magnitude((VuoPoint3d){matrix[8], matrix[9], matrix[10]})
382 };
383}
384
388static inline void VuoTransform_printMatrix4x4(const float *matrix) __attribute__((nonnull));
389static inline void VuoTransform_printMatrix4x4(const float *matrix)
390{
391 for (int i=0; i<4; ++i)
392 fprintf(stderr, "[ %11.6f %11.6f %11.6f %11.6f ]\n",matrix[i+0*4],matrix[i+1*4],matrix[i+2*4],matrix[i+3*4]);
393}
394
395void VuoTransform_invertMatrix4x4(const float *matrix, float *outputInvertedMatrix) __attribute__((nonnull));
396
403static inline VuoPoint3d VuoTransform_transformPoint(const float *matrix, VuoPoint3d point) __attribute__((nonnull));
404static inline VuoPoint3d VuoTransform_transformPoint(const float *matrix, VuoPoint3d point)
405{
406 return (VuoPoint3d){
407 point.x * matrix[0] + point.y * matrix[4] + point.z * matrix[ 8] + matrix[12],
408 point.x * matrix[1] + point.y * matrix[5] + point.z * matrix[ 9] + matrix[13],
409 point.x * matrix[2] + point.y * matrix[6] + point.z * matrix[10] + matrix[14]
410 };
411}
412
413VuoPoint2d VuoTransform_transform_VuoPoint2d(VuoTransform transform, VuoPoint2d point);
414VuoPoint3d VuoTransform_transform_VuoPoint3d(VuoTransform transform, VuoPoint3d point);
415
424static inline VuoPoint3d VuoTransform_transformVector(const float *matrix, VuoPoint3d point) __attribute__((nonnull));
425static inline VuoPoint3d VuoTransform_transformVector(const float *matrix, VuoPoint3d point)
426{
427 return (VuoPoint3d){
428 point.x * matrix[0] + point.y * matrix[4] + point.z * matrix[ 8],
429 point.x * matrix[1] + point.y * matrix[5] + point.z * matrix[ 9],
430 point.x * matrix[2] + point.y * matrix[6] + point.z * matrix[10]
431 };
432}
433
434
435VuoRectangle VuoTransform_transformRectangle(const float *matrix, VuoRectangle rectangle) __attribute__((nonnull));
436
437VuoTransform VuoTransform_makeFromJson(struct json_object *js);
438struct json_object * VuoTransform_getJson(const VuoTransform value);
439char * VuoTransform_getSummary(const VuoTransform value);
440
442
449
454#ifdef __cplusplus
455}
456#endif
457
458#endif