ode.cpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404
  1. /*************************************************************************
  2. * *
  3. * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
  4. * All rights reserved. Email: [email protected] 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. #ifdef _MSC_VER
  23. #pragma warning(disable:4291) // for VC++, no complaints about "no matching operator delete found"
  24. #endif
  25. // this source file is mostly concerned with the data structures, not the
  26. // numerics.
  27. #include "objects.h"
  28. #include <ode/ode.h>
  29. #include "joint.h"
  30. #include <ode/odemath.h>
  31. #include <ode/matrix.h>
  32. #include "step.h"
  33. #include <ode/memory.h>
  34. #include <ode/error.h>
  35. // misc defines
  36. #define ALLOCA dALLOCA16
  37. //****************************************************************************
  38. // utility
  39. static inline void initObject (dObject *obj, dxWorld *w)
  40. {
  41. obj->world = w;
  42. obj->next = 0;
  43. obj->tome = 0;
  44. obj->userdata = 0;
  45. obj->tag = 0;
  46. }
  47. // add an object `obj' to the list who's head pointer is pointed to by `first'.
  48. static inline void addObjectToList (dObject *obj, dObject **first)
  49. {
  50. obj->next = *first;
  51. obj->tome = first;
  52. if (*first) (*first)->tome = &obj->next;
  53. (*first) = obj;
  54. }
  55. // remove the object from the linked list
  56. static inline void removeObjectFromList (dObject *obj)
  57. {
  58. if (obj->next) obj->next->tome = obj->tome;
  59. *(obj->tome) = obj->next;
  60. // safeguard
  61. obj->next = 0;
  62. obj->tome = 0;
  63. }
  64. // remove the joint from neighbour lists of all connected bodies
  65. static void removeJointReferencesFromAttachedBodies (dxJoint *j)
  66. {
  67. for (int i=0; i<2; i++) {
  68. dxBody *body = j->node[i].body;
  69. if (body) {
  70. dxJointNode *n = body->firstjoint;
  71. dxJointNode *last = 0;
  72. while (n) {
  73. if (n->joint == j) {
  74. if (last) last->next = n->next;
  75. else body->firstjoint = n->next;
  76. break;
  77. }
  78. last = n;
  79. n = n->next;
  80. }
  81. }
  82. }
  83. j->node[0].body = 0;
  84. j->node[0].next = 0;
  85. j->node[1].body = 0;
  86. j->node[1].next = 0;
  87. }
  88. //****************************************************************************
  89. // island processing
  90. // this groups all joints and bodies in a world into islands. all objects
  91. // in an island are reachable by going through connected bodies and joints.
  92. // each island can be simulated separately.
  93. // note that joints that are not attached to anything will not be included
  94. // in any island, an so they do not affect the simulation.
  95. //
  96. // this function starts new island from unvisited bodies. however, it will
  97. // never start a new islands from a disabled body. thus islands of disabled
  98. // bodies will not be included in the simulation. disabled bodies are
  99. // re-enabled if they are found to be part of an active island.
  100. static void processIslands (dxWorld *world, dReal stepsize)
  101. {
  102. dxBody *b,*bb,**body;
  103. dxJoint *j,**joint;
  104. // nothing to do if no bodies
  105. if (world->nb <= 0) return;
  106. // make arrays for body and joint lists (for a single island) to go into
  107. body = (dxBody**) ALLOCA (world->nb * sizeof(dxBody*));
  108. joint = (dxJoint**) ALLOCA (world->nj * sizeof(dxJoint*));
  109. int bcount = 0; // number of bodies in `body'
  110. int jcount = 0; // number of joints in `joint'
  111. // set all body/joint tags to 0
  112. for (b=world->firstbody; b; b=(dxBody*)b->next) b->tag = 0;
  113. for (j=world->firstjoint; j; j=(dxJoint*)j->next) j->tag = 0;
  114. // allocate a stack of unvisited bodies in the island. the maximum size of
  115. // the stack can be the lesser of the number of bodies or joints, because
  116. // new bodies are only ever added to the stack by going through untagged
  117. // joints. all the bodies in the stack must be tagged!
  118. int stackalloc = (world->nj < world->nb) ? world->nj : world->nb;
  119. dxBody **stack = (dxBody**) ALLOCA (stackalloc * sizeof(dxBody*));
  120. for (bb=world->firstbody; bb; bb=(dxBody*)bb->next) {
  121. // get bb = the next enabled, untagged body, and tag it
  122. if (bb->tag || (bb->flags & dxBodyDisabled)) continue;
  123. bb->tag = 1;
  124. // tag all bodies and joints starting from bb.
  125. int stacksize = 0;
  126. b = bb;
  127. body[0] = bb;
  128. bcount = 1;
  129. jcount = 0;
  130. goto quickstart;
  131. while (stacksize > 0) {
  132. b = stack[--stacksize]; // pop body off stack
  133. body[bcount++] = b; // put body on body list
  134. quickstart:
  135. // traverse and tag all body's joints, add untagged connected bodies
  136. // to stack
  137. for (dxJointNode *n=b->firstjoint; n; n=n->next) {
  138. if (!n->joint->tag) {
  139. n->joint->tag = 1;
  140. joint[jcount++] = n->joint;
  141. if (n->body && !n->body->tag) {
  142. n->body->tag = 1;
  143. stack[stacksize++] = n->body;
  144. }
  145. }
  146. }
  147. dIASSERT(stacksize <= world->nb);
  148. dIASSERT(stacksize <= world->nj);
  149. }
  150. // now do something with body and joint lists
  151. dInternalStepIsland (world,body,bcount,joint,jcount,stepsize);
  152. // what we've just done may have altered the body/joint tag values.
  153. // we must make sure that these tags are nonzero.
  154. // also make sure all bodies are in the enabled state.
  155. int i;
  156. for (i=0; i<bcount; i++) {
  157. body[i]->tag = 1;
  158. body[i]->flags &= ~dxBodyDisabled;
  159. }
  160. for (i=0; i<jcount; i++) joint[i]->tag = 1;
  161. }
  162. // if debugging, check that all objects (except for disabled bodies,
  163. // unconnected joints, and joints that are connected to disabled bodies)
  164. // were tagged.
  165. # ifndef dNODEBUG
  166. for (b=world->firstbody; b; b=(dxBody*)b->next) {
  167. if (b->flags & dxBodyDisabled) {
  168. if (b->tag) dDebug (0,"disabled body tagged");
  169. }
  170. else {
  171. if (!b->tag) dDebug (0,"enabled body not tagged");
  172. }
  173. }
  174. for (j=world->firstjoint; j; j=(dxJoint*)j->next) {
  175. if ((j->node[0].body && (j->node[0].body->flags & dxBodyDisabled)==0) ||
  176. (j->node[1].body && (j->node[1].body->flags & dxBodyDisabled)==0)) {
  177. if (!j->tag) dDebug (0,"attached enabled joint not tagged");
  178. }
  179. else {
  180. if (j->tag) dDebug (0,"unattached or disabled joint tagged");
  181. }
  182. }
  183. # endif
  184. /******************** breakable joint contribution ***********************/
  185. dxJoint* nextJ;
  186. if (!world->firstjoint)
  187. nextJ = 0;
  188. else
  189. nextJ = (dxJoint*)world->firstjoint->next;
  190. for (j=world->firstjoint; j; j=nextJ) {
  191. nextJ = (dxJoint*)j->next;
  192. // check if joint is breakable and broken
  193. if (j->breakInfo && j->breakInfo->flags & dJOINT_BROKEN) {
  194. // detach (break) the joint
  195. dJointAttach (j, 0, 0);
  196. // call the callback function if it is set
  197. if (j->breakInfo->callback) j->breakInfo->callback (j);
  198. // finally destroy the joint if the dJOINT_DELETE_ON_BREAK is set
  199. if (j->breakInfo->flags & dJOINT_DELETE_ON_BREAK) dJointDestroy (j);
  200. }
  201. }
  202. /*************************************************************************/
  203. }
  204. //****************************************************************************
  205. // debugging
  206. // see if an object list loops on itself (if so, it's bad).
  207. static int listHasLoops (dObject *first)
  208. {
  209. if (first==0 || first->next==0) return 0;
  210. dObject *a=first,*b=first->next;
  211. int skip=0;
  212. while (b) {
  213. if (a==b) return 1;
  214. b = b->next;
  215. if (skip) a = a->next;
  216. skip ^= 1;
  217. }
  218. return 0;
  219. }
  220. // check the validity of the world data structures
  221. static void checkWorld (dxWorld *w)
  222. {
  223. dxBody *b;
  224. dxJoint *j;
  225. // check there are no loops
  226. if (listHasLoops (w->firstbody)) dDebug (0,"body list has loops");
  227. if (listHasLoops (w->firstjoint)) dDebug (0,"joint list has loops");
  228. // check lists are well formed (check `tome' pointers)
  229. for (b=w->firstbody; b; b=(dxBody*)b->next) {
  230. if (b->next && b->next->tome != &b->next)
  231. dDebug (0,"bad tome pointer in body list");
  232. }
  233. for (j=w->firstjoint; j; j=(dxJoint*)j->next) {
  234. if (j->next && j->next->tome != &j->next)
  235. dDebug (0,"bad tome pointer in joint list");
  236. }
  237. // check counts
  238. int n = 0;
  239. for (b=w->firstbody; b; b=(dxBody*)b->next) n++;
  240. if (w->nb != n) dDebug (0,"body count incorrect");
  241. n = 0;
  242. for (j=w->firstjoint; j; j=(dxJoint*)j->next) n++;
  243. if (w->nj != n) dDebug (0,"joint count incorrect");
  244. // set all tag values to a known value
  245. static int count = 0;
  246. count++;
  247. for (b=w->firstbody; b; b=(dxBody*)b->next) b->tag = count;
  248. for (j=w->firstjoint; j; j=(dxJoint*)j->next) j->tag = count;
  249. // check all body/joint world pointers are ok
  250. for (b=w->firstbody; b; b=(dxBody*)b->next) if (b->world != w)
  251. dDebug (0,"bad world pointer in body list");
  252. for (j=w->firstjoint; j; j=(dxJoint*)j->next) if (j->world != w)
  253. dDebug (0,"bad world pointer in joint list");
  254. /*
  255. // check for half-connected joints - actually now these are valid
  256. for (j=w->firstjoint; j; j=(dxJoint*)j->next) {
  257. if (j->node[0].body || j->node[1].body) {
  258. if (!(j->node[0].body && j->node[1].body))
  259. dDebug (0,"half connected joint found");
  260. }
  261. }
  262. */
  263. // check that every joint node appears in the joint lists of both bodies it
  264. // attaches
  265. for (j=w->firstjoint; j; j=(dxJoint*)j->next) {
  266. for (int i=0; i<2; i++) {
  267. if (j->node[i].body) {
  268. int ok = 0;
  269. for (dxJointNode *n=j->node[i].body->firstjoint; n; n=n->next) {
  270. if (n->joint == j) ok = 1;
  271. }
  272. if (ok==0) dDebug (0,"joint not in joint list of attached body");
  273. }
  274. }
  275. }
  276. // check all body joint lists (correct body ptrs)
  277. for (b=w->firstbody; b; b=(dxBody*)b->next) {
  278. for (dxJointNode *n=b->firstjoint; n; n=n->next) {
  279. if (&n->joint->node[0] == n) {
  280. if (n->joint->node[1].body != b)
  281. dDebug (0,"bad body pointer in joint node of body list (1)");
  282. }
  283. else {
  284. if (n->joint->node[0].body != b)
  285. dDebug (0,"bad body pointer in joint node of body list (2)");
  286. }
  287. if (n->joint->tag != count) dDebug (0,"bad joint node pointer in body");
  288. }
  289. }
  290. // check all body pointers in joints, check they are distinct
  291. for (j=w->firstjoint; j; j=(dxJoint*)j->next) {
  292. if (j->node[0].body && (j->node[0].body == j->node[1].body))
  293. dDebug (0,"non-distinct body pointers in joint");
  294. if ((j->node[0].body && j->node[0].body->tag != count) ||
  295. (j->node[1].body && j->node[1].body->tag != count))
  296. dDebug (0,"bad body pointer in joint");
  297. }
  298. }
  299. void dWorldCheck (dxWorld *w)
  300. {
  301. checkWorld (w);
  302. }
  303. //****************************************************************************
  304. // body
  305. dxBody *dBodyCreate (dxWorld *w)
  306. {
  307. dAASSERT (w);
  308. dxBody *b = new dxBody;
  309. initObject (b,w);
  310. b->firstjoint = 0;
  311. b->flags = 0;
  312. b->geom = 0;
  313. dMassSetParameters (&b->mass,1,0,0,0,1,1,1,0,0,0);
  314. dSetZero (b->invI,4*3);
  315. b->invI[0] = 1;
  316. b->invI[5] = 1;
  317. b->invI[10] = 1;
  318. b->invMass = 1;
  319. dSetZero (b->pos,4);
  320. dSetZero (b->q,4);
  321. b->q[0] = 1;
  322. dRSetIdentity (b->R);
  323. dSetZero (b->lvel,4);
  324. dSetZero (b->avel,4);
  325. dSetZero (b->facc,4);
  326. dSetZero (b->tacc,4);
  327. dSetZero (b->finite_rot_axis,4);
  328. addObjectToList (b,(dObject **) &w->firstbody);
  329. w->nb++;
  330. return b;
  331. }
  332. void dBodyDestroy (dxBody *b)
  333. {
  334. dAASSERT (b);
  335. // all geoms that link to this body must be notified that the body is about
  336. // to disappear. note that the call to dGeomSetBody(geom,0) will result in
  337. // dGeomGetBodyNext() returning 0 for the body, so we must get the next body
  338. // before setting the body to 0.
  339. dxGeom *next_geom = 0;
  340. for (dxGeom *geom = b->geom; geom; geom = next_geom) {
  341. next_geom = dGeomGetBodyNext (geom);
  342. dGeomSetBody (geom,0);
  343. }
  344. // detach all neighbouring joints, then delete this body.
  345. dxJointNode *n = b->firstjoint;
  346. while (n) {
  347. // sneaky trick to speed up removal of joint references (black magic)
  348. n->joint->node[(n == n->joint->node)].body = 0;
  349. dxJointNode *next = n->next;
  350. n->next = 0;
  351. removeJointReferencesFromAttachedBodies (n->joint);
  352. n = next;
  353. }
  354. removeObjectFromList (b);
  355. b->world->nb--;
  356. delete b;
  357. }
  358. void dBodySetData (dBodyID b, void *data)
  359. {
  360. dAASSERT (b);
  361. b->userdata = data;
  362. }
  363. void *dBodyGetData (dBodyID b)
  364. {
  365. dAASSERT (b);
  366. return b->userdata;
  367. }
  368. void dBodySetPosition (dBodyID b, dReal x, dReal y, dReal z)
  369. {
  370. dAASSERT (b);
  371. b->pos[0] = x;
  372. b->pos[1] = y;
  373. b->pos[2] = z;
  374. // notify all attached geoms that this body has moved
  375. for (dxGeom *geom = b->geom; geom; geom = dGeomGetBodyNext (geom))
  376. dGeomMoved (geom);
  377. }
  378. void dBodySetRotation (dBodyID b, const dMatrix3 R)
  379. {
  380. dAASSERT (b && R);
  381. dQuaternion q;
  382. dRtoQ (R,q);
  383. dNormalize4 (q);
  384. b->q[0] = q[0];
  385. b->q[1] = q[1];
  386. b->q[2] = q[2];
  387. b->q[3] = q[3];
  388. dQtoR (b->q,b->R);
  389. // notify all attached geoms that this body has moved
  390. for (dxGeom *geom = b->geom; geom; geom = dGeomGetBodyNext (geom))
  391. dGeomMoved (geom);
  392. }
  393. void dBodySetQuaternion (dBodyID b, const dQuaternion q)
  394. {
  395. dAASSERT (b && q);
  396. b->q[0] = q[0];
  397. b->q[1] = q[1];
  398. b->q[2] = q[2];
  399. b->q[3] = q[3];
  400. dNormalize4 (b->q);
  401. dQtoR (b->q,b->R);
  402. // notify all attached geoms that this body has moved
  403. for (dxGeom *geom = b->geom; geom; geom = dGeomGetBodyNext (geom))
  404. dGeomMoved (geom);
  405. }
  406. void dBodySetLinearVel (dBodyID b, dReal x, dReal y, dReal z)
  407. {
  408. dAASSERT (b);
  409. b->lvel[0] = x;
  410. b->lvel[1] = y;
  411. b->lvel[2] = z;
  412. }
  413. void dBodySetAngularVel (dBodyID b, dReal x, dReal y, dReal z)
  414. {
  415. dAASSERT (b);
  416. b->avel[0] = x;
  417. b->avel[1] = y;
  418. b->avel[2] = z;
  419. }
  420. const dReal * dBodyGetPosition (dBodyID b)
  421. {
  422. dAASSERT (b);
  423. return b->pos;
  424. }
  425. const dReal * dBodyGetRotation (dBodyID b)
  426. {
  427. dAASSERT (b);
  428. return b->R;
  429. }
  430. const dReal * dBodyGetQuaternion (dBodyID b)
  431. {
  432. dAASSERT (b);
  433. return b->q;
  434. }
  435. const dReal * dBodyGetLinearVel (dBodyID b)
  436. {
  437. dAASSERT (b);
  438. return b->lvel;
  439. }
  440. const dReal * dBodyGetAngularVel (dBodyID b)
  441. {
  442. dAASSERT (b);
  443. return b->avel;
  444. }
  445. void dBodySetMass (dBodyID b, const dMass *mass)
  446. {
  447. dAASSERT (b && mass);
  448. memcpy (&b->mass,mass,sizeof(dMass));
  449. if (dInvertPDMatrix (b->mass.I,b->invI,3)==0) {
  450. dDEBUGMSG ("inertia must be positive definite");
  451. dRSetIdentity (b->invI);
  452. }
  453. b->invMass = dRecip(b->mass.mass);
  454. }
  455. void dBodyGetMass (dBodyID b, dMass *mass)
  456. {
  457. dAASSERT (b && mass);
  458. memcpy (mass,&b->mass,sizeof(dMass));
  459. }
  460. void dBodyAddForce (dBodyID b, dReal fx, dReal fy, dReal fz)
  461. {
  462. dAASSERT (b);
  463. b->facc[0] += fx;
  464. b->facc[1] += fy;
  465. b->facc[2] += fz;
  466. }
  467. void dBodyAddTorque (dBodyID b, dReal fx, dReal fy, dReal fz)
  468. {
  469. dAASSERT (b);
  470. b->tacc[0] += fx;
  471. b->tacc[1] += fy;
  472. b->tacc[2] += fz;
  473. }
  474. void dBodyAddRelForce (dBodyID b, dReal fx, dReal fy, dReal fz)
  475. {
  476. dAASSERT (b);
  477. dVector3 t1,t2;
  478. t1[0] = fx;
  479. t1[1] = fy;
  480. t1[2] = fz;
  481. t1[3] = 0;
  482. dMULTIPLY0_331 (t2,b->R,t1);
  483. b->facc[0] += t2[0];
  484. b->facc[1] += t2[1];
  485. b->facc[2] += t2[2];
  486. }
  487. void dBodyAddRelTorque (dBodyID b, dReal fx, dReal fy, dReal fz)
  488. {
  489. dAASSERT (b);
  490. dVector3 t1,t2;
  491. t1[0] = fx;
  492. t1[1] = fy;
  493. t1[2] = fz;
  494. t1[3] = 0;
  495. dMULTIPLY0_331 (t2,b->R,t1);
  496. b->tacc[0] += t2[0];
  497. b->tacc[1] += t2[1];
  498. b->tacc[2] += t2[2];
  499. }
  500. void dBodyAddForceAtPos (dBodyID b, dReal fx, dReal fy, dReal fz,
  501. dReal px, dReal py, dReal pz)
  502. {
  503. dAASSERT (b);
  504. b->facc[0] += fx;
  505. b->facc[1] += fy;
  506. b->facc[2] += fz;
  507. dVector3 f,q;
  508. f[0] = fx;
  509. f[1] = fy;
  510. f[2] = fz;
  511. q[0] = px - b->pos[0];
  512. q[1] = py - b->pos[1];
  513. q[2] = pz - b->pos[2];
  514. dCROSS (b->tacc,+=,q,f);
  515. }
  516. void dBodyAddForceAtRelPos (dBodyID b, dReal fx, dReal fy, dReal fz,
  517. dReal px, dReal py, dReal pz)
  518. {
  519. dAASSERT (b);
  520. dVector3 prel,f,p;
  521. f[0] = fx;
  522. f[1] = fy;
  523. f[2] = fz;
  524. f[3] = 0;
  525. prel[0] = px;
  526. prel[1] = py;
  527. prel[2] = pz;
  528. prel[3] = 0;
  529. dMULTIPLY0_331 (p,b->R,prel);
  530. b->facc[0] += f[0];
  531. b->facc[1] += f[1];
  532. b->facc[2] += f[2];
  533. dCROSS (b->tacc,+=,p,f);
  534. }
  535. void dBodyAddRelForceAtPos (dBodyID b, dReal fx, dReal fy, dReal fz,
  536. dReal px, dReal py, dReal pz)
  537. {
  538. dAASSERT (b);
  539. dVector3 frel,f;
  540. frel[0] = fx;
  541. frel[1] = fy;
  542. frel[2] = fz;
  543. frel[3] = 0;
  544. dMULTIPLY0_331 (f,b->R,frel);
  545. b->facc[0] += f[0];
  546. b->facc[1] += f[1];
  547. b->facc[2] += f[2];
  548. dVector3 q;
  549. q[0] = px - b->pos[0];
  550. q[1] = py - b->pos[1];
  551. q[2] = pz - b->pos[2];
  552. dCROSS (b->tacc,+=,q,f);
  553. }
  554. void dBodyAddRelForceAtRelPos (dBodyID b, dReal fx, dReal fy, dReal fz,
  555. dReal px, dReal py, dReal pz)
  556. {
  557. dAASSERT (b);
  558. dVector3 frel,prel,f,p;
  559. frel[0] = fx;
  560. frel[1] = fy;
  561. frel[2] = fz;
  562. frel[3] = 0;
  563. prel[0] = px;
  564. prel[1] = py;
  565. prel[2] = pz;
  566. prel[3] = 0;
  567. dMULTIPLY0_331 (f,b->R,frel);
  568. dMULTIPLY0_331 (p,b->R,prel);
  569. b->facc[0] += f[0];
  570. b->facc[1] += f[1];
  571. b->facc[2] += f[2];
  572. dCROSS (b->tacc,+=,p,f);
  573. }
  574. const dReal * dBodyGetForce (dBodyID b)
  575. {
  576. dAASSERT (b);
  577. return b->facc;
  578. }
  579. const dReal * dBodyGetTorque (dBodyID b)
  580. {
  581. dAASSERT (b);
  582. return b->tacc;
  583. }
  584. void dBodySetForce (dBodyID b, dReal x, dReal y, dReal z)
  585. {
  586. dAASSERT (b);
  587. b->facc[0] = x;
  588. b->facc[1] = y;
  589. b->facc[2] = z;
  590. }
  591. void dBodySetTorque (dBodyID b, dReal x, dReal y, dReal z)
  592. {
  593. dAASSERT (b);
  594. b->tacc[0] = x;
  595. b->tacc[1] = y;
  596. b->tacc[2] = z;
  597. }
  598. void dBodyGetRelPointPos (dBodyID b, dReal px, dReal py, dReal pz,
  599. dVector3 result)
  600. {
  601. dAASSERT (b);
  602. dVector3 prel,p;
  603. prel[0] = px;
  604. prel[1] = py;
  605. prel[2] = pz;
  606. prel[3] = 0;
  607. dMULTIPLY0_331 (p,b->R,prel);
  608. result[0] = p[0] + b->pos[0];
  609. result[1] = p[1] + b->pos[1];
  610. result[2] = p[2] + b->pos[2];
  611. }
  612. void dBodyGetRelPointVel (dBodyID b, dReal px, dReal py, dReal pz,
  613. dVector3 result)
  614. {
  615. dAASSERT (b);
  616. dVector3 prel,p;
  617. prel[0] = px;
  618. prel[1] = py;
  619. prel[2] = pz;
  620. prel[3] = 0;
  621. dMULTIPLY0_331 (p,b->R,prel);
  622. result[0] = b->lvel[0];
  623. result[1] = b->lvel[1];
  624. result[2] = b->lvel[2];
  625. dCROSS (result,+=,b->avel,p);
  626. }
  627. void dBodyGetPointVel (dBodyID b, dReal px, dReal py, dReal pz,
  628. dVector3 result)
  629. {
  630. dAASSERT (b);
  631. dVector3 p;
  632. p[0] = px - b->pos[0];
  633. p[1] = py - b->pos[1];
  634. p[2] = pz - b->pos[2];
  635. p[3] = 0;
  636. result[0] = b->lvel[0];
  637. result[1] = b->lvel[1];
  638. result[2] = b->lvel[2];
  639. dCROSS (result,+=,b->avel,p);
  640. }
  641. void dBodyGetPosRelPoint (dBodyID b, dReal px, dReal py, dReal pz,
  642. dVector3 result)
  643. {
  644. dAASSERT (b);
  645. dVector3 prel;
  646. prel[0] = px - b->pos[0];
  647. prel[1] = py - b->pos[1];
  648. prel[2] = pz - b->pos[2];
  649. prel[3] = 0;
  650. dMULTIPLY1_331 (result,b->R,prel);
  651. }
  652. void dBodyVectorToWorld (dBodyID b, dReal px, dReal py, dReal pz,
  653. dVector3 result)
  654. {
  655. dAASSERT (b);
  656. dVector3 p;
  657. p[0] = px;
  658. p[1] = py;
  659. p[2] = pz;
  660. p[3] = 0;
  661. dMULTIPLY0_331 (result,b->R,p);
  662. }
  663. void dBodyVectorFromWorld (dBodyID b, dReal px, dReal py, dReal pz,
  664. dVector3 result)
  665. {
  666. dAASSERT (b);
  667. dVector3 p;
  668. p[0] = px;
  669. p[1] = py;
  670. p[2] = pz;
  671. p[3] = 0;
  672. dMULTIPLY1_331 (result,b->R,p);
  673. }
  674. void dBodySetFiniteRotationMode (dBodyID b, int mode)
  675. {
  676. dAASSERT (b);
  677. b->flags &= ~(dxBodyFlagFiniteRotation | dxBodyFlagFiniteRotationAxis);
  678. if (mode) {
  679. b->flags |= dxBodyFlagFiniteRotation;
  680. if (b->finite_rot_axis[0] != 0 || b->finite_rot_axis[1] != 0 ||
  681. b->finite_rot_axis[2] != 0) {
  682. b->flags |= dxBodyFlagFiniteRotationAxis;
  683. }
  684. }
  685. }
  686. void dBodySetFiniteRotationAxis (dBodyID b, dReal x, dReal y, dReal z)
  687. {
  688. dAASSERT (b);
  689. b->finite_rot_axis[0] = x;
  690. b->finite_rot_axis[1] = y;
  691. b->finite_rot_axis[2] = z;
  692. if (x != 0 || y != 0 || z != 0) {
  693. dNormalize3 (b->finite_rot_axis);
  694. b->flags |= dxBodyFlagFiniteRotationAxis;
  695. }
  696. else {
  697. b->flags &= ~dxBodyFlagFiniteRotationAxis;
  698. }
  699. }
  700. int dBodyGetFiniteRotationMode (dBodyID b)
  701. {
  702. dAASSERT (b);
  703. return ((b->flags & dxBodyFlagFiniteRotation) != 0);
  704. }
  705. void dBodyGetFiniteRotationAxis (dBodyID b, dVector3 result)
  706. {
  707. dAASSERT (b);
  708. result[0] = b->finite_rot_axis[0];
  709. result[1] = b->finite_rot_axis[1];
  710. result[2] = b->finite_rot_axis[2];
  711. }
  712. int dBodyGetNumJoints (dBodyID b)
  713. {
  714. dAASSERT (b);
  715. int count=0;
  716. for (dxJointNode *n=b->firstjoint; n; n=n->next, count++);
  717. return count;
  718. }
  719. dJointID dBodyGetJoint (dBodyID b, int index)
  720. {
  721. dAASSERT (b);
  722. int i=0;
  723. for (dxJointNode *n=b->firstjoint; n; n=n->next, i++) {
  724. if (i == index) return n->joint;
  725. }
  726. return 0;
  727. }
  728. void dBodyEnable (dBodyID b)
  729. {
  730. dAASSERT (b);
  731. b->flags &= ~dxBodyDisabled;
  732. }
  733. void dBodyDisable (dBodyID b)
  734. {
  735. dAASSERT (b);
  736. b->flags |= dxBodyDisabled;
  737. }
  738. int dBodyIsEnabled (dBodyID b)
  739. {
  740. dAASSERT (b);
  741. return ((b->flags & dxBodyDisabled) == 0);
  742. }
  743. void dBodySetGravityMode (dBodyID b, int mode)
  744. {
  745. dAASSERT (b);
  746. if (mode) b->flags &= ~dxBodyNoGravity;
  747. else b->flags |= dxBodyNoGravity;
  748. }
  749. int dBodyGetGravityMode (dBodyID b)
  750. {
  751. dAASSERT (b);
  752. return ((b->flags & dxBodyNoGravity) == 0);
  753. }
  754. //****************************************************************************
  755. // joints
  756. static void dJointInit (dxWorld *w, dxJoint *j)
  757. {
  758. dIASSERT (w && j);
  759. initObject (j,w);
  760. j->vtable = 0;
  761. j->flags = 0;
  762. j->node[0].joint = j;
  763. j->node[0].body = 0;
  764. j->node[0].next = 0;
  765. j->node[1].joint = j;
  766. j->node[1].body = 0;
  767. j->node[1].next = 0;
  768. addObjectToList (j,(dObject **) &w->firstjoint);
  769. w->nj++;
  770. }
  771. static dxJoint *createJoint (dWorldID w, dJointGroupID group,
  772. dxJoint::Vtable *vtable)
  773. {
  774. dIASSERT (w && vtable);
  775. dxJoint *j;
  776. if (group) {
  777. j = (dxJoint*) group->stack.alloc (vtable->size);
  778. group->num++;
  779. }
  780. else j = (dxJoint*) dAlloc (vtable->size);
  781. dJointInit (w,j);
  782. j->vtable = vtable;
  783. if (group) j->flags |= dJOINT_INGROUP;
  784. if (vtable->init) vtable->init (j);
  785. j->feedback = 0;
  786. /******************** breakable joint contribution ***********************/
  787. j->breakInfo = 0;
  788. /*************************************************************************/
  789. return j;
  790. }
  791. dxJoint * dJointCreateBall (dWorldID w, dJointGroupID group)
  792. {
  793. dAASSERT (w);
  794. return createJoint (w,group,&__dball_vtable);
  795. }
  796. dxJoint * dJointCreateHinge (dWorldID w, dJointGroupID group)
  797. {
  798. dAASSERT (w);
  799. return createJoint (w,group,&__dhinge_vtable);
  800. }
  801. dxJoint * dJointCreateSlider (dWorldID w, dJointGroupID group)
  802. {
  803. dAASSERT (w);
  804. return createJoint (w,group,&__dslider_vtable);
  805. }
  806. dxJoint * dJointCreateContact (dWorldID w, dJointGroupID group,
  807. const dContact *c)
  808. {
  809. dAASSERT (w && c);
  810. dxJointContact *j = (dxJointContact *)
  811. createJoint (w,group,&__dcontact_vtable);
  812. j->contact = *c;
  813. return j;
  814. }
  815. dxJoint * dJointCreateHinge2 (dWorldID w, dJointGroupID group)
  816. {
  817. dAASSERT (w);
  818. return createJoint (w,group,&__dhinge2_vtable);
  819. }
  820. dxJoint * dJointCreateUniversal (dWorldID w, dJointGroupID group)
  821. {
  822. dAASSERT (w);
  823. return createJoint (w,group,&__duniversal_vtable);
  824. }
  825. dxJoint * dJointCreateFixed (dWorldID w, dJointGroupID group)
  826. {
  827. dAASSERT (w);
  828. return createJoint (w,group,&__dfixed_vtable);
  829. }
  830. dxJoint * dJointCreateNull (dWorldID w, dJointGroupID group)
  831. {
  832. dAASSERT (w);
  833. return createJoint (w,group,&__dnull_vtable);
  834. }
  835. dxJoint * dJointCreateAMotor (dWorldID w, dJointGroupID group)
  836. {
  837. dAASSERT (w);
  838. return createJoint (w,group,&__damotor_vtable);
  839. }
  840. void dJointDestroy (dxJoint *j)
  841. {
  842. dAASSERT (j);
  843. if (j->flags & dJOINT_INGROUP) return;
  844. removeJointReferencesFromAttachedBodies (j);
  845. removeObjectFromList (j);
  846. /******************** breakable joint contribution ***********************/
  847. if (j->breakInfo) delete j->breakInfo;
  848. /*************************************************************************/
  849. j->world->nj--;
  850. dFree (j,j->vtable->size);
  851. }
  852. dJointGroupID dJointGroupCreate (int max_size)
  853. {
  854. // not any more ... dUASSERT (max_size > 0,"max size must be > 0");
  855. dxJointGroup *group = new dxJointGroup;
  856. group->num = 0;
  857. return group;
  858. }
  859. void dJointGroupDestroy (dJointGroupID group)
  860. {
  861. dAASSERT (group);
  862. dJointGroupEmpty (group);
  863. delete group;
  864. }
  865. void dJointGroupEmpty (dJointGroupID group)
  866. {
  867. // the joints in this group are detached starting from the most recently
  868. // added (at the top of the stack). this helps ensure that the various
  869. // linked lists are not traversed too much, as the joints will hopefully
  870. // be at the start of those lists.
  871. // if any group joints have their world pointer set to 0, their world was
  872. // previously destroyed. no special handling is required for these joints.
  873. dAASSERT (group);
  874. int i;
  875. dxJoint **jlist = (dxJoint**) ALLOCA (group->num * sizeof(dxJoint*));
  876. dxJoint *j = (dxJoint*) group->stack.rewind();
  877. for (i=0; i < group->num; i++) {
  878. jlist[i] = j;
  879. j = (dxJoint*) (group->stack.next (j->vtable->size));
  880. }
  881. for (i=group->num-1; i >= 0; i--) {
  882. if (jlist[i]->world) {
  883. removeJointReferencesFromAttachedBodies (jlist[i]);
  884. removeObjectFromList (jlist[i]);
  885. jlist[i]->world->nj--;
  886. }
  887. }
  888. group->num = 0;
  889. group->stack.freeAll();
  890. }
  891. void dJointAttach (dxJoint *joint, dxBody *body1, dxBody *body2)
  892. {
  893. // check arguments
  894. dUASSERT (joint,"bad joint argument");
  895. dUASSERT (body1 == 0 || body1 != body2,"can't have body1==body2");
  896. dxWorld *world = joint->world;
  897. dUASSERT ( (!body1 || body1->world == world) &&
  898. (!body2 || body2->world == world),
  899. "joint and bodies must be in same world");
  900. // check if the joint can not be attached to just one body
  901. dUASSERT (!((joint->flags & dJOINT_TWOBODIES) &&
  902. ((body1 != 0) ^ (body2 != 0))),
  903. "joint can not be attached to just one body");
  904. // remove any existing body attachments
  905. if (joint->node[0].body || joint->node[1].body) {
  906. removeJointReferencesFromAttachedBodies (joint);
  907. }
  908. // if a body is zero, make sure that it is body2, so 0 --> node[1].body
  909. if (body1==0) {
  910. body1 = body2;
  911. body2 = 0;
  912. joint->flags |= dJOINT_REVERSE;
  913. }
  914. else {
  915. joint->flags &= (~dJOINT_REVERSE);
  916. }
  917. // attach to new bodies
  918. joint->node[0].body = body1;
  919. joint->node[1].body = body2;
  920. if (body1) {
  921. joint->node[1].next = body1->firstjoint;
  922. body1->firstjoint = &joint->node[1];
  923. }
  924. else joint->node[1].next = 0;
  925. if (body2) {
  926. joint->node[0].next = body2->firstjoint;
  927. body2->firstjoint = &joint->node[0];
  928. }
  929. else {
  930. joint->node[0].next = 0;
  931. }
  932. }
  933. void dJointSetData (dxJoint *joint, void *data)
  934. {
  935. dAASSERT (joint);
  936. joint->userdata = data;
  937. }
  938. void *dJointGetData (dxJoint *joint)
  939. {
  940. dAASSERT (joint);
  941. return joint->userdata;
  942. }
  943. int dJointGetType (dxJoint *joint)
  944. {
  945. dAASSERT (joint);
  946. return joint->vtable->typenum;
  947. }
  948. dBodyID dJointGetBody (dxJoint *joint, int index)
  949. {
  950. dAASSERT (joint);
  951. if (index >= 0 && index < 2) return joint->node[index].body;
  952. else return 0;
  953. }
  954. void dJointSetFeedback (dxJoint *joint, dJointFeedback *f)
  955. {
  956. dAASSERT (joint);
  957. joint->feedback = f;
  958. }
  959. dJointFeedback *dJointGetFeedback (dxJoint *joint)
  960. {
  961. dAASSERT (joint);
  962. return joint->feedback;
  963. }
  964. int dAreConnected (dBodyID b1, dBodyID b2)
  965. {
  966. dAASSERT (b1 && b2);
  967. // look through b1's neighbour list for b2
  968. for (dxJointNode *n=b1->firstjoint; n; n=n->next) {
  969. if (n->body == b2) return 1;
  970. }
  971. return 0;
  972. }
  973. int dAreConnectedExcluding (dBodyID b1, dBodyID b2, int joint_type)
  974. {
  975. dAASSERT (b1 && b2);
  976. // look through b1's neighbour list for b2
  977. for (dxJointNode *n=b1->firstjoint; n; n=n->next) {
  978. if (dJointGetType (n->joint) != joint_type && n->body == b2) return 1;
  979. }
  980. return 0;
  981. }
  982. //****************************************************************************
  983. // world
  984. dxWorld * dWorldCreate()
  985. {
  986. dxWorld *w = new dxWorld;
  987. w->firstbody = 0;
  988. w->firstjoint = 0;
  989. w->nb = 0;
  990. w->nj = 0;
  991. dSetZero (w->gravity,4);
  992. w->global_erp = REAL(0.2);
  993. #if defined(dSINGLE)
  994. w->global_cfm = 1e-5f;
  995. #elif defined(dDOUBLE)
  996. w->global_cfm = 1e-10;
  997. #else
  998. #error dSINGLE or dDOUBLE must be defined
  999. #endif
  1000. return w;
  1001. }
  1002. void dWorldDestroy (dxWorld *w)
  1003. {
  1004. // delete all bodies and joints
  1005. dAASSERT (w);
  1006. dxBody *nextb, *b = w->firstbody;
  1007. while (b) {
  1008. nextb = (dxBody*) b->next;
  1009. delete b;
  1010. b = nextb;
  1011. }
  1012. dxJoint *nextj, *j = w->firstjoint;
  1013. while (j) {
  1014. nextj = (dxJoint*)j->next;
  1015. if (j->flags & dJOINT_INGROUP) {
  1016. // the joint is part of a group, so "deactivate" it instead
  1017. j->world = 0;
  1018. j->node[0].body = 0;
  1019. j->node[0].next = 0;
  1020. j->node[1].body = 0;
  1021. j->node[1].next = 0;
  1022. dMessage (0,"warning: destroying world containing grouped joints");
  1023. }
  1024. else {
  1025. dFree (j,j->vtable->size);
  1026. }
  1027. j = nextj;
  1028. }
  1029. delete w;
  1030. }
  1031. void dWorldSetGravity (dWorldID w, dReal x, dReal y, dReal z)
  1032. {
  1033. dAASSERT (w);
  1034. w->gravity[0] = x;
  1035. w->gravity[1] = y;
  1036. w->gravity[2] = z;
  1037. }
  1038. void dWorldGetGravity (dWorldID w, dVector3 g)
  1039. {
  1040. dAASSERT (w);
  1041. g[0] = w->gravity[0];
  1042. g[1] = w->gravity[1];
  1043. g[2] = w->gravity[2];
  1044. }
  1045. void dWorldSetERP (dWorldID w, dReal erp)
  1046. {
  1047. dAASSERT (w);
  1048. w->global_erp = erp;
  1049. }
  1050. dReal dWorldGetERP (dWorldID w)
  1051. {
  1052. dAASSERT (w);
  1053. return w->global_erp;
  1054. }
  1055. void dWorldSetCFM (dWorldID w, dReal cfm)
  1056. {
  1057. dAASSERT (w);
  1058. w->global_cfm = cfm;
  1059. }
  1060. dReal dWorldGetCFM (dWorldID w)
  1061. {
  1062. dAASSERT (w);
  1063. return w->global_cfm;
  1064. }
  1065. void dWorldStep (dWorldID w, dReal stepsize)
  1066. {
  1067. dUASSERT (w,"bad world argument");
  1068. dUASSERT (stepsize > 0,"stepsize must be > 0");
  1069. processIslands (w,stepsize);
  1070. }
  1071. void dWorldImpulseToForce (dWorldID w, dReal stepsize,
  1072. dReal ix, dReal iy, dReal iz,
  1073. dVector3 force)
  1074. {
  1075. dAASSERT (w);
  1076. stepsize = dRecip(stepsize);
  1077. force[0] = stepsize * ix;
  1078. force[1] = stepsize * iy;
  1079. force[2] = stepsize * iz;
  1080. // @@@ force[3] = 0;
  1081. }
  1082. //****************************************************************************
  1083. // testing
  1084. #define NUM 100
  1085. #define DO(x)
  1086. extern "C" void dTestDataStructures()
  1087. {
  1088. int i;
  1089. DO(printf ("testDynamicsStuff()\n"));
  1090. dBodyID body [NUM];
  1091. int nb = 0;
  1092. dJointID joint [NUM];
  1093. int nj = 0;
  1094. for (i=0; i<NUM; i++) body[i] = 0;
  1095. for (i=0; i<NUM; i++) joint[i] = 0;
  1096. DO(printf ("creating world\n"));
  1097. dWorldID w = dWorldCreate();
  1098. checkWorld (w);
  1099. for (;;) {
  1100. if (nb < NUM && dRandReal() > 0.5) {
  1101. DO(printf ("creating body\n"));
  1102. body[nb] = dBodyCreate (w);
  1103. DO(printf ("\t--> %p\n",body[nb]));
  1104. nb++;
  1105. checkWorld (w);
  1106. DO(printf ("%d BODIES, %d JOINTS\n",nb,nj));
  1107. }
  1108. if (nj < NUM && nb > 2 && dRandReal() > 0.5) {
  1109. dBodyID b1 = body [dRand() % nb];
  1110. dBodyID b2 = body [dRand() % nb];
  1111. if (b1 != b2) {
  1112. DO(printf ("creating joint, attaching to %p,%p\n",b1,b2));
  1113. joint[nj] = dJointCreateBall (w,0);
  1114. DO(printf ("\t-->%p\n",joint[nj]));
  1115. checkWorld (w);
  1116. dJointAttach (joint[nj],b1,b2);
  1117. nj++;
  1118. checkWorld (w);
  1119. DO(printf ("%d BODIES, %d JOINTS\n",nb,nj));
  1120. }
  1121. }
  1122. if (nj > 0 && nb > 2 && dRandReal() > 0.5) {
  1123. dBodyID b1 = body [dRand() % nb];
  1124. dBodyID b2 = body [dRand() % nb];
  1125. if (b1 != b2) {
  1126. int k = dRand() % nj;
  1127. DO(printf ("reattaching joint %p\n",joint[k]));
  1128. dJointAttach (joint[k],b1,b2);
  1129. checkWorld (w);
  1130. DO(printf ("%d BODIES, %d JOINTS\n",nb,nj));
  1131. }
  1132. }
  1133. if (nb > 0 && dRandReal() > 0.5) {
  1134. int k = dRand() % nb;
  1135. DO(printf ("destroying body %p\n",body[k]));
  1136. dBodyDestroy (body[k]);
  1137. checkWorld (w);
  1138. for (; k < (NUM-1); k++) body[k] = body[k+1];
  1139. nb--;
  1140. DO(printf ("%d BODIES, %d JOINTS\n",nb,nj));
  1141. }
  1142. if (nj > 0 && dRandReal() > 0.5) {
  1143. int k = dRand() % nj;
  1144. DO(printf ("destroying joint %p\n",joint[k]));
  1145. dJointDestroy (joint[k]);
  1146. checkWorld (w);
  1147. for (; k < (NUM-1); k++) joint[k] = joint[k+1];
  1148. nj--;
  1149. DO(printf ("%d BODIES, %d JOINTS\n",nb,nj));
  1150. }
  1151. }
  1152. /*
  1153. printf ("creating world\n");
  1154. dWorldID w = dWorldCreate();
  1155. checkWorld (w);
  1156. printf ("creating body\n");
  1157. dBodyID b1 = dBodyCreate (w);
  1158. checkWorld (w);
  1159. printf ("creating body\n");
  1160. dBodyID b2 = dBodyCreate (w);
  1161. checkWorld (w);
  1162. printf ("creating joint\n");
  1163. dJointID j = dJointCreateBall (w);
  1164. checkWorld (w);
  1165. printf ("attaching joint\n");
  1166. dJointAttach (j,b1,b2);
  1167. checkWorld (w);
  1168. printf ("destroying joint\n");
  1169. dJointDestroy (j);
  1170. checkWorld (w);
  1171. printf ("destroying body\n");
  1172. dBodyDestroy (b1);
  1173. checkWorld (w);
  1174. printf ("destroying body\n");
  1175. dBodyDestroy (b2);
  1176. checkWorld (w);
  1177. printf ("destroying world\n");
  1178. dWorldDestroy (w);
  1179. */
  1180. }