Open Dynamics Engine

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