Aeon Engine c550894
AeonGames Open Source Game Engine
Loading...
Searching...
No Matches
3DMath.h
Go to the documentation of this file.
1/*
2Copyright (C) 2009-2019,2025,2026 Rodrigo Jose Hernandez Cordoba
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16#ifndef AEONGAMES_MATH_H
17#define AEONGAMES_MATH_H
41#include <cmath>
42#include <cassert>
43#include <cstring>
44#include <climits>
45#include <cfloat>
46#include <cstdio>
47
48#if 0
50// @{
52constexpr float PI = M_PI;
54constexpr float TWOPI = M_PI * 2;
56constexpr float PIOVER180 = M_PI / 180.0f;
58constexpr float ONE80OVERPI = 180 / M_PI;
60const float FLT_TOLERANCE = std::sqrt ( FLT_EPSILON );
61// @}
62#endif
63
64inline void RotateVectorByQuat ( const float* q, const float* v, float* out );
65
66#if 0
68// @{
73inline float DEG2RAD ( float deg )
74{
75 return PIOVER180 * deg;
76}
81inline float RAD2DEG ( float rad )
82{
83 return ONE80OVERPI * rad;
84}
85#endif
92inline float sabs ( float x )
93{
94 return x < 0 ? -x : x;
95}
96// @}
98// @{
99//-----------VECTORS-------------
106inline float* Cross3 ( float* v1, float* v2, float* dst )
107{
108 float r[3];
109 r[0] = ( ( v1[1] * v2[2] ) - ( v1[2] * v2[1] ) );
110 r[1] = ( ( v1[2] * v2[0] ) - ( v1[0] * v2[2] ) );
111 r[2] = ( ( v1[0] * v2[1] ) - ( v1[1] * v2[0] ) );
112 memcpy ( dst, r, sizeof ( float ) * 3 );
113 return dst;
114}
115
120inline float Length ( float const * const v )
121{
122 return ( float ) sqrtf ( ( v[0] * v[0] ) + ( v[1] * v[1] ) + ( v[2] * v[2] ) );
123}
124
129inline float Length4 ( float* v )
130{
131 return ( float ) sqrtf ( ( v[0] * v[0] ) + ( v[1] * v[1] ) + ( v[2] * v[2] ) + ( v[3] * v[3] ) );
132}
133
139inline float Dot ( const float v1[], const float v2[] )
140{
141 return ( float ) ( v1[0] * v2[0] ) + ( v1[1] * v2[1] ) + ( v1[2] * v2[2] );
142}
143
149inline float Dot4 ( const float v1[], const float v2[] )
150{
151 return ( float ) ( v1[0] * v2[0] ) + ( v1[1] * v2[1] ) + ( v1[2] * v2[2] ) + ( v1[3] * v2[3] );
152}
153
158inline float* Normalize ( float* v )
159{
160 float length = Length ( v );
161 // do nothing if length = 0
162 if ( length )
163 {
164 v[0] /= length;
165 v[1] /= length;
166 v[2] /= length;
167 }
168 return v;
169}
170
175inline float* Normalize4 ( float* v )
176{
177 float length = Length4 ( v );
178 // do nothing if length = 0
179 if ( length )
180 {
181 float oneoverlength = 1.0f / length;
182 v[0] *= oneoverlength;
183 v[1] *= oneoverlength;
184 v[2] *= oneoverlength;
185 v[3] *= oneoverlength;
186 }
187 return v;
188}
189
195inline float* NormalizePlane ( float const * const aPlane, float* aOut )
196{
197 float length = Length ( aPlane );
198 // do nothing if length = 0
199 if ( length )
200 {
201 aOut[0] = aPlane[0] / length;
202 aOut[1] = aPlane[1] / length;
203 aOut[2] = aPlane[2] / length;
204 aOut[3] = aPlane[3] / length;
205 }
206 return aOut;
207}
208
209
212inline float* Add4 ( float* v1, float* v2, float* out )
213{
214 out[0] = v1[0] + v2[0];
215 out[1] = v1[1] + v2[1];
216 out[2] = v1[2] + v2[2];
217 out[3] = v1[3] + v2[3];
218 return out;
219}
220
223inline float* Subtract4 ( float* v1, float* v2, float* out )
224{
225 out[0] = v1[0] - v2[0];
226 out[1] = v1[1] - v2[1];
227 out[2] = v1[2] - v2[2];
228 out[3] = v1[3] - v2[3];
229 return out;
230}
231
233inline float* ScalarMultiply4 ( float* v, float s, float* out )
234{
235 out[0] = v[0] * s;
236 out[1] = v[1] * s;
237 out[2] = v[2] * s;
238 out[3] = v[3] * s;
239 return out;
240}
241
249inline void ClipVelocity ( float* v, float* normal, float overbounce )
250{
251 float backoff;
252 float change;
253 int i;
254 backoff =
255 v[0] * normal[0] +
256 v[1] * normal[1] +
257 v[2] * normal[2];
258 if ( backoff < 0 )
259 {
260 backoff *= overbounce;
261 }
262 else
263 {
264 backoff /= overbounce;
265 }
266 for ( i = 0 ; i < 3 ; i++ )
267 {
268 change = normal[i] * backoff;
269 v[i] = v[i] - change;
270 }
271}
272
281inline int ClosestAxis ( float* v )
282{
283 float a[2];
284 int axis = ( a[0] = sabs ( v[0] ) ) < ( a[1] = sabs ( v[1] ) ) ? 1 : 0;
285 return a[axis] < sabs ( v[2] ) ? 2 : axis;
286}
287
298inline void InterpolateVectors ( float* v1, float* v2, float interpolation, float* out )
299{
300 float localout[3];
301 localout[0] = v1[0] + ( ( v2[0] - v1[0] ) * interpolation );
302 localout[1] = v1[1] + ( ( v2[1] - v1[1] ) * interpolation );
303 localout[2] = v1[2] + ( ( v2[2] - v1[2] ) * interpolation );
304 out[0] = localout[0];
305 out[1] = localout[1];
306 out[2] = localout[2];
307}
308
316inline float DistanceSquared ( const float a[], const float b[] )
317{
318 float v[3] = {b[0] - a[0], b[1] - a[1], b[2] - a[2]};
319 return ( v[0] * v[0] ) + ( v[1] * v[1] ) + ( v[2] * v[2] );
320}
321
329inline float Distance ( const float a[], const float b[] )
330{
331 return sqrtf ( DistanceSquared ( a, b ) );
332}
333
341inline float* MultVector4x4Matrix ( const float* v, const float* m, float* out )
342{
343 float vc[3] = {v[0], v[1], v[2]};
344 out[0] = vc[0] * m[0] + vc[1] * m[4] + vc[2] * m[ 8] + m[12];
345 out[1] = vc[0] * m[1] + vc[1] * m[5] + vc[2] * m[ 9] + m[13];
346 out[2] = vc[0] * m[2] + vc[1] * m[6] + vc[2] * m[10] + m[14];
347 return out;
348}
349
356inline float* MultVectorScalar ( float* v, float s, float* out )
357{
358 out[0] = v[0] * s;
359 out[1] = v[1] * s;
360 out[2] = v[2] * s;
361 return out;
362}
363
371inline void MultVector3x3Matrix ( float* v, float* m, float* out )
372{
373 float vc[3] = {v[0], v[1], v[2]};
374 out[0] = vc[0] * m[0] + vc[1] * m[4] + vc[2] * m[ 8];
375 out[1] = vc[0] * m[1] + vc[1] * m[5] + vc[2] * m[ 9];
376 out[2] = vc[0] * m[2] + vc[1] * m[6] + vc[2] * m[10];
377}
378
380inline float* GetScaleVectorInverse ( const float* v, float *out )
381{
382 out[0] = 1.0f / v[0];
383 out[1] = 1.0f / v[1];
384 out[2] = 1.0f / v[2];
385 return out;
386}
387
388inline float* GetPositionVectorInverse ( const float* v, float *out )
389{
390 out[0] = -v[0];
391 out[1] = -v[1];
392 out[2] = -v[2];
393 return out;
394}
395
396// @}
397
399// Forward declarations for functions defined in the Quaternion Functions group.
400inline void QuatTo3x3Matrix ( const float* q, float* m );
401inline float* GetQuaternionInverse ( const float* q, float* out );
403
405// @{
410inline float* SetIdentityMatrix4x4 ( float* M )
411{
412 M[0] = M[5] = M[10] = M[15] = 1.0f;
413 M[1] = M[2] = M[3] = M[4] = M[6] = M[7] = M[8] = M[9] = M[11] = M[12] = M[13] = M[14] = 0.0f;
414 return M;
415}
416
421inline float* Extract3x3Matrix ( const float* m, float* out )
422{
423 out[0] = m[0];
424 out[1] = m[1];
425 out[2] = m[2];
426 out[3] = m[4];
427 out[4] = m[5];
428 out[5] = m[6];
429 out[6] = m[8];
430 out[7] = m[9];
431 out[8] = m[10];
432 return out;
433}
434
439inline float* Extract3x3Into4x4 ( const float* m, float* out )
440{
441 out[0] = m[0];
442 out[1] = m[1];
443 out[2] = m[2];
444 out[3] = 0;
445 out[4] = m[4];
446 out[5] = m[5];
447 out[6] = m[6];
448 out[7] = 0;
449 out[8] = m[8];
450 out[9] = m[9];
451 out[10] = m[10];
452 out[11] = 0;
453 out[12] = 0;
454 out[13] = 0;
455 out[14] = 0;
456 out[15] = 1;
457 return out;
458}
459
464inline float* Convert3x3To4x3 ( const float* m, float* out )
465{
466 /* Setting the values backward allow
467 for the input matrix to be output matrix
468 (in place conversion)*/
469 out[11] = 0;
470 out[10] = m[8];
471 out[9] = m[7];
472 out[8] = m[6];
473 out[7] = 0;
474 out[6] = m[5];
475 out[5] = m[4];
476 out[4] = m[3];
477 out[3] = 0;
478 out[2] = m[2];
479 out[1] = m[1];
480 out[0] = m[0];
481 return out;
482}
483
488inline float* Convert3x3To4x4 ( const float* m, float* out )
489{
490 out[15] = 1;
491 out[14] = 0;
492 out[13] = 0;
493 out[12] = 0;
494 return Convert3x3To4x3 ( m, out );
495}
496
501inline float* Transpose3x3Matrix ( const float *src, float *dst )
502{
503 float tmp[9];
504 for ( int i = 0; i < 3; i++ )
505 {
506 tmp[i] = src[i * 3];
507 tmp[i + 3] = src[i * 3 + 1];
508 tmp[i + 6] = src[i * 3 + 2];
509 }
510 memcpy ( dst, tmp, sizeof ( float ) * 9 );
511 return dst;
512}
513
514
518inline float DeterminantMatrix3 ( const float *src )
519{
520 float A = src[4] * src[8] - src[5] * src[7];
521 float B = - ( src[3] * src[8] - src[5] * src[6] );
522 float C = ( src[3] * src[7] - src[4] * src[6] );
523 return src[0] * A + src[1] * B + src[2] * C;
524}
525
530inline float* Invert3x3Matrix ( const float *src, float *dst )
531{
532 float A = src[4] * src[8] - src[5] * src[7];
533 float B = - ( src[3] * src[8] - src[5] * src[6] );
534 float C = ( src[3] * src[7] - src[4] * src[6] );
535 float determinant = src[0] * A + src[1] * B + src[2] * C;
536 if ( determinant != 0.0f )
537 {
538 float D = - ( src[1] * src[8] - src[2] * src[7] );
539 float E = src[0] * src[8] - src[2] * src[6];
540 float F = - ( src[0] * src[7] - src[1] * src[6] );
541 float G = src[1] * src[5] - src[2] * src[4];
542 float H = - ( src[0] * src[5] - src[2] * src[3] );
543 float I = src[0] * src[4] - src[1] * src[3];
544 dst[0] = A / determinant;
545 dst[3] = B / determinant;
546 dst[6] = C / determinant;
547 dst[1] = D / determinant;
548 dst[4] = E / determinant;
549 dst[7] = F / determinant;
550 dst[2] = G / determinant;
551 dst[5] = H / determinant;
552 dst[8] = I / determinant;
553 }
554 return dst;
555}
556
557
591inline float* InvertOrthogonalMatrix ( float *src, float *dst )
592{
593 /*
594 From:
595
596 [ X.x Y.x Z.x P.x ]
597 [ X.y Y.y Z.y P.y ]
598 [ X.z Y.z Z.z P.z ]
599 [ 0 0 0 1 ]
600
601 To:
602
603 [ X.x X.y X.z -dot(P, X) ]
604 [ Y.x Y.y Y.z -dot(P, Y) ]
605 [ Z.x Z.y Z.z -dot(P, Z) ]
606 [ 0 0 0 1 ]
607 */
608
609 float tmp[16] =
610 {
611 src[ 0], src[ 4], src[ 8], 0.0f,
612 src[ 1], src[ 5], src[ 9], 0.0f,
613 src[ 2], src[ 6], src[10], 0.0f,
614 - ( src[12]*src[ 0] + src[13]*src[ 1] + src[14]*src[ 2] ),
615 - ( src[12]*src[ 4] + src[13]*src[ 5] + src[14]*src[ 6] ),
616 - ( src[12]*src[ 8] + src[13]*src[ 9] + src[14]*src[ 10] ),
617 1.0f
618 };
619
620 memcpy ( dst, tmp, sizeof ( float ) * 16 );
621
622 return dst;
623}
624
637inline float* InvertMatrix ( float *mat, float *dest )
638{
639 float dst[16];
640 memcpy ( dst, dest, sizeof ( float ) * 16 );
641 float tmp[12]; /* temp array for pairs */
642 float src[16]; /* array of transpose source matrix */
643 float det; /* determinant */
644 /* transpose matrix */
645 for ( int i = 0; i < 4; i++ )
646 {
647 src[i] = mat[i * 4];
648 src[i + 4] = mat[i * 4 + 1];
649 src[i + 8] = mat[i * 4 + 2];
650 src[i + 12] = mat[i * 4 + 3];
651 }
652 /* calculate pairs for first 8 elements (cofactors) */
653 tmp[0] = src[10] * src[15];
654 tmp[1] = src[11] * src[14];
655 tmp[2] = src[9] * src[15];
656 tmp[3] = src[11] * src[13];
657 tmp[4] = src[9] * src[14];
658 tmp[5] = src[10] * src[13];
659 tmp[6] = src[8] * src[15];
660 tmp[7] = src[11] * src[12];
661 tmp[8] = src[8] * src[14];
662 tmp[9] = src[10] * src[12];
663 tmp[10] = src[8] * src[13];
664 tmp[11] = src[9] * src[12];
665 /* calculate first 8 elements (cofactors) */
666 dst[0] = tmp[0] * src[5] + tmp[3] * src[6] + tmp[4] * src[7];
667 dst[0] -= tmp[1] * src[5] + tmp[2] * src[6] + tmp[5] * src[7];
668 dst[1] = tmp[1] * src[4] + tmp[6] * src[6] + tmp[9] * src[7];
669 dst[1] -= tmp[0] * src[4] + tmp[7] * src[6] + tmp[8] * src[7];
670 dst[2] = tmp[2] * src[4] + tmp[7] * src[5] + tmp[10] * src[7];
671 dst[2] -= tmp[3] * src[4] + tmp[6] * src[5] + tmp[11] * src[7];
672 dst[3] = tmp[5] * src[4] + tmp[8] * src[5] + tmp[11] * src[6];
673 dst[3] -= tmp[4] * src[4] + tmp[9] * src[5] + tmp[10] * src[6];
674 dst[4] = tmp[1] * src[1] + tmp[2] * src[2] + tmp[5] * src[3];
675 dst[4] -= tmp[0] * src[1] + tmp[3] * src[2] + tmp[4] * src[3];
676 dst[5] = tmp[0] * src[0] + tmp[7] * src[2] + tmp[8] * src[3];
677 dst[5] -= tmp[1] * src[0] + tmp[6] * src[2] + tmp[9] * src[3];
678 dst[6] = tmp[3] * src[0] + tmp[6] * src[1] + tmp[11] * src[3];
679 dst[6] -= tmp[2] * src[0] + tmp[7] * src[1] + tmp[10] * src[3];
680 dst[7] = tmp[4] * src[0] + tmp[9] * src[1] + tmp[10] * src[2];
681 dst[7] -= tmp[5] * src[0] + tmp[8] * src[1] + tmp[11] * src[2];
682 /* calculate pairs for second 8 elements (cofactors) */
683 tmp[0] = src[2] * src[7];
684 tmp[1] = src[3] * src[6];
685 tmp[2] = src[1] * src[7];
686 tmp[3] = src[3] * src[5];
687 tmp[4] = src[1] * src[6];
688 tmp[5] = src[2] * src[5];
689 tmp[6] = src[0] * src[7];
690 tmp[7] = src[3] * src[4];
691 tmp[8] = src[0] * src[6];
692 tmp[9] = src[2] * src[4];
693 tmp[10] = src[0] * src[5];
694 tmp[11] = src[1] * src[4];
695 /* calculate second 8 elements (cofactors) */
696 dst[8] = tmp[0] * src[13] + tmp[3] * src[14] + tmp[4] * src[15];
697 dst[8] -= tmp[1] * src[13] + tmp[2] * src[14] + tmp[5] * src[15];
698 dst[9] = tmp[1] * src[12] + tmp[6] * src[14] + tmp[9] * src[15];
699 dst[9] -= tmp[0] * src[12] + tmp[7] * src[14] + tmp[8] * src[15];
700 dst[10] = tmp[2] * src[12] + tmp[7] * src[13] + tmp[10] * src[15];
701 dst[10] -= tmp[3] * src[12] + tmp[6] * src[13] + tmp[11] * src[15];
702 dst[11] = tmp[5] * src[12] + tmp[8] * src[13] + tmp[11] * src[14];
703 dst[11] -= tmp[4] * src[12] + tmp[9] * src[13] + tmp[10] * src[14];
704 dst[12] = tmp[2] * src[10] + tmp[5] * src[11] + tmp[1] * src[9];
705 dst[12] -= tmp[4] * src[11] + tmp[0] * src[9] + tmp[3] * src[10];
706 dst[13] = tmp[8] * src[11] + tmp[0] * src[8] + tmp[7] * src[10];
707 dst[13] -= tmp[6] * src[10] + tmp[9] * src[11] + tmp[1] * src[8];
708 dst[14] = tmp[6] * src[9] + tmp[11] * src[11] + tmp[3] * src[8];
709 dst[14] -= tmp[10] * src[11] + tmp[2] * src[8] + tmp[7] * src[9];
710 dst[15] = tmp[10] * src[10] + tmp[4] * src[8] + tmp[9] * src[9];
711 dst[15] -= tmp[8] * src[9] + tmp[11] * src[10] + tmp[5] * src[8];
712 /* calculate determinant */
713 det = src[0] * dst[0] + src[1] * dst[1] + src[2] * dst[2] + src[3] * dst[3];
714 /* calculate matrix inverse */
715 det = 1 / det;
716 for ( float & j : dst )
717 {
718 j *= det;
719 }
720 memcpy ( dest, dst, sizeof ( float ) * 16 );
721 return dest;
722}
723#if 0
725
737inline float* Multiply4x4Matrix ( const float* A, const float* B, float* out )
738{
739 float result[16];
740 float mx1[16];
741 float mx2[16];
742 memcpy ( mx1, A, sizeof ( float ) * 16 );
743 memcpy ( mx2, B, sizeof ( float ) * 16 );
744#if 0
745 // This code is unsafe, kept here only as reference
746 if ( bHasSSE )
747 {
748#ifdef __GNUC__
749 __asm__
750 (
751 "movss %0,%%xmm4\n\t"
752 "shufps $0x0,%%xmm4,%%xmm4\n\t"
753 "movups %1,%%xmm0\n\t"
754 "mulps %%xmm4,%%xmm0\n\t"
755 // ------+
756 "movss 4%0,%%xmm4\n\t"
757 "shufps $0x0,%%xmm4,%%xmm4\n\t"
758 "movups 16%1,%%xmm1\n\t"
759 "mulps %%xmm4,%%xmm1\n\t"
760 // ------+
761 "movss 8%0,%%xmm4\n\t"
762 "shufps $0x0,%%xmm4,%%xmm4\n\t"
763 "movups 32%1,%%xmm2\n\t"
764 "mulps %%xmm4,%%xmm2\n\t"
765 // ------+
766 "movss 12%0,%%xmm4\n\t"
767 "shufps $0x0,%%xmm4,%%xmm4\n\t"
768 "movups 48%1,%%xmm3\n\t"
769 "mulps %%xmm4,%%xmm3\n\t"
770 //-------+
771 "addps %%xmm1,%%xmm0\n\t"
772 "addps %%xmm2,%%xmm0\n\t"
773 "addps %%xmm3,%%xmm0\n\t"
774 "movups %%xmm0,%2\n\t"
775 // done a side
776 "movss 16%0,%%xmm4\n\t"
777 "shufps $0x0,%%xmm4,%%xmm4\n\t"
778 "movups %1,%%xmm0\n\t"
779 "mulps %%xmm4,%%xmm0\n\t"
780 // ------
781 "movss 20%0,%%xmm4\n\t"
782 "shufps $0x0,%%xmm4,%%xmm4\n\t"
783 "movups 16%1,%%xmm1\n\t"
784 "mulps %%xmm4,%%xmm1\n\t"
785 // ------
786 "movss 24%0,%%xmm4\n\t"
787 "shufps $0x0,%%xmm4,%%xmm4\n\t"
788 "movups 32%1,%%xmm2\n\t"
789 "mulps %%xmm4,%%xmm2\n\t"
790 // ------
791 "movss 28%0,%%xmm4\n\t"
792 "shufps $0x0,%%xmm4,%%xmm4\n\t"
793 "movups 48%1,%%xmm3\n\t"
794 "mulps %%xmm4,%%xmm3\n\t"
795 //-------
796 "addps %%xmm1,%%xmm0\n\t"
797 "addps %%xmm2,%%xmm0\n\t"
798 "addps %%xmm3,%%xmm0\n\t"
799 "movups %%xmm0,16%2\n\t"
800 // done a side
801 "movss 32%0,%%xmm4\n\t"
802 "shufps $0x0,%%xmm4,%%xmm4\n\t"
803 "movups %1,%%xmm0\n\t"
804 "mulps %%xmm4,%%xmm0\n\t"
805 // ------
806 "movss 36%0,%%xmm4\n\t"
807 "shufps $0x0,%%xmm4,%%xmm4\n\t"
808 "movups 16%1,%%xmm1\n\t"
809 "mulps %%xmm4,%%xmm1\n\t"
810 // ------
811 "movss 40%0,%%xmm4\n\t"
812 "shufps $0x0,%%xmm4,%%xmm4\n\t"
813 "movups 32%1,%%xmm2\n\t"
814 "mulps %%xmm4,%%xmm2\n\t"
815 // ------
816 "movss 44%0,%%xmm4\n\t"
817 "shufps $0x0,%%xmm4,%%xmm4\n\t"
818 "movups 48%1,%%xmm3\n\t"
819 "mulps %%xmm4,%%xmm3\n\t"
820 //-------
821 "addps %%xmm1,%%xmm0\n\t"
822 "addps %%xmm2,%%xmm0\n\t"
823 "addps %%xmm3,%%xmm0\n\t"
824 "movups %%xmm0,32%2\n\t"
825 // done a side
826 "movss 48%0,%%xmm4\n\t"
827 "shufps $0x0,%%xmm4,%%xmm4\n\t"
828 "movups %1,%%xmm0\n\t"
829 "mulps %%xmm4,%%xmm0\n\t"
830 // ------
831 "movss 52%0,%%xmm4\n\t"
832 "shufps $0x0,%%xmm4,%%xmm4\n\t"
833 "movups 16%1,%%xmm1\n\t"
834 "mulps %%xmm4,%%xmm1\n\t"
835 // ------
836 "movss 56%0,%%xmm4\n\t"
837 "shufps $0x0,%%xmm4,%%xmm4\n\t"
838 "movups 32%1,%%xmm2\n\t"
839 "mulps %%xmm4,%%xmm2\n\t"
840 // ------
841 "movss 60%0,%%xmm4\n\t"
842 "shufps $0x0,%%xmm4,%%xmm4\n\t"
843 "movups 48%1,%%xmm3\n\t"
844 "mulps %%xmm4,%%xmm3\n\t"
845 //-------
846 "addps %%xmm1,%%xmm0\n\t"
847 "addps %%xmm2,%%xmm0\n\t"
848 "addps %%xmm3,%%xmm0\n\t"
849 "movups %%xmm0,48%2\n\t"
850 :
851 : "m" ( mx[0] ), "m" ( m2[0] ), "m" ( result[0] )
852 : "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4"
853 );
854 // __asm__ __volatile__ ("rdtsc" : "=A" (nElapsedTime));
855 // fprintf(stdout,"ElapsedTime: %d\n",nElapsedTime-nCurrentTime);
856
857#elif _MSC_VER
858 __asm
859 {
860 // Small preamble, MSVC Inline ASM doesn't
861 // automatically reference object variables
862 mov eax, this // avoid C4537 Warning
863 lea eax, [eax]this.mx
864 mov ecx, MX // avoid C4537 Warning
865 lea ecx, [ecx]m2
866 lea edx, result // local variables need not be moved, if they are, app crashes
867 movss xmm4, [eax]
868 shufps xmm4, xmm4, 0
869 movups xmm0, [ecx]
870 mulps xmm0, xmm4
871 // ------
872 movss xmm4, [eax+ 4]
873 shufps xmm4, xmm4, 0
874 movups xmm1, [ecx+16]
875 mulps xmm1, xmm4
876 // ------
877 movss xmm4, [eax+ 8]
878 shufps xmm4, xmm4, 0
879 movups xmm2, [ecx+32]
880 mulps xmm2, xmm4
881 // ------
882 movss xmm4, [eax+ 12]
883 shufps xmm4, xmm4, 0
884 movups xmm3, [ecx+48]
885 mulps xmm3, xmm4
886 //-------
887 addps xmm0, xmm1
888 addps xmm0, xmm2
889 addps xmm0, xmm3
890 movups [edx], xmm0
891 // done a side
892 movss xmm4, [eax+ 16]
893 shufps xmm4, xmm4, 0
894 movups xmm0, [ecx]
895 mulps xmm0, xmm4
896 // ------
897 movss xmm4, [eax+ 20]
898 shufps xmm4, xmm4, 0
899 movups xmm1, [ecx+16]
900 mulps xmm1, xmm4
901 // ------
902 movss xmm4, [eax+ 24]
903 shufps xmm4, xmm4, 0
904 movups xmm2, [ecx+32]
905 mulps xmm2, xmm4
906 // ------
907 movss xmm4, [eax+ 28]
908 shufps xmm4, xmm4, 0
909 movups xmm3, [ecx+48]
910 mulps xmm3, xmm4
911 //-------
912 addps xmm0, xmm1
913 addps xmm0, xmm2
914 addps xmm0, xmm3
915 movups [edx+16], xmm0
916 // done a side
917 movss xmm4, [eax+ 32]
918 shufps xmm4, xmm4, 0
919 movups xmm0, [ecx]
920 mulps xmm0, xmm4
921 // ------
922 movss xmm4, [eax+ 36]
923 shufps xmm4, xmm4, 0
924 movups xmm1, [ecx+16]
925 mulps xmm1, xmm4
926 // ------
927 movss xmm4, [eax+ 40]
928 shufps xmm4, xmm4, 0
929 movups xmm2, [ecx+32]
930 mulps xmm2, xmm4
931 // ------
932 movss xmm4, [eax+ 44]
933 shufps xmm4, xmm4, 0
934 movups xmm3, [ecx+48]
935 mulps xmm3, xmm4
936 //-------
937 addps xmm0, xmm1
938 addps xmm0, xmm2
939 addps xmm0, xmm3
940 movups [edx+32], xmm0
941 // done a side
942 movss xmm4, [eax+ 48]
943 shufps xmm4, xmm4, 0
944 movups xmm0, [ecx]
945 mulps xmm0, xmm4
946 // ------
947 movss xmm4, [eax+ 52]
948 shufps xmm4, xmm4, 0
949 movups xmm1, [ecx+16]
950 mulps xmm1, xmm4
951 // ------
952 movss xmm4, [eax+ 56]
953 shufps xmm4, xmm4, 0
954 movups xmm2, [ecx+32]
955 mulps xmm2, xmm4
956 // ------
957 movss xmm4, [eax+ 60]
958 shufps xmm4, xmm4, 0
959 movups xmm3, [ecx+48]
960 mulps xmm3, xmm4
961 //-------
962 addps xmm0, xmm1
963 addps xmm0, xmm2
964 addps xmm0, xmm3
965 movups [edx+48], xmm0
966 // done a side
967 }
968#endif
969 }
970 else
971 {
972#endif
973#if 0
974 // Row mayor (DX way)
975 /* In column mayor you must pre multiply
976 this means that the Model View Projection Matrix must be calculated as:
977 Model * View * Projection */
978 result[ 0] = mx1[ 0] * mx2[ 0] + mx1[ 1] * mx2[ 4] + mx1[ 2] * mx2[ 8] + mx1[ 3] * mx2[12];
979 result[ 1] = mx1[ 0] * mx2[ 1] + mx1[ 1] * mx2[ 5] + mx1[ 2] * mx2[ 9] + mx1[ 3] * mx2[13];
980 result[ 2] = mx1[ 0] * mx2[ 2] + mx1[ 1] * mx2[ 6] + mx1[ 2] * mx2[10] + mx1[ 3] * mx2[14];
981 result[ 3] = mx1[ 0] * mx2[ 3] + mx1[ 1] * mx2[ 7] + mx1[ 2] * mx2[11] + mx1[ 3] * mx2[15];
982
983 result[ 4] = mx1[ 4] * mx2[ 0] + mx1[ 5] * mx2[ 4] + mx1[ 6] * mx2[ 8] + mx1[ 7] * mx2[12];
984 result[ 5] = mx1[ 4] * mx2[ 1] + mx1[ 5] * mx2[ 5] + mx1[ 6] * mx2[ 9] + mx1[ 7] * mx2[13];
985 result[ 6] = mx1[ 4] * mx2[ 2] + mx1[ 5] * mx2[ 6] + mx1[ 6] * mx2[10] + mx1[ 7] * mx2[14];
986 result[ 7] = mx1[ 4] * mx2[ 3] + mx1[ 5] * mx2[ 7] + mx1[ 6] * mx2[11] + mx1[ 7] * mx2[15];
987
988 result[ 8] = mx1[ 8] * mx2[ 0] + mx1[ 9] * mx2[ 4] + mx1[10] * mx2[ 8] + mx1[11] * mx2[12];
989 result[ 9] = mx1[ 8] * mx2[ 1] + mx1[ 9] * mx2[ 5] + mx1[10] * mx2[ 9] + mx1[11] * mx2[13];
990 result[10] = mx1[ 8] * mx2[ 2] + mx1[ 9] * mx2[ 6] + mx1[10] * mx2[10] + mx1[11] * mx2[14];
991 result[11] = mx1[ 8] * mx2[ 3] + mx1[ 9] * mx2[ 7] + mx1[10] * mx2[11] + mx1[11] * mx2[15];
992
993 result[12] = mx1[12] * mx2[ 0] + mx1[13] * mx2[ 4] + mx1[14] * mx2[ 8] + mx1[15] * mx2[12];
994 result[13] = mx1[12] * mx2[ 1] + mx1[13] * mx2[ 5] + mx1[14] * mx2[ 9] + mx1[15] * mx2[13];
995 result[14] = mx1[12] * mx2[ 2] + mx1[13] * mx2[ 6] + mx1[14] * mx2[10] + mx1[15] * mx2[14];
996 result[15] = mx1[12] * mx2[ 3] + mx1[13] * mx2[ 7] + mx1[14] * mx2[11] + mx1[15] * mx2[15];
997#else
998 // Column mayor (OpenGL way)
999 /* In column mayor you must post multiply,
1000 this means that the Model View Projection Matrix must be calculated as:
1001 Projection * View * Model */
1002 result[ 0] = mx1[ 0] * mx2[ 0] + mx1[ 4] * mx2[ 1] + mx1[ 8] * mx2[ 2] + mx1[12] * mx2[ 3];
1003 result[ 1] = mx1[ 1] * mx2[ 0] + mx1[ 5] * mx2[ 1] + mx1[ 9] * mx2[ 2] + mx1[13] * mx2[ 3];
1004 result[ 2] = mx1[ 2] * mx2[ 0] + mx1[ 6] * mx2[ 1] + mx1[10] * mx2[ 2] + mx1[14] * mx2[ 3];
1005 result[ 3] = mx1[ 3] * mx2[ 0] + mx1[ 7] * mx2[ 1] + mx1[11] * mx2[ 2] + mx1[15] * mx2[ 3];
1006
1007 result[ 4] = mx1[ 0] * mx2[ 4] + mx1[ 4] * mx2[ 5] + mx1[ 8] * mx2[ 6] + mx1[12] * mx2[ 7];
1008 result[ 5] = mx1[ 1] * mx2[ 4] + mx1[ 5] * mx2[ 5] + mx1[ 9] * mx2[ 6] + mx1[13] * mx2[ 7];
1009 result[ 6] = mx1[ 2] * mx2[ 4] + mx1[ 6] * mx2[ 5] + mx1[10] * mx2[ 6] + mx1[14] * mx2[ 7];
1010 result[ 7] = mx1[ 3] * mx2[ 4] + mx1[ 7] * mx2[ 5] + mx1[11] * mx2[ 6] + mx1[15] * mx2[ 7];
1011
1012 result[ 8] = mx1[ 0] * mx2[ 8] + mx1[ 4] * mx2[ 9] + mx1[ 8] * mx2[10] + mx1[12] * mx2[11];
1013 result[ 9] = mx1[ 1] * mx2[ 8] + mx1[ 5] * mx2[ 9] + mx1[ 9] * mx2[10] + mx1[13] * mx2[11];
1014 result[10] = mx1[ 2] * mx2[ 8] + mx1[ 6] * mx2[ 9] + mx1[10] * mx2[10] + mx1[14] * mx2[11];
1015 result[11] = mx1[ 3] * mx2[ 8] + mx1[ 7] * mx2[ 9] + mx1[11] * mx2[10] + mx1[15] * mx2[11];
1016
1017 result[12] = mx1[ 0] * mx2[12] + mx1[ 4] * mx2[13] + mx1[ 8] * mx2[14] + mx1[12] * mx2[15];
1018 result[13] = mx1[ 1] * mx2[12] + mx1[ 5] * mx2[13] + mx1[ 9] * mx2[14] + mx1[13] * mx2[15];
1019 result[14] = mx1[ 2] * mx2[12] + mx1[ 6] * mx2[13] + mx1[10] * mx2[14] + mx1[14] * mx2[15];
1020 result[15] = mx1[ 3] * mx2[12] + mx1[ 7] * mx2[13] + mx1[11] * mx2[14] + mx1[15] * mx2[15];
1021#endif
1022#if 0
1023 }
1024#endif
1025 memcpy ( out, result, sizeof ( float ) * 16 );
1026 return out;
1027}
1028#endif
1058inline float* Multiply3x3Matrix ( float* A, float* B, float* dst )
1059{
1060 float mx1[16];
1061 float mx2[16];
1062 memcpy ( mx1, A, sizeof ( float ) * 16 );
1063 memcpy ( mx2, B, sizeof ( float ) * 16 );
1064 // Column mayor (OpenGL way)
1065 dst[ 0] = mx1[ 0] * mx2[ 0] + mx1[ 4] * mx2[ 1] + mx1[ 8] * mx2[ 2];
1066 dst[ 1] = mx1[ 1] * mx2[ 0] + mx1[ 5] * mx2[ 1] + mx1[ 9] * mx2[ 2];
1067 dst[ 2] = mx1[ 2] * mx2[ 0] + mx1[ 6] * mx2[ 1] + mx1[10] * mx2[ 2];
1068
1069 dst[ 4] = mx1[ 0] * mx2[ 4] + mx1[ 4] * mx2[ 5] + mx1[ 8] * mx2[ 6];
1070 dst[ 5] = mx1[ 1] * mx2[ 4] + mx1[ 5] * mx2[ 5] + mx1[ 9] * mx2[ 6];
1071 dst[ 6] = mx1[ 2] * mx2[ 4] + mx1[ 6] * mx2[ 5] + mx1[10] * mx2[ 6];
1072
1073 dst[ 8] = mx1[ 0] * mx2[ 8] + mx1[ 4] * mx2[ 9] + mx1[ 8] * mx2[10];
1074 dst[ 9] = mx1[ 1] * mx2[ 8] + mx1[ 5] * mx2[ 9] + mx1[ 9] * mx2[10];
1075 dst[10] = mx1[ 2] * mx2[ 8] + mx1[ 6] * mx2[ 9] + mx1[10] * mx2[10];
1076 return dst;
1077}
1078
1089inline void InterpolateMatrices ( float* m1, float* m2, float* o, float i )
1090{
1091 if ( i < 0.0f )
1092 {
1093 memcpy ( o, m1, sizeof ( float ) * 16 );
1094 return;
1095 }
1096 else if ( i > 1.0f )
1097 {
1098 memcpy ( o, m2, sizeof ( float ) * 16 );
1099 return;
1100 }
1101 o[ 0] = m1[ 0] + ( ( m2[ 0] - m1[ 0] ) * i );
1102 o[ 1] = m1[ 1] + ( ( m2[ 1] - m1[ 1] ) * i );
1103 o[ 2] = m1[ 2] + ( ( m2[ 2] - m1[ 2] ) * i );
1104 o[ 3] = m1[ 3] + ( ( m2[ 3] - m1[ 3] ) * i );
1105 o[ 4] = m1[ 4] + ( ( m2[ 4] - m1[ 4] ) * i );
1106 o[ 5] = m1[ 5] + ( ( m2[ 5] - m1[ 5] ) * i );
1107 o[ 6] = m1[ 6] + ( ( m2[ 6] - m1[ 6] ) * i );
1108 o[ 7] = m1[ 7] + ( ( m2[ 7] - m1[ 7] ) * i );
1109 o[ 8] = m1[ 8] + ( ( m2[ 8] - m1[ 8] ) * i );
1110 o[ 9] = m1[ 9] + ( ( m2[ 9] - m1[ 9] ) * i );
1111 o[10] = m1[10] + ( ( m2[10] - m1[10] ) * i );
1112 o[11] = m1[11] + ( ( m2[11] - m1[11] ) * i );
1113 o[12] = m1[12] + ( ( m2[12] - m1[12] ) * i );
1114 o[13] = m1[13] + ( ( m2[13] - m1[13] ) * i );
1115 o[14] = m1[14] + ( ( m2[14] - m1[14] ) * i );
1116 o[15] = m1[15] + ( ( m2[15] - m1[15] ) * i );
1117}
1118#if 0
1120
1133inline float* GetRotationMatrix ( float* R, float angle, float x, float y, float z )
1134{
1135 float radians = float ( ( angle / 180.0f ) * PI );
1136 float c = cosf ( radians );
1137 float s = sinf ( radians );
1138 R[ 0] = x * x * ( 1 - c ) + c;
1139 R[ 1] = x * y * ( 1 - c ) - z * s;
1140 R[ 2] = x * z * ( 1 - c ) + y * s;
1141 R[ 3] = 0;
1142 R[ 4] = y * x * ( 1 - c ) + z * s;
1143 R[ 5] = y * y * ( 1 - c ) + c;
1144 R[ 6] = y * z * ( 1 - c ) - x * s;
1145 R[ 7] = 0;
1146 R[ 8] = x * z * ( 1 - c ) - y * s;
1147 R[ 9] = y * z * ( 1 - c ) + x * s;
1148 R[10] = z * z * ( 1 - c ) + c;
1149 R[11] = 0;
1150 R[12] = 0;
1151 R[13] = 0;
1152 R[14] = 0;
1153 R[15] = 1;
1154 return R;
1155}
1156#endif
1157#if 0
1169inline float* RotateMatrix ( float* src, float* dst, float angle, float x, float y, float z )
1170{
1171 /*
1172 This replicates how glRotatef works.
1173 */
1174 float r[16];
1175 GetRotationMatrix ( r, angle, x, y, z );
1176 return Multiply4x4Matrix ( src, r, dst );
1177}
1178#endif
1179#if 0
1194inline float* RotateMatrixObjectSpace ( float* src, float* dst, float angle, float x, float y, float z )
1195{
1196 float v[3] = {x, y, z};
1197 MultVector3x3Matrix ( v, src, v );
1198 if ( dst != src )
1199 {
1200 // safeguards
1201 dst[ 3] = 0;
1202 dst[ 7] = 0;
1203 dst[11] = 0;
1204 dst[12] = src[12];
1205 dst[13] = src[13];
1206 dst[14] = src[14];
1207 dst[15] = 1;
1208 }
1209 float r[16];
1210 GetRotationMatrix ( r, angle, v[0], v[1], v[2] );
1211 return Multiply3x3Matrix ( src, r, dst );
1212}
1213#endif
1214#if 0
1229inline float* RotateMatrixInertialSpace ( float* src, float* dst, float angle, float x, float y, float z )
1230{
1231 if ( dst != src )
1232 {
1233 // safeguards
1234 dst[ 3] = 0;
1235 dst[ 7] = 0;
1236 dst[11] = 0;
1237 dst[12] = src[12];
1238 dst[13] = src[13];
1239 dst[14] = src[14];
1240 dst[15] = 1;
1241 }
1242 float r[16];
1243 GetRotationMatrix ( r, angle, x, y, z );
1244 return Multiply3x3Matrix ( src, r, dst );
1245}
1246#endif
1247
1252inline float* Matrix3x3To4x4 ( const float* src, float* dst )
1253{
1254 dst[ 0] = src[ 0];
1255 dst[ 1] = src[ 1];
1256 dst[ 2] = src[ 2];
1257 dst[ 3] = 0;
1258
1259 dst[ 4] = src[ 4];
1260 dst[ 5] = src[ 5];
1261 dst[ 6] = src[ 6];
1262 dst[ 7] = 0;
1263
1264 dst[ 8] = src[ 8];
1265 dst[ 9] = src[ 9];
1266 dst[10] = src[10];
1267 dst[11] = 0;
1268
1269 dst[12] = 0;
1270 dst[13] = 0;
1271 dst[14] = 0;
1272 dst[15] = 1;
1273 return dst;
1274}
1275
1300inline float* TranslateMatrixObjectSpace ( float* v, float* src, float* dst )
1301{
1302 float result[16];
1303#if 0
1304 result[ 0] = src[ 0];
1305 result[ 1] = src[ 1];
1306 result[ 2] = src[ 2];
1307 result[ 3] = src[ 3];
1308
1309 result[ 4] = src[ 4];
1310 result[ 5] = src[ 5];
1311 result[ 6] = src[ 6];
1312 result[ 7] = src[ 7];
1313
1314 result[ 8] = src[ 8];
1315 result[ 9] = src[ 9];
1316 result[10] = src[10];
1317 result[11] = src[11];
1318
1319 result[12] = v[0] * src[ 0] + v[1] * src[ 4] + v[2] * src[ 8] + src[12];
1320 result[13] = v[0] * src[ 1] + v[1] * src[ 5] + v[2] * src[ 9] + src[13];
1321 result[14] = v[0] * src[ 2] + v[1] * src[ 6] + v[2] * src[10] + src[14];
1322 // in theory src[3], src[7] and src[11] will always be zero and src[15] one, safe to asume so?
1323 result[15] = v[0] * src[ 3] + v[1] * src[ 7] + v[2] * src[11] + src[15];
1324#else
1325 Matrix3x3To4x4 ( src, result );
1326 result[12] = src[ 0] * v[0] + src[ 4] * v[1] + src[ 8] * v[2] + src[12];
1327 result[13] = src[ 1] * v[0] + src[ 5] * v[1] + src[ 9] * v[2] + src[13];
1328 result[14] = src[ 2] * v[0] + src[ 6] * v[1] + src[10] * v[2] + src[14];
1329#endif
1330
1331 memcpy ( dst, result, sizeof ( float ) * 16 );
1332 return dst;
1333}
1334
1358inline float* TranslateMatrixInertialSpace ( float* v, float* src, float* dst )
1359{
1360 float result[16];
1361#if 0
1362 result[ 0] = src[ 0] + src[ 3] * v[ 0];
1363 result[ 1] = src[ 1] + src[ 3] * v[ 1];
1364 result[ 2] = src[ 2] + src[ 3] * v[ 2];
1365 result[ 3] = src[ 3];
1366
1367 result[ 4] = src[ 4] + src[ 7] * v[ 0];
1368 result[ 5] = src[ 5] + src[ 7] * v[ 1];
1369 result[ 6] = src[ 6] + src[ 7] * v[ 2];
1370 result[ 7] = src[ 7];
1371
1372 result[ 8] = src[ 8] + src[11] * v[ 0];
1373 result[ 9] = src[ 9] + src[11] * v[ 1];
1374 result[10] = src[10] + src[11] * v[ 2];
1375 result[11] = src[11];
1376
1377 result[12] = src[12] + src[15] * v[ 0];
1378 result[13] = src[13] + src[15] * v[ 1];
1379 result[14] = src[14] + src[15] * v[ 2];
1380 result[15] = src[15];
1381#else
1382 Matrix3x3To4x4 ( src, result );
1383 result[12] = src[12] + v[ 0];
1384 result[13] = src[13] + v[ 1];
1385 result[14] = src[14] + v[ 2];
1386#endif
1387 memcpy ( dst, result, sizeof ( float ) * 16 );
1388 return dst;
1389}
1390
1397inline float* GetMatrixFromSRT ( const float* srt, float* M )
1398{
1399 float R[9];
1400 QuatTo3x3Matrix ( srt + 3, R );
1401 // Simplified 3x3 scale matrix multiplication
1402 M[ 0] = R[ 0] * srt[0];
1403 M[ 1] = R[ 1] * srt[0];
1404 M[ 2] = R[ 2] * srt[0];
1405 M[ 3] = 0;
1406
1407 M[ 4] = R[ 3] * srt[1];
1408 M[ 5] = R[ 4] * srt[1];
1409 M[ 6] = R[ 5] * srt[1];
1410 M[ 7] = 0;
1411
1412 M[ 8] = R[ 6] * srt[2];
1413 M[ 9] = R[ 7] * srt[2];
1414 M[10] = R[ 8] * srt[2];
1415 M[11] = 0;
1416 // Simplified translation multiplication
1417 M[12] = srt[7];
1418 M[13] = srt[8];
1419 M[14] = srt[9];
1420 M[15] = 1;
1421 return M;
1422}
1423
1432
1433inline float* GetMatrixFromSRT ( float* s, float* r, float* t, float* M )
1434{
1435 float srt[10] = {s[0], s[1], s[2], r[0], r[1], r[2], r[3], t[0], t[1], t[2],};
1436 return GetMatrixFromSRT ( srt, M );
1437}
1438
1445inline float* GetInvertedMatrixFromSRT ( const float* srt, float* M )
1446{
1447#if 0
1448 // This works
1449 GetMatrixFromSRT ( srt, M );
1450 InvertOrthogonalMatrix ( M, M );
1451 return M;
1452#else
1453#if 0
1454 // this does work
1455 // This is a simple transpose approach
1456 float R[9];
1457 QuatTo3x3Matrix ( srt + 3, R );
1458 // Simplified 3x3 scale matrix multiplication
1459 M[0 ] = R[0] * srt[0];
1460 M[4 ] = R[1] * srt[0];
1461 M[8 ] = R[2] * srt[0];
1462 M[3] = 0;
1463
1464 M[1 ] = R[3] * srt[1];
1465 M[5 ] = R[4] * srt[1];
1466 M[9 ] = R[5] * srt[1];
1467 M[7] = 0;
1468
1469 M[2 ] = R[6] * srt[2];
1470 M[6 ] = R[7] * srt[2];
1471 M[10] = R[8] * srt[2];
1472 M[11] = 0;
1473
1474 // Simplified translation multiplication
1475 M[12] = M[0] * srt[7] + M[1] * srt[8] + M[2] * srt[9] + M[3];
1476 M[13] = M[4] * srt[7] + M[5] * srt[8] + M[6] * srt[9] + M[7];
1477 M[14] = M[8] * srt[7] + M[9] * srt[8] + M[10] * srt[9] + M[11];
1478 M[15] = 1;
1479 return M;
1480#else
1481 // This inverts each vector
1482 float invstr[10] =
1483 {
1484 1.0f / srt[0], 1.0f / srt[1], 1.0f / srt[2],
1485 srt[3], -srt[4], -srt[5], -srt[6],
1486 -srt[7], -srt[8], -srt[9]
1487 };
1488 RotateVectorByQuat ( invstr + 3, invstr + 7, invstr + 7 );
1489 GetMatrixFromSRT ( invstr, M );
1490 return M;
1491#endif
1492#endif
1493}
1494
1495// @}
1497// @{
1498//------------Quaternions------------------------------------------------
1500inline float* GetQuaternionInverse ( const float* q, float* out )
1501{
1502 out[0] = q[0];
1503 out[1] = -q[1];
1504 out[2] = -q[2];
1505 out[3] = -q[3];
1506 return out;
1507}
1508
1520inline void AngleAxisToQuat ( float angle, float x, float y, float z, float* quat )
1521{
1522 float radians = float ( ( angle / 180.0f ) * M_PI );
1523 float result = ( float ) sin ( radians / 2.0f );
1524 quat[0] = ( float ) cos ( radians / 2.0f );
1525 quat[1] = float ( x * result );
1526 quat[2] = float ( y * result );
1527 quat[3] = float ( z * result );
1528}
1529
1540inline void EulerToQuat ( float* euler, float* q )
1541{
1542 float roll = ( ( euler[0] / 180.0f ) * static_cast<float> ( M_PI ) );
1543 float pitch = ( ( euler[1] / 180.0f ) * static_cast<float> ( M_PI ) );
1544 float yaw = ( ( euler[2] / 180.0f ) * static_cast<float> ( M_PI ) );
1545 q[0] = cos ( roll / 2 ) * cos ( pitch / 2 ) * cos ( yaw / 2 ) + sin ( roll / 2 ) * sin ( pitch / 2 ) * sin ( yaw / 2 );
1546 q[1] = sin ( roll / 2 ) * cos ( pitch / 2 ) * cos ( yaw / 2 ) - cos ( roll / 2 ) * sin ( pitch / 2 ) * sin ( yaw / 2 );
1547 q[2] = cos ( roll / 2 ) * sin ( pitch / 2 ) * cos ( yaw / 2 ) + sin ( roll / 2 ) * cos ( pitch / 2 ) * sin ( yaw / 2 );
1548 q[3] = cos ( roll / 2 ) * cos ( pitch / 2 ) * sin ( yaw / 2 ) - sin ( roll / 2 ) * sin ( pitch / 2 ) * cos ( yaw / 2 );
1549}
1550
1556inline float* MultQuats ( const float* q1, const float* q2, float* out )
1557{
1558 // W,X,Y,Z
1559 float qc1[4] = {q1[0], q1[1], q1[2], q1[3]};
1560 float qc2[4] = {q2[0], q2[1], q2[2], q2[3]};
1561 out[0] = ( qc1[0] * qc2[0] - qc1[1] * qc2[1] - qc1[2] * qc2[2] - qc1[3] * qc2[3] );
1562 out[1] = ( qc1[0] * qc2[1] + qc1[1] * qc2[0] + qc1[2] * qc2[3] - qc1[3] * qc2[2] );
1563 out[2] = ( qc1[0] * qc2[2] - qc1[1] * qc2[3] + qc1[2] * qc2[0] + qc1[3] * qc2[1] );
1564 out[3] = ( qc1[0] * qc2[3] + qc1[1] * qc2[2] - qc1[2] * qc2[1] + qc1[3] * qc2[0] );
1565 return out;
1566}
1567
1575inline void QuatTo4x4Matrix ( float* q, float* m )
1576{
1577 // leaves the translation row intact
1578 m[ 0] = 1.0f - 2.0f * ( q[2] * q[2] + q[3] * q[3] );
1579 m[ 1] = 2.0f * ( q[1] * q[2] + q[3] * q[0] );
1580 m[ 2] = 2.0f * ( q[1] * q[3] - q[2] * q[0] );
1581 m[ 3] = 0.0f;
1582 // Second row
1583 m[ 4] = 2.0f * ( q[1] * q[2] - q[3] * q[0] );
1584 m[ 5] = 1.0f - 2.0f * ( q[1] * q[1] + q[3] * q[3] );
1585 m[ 6] = 2.0f * ( q[3] * q[2] + q[1] * q[0] );
1586 m[ 7] = 0.0f;
1587 // Third row
1588 m[ 8] = 2.0f * ( q[1] * q[3] + q[2] * q[0] );
1589 m[ 9] = 2.0f * ( q[2] * q[3] - q[1] * q[0] );
1590 m[10] = 1.0f - 2.0f * ( q[1] * q[1] + q[2] * q[2] );
1591 m[11] = 0.0f;
1592}
1593
1597inline void QuatTo3x3Matrix ( const float* q, float* m )
1598{
1599#if 0
1600 // First row
1601 m[ 0] = 1.0f - 2.0f * ( q[2] * q[2] + q[3] * q[3] );
1602 m[ 1] = 2.0f * ( q[1] * q[2] + q[3] * q[0] );
1603 m[ 2] = 2.0f * ( q[1] * q[3] - q[2] * q[0] );
1604 // Second row
1605 m[ 3] = 2.0f * ( q[1] * q[2] - q[3] * q[0] );
1606 m[ 4] = 1.0f - 2.0f * ( q[1] * q[1] + q[3] * q[3] );
1607 m[ 5] = 2.0f * ( q[3] * q[2] + q[1] * q[0] );
1608 // Third row
1609 m[ 6] = 2.0f * ( q[1] * q[3] + q[2] * q[0] );
1610 m[ 7] = 2.0f * ( q[2] * q[3] - q[1] * q[0] );
1611 m[ 8] = 1.0f - 2.0f * ( q[1] * q[1] + q[2] * q[2] );
1612#else
1613 // Products
1614 float p1 = q[0] * q[1];
1615 float p2 = q[0] * q[2];
1616 float p3 = q[0] * q[3];
1617
1618 float p4 = q[1] * q[1];
1619 float p5 = q[1] * q[2];
1620 float p6 = q[1] * q[3];
1621
1622 float p7 = q[2] * q[2];
1623 float p8 = q[2] * q[3];
1624
1625 float p9 = q[3] * q[3];
1626
1627 // First row
1628 m[ 0] = 1.0f - 2.0f * ( p7 + p9 );
1629 m[ 1] = 2.0f * ( p5 + p3 );
1630 m[ 2] = 2.0f * ( p6 - p2 );
1631 // Second row
1632 m[ 3] = 2.0f * ( p5 - p3 );
1633 m[ 4] = 1.0f - 2.0f * ( p4 + p9 );
1634 m[ 5] = 2.0f * ( p8 + p1 );
1635 // Third row
1636 m[ 6] = 2.0f * ( p6 + p2 );
1637 m[ 7] = 2.0f * ( p8 - p1 );
1638 m[ 8] = 1.0f - 2.0f * ( p4 + p7 );
1639#endif
1640}
1641
1649inline void Matrix4x4ToQuat ( float *matrix, float *q )
1650{
1651 /*
1652 [0][4][ 8][12]
1653 [1][5][ 9][13]
1654 [2][6][10][14]
1655 [3][7][11][15]
1656 */
1657 float T = matrix[0] + matrix[5] + matrix[10] + 1;
1658 float S;
1659 if ( T > 0.0f )
1660 {
1661 S = 0.5f / sqrtf ( T );
1662 q[0] = 0.25f / S;
1663 q[1] = ( matrix[6] - matrix[9] ) * S;
1664 q[2] = ( matrix[8] - matrix[2] ) * S;
1665 q[3] = ( matrix[1] - matrix[4] ) * S;
1666 return;
1667 }
1668 else
1669 {
1670 if ( ( matrix[0] > matrix[5] ) & ( matrix[0] > matrix[10] ) )
1671 {
1672 S = sqrtf ( 1.0f + matrix[0] - matrix[5] - matrix[10] ) * 2.0f; // S=4*qx
1673 q[0] = ( matrix[9] - matrix[6] ) / S;
1674 q[1] = 0.25f * S;
1675 q[2] = ( matrix[4] + matrix[1] ) / S;
1676 q[3] = ( matrix[8] + matrix[2] ) / S;
1677 }
1678 else if ( matrix[5] > matrix[10] )
1679 {
1680 S = sqrt ( 1.0f + matrix[5] - matrix[0] - matrix[10] ) * 2.0f; // S=4*qy
1681 q[0] = ( matrix[8] - matrix[2] ) / S;
1682 q[1] = ( matrix[4] + matrix[1] ) / S;
1683 q[2] = 0.25f * S;
1684 q[3] = ( matrix[9] + matrix[6] ) / S;
1685 }
1686 else
1687 {
1688 S = sqrt ( 1.0f + matrix[10] - matrix[0] - matrix[5] ) * 2.0f; // S=4*qz
1689 q[0] = ( matrix[4] - matrix[1] ) / S;
1690 q[1] = ( matrix[8] + matrix[2] ) / S;
1691 q[2] = ( matrix[9] + matrix[6] ) / S;
1692 q[3] = 0.25f * S;
1693 }
1694 }
1695}
1696#if 0
1709inline void Quat4x4MatrixMult ( float* q, float* m, float* dst )
1710{
1711 // \todo Reformat parameter order to match MultiplyMatrix
1712 float qm[16];
1713 qm[12] = 0;
1714 qm[13] = 0;
1715 qm[14] = 0;
1716 qm[15] = 1;
1717 QuatTo4x4Matrix ( q, qm );
1718 Multiply4x4Matrix ( qm, m, dst );
1719}
1720#endif
1721//-------------------------------------------//
1730inline void RotateVectorByQuat ( const float* q, const float* v, float* out )
1731{
1732 float localout[3];
1733#if 1
1734 float t1 = ( -q[1] * v[0] - q[2] * v[1] - q[3] * v[2] );
1735 float t2 = ( q[0] * v[0] + q[2] * v[2] - q[3] * v[1] );
1736 float t3 = ( q[0] * v[1] + q[3] * v[0] - q[1] * v[2] );
1737 float t4 = ( q[0] * v[2] + q[1] * v[1] - q[2] * v[0] );
1738
1739 localout[0] = t1 * -q[1] + t2 * q[0] + t3 * -q[3] - t4 * -q[2];
1740 localout[1] = t1 * -q[2] + t3 * q[0] + t4 * -q[1] - t2 * -q[3];
1741 localout[2] = t1 * -q[3] + t4 * q[0] + t2 * -q[2] - t3 * -q[1];
1742#else
1743 localout[0] =
1744 ( -q[1] * v[0] - q[2] * v[1] - q[3] * v[2] ) * -q[1] +
1745 ( q[0] * v[0] + q[2] * v[2] - q[3] * v[1] ) * q[0] +
1746 ( q[0] * v[1] + q[3] * v[0] - q[1] * v[2] ) * -q[3] -
1747 ( q[0] * v[2] + q[1] * v[1] - q[2] * v[0] ) * -q[2] ;
1748 localout[1] =
1749 ( -q[1] * v[0] - q[2] * v[1] - q[3] * v[2] ) * -q[2] +
1750 ( q[0] * v[1] + q[3] * v[0] - q[1] * v[2] ) * q[0] +
1751 ( q[0] * v[2] + q[1] * v[1] - q[2] * v[0] ) * -q[1] -
1752 ( q[0] * v[0] + q[2] * v[2] - q[3] * v[1] ) * -q[3] ;
1753 localout[2] =
1754 ( -q[1] * v[0] - q[2] * v[1] - q[3] * v[2] ) * -q[3] +
1755 ( q[0] * v[2] + q[1] * v[1] - q[2] * v[0] ) * q[0] +
1756 ( q[0] * v[0] + q[2] * v[2] - q[3] * v[1] ) * -q[2] -
1757 ( q[0] * v[1] + q[3] * v[0] - q[1] * v[2] ) * -q[1];
1758#endif
1759 out[0] = localout[0];
1760 out[1] = localout[1];
1761 out[2] = localout[2];
1762}
1763
1772inline void MultQuats4 ( float* q1, float* q2, float* out )
1773{
1774 float localout[4];
1775 localout[0] = ( q1[0] * q2[0] ) - ( q1[1] * q2[1] ) - ( q1[2] * q2[2] ) - ( q1[3] * q2[3] );
1776 localout[1] = ( q1[1] * q2[0] ) + ( q1[0] * q2[1] ) + ( q1[2] * q2[3] ) - ( q1[3] * q2[2] );
1777 localout[2] = ( q1[2] * q2[0] ) + ( q1[0] * q2[2] ) + ( q1[3] * q2[1] ) - ( q1[1] * q2[3] );
1778 localout[3] = ( q1[3] * q2[0] ) + ( q1[0] * q2[3] ) + ( q1[1] * q2[2] ) - ( q1[2] * q2[1] );
1779
1780#if 1
1781 /* compute magnitude of the quaternion */
1782 float mag = sqrtf ( ( localout[1] * localout[1] ) + ( localout[2] * localout[2] )
1783 + ( localout[3] * localout[3] ) + ( localout[0] * localout[0] ) );
1784
1785 /* check for bogus length, to protect against divide by zero */
1786 if ( mag > 0.0f )
1787 {
1788 /* normalize it */
1789 float oneOverMag = 1.0f / mag;
1790 localout[0] *= oneOverMag;
1791 localout[1] *= oneOverMag;
1792 localout[2] *= oneOverMag;
1793 localout[3] *= oneOverMag;
1794 }
1795#endif
1796 out[0] = localout[0];
1797 out[1] = localout[1];
1798 out[2] = localout[2];
1799 out[3] = localout[3];
1800}
1801
1808inline bool CapInterpolation ( const float* q1, const float* q2, double interpolation, float* out )
1809{
1810 if ( interpolation <= 0.0f )
1811 {
1812 out[1] = q1[1];
1813 out[2] = q1[2];
1814 out[3] = q1[3];
1815 out[0] = q1[0];
1816 return true;
1817 }
1818 else if ( interpolation >= 1.0f )
1819 {
1820 out[1] = q2[1];
1821 out[2] = q2[2];
1822 out[3] = q2[3];
1823 out[0] = q2[0];
1824 return true;
1825 }
1826 return false;
1827}
1828
1837inline float* LerpQuats ( const float* q1, const float* q2, double interpolation, float* out )
1838{
1839#if 0
1840 float sign = 1.0;
1841 float dot = Dot4 ( q1, q2 );
1842#endif
1843 if ( CapInterpolation ( q1, q2, interpolation, out ) )
1844 {
1845 return out;
1846 }
1847#if 0
1848 else if ( dot < 0.0f )
1849 {
1850 sign = -1.0;
1851 }
1852 out[0] = q1[0] + ( ( ( q2[0] * sign ) - q1[0] ) * interpolation );
1853 out[1] = q1[1] + ( ( ( q2[1] * sign ) - q1[1] ) * interpolation );
1854 out[2] = q1[2] + ( ( ( q2[2] * sign ) - q1[2] ) * interpolation );
1855 out[3] = q1[3] + ( ( ( q2[3] * sign ) - q1[3] ) * interpolation );
1856#else
1857 out[0] = static_cast<float> ( ( q1[0] * ( 1.0 - interpolation ) ) + ( q2[0] * interpolation ) );
1858 out[1] = static_cast<float> ( ( q1[1] * ( 1.0 - interpolation ) ) + ( q2[1] * interpolation ) );
1859 out[2] = static_cast<float> ( ( q1[2] * ( 1.0 - interpolation ) ) + ( q2[2] * interpolation ) );
1860 out[3] = static_cast<float> ( ( q1[3] * ( 1.0 - interpolation ) ) + ( q2[3] * interpolation ) );
1861#endif
1862 return out;
1863}
1864
1874inline float* NlerpQuats ( const float* q1, const float* q2, double interp, float* out )
1875{
1876 return Normalize4 ( LerpQuats ( q1, q2, interp, out ) );
1877}
1878
1885inline float* SlerpQuats ( float* q1, float* q2, float interpolation, float* out )
1886{
1887 if ( CapInterpolation ( q1, q2, interpolation, out ) )
1888 {
1889 return out;
1890 }
1891 float dot = Dot4 ( q1, q2 );
1892 float sign = 1.0f;
1893 if ( fabs ( dot ) > 0.9999f )
1894 {
1895 memcpy ( out, q1, sizeof ( float ) * 4 );
1896 return out;
1897 }
1898 else if ( dot < 0.0f )
1899 {
1900 dot = -dot;
1901 sign = -1.0;
1902 }
1903 float theta = acosf ( dot );
1904 float sinT = 1.0f / sinf ( theta );
1905 float newFactor = sinf ( interpolation * theta ) * sinT;
1906 float invFactor = sinf ( ( 1.0f - interpolation ) * theta ) * sinT;
1907
1908 out[0] = invFactor * q1[0] + newFactor * q2[0] * sign;
1909 out[1] = invFactor * q1[1] + newFactor * q2[1] * sign;
1910 out[2] = invFactor * q1[2] + newFactor * q2[2] * sign;
1911 out[3] = invFactor * q1[3] + newFactor * q2[3] * sign;
1912 return out;
1913}
1914#if 0
1915// Quaternion Logarithm
1916inline float* QuatLn ( float* q, float* out )
1917{
1918 // Clip W
1919 float w = q[0] > 1.0f ? 1.0f : q[0] < -1.0f ? -1.0f : q[0];
1920 float a = acosf ( w );
1921 float s = sinf ( a );
1922
1923 if ( s == 0.0f )
1924 {
1925 memset ( out, 0, sizeof ( float ) * 4 );
1926 }
1927 else
1928 {
1929 a /= s;
1930 out[0] = 0;
1931 out[1] = q[1] * a;
1932 out[2] = q[2] * a;
1933 out[3] = q[3] * a;
1934 }
1935 return out;
1936}
1937
1938// Quaternion Exponent
1939inline float* QuatExp ( float* q, float* out )
1940{
1941 float a = Length ( q + 1 );
1942 float s = sinf ( a );
1943 float c = cosf ( a );
1944
1945 out[0] = c;
1946 if ( a == 0.0f )
1947 {
1948 memset ( out + 1, 0, sizeof ( float ) * 3 );
1949 }
1950 else
1951 {
1952 s /= a;
1953 out[1] = q[1] * s;
1954 out[2] = q[2] * s;
1955 out[3] = q[3] * s;
1956 }
1957 return out;
1958}
1959inline float* GetInnerQuat ( float* past, float* current, float* future, float* out )
1960{
1961 float q[4] = {current[0], -current[1], -current[2], -current[3]};
1962 float tmp1[4];
1963 float tmp2[4];
1964 float tmp3[4];
1965 float tmp4[4];
1966 float tmp5[4];
1967 float tmp6[4];
1968 float tmp7[4];
1969 return Normalize4 ( MultQuats ( current, ScalarMultiply4 ( QuatExp ( Add4 ( QuatLn ( MultQuats ( q, past, tmp1 ), tmp2 ), QuatLn ( MultQuats ( q, future, tmp3 ), tmp4 ), tmp5 ), tmp6 ), -0.25f, tmp7 ), out ) );
1970}
1971
1978inline float* SquadQuats ( float* q0, float* q1, float* q2, float* q3, float interp, float* out )
1979{
1980 // http://theory.org/software/qfa/writeup/node12.html
1981 // ken shoemake Quaternion Calculus and Fast Animation
1982 // http://www.gamedev.net/topic/272295-interpolation-using-squad/
1983 // http://msdn.microsoft.com/en-us/library/windows/desktop/bb281657%28v=vs.85%29.aspx
1984 // http://www.gamedev.net/topic/421365-spline-based-quaternion-interpolation/
1985 // http://willperone.net/Code/quaternion.php
1986 float tmp1[4];
1987 float tmp2[4];
1988 float a1[4];
1989 float a2[4];
1990 return SlerpQuats ( SlerpQuats ( q1, q2, interp, tmp1 ), SlerpQuats ( GetInnerQuat ( q0, q1, q2, a1 ), GetInnerQuat ( q1, q2, q3, a2 ), interp, tmp2 ), 2 * interp * ( 1 - interp ), out );
1991 //return SlerpQuatsNoInvert ( SlerpQuatsNoInvert ( q1, q2, interp, tmp1 ), SlerpQuatsNoInvert ( GetInnerQuad ( q0, q1, q2, a1 ), GetInnerQuad ( q1, q2, q3, a2 ), interp, tmp2 ), 2 * interp * ( 1 - interp ), out );
1992}
1993#endif
1994
1995// @}
1997// @{
1999inline float* MultSRTs ( const float* srt1, const float* srt2, float* out )
2000{
2001 float localout[10];
2002 // Scale
2003 localout[0] = srt1[0] * srt2[0];
2004 localout[1] = srt1[1] * srt2[1];
2005 localout[2] = srt1[2] * srt2[2];
2006 // Rotation
2007 MultQuats ( srt1 + 3, srt2 + 3, localout + 3 );
2008 // Translation
2009 RotateVectorByQuat ( srt1 + 3, srt2 + 7, localout + 7 );
2010 localout[7] += srt1[7];
2011 localout[8] += srt1[8];
2012 localout[9] += srt1[9];
2013 memcpy ( out, localout, sizeof ( float ) * 10 );
2014 return out;
2015}
2016
2021inline float* InvertSRT ( const float* srt, float* out )
2022{
2023 out[0] = 1.0f / srt[0];
2024 out[1] = 1.0f / srt[1];
2025 out[2] = 1.0f / srt[2];
2026 out[3] = srt[3];
2027 out[4] = -srt[4];
2028 out[5] = -srt[5];
2029 out[6] = -srt[6];
2030 out[7] = -srt[7];
2031 out[8] = -srt[8];
2032 out[9] = -srt[9];
2033 RotateVectorByQuat ( out + 3, out + 7, out + 7 );
2034 return out;
2035}
2036// @}
2037
2039// @{
2045inline float PointDistanceToPlane ( float* plane, const float* point, const float* dimensions = nullptr )
2046{
2047 return
2048 plane[0] * point[0] +
2049 plane[1] * point[1] +
2050 plane[2] * point[2] -
2051 plane[3];
2052}
2053
2059inline float SphereDistanceToPlane ( float* plane, const float* point, const float* dimensions )
2060{
2061 return
2062 plane[0] * point[0] +
2063 plane[1] * point[1] +
2064 plane[2] * point[2] -
2065 ( plane[3] + dimensions[0] );
2066}
2067
2073inline float BoxDistanceToPlane ( float* plane, const float* point, const float* dimensions )
2074{
2075 float offsets[3] =
2076 {
2077 ( plane[0] < 0 ) ? dimensions[0] : -dimensions[0],
2078 ( plane[1] < 0 ) ? dimensions[1] : -dimensions[1],
2079 ( plane[2] < 0 ) ? dimensions[2] : -dimensions[2]
2080 };
2081
2082 float dist = plane[3] - Dot ( offsets, plane );
2083
2084 return
2085 plane[0] * point[0] +
2086 plane[1] * point[1] +
2087 plane[2] * point[2] - dist;
2088}
2089
2095inline float CapsuleDistanceToPlane ( float* plane, const float* point, const float* dimensions )
2096{
2097 // radius is dimensions[0] and halfheight is dimensions [1]
2098
2099 float dist = plane[3] + dimensions[0];
2100
2101 float offset = dimensions[1] - dimensions[0];
2102
2103 float direction = plane[2] * offset;
2104
2105 if ( direction > 0 )
2106 {
2107 // if the offset (halfheight-radius) is in the same direction as the plane normal subtract it from the point
2108 return
2109 plane[0] * point[0] +
2110 plane[1] * point[1] +
2111 plane[2] * ( point[2] - offset ) -
2112 dist;
2113 }
2114 // if the offset (halfheight-radius) is in the oposite direction or parallel to the plane normal add it to the point
2115 return
2116 plane[0] * point[0] +
2117 plane[1] * point[1] +
2118 plane[2] * ( point[2] + offset ) -
2119 dist;
2120}
2121// @}
2122
2125inline void PrintMatrix ( const float* M )
2126{
2127 printf (
2128 "%f %f %f %f\n"
2129 "%f %f %f %f\n"
2130 "%f %f %f %f\n"
2131 "%f %f %f %f\n",
2132 M[0], M[4], M[ 8], M[12],
2133 M[1], M[5], M[ 9], M[13],
2134 M[2], M[6], M[10], M[14],
2135 M[3], M[7], M[11], M[15]
2136 );
2137}
2138#endif
float * MultQuats(const float *q1, const float *q2, float *out)
Multiply two quaternions.
Definition 3DMath.h:1556
float * InvertOrthogonalMatrix(float *src, float *dst)
Inverts a RT (rotation and translation) 4x4 matrix.
Definition 3DMath.h:591
void PrintMatrix(const float *M)
Prints a 4x4 matrix to stdout in row-major visual layout.
Definition 3DMath.h:2125
float * LerpQuats(const float *q1, const float *q2, double interpolation, float *out)
Linearly interpolate between two quaternions.
Definition 3DMath.h:1837
float * NormalizePlane(float const *const aPlane, float *aOut)
Normalizes a plane.
Definition 3DMath.h:195
float * TranslateMatrixInertialSpace(float *v, float *src, float *dst)
Translates a 4x4 matrix using a vector relative from its current position using the inertial axis.
Definition 3DMath.h:1358
float * MultVectorScalar(float *v, float s, float *out)
Multiplies a vector and a Scalar.
Definition 3DMath.h:356
float * InvertSRT(const float *srt, float *out)
Inverts an SRT (scale-rotation-translation) transform.
Definition 3DMath.h:2021
float sabs(float x)
Single pressision floating point absolute value.
Definition 3DMath.h:92
float * Transpose3x3Matrix(const float *src, float *dst)
Transposes a 3x3 Matrix.
Definition 3DMath.h:501
float * Extract3x3Matrix(const float *m, float *out)
Extracts a 3x3 matrix from a 4x4 matrix.
Definition 3DMath.h:421
float PointDistanceToPlane(float *plane, const float *point, const float *dimensions=nullptr)
Computes the signed distance from a point to a plane.
Definition 3DMath.h:2045
float * Convert3x3To4x3(const float *m, float *out)
converts a 3x3 matrix to a 4x3 matrix.
Definition 3DMath.h:464
float * Matrix3x3To4x4(const float *src, float *dst)
Copies the 3x3 rotational part of a 4x4 matrix into a new 4x4 matrix.
Definition 3DMath.h:1252
float * NlerpQuats(const float *q1, const float *q2, double interp, float *out)
Linearly interpolate between two quaternions return the normalized result.
Definition 3DMath.h:1874
float * GetMatrixFromSRT(const float *srt, float *M)
Constructs a transformation matrix from SRT vector.
Definition 3DMath.h:1397
void EulerToQuat(float *euler, float *q)
Convert euler angle rotation notation to a quaternion.
Definition 3DMath.h:1540
float Distance(const float a[], const float b[])
Returns the distance between point a and b.
Definition 3DMath.h:329
float * GetQuaternionInverse(const float *q, float *out)
Inverts a unit length quaternion, same as quaternion conjugate.
Definition 3DMath.h:1500
float * Normalize4(float *v)
Normalize vector.
Definition 3DMath.h:175
void QuatTo3x3Matrix(const float *q, float *m)
Builds a 3x3 rotation matrix out of a quaternion.
Definition 3DMath.h:1597
float * Invert3x3Matrix(const float *src, float *dst)
Inverts a 3x3 Matrix.
Definition 3DMath.h:530
float DeterminantMatrix3(const float *src)
Computes the determinant of a 3x3 matrix.
Definition 3DMath.h:518
float * Multiply3x3Matrix(float *A, float *B, float *dst)
Multiplies only the 3x3 part of two 4x4 matrices.
Definition 3DMath.h:1058
float * Cross3(float *v1, float *v2, float *dst)
Cross product.
Definition 3DMath.h:106
float SphereDistanceToPlane(float *plane, const float *point, const float *dimensions)
Computes the distance from a bounding sphere to a plane.
Definition 3DMath.h:2059
float * GetScaleVectorInverse(const float *v, float *out)
Returns the multiplicative inverse of a scale (transform) vector.
Definition 3DMath.h:380
void MultQuats4(float *q1, float *q2, float *out)
Multiplies two quaternions.
Definition 3DMath.h:1772
void QuatTo4x4Matrix(float *q, float *m)
Builds a 3x4 rotation matrix out of a quaternion inside a 4x4 matrix.
Definition 3DMath.h:1575
void ClipVelocity(float *v, float *normal, float overbounce)
Clips Velocity against impacting surface normal.
Definition 3DMath.h:249
void InterpolateMatrices(float *m1, float *m2, float *o, float i)
Linearly interpolate two matrices.
Definition 3DMath.h:1089
float * SetIdentityMatrix4x4(float *M)
Set a matrix to the Identity.
Definition 3DMath.h:410
float * Convert3x3To4x4(const float *m, float *out)
converts a 3x3 matrix to a 4x4 matrix.
Definition 3DMath.h:488
float * Extract3x3Into4x4(const float *m, float *out)
Extracts a 3x3 matrix from a 4x4 matrix into a 4x4 matrix.
Definition 3DMath.h:439
void Matrix4x4ToQuat(float *matrix, float *q)
Extracts rotation matrix and converts it into a quaternion.
Definition 3DMath.h:1649
float DistanceSquared(const float a[], const float b[])
Returns the squared distance between point a and b.
Definition 3DMath.h:316
void AngleAxisToQuat(float angle, float x, float y, float z, float *quat)
Convert axis angle rotation notation to a quaternion.
Definition 3DMath.h:1520
int ClosestAxis(float *v)
Returns the closest to paralell axis to the provided vector.
Definition 3DMath.h:281
float * TranslateMatrixObjectSpace(float *v, float *src, float *dst)
Translates a 4x4 matrix using a vector relative from its current position using the object axis.
Definition 3DMath.h:1300
float * Add4(float *v1, float *v2, float *out)
adds two 4 element vectors.
Definition 3DMath.h:212
float * MultSRTs(const float *srt1, const float *srt2, float *out)
This function should be equivalent to multiplying the two matrices generated from the SRTs.
Definition 3DMath.h:1999
float BoxDistanceToPlane(float *plane, const float *point, const float *dimensions)
Computes the distance from an axis-aligned bounding box to a plane.
Definition 3DMath.h:2073
float * GetPositionVectorInverse(const float *v, float *out)
Returns the additive inverse of a position (transform) vector.
Definition 3DMath.h:388
float * MultVector4x4Matrix(const float *v, const float *m, float *out)
Multiplies a vector and a 4x4 matrix.
Definition 3DMath.h:341
void RotateVectorByQuat(const float *q, const float *v, float *out)
Rotates a vector around the origin by a quaternion.
Definition 3DMath.h:1730
float Dot(const float v1[], const float v2[])
3 element vector Dot Product.
Definition 3DMath.h:139
float Length(float const *const v)
Calculate vector length.
Definition 3DMath.h:120
float * Subtract4(float *v1, float *v2, float *out)
adds two 4 element vectors.
Definition 3DMath.h:223
void MultVector3x3Matrix(float *v, float *m, float *out)
Multiplies a vector and the rotational 3x3 part of a 4x4 matrix.
Definition 3DMath.h:371
bool CapInterpolation(const float *q1, const float *q2, double interpolation, float *out)
Caps quaternion interpolation factor to [0,1] and copies the corresponding endpoint.
Definition 3DMath.h:1808
float Length4(float *v)
Calculate 4 element vector length.
Definition 3DMath.h:129
float CapsuleDistanceToPlane(float *plane, const float *point, const float *dimensions)
Computes the distance from a capsule to a plane.
Definition 3DMath.h:2095
float * GetInvertedMatrixFromSRT(const float *srt, float *M)
Constructs an inverted transformation matrix from SRT vector.
Definition 3DMath.h:1445
float * SlerpQuats(float *q1, float *q2, float interpolation, float *out)
Spherical Linear interpolation between two quaternions.
Definition 3DMath.h:1885
float Dot4(const float v1[], const float v2[])
4 element vector Dot Product.
Definition 3DMath.h:149
void InterpolateVectors(float *v1, float *v2, float interpolation, float *out)
Interpolates between two vectors.
Definition 3DMath.h:298
float * Normalize(float *v)
Normalize vector.
Definition 3DMath.h:158
float * InvertMatrix(float *mat, float *dest)
Invert a 4x4 matrix.
Definition 3DMath.h:637
float * ScalarMultiply4(float *v, float s, float *out)
Multiply 4 element vector by a scalar.
Definition 3DMath.h:233