1 /*************************************************************************
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
21 *************************************************************************/
23 #ifndef _ODE_ODEMATH_H_
24 #define _ODE_ODEMATH_H_
26 #include <ode/common.h>
29 * macro to access elements i,j in an NxM matrix A, independent of the
30 * matrix storage convention.
32 #define dACCESS33(A,i,j) ((A)[(i)*4+(j)])
35 * Macro to test for valid floating point values
37 #define dVALIDVEC3(v) (!(dIsNan(v[0]) || dIsNan(v[1]) || dIsNan(v[2])))
38 #define dVALIDVEC4(v) (!(dIsNan(v[0]) || dIsNan(v[1]) || dIsNan(v[2]) || dIsNan(v[3])))
39 #define dVALIDMAT3(m) (!(dIsNan(m[0]) || dIsNan(m[1]) || dIsNan(m[2]) || dIsNan(m[3]) || dIsNan(m[4]) || dIsNan(m[5]) || dIsNan(m[6]) || dIsNan(m[7]) || dIsNan(m[8]) || dIsNan(m[9]) || dIsNan(m[10]) || dIsNan(m[11])))
40 #define dVALIDMAT4(m) (!(dIsNan(m[0]) || dIsNan(m[1]) || dIsNan(m[2]) || dIsNan(m[3]) || dIsNan(m[4]) || dIsNan(m[5]) || dIsNan(m[6]) || dIsNan(m[7]) || dIsNan(m[8]) || dIsNan(m[9]) || dIsNan(m[10]) || dIsNan(m[11]) || dIsNan(m[12]) || dIsNan(m[13]) || dIsNan(m[14]) || dIsNan(m[15]) ))
43 ODE_PURE_INLINE
void dZeroVector3(dVector3 res
)
45 res
[dV3E_X
] = REAL(0.0);
46 res
[dV3E_Y
] = REAL(0.0);
47 res
[dV3E_Z
] = REAL(0.0);
50 ODE_PURE_INLINE
void dAssignVector3(dVector3 res
, dReal x
, dReal y
, dReal z
)
57 ODE_PURE_INLINE
void dZeroMatrix3(dMatrix3 res
)
59 res
[dM3E_XX
] = REAL(0.0); res
[dM3E_XY
] = REAL(0.0); res
[dM3E_XZ
] = REAL(0.0);
60 res
[dM3E_YX
] = REAL(0.0); res
[dM3E_YY
] = REAL(0.0); res
[dM3E_YZ
] = REAL(0.0);
61 res
[dM3E_ZX
] = REAL(0.0); res
[dM3E_ZY
] = REAL(0.0); res
[dM3E_ZZ
] = REAL(0.0);
64 ODE_PURE_INLINE
void dZeroMatrix4(dMatrix4 res
)
66 res
[dM4E_XX
] = REAL(0.0); res
[dM4E_XY
] = REAL(0.0); res
[dM4E_XZ
] = REAL(0.0); res
[dM4E_XO
] = REAL(0.0);
67 res
[dM4E_YX
] = REAL(0.0); res
[dM4E_YY
] = REAL(0.0); res
[dM4E_YZ
] = REAL(0.0); res
[dM4E_YO
] = REAL(0.0);
68 res
[dM4E_ZX
] = REAL(0.0); res
[dM4E_ZY
] = REAL(0.0); res
[dM4E_ZZ
] = REAL(0.0); res
[dM4E_ZO
] = REAL(0.0);
69 res
[dM4E_OX
] = REAL(0.0); res
[dM4E_OY
] = REAL(0.0); res
[dM4E_OZ
] = REAL(0.0); res
[dM4E_OO
] = REAL(0.0);
72 /* Some vector math */
73 ODE_PURE_INLINE
void dAddVectors3(dReal
*res
, const dReal
*a
, const dReal
*b
)
75 const dReal res_0
= a
[0] + b
[0];
76 const dReal res_1
= a
[1] + b
[1];
77 const dReal res_2
= a
[2] + b
[2];
78 /* Only assign after all the calculations are over to avoid incurring memory aliasing*/
79 res
[0] = res_0
; res
[1] = res_1
; res
[2] = res_2
;
82 ODE_PURE_INLINE
void dSubtractVectors3(dReal
*res
, const dReal
*a
, const dReal
*b
)
84 const dReal res_0
= a
[0] - b
[0];
85 const dReal res_1
= a
[1] - b
[1];
86 const dReal res_2
= a
[2] - b
[2];
87 /* Only assign after all the calculations are over to avoid incurring memory aliasing*/
88 res
[0] = res_0
; res
[1] = res_1
; res
[2] = res_2
;
91 ODE_PURE_INLINE
void dAddVectorScaledVector3(dReal
*res
, const dReal
*a
, const dReal
*b
, dReal b_scale
)
93 const dReal res_0
= a
[0] + b_scale
* b
[0];
94 const dReal res_1
= a
[1] + b_scale
* b
[1];
95 const dReal res_2
= a
[2] + b_scale
* b
[2];
96 /* Only assign after all the calculations are over to avoid incurring memory aliasing*/
97 res
[0] = res_0
; res
[1] = res_1
; res
[2] = res_2
;
100 ODE_PURE_INLINE
void dAddScaledVectors3(dReal
*res
, const dReal
*a
, const dReal
*b
, dReal a_scale
, dReal b_scale
)
102 const dReal res_0
= a_scale
* a
[0] + b_scale
* b
[0];
103 const dReal res_1
= a_scale
* a
[1] + b_scale
* b
[1];
104 const dReal res_2
= a_scale
* a
[2] + b_scale
* b
[2];
105 /* Only assign after all the calculations are over to avoid incurring memory aliasing*/
106 res
[0] = res_0
; res
[1] = res_1
; res
[2] = res_2
;
109 ODE_PURE_INLINE
void dAddThreeScaledVectors3(dReal
*res
, const dReal
*a
, const dReal
*b
, const dReal
*c
, dReal a_scale
, dReal b_scale
, dReal c_scale
)
111 const dReal res_0
= a_scale
* a
[0] + b_scale
* b
[0] + c_scale
* c
[0];
112 const dReal res_1
= a_scale
* a
[1] + b_scale
* b
[1] + c_scale
* c
[1];
113 const dReal res_2
= a_scale
* a
[2] + b_scale
* b
[2] + c_scale
* c
[2];
114 /* Only assign after all the calculations are over to avoid incurring memory aliasing*/
115 res
[0] = res_0
; res
[1] = res_1
; res
[2] = res_2
;
118 ODE_PURE_INLINE
void dScaleVector3(dReal
*res
, dReal nScale
)
125 ODE_PURE_INLINE
void dNegateVector3(dReal
*res
)
132 ODE_PURE_INLINE
void dCopyVector3(dReal
*res
, const dReal
*a
)
134 const dReal res_0
= a
[0];
135 const dReal res_1
= a
[1];
136 const dReal res_2
= a
[2];
137 /* Only assign after all the calculations are over to avoid incurring memory aliasing*/
138 res
[0] = res_0
; res
[1] = res_1
; res
[2] = res_2
;
141 ODE_PURE_INLINE
void dCopyScaledVector3(dReal
*res
, const dReal
*a
, dReal nScale
)
143 const dReal res_0
= a
[0] * nScale
;
144 const dReal res_1
= a
[1] * nScale
;
145 const dReal res_2
= a
[2] * nScale
;
146 /* Only assign after all the calculations are over to avoid incurring memory aliasing*/
147 res
[0] = res_0
; res
[1] = res_1
; res
[2] = res_2
;
150 ODE_PURE_INLINE
void dCopyNegatedVector3(dReal
*res
, const dReal
*a
)
152 const dReal res_0
= -a
[0];
153 const dReal res_1
= -a
[1];
154 const dReal res_2
= -a
[2];
155 /* Only assign after all the calculations are over to avoid incurring memory aliasing*/
156 res
[0] = res_0
; res
[1] = res_1
; res
[2] = res_2
;
159 ODE_PURE_INLINE
void dCopyVector4(dReal
*res
, const dReal
*a
)
161 const dReal res_0
= a
[0];
162 const dReal res_1
= a
[1];
163 const dReal res_2
= a
[2];
164 const dReal res_3
= a
[3];
165 /* Only assign after all the calculations are over to avoid incurring memory aliasing*/
166 res
[0] = res_0
; res
[1] = res_1
; res
[2] = res_2
; res
[3] = res_3
;
169 ODE_PURE_INLINE
void dCopyMatrix4x4(dReal
*res
, const dReal
*a
)
171 dCopyVector4(res
+ 0, a
+ 0);
172 dCopyVector4(res
+ 4, a
+ 4);
173 dCopyVector4(res
+ 8, a
+ 8);
176 ODE_PURE_INLINE
void dCopyMatrix4x3(dReal
*res
, const dReal
*a
)
178 dCopyVector3(res
+ 0, a
+ 0);
179 dCopyVector3(res
+ 4, a
+ 4);
180 dCopyVector3(res
+ 8, a
+ 8);
183 ODE_PURE_INLINE
void dGetMatrixColumn3(dReal
*res
, const dReal
*a
, unsigned n
)
185 const dReal res_0
= a
[n
+ 0];
186 const dReal res_1
= a
[n
+ 4];
187 const dReal res_2
= a
[n
+ 8];
188 /* Only assign after all the calculations are over to avoid incurring memory aliasing*/
189 res
[0] = res_0
; res
[1] = res_1
; res
[2] = res_2
;
192 ODE_PURE_INLINE dReal
dCalcVectorLength3(const dReal
*a
)
194 return dSqrt(a
[0] * a
[0] + a
[1] * a
[1] + a
[2] * a
[2]);
197 ODE_PURE_INLINE dReal
dCalcVectorLengthSquare3(const dReal
*a
)
199 return (a
[0] * a
[0] + a
[1] * a
[1] + a
[2] * a
[2]);
202 ODE_PURE_INLINE dReal
dCalcPointDepth3(const dReal
*test_p
, const dReal
*plane_p
, const dReal
*plane_n
)
204 return (plane_p
[0] - test_p
[0]) * plane_n
[0] + (plane_p
[1] - test_p
[1]) * plane_n
[1] + (plane_p
[2] - test_p
[2]) * plane_n
[2];
209 * 3-way dot product. _dCalcVectorDot3 means that elements of `a' and `b' are spaced
210 * step_a and step_b indexes apart respectively. dCalcVectorDot3() means dDot311.
213 ODE_PURE_INLINE dReal
_dCalcVectorDot3(const dReal
*a
, const dReal
*b
, unsigned step_a
, unsigned step_b
)
215 return a
[0] * b
[0] + a
[step_a
] * b
[step_b
] + a
[2 * step_a
] * b
[2 * step_b
];
219 ODE_PURE_INLINE dReal
dCalcVectorDot3 (const dReal
*a
, const dReal
*b
) { return _dCalcVectorDot3(a
,b
,1,1); }
220 ODE_PURE_INLINE dReal
dCalcVectorDot3_13 (const dReal
*a
, const dReal
*b
) { return _dCalcVectorDot3(a
,b
,1,3); }
221 ODE_PURE_INLINE dReal
dCalcVectorDot3_31 (const dReal
*a
, const dReal
*b
) { return _dCalcVectorDot3(a
,b
,3,1); }
222 ODE_PURE_INLINE dReal
dCalcVectorDot3_33 (const dReal
*a
, const dReal
*b
) { return _dCalcVectorDot3(a
,b
,3,3); }
223 ODE_PURE_INLINE dReal
dCalcVectorDot3_14 (const dReal
*a
, const dReal
*b
) { return _dCalcVectorDot3(a
,b
,1,4); }
224 ODE_PURE_INLINE dReal
dCalcVectorDot3_41 (const dReal
*a
, const dReal
*b
) { return _dCalcVectorDot3(a
,b
,4,1); }
225 ODE_PURE_INLINE dReal
dCalcVectorDot3_44 (const dReal
*a
, const dReal
*b
) { return _dCalcVectorDot3(a
,b
,4,4); }
229 * cross product, set res = a x b. _dCalcVectorCross3 means that elements of `res', `a'
230 * and `b' are spaced step_res, step_a and step_b indexes apart respectively.
231 * dCalcVectorCross3() means dCross3111.
234 ODE_PURE_INLINE
void _dCalcVectorCross3(dReal
*res
, const dReal
*a
, const dReal
*b
, unsigned step_res
, unsigned step_a
, unsigned step_b
)
236 const dReal res_0
= a
[ step_a
]*b
[2*step_b
] - a
[2*step_a
]*b
[ step_b
];
237 const dReal res_1
= a
[2*step_a
]*b
[ 0] - a
[ 0]*b
[2*step_b
];
238 const dReal res_2
= a
[ 0]*b
[ step_b
] - a
[ step_a
]*b
[ 0];
239 /* Only assign after all the calculations are over to avoid incurring memory aliasing*/
241 res
[ step_res
] = res_1
;
242 res
[2*step_res
] = res_2
;
245 ODE_PURE_INLINE
void dCalcVectorCross3 (dReal
*res
, const dReal
*a
, const dReal
*b
) { _dCalcVectorCross3(res
, a
, b
, 1, 1, 1); }
246 ODE_PURE_INLINE
void dCalcVectorCross3_114(dReal
*res
, const dReal
*a
, const dReal
*b
) { _dCalcVectorCross3(res
, a
, b
, 1, 1, 4); }
247 ODE_PURE_INLINE
void dCalcVectorCross3_141(dReal
*res
, const dReal
*a
, const dReal
*b
) { _dCalcVectorCross3(res
, a
, b
, 1, 4, 1); }
248 ODE_PURE_INLINE
void dCalcVectorCross3_144(dReal
*res
, const dReal
*a
, const dReal
*b
) { _dCalcVectorCross3(res
, a
, b
, 1, 4, 4); }
249 ODE_PURE_INLINE
void dCalcVectorCross3_411(dReal
*res
, const dReal
*a
, const dReal
*b
) { _dCalcVectorCross3(res
, a
, b
, 4, 1, 1); }
250 ODE_PURE_INLINE
void dCalcVectorCross3_414(dReal
*res
, const dReal
*a
, const dReal
*b
) { _dCalcVectorCross3(res
, a
, b
, 4, 1, 4); }
251 ODE_PURE_INLINE
void dCalcVectorCross3_441(dReal
*res
, const dReal
*a
, const dReal
*b
) { _dCalcVectorCross3(res
, a
, b
, 4, 4, 1); }
252 ODE_PURE_INLINE
void dCalcVectorCross3_444(dReal
*res
, const dReal
*a
, const dReal
*b
) { _dCalcVectorCross3(res
, a
, b
, 4, 4, 4); }
254 ODE_PURE_INLINE
void dAddVectorCross3(dReal
*res
, const dReal
*a
, const dReal
*b
)
257 dCalcVectorCross3(tmp
, a
, b
);
258 dAddVectors3(res
, res
, tmp
);
261 ODE_PURE_INLINE
void dSubtractVectorCross3(dReal
*res
, const dReal
*a
, const dReal
*b
)
264 dCalcVectorCross3(tmp
, a
, b
);
265 dSubtractVectors3(res
, res
, tmp
);
270 * set a 3x3 submatrix of A to a matrix such that submatrix(A)*b = a x b.
271 * A is stored by rows, and has `skip' elements per row. the matrix is
272 * assumed to be already zero, so this does not write zero elements!
273 * if (plus,minus) is (+,-) then a positive version will be written.
274 * if (plus,minus) is (-,+) then a negative version will be written.
277 ODE_PURE_INLINE
void dSetCrossMatrixPlus(dReal
*res
, const dReal
*a
, unsigned skip
)
279 const dReal a_0
= a
[0], a_1
= a
[1], a_2
= a
[2];
284 res
[2*skip
+0] = -a_1
;
285 res
[2*skip
+1] = +a_0
;
288 ODE_PURE_INLINE
void dSetCrossMatrixMinus(dReal
*res
, const dReal
*a
, unsigned skip
)
290 const dReal a_0
= a
[0], a_1
= a
[1], a_2
= a
[2];
295 res
[2*skip
+0] = +a_1
;
296 res
[2*skip
+1] = -a_0
;
301 * compute the distance between two 3D-vectors
304 ODE_PURE_INLINE dReal
dCalcPointsDistance3(const dReal
*a
, const dReal
*b
)
308 dSubtractVectors3(tmp
, a
, b
);
309 res
= dCalcVectorLength3(tmp
);
314 * special case matrix multiplication, with operator selection
317 ODE_PURE_INLINE
void _dMultiplyHelper0_331(dReal
*res
, const dReal
*a
, const dReal
*b
)
319 const dReal res_0
= dCalcVectorDot3(a
, b
);
320 const dReal res_1
= dCalcVectorDot3(a
+ 4, b
);
321 const dReal res_2
= dCalcVectorDot3(a
+ 8, b
);
322 /* Only assign after all the calculations are over to avoid incurring memory aliasing*/
323 res
[0] = res_0
; res
[1] = res_1
; res
[2] = res_2
;
326 ODE_PURE_INLINE
void _dMultiplyHelper1_331(dReal
*res
, const dReal
*a
, const dReal
*b
)
328 const dReal res_0
= dCalcVectorDot3_41(a
, b
);
329 const dReal res_1
= dCalcVectorDot3_41(a
+ 1, b
);
330 const dReal res_2
= dCalcVectorDot3_41(a
+ 2, b
);
331 /* Only assign after all the calculations are over to avoid incurring memory aliasing*/
332 res
[0] = res_0
; res
[1] = res_1
; res
[2] = res_2
;
335 ODE_PURE_INLINE
void _dMultiplyHelper0_133(dReal
*res
, const dReal
*a
, const dReal
*b
)
337 _dMultiplyHelper1_331(res
, b
, a
);
340 ODE_PURE_INLINE
void _dMultiplyHelper1_133(dReal
*res
, const dReal
*a
, const dReal
*b
)
342 const dReal res_0
= dCalcVectorDot3_44(a
, b
);
343 const dReal res_1
= dCalcVectorDot3_44(a
+ 1, b
);
344 const dReal res_2
= dCalcVectorDot3_44(a
+ 2, b
);
345 /* Only assign after all the calculations are over to avoid incurring memory aliasing*/
346 res
[0] = res_0
; res
[1] = res_1
; res
[2] = res_2
;
350 Note: NEVER call any of these functions/macros with the same variable for A and C,
351 it is not equivalent to A*=B.
354 ODE_PURE_INLINE
void dMultiply0_331(dReal
*res
, const dReal
*a
, const dReal
*b
)
356 _dMultiplyHelper0_331(res
, a
, b
);
359 ODE_PURE_INLINE
void dMultiply1_331(dReal
*res
, const dReal
*a
, const dReal
*b
)
361 _dMultiplyHelper1_331(res
, a
, b
);
364 ODE_PURE_INLINE
void dMultiply0_133(dReal
*res
, const dReal
*a
, const dReal
*b
)
366 _dMultiplyHelper0_133(res
, a
, b
);
369 ODE_PURE_INLINE
void dMultiply0_333(dReal
*res
, const dReal
*a
, const dReal
*b
)
371 _dMultiplyHelper0_133(res
+ 0, a
+ 0, b
);
372 _dMultiplyHelper0_133(res
+ 4, a
+ 4, b
);
373 _dMultiplyHelper0_133(res
+ 8, a
+ 8, b
);
376 ODE_PURE_INLINE
void dMultiply1_333(dReal
*res
, const dReal
*a
, const dReal
*b
)
378 _dMultiplyHelper1_133(res
+ 0, b
, a
+ 0);
379 _dMultiplyHelper1_133(res
+ 4, b
, a
+ 1);
380 _dMultiplyHelper1_133(res
+ 8, b
, a
+ 2);
383 ODE_PURE_INLINE
void dMultiply2_333(dReal
*res
, const dReal
*a
, const dReal
*b
)
385 _dMultiplyHelper0_331(res
+ 0, b
, a
+ 0);
386 _dMultiplyHelper0_331(res
+ 4, b
, a
+ 4);
387 _dMultiplyHelper0_331(res
+ 8, b
, a
+ 8);
390 ODE_PURE_INLINE
void dMultiplyAdd0_331(dReal
*res
, const dReal
*a
, const dReal
*b
)
393 _dMultiplyHelper0_331(tmp
, a
, b
);
394 dAddVectors3(res
, res
, tmp
);
397 ODE_PURE_INLINE
void dMultiplyAdd1_331(dReal
*res
, const dReal
*a
, const dReal
*b
)
400 _dMultiplyHelper1_331(tmp
, a
, b
);
401 dAddVectors3(res
, res
, tmp
);
404 ODE_PURE_INLINE
void dMultiplyAdd0_133(dReal
*res
, const dReal
*a
, const dReal
*b
)
407 _dMultiplyHelper0_133(tmp
, a
, b
);
408 dAddVectors3(res
, res
, tmp
);
411 ODE_PURE_INLINE
void dMultiplyAdd0_333(dReal
*res
, const dReal
*a
, const dReal
*b
)
414 _dMultiplyHelper0_133(tmp
, a
+ 0, b
);
415 dAddVectors3(res
+ 0, res
+ 0, tmp
);
416 _dMultiplyHelper0_133(tmp
, a
+ 4, b
);
417 dAddVectors3(res
+ 4, res
+ 4, tmp
);
418 _dMultiplyHelper0_133(tmp
, a
+ 8, b
);
419 dAddVectors3(res
+ 8, res
+ 8, tmp
);
422 ODE_PURE_INLINE
void dMultiplyAdd1_333(dReal
*res
, const dReal
*a
, const dReal
*b
)
425 _dMultiplyHelper1_133(tmp
, b
, a
+ 0);
426 dAddVectors3(res
+ 0, res
+ 0, tmp
);
427 _dMultiplyHelper1_133(tmp
, b
, a
+ 1);
428 dAddVectors3(res
+ 4, res
+ 4, tmp
);
429 _dMultiplyHelper1_133(tmp
, b
, a
+ 2);
430 dAddVectors3(res
+ 8, res
+ 8, tmp
);
433 ODE_PURE_INLINE
void dMultiplyAdd2_333(dReal
*res
, const dReal
*a
, const dReal
*b
)
436 _dMultiplyHelper0_331(tmp
, b
, a
+ 0);
437 dAddVectors3(res
+ 0, res
+ 0, tmp
);
438 _dMultiplyHelper0_331(tmp
, b
, a
+ 4);
439 dAddVectors3(res
+ 4, res
+ 4, tmp
);
440 _dMultiplyHelper0_331(tmp
, b
, a
+ 8);
441 dAddVectors3(res
+ 8, res
+ 8, tmp
);
444 ODE_PURE_INLINE dReal
dCalcMatrix3Det( const dReal
* mat
)
448 det
= mat
[0] * ( mat
[5]*mat
[10] - mat
[9]*mat
[6] )
449 - mat
[1] * ( mat
[4]*mat
[10] - mat
[8]*mat
[6] )
450 + mat
[2] * ( mat
[4]*mat
[9] - mat
[8]*mat
[5] );
456 Closed form matrix inversion, copied from
457 collision_util.h for use in the stepper.
459 Returns the determinant.
460 returns 0 and does nothing
461 if the matrix is singular.
463 ODE_PURE_INLINE dReal
dInvertMatrix3(dReal
*dst
, const dReal
*ma
)
468 det
= dCalcMatrix3Det( ma
);
471 /* Setting an arbitrary non-zero threshold
472 for the determinant doesn't do anyone
473 any favors. The condition number is the
474 important thing. If all the eigen-values
475 of the matrix are small, so is the
476 determinant, but it can still be well
478 A single extremely large eigen-value could
479 push the determinant over threshold, but
480 produce a very unstable result if the other
481 eigen-values are small. So we just say that
482 the determinant must be non-zero and trust the
483 caller to provide well-conditioned matrices.
490 detRecip
= dRecip(det
);
492 dst
[0] = ( ma
[5]*ma
[10] - ma
[6]*ma
[9] ) * detRecip
;
493 dst
[1] = ( ma
[9]*ma
[2] - ma
[1]*ma
[10] ) * detRecip
;
494 dst
[2] = ( ma
[1]*ma
[6] - ma
[5]*ma
[2] ) * detRecip
;
496 dst
[4] = ( ma
[6]*ma
[8] - ma
[4]*ma
[10] ) * detRecip
;
497 dst
[5] = ( ma
[0]*ma
[10] - ma
[8]*ma
[2] ) * detRecip
;
498 dst
[6] = ( ma
[4]*ma
[2] - ma
[0]*ma
[6] ) * detRecip
;
500 dst
[8] = ( ma
[4]*ma
[9] - ma
[8]*ma
[5] ) * detRecip
;
501 dst
[9] = ( ma
[8]*ma
[1] - ma
[0]*ma
[9] ) * detRecip
;
502 dst
[10] = ( ma
[0]*ma
[5] - ma
[1]*ma
[4] ) * detRecip
;
508 /* Include legacy macros here */
509 #include <ode/odemath_legacy.h>
517 * normalize 3x1 and 4x1 vectors (i.e. scale them to unit length)
521 ODE_API
int dSafeNormalize3 (dVector3 a
);
522 ODE_API
int dSafeNormalize4 (dVector4 a
);
523 ODE_API
void dNormalize3 (dVector3 a
); /* Potentially asserts on zero vec*/
524 ODE_API
void dNormalize4 (dVector4 a
); /* Potentially asserts on zero vec*/
527 * given a unit length "normal" vector n, generate vectors p and q vectors
528 * that are an orthonormal basis for the plane space perpendicular to n.
529 * i.e. this makes p,q such that n,p,q are all perpendicular to each other.
530 * q will equal n x p. if n is not unit length then p will be unit length but
534 ODE_API
void dPlaneSpace (const dVector3 n
, dVector3 p
, dVector3 q
);
535 /* Makes sure the matrix is a proper rotation, returns a boolean status */
536 ODE_API
int dOrthogonalizeR(dMatrix3 m
);