- Main Page
- Modules
- Data Structures
- Files

# odemath.h

    00001 /*************************************************************************
    00002  *                                                                       *
    00003  * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
    00004  * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
    00005  *                                                                       *
    00006  * This library is free software; you can redistribute it and/or         *
    00007  * modify it under the terms of EITHER:                                  *
    00008  *   (1) The GNU Lesser General Public License as published by the Free  *
    00009  *       Software Foundation; either version 2.1 of the License, or (at  *
    00010  *       your option) any later version. The text of the GNU Lesser      *
    00011  *       General Public License is included with this library in the     *
    00012  *       file LICENSE.TXT.                                               *
    00013  *   (2) The BSD-style license that is included with this library in     *
    00014  *       the file LICENSE-BSD.TXT.                                       *
    00015  *                                                                       *
    00016  * This library is distributed in the hope that it will be useful,       *
    00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
    00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
    00019  * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
    00020  *                                                                       *
    00021  *************************************************************************/
    00022
    00023 #ifndef _ODE_ODEMATH_H_
    00024 #define _ODE_ODEMATH_H_
    00025
    00026 #include <ode/common.h>
    00027
    00028 #ifdef __GNUC__
    00029 #define PURE_INLINE extern inline
    00030 #else
    00031 #define PURE_INLINE inline
    00032 #endif
    00033
    00034 /*
    00035  * macro to access elements i,j in an NxM matrix A, independent of the
    00036  * matrix storage convention.
    00037  */
    00038 #define dACCESS33(A,i,j) ((A)[(i)*4+(j)])
    00039
    00040 /*
    00041  * Macro to test for valid floating point values
    00042  */
    00043 #define dVALIDVEC3(v) (!(dIsNan(v[0]) | dIsNan(v[1]) | dIsNan(v[2])))
    00044 #define dVALIDVEC4(v) (!(dIsNan(v[0]) | dIsNan(v[2]) | dIsNan(v[2]) | dIsNan(v[3])))
    00045 #define dVALIDMAT(m) (!(dIsNan(m[0]) | dIsNan(m[2]) | 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])))
    00046
    00047
    00048 /*
    00049  * 3-way dot product. dDOTpq means that elements of `a' and `b' are spaced
    00050  * p and q indexes apart respectively. dDOT() means dDOT11.
    00051  * in C++ we could use function templates to get all the versions of these
    00052  * functions - but on some compilers this will result in sub-optimal code.
    00053  */
    00054
    00055 #define dDOTpq(a,b,p,q) ((a)[0]*(b)[0] + (a)[p]*(b)[q] + (a)[2*(p)]*(b)[2*(q)])
    00056
    00057 #ifdef __cplusplus
    00058
    00059 PURE_INLINE dReal dDOT   (const dReal *a, const dReal *b) { return dDOTpq(a,b,1,1); }
    00060 PURE_INLINE dReal dDOT13 (const dReal *a, const dReal *b) { return dDOTpq(a,b,1,3); }
    00061 PURE_INLINE dReal dDOT31 (const dReal *a, const dReal *b) { return dDOTpq(a,b,3,1); }
    00062 PURE_INLINE dReal dDOT33 (const dReal *a, const dReal *b) { return dDOTpq(a,b,3,3); }
    00063 PURE_INLINE dReal dDOT14 (const dReal *a, const dReal *b) { return dDOTpq(a,b,1,4); }
    00064 PURE_INLINE dReal dDOT41 (const dReal *a, const dReal *b) { return dDOTpq(a,b,4,1); }
    00065 PURE_INLINE dReal dDOT44 (const dReal *a, const dReal *b) { return dDOTpq(a,b,4,4); }
    00066
    00067 #else
    00068
    00069 #define dDOT(a,b)   dDOTpq(a,b,1,1)
    00070 #define dDOT13(a,b) dDOTpq(a,b,1,3)
    00071 #define dDOT31(a,b) dDOTpq(a,b,3,1)
    00072 #define dDOT33(a,b) dDOTpq(a,b,3,3)
    00073 #define dDOT14(a,b) dDOTpq(a,b,1,4)
    00074 #define dDOT41(a,b) dDOTpq(a,b,4,1)
    00075 #define dDOT44(a,b) dDOTpq(a,b,4,4)
    00076
    00077 #endif /* __cplusplus */
    00078
    00079
    00080 /*
    00081  * cross product, set a = b x c. dCROSSpqr means that elements of `a', `b'
    00082  * and `c' are spaced p, q and r indexes apart respectively.
    00083  * dCROSS() means dCROSS111. `op' is normally `=', but you can set it to
    00084  * +=, -= etc to get other effects.
    00085  */
    00086
    00087 #define dCROSS(a,op,b,c) \
    00088 do { \
    00089   (a)[0] op ((b)[1]*(c)[2] - (b)[2]*(c)[1]); \
    00090   (a)[1] op ((b)[2]*(c)[0] - (b)[0]*(c)[2]); \
    00091   (a)[2] op ((b)[0]*(c)[1] - (b)[1]*(c)[0]); \
    00092 } while(0)
    00093 #define dCROSSpqr(a,op,b,c,p,q,r) \
    00094 do { \
    00095   (a)[  0] op ((b)[  q]*(c)[2*r] - (b)[2*q]*(c)[  r]); \
    00096   (a)[  p] op ((b)[2*q]*(c)[  0] - (b)[  0]*(c)[2*r]); \
    00097   (a)[2*p] op ((b)[  0]*(c)[  r] - (b)[  q]*(c)[  0]); \
    00098 } while(0)
    00099 #define dCROSS114(a,op,b,c) dCROSSpqr(a,op,b,c,1,1,4)
    00100 #define dCROSS141(a,op,b,c) dCROSSpqr(a,op,b,c,1,4,1)
    00101 #define dCROSS144(a,op,b,c) dCROSSpqr(a,op,b,c,1,4,4)
    00102 #define dCROSS411(a,op,b,c) dCROSSpqr(a,op,b,c,4,1,1)
    00103 #define dCROSS414(a,op,b,c) dCROSSpqr(a,op,b,c,4,1,4)
    00104 #define dCROSS441(a,op,b,c) dCROSSpqr(a,op,b,c,4,4,1)
    00105 #define dCROSS444(a,op,b,c) dCROSSpqr(a,op,b,c,4,4,4)
    00106
    00107
    00108 /*
    00109  * set a 3x3 submatrix of A to a matrix such that submatrix(A)*b = a x b.
    00110  * A is stored by rows, and has `skip' elements per row. the matrix is
    00111  * assumed to be already zero, so this does not write zero elements!
    00112  * if (plus,minus) is (+,-) then a positive version will be written.
    00113  * if (plus,minus) is (-,+) then a negative version will be written.
    00114  */
    00115
    00116 #define dCROSSMAT(A,a,skip,plus,minus) \
    00117 do { \
    00118   (A)[1] = minus (a)[2]; \
    00119   (A)[2] = plus (a)[1]; \
    00120   (A)[(skip)+0] = plus (a)[2]; \
    00121   (A)[(skip)+2] = minus (a)[0]; \
    00122   (A)[2*(skip)+0] = minus (a)[1]; \
    00123   (A)[2*(skip)+1] = plus (a)[0]; \
    00124 } while(0)
    00125
    00126
    00127 /*
    00128  * compute the distance between two 3D-vectors
    00129  */
    00130
    00131 #ifdef __cplusplus
    00132 PURE_INLINE dReal dDISTANCE (const dVector3 a, const dVector3 b)
    00133    { return dSqrt( (a[0]-b[0])*(a[0]-b[0]) + (a[1]-b[1])*(a[1]-b[1]) + (a[2]-b[2])*(a[2]-b[2]) ); }
    00134 #else
    00135 #define dDISTANCE(a,b) \
    00136    (dSqrt( ((a)[0]-(b)[0])*((a)[0]-(b)[0]) + ((a)[1]-(b)[1])*((a)[1]-(b)[1]) + ((a)[2]-(b)[2])*((a)[2]-(b)[2]) ))
    00137 #endif
    00138
    00139
    00140 /*
    00141  * special case matrix multipication, with operator selection
    00142  */
    00143
    00144 #define dMULTIPLYOP0_331(A,op,B,C) \
    00145 do { \
    00146   (A)[0] op dDOT((B),(C)); \
    00147   (A)[1] op dDOT((B+4),(C)); \
    00148   (A)[2] op dDOT((B+8),(C)); \
    00149 } while(0)
    00150 #define dMULTIPLYOP1_331(A,op,B,C) \
    00151 do { \
    00152   (A)[0] op dDOT41((B),(C)); \
    00153   (A)[1] op dDOT41((B+1),(C)); \
    00154   (A)[2] op dDOT41((B+2),(C)); \
    00155 } while(0)
    00156 #define dMULTIPLYOP0_133(A,op,B,C) \
    00157 do { \
    00158   (A)[0] op dDOT14((B),(C)); \
    00159   (A)[1] op dDOT14((B),(C+1)); \
    00160   (A)[2] op dDOT14((B),(C+2)); \
    00161 } while(0)
    00162 #define dMULTIPLYOP0_333(A,op,B,C) \
    00163 do { \
    00164   (A)[0] op dDOT14((B),(C)); \
    00165   (A)[1] op dDOT14((B),(C+1)); \
    00166   (A)[2] op dDOT14((B),(C+2)); \
    00167   (A)[4] op dDOT14((B+4),(C)); \
    00168   (A)[5] op dDOT14((B+4),(C+1)); \
    00169   (A)[6] op dDOT14((B+4),(C+2)); \
    00170   (A)[8] op dDOT14((B+8),(C)); \
    00171   (A)[9] op dDOT14((B+8),(C+1)); \
    00172   (A)[10] op dDOT14((B+8),(C+2)); \
    00173 } while(0)
    00174 #define dMULTIPLYOP1_333(A,op,B,C) \
    00175 do { \
    00176   (A)[0] op dDOT44((B),(C)); \
    00177   (A)[1] op dDOT44((B),(C+1)); \
    00178   (A)[2] op dDOT44((B),(C+2)); \
    00179   (A)[4] op dDOT44((B+1),(C)); \
    00180   (A)[5] op dDOT44((B+1),(C+1)); \
    00181   (A)[6] op dDOT44((B+1),(C+2)); \
    00182   (A)[8] op dDOT44((B+2),(C)); \
    00183   (A)[9] op dDOT44((B+2),(C+1)); \
    00184   (A)[10] op dDOT44((B+2),(C+2)); \
    00185 } while(0)
    00186 #define dMULTIPLYOP2_333(A,op,B,C) \
    00187 do { \
    00188   (A)[0] op dDOT((B),(C)); \
    00189   (A)[1] op dDOT((B),(C+4)); \
    00190   (A)[2] op dDOT((B),(C+8)); \
    00191   (A)[4] op dDOT((B+4),(C)); \
    00192   (A)[5] op dDOT((B+4),(C+4)); \
    00193   (A)[6] op dDOT((B+4),(C+8)); \
    00194   (A)[8] op dDOT((B+8),(C)); \
    00195   (A)[9] op dDOT((B+8),(C+4)); \
    00196   (A)[10] op dDOT((B+8),(C+8)); \
    00197 } while(0)
    00198
    00199 #ifdef __cplusplus
    00200
    00201 #define DECL template <class TA, class TB, class TC> PURE_INLINE void
    00202
    00203 DECL dMULTIPLY0_331(TA *A, const TB *B, const TC *C) { dMULTIPLYOP0_331(A,=,B,C); }
    00204 DECL dMULTIPLY1_331(TA *A, const TB *B, const TC *C) { dMULTIPLYOP1_331(A,=,B,C); }
    00205 DECL dMULTIPLY0_133(TA *A, const TB *B, const TC *C) { dMULTIPLYOP0_133(A,=,B,C); }
    00206 DECL dMULTIPLY0_333(TA *A, const TB *B, const TC *C) { dMULTIPLYOP0_333(A,=,B,C); }
    00207 DECL dMULTIPLY1_333(TA *A, const TB *B, const TC *C) { dMULTIPLYOP1_333(A,=,B,C); }
    00208 DECL dMULTIPLY2_333(TA *A, const TB *B, const TC *C) { dMULTIPLYOP2_333(A,=,B,C); }
    00209
    00210 DECL dMULTIPLYADD0_331(TA *A, const TB *B, const TC *C) { dMULTIPLYOP0_331(A,+=,B,C); }
    00211 DECL dMULTIPLYADD1_331(TA *A, const TB *B, const TC *C) { dMULTIPLYOP1_331(A,+=,B,C); }
    00212 DECL dMULTIPLYADD0_133(TA *A, const TB *B, const TC *C) { dMULTIPLYOP0_133(A,+=,B,C); }
    00213 DECL dMULTIPLYADD0_333(TA *A, const TB *B, const TC *C) { dMULTIPLYOP0_333(A,+=,B,C); }
    00214 DECL dMULTIPLYADD1_333(TA *A, const TB *B, const TC *C) { dMULTIPLYOP1_333(A,+=,B,C); }
    00215 DECL dMULTIPLYADD2_333(TA *A, const TB *B, const TC *C) { dMULTIPLYOP2_333(A,+=,B,C); }
    00216
    00217 #undef DECL
    00218
    00219 #else
    00220
    00221 #define dMULTIPLY0_331(A,B,C) dMULTIPLYOP0_331(A,=,B,C)
    00222 #define dMULTIPLY1_331(A,B,C) dMULTIPLYOP1_331(A,=,B,C)
    00223 #define dMULTIPLY0_133(A,B,C) dMULTIPLYOP0_133(A,=,B,C)
    00224 #define dMULTIPLY0_333(A,B,C) dMULTIPLYOP0_333(A,=,B,C)
    00225 #define dMULTIPLY1_333(A,B,C) dMULTIPLYOP1_333(A,=,B,C)
    00226 #define dMULTIPLY2_333(A,B,C) dMULTIPLYOP2_333(A,=,B,C)
    00227
    00228 #define dMULTIPLYADD0_331(A,B,C) dMULTIPLYOP0_331(A,+=,B,C)
    00229 #define dMULTIPLYADD1_331(A,B,C) dMULTIPLYOP1_331(A,+=,B,C)
    00230 #define dMULTIPLYADD0_133(A,B,C) dMULTIPLYOP0_133(A,+=,B,C)
    00231 #define dMULTIPLYADD0_333(A,B,C) dMULTIPLYOP0_333(A,+=,B,C)
    00232 #define dMULTIPLYADD1_333(A,B,C) dMULTIPLYOP1_333(A,+=,B,C)
    00233 #define dMULTIPLYADD2_333(A,B,C) dMULTIPLYOP2_333(A,+=,B,C)
    00234
    00235 #endif
    00236
    00237
    00238 #ifdef __cplusplus
    00239 extern "C" {
    00240 #endif
    00241
    00242 /*
    00243  * normalize 3x1 and 4x1 vectors (i.e. scale them to unit length)
    00244  */
    00245 ODE_API void dNormalize3 (dVector3 a);
    00246 ODE_API void dNormalize4 (dVector4 a);
    00247
    00248
    00249 /*
    00250  * given a unit length "normal" vector n, generate vectors p and q vectors
    00251  * that are an orthonormal basis for the plane space perpendicular to n.
    00252  * i.e. this makes p,q such that n,p,q are all perpendicular to each other.
    00253  * q will equal n x p. if n is not unit length then p will be unit length but
    00254  * q wont be.
    00255  */
    00256
    00257 ODE_API void dPlaneSpace (const dVector3 n, dVector3 p, dVector3 q);
    00258
    00259 #ifdef __cplusplus
    00260 }
    00261 #endif
    00262
    00263 #endif