demo_boxstack.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670
  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. #include <ode/ode.h>
  23. #include <drawstuff/drawstuff.h>
  24. #include "texturepath.h"
  25. #ifdef _MSC_VER
  26. #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints
  27. #endif
  28. #include "icosahedron_geom.h"
  29. //<---- Convex Object
  30. dReal planes[]= // planes for a cube, these should coincide with the face array
  31. {
  32. 1.0f ,0.0f ,0.0f ,0.25f,
  33. 0.0f ,1.0f ,0.0f ,0.25f,
  34. 0.0f ,0.0f ,1.0f ,0.25f,
  35. -1.0f,0.0f ,0.0f ,0.25f,
  36. 0.0f ,-1.0f,0.0f ,0.25f,
  37. 0.0f ,0.0f ,-1.0f,0.25f
  38. /*
  39. 1.0f ,0.0f ,0.0f ,2.0f,
  40. 0.0f ,1.0f ,0.0f ,1.0f,
  41. 0.0f ,0.0f ,1.0f ,1.0f,
  42. 0.0f ,0.0f ,-1.0f,1.0f,
  43. 0.0f ,-1.0f,0.0f ,1.0f,
  44. -1.0f,0.0f ,0.0f ,0.0f
  45. */
  46. };
  47. const unsigned int planecount=6;
  48. dReal points[]= // points for a cube
  49. {
  50. 0.25f,0.25f,0.25f, // point 0
  51. -0.25f,0.25f,0.25f, // point 1
  52. 0.25f,-0.25f,0.25f, // point 2
  53. -0.25f,-0.25f,0.25f,// point 3
  54. 0.25f,0.25f,-0.25f, // point 4
  55. -0.25f,0.25f,-0.25f,// point 5
  56. 0.25f,-0.25f,-0.25f,// point 6
  57. -0.25f,-0.25f,-0.25f,// point 7
  58. };
  59. const unsigned int pointcount=8;
  60. unsigned int polygons[] = //Polygons for a cube (6 squares)
  61. {
  62. 4,0,2,6,4, // positive X
  63. 4,1,0,4,5, // positive Y
  64. 4,0,1,3,2, // positive Z
  65. 4,3,1,5,7, // negative X
  66. 4,2,3,7,6, // negative Y
  67. 4,5,4,6,7, // negative Z
  68. };
  69. //----> Convex Object
  70. // select correct drawing functions
  71. #ifdef dDOUBLE
  72. #define dsDrawBox dsDrawBoxD
  73. #define dsDrawSphere dsDrawSphereD
  74. #define dsDrawCylinder dsDrawCylinderD
  75. #define dsDrawCapsule dsDrawCapsuleD
  76. #define dsDrawConvex dsDrawConvexD
  77. #endif
  78. // some constants
  79. #define NUM 100 // max number of objects
  80. #define DENSITY (5.0) // density of all objects
  81. #define GPB 3 // maximum number of geometries per body
  82. #define MAX_CONTACTS 8 // maximum number of contact points per body
  83. #define MAX_FEEDBACKNUM 20
  84. #define GRAVITY REAL(0.5)
  85. #define USE_GEOM_OFFSET 1
  86. // dynamics and collision objects
  87. struct MyObject {
  88. dBodyID body; // the body
  89. dGeomID geom[GPB]; // geometries representing this body
  90. };
  91. static int num=0; // number of objects in simulation
  92. static int nextobj=0; // next object to recycle if num==NUM
  93. static dWorldID world;
  94. static dSpaceID space;
  95. static MyObject obj[NUM];
  96. static dJointGroupID contactgroup;
  97. static int selected = -1; // selected object
  98. static int show_aabb = 0; // show geom AABBs?
  99. static int show_contacts = 0; // show contact points?
  100. static int random_pos = 1; // drop objects from random position?
  101. static int write_world = 0;
  102. static int show_body = 0;
  103. struct MyFeedback {
  104. dJointFeedback fb;
  105. bool first;
  106. };
  107. static int doFeedback=0;
  108. static MyFeedback feedbacks[MAX_FEEDBACKNUM];
  109. static int fbnum=0;
  110. // this is called by dSpaceCollide when two objects in space are
  111. // potentially colliding.
  112. static void nearCallback (void *data, dGeomID o1, dGeomID o2)
  113. {
  114. int i;
  115. // if (o1->body && o2->body) return;
  116. // exit without doing anything if the two bodies are connected by a joint
  117. dBodyID b1 = dGeomGetBody(o1);
  118. dBodyID b2 = dGeomGetBody(o2);
  119. if (b1 && b2 && dAreConnectedExcluding (b1,b2,dJointTypeContact)) return;
  120. dContact contact[MAX_CONTACTS]; // up to MAX_CONTACTS contacts per box-box
  121. for (i=0; i<MAX_CONTACTS; i++) {
  122. contact[i].surface.mode = dContactBounce | dContactSoftCFM;
  123. contact[i].surface.mu = dInfinity;
  124. contact[i].surface.mu2 = 0;
  125. contact[i].surface.bounce = 0.1;
  126. contact[i].surface.bounce_vel = 0.1;
  127. contact[i].surface.soft_cfm = 0.01;
  128. }
  129. if (int numc = dCollide (o1,o2,MAX_CONTACTS,&contact[0].geom,
  130. sizeof(dContact))) {
  131. dMatrix3 RI;
  132. dRSetIdentity (RI);
  133. const dReal ss[3] = {0.02,0.02,0.02};
  134. for (i=0; i<numc; i++) {
  135. dJointID c = dJointCreateContact (world,contactgroup,contact+i);
  136. dJointAttach (c,b1,b2);
  137. if (show_contacts) dsDrawBox (contact[i].geom.pos,RI,ss);
  138. if (doFeedback && (b1==obj[selected].body || b2==obj[selected].body))
  139. {
  140. if (fbnum<MAX_FEEDBACKNUM)
  141. {
  142. feedbacks[fbnum].first = b1==obj[selected].body;
  143. dJointSetFeedback (c,&feedbacks[fbnum++].fb);
  144. }
  145. else fbnum++;
  146. }
  147. }
  148. }
  149. }
  150. // start simulation - set viewpoint
  151. static void start()
  152. {
  153. dAllocateODEDataForThread(dAllocateMaskAll);
  154. static float xyz[3] = {2.1640f,-1.3079f,1.7600f};
  155. static float hpr[3] = {125.5000f,-17.0000f,0.0000f};
  156. dsSetViewpoint (xyz,hpr);
  157. printf ("To drop another object, press:\n");
  158. printf (" b for box.\n");
  159. printf (" s for sphere.\n");
  160. printf (" c for capsule.\n");
  161. printf (" y for cylinder.\n");
  162. printf (" v for a convex object.\n");
  163. printf (" x for a composite object.\n");
  164. printf ("To select an object, press space.\n");
  165. printf ("To disable the selected object, press d.\n");
  166. printf ("To enable the selected object, press e.\n");
  167. printf ("To dump transformation data for the selected object, press p.\n");
  168. printf ("To toggle showing the geom AABBs, press a.\n");
  169. printf ("To toggle showing the contact points, press t.\n");
  170. printf ("To toggle dropping from random position/orientation, press r.\n");
  171. printf ("To save the current state to 'state.dif', press 1.\n");
  172. printf ("To show joint feedbacks of selected object, press f.\n");
  173. }
  174. char locase (char c)
  175. {
  176. if (c >= 'A' && c <= 'Z') return c - ('a'-'A');
  177. else return c;
  178. }
  179. // called when a key pressed
  180. static void command (int cmd)
  181. {
  182. size_t i;
  183. int j,k;
  184. dReal sides[3];
  185. dMass m;
  186. int setBody;
  187. cmd = locase (cmd);
  188. if (cmd == 'b' || cmd == 's' || cmd == 'c' || cmd == 'x' || cmd == 'y' || cmd == 'v')
  189. {
  190. setBody = 0;
  191. if (num < NUM) {
  192. i = num;
  193. num++;
  194. }
  195. else {
  196. i = nextobj;
  197. nextobj++;
  198. if (nextobj >= num) nextobj = 0;
  199. // destroy the body and geoms for slot i
  200. dBodyDestroy (obj[i].body);
  201. for (k=0; k < GPB; k++) {
  202. if (obj[i].geom[k]) dGeomDestroy (obj[i].geom[k]);
  203. }
  204. memset (&obj[i],0,sizeof(obj[i]));
  205. }
  206. obj[i].body = dBodyCreate (world);
  207. for (k=0; k<3; k++) sides[k] = dRandReal()*0.5+0.1;
  208. dMatrix3 R;
  209. if (random_pos)
  210. {
  211. dBodySetPosition (obj[i].body,
  212. dRandReal()*2-1,dRandReal()*2-1,dRandReal()+2);
  213. dRFromAxisAndAngle (R,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
  214. dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
  215. }
  216. else
  217. {
  218. dReal maxheight = 0;
  219. for (k=0; k<num; k++)
  220. {
  221. const dReal *pos = dBodyGetPosition (obj[k].body);
  222. if (pos[2] > maxheight) maxheight = pos[2];
  223. }
  224. dBodySetPosition (obj[i].body, 0,0,maxheight+1);
  225. dRSetIdentity (R);
  226. //dRFromAxisAndAngle (R,0,0,1,/*dRandReal()*10.0-5.0*/0);
  227. }
  228. dBodySetRotation (obj[i].body,R);
  229. dBodySetData (obj[i].body,(void*) i);
  230. if (cmd == 'b') {
  231. dMassSetBox (&m,DENSITY,sides[0],sides[1],sides[2]);
  232. obj[i].geom[0] = dCreateBox (space,sides[0],sides[1],sides[2]);
  233. }
  234. else if (cmd == 'c') {
  235. sides[0] *= 0.5;
  236. dMassSetCapsule (&m,DENSITY,3,sides[0],sides[1]);
  237. obj[i].geom[0] = dCreateCapsule (space,sides[0],sides[1]);
  238. }
  239. //<---- Convex Object
  240. else if (cmd == 'v')
  241. {
  242. dMassSetBox (&m,DENSITY,0.25,0.25,0.25);
  243. #if 0
  244. obj[i].geom[0] = dCreateConvex (space,
  245. planes,
  246. planecount,
  247. points,
  248. pointcount,
  249. polygons);
  250. #else
  251. obj[i].geom[0] = dCreateConvex (space,
  252. Sphere_planes,
  253. Sphere_planecount,
  254. Sphere_points,
  255. Sphere_pointcount,
  256. Sphere_polygons);
  257. #endif
  258. }
  259. //----> Convex Object
  260. else if (cmd == 'y') {
  261. dMassSetCylinder (&m,DENSITY,3,sides[0],sides[1]);
  262. obj[i].geom[0] = dCreateCylinder (space,sides[0],sides[1]);
  263. }
  264. else if (cmd == 's') {
  265. sides[0] *= 0.5;
  266. dMassSetSphere (&m,DENSITY,sides[0]);
  267. obj[i].geom[0] = dCreateSphere (space,sides[0]);
  268. }
  269. else if (cmd == 'x' && USE_GEOM_OFFSET) {
  270. setBody = 1;
  271. // start accumulating masses for the encapsulated geometries
  272. dMass m2;
  273. dMassSetZero (&m);
  274. dReal dpos[GPB][3]; // delta-positions for encapsulated geometries
  275. dMatrix3 drot[GPB];
  276. // set random delta positions
  277. for (j=0; j<GPB; j++) {
  278. for (k=0; k<3; k++) dpos[j][k] = dRandReal()*0.3-0.15;
  279. }
  280. for (k=0; k<GPB; k++) {
  281. if (k==0) {
  282. dReal radius = dRandReal()*0.25+0.05;
  283. obj[i].geom[k] = dCreateSphere (space,radius);
  284. dMassSetSphere (&m2,DENSITY,radius);
  285. }
  286. else if (k==1) {
  287. obj[i].geom[k] = dCreateBox (space,sides[0],sides[1],sides[2]);
  288. dMassSetBox (&m2,DENSITY,sides[0],sides[1],sides[2]);
  289. }
  290. else {
  291. dReal radius = dRandReal()*0.1+0.05;
  292. dReal length = dRandReal()*1.0+0.1;
  293. obj[i].geom[k] = dCreateCapsule (space,radius,length);
  294. dMassSetCapsule (&m2,DENSITY,3,radius,length);
  295. }
  296. dRFromAxisAndAngle (drot[k],dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
  297. dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
  298. dMassRotate (&m2,drot[k]);
  299. dMassTranslate (&m2,dpos[k][0],dpos[k][1],dpos[k][2]);
  300. // add to the total mass
  301. dMassAdd (&m,&m2);
  302. }
  303. for (k=0; k<GPB; k++) {
  304. dGeomSetBody (obj[i].geom[k],obj[i].body);
  305. dGeomSetOffsetPosition (obj[i].geom[k],
  306. dpos[k][0]-m.c[0],
  307. dpos[k][1]-m.c[1],
  308. dpos[k][2]-m.c[2]);
  309. dGeomSetOffsetRotation(obj[i].geom[k], drot[k]);
  310. }
  311. dMassTranslate (&m,-m.c[0],-m.c[1],-m.c[2]);
  312. dBodySetMass (obj[i].body,&m);
  313. }
  314. else if (cmd == 'x') {
  315. dGeomID g2[GPB]; // encapsulated geometries
  316. dReal dpos[GPB][3]; // delta-positions for encapsulated geometries
  317. // start accumulating masses for the encapsulated geometries
  318. dMass m2;
  319. dMassSetZero (&m);
  320. // set random delta positions
  321. for (j=0; j<GPB; j++) {
  322. for (k=0; k<3; k++) dpos[j][k] = dRandReal()*0.3-0.15;
  323. }
  324. for (k=0; k<GPB; k++) {
  325. obj[i].geom[k] = dCreateGeomTransform (space);
  326. dGeomTransformSetCleanup (obj[i].geom[k],1);
  327. if (k==0) {
  328. dReal radius = dRandReal()*0.25+0.05;
  329. g2[k] = dCreateSphere (0,radius);
  330. dMassSetSphere (&m2,DENSITY,radius);
  331. }
  332. else if (k==1) {
  333. g2[k] = dCreateBox (0,sides[0],sides[1],sides[2]);
  334. dMassSetBox (&m2,DENSITY,sides[0],sides[1],sides[2]);
  335. }
  336. else {
  337. dReal radius = dRandReal()*0.1+0.05;
  338. dReal length = dRandReal()*1.0+0.1;
  339. g2[k] = dCreateCapsule (0,radius,length);
  340. dMassSetCapsule (&m2,DENSITY,3,radius,length);
  341. }
  342. dGeomTransformSetGeom (obj[i].geom[k],g2[k]);
  343. // set the transformation (adjust the mass too)
  344. dGeomSetPosition (g2[k],dpos[k][0],dpos[k][1],dpos[k][2]);
  345. dMatrix3 Rtx;
  346. dRFromAxisAndAngle (Rtx,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
  347. dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
  348. dGeomSetRotation (g2[k],Rtx);
  349. dMassRotate (&m2,Rtx);
  350. // Translation *after* rotation
  351. dMassTranslate (&m2,dpos[k][0],dpos[k][1],dpos[k][2]);
  352. // add to the total mass
  353. dMassAdd (&m,&m2);
  354. }
  355. // move all encapsulated objects so that the center of mass is (0,0,0)
  356. for (k=0; k<GPB; k++) {
  357. dGeomSetPosition (g2[k],
  358. dpos[k][0]-m.c[0],
  359. dpos[k][1]-m.c[1],
  360. dpos[k][2]-m.c[2]);
  361. }
  362. dMassTranslate (&m,-m.c[0],-m.c[1],-m.c[2]);
  363. }
  364. if (!setBody)
  365. for (k=0; k < GPB; k++) {
  366. if (obj[i].geom[k]) dGeomSetBody (obj[i].geom[k],obj[i].body);
  367. }
  368. dBodySetMass (obj[i].body,&m);
  369. }
  370. if (cmd == ' ') {
  371. selected++;
  372. if (selected >= num) selected = 0;
  373. if (selected < 0) selected = 0;
  374. }
  375. else if (cmd == 'd' && selected >= 0 && selected < num) {
  376. dBodyDisable (obj[selected].body);
  377. }
  378. else if (cmd == 'e' && selected >= 0 && selected < num) {
  379. dBodyEnable (obj[selected].body);
  380. }
  381. else if (cmd == 'a') {
  382. show_aabb ^= 1;
  383. }
  384. else if (cmd == 't') {
  385. show_contacts ^= 1;
  386. }
  387. else if (cmd == 'r') {
  388. random_pos ^= 1;
  389. }
  390. else if (cmd == '1') {
  391. write_world = 1;
  392. }
  393. else if (cmd == 'p'&& selected >= 0)
  394. {
  395. const dReal* pos = dGeomGetPosition(obj[selected].geom[0]);
  396. const dReal* rot = dGeomGetRotation(obj[selected].geom[0]);
  397. printf("POSITION:\n\t[%f,%f,%f]\n\n",pos[0],pos[1],pos[2]);
  398. printf("ROTATION:\n\t[%f,%f,%f,%f]\n\t[%f,%f,%f,%f]\n\t[%f,%f,%f,%f]\n\n",
  399. rot[0],rot[1],rot[2],rot[3],
  400. rot[4],rot[5],rot[6],rot[7],
  401. rot[8],rot[9],rot[10],rot[11]);
  402. }
  403. else if (cmd == 'f' && selected >= 0 && selected < num) {
  404. if (dBodyIsEnabled(obj[selected].body))
  405. doFeedback = 1;
  406. }
  407. }
  408. // draw a geom
  409. void drawGeom (dGeomID g, const dReal *pos, const dReal *R, int show_aabb)
  410. {
  411. int i;
  412. if (!g) return;
  413. if (!pos) pos = dGeomGetPosition (g);
  414. if (!R) R = dGeomGetRotation (g);
  415. int type = dGeomGetClass (g);
  416. if (type == dBoxClass) {
  417. dVector3 sides;
  418. dGeomBoxGetLengths (g,sides);
  419. dsDrawBox (pos,R,sides);
  420. }
  421. else if (type == dSphereClass) {
  422. dsDrawSphere (pos,R,dGeomSphereGetRadius (g));
  423. }
  424. else if (type == dCapsuleClass) {
  425. dReal radius,length;
  426. dGeomCapsuleGetParams (g,&radius,&length);
  427. dsDrawCapsule (pos,R,length,radius);
  428. }
  429. //<---- Convex Object
  430. else if (type == dConvexClass)
  431. {
  432. #if 0
  433. dsDrawConvex(pos,R,planes,
  434. planecount,
  435. points,
  436. pointcount,
  437. polygons);
  438. #else
  439. dsDrawConvex(pos,R,
  440. Sphere_planes,
  441. Sphere_planecount,
  442. Sphere_points,
  443. Sphere_pointcount,
  444. Sphere_polygons);
  445. #endif
  446. }
  447. //----> Convex Object
  448. else if (type == dCylinderClass) {
  449. dReal radius,length;
  450. dGeomCylinderGetParams (g,&radius,&length);
  451. dsDrawCylinder (pos,R,length,radius);
  452. }
  453. else if (type == dGeomTransformClass) {
  454. dGeomID g2 = dGeomTransformGetGeom (g);
  455. const dReal *pos2 = dGeomGetPosition (g2);
  456. const dReal *R2 = dGeomGetRotation (g2);
  457. dVector3 actual_pos;
  458. dMatrix3 actual_R;
  459. dMultiply0_331 (actual_pos,R,pos2);
  460. actual_pos[0] += pos[0];
  461. actual_pos[1] += pos[1];
  462. actual_pos[2] += pos[2];
  463. dMultiply0_333 (actual_R,R,R2);
  464. drawGeom (g2,actual_pos,actual_R,0);
  465. }
  466. if (show_body) {
  467. dBodyID body = dGeomGetBody(g);
  468. if (body) {
  469. const dReal *bodypos = dBodyGetPosition (body);
  470. const dReal *bodyr = dBodyGetRotation (body);
  471. dReal bodySides[3] = { 0.1, 0.1, 0.1 };
  472. dsSetColorAlpha(0,1,0,1);
  473. dsDrawBox(bodypos,bodyr,bodySides);
  474. }
  475. }
  476. if (show_aabb) {
  477. // draw the bounding box for this geom
  478. dReal aabb[6];
  479. dGeomGetAABB (g,aabb);
  480. dVector3 bbpos;
  481. for (i=0; i<3; i++) bbpos[i] = 0.5*(aabb[i*2] + aabb[i*2+1]);
  482. dVector3 bbsides;
  483. for (i=0; i<3; i++) bbsides[i] = aabb[i*2+1] - aabb[i*2];
  484. dMatrix3 RI;
  485. dRSetIdentity (RI);
  486. dsSetColorAlpha (1,0,0,0.5);
  487. dsDrawBox (bbpos,RI,bbsides);
  488. }
  489. }
  490. // simulation loop
  491. static void simLoop (int pause)
  492. {
  493. dsSetColor (0,0,2);
  494. dSpaceCollide (space,0,&nearCallback);
  495. if (!pause) dWorldQuickStep (world,0.02);
  496. if (write_world) {
  497. FILE *f = fopen ("state.dif","wt");
  498. if (f) {
  499. dWorldExportDIF (world,f,"X");
  500. fclose (f);
  501. }
  502. write_world = 0;
  503. }
  504. if (doFeedback)
  505. {
  506. if (fbnum>MAX_FEEDBACKNUM)
  507. printf("joint feedback buffer overflow!\n");
  508. else
  509. {
  510. dVector3 sum = {0, 0, 0};
  511. printf("\n");
  512. for (int i=0; i<fbnum; i++) {
  513. dReal* f = feedbacks[i].first?feedbacks[i].fb.f1:feedbacks[i].fb.f2;
  514. printf("%f %f %f\n", f[0], f[1], f[2]);
  515. sum[0] += f[0];
  516. sum[1] += f[1];
  517. sum[2] += f[2];
  518. }
  519. printf("Sum: %f %f %f\n", sum[0], sum[1], sum[2]);
  520. dMass m;
  521. dBodyGetMass(obj[selected].body, &m);
  522. printf("Object G=%f\n", GRAVITY*m.mass);
  523. }
  524. doFeedback = 0;
  525. fbnum = 0;
  526. }
  527. // remove all contact joints
  528. dJointGroupEmpty (contactgroup);
  529. dsSetColor (1,1,0);
  530. dsSetTexture (DS_WOOD);
  531. for (int i=0; i<num; i++) {
  532. for (int j=0; j < GPB; j++) {
  533. if (i==selected) {
  534. dsSetColor (0,0.7,1);
  535. }
  536. else if (! dBodyIsEnabled (obj[i].body)) {
  537. dsSetColor (1,0.8,0);
  538. }
  539. else {
  540. dsSetColor (1,1,0);
  541. }
  542. drawGeom (obj[i].geom[j],0,0,show_aabb);
  543. }
  544. }
  545. }
  546. int main (int argc, char **argv)
  547. {
  548. // setup pointers to drawstuff callback functions
  549. dsFunctions fn;
  550. fn.version = DS_VERSION;
  551. fn.start = &start;
  552. fn.step = &simLoop;
  553. fn.command = &command;
  554. fn.stop = 0;
  555. fn.path_to_textures = DRAWSTUFF_TEXTURE_PATH;
  556. // create world
  557. dInitODE2(0);
  558. world = dWorldCreate();
  559. space = dHashSpaceCreate (0);
  560. contactgroup = dJointGroupCreate (0);
  561. dWorldSetGravity (world,0,0,-GRAVITY);
  562. dWorldSetCFM (world,1e-5);
  563. dWorldSetAutoDisableFlag (world,1);
  564. #if 1
  565. dWorldSetAutoDisableAverageSamplesCount( world, 10 );
  566. #endif
  567. dWorldSetLinearDamping(world, 0.00001);
  568. dWorldSetAngularDamping(world, 0.005);
  569. dWorldSetMaxAngularSpeed(world, 200);
  570. dWorldSetContactMaxCorrectingVel (world,0.1);
  571. dWorldSetContactSurfaceLayer (world,0.001);
  572. dCreatePlane (space,0,0,1,0);
  573. memset (obj,0,sizeof(obj));
  574. dThreadingImplementationID threading = dThreadingAllocateMultiThreadedImplementation();
  575. dThreadingThreadPoolID pool = dThreadingAllocateThreadPool(4, 0, dAllocateFlagBasicData, NULL);
  576. dThreadingThreadPoolServeMultiThreadedImplementation(pool, threading);
  577. // dWorldSetStepIslandsProcessingMaxThreadCount(world, 1);
  578. dWorldSetStepThreadingImplementation(world, dThreadingImplementationGetFunctions(threading), threading);
  579. // run simulation
  580. dsSimulationLoop (argc,argv,352,288,&fn);
  581. dThreadingImplementationShutdownProcessing(threading);
  582. dThreadingFreeThreadPool(pool);
  583. dWorldSetStepThreadingImplementation(world, NULL, NULL);
  584. dThreadingFreeImplementation(threading);
  585. dJointGroupDestroy (contactgroup);
  586. dSpaceDestroy (space);
  587. dWorldDestroy (world);
  588. dCloseODE();
  589. return 0;
  590. }