Open Dynamics Engine
|
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_COMMON_H_ 00024 #define _ODE_COMMON_H_ 00025 #include <ode/odeconfig.h> 00026 #include <ode/error.h> 00027 #include <math.h> 00028 00029 #ifdef __cplusplus 00030 extern "C" { 00031 #endif 00032 00033 00034 #define PURE_INLINE static __inline 00035 00036 00037 /* configuration stuff */ 00038 00039 /* constants */ 00040 00041 /* pi and 1/sqrt(2) are defined here if necessary because they don't get 00042 * defined in <math.h> on some platforms (like MS-Windows) 00043 */ 00044 00045 #ifndef M_PI 00046 #define M_PI REAL(3.1415926535897932384626433832795029) 00047 #endif 00048 #ifndef M_SQRT1_2 00049 #define M_SQRT1_2 REAL(0.7071067811865475244008443621048490) 00050 #endif 00051 00052 00053 /* debugging: 00054 * IASSERT is an internal assertion, i.e. a consistency check. if it fails 00055 * we want to know where. 00056 * UASSERT is a user assertion, i.e. if it fails a nice error message 00057 * should be printed for the user. 00058 * AASSERT is an arguments assertion, i.e. if it fails "bad argument(s)" 00059 * is printed. 00060 * DEBUGMSG just prints out a message 00061 */ 00062 00063 # if defined(__STDC__) && __STDC_VERSION__ >= 199901L 00064 # define __FUNCTION__ __func__ 00065 # endif 00066 #ifndef dNODEBUG 00067 # ifdef __GNUC__ 00068 # define dIASSERT(a) { if (!(a)) { dDebug (d_ERR_IASSERT, \ 00069 "assertion \"" #a "\" failed in %s() [%s:%u]",__FUNCTION__,__FILE__,__LINE__); } } 00070 # define dUASSERT(a,msg) { if (!(a)) { dDebug (d_ERR_UASSERT, \ 00071 msg " in %s()", __FUNCTION__); } } 00072 # define dDEBUGMSG(msg) { dMessage (d_ERR_UASSERT, \ 00073 msg " in %s() [%s:%u]", __FUNCTION__,__FILE__,__LINE__); } 00074 # else // not __GNUC__ 00075 # define dIASSERT(a) { if (!(a)) { dDebug (d_ERR_IASSERT, \ 00076 "assertion \"" #a "\" failed in %s:%u",__FILE__,__LINE__); } } 00077 # define dUASSERT(a,msg) { if (!(a)) { dDebug (d_ERR_UASSERT, \ 00078 msg " (%s:%u)", __FILE__,__LINE__); } } 00079 # define dDEBUGMSG(msg) { dMessage (d_ERR_UASSERT, \ 00080 msg " (%s:%u)", __FILE__,__LINE__); } 00081 # endif 00082 # define dIVERIFY(a) dIASSERT(a) 00083 #else 00084 # define dIASSERT(a) ((void)0) 00085 # define dUASSERT(a,msg) ((void)0) 00086 # define dDEBUGMSG(msg) ((void)0) 00087 # define dIVERIFY(a) ((void)(a)) 00088 #endif 00089 00090 # ifdef __GNUC__ 00091 # define dICHECK(a) { if (!(a)) { dDebug (d_ERR_IASSERT, \ 00092 "assertion \"" #a "\" failed in %s() [%s:%u]",__FUNCTION__,__FILE__,__LINE__); *(int *)0 = 0; } } 00093 # else // not __GNUC__ 00094 # define dICHECK(a) { if (!(a)) { dDebug (d_ERR_IASSERT, \ 00095 "assertion \"" #a "\" failed in %s:%u",__FILE__,__LINE__); *(int *)0 = 0; } } 00096 # endif 00097 00098 // Argument assert is a special case of user assert 00099 #define dAASSERT(a) dUASSERT(a,"Bad argument(s)") 00100 00101 /* floating point data type, vector, matrix and quaternion types */ 00102 00103 #if defined(dSINGLE) 00104 typedef float dReal; 00105 #ifdef dDOUBLE 00106 #error You can only #define dSINGLE or dDOUBLE, not both. 00107 #endif // dDOUBLE 00108 #elif defined(dDOUBLE) 00109 typedef double dReal; 00110 #else 00111 #error You must #define dSINGLE or dDOUBLE 00112 #endif 00113 00114 // Detect if we've got both trimesh engines enabled. 00115 #if dTRIMESH_ENABLED 00116 #if dTRIMESH_OPCODE && dTRIMESH_GIMPACT 00117 #error You can only #define dTRIMESH_OPCODE or dTRIMESH_GIMPACT, not both. 00118 #endif 00119 #endif // dTRIMESH_ENABLED 00120 00121 // Define a type for indices, either 16 or 32 bit, based on build option 00122 // TODO: Currently GIMPACT only supports 32 bit indices. 00123 #if dTRIMESH_16BIT_INDICES 00124 #if dTRIMESH_GIMPACT 00125 typedef uint32 dTriIndex; 00126 #else // dTRIMESH_GIMPACT 00127 typedef uint16 dTriIndex; 00128 #endif // dTRIMESH_GIMPACT 00129 #else // dTRIMESH_16BIT_INDICES 00130 typedef uint32 dTriIndex; 00131 #endif // dTRIMESH_16BIT_INDICES 00132 00133 /* round an integer up to a multiple of 4, except that 0 and 1 are unmodified 00134 * (used to compute matrix leading dimensions) 00135 */ 00136 #define dPAD(a) (((a) > 1) ? ((((a)-1)|3)+1) : (a)) 00137 00138 /* these types are mainly just used in headers */ 00139 typedef dReal dVector3[4]; 00140 typedef dReal dVector4[4]; 00141 typedef dReal dMatrix3[4*3]; 00142 typedef dReal dMatrix4[4*4]; 00143 typedef dReal dMatrix6[8*6]; 00144 typedef dReal dQuaternion[4]; 00145 00146 00147 /* precision dependent scalar math functions */ 00148 00149 #if defined(dSINGLE) 00150 00151 #define REAL(x) (x ## f) /* form a constant */ 00152 #define dRecip(x) ((1.0f/(x))) /* reciprocal */ 00153 #define dSqrt(x) (sqrtf(x)) /* square root */ 00154 #define dRecipSqrt(x) ((1.0f/sqrtf(x))) /* reciprocal square root */ 00155 #define dSin(x) (sinf(x)) /* sine */ 00156 #define dCos(x) (cosf(x)) /* cosine */ 00157 #define dFabs(x) (fabsf(x)) /* absolute value */ 00158 #define dAtan2(y,x) (atan2f(y,x)) /* arc tangent with 2 args */ 00159 #define dFMod(a,b) (fmodf(a,b)) /* modulo */ 00160 #define dFloor(x) floorf(x) /* floor */ 00161 #define dCeil(x) ceilf(x) /* floor */ 00162 #define dCopySign(a,b) ((dReal)copysignf(a,b)) /* copy value sign */ 00163 #define dNextAfter(x, y) nextafterf(x, y) /* next value after */ 00164 00165 #if defined(_ODE__NEXTAFTERF_REQUIRED) 00166 float _nextafterf(float x, float y); 00167 #endif 00168 00169 #ifdef HAVE___ISNANF 00170 #define dIsNan(x) (__isnanf(x)) 00171 #elif defined(HAVE__ISNANF) 00172 #define dIsNan(x) (_isnanf(x)) 00173 #elif defined(HAVE_ISNANF) 00174 #define dIsNan(x) (isnanf(x)) 00175 #else 00176 /* 00177 fall back to _isnan which is the VC way, 00178 this may seem redundant since we already checked 00179 for _isnan before, but if isnan is detected by 00180 configure but is not found during compilation 00181 we should always make sure we check for __isnanf, 00182 _isnanf and isnanf in that order before falling 00183 back to a default 00184 */ 00185 #define dIsNan(x) (_isnan(x)) 00186 #endif 00187 00188 #elif defined(dDOUBLE) 00189 00190 #define REAL(x) (x) 00191 #define dRecip(x) (1.0/(x)) 00192 #define dSqrt(x) sqrt(x) 00193 #define dRecipSqrt(x) (1.0/sqrt(x)) 00194 #define dSin(x) sin(x) 00195 #define dCos(x) cos(x) 00196 #define dFabs(x) fabs(x) 00197 #define dAtan2(y,x) atan2((y),(x)) 00198 #define dFMod(a,b) (fmod((a),(b))) 00199 #define dFloor(x) floor(x) 00200 #define dCeil(x) ceil(x) 00201 #define dCopySign(a,b) (copysign((a),(b))) 00202 #define dNextAfter(x, y) nextafter(x, y) 00203 00204 #undef _ODE__NEXTAFTERF_REQUIRED 00205 00206 #ifdef HAVE___ISNAN 00207 #define dIsNan(x) (__isnan(x)) 00208 #elif defined(HAVE__ISNAN) 00209 #define dIsNan(x) (_isnan(x)) 00210 #elif defined(HAVE_ISNAN) 00211 #define dIsNan(x) (isnan(x)) 00212 #else 00213 #define dIsNan(x) (_isnan(x)) 00214 #endif 00215 00216 #else 00217 #error You must #define dSINGLE or dDOUBLE 00218 #endif 00219 00220 /* internal object types (all prefixed with `dx') */ 00221 00222 struct dxWorld; /* dynamics world */ 00223 struct dxSpace; /* collision space */ 00224 struct dxBody; /* rigid body (dynamics object) */ 00225 struct dxGeom; /* geometry (collision object) */ 00226 struct dxJoint; 00227 struct dxJointNode; 00228 struct dxJointGroup; 00229 struct dxWorldProcessThreadingManager; 00230 00231 typedef struct dxWorld *dWorldID; 00232 typedef struct dxSpace *dSpaceID; 00233 typedef struct dxBody *dBodyID; 00234 typedef struct dxGeom *dGeomID; 00235 typedef struct dxJoint *dJointID; 00236 typedef struct dxJointGroup *dJointGroupID; 00237 typedef struct dxWorldProcessThreadingManager *dWorldStepThreadingManagerID; 00238 00239 /* error numbers */ 00240 00241 enum { 00242 d_ERR_UNKNOWN = 0, /* unknown error */ 00243 d_ERR_IASSERT, /* internal assertion failed */ 00244 d_ERR_UASSERT, /* user assertion failed */ 00245 d_ERR_LCP /* user assertion failed */ 00246 }; 00247 00248 00249 /* joint type numbers */ 00250 00251 typedef enum { 00252 dJointTypeNone = 0, /* or "unknown" */ 00253 dJointTypeBall, 00254 dJointTypeHinge, 00255 dJointTypeSlider, 00256 dJointTypeContact, 00257 dJointTypeUniversal, 00258 dJointTypeHinge2, 00259 dJointTypeFixed, 00260 dJointTypeNull, 00261 dJointTypeAMotor, 00262 dJointTypeLMotor, 00263 dJointTypePlane2D, 00264 dJointTypePR, 00265 dJointTypePU, 00266 dJointTypePiston 00267 } dJointType; 00268 00269 00270 /* an alternative way of setting joint parameters, using joint parameter 00271 * structures and member constants. we don't actually do this yet. 00272 */ 00273 00274 /* 00275 typedef struct dLimot { 00276 int mode; 00277 dReal lostop, histop; 00278 dReal vel, fmax; 00279 dReal fudge_factor; 00280 dReal bounce, soft; 00281 dReal suspension_erp, suspension_cfm; 00282 } dLimot; 00283 00284 enum { 00285 dLimotLoStop = 0x0001, 00286 dLimotHiStop = 0x0002, 00287 dLimotVel = 0x0004, 00288 dLimotFMax = 0x0008, 00289 dLimotFudgeFactor = 0x0010, 00290 dLimotBounce = 0x0020, 00291 dLimotSoft = 0x0040 00292 }; 00293 */ 00294 00295 00296 /* standard joint parameter names. why are these here? - because we don't want 00297 * to include all the joint function definitions in joint.cpp. hmmmm. 00298 * MSVC complains if we call D_ALL_PARAM_NAMES_X with a blank second argument, 00299 * which is why we have the D_ALL_PARAM_NAMES macro as well. please copy and 00300 * paste between these two. 00301 */ 00302 00303 #define D_ALL_PARAM_NAMES(start) \ 00304 /* parameters for limits and motors */ \ 00305 dParamLoStop = start, \ 00306 dParamHiStop, \ 00307 dParamVel, \ 00308 dParamFMax, \ 00309 dParamFudgeFactor, \ 00310 dParamBounce, \ 00311 dParamCFM, \ 00312 dParamStopERP, \ 00313 dParamStopCFM, \ 00314 /* parameters for suspension */ \ 00315 dParamSuspensionERP, \ 00316 dParamSuspensionCFM, \ 00317 dParamERP, \ 00318 00319 00320 00321 00322 00323 00324 00325 00326 00327 #define D_ALL_PARAM_NAMES_X(start,x) \ 00328 dParamGroup ## x = start, \ 00329 /* parameters for limits and motors */ \ 00330 dParamLoStop ## x = start, \ 00331 dParamHiStop ## x, \ 00332 dParamVel ## x, \ 00333 dParamFMax ## x, \ 00334 dParamFudgeFactor ## x, \ 00335 dParamBounce ## x, \ 00336 dParamCFM ## x, \ 00337 dParamStopERP ## x, \ 00338 dParamStopCFM ## x, \ 00339 /* parameters for suspension */ \ 00340 dParamSuspensionERP ## x, \ 00341 dParamSuspensionCFM ## x, \ 00342 dParamERP ## x, 00343 00344 enum { 00345 D_ALL_PARAM_NAMES(0) 00346 dParamsInGroup, 00347 D_ALL_PARAM_NAMES_X(0x000,1) 00348 D_ALL_PARAM_NAMES_X(0x100,2) 00349 D_ALL_PARAM_NAMES_X(0x200,3) 00350 00351 /* add a multiple of this constant to the basic parameter numbers to get 00352 * the parameters for the second, third etc axes. 00353 */ 00354 dParamGroup=0x100 00355 }; 00356 00357 00358 /* angular motor mode numbers */ 00359 00360 enum { 00361 dAMotorUser = 0, 00362 dAMotorEuler = 1 00363 }; 00364 00365 00366 /* joint force feedback information */ 00367 00368 typedef struct dJointFeedback { 00369 dVector3 f1; /* force applied to body 1 */ 00370 dVector3 t1; /* torque applied to body 1 */ 00371 dVector3 f2; /* force applied to body 2 */ 00372 dVector3 t2; /* torque applied to body 2 */ 00373 } dJointFeedback; 00374 00375 00376 /* private functions that must be implemented by the collision library: 00377 * (1) indicate that a geom has moved, (2) get the next geom in a body list. 00378 * these functions are called whenever the position of geoms connected to a 00379 * body have changed, e.g. with dBodySetPosition(), dBodySetRotation(), or 00380 * when the ODE step function updates the body state. 00381 */ 00382 00383 void dGeomMoved (dGeomID); 00384 dGeomID dGeomGetBodyNext (dGeomID); 00385 00404 ODE_API const char* dGetConfiguration (void); 00405 00414 ODE_API int dCheckConfiguration( const char* token ); 00415 00416 #ifdef __cplusplus 00417 } 00418 #endif 00419 00420 #endif