ode/src/ode.cpp
changeset 0 2f259fa3e83a
equal deleted inserted replaced
-1:000000000000 0:2f259fa3e83a
       
     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 // this source file is mostly concerned with the data structures, not the
       
    24 // numerics.
       
    25 
       
    26 #include <e32std.h>
       
    27 #include <pls.h>
       
    28 #include "object.h"
       
    29 #include <ode/ode.h>
       
    30 #include "joint.h"
       
    31 #include <ode/odemath.h>
       
    32 #include <ode/matrix.h>
       
    33 #include "step.h"
       
    34 #include "quickstep.h"
       
    35 #include "util.h"
       
    36 #include <ode/memory.h>
       
    37 #include <ode/error.h>
       
    38 
       
    39 #ifdef __WINSCW__
       
    40 
       
    41 TInt InitializeGlobaData( TOdeStaticData* aData )
       
    42     {
       
    43     Mem::FillZ( aData, sizeof( TOdeStaticData ) );
       
    44     aData->autoEnableDepth = 2;
       
    45     return KErrNone;
       
    46     }
       
    47     
       
    48 struct TOdeStaticData* GetGlobalData()
       
    49     {
       
    50     return Pls<TOdeStaticData>( TUid::Uid( 0x2001CBE3 ), InitializeGlobaData );
       
    51     }
       
    52 
       
    53 #else
       
    54 
       
    55 static struct TOdeStaticData odeStaticData;
       
    56 
       
    57 struct TOdeStaticData* GetGlobalData()
       
    58     {
       
    59     return &odeStaticData;
       
    60     }
       
    61 
       
    62 #endif // __WINSCW__
       
    63 
       
    64 // misc defines
       
    65 //#define ALLOCA dALLOCA16
       
    66 
       
    67 //****************************************************************************
       
    68 // utility
       
    69 
       
    70 static inline void initObject (dObject *obj, dxWorld *w)
       
    71 {
       
    72   obj->world = w;
       
    73   obj->next = 0;
       
    74   obj->tome = 0;
       
    75   obj->userdata = 0;
       
    76   obj->tag = 0;
       
    77 }
       
    78 
       
    79 
       
    80 // add an object `obj' to the list who's head pointer is pointed to by `first'.
       
    81 
       
    82 static inline void addObjectToList (dObject *obj, dObject **first)
       
    83 {
       
    84   obj->next = *first;
       
    85   obj->tome = first;
       
    86   if (*first) (*first)->tome = &obj->next;
       
    87   (*first) = obj;
       
    88 }
       
    89 
       
    90 
       
    91 // remove the object from the linked list
       
    92 
       
    93 static inline void removeObjectFromList (dObject *obj)
       
    94 {
       
    95   if (obj->next) obj->next->tome = obj->tome;
       
    96   *(obj->tome) = obj->next;
       
    97   // safeguard
       
    98   obj->next = 0;
       
    99   obj->tome = 0;
       
   100 }
       
   101 
       
   102 
       
   103 // remove the joint from neighbour lists of all connected bodies
       
   104 
       
   105 static void removeJointReferencesFromAttachedBodies (dxJoint *j)
       
   106 {
       
   107   for (int i=0; i<2; i++) {
       
   108     dxBody *body = j->node[i].body;
       
   109     if (body) {
       
   110       dxJointNode *n = body->firstjoint;
       
   111       dxJointNode *last = 0;
       
   112       while (n) {
       
   113 	if (n->joint == j) {
       
   114 	  if (last) last->next = n->next;
       
   115 	  else body->firstjoint = n->next;
       
   116 	  break;
       
   117 	}
       
   118 	last = n;
       
   119 	n = n->next;
       
   120       }
       
   121     }
       
   122   }
       
   123   j->node[0].body = 0;
       
   124   j->node[0].next = 0;
       
   125   j->node[1].body = 0;
       
   126   j->node[1].next = 0;
       
   127 }
       
   128 
       
   129 //****************************************************************************
       
   130 // debugging
       
   131 
       
   132 
       
   133 // check the validity of the world data structures
       
   134 
       
   135 static void checkWorld (dxWorld */*w*/)
       
   136 {
       
   137   //dxBody *b;
       
   138   //dxJoint *j;
       
   139 
       
   140  // TBD
       
   141 
       
   142 }
       
   143 
       
   144 
       
   145 void dWorldCheck (dxWorld *w)
       
   146 {
       
   147   checkWorld (w);
       
   148 }
       
   149 
       
   150 //****************************************************************************
       
   151 // body
       
   152 EXPORT_C dxWorld* dBodyGetWorld (dxBody* b)
       
   153 {
       
   154 
       
   155   return b->world;
       
   156 }
       
   157 
       
   158 EXPORT_C dxBody *dBodyCreate (dxWorld *w)
       
   159 {
       
   160 
       
   161   dxBody *b = new dxBody;
       
   162   initObject (b,w);
       
   163   b->firstjoint = 0;
       
   164   b->flags = 0;
       
   165   b->geom = 0;
       
   166   b->average_lvel_buffer = 0;
       
   167   b->average_avel_buffer = 0;
       
   168   dMassSetParameters (&b->mass,REAL(1.0),0,0,0,REAL(1.0),REAL(1.0),REAL(1.0),0,0,0);
       
   169   dSetZero (b->invI,4*3);
       
   170   b->invI[0] = REAL(1.0);
       
   171   b->invI[5] = REAL(1.0);
       
   172   b->invI[10] = REAL(1.0);
       
   173   b->invMass = REAL(1.0);
       
   174   dSetZero (b->posr.pos,4);
       
   175   dSetZero (b->q,4);
       
   176   b->q[0] = REAL(1.0);
       
   177   dRSetIdentity (b->posr.R);
       
   178   dSetZero (b->lvel,4);
       
   179   dSetZero (b->avel,4);
       
   180   dSetZero (b->facc,4);
       
   181   dSetZero (b->tacc,4);
       
   182   dSetZero (b->finite_rot_axis,4);
       
   183   addObjectToList (b,(dObject **) &w->firstbody);
       
   184   w->nb++;
       
   185 
       
   186   // set auto-disable parameters
       
   187   b->average_avel_buffer = b->average_lvel_buffer = 0; // no buffer at beginnin
       
   188   dBodySetAutoDisableDefaults (b);	// must do this after adding to world
       
   189   b->adis_stepsleft = b->adis.idle_steps;
       
   190   b->adis_timeleft = b->adis.idle_time;
       
   191   b->average_counter = 0;
       
   192   b->average_ready = 0; // average buffer not filled on the beginning
       
   193   dBodySetAutoDisableAverageSamplesCount(b, b->adis.average_samples);
       
   194 
       
   195   return b;
       
   196 }
       
   197 
       
   198 
       
   199 EXPORT_C void dBodyDestroy (dxBody *b)
       
   200 {
       
   201 
       
   202 
       
   203   // all geoms that link to this body must be notified that the body is about
       
   204   // to disappear. note that the call to dGeomSetBody(geom,0) will result in
       
   205   // dGeomGetBodyNext() returning 0 for the body, so we must get the next body
       
   206   // before setting the body to 0.
       
   207   dxGeom *next_geom = 0;
       
   208   for (dxGeom *geom = b->geom; geom; geom = next_geom) {
       
   209     next_geom = dGeomGetBodyNext (geom);
       
   210     dGeomSetBody (geom,0);
       
   211   }
       
   212 
       
   213   // detach all neighbouring joints, then delete this body.
       
   214   dxJointNode *n = b->firstjoint;
       
   215   while (n) {
       
   216     // sneaky trick to speed up removal of joint references (black magic)
       
   217     n->joint->node[(n == n->joint->node)].body = 0;
       
   218 
       
   219     dxJointNode *next = n->next;
       
   220     n->next = 0;
       
   221     removeJointReferencesFromAttachedBodies (n->joint);
       
   222     n = next;
       
   223   }
       
   224   removeObjectFromList (b);
       
   225   b->world->nb--;
       
   226 
       
   227   // delete the average buffers
       
   228   if(b->average_lvel_buffer)
       
   229   {
       
   230 	  delete[] (b->average_lvel_buffer);
       
   231 	  b->average_lvel_buffer = 0;
       
   232   }
       
   233   if(b->average_avel_buffer)
       
   234   {
       
   235 	  delete[] (b->average_avel_buffer);
       
   236 	  b->average_avel_buffer = 0;
       
   237   }
       
   238 
       
   239   delete b;
       
   240 }
       
   241 
       
   242 
       
   243 EXPORT_C void dBodySetData (dBodyID b, void *data)
       
   244 {
       
   245   b->userdata = data;
       
   246 }
       
   247 
       
   248 
       
   249 EXPORT_C void *dBodyGetData (dBodyID b)
       
   250 {
       
   251   return b->userdata;
       
   252 }
       
   253 
       
   254 
       
   255 EXPORT_C void dBodySetPosition (dBodyID b, dReal x, dReal y, dReal z)
       
   256 {
       
   257 
       
   258   b->posr.pos[0] = x;
       
   259   b->posr.pos[1] = y;
       
   260   b->posr.pos[2] = z;
       
   261 
       
   262   // notify all attached geoms that this body has moved
       
   263   for (dxGeom *geom = b->geom; geom; geom = dGeomGetBodyNext (geom))
       
   264     dGeomMoved (geom);
       
   265 }
       
   266 
       
   267 
       
   268 EXPORT_C void dBodySetRotation (dBodyID b, const dMatrix3 R)
       
   269 {
       
   270   dQuaternion q;
       
   271   dRtoQ (R,q);
       
   272   dNormalize4 (q);
       
   273   b->q[0] = q[0];
       
   274   b->q[1] = q[1];
       
   275   b->q[2] = q[2];
       
   276   b->q[3] = q[3];
       
   277   dQtoR (b->q,b->posr.R);
       
   278 
       
   279   // notify all attached geoms that this body has moved
       
   280   for (dxGeom *geom = b->geom; geom; geom = dGeomGetBodyNext (geom))
       
   281     dGeomMoved (geom);
       
   282 }
       
   283 
       
   284 
       
   285 EXPORT_C void dBodySetQuaternion (dBodyID b, const dQuaternion q)
       
   286 {
       
   287 
       
   288   b->q[0] = q[0];
       
   289   b->q[1] = q[1];
       
   290   b->q[2] = q[2];
       
   291   b->q[3] = q[3];
       
   292   dNormalize4 (b->q);
       
   293   dQtoR (b->q,b->posr.R);
       
   294 
       
   295   // notify all attached geoms that this body has moved
       
   296   for (dxGeom *geom = b->geom; geom; geom = dGeomGetBodyNext (geom))
       
   297     dGeomMoved (geom);
       
   298 }
       
   299 
       
   300 
       
   301 EXPORT_C void dBodySetLinearVel  (dBodyID b, dReal x, dReal y, dReal z)
       
   302 {
       
   303   b->lvel[0] = x;
       
   304   b->lvel[1] = y;
       
   305   b->lvel[2] = z;
       
   306 }
       
   307 
       
   308 
       
   309 EXPORT_C void dBodySetAngularVel (dBodyID b, dReal x, dReal y, dReal z)
       
   310 {
       
   311   b->avel[0] = x;
       
   312   b->avel[1] = y;
       
   313   b->avel[2] = z;
       
   314 }
       
   315 
       
   316 
       
   317 EXPORT_C const dReal * dBodyGetPosition (dBodyID b)
       
   318 {
       
   319   return b->posr.pos;
       
   320 }
       
   321 
       
   322 
       
   323 EXPORT_C void dBodyCopyPosition (dBodyID b, dVector3 pos)
       
   324 {
       
   325 	dReal* src = b->posr.pos;
       
   326 	pos[0] = src[0];
       
   327 	pos[1] = src[1];
       
   328 	pos[2] = src[2];
       
   329 }
       
   330 
       
   331 
       
   332 EXPORT_C const dReal * dBodyGetRotation (dBodyID b)
       
   333 {
       
   334   return b->posr.R;
       
   335 }
       
   336 
       
   337 
       
   338 EXPORT_C void dBodyCopyRotation (dBodyID b, dMatrix3 R)
       
   339 {
       
   340 	const dReal* src = b->posr.R;
       
   341 	R[0] = src[0];
       
   342 	R[1] = src[1];
       
   343 	R[2] = src[2];
       
   344 	R[3] = src[3];
       
   345 	R[4] = src[4];
       
   346 	R[5] = src[5];
       
   347 	R[6] = src[6];
       
   348 	R[7] = src[7];
       
   349 	R[8] = src[8];
       
   350 	R[9] = src[9];
       
   351 	R[10] = src[10];
       
   352 	R[11] = src[11];
       
   353 }
       
   354 
       
   355 
       
   356 EXPORT_C const dReal * dBodyGetQuaternion (dBodyID b)
       
   357 {
       
   358   return b->q;
       
   359 }
       
   360 
       
   361 
       
   362 EXPORT_C void dBodyCopyQuaternion (dBodyID b, dQuaternion quat)
       
   363 {
       
   364 	dReal* src = b->q;
       
   365 	quat[0] = src[0];
       
   366 	quat[1] = src[1];
       
   367 	quat[2] = src[2];
       
   368 	quat[3] = src[3];
       
   369 }
       
   370 
       
   371 
       
   372 EXPORT_C const dReal * dBodyGetLinearVel (dBodyID b)
       
   373 {
       
   374   return b->lvel;
       
   375 }
       
   376 
       
   377 
       
   378 EXPORT_C const dReal * dBodyGetAngularVel (dBodyID b)
       
   379 {
       
   380   return b->avel;
       
   381 }
       
   382 
       
   383 
       
   384 EXPORT_C void dBodySetMass (dBodyID b, const dMass *mass)
       
   385 {
       
   386   // The centre of mass must be at the origin.
       
   387   // Use dMassTranslate( mass, -mass->c[0], -mass->c[1], -mass->c[2] ) to correct it.
       
   388 
       
   389   memcpy (&b->mass,mass,sizeof(dMass));
       
   390   if (dInvertPDMatrix (b->mass.I,b->invI,3)==0) {
       
   391     dRSetIdentity (b->invI);
       
   392   }
       
   393   b->invMass = dRecip(b->mass.mass);
       
   394 }
       
   395 
       
   396 
       
   397 EXPORT_C void dBodyGetMass (dBodyID b, dMass *mass)
       
   398 {
       
   399   memcpy (mass,&b->mass,sizeof(dMass));
       
   400 }
       
   401 
       
   402 
       
   403 EXPORT_C void dBodyAddForce (dBodyID b, dReal fx, dReal fy, dReal fz)
       
   404 {
       
   405   b->facc[0] += fx;
       
   406   b->facc[1] += fy;
       
   407   b->facc[2] += fz;
       
   408 }
       
   409 
       
   410 
       
   411 EXPORT_C void dBodyAddTorque (dBodyID b, dReal fx, dReal fy, dReal fz)
       
   412 {
       
   413   b->tacc[0] += fx;
       
   414   b->tacc[1] += fy;
       
   415   b->tacc[2] += fz;
       
   416 }
       
   417 
       
   418 
       
   419 EXPORT_C void dBodyAddRelForce (dBodyID b, dReal fx, dReal fy, dReal fz)
       
   420 {
       
   421   dVector3 t1,t2;
       
   422   t1[0] = fx;
       
   423   t1[1] = fy;
       
   424   t1[2] = fz;
       
   425   t1[3] = 0;
       
   426   dMULTIPLY0_331 (t2,b->posr.R,t1);
       
   427   b->facc[0] += t2[0];
       
   428   b->facc[1] += t2[1];
       
   429   b->facc[2] += t2[2];
       
   430 }
       
   431 
       
   432 
       
   433 EXPORT_C void dBodyAddRelTorque (dBodyID b, dReal fx, dReal fy, dReal fz)
       
   434 {
       
   435   dVector3 t1,t2;
       
   436   t1[0] = fx;
       
   437   t1[1] = fy;
       
   438   t1[2] = fz;
       
   439   t1[3] = 0;
       
   440   dMULTIPLY0_331 (t2,b->posr.R,t1);
       
   441   b->tacc[0] += t2[0];
       
   442   b->tacc[1] += t2[1];
       
   443   b->tacc[2] += t2[2];
       
   444 }
       
   445 
       
   446 
       
   447 EXPORT_C void dBodyAddForceAtPos (dBodyID b, dReal fx, dReal fy, dReal fz,
       
   448 			 dReal px, dReal py, dReal pz)
       
   449 {
       
   450   b->facc[0] += fx;
       
   451   b->facc[1] += fy;
       
   452   b->facc[2] += fz;
       
   453   dVector3 f,q;
       
   454   f[0] = fx;
       
   455   f[1] = fy;
       
   456   f[2] = fz;
       
   457   q[0] = px - b->posr.pos[0];
       
   458   q[1] = py - b->posr.pos[1];
       
   459   q[2] = pz - b->posr.pos[2];
       
   460   dCROSS (b->tacc,+=,q,f);
       
   461 }
       
   462 
       
   463 
       
   464 EXPORT_C void dBodyAddForceAtRelPos (dBodyID b, dReal fx, dReal fy, dReal fz,
       
   465 			    dReal px, dReal py, dReal pz)
       
   466 {
       
   467   dVector3 prel,f,p;
       
   468   f[0] = fx;
       
   469   f[1] = fy;
       
   470   f[2] = fz;
       
   471   f[3] = 0;
       
   472   prel[0] = px;
       
   473   prel[1] = py;
       
   474   prel[2] = pz;
       
   475   prel[3] = 0;
       
   476   dMULTIPLY0_331 (p,b->posr.R,prel);
       
   477   b->facc[0] += f[0];
       
   478   b->facc[1] += f[1];
       
   479   b->facc[2] += f[2];
       
   480   dCROSS (b->tacc,+=,p,f);
       
   481 }
       
   482 
       
   483 
       
   484 EXPORT_C void dBodyAddRelForceAtPos (dBodyID b, dReal fx, dReal fy, dReal fz,
       
   485 			    dReal px, dReal py, dReal pz)
       
   486 {
       
   487   dVector3 frel,f;
       
   488   frel[0] = fx;
       
   489   frel[1] = fy;
       
   490   frel[2] = fz;
       
   491   frel[3] = 0;
       
   492   dMULTIPLY0_331 (f,b->posr.R,frel);
       
   493   b->facc[0] += f[0];
       
   494   b->facc[1] += f[1];
       
   495   b->facc[2] += f[2];
       
   496   dVector3 q;
       
   497   q[0] = px - b->posr.pos[0];
       
   498   q[1] = py - b->posr.pos[1];
       
   499   q[2] = pz - b->posr.pos[2];
       
   500   dCROSS (b->tacc,+=,q,f);
       
   501 }
       
   502 
       
   503 
       
   504 EXPORT_C void dBodyAddRelForceAtRelPos (dBodyID b, dReal fx, dReal fy, dReal fz,
       
   505 			       dReal px, dReal py, dReal pz)
       
   506 {
       
   507   dVector3 frel,prel,f,p;
       
   508   frel[0] = fx;
       
   509   frel[1] = fy;
       
   510   frel[2] = fz;
       
   511   frel[3] = 0;
       
   512   prel[0] = px;
       
   513   prel[1] = py;
       
   514   prel[2] = pz;
       
   515   prel[3] = 0;
       
   516   dMULTIPLY0_331 (f,b->posr.R,frel);
       
   517   dMULTIPLY0_331 (p,b->posr.R,prel);
       
   518   b->facc[0] += f[0];
       
   519   b->facc[1] += f[1];
       
   520   b->facc[2] += f[2];
       
   521   dCROSS (b->tacc,+=,p,f);
       
   522 }
       
   523 
       
   524 
       
   525 EXPORT_C const dReal * dBodyGetForce (dBodyID b)
       
   526 {
       
   527   return b->facc;
       
   528 }
       
   529 
       
   530 
       
   531 EXPORT_C const dReal * dBodyGetTorque (dBodyID b)
       
   532 {
       
   533   return b->tacc;
       
   534 }
       
   535 
       
   536 
       
   537 EXPORT_C void dBodySetForce (dBodyID b, dReal x, dReal y, dReal z)
       
   538 {
       
   539   b->facc[0] = x;
       
   540   b->facc[1] = y;
       
   541   b->facc[2] = z;
       
   542 }
       
   543 
       
   544 
       
   545 EXPORT_C void dBodySetTorque (dBodyID b, dReal x, dReal y, dReal z)
       
   546 {
       
   547   b->tacc[0] = x;
       
   548   b->tacc[1] = y;
       
   549   b->tacc[2] = z;
       
   550 }
       
   551 
       
   552 
       
   553 EXPORT_C void dBodyGetRelPointPos (dBodyID b, dReal px, dReal py, dReal pz,
       
   554 			  dVector3 result)
       
   555 {
       
   556   dVector3 prel,p;
       
   557   prel[0] = px;
       
   558   prel[1] = py;
       
   559   prel[2] = pz;
       
   560   prel[3] = 0;
       
   561   dMULTIPLY0_331 (p,b->posr.R,prel);
       
   562   result[0] = p[0] + b->posr.pos[0];
       
   563   result[1] = p[1] + b->posr.pos[1];
       
   564   result[2] = p[2] + b->posr.pos[2];
       
   565 }
       
   566 
       
   567 
       
   568 EXPORT_C void dBodyGetRelPointVel (dBodyID b, dReal px, dReal py, dReal pz,
       
   569 			  dVector3 result)
       
   570 {
       
   571   dVector3 prel,p;
       
   572   prel[0] = px;
       
   573   prel[1] = py;
       
   574   prel[2] = pz;
       
   575   prel[3] = 0;
       
   576   dMULTIPLY0_331 (p,b->posr.R,prel);
       
   577   result[0] = b->lvel[0];
       
   578   result[1] = b->lvel[1];
       
   579   result[2] = b->lvel[2];
       
   580   dCROSS (result,+=,b->avel,p);
       
   581 }
       
   582 
       
   583 
       
   584 EXPORT_C void dBodyGetPointVel (dBodyID b, dReal px, dReal py, dReal pz,
       
   585 		       dVector3 result)
       
   586 {
       
   587   dVector3 p;
       
   588   p[0] = px - b->posr.pos[0];
       
   589   p[1] = py - b->posr.pos[1];
       
   590   p[2] = pz - b->posr.pos[2];
       
   591   p[3] = 0;
       
   592   result[0] = b->lvel[0];
       
   593   result[1] = b->lvel[1];
       
   594   result[2] = b->lvel[2];
       
   595   dCROSS (result,+=,b->avel,p);
       
   596 }
       
   597 
       
   598 
       
   599 EXPORT_C void dBodyGetPosRelPoint (dBodyID b, dReal px, dReal py, dReal pz,
       
   600 			  dVector3 result)
       
   601 {
       
   602   dVector3 prel;
       
   603   prel[0] = px - b->posr.pos[0];
       
   604   prel[1] = py - b->posr.pos[1];
       
   605   prel[2] = pz - b->posr.pos[2];
       
   606   prel[3] = 0;
       
   607   dMULTIPLY1_331 (result,b->posr.R,prel);
       
   608 }
       
   609 
       
   610 
       
   611 EXPORT_C void dBodyVectorToWorld (dBodyID b, dReal px, dReal py, dReal pz,
       
   612 			 dVector3 result)
       
   613 {
       
   614   dVector3 p;
       
   615   p[0] = px;
       
   616   p[1] = py;
       
   617   p[2] = pz;
       
   618   p[3] = 0;
       
   619   dMULTIPLY0_331 (result,b->posr.R,p);
       
   620 }
       
   621 
       
   622 
       
   623 EXPORT_C void dBodyVectorFromWorld (dBodyID b, dReal px, dReal py, dReal pz,
       
   624 			   dVector3 result)
       
   625 {
       
   626   dVector3 p;
       
   627   p[0] = px;
       
   628   p[1] = py;
       
   629   p[2] = pz;
       
   630   p[3] = 0;
       
   631   dMULTIPLY1_331 (result,b->posr.R,p);
       
   632 }
       
   633 
       
   634 
       
   635 EXPORT_C void dBodySetFiniteRotationMode (dBodyID b, int mode)
       
   636 {
       
   637   b->flags &= ~(dxBodyFlagFiniteRotation | dxBodyFlagFiniteRotationAxis);
       
   638   if (mode) {
       
   639     b->flags |= dxBodyFlagFiniteRotation;
       
   640     if (b->finite_rot_axis[0] != 0 || b->finite_rot_axis[1] != 0 ||
       
   641 	b->finite_rot_axis[2] != 0) {
       
   642       b->flags |= dxBodyFlagFiniteRotationAxis;
       
   643     }
       
   644   }
       
   645 }
       
   646 
       
   647 
       
   648 EXPORT_C void dBodySetFiniteRotationAxis (dBodyID b, dReal x, dReal y, dReal z)
       
   649 {
       
   650   b->finite_rot_axis[0] = x;
       
   651   b->finite_rot_axis[1] = y;
       
   652   b->finite_rot_axis[2] = z;
       
   653   if (x != 0 || y != 0 || z != 0) {
       
   654     dNormalize3 (b->finite_rot_axis);
       
   655     b->flags |= dxBodyFlagFiniteRotationAxis;
       
   656   }
       
   657   else {
       
   658     b->flags &= ~dxBodyFlagFiniteRotationAxis;
       
   659   }
       
   660 }
       
   661 
       
   662 
       
   663 EXPORT_C int dBodyGetFiniteRotationMode (dBodyID b)
       
   664 {
       
   665   return ((b->flags & dxBodyFlagFiniteRotation) != 0);
       
   666 }
       
   667 
       
   668 
       
   669 EXPORT_C void dBodyGetFiniteRotationAxis (dBodyID b, dVector3 result)
       
   670 {
       
   671   result[0] = b->finite_rot_axis[0];
       
   672   result[1] = b->finite_rot_axis[1];
       
   673   result[2] = b->finite_rot_axis[2];
       
   674 }
       
   675 
       
   676 
       
   677 EXPORT_C int dBodyGetNumJoints (dBodyID b)
       
   678 {
       
   679   int count=0;
       
   680   for (dxJointNode *n=b->firstjoint; n ; n=n->next, count++)
       
   681       {
       
   682       }
       
   683   return count;
       
   684 }
       
   685 
       
   686 
       
   687 EXPORT_C dJointID dBodyGetJoint (dBodyID b, int index)
       
   688 {
       
   689   int i=0;
       
   690   for (dxJointNode *n=b->firstjoint; n; n=n->next, i++) {
       
   691     if (i == index) return n->joint;
       
   692   }
       
   693   return 0;
       
   694 }
       
   695 
       
   696 
       
   697 EXPORT_C void dBodyEnable (dBodyID b)
       
   698 {
       
   699   b->flags &= ~dxBodyDisabled;
       
   700   b->adis_stepsleft = b->adis.idle_steps;
       
   701   b->adis_timeleft = b->adis.idle_time;
       
   702   // no code for average-processing needed here
       
   703 }
       
   704 
       
   705 
       
   706 EXPORT_C void dBodyDisable (dBodyID b)
       
   707 {
       
   708   b->flags |= dxBodyDisabled;
       
   709 }
       
   710 
       
   711 
       
   712 EXPORT_C int dBodyIsEnabled (dBodyID b)
       
   713 {
       
   714   return ((b->flags & dxBodyDisabled) == 0);
       
   715 }
       
   716 
       
   717 
       
   718 EXPORT_C void dBodySetGravityMode (dBodyID b, int mode)
       
   719 {
       
   720   if (mode) b->flags &= ~dxBodyNoGravity;
       
   721   else b->flags |= dxBodyNoGravity;
       
   722 }
       
   723 
       
   724 
       
   725 EXPORT_C int dBodyGetGravityMode (dBodyID b)
       
   726 {
       
   727   return ((b->flags & dxBodyNoGravity) == 0);
       
   728 }
       
   729 
       
   730 
       
   731 // body auto-disable functions
       
   732 
       
   733 EXPORT_C dReal dBodyGetAutoDisableLinearThreshold (dBodyID b)
       
   734 {
       
   735 	return dSqrt (b->adis.linear_average_threshold);
       
   736 }
       
   737 
       
   738 
       
   739 EXPORT_C void dBodySetAutoDisableLinearThreshold (dBodyID b, dReal linear_average_threshold)
       
   740 {
       
   741 	b->adis.linear_average_threshold = dMUL(linear_average_threshold,linear_average_threshold);
       
   742 }
       
   743 
       
   744 
       
   745 EXPORT_C dReal dBodyGetAutoDisableAngularThreshold (dBodyID b)
       
   746 {
       
   747 	return dSqrt (b->adis.angular_average_threshold);
       
   748 }
       
   749 
       
   750 
       
   751 EXPORT_C void dBodySetAutoDisableAngularThreshold (dBodyID b, dReal angular_average_threshold)
       
   752 {
       
   753 	b->adis.angular_average_threshold = dMUL(angular_average_threshold,angular_average_threshold);
       
   754 }
       
   755 
       
   756 
       
   757 EXPORT_C int dBodyGetAutoDisableAverageSamplesCount (dBodyID b)
       
   758 {
       
   759 	return b->adis.average_samples;
       
   760 }
       
   761 
       
   762 
       
   763 EXPORT_C void dBodySetAutoDisableAverageSamplesCount (dBodyID b, unsigned int average_samples_count)
       
   764 {
       
   765 	b->adis.average_samples = average_samples_count;
       
   766 	// update the average buffers
       
   767 	if(b->average_lvel_buffer)
       
   768 	{
       
   769 		delete[] b->average_lvel_buffer;
       
   770 		b->average_lvel_buffer = 0;
       
   771 	}
       
   772 	if(b->average_avel_buffer)
       
   773 	{
       
   774 		delete[] b->average_avel_buffer;
       
   775 		b->average_avel_buffer = 0;
       
   776 	}
       
   777 	if(b->adis.average_samples > 0)
       
   778 	{
       
   779 		b->average_lvel_buffer = new dVector3[b->adis.average_samples];
       
   780 		b->average_avel_buffer = new dVector3[b->adis.average_samples];
       
   781 	}
       
   782 	else
       
   783 	{
       
   784 		b->average_lvel_buffer = 0;
       
   785 		b->average_avel_buffer = 0;
       
   786 	}
       
   787 	// new buffer is empty
       
   788 	b->average_counter = 0;
       
   789 	b->average_ready = 0;
       
   790 }
       
   791 
       
   792 
       
   793 EXPORT_C int dBodyGetAutoDisableSteps (dBodyID b)
       
   794 {
       
   795 	return b->adis.idle_steps;
       
   796 }
       
   797 
       
   798 
       
   799 EXPORT_C void dBodySetAutoDisableSteps (dBodyID b, int steps)
       
   800 {
       
   801 	b->adis.idle_steps = steps;
       
   802 }
       
   803 
       
   804 
       
   805 EXPORT_C dReal dBodyGetAutoDisableTime (dBodyID b)
       
   806 {
       
   807 	return b->adis.idle_time;
       
   808 }
       
   809 
       
   810 
       
   811 EXPORT_C void dBodySetAutoDisableTime (dBodyID b, dReal time)
       
   812 {
       
   813 	b->adis.idle_time = time;
       
   814 }
       
   815 
       
   816 
       
   817 EXPORT_C int dBodyGetAutoDisableFlag (dBodyID b)
       
   818 {
       
   819 	return ((b->flags & dxBodyAutoDisable) != 0);
       
   820 }
       
   821 
       
   822 
       
   823 EXPORT_C void dBodySetAutoDisableFlag (dBodyID b, int do_auto_disable)
       
   824 {
       
   825 	if (!do_auto_disable)
       
   826 	{
       
   827 		b->flags &= ~dxBodyAutoDisable;
       
   828 		// (mg) we should also reset the IsDisabled state to correspond to the DoDisabling flag
       
   829 		b->flags &= ~dxBodyDisabled;
       
   830 		b->adis.idle_steps = dWorldGetAutoDisableSteps(b->world);
       
   831 		b->adis.idle_time = dWorldGetAutoDisableTime(b->world);
       
   832 		// resetting the average calculations too
       
   833 		dBodySetAutoDisableAverageSamplesCount(b, dWorldGetAutoDisableAverageSamplesCount(b->world) );
       
   834 	}
       
   835 	else
       
   836 	{
       
   837 		b->flags |= dxBodyAutoDisable;
       
   838 	}
       
   839 }
       
   840 
       
   841 
       
   842 EXPORT_C void dBodySetAutoDisableDefaults (dBodyID b)
       
   843 {
       
   844 	dWorldID w = b->world;
       
   845 	b->adis = w->adis;
       
   846 	dBodySetAutoDisableFlag (b, w->adis_flag);
       
   847 }
       
   848 
       
   849 //****************************************************************************
       
   850 // joints
       
   851 
       
   852 static void dJointInit (dxWorld *w, dxJoint *j)
       
   853 {
       
   854   initObject (j,w);
       
   855   j->vtable = 0;
       
   856   j->flags = 0;
       
   857   j->node[0].joint = j;
       
   858   j->node[0].body = 0;
       
   859   j->node[0].next = 0;
       
   860   j->node[1].joint = j;
       
   861   j->node[1].body = 0;
       
   862   j->node[1].next = 0;
       
   863   dSetZero (j->lambda,6);
       
   864   addObjectToList (j,(dObject **) &w->firstjoint);
       
   865   w->nj++;
       
   866 }
       
   867 
       
   868 
       
   869 static dxJoint *createJoint (dWorldID w, dJointGroupID group,
       
   870 			     dxJoint::Vtable *vtable)
       
   871 {
       
   872   dxJoint *j;
       
   873   if (group) {
       
   874     j = (dxJoint*) group->stack.alloc (vtable->size);
       
   875     group->num++;
       
   876   }
       
   877   else j = (dxJoint*) dAlloc (vtable->size);
       
   878   dJointInit (w,j);
       
   879   j->vtable = vtable;
       
   880   if (group) j->flags |= dJOINT_INGROUP;
       
   881   if (vtable->init) vtable->init (j);
       
   882   j->feedback = 0;
       
   883   return j;
       
   884 }
       
   885 
       
   886 
       
   887 EXPORT_C dxJoint * dJointCreateBall (dWorldID w, dJointGroupID group)
       
   888 {
       
   889   return createJoint (w,group,&__dball_vtable);
       
   890 }
       
   891 
       
   892 
       
   893 EXPORT_C dxJoint * dJointCreateHinge (dWorldID w, dJointGroupID group)
       
   894 {
       
   895   return createJoint (w,group,&__dhinge_vtable);
       
   896 }
       
   897 
       
   898 
       
   899 EXPORT_C dxJoint * dJointCreateSlider (dWorldID w, dJointGroupID group)
       
   900 {
       
   901   return createJoint (w,group,&__dslider_vtable);
       
   902 }
       
   903 
       
   904 
       
   905 EXPORT_C dxJoint * dJointCreateContact (dWorldID w, dJointGroupID group,
       
   906 			       const dContact *c)
       
   907 {
       
   908   dxJointContact *j = (dxJointContact *)
       
   909     createJoint (w,group,&__dcontact_vtable);
       
   910   j->contact = *c;
       
   911   return j;
       
   912 }
       
   913 
       
   914 
       
   915 EXPORT_C dxJoint * dJointCreateHinge2 (dWorldID w, dJointGroupID group)
       
   916 {
       
   917   return createJoint (w,group,&__dhinge2_vtable);
       
   918 }
       
   919 
       
   920 
       
   921 EXPORT_C dxJoint * dJointCreateUniversal (dWorldID w, dJointGroupID group)
       
   922 {
       
   923   return createJoint (w,group,&__duniversal_vtable);
       
   924 }
       
   925 
       
   926 EXPORT_C dxJoint * dJointCreatePR (dWorldID w, dJointGroupID group)
       
   927 {
       
   928   return createJoint (w,group,&__dPR_vtable);
       
   929 }
       
   930 
       
   931 EXPORT_C dxJoint * dJointCreateFixed (dWorldID w, dJointGroupID group)
       
   932 {
       
   933   return createJoint (w,group,&__dfixed_vtable);
       
   934 }
       
   935 
       
   936 
       
   937 EXPORT_C dxJoint * dJointCreateNull (dWorldID w, dJointGroupID group)
       
   938 {
       
   939   return createJoint (w,group,&__dnull_vtable);
       
   940 }
       
   941 
       
   942 
       
   943 EXPORT_C dxJoint * dJointCreateAMotor (dWorldID w, dJointGroupID group)
       
   944 {
       
   945   return createJoint (w,group,&__damotor_vtable);
       
   946 }
       
   947 
       
   948 EXPORT_C dxJoint * dJointCreateLMotor (dWorldID w, dJointGroupID group)
       
   949 {
       
   950   return createJoint (w,group,&__dlmotor_vtable);
       
   951 }
       
   952 
       
   953 EXPORT_C dxJoint * dJointCreatePlane2D (dWorldID w, dJointGroupID group)
       
   954 {
       
   955   return createJoint (w,group,&__dplane2d_vtable);
       
   956 }
       
   957 
       
   958 EXPORT_C void dJointDestroy (dxJoint *j)
       
   959 {;
       
   960   if (j->flags & dJOINT_INGROUP) return;
       
   961   removeJointReferencesFromAttachedBodies (j);
       
   962   removeObjectFromList (j);
       
   963   j->world->nj--;
       
   964   dFree (j,j->vtable->size);
       
   965 }
       
   966 
       
   967 
       
   968 EXPORT_C dJointGroupID dJointGroupCreate (int /*max_size*/)
       
   969 {
       
   970   dxJointGroup *group = new dxJointGroup;
       
   971   group->num = 0;
       
   972   return group;
       
   973 }
       
   974 
       
   975 
       
   976 EXPORT_C void dJointGroupDestroy (dJointGroupID group)
       
   977 {
       
   978   dJointGroupEmpty (group);
       
   979   delete group;
       
   980 }
       
   981 
       
   982 
       
   983 EXPORT_C void dJointGroupEmpty (dJointGroupID group)
       
   984 {
       
   985   // the joints in this group are detached starting from the most recently
       
   986   // added (at the top of the stack). this helps ensure that the various
       
   987   // linked lists are not traversed too much, as the joints will hopefully
       
   988   // be at the start of those lists.
       
   989   // if any group joints have their world pointer set to 0, their world was
       
   990   // previously destroyed. no special handling is required for these joints.
       
   991 
       
   992   int i;
       
   993   dxJoint **jlist = (dxJoint**) malloc (group->num * sizeof(dxJoint*));
       
   994   if (jlist == NULL) {
       
   995   	return;
       
   996   }
       
   997   dxJoint *j = (dxJoint*) group->stack.rewind();
       
   998   for (i=0; i < group->num; i++) {
       
   999     jlist[i] = j;
       
  1000     j = (dxJoint*) (group->stack.next (j->vtable->size));
       
  1001   }
       
  1002   for (i=group->num-1; i >= 0; i--) {
       
  1003     if (jlist[i]->world) {
       
  1004       removeJointReferencesFromAttachedBodies (jlist[i]);
       
  1005       removeObjectFromList (jlist[i]);
       
  1006       jlist[i]->world->nj--;
       
  1007     }
       
  1008   }
       
  1009   group->num = 0;
       
  1010   
       
  1011   free(jlist);
       
  1012   
       
  1013   group->stack.freeAll();
       
  1014   
       
  1015 }
       
  1016 
       
  1017 
       
  1018 EXPORT_C void dJointAttach (dxJoint *joint, dxBody *body1, dxBody *body2)
       
  1019 {
       
  1020   // remove any existing body attachments
       
  1021   if (joint->node[0].body || joint->node[1].body) {
       
  1022     removeJointReferencesFromAttachedBodies (joint);
       
  1023   }
       
  1024 
       
  1025   // if a body is zero, make sure that it is body2, so 0 --> node[1].body
       
  1026   if (body1==0) {
       
  1027     body1 = body2;
       
  1028     body2 = 0;
       
  1029     joint->flags |= dJOINT_REVERSE;
       
  1030   }
       
  1031   else {
       
  1032     joint->flags &= (~dJOINT_REVERSE);
       
  1033   }
       
  1034 
       
  1035   // attach to new bodies
       
  1036   joint->node[0].body = body1;
       
  1037   joint->node[1].body = body2;
       
  1038   if (body1) {
       
  1039     joint->node[1].next = body1->firstjoint;
       
  1040     body1->firstjoint = &joint->node[1];
       
  1041   }
       
  1042   else joint->node[1].next = 0;
       
  1043   if (body2) {
       
  1044     joint->node[0].next = body2->firstjoint;
       
  1045     body2->firstjoint = &joint->node[0];
       
  1046   }
       
  1047   else {
       
  1048     joint->node[0].next = 0;
       
  1049   }
       
  1050 }
       
  1051 
       
  1052 
       
  1053 EXPORT_C void dJointSetData (dxJoint *joint, void *data)
       
  1054 {
       
  1055   joint->userdata = data;
       
  1056 }
       
  1057 
       
  1058 
       
  1059 EXPORT_C void *dJointGetData (dxJoint *joint)
       
  1060 {
       
  1061   return joint->userdata;
       
  1062 }
       
  1063 
       
  1064 
       
  1065 EXPORT_C int dJointGetType (dxJoint *joint)
       
  1066 {
       
  1067   return joint->vtable->typenum;
       
  1068 }
       
  1069 
       
  1070 
       
  1071 EXPORT_C dBodyID dJointGetBody (dxJoint *joint, int index)
       
  1072 {
       
  1073   if (index == 0 || index == 1) {
       
  1074     if (joint->flags & dJOINT_REVERSE) return joint->node[1-index].body;
       
  1075     else return joint->node[index].body;
       
  1076   }
       
  1077   else return 0;
       
  1078 }
       
  1079 
       
  1080 
       
  1081 EXPORT_C void dJointSetFeedback (dxJoint *joint, dJointFeedback *f)
       
  1082 {
       
  1083   joint->feedback = f;
       
  1084 }
       
  1085 
       
  1086 
       
  1087 EXPORT_C dJointFeedback *dJointGetFeedback (dxJoint *joint)
       
  1088 {
       
  1089   return joint->feedback;
       
  1090 }
       
  1091 
       
  1092 
       
  1093 
       
  1094 EXPORT_C dJointID dConnectingJoint (dBodyID in_b1, dBodyID in_b2)
       
  1095 {
       
  1096 	dBodyID b1, b2;
       
  1097 
       
  1098 	if (in_b1 == 0) {
       
  1099 		b1 = in_b2;
       
  1100 		b2 = in_b1;
       
  1101 	}
       
  1102 	else {
       
  1103 		b1 = in_b1;
       
  1104 		b2 = in_b2;
       
  1105 	}
       
  1106 
       
  1107     // look through b1's neighbour list for b2
       
  1108     for (dxJointNode *n=b1->firstjoint; n; n=n->next) {
       
  1109         if (n->body == b2) return n->joint;
       
  1110     }
       
  1111 
       
  1112     return 0;
       
  1113 }
       
  1114 
       
  1115 
       
  1116 
       
  1117 EXPORT_C int dConnectingJointList (dBodyID in_b1, dBodyID in_b2, dJointID* out_list)
       
  1118 {
       
  1119 	dBodyID b1, b2;
       
  1120 
       
  1121 	if (in_b1 == 0) {
       
  1122 		b1 = in_b2;
       
  1123 		b2 = in_b1;
       
  1124 	}
       
  1125 	else {
       
  1126 		b1 = in_b1;
       
  1127 		b2 = in_b2;
       
  1128 	}
       
  1129 
       
  1130     // look through b1's neighbour list for b2
       
  1131     int numConnectingJoints = 0;
       
  1132     for (dxJointNode *n=b1->firstjoint; n; n=n->next) {
       
  1133         if (n->body == b2)
       
  1134             out_list[numConnectingJoints++] = n->joint;
       
  1135     }
       
  1136 
       
  1137     return numConnectingJoints;
       
  1138 }
       
  1139 
       
  1140 
       
  1141 EXPORT_C int dAreConnected (dBodyID b1, dBodyID b2)
       
  1142 {
       
  1143   // look through b1's neighbour list for b2
       
  1144   for (dxJointNode *n=b1->firstjoint; n; n=n->next) {
       
  1145     if (n->body == b2) return 1;
       
  1146   }
       
  1147   return 0;
       
  1148 }
       
  1149 
       
  1150 
       
  1151 EXPORT_C int dAreConnectedExcluding (dBodyID b1, dBodyID b2, int joint_type)
       
  1152 {
       
  1153   // look through b1's neighbour list for b2
       
  1154   for (dxJointNode *n=b1->firstjoint; n; n=n->next) {
       
  1155     if (dJointGetType (n->joint) != joint_type && n->body == b2) return 1;
       
  1156   }
       
  1157   return 0;
       
  1158 }
       
  1159 
       
  1160 //****************************************************************************
       
  1161 // world
       
  1162 
       
  1163 EXPORT_C dxWorld * dWorldCreate()
       
  1164 {
       
  1165   dxWorld *w = new dxWorld;
       
  1166   w->firstbody = 0;
       
  1167   w->firstjoint = 0;
       
  1168   w->nb = 0;
       
  1169   w->nj = 0;
       
  1170   dSetZero (w->gravity,4);
       
  1171   w->global_erp = REAL(0.2);
       
  1172 
       
  1173   w->global_cfm = REAL(2e-5f);
       
  1174 
       
  1175   w->adis.idle_steps = 10;
       
  1176   w->adis.idle_time = 0;
       
  1177   w->adis_flag = 0;
       
  1178   w->adis.average_samples = 1;		// Default is 1 sample => Instantaneous velocity
       
  1179   w->adis.angular_average_threshold = dMUL(REAL(0.01),REAL(0.01));	// (magnitude squared)
       
  1180   w->adis.linear_average_threshold = dMUL(REAL(0.01),REAL(0.01));		// (magnitude squared)
       
  1181 
       
  1182   w->qs.num_iterations = 20;
       
  1183   w->qs.w = REAL(1.3);
       
  1184 
       
  1185   w->contactp.max_vel = dInfinity;
       
  1186   w->contactp.min_depth = 0;
       
  1187 
       
  1188   return w;
       
  1189 }
       
  1190 
       
  1191 
       
  1192 EXPORT_C void dWorldDestroy (dxWorld *w)
       
  1193 {
       
  1194   // delete all bodies and joints
       
  1195 
       
  1196   dxBody *nextb, *b = w->firstbody;
       
  1197   while (b) {
       
  1198     nextb = (dxBody*) b->next;
       
  1199     if(b->average_lvel_buffer)
       
  1200     {
       
  1201       delete[] (b->average_lvel_buffer);
       
  1202       b->average_lvel_buffer = 0;
       
  1203     }
       
  1204     if(b->average_avel_buffer)
       
  1205     {
       
  1206       delete[] (b->average_avel_buffer);
       
  1207       b->average_avel_buffer = 0;
       
  1208     }
       
  1209     dBodyDestroy(b); // calling here dBodyDestroy for correct destroying! (i.e. the average buffers)
       
  1210     b = nextb;
       
  1211   }
       
  1212   dxJoint *nextj, *j = w->firstjoint;
       
  1213   while (j) {
       
  1214     nextj = (dxJoint*)j->next;
       
  1215     if (j->flags & dJOINT_INGROUP) {
       
  1216       // the joint is part of a group, so "deactivate" it instead
       
  1217       j->world = 0;
       
  1218       j->node[0].body = 0;
       
  1219       j->node[0].next = 0;
       
  1220       j->node[1].body = 0;
       
  1221       j->node[1].next = 0;
       
  1222     }
       
  1223     else {
       
  1224       dFree (j,j->vtable->size);
       
  1225     }
       
  1226     j = nextj;
       
  1227   }
       
  1228   delete w;
       
  1229 }
       
  1230 
       
  1231 
       
  1232 EXPORT_C void dWorldSetGravity (dWorldID w, dReal x, dReal y, dReal z)
       
  1233 {
       
  1234   w->gravity[0] = x;
       
  1235   w->gravity[1] = y;
       
  1236   w->gravity[2] = z;
       
  1237 }
       
  1238 
       
  1239 
       
  1240 EXPORT_C void dWorldGetGravity (dWorldID w, dVector3 g)
       
  1241 {
       
  1242   g[0] = w->gravity[0];
       
  1243   g[1] = w->gravity[1];
       
  1244   g[2] = w->gravity[2];
       
  1245 }
       
  1246 
       
  1247 
       
  1248 EXPORT_C void dWorldSetERP (dWorldID w, dReal erp)
       
  1249 {
       
  1250   w->global_erp = erp;
       
  1251 }
       
  1252 
       
  1253 
       
  1254 EXPORT_C dReal dWorldGetERP (dWorldID w)
       
  1255 {
       
  1256   return w->global_erp;
       
  1257 }
       
  1258 
       
  1259 
       
  1260 EXPORT_C void dWorldSetCFM (dWorldID w, dReal cfm)
       
  1261 {
       
  1262   w->global_cfm = cfm;
       
  1263 }
       
  1264 
       
  1265 
       
  1266 EXPORT_C dReal dWorldGetCFM (dWorldID w)
       
  1267 {
       
  1268   return w->global_cfm;
       
  1269 }
       
  1270 
       
  1271 
       
  1272 EXPORT_C void dWorldStep (dWorldID w, dReal stepsize)
       
  1273 {
       
  1274   dxProcessIslands (w,stepsize,&dInternalStepIsland);
       
  1275 }
       
  1276 
       
  1277 
       
  1278 EXPORT_C void dWorldQuickStep (dWorldID w, dReal stepsize)
       
  1279 {
       
  1280   dxProcessIslands (w,stepsize,&dxQuickStepper);
       
  1281 }
       
  1282 
       
  1283 
       
  1284 EXPORT_C void dWorldImpulseToForce (dWorldID /*w*/, dReal stepsize,
       
  1285 			   dReal ix, dReal iy, dReal iz,
       
  1286 			   dVector3 force)
       
  1287 {
       
  1288   stepsize = dRecip(stepsize);
       
  1289   force[0] = dMUL(stepsize,ix);
       
  1290   force[1] = dMUL(stepsize,iy);
       
  1291   force[2] = dMUL(stepsize,iz);
       
  1292   // @@@ force[3] = 0;
       
  1293 }
       
  1294 
       
  1295 
       
  1296 // world auto-disable functions
       
  1297 
       
  1298 EXPORT_C dReal dWorldGetAutoDisableLinearThreshold (dWorldID w)
       
  1299 {
       
  1300 	return dSqrt (w->adis.linear_average_threshold);
       
  1301 }
       
  1302 
       
  1303 
       
  1304 EXPORT_C void dWorldSetAutoDisableLinearThreshold (dWorldID w, dReal linear_average_threshold)
       
  1305 {
       
  1306 	w->adis.linear_average_threshold = dMUL(linear_average_threshold,linear_average_threshold);
       
  1307 }
       
  1308 
       
  1309 
       
  1310 EXPORT_C dReal dWorldGetAutoDisableAngularThreshold (dWorldID w)
       
  1311 {
       
  1312 	return dSqrt (w->adis.angular_average_threshold);
       
  1313 }
       
  1314 
       
  1315 
       
  1316 EXPORT_C void dWorldSetAutoDisableAngularThreshold (dWorldID w, dReal angular_average_threshold)
       
  1317 {
       
  1318 	w->adis.angular_average_threshold = dMUL(angular_average_threshold,angular_average_threshold);
       
  1319 }
       
  1320 
       
  1321 
       
  1322 EXPORT_C int dWorldGetAutoDisableAverageSamplesCount (dWorldID w)
       
  1323 {
       
  1324 	return w->adis.average_samples;
       
  1325 }
       
  1326 
       
  1327 
       
  1328 EXPORT_C void dWorldSetAutoDisableAverageSamplesCount (dWorldID w, unsigned int average_samples_count)
       
  1329 {
       
  1330 	w->adis.average_samples = average_samples_count;
       
  1331 }
       
  1332 
       
  1333 
       
  1334 EXPORT_C int dWorldGetAutoDisableSteps (dWorldID w)
       
  1335 {
       
  1336 	return w->adis.idle_steps;
       
  1337 }
       
  1338 
       
  1339 
       
  1340 EXPORT_C void dWorldSetAutoDisableSteps (dWorldID w, int steps)
       
  1341 {
       
  1342 	w->adis.idle_steps = steps;
       
  1343 }
       
  1344 
       
  1345 
       
  1346 EXPORT_C dReal dWorldGetAutoDisableTime (dWorldID w)
       
  1347 {
       
  1348 	return w->adis.idle_time;
       
  1349 }
       
  1350 
       
  1351 
       
  1352 EXPORT_C void dWorldSetAutoDisableTime (dWorldID w, dReal time)
       
  1353 {
       
  1354 	w->adis.idle_time = time;
       
  1355 }
       
  1356 
       
  1357 
       
  1358 EXPORT_C int dWorldGetAutoDisableFlag (dWorldID w)
       
  1359 {
       
  1360 	return w->adis_flag;
       
  1361 }
       
  1362 
       
  1363 
       
  1364 EXPORT_C void dWorldSetAutoDisableFlag (dWorldID w, int do_auto_disable)
       
  1365 {
       
  1366 	w->adis_flag = (do_auto_disable != 0);
       
  1367 }
       
  1368 
       
  1369 
       
  1370 EXPORT_C void dWorldSetQuickStepNumIterations (dWorldID w, int num)
       
  1371 {
       
  1372 	w->qs.num_iterations = num;
       
  1373 }
       
  1374 
       
  1375 
       
  1376 EXPORT_C int dWorldGetQuickStepNumIterations (dWorldID w)
       
  1377 {
       
  1378 	return w->qs.num_iterations;
       
  1379 }
       
  1380 
       
  1381 
       
  1382 EXPORT_C void dWorldSetQuickStepW (dWorldID w, dReal param)
       
  1383 {
       
  1384 	w->qs.w = param;
       
  1385 }
       
  1386 
       
  1387 
       
  1388 EXPORT_C dReal dWorldGetQuickStepW (dWorldID w)
       
  1389 {
       
  1390 	return w->qs.w;
       
  1391 }
       
  1392 
       
  1393 
       
  1394 EXPORT_C void dWorldSetContactMaxCorrectingVel (dWorldID w, dReal vel)
       
  1395 {
       
  1396 	w->contactp.max_vel = vel;
       
  1397 }
       
  1398 
       
  1399 
       
  1400 EXPORT_C dReal dWorldGetContactMaxCorrectingVel (dWorldID w)
       
  1401 {
       
  1402 	return w->contactp.max_vel;
       
  1403 }
       
  1404 
       
  1405 
       
  1406 EXPORT_C void dWorldSetContactSurfaceLayer (dWorldID w, dReal depth)
       
  1407 {
       
  1408 	w->contactp.min_depth = depth;
       
  1409 }
       
  1410 
       
  1411 
       
  1412 EXPORT_C dReal dWorldGetContactSurfaceLayer (dWorldID w)
       
  1413 {
       
  1414 	return w->contactp.min_depth;
       
  1415 }
       
  1416