|
1 /************************************************************************* |
|
2 * * |
|
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * |
|
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org * |
|
5 * * |
|
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 * |
|
12 * file LICENSE.TXT. * |
|
13 * (2) The BSD-style license that is included with this library in * |
|
14 * the file LICENSE-BSD.TXT. * |
|
15 * * |
|
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. * |
|
20 * * |
|
21 *************************************************************************/ |
|
22 |
|
23 #ifndef _ODE_ODEMATH_H_ |
|
24 #define _ODE_ODEMATH_H_ |
|
25 |
|
26 #include <ode/common.h> |
|
27 |
|
28 #ifdef __GNUC__ |
|
29 #define PURE_INLINE extern inline |
|
30 #else |
|
31 #define PURE_INLINE inline |
|
32 #endif |
|
33 |
|
34 /* |
|
35 * macro to access elements i,j in an NxM matrix A, independent of the |
|
36 * matrix storage convention. |
|
37 */ |
|
38 #define dACCESS33(A,i,j) ((A)[(i)*4+(j)]) |
|
39 |
|
40 /* |
|
41 * Macro to test for valid floating point values |
|
42 */ |
|
43 #define dVALIDVEC3(v) (!(dIsNan(v[0]) || dIsNan(v[1]) || dIsNan(v[2]))) |
|
44 #define dVALIDVEC4(v) (!(dIsNan(v[0]) || dIsNan(v[1]) || dIsNan(v[2]) || dIsNan(v[3]))) |
|
45 #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]))) |
|
46 #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]) )) |
|
47 |
|
48 |
|
49 |
|
50 /* |
|
51 * General purpose vector operations with other vectors or constants. |
|
52 */ |
|
53 |
|
54 #define dOP(a,op,b,c) \ |
|
55 (a)[0] = ((b)[0]) op ((c)[0]); \ |
|
56 (a)[1] = ((b)[1]) op ((c)[1]); \ |
|
57 (a)[2] = ((b)[2]) op ((c)[2]); |
|
58 #define dOPC(a,op,b,c) \ |
|
59 (a)[0] = ((b)[0]) op (c); \ |
|
60 (a)[1] = ((b)[1]) op (c); \ |
|
61 (a)[2] = ((b)[2]) op (c); |
|
62 #define dOPE(a,op,b) \ |
|
63 (a)[0] op ((b)[0]); \ |
|
64 (a)[1] op ((b)[1]); \ |
|
65 (a)[2] op ((b)[2]); |
|
66 #define dOPEC(a,op,c) \ |
|
67 (a)[0] op (c); \ |
|
68 (a)[1] op (c); \ |
|
69 (a)[2] op (c); |
|
70 |
|
71 |
|
72 |
|
73 |
|
74 |
|
75 /* |
|
76 * 3-way dot product. dDOTpq means that elements of `a' and `b' are spaced |
|
77 * p and q indexes apart respectively. dDOT() means dDOT11. |
|
78 * in C++ we could use function templates to get all the versions of these |
|
79 * functions - but on some compilers this will result in sub-optimal code. |
|
80 */ |
|
81 |
|
82 #define dDOTpq(a,b,p,q) (dMUL((a)[0],(b)[0]) + dMUL((a)[p],(b)[q]) + dMUL((a)[2*(p)],(b)[2*(q)])) |
|
83 |
|
84 |
|
85 #ifdef __cplusplus |
|
86 |
|
87 PURE_INLINE dReal dDOT (const dReal *a, const dReal *b) { return dDOTpq(a,b,1,1); } |
|
88 PURE_INLINE dReal dDOT13 (const dReal *a, const dReal *b) { return dDOTpq(a,b,1,3); } |
|
89 PURE_INLINE dReal dDOT31 (const dReal *a, const dReal *b) { return dDOTpq(a,b,3,1); } |
|
90 PURE_INLINE dReal dDOT33 (const dReal *a, const dReal *b) { return dDOTpq(a,b,3,3); } |
|
91 PURE_INLINE dReal dDOT14 (const dReal *a, const dReal *b) { return dDOTpq(a,b,1,4); } |
|
92 PURE_INLINE dReal dDOT41 (const dReal *a, const dReal *b) { return dDOTpq(a,b,4,1); } |
|
93 PURE_INLINE dReal dDOT44 (const dReal *a, const dReal *b) { return dDOTpq(a,b,4,4); } |
|
94 |
|
95 #endif /* __cplusplus */ |
|
96 |
|
97 |
|
98 /* |
|
99 * cross product, set a = b x c. dCROSSpqr means that elements of `a', `b' |
|
100 * and `c' are spaced p, q and r indexes apart respectively. |
|
101 * dCROSS() means dCROSS111. `op' is normally `=', but you can set it to |
|
102 * +=, -= etc to get other effects. |
|
103 */ |
|
104 |
|
105 #define dCROSS(a,op,b,c) \ |
|
106 do { \ |
|
107 (a)[0] op (dMUL((b)[1],(c)[2]) - dMUL((b)[2],(c)[1])); \ |
|
108 (a)[1] op (dMUL((b)[2],(c)[0]) - dMUL((b)[0],(c)[2])); \ |
|
109 (a)[2] op (dMUL((b)[0],(c)[1]) - dMUL((b)[1],(c)[0])); \ |
|
110 } while(0) |
|
111 |
|
112 #define dCROSSpqr(a,op,b,c,p,q,r) \ |
|
113 do { \ |
|
114 (a)[ 0] op (dMUL((b)[ q],(c)[2*r]) - dMUL((b)[2*q],(c)[ r])); \ |
|
115 (a)[ p] op (dMUL((b)[2*q],(c)[ 0]) - dMUL((b)[ 0],(c)[2*r])); \ |
|
116 (a)[2*p] op (dMUL((b)[ 0],(c)[ r]) - dMUL((b)[ q],(c)[ 0])); \ |
|
117 } while(0) |
|
118 #define dCROSS114(a,op,b,c) dCROSSpqr(a,op,b,c,1,1,4) |
|
119 #define dCROSS141(a,op,b,c) dCROSSpqr(a,op,b,c,1,4,1) |
|
120 #define dCROSS144(a,op,b,c) dCROSSpqr(a,op,b,c,1,4,4) |
|
121 #define dCROSS411(a,op,b,c) dCROSSpqr(a,op,b,c,4,1,1) |
|
122 #define dCROSS414(a,op,b,c) dCROSSpqr(a,op,b,c,4,1,4) |
|
123 #define dCROSS441(a,op,b,c) dCROSSpqr(a,op,b,c,4,4,1) |
|
124 #define dCROSS444(a,op,b,c) dCROSSpqr(a,op,b,c,4,4,4) |
|
125 |
|
126 |
|
127 /* |
|
128 * set a 3x3 submatrix of A to a matrix such that submatrix(A)*b = a x b. |
|
129 * A is stored by rows, and has `skip' elements per row. the matrix is |
|
130 * assumed to be already zero, so this does not write zero elements! |
|
131 * if (plus,minus) is (+,-) then a positive version will be written. |
|
132 * if (plus,minus) is (-,+) then a negative version will be written. |
|
133 */ |
|
134 |
|
135 #define dCROSSMAT(A,a,skip,plus,minus) \ |
|
136 do { \ |
|
137 (A)[1] = minus (a)[2]; \ |
|
138 (A)[2] = plus (a)[1]; \ |
|
139 (A)[(skip)+0] = plus (a)[2]; \ |
|
140 (A)[(skip)+2] = minus (a)[0]; \ |
|
141 (A)[2*(skip)+0] = minus (a)[1]; \ |
|
142 (A)[2*(skip)+1] = plus (a)[0]; \ |
|
143 } while(0) |
|
144 |
|
145 |
|
146 /* |
|
147 * compute the distance between two 3D-vectors |
|
148 */ |
|
149 |
|
150 #ifdef __cplusplus |
|
151 #define dDISTANCE(a,b) \ |
|
152 (dSqrt( dMUL(((a)[0]-(b)[0]),((a)[0]-(b)[0])) + dMUL(((a)[1]-(b)[1]),((a)[1]-(b)[1])) + dMUL(((a)[2]-(b)[2]),((a)[2]-(b)[2])) )) |
|
153 #endif |
|
154 |
|
155 |
|
156 /* |
|
157 * special case matrix multipication, with operator selection |
|
158 */ |
|
159 |
|
160 #define dMULTIPLYOP0_331(A,op,B,C) \ |
|
161 do { \ |
|
162 (A)[0] op dDOT((B),(C)); \ |
|
163 (A)[1] op dDOT((B+4),(C)); \ |
|
164 (A)[2] op dDOT((B+8),(C)); \ |
|
165 } while(0) |
|
166 #define dMULTIPLYOP1_331(A,op,B,C) \ |
|
167 do { \ |
|
168 (A)[0] op dDOT41((B),(C)); \ |
|
169 (A)[1] op dDOT41((B+1),(C)); \ |
|
170 (A)[2] op dDOT41((B+2),(C)); \ |
|
171 } while(0) |
|
172 #define dMULTIPLYOP0_133(A,op,B,C) \ |
|
173 do { \ |
|
174 (A)[0] op dDOT14((B),(C)); \ |
|
175 (A)[1] op dDOT14((B),(C+1)); \ |
|
176 (A)[2] op dDOT14((B),(C+2)); \ |
|
177 } while(0) |
|
178 #define dMULTIPLYOP0_333(A,op,B,C) \ |
|
179 do { \ |
|
180 (A)[0] op dDOT14((B),(C)); \ |
|
181 (A)[1] op dDOT14((B),(C+1)); \ |
|
182 (A)[2] op dDOT14((B),(C+2)); \ |
|
183 (A)[4] op dDOT14((B+4),(C)); \ |
|
184 (A)[5] op dDOT14((B+4),(C+1)); \ |
|
185 (A)[6] op dDOT14((B+4),(C+2)); \ |
|
186 (A)[8] op dDOT14((B+8),(C)); \ |
|
187 (A)[9] op dDOT14((B+8),(C+1)); \ |
|
188 (A)[10] op dDOT14((B+8),(C+2)); \ |
|
189 } while(0) |
|
190 #define dMULTIPLYOP1_333(A,op,B,C) \ |
|
191 do { \ |
|
192 (A)[0] op dDOT44((B),(C)); \ |
|
193 (A)[1] op dDOT44((B),(C+1)); \ |
|
194 (A)[2] op dDOT44((B),(C+2)); \ |
|
195 (A)[4] op dDOT44((B+1),(C)); \ |
|
196 (A)[5] op dDOT44((B+1),(C+1)); \ |
|
197 (A)[6] op dDOT44((B+1),(C+2)); \ |
|
198 (A)[8] op dDOT44((B+2),(C)); \ |
|
199 (A)[9] op dDOT44((B+2),(C+1)); \ |
|
200 (A)[10] op dDOT44((B+2),(C+2)); \ |
|
201 } while(0) |
|
202 #define dMULTIPLYOP2_333(A,op,B,C) \ |
|
203 do { \ |
|
204 (A)[0] op dDOT((B),(C)); \ |
|
205 (A)[1] op dDOT((B),(C+4)); \ |
|
206 (A)[2] op dDOT((B),(C+8)); \ |
|
207 (A)[4] op dDOT((B+4),(C)); \ |
|
208 (A)[5] op dDOT((B+4),(C+4)); \ |
|
209 (A)[6] op dDOT((B+4),(C+8)); \ |
|
210 (A)[8] op dDOT((B+8),(C)); \ |
|
211 (A)[9] op dDOT((B+8),(C+4)); \ |
|
212 (A)[10] op dDOT((B+8),(C+8)); \ |
|
213 } while(0) |
|
214 |
|
215 #ifdef __cplusplus |
|
216 |
|
217 #define DECL template <class TA, class TB, class TC> PURE_INLINE void |
|
218 |
|
219 DECL dMULTIPLY0_331(TA *A, const TB *B, const TC *C) { dMULTIPLYOP0_331(A,=,B,C); } |
|
220 DECL dMULTIPLY1_331(TA *A, const TB *B, const TC *C) { dMULTIPLYOP1_331(A,=,B,C); } |
|
221 DECL dMULTIPLY0_133(TA *A, const TB *B, const TC *C) { dMULTIPLYOP0_133(A,=,B,C); } |
|
222 DECL dMULTIPLY0_333(TA *A, const TB *B, const TC *C) { dMULTIPLYOP0_333(A,=,B,C); } |
|
223 DECL dMULTIPLY1_333(TA *A, const TB *B, const TC *C) { dMULTIPLYOP1_333(A,=,B,C); } |
|
224 DECL dMULTIPLY2_333(TA *A, const TB *B, const TC *C) { dMULTIPLYOP2_333(A,=,B,C); } |
|
225 |
|
226 DECL dMULTIPLYADD0_331(TA *A, const TB *B, const TC *C) { dMULTIPLYOP0_331(A,+=,B,C); } |
|
227 DECL dMULTIPLYADD1_331(TA *A, const TB *B, const TC *C) { dMULTIPLYOP1_331(A,+=,B,C); } |
|
228 DECL dMULTIPLYADD0_133(TA *A, const TB *B, const TC *C) { dMULTIPLYOP0_133(A,+=,B,C); } |
|
229 DECL dMULTIPLYADD0_333(TA *A, const TB *B, const TC *C) { dMULTIPLYOP0_333(A,+=,B,C); } |
|
230 DECL dMULTIPLYADD1_333(TA *A, const TB *B, const TC *C) { dMULTIPLYOP1_333(A,+=,B,C); } |
|
231 DECL dMULTIPLYADD2_333(TA *A, const TB *B, const TC *C) { dMULTIPLYOP2_333(A,+=,B,C); } |
|
232 |
|
233 #undef DECL |
|
234 |
|
235 #else |
|
236 |
|
237 #define dMULTIPLY0_331(A,B,C) dMULTIPLYOP0_331(A,=,B,C) |
|
238 #define dMULTIPLY1_331(A,B,C) dMULTIPLYOP1_331(A,=,B,C) |
|
239 #define dMULTIPLY0_133(A,B,C) dMULTIPLYOP0_133(A,=,B,C) |
|
240 #define dMULTIPLY0_333(A,B,C) dMULTIPLYOP0_333(A,=,B,C) |
|
241 #define dMULTIPLY1_333(A,B,C) dMULTIPLYOP1_333(A,=,B,C) |
|
242 #define dMULTIPLY2_333(A,B,C) dMULTIPLYOP2_333(A,=,B,C) |
|
243 |
|
244 #define dMULTIPLYADD0_331(A,B,C) dMULTIPLYOP0_331(A,+=,B,C) |
|
245 #define dMULTIPLYADD1_331(A,B,C) dMULTIPLYOP1_331(A,+=,B,C) |
|
246 #define dMULTIPLYADD0_133(A,B,C) dMULTIPLYOP0_133(A,+=,B,C) |
|
247 #define dMULTIPLYADD0_333(A,B,C) dMULTIPLYOP0_333(A,+=,B,C) |
|
248 #define dMULTIPLYADD1_333(A,B,C) dMULTIPLYOP1_333(A,+=,B,C) |
|
249 #define dMULTIPLYADD2_333(A,B,C) dMULTIPLYOP2_333(A,+=,B,C) |
|
250 |
|
251 #endif |
|
252 |
|
253 |
|
254 #ifdef __cplusplus |
|
255 extern "C" { |
|
256 #endif |
|
257 |
|
258 /* |
|
259 * normalize 3x1 and 4x1 vectors (i.e. scale them to unit length) |
|
260 */ |
|
261 ODE_API IMPORT_C void dNormalize3 (dVector3 a); |
|
262 ODE_API IMPORT_C void dNormalize4 (dVector4 a); |
|
263 |
|
264 |
|
265 /* |
|
266 * given a unit length "normal" vector n, generate vectors p and q vectors |
|
267 * that are an orthonormal basis for the plane space perpendicular to n. |
|
268 * i.e. this makes p,q such that n,p,q are all perpendicular to each other. |
|
269 * q will equal n x p. if n is not unit length then p will be unit length but |
|
270 * q wont be. |
|
271 */ |
|
272 |
|
273 ODE_API IMPORT_C void dPlaneSpace (const dVector3 n, dVector3 p, dVector3 q); |
|
274 |
|
275 ODE_API IMPORT_C dReal dArcTan2(const dReal x, const dReal y); |
|
276 ODE_API IMPORT_C dReal dArcSin(const dReal arg); |
|
277 |
|
278 #ifdef __cplusplus |
|
279 } |
|
280 #endif |
|
281 |
|
282 #endif |