demo_crash.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642
  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. // This is a demo of the QuickStep and StepFast methods,
  23. // originally by David Whittaker.
  24. #include <ode/ode.h>
  25. #include <drawstuff/drawstuff.h>
  26. #include "texturepath.h"
  27. #ifdef _MSC_VER
  28. #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints
  29. #endif
  30. // select correct drawing functions
  31. #ifdef dDOUBLE
  32. #define dsDrawBox dsDrawBoxD
  33. #define dsDrawSphere dsDrawSphereD
  34. #define dsDrawCylinder dsDrawCylinderD
  35. #define dsDrawCapsule dsDrawCapsuleD
  36. #endif
  37. // some constants
  38. #define LENGTH 3.5 // chassis length
  39. #define WIDTH 2.5 // chassis width
  40. #define HEIGHT 1.0 // chassis height
  41. #define RADIUS 0.5 // wheel radius
  42. #define STARTZ 1.0 // starting height of chassis
  43. #define CMASS 1 // chassis mass
  44. #define WMASS 1 // wheel mass
  45. #define COMOFFSET -5 // center of mass offset
  46. #define WALLMASS 1 // wall box mass
  47. #define BALLMASS 1 // ball mass
  48. #define FMAX 25 // car engine fmax
  49. #define ROWS 1 // rows of cars
  50. #define COLS 1 // columns of cars
  51. #define ITERS 20 // number of iterations
  52. #define WBOXSIZE 1.0 // size of wall boxes
  53. #define WALLWIDTH 12 // width of wall
  54. #define WALLHEIGHT 10 // height of wall
  55. #define DISABLE_THRESHOLD 0.008 // maximum velocity (squared) a body can have and be disabled
  56. #define DISABLE_STEPS 10 // number of steps a box has to have been disable-able before it will be disabled
  57. #define CANNON_X -10 // x position of cannon
  58. #define CANNON_Y 5 // y position of cannon
  59. #define CANNON_BALL_MASS 10 // mass of the cannon ball
  60. #define CANNON_BALL_RADIUS 0.5
  61. //#define BOX
  62. #define CARS
  63. #define WALL
  64. //#define BALLS
  65. //#define BALLSTACK
  66. //#define ONEBALL
  67. //#define CENTIPEDE
  68. #define CANNON
  69. // dynamics and collision objects (chassis, 3 wheels, environment)
  70. static dWorldID world;
  71. static dSpaceID space;
  72. static dThreadingImplementationID threading;
  73. static dThreadingThreadPoolID pool;
  74. static dBodyID body[10000];
  75. static int bodies;
  76. static dJointID joint[100000];
  77. static int joints;
  78. static dJointGroupID contactgroup;
  79. static dGeomID ground;
  80. static dGeomID box[10000];
  81. static int boxes;
  82. static dGeomID sphere[10000];
  83. static int spheres;
  84. static dGeomID wall_boxes[10000];
  85. static dBodyID wall_bodies[10000];
  86. static dGeomID cannon_ball_geom;
  87. static dBodyID cannon_ball_body;
  88. static int wb_stepsdis[10000];
  89. static int wb;
  90. static bool doFast;
  91. static dBodyID b;
  92. static dMass m;
  93. // things that the user controls
  94. static dReal turn = 0, speed = 0; // user commands
  95. static dReal cannon_angle=0,cannon_elevation=-1.2;
  96. // this is called by dSpaceCollide when two objects in space are
  97. // potentially colliding.
  98. static void nearCallback (void *data, dGeomID o1, dGeomID o2)
  99. {
  100. int i,n;
  101. dBodyID b1 = dGeomGetBody(o1);
  102. dBodyID b2 = dGeomGetBody(o2);
  103. if (b1 && b2 && dAreConnected(b1, b2))
  104. return;
  105. const int N = 4;
  106. dContact contact[N];
  107. n = dCollide (o1,o2,N,&contact[0].geom,sizeof(dContact));
  108. if (n > 0) {
  109. for (i=0; i<n; i++) {
  110. contact[i].surface.mode = dContactSlip1 | dContactSlip2 | dContactSoftERP | dContactSoftCFM | dContactApprox1;
  111. if (dGeomGetClass(o1) == dSphereClass || dGeomGetClass(o2) == dSphereClass)
  112. contact[i].surface.mu = 20;
  113. else
  114. contact[i].surface.mu = 0.5;
  115. contact[i].surface.slip1 = 0.0;
  116. contact[i].surface.slip2 = 0.0;
  117. contact[i].surface.soft_erp = 0.8;
  118. contact[i].surface.soft_cfm = 0.01;
  119. dJointID c = dJointCreateContact (world,contactgroup,contact+i);
  120. dJointAttach (c,dGeomGetBody(o1),dGeomGetBody(o2));
  121. }
  122. }
  123. }
  124. // start simulation - set viewpoint
  125. static void start()
  126. {
  127. dAllocateODEDataForThread(dAllocateMaskAll);
  128. static float xyz[3] = {3.8548f,9.0843f,7.5900f};
  129. static float hpr[3] = {-145.5f,-22.5f,0.25f};
  130. dsSetViewpoint (xyz,hpr);
  131. printf ("Press:\t'a' to increase speed.\n"
  132. "\t'z' to decrease speed.\n"
  133. "\t',' to steer left.\n"
  134. "\t'.' to steer right.\n"
  135. "\t' ' to reset speed and steering.\n"
  136. "\t'[' to turn the cannon left.\n"
  137. "\t']' to turn the cannon right.\n"
  138. "\t'1' to raise the cannon.\n"
  139. "\t'2' to lower the cannon.\n"
  140. "\t'x' to shoot from the cannon.\n"
  141. "\t'f' to toggle fast step mode.\n"
  142. "\t'r' to reset simulation.\n");
  143. }
  144. void makeCar(dReal x, dReal y, int &bodyI, int &jointI, int &boxI, int &sphereI)
  145. {
  146. int i;
  147. dMass m;
  148. // chassis body
  149. body[bodyI] = dBodyCreate (world);
  150. dBodySetPosition (body[bodyI],x,y,STARTZ);
  151. dMassSetBox (&m,1,LENGTH,WIDTH,HEIGHT);
  152. dMassAdjust (&m,CMASS/2.0);
  153. dBodySetMass (body[bodyI],&m);
  154. box[boxI] = dCreateBox (space,LENGTH,WIDTH,HEIGHT);
  155. dGeomSetBody (box[boxI],body[bodyI]);
  156. // wheel bodies
  157. for (i=1; i<=4; i++) {
  158. body[bodyI+i] = dBodyCreate (world);
  159. dQuaternion q;
  160. dQFromAxisAndAngle (q,1,0,0,M_PI*0.5);
  161. dBodySetQuaternion (body[bodyI+i],q);
  162. dMassSetSphere (&m,1,RADIUS);
  163. dMassAdjust (&m,WMASS);
  164. dBodySetMass (body[bodyI+i],&m);
  165. sphere[sphereI+i-1] = dCreateSphere (space,RADIUS);
  166. dGeomSetBody (sphere[sphereI+i-1],body[bodyI+i]);
  167. }
  168. dBodySetPosition (body[bodyI+1],x+0.4*LENGTH-0.5*RADIUS,y+WIDTH*0.5,STARTZ-HEIGHT*0.5);
  169. dBodySetPosition (body[bodyI+2],x+0.4*LENGTH-0.5*RADIUS,y-WIDTH*0.5,STARTZ-HEIGHT*0.5);
  170. dBodySetPosition (body[bodyI+3],x-0.4*LENGTH+0.5*RADIUS,y+WIDTH*0.5,STARTZ-HEIGHT*0.5);
  171. dBodySetPosition (body[bodyI+4],x-0.4*LENGTH+0.5*RADIUS,y-WIDTH*0.5,STARTZ-HEIGHT*0.5);
  172. // front and back wheel hinges
  173. for (i=0; i<4; i++) {
  174. joint[jointI+i] = dJointCreateHinge2 (world,0);
  175. dJointAttach (joint[jointI+i],body[bodyI],body[bodyI+i+1]);
  176. const dReal *a = dBodyGetPosition (body[bodyI+i+1]);
  177. dJointSetHinge2Anchor (joint[jointI+i],a[0],a[1],a[2]);
  178. dJointSetHinge2Axis1 (joint[jointI+i],0,0,(i<2 ? 1 : -1));
  179. dJointSetHinge2Axis2 (joint[jointI+i],0,1,0);
  180. dJointSetHinge2Param (joint[jointI+i],dParamSuspensionERP,0.8);
  181. dJointSetHinge2Param (joint[jointI+i],dParamSuspensionCFM,1e-5);
  182. dJointSetHinge2Param (joint[jointI+i],dParamVel2,0);
  183. dJointSetHinge2Param (joint[jointI+i],dParamFMax2,FMAX);
  184. }
  185. //center of mass offset body. (hang another copy of the body COMOFFSET units below it by a fixed joint)
  186. dBodyID b = dBodyCreate (world);
  187. dBodySetPosition (b,x,y,STARTZ+COMOFFSET);
  188. dMassSetBox (&m,1,LENGTH,WIDTH,HEIGHT);
  189. dMassAdjust (&m,CMASS/2.0);
  190. dBodySetMass (b,&m);
  191. dJointID j = dJointCreateFixed(world, 0);
  192. dJointAttach(j, body[bodyI], b);
  193. dJointSetFixed(j);
  194. //box[boxI+1] = dCreateBox(space,LENGTH,WIDTH,HEIGHT);
  195. //dGeomSetBody (box[boxI+1],b);
  196. bodyI += 5;
  197. jointI += 4;
  198. boxI += 1;
  199. sphereI += 4;
  200. }
  201. static
  202. void shutdownSimulation()
  203. {
  204. // destroy world if it exists
  205. if (bodies)
  206. {
  207. dThreadingImplementationShutdownProcessing(threading);
  208. dThreadingFreeThreadPool(pool);
  209. dWorldSetStepThreadingImplementation(world, NULL, NULL);
  210. dThreadingFreeImplementation(threading);
  211. dJointGroupDestroy (contactgroup);
  212. dSpaceDestroy (space);
  213. dWorldDestroy (world);
  214. bodies = 0;
  215. }
  216. }
  217. static
  218. void setupSimulation()
  219. {
  220. int i;
  221. for (i = 0; i < 1000; i++)
  222. wb_stepsdis[i] = 0;
  223. // recreate world
  224. world = dWorldCreate();
  225. // space = dHashSpaceCreate( 0 );
  226. // space = dSimpleSpaceCreate( 0 );
  227. space = dSweepAndPruneSpaceCreate( 0, dSAP_AXES_XYZ );
  228. contactgroup = dJointGroupCreate (0);
  229. dWorldSetGravity (world,0,0,-1.5);
  230. dWorldSetCFM (world, 1e-5);
  231. dWorldSetERP (world, 0.8);
  232. dWorldSetQuickStepNumIterations (world,ITERS);
  233. threading = dThreadingAllocateMultiThreadedImplementation();
  234. pool = dThreadingAllocateThreadPool(4, 0, dAllocateFlagBasicData, NULL);
  235. dThreadingThreadPoolServeMultiThreadedImplementation(pool, threading);
  236. // dWorldSetStepIslandsProcessingMaxThreadCount(world, 1);
  237. dWorldSetStepThreadingImplementation(world, dThreadingImplementationGetFunctions(threading), threading);
  238. ground = dCreatePlane (space,0,0,1,0);
  239. bodies = 0;
  240. joints = 0;
  241. boxes = 0;
  242. spheres = 0;
  243. wb = 0;
  244. #ifdef CARS
  245. for (dReal x = 0.0; x < COLS*(LENGTH+RADIUS); x += LENGTH+RADIUS)
  246. for (dReal y = -((ROWS-1)*(WIDTH/2+RADIUS)); y <= ((ROWS-1)*(WIDTH/2+RADIUS)); y += WIDTH+RADIUS*2)
  247. makeCar(x, y, bodies, joints, boxes, spheres);
  248. #endif
  249. #ifdef WALL
  250. bool offset = false;
  251. for (dReal z = WBOXSIZE/2.0; z <= WALLHEIGHT; z+=WBOXSIZE)
  252. {
  253. offset = !offset;
  254. for (dReal y = (-WALLWIDTH+z)/2; y <= (WALLWIDTH-z)/2; y+=WBOXSIZE)
  255. {
  256. wall_bodies[wb] = dBodyCreate (world);
  257. dBodySetPosition (wall_bodies[wb],-20,y,z);
  258. dMassSetBox (&m,1,WBOXSIZE,WBOXSIZE,WBOXSIZE);
  259. dMassAdjust (&m, WALLMASS);
  260. dBodySetMass (wall_bodies[wb],&m);
  261. wall_boxes[wb] = dCreateBox (space,WBOXSIZE,WBOXSIZE,WBOXSIZE);
  262. dGeomSetBody (wall_boxes[wb],wall_bodies[wb]);
  263. //dBodyDisable(wall_bodies[wb++]);
  264. wb++;
  265. }
  266. }
  267. dMessage(0,"wall boxes: %i", wb);
  268. #endif
  269. #ifdef BALLS
  270. for (dReal x = -7; x <= -4; x+=1)
  271. for (dReal y = -1.5; y <= 1.5; y+=1)
  272. for (dReal z = 1; z <= 4; z+=1)
  273. {
  274. b = dBodyCreate (world);
  275. dBodySetPosition (b,x*RADIUS*2,y*RADIUS*2,z*RADIUS*2);
  276. dMassSetSphere (&m,1,RADIUS);
  277. dMassAdjust (&m, BALLMASS);
  278. dBodySetMass (b,&m);
  279. sphere[spheres] = dCreateSphere (space,RADIUS);
  280. dGeomSetBody (sphere[spheres++],b);
  281. }
  282. #endif
  283. #ifdef ONEBALL
  284. b = dBodyCreate (world);
  285. dBodySetPosition (b,0,0,2);
  286. dMassSetSphere (&m,1,RADIUS);
  287. dMassAdjust (&m, 1);
  288. dBodySetMass (b,&m);
  289. sphere[spheres] = dCreateSphere (space,RADIUS);
  290. dGeomSetBody (sphere[spheres++],b);
  291. #endif
  292. #ifdef BALLSTACK
  293. for (dReal z = 1; z <= 6; z+=1)
  294. {
  295. b = dBodyCreate (world);
  296. dBodySetPosition (b,0,0,z*RADIUS*2);
  297. dMassSetSphere (&m,1,RADIUS);
  298. dMassAdjust (&m, 0.1);
  299. dBodySetMass (b,&m);
  300. sphere[spheres] = dCreateSphere (space,RADIUS);
  301. dGeomSetBody (sphere[spheres++],b);
  302. }
  303. #endif
  304. #ifdef CENTIPEDE
  305. dBodyID lastb = 0;
  306. for (dReal y = 0; y < 10*LENGTH; y+=LENGTH+0.1)
  307. {
  308. // chassis body
  309. b = body[bodies] = dBodyCreate (world);
  310. dBodySetPosition (body[bodies],-15,y,STARTZ);
  311. dMassSetBox (&m,1,WIDTH,LENGTH,HEIGHT);
  312. dMassAdjust (&m,CMASS);
  313. dBodySetMass (body[bodies],&m);
  314. box[boxes] = dCreateBox (space,WIDTH,LENGTH,HEIGHT);
  315. dGeomSetBody (box[boxes++],body[bodies++]);
  316. for (dReal x = -17; x > -20; x-=RADIUS*2)
  317. {
  318. body[bodies] = dBodyCreate (world);
  319. dBodySetPosition(body[bodies], x, y, STARTZ);
  320. dMassSetSphere(&m, 1, RADIUS);
  321. dMassAdjust(&m, WMASS);
  322. dBodySetMass(body[bodies], &m);
  323. sphere[spheres] = dCreateSphere (space, RADIUS);
  324. dGeomSetBody (sphere[spheres++], body[bodies]);
  325. joint[joints] = dJointCreateHinge2 (world,0);
  326. if (x == -17)
  327. dJointAttach (joint[joints],b,body[bodies]);
  328. else
  329. dJointAttach (joint[joints],body[bodies-2],body[bodies]);
  330. const dReal *a = dBodyGetPosition (body[bodies++]);
  331. dJointSetHinge2Anchor (joint[joints],a[0],a[1],a[2]);
  332. dJointSetHinge2Axis1 (joint[joints],0,0,1);
  333. dJointSetHinge2Axis2 (joint[joints],1,0,0);
  334. dJointSetHinge2Param (joint[joints],dParamSuspensionERP,1.0);
  335. dJointSetHinge2Param (joint[joints],dParamSuspensionCFM,1e-5);
  336. dJointSetHinge2Param (joint[joints],dParamLoStop,0);
  337. dJointSetHinge2Param (joint[joints],dParamHiStop,0);
  338. dJointSetHinge2Param (joint[joints],dParamVel2,-10.0);
  339. dJointSetHinge2Param (joint[joints++],dParamFMax2,FMAX);
  340. body[bodies] = dBodyCreate (world);
  341. dBodySetPosition(body[bodies], -30 - x, y, STARTZ);
  342. dMassSetSphere(&m, 1, RADIUS);
  343. dMassAdjust(&m, WMASS);
  344. dBodySetMass(body[bodies], &m);
  345. sphere[spheres] = dCreateSphere (space, RADIUS);
  346. dGeomSetBody (sphere[spheres++], body[bodies]);
  347. joint[joints] = dJointCreateHinge2 (world,0);
  348. if (x == -17)
  349. dJointAttach (joint[joints],b,body[bodies]);
  350. else
  351. dJointAttach (joint[joints],body[bodies-2],body[bodies]);
  352. const dReal *b = dBodyGetPosition (body[bodies++]);
  353. dJointSetHinge2Anchor (joint[joints],b[0],b[1],b[2]);
  354. dJointSetHinge2Axis1 (joint[joints],0,0,1);
  355. dJointSetHinge2Axis2 (joint[joints],1,0,0);
  356. dJointSetHinge2Param (joint[joints],dParamSuspensionERP,1.0);
  357. dJointSetHinge2Param (joint[joints],dParamSuspensionCFM,1e-5);
  358. dJointSetHinge2Param (joint[joints],dParamLoStop,0);
  359. dJointSetHinge2Param (joint[joints],dParamHiStop,0);
  360. dJointSetHinge2Param (joint[joints],dParamVel2,10.0);
  361. dJointSetHinge2Param (joint[joints++],dParamFMax2,FMAX);
  362. }
  363. if (lastb)
  364. {
  365. dJointID j = dJointCreateFixed(world,0);
  366. dJointAttach (j, b, lastb);
  367. dJointSetFixed(j);
  368. }
  369. lastb = b;
  370. }
  371. #endif
  372. #ifdef BOX
  373. body[bodies] = dBodyCreate (world);
  374. dBodySetPosition (body[bodies],0,0,HEIGHT/2);
  375. dMassSetBox (&m,1,LENGTH,WIDTH,HEIGHT);
  376. dMassAdjust (&m, 1);
  377. dBodySetMass (body[bodies],&m);
  378. box[boxes] = dCreateBox (space,LENGTH,WIDTH,HEIGHT);
  379. dGeomSetBody (box[boxes++],body[bodies++]);
  380. #endif
  381. #ifdef CANNON
  382. cannon_ball_body = dBodyCreate (world);
  383. cannon_ball_geom = dCreateSphere (space,CANNON_BALL_RADIUS);
  384. dMassSetSphereTotal (&m,CANNON_BALL_MASS,CANNON_BALL_RADIUS);
  385. dBodySetMass (cannon_ball_body,&m);
  386. dGeomSetBody (cannon_ball_geom,cannon_ball_body);
  387. dBodySetPosition (cannon_ball_body,CANNON_X,CANNON_Y,CANNON_BALL_RADIUS);
  388. #endif
  389. }
  390. // called when a key pressed
  391. static void command (int cmd)
  392. {
  393. switch (cmd) {
  394. case 'a': case 'A':
  395. speed += 0.3;
  396. break;
  397. case 'z': case 'Z':
  398. speed -= 0.3;
  399. break;
  400. case ',':
  401. turn += 0.1;
  402. if (turn > 0.3)
  403. turn = 0.3;
  404. break;
  405. case '.':
  406. turn -= 0.1;
  407. if (turn < -0.3)
  408. turn = -0.3;
  409. break;
  410. case ' ':
  411. speed = 0;
  412. turn = 0;
  413. break;
  414. case 'f': case 'F':
  415. doFast = !doFast;
  416. break;
  417. case 'r': case 'R':
  418. shutdownSimulation();
  419. setupSimulation();
  420. break;
  421. case '[':
  422. cannon_angle += 0.1;
  423. break;
  424. case ']':
  425. cannon_angle -= 0.1;
  426. break;
  427. case '1':
  428. cannon_elevation += 0.1;
  429. break;
  430. case '2':
  431. cannon_elevation -= 0.1;
  432. break;
  433. case 'x': case 'X': {
  434. dMatrix3 R2,R3,R4;
  435. dRFromAxisAndAngle (R2,0,0,1,cannon_angle);
  436. dRFromAxisAndAngle (R3,0,1,0,cannon_elevation);
  437. dMultiply0 (R4,R2,R3,3,3,3);
  438. dReal cpos[3] = {CANNON_X,CANNON_Y,1};
  439. for (int i=0; i<3; i++) cpos[i] += 3*R4[i*4+2];
  440. dBodySetPosition (cannon_ball_body,cpos[0],cpos[1],cpos[2]);
  441. dReal force = 10;
  442. dBodySetLinearVel (cannon_ball_body,force*R4[2],force*R4[6],force*R4[10]);
  443. dBodySetAngularVel (cannon_ball_body,0,0,0);
  444. break;
  445. }
  446. }
  447. }
  448. // simulation loop
  449. static void simLoop (int pause)
  450. {
  451. int i, j;
  452. dsSetTexture (DS_WOOD);
  453. if (!pause) {
  454. #ifdef BOX
  455. dBodyAddForce(body[bodies-1],lspeed,0,0);
  456. #endif
  457. for (j = 0; j < joints; j++)
  458. {
  459. dReal curturn = dJointGetHinge2Angle1 (joint[j]);
  460. //dMessage (0,"curturn %e, turn %e, vel %e", curturn, turn, (turn-curturn)*1.0);
  461. dJointSetHinge2Param(joint[j],dParamVel,(turn-curturn)*1.0);
  462. dJointSetHinge2Param(joint[j],dParamFMax,dInfinity);
  463. dJointSetHinge2Param(joint[j],dParamVel2,speed);
  464. dJointSetHinge2Param(joint[j],dParamFMax2,FMAX);
  465. dBodyEnable(dJointGetBody(joint[j],0));
  466. dBodyEnable(dJointGetBody(joint[j],1));
  467. }
  468. if (doFast)
  469. {
  470. dSpaceCollide (space,0,&nearCallback);
  471. dWorldQuickStep (world,0.05);
  472. dJointGroupEmpty (contactgroup);
  473. }
  474. else
  475. {
  476. dSpaceCollide (space,0,&nearCallback);
  477. dWorldStep (world,0.05);
  478. dJointGroupEmpty (contactgroup);
  479. }
  480. for (i = 0; i < wb; i++)
  481. {
  482. b = dGeomGetBody(wall_boxes[i]);
  483. if (dBodyIsEnabled(b))
  484. {
  485. bool disable = true;
  486. const dReal *lvel = dBodyGetLinearVel(b);
  487. dReal lspeed = lvel[0]*lvel[0]+lvel[1]*lvel[1]+lvel[2]*lvel[2];
  488. if (lspeed > DISABLE_THRESHOLD)
  489. disable = false;
  490. const dReal *avel = dBodyGetAngularVel(b);
  491. dReal aspeed = avel[0]*avel[0]+avel[1]*avel[1]+avel[2]*avel[2];
  492. if (aspeed > DISABLE_THRESHOLD)
  493. disable = false;
  494. if (disable)
  495. wb_stepsdis[i]++;
  496. else
  497. wb_stepsdis[i] = 0;
  498. if (wb_stepsdis[i] > DISABLE_STEPS)
  499. {
  500. dBodyDisable(b);
  501. dsSetColor(0.5,0.5,1);
  502. }
  503. else
  504. dsSetColor(1,1,1);
  505. }
  506. else
  507. dsSetColor(0.4,0.4,0.4);
  508. dVector3 ss;
  509. dGeomBoxGetLengths (wall_boxes[i], ss);
  510. dsDrawBox(dGeomGetPosition(wall_boxes[i]), dGeomGetRotation(wall_boxes[i]), ss);
  511. }
  512. }
  513. else
  514. {
  515. for (i = 0; i < wb; i++)
  516. {
  517. b = dGeomGetBody(wall_boxes[i]);
  518. if (dBodyIsEnabled(b))
  519. dsSetColor(1,1,1);
  520. else
  521. dsSetColor(0.4,0.4,0.4);
  522. dVector3 ss;
  523. dGeomBoxGetLengths (wall_boxes[i], ss);
  524. dsDrawBox(dGeomGetPosition(wall_boxes[i]), dGeomGetRotation(wall_boxes[i]), ss);
  525. }
  526. }
  527. dsSetColor (0,1,1);
  528. dReal sides[3] = {LENGTH,WIDTH,HEIGHT};
  529. for (i = 0; i < boxes; i++)
  530. dsDrawBox (dGeomGetPosition(box[i]),dGeomGetRotation(box[i]),sides);
  531. dsSetColor (1,1,1);
  532. for (i=0; i< spheres; i++) dsDrawSphere (dGeomGetPosition(sphere[i]),
  533. dGeomGetRotation(sphere[i]),RADIUS);
  534. // draw the cannon
  535. dsSetColor (1,1,0);
  536. dMatrix3 R2,R3,R4;
  537. dRFromAxisAndAngle (R2,0,0,1,cannon_angle);
  538. dRFromAxisAndAngle (R3,0,1,0,cannon_elevation);
  539. dMultiply0 (R4,R2,R3,3,3,3);
  540. dReal cpos[3] = {CANNON_X,CANNON_Y,1};
  541. dReal csides[3] = {2,2,2};
  542. dsDrawBox (cpos,R2,csides);
  543. for (i=0; i<3; i++) cpos[i] += 1.5*R4[i*4+2];
  544. dsDrawCylinder (cpos,R4,3,0.5);
  545. // draw the cannon ball
  546. dsDrawSphere (dBodyGetPosition(cannon_ball_body),dBodyGetRotation(cannon_ball_body),
  547. CANNON_BALL_RADIUS);
  548. }
  549. int main (int argc, char **argv)
  550. {
  551. doFast = true;
  552. // setup pointers to drawstuff callback functions
  553. dsFunctions fn;
  554. fn.version = DS_VERSION;
  555. fn.start = &start;
  556. fn.step = &simLoop;
  557. fn.command = &command;
  558. fn.stop = 0;
  559. fn.path_to_textures = DRAWSTUFF_TEXTURE_PATH;
  560. dInitODE2(0);
  561. bodies = 0;
  562. joints = 0;
  563. boxes = 0;
  564. spheres = 0;
  565. setupSimulation();
  566. // run simulation
  567. dsSimulationLoop (argc,argv,352,288,&fn);
  568. shutdownSimulation();
  569. dCloseODE();
  570. return 0;
  571. }