test_boxstackb.cpp 14 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375
  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. #ifdef _MSC_VER
  25. #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints
  26. #endif
  27. // select correct drawing functions
  28. #ifdef dDOUBLE
  29. #define dsDrawBox dsDrawBoxD
  30. #define dsDrawSphere dsDrawSphereD
  31. #define dsDrawCylinder dsDrawCylinderD
  32. #define dsDrawCappedCylinder dsDrawCappedCylinderD
  33. #endif
  34. // some constants
  35. const dReal vTerrainLength = 4.f;
  36. const dReal vTerrainHeight = 0.5f;
  37. const int TERRAINNODES = 4;
  38. dReal pTerrainHeights[TERRAINNODES*TERRAINNODES];
  39. dGeomID terrainZ = NULL;
  40. dGeomID terrainY = NULL;
  41. #define NUM 20 // max number of objects
  42. #define DENSITY (5.0) // density of all objects
  43. #define GPB 3 // maximum number of geometries per body
  44. #define MAX_CONTACTS 4 // maximum number of contact points per body
  45. // dynamics and collision objects
  46. struct MyObject {
  47. dBodyID body; // the body
  48. dGeomID geom[GPB]; // geometries representing this body
  49. };
  50. static int num=0; // number of objects in simulation
  51. static int nextobj=0; // next object to recycle if num==NUM
  52. static dWorldID world;
  53. static dSpaceID space;
  54. static MyObject obj[NUM];
  55. static dJointGroupID contactgroup;
  56. static int selected = -1; // selected object
  57. static int show_aabb = 0; // show geom AABBs?
  58. static int show_contacts = 0; // show contact points?
  59. static int random_pos = 1; // drop objects from random position?
  60. // this is called by dSpaceCollide when two objects in space are
  61. // potentially colliding.
  62. static void nearCallback (void *data, dGeomID o1, dGeomID o2)
  63. {
  64. int i;
  65. // if (o1->body && o2->body) return;
  66. // exit without doing anything if the two bodies are connected by a joint
  67. dBodyID b1 = dGeomGetBody(o1);
  68. dBodyID b2 = dGeomGetBody(o2);
  69. if (b1 && b2 && dAreConnectedExcluding (b1,b2,dJointTypeContact)) return;
  70. dContact contact[MAX_CONTACTS]; // up to MAX_CONTACTS contacts per box-box
  71. for (i=0; i<MAX_CONTACTS; i++) {
  72. contact[i].surface.mode = dContactBounce | dContactApprox1; //dContactSoftCFM;
  73. contact[i].surface.mu = dInfinity;
  74. contact[i].surface.mu2 = 0;
  75. contact[i].surface.bounce = 0.1;
  76. contact[i].surface.bounce_vel = 0.1;
  77. contact[i].surface.soft_cfm = 0.01;
  78. }
  79. if (int numc = dCollide (o1,o2,MAX_CONTACTS,&contact[0].geom,
  80. sizeof(dContact))) {
  81. dMatrix3 RI;
  82. dRSetIdentity (RI);
  83. const dReal ss[3] = {0.02,0.02,0.02};
  84. for (i=0; i<numc; i++) {
  85. dJointID c = dJointCreateContact (world,contactgroup,contact+i);
  86. dJointAttach (c,b1,b2);
  87. if (show_contacts) dsDrawBox (contact[i].geom.pos,RI,ss);
  88. }
  89. }
  90. }
  91. // start simulation - set viewpoint
  92. static void start()
  93. {
  94. static float xyz[3] = {2.1640f,-1.3079f,1.7600f};
  95. static float hpr[3] = {125.5000f,-17.0000f,0.0000f};
  96. dsSetViewpoint (xyz,hpr);
  97. printf ("To drop another object, press:\n");
  98. printf (" b for box.\n");
  99. printf (" s for sphere.\n");
  100. printf (" c for cylinder.\n");
  101. printf (" x for a composite object.\n");
  102. printf ("To select an object, press space.\n");
  103. printf ("To disable the selected object, press d.\n");
  104. printf ("To enable the selected object, press e.\n");
  105. printf ("To toggle showing the geom AABBs, press a.\n");
  106. printf ("To toggle showing the contact points, press t.\n");
  107. printf ("To toggle dropping from random position/orientation, press r.\n");
  108. }
  109. char locase (char c)
  110. {
  111. if (c >= 'A' && c <= 'Z') return c - ('a'-'A');
  112. else return c;
  113. }
  114. // called when a key pressed
  115. static void command (int cmd)
  116. {
  117. int i,j,k;
  118. dReal sides[3];
  119. dMass m;
  120. cmd = locase (cmd);
  121. if (cmd == 'b' || cmd == 's' || cmd == 'c' || cmd == 'x'
  122. /* || cmd == 'l' */) {
  123. if (num < NUM) {
  124. i = num;
  125. num++;
  126. }
  127. else {
  128. i = nextobj;
  129. nextobj++;
  130. if (nextobj >= num) nextobj = 0;
  131. // destroy the body and geoms for slot i
  132. dBodyDestroy (obj[i].body);
  133. for (k=0; k < GPB; k++) {
  134. if (obj[i].geom[k]) dGeomDestroy (obj[i].geom[k]);
  135. }
  136. memset (&obj[i],0,sizeof(obj[i]));
  137. }
  138. obj[i].body = dBodyCreate (world);
  139. for (k=0; k<3; k++) sides[k] = dRandReal()*0.5+0.1;
  140. dMatrix3 R;
  141. if (random_pos) {
  142. dBodySetPosition (obj[i].body,
  143. dRandReal()*2-1,dRandReal()*2+1,dRandReal()+3);
  144. dRFromAxisAndAngle (R,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
  145. dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
  146. }
  147. else {
  148. dReal maxheight = 0;
  149. for (k=0; k<num; k++) {
  150. const dReal *pos = dBodyGetPosition (obj[k].body);
  151. if (pos[2] > maxheight) maxheight = pos[2];
  152. }
  153. dBodySetPosition (obj[i].body, 0,maxheight+1,maxheight+3);
  154. dRFromAxisAndAngle (R,0,0,1,dRandReal()*10.0-5.0);
  155. }
  156. dBodySetRotation (obj[i].body,R);
  157. dBodySetData (obj[i].body,(void*) i);
  158. if (cmd == 'b') {
  159. dMassSetBox (&m,DENSITY,sides[0],sides[1],sides[2]);
  160. obj[i].geom[0] = dCreateBox (space,sides[0],sides[1],sides[2]);
  161. }
  162. else if (cmd == 'c') {
  163. sides[0] *= 0.5;
  164. dMassSetCappedCylinder (&m,DENSITY,3,sides[0],sides[1]);
  165. obj[i].geom[0] = dCreateCCylinder (space,sides[0],sides[1]);
  166. }
  167. /*
  168. // cylinder option not yet implemented
  169. else if (cmd == 'l') {
  170. sides[1] *= 0.5;
  171. dMassSetCappedCylinder (&m,DENSITY,3,sides[0],sides[1]);
  172. obj[i].geom[0] = dCreateCylinder (space,sides[0],sides[1]);
  173. }
  174. */
  175. else if (cmd == 's') {
  176. sides[0] *= 0.5;
  177. dMassSetSphere (&m,DENSITY,sides[0]);
  178. obj[i].geom[0] = dCreateSphere (space,sides[0]);
  179. }
  180. else if (cmd == 'x') {
  181. dGeomID g2[GPB]; // encapsulated geometries
  182. dReal dpos[GPB][3]; // delta-positions for encapsulated geometries
  183. // start accumulating masses for the encapsulated geometries
  184. dMass m2;
  185. dMassSetZero (&m);
  186. // set random delta positions
  187. for (j=0; j<GPB; j++) {
  188. for (k=0; k<3; k++) dpos[j][k] = dRandReal()*0.3-0.15;
  189. }
  190. for (k=0; k<GPB; k++) {
  191. obj[i].geom[k] = dCreateGeomTransform (space);
  192. dGeomTransformSetCleanup (obj[i].geom[k],1);
  193. if (k==0) {
  194. dReal radius = dRandReal()*0.25+0.05;
  195. g2[k] = dCreateSphere (0,radius);
  196. dMassSetSphere (&m2,DENSITY,radius);
  197. }
  198. else if (k==1) {
  199. g2[k] = dCreateBox (0,sides[0],sides[1],sides[2]);
  200. dMassSetBox (&m2,DENSITY,sides[0],sides[1],sides[2]);
  201. }
  202. else {
  203. dReal radius = dRandReal()*0.1+0.05;
  204. dReal length = dRandReal()*1.0+0.1;
  205. g2[k] = dCreateCCylinder (0,radius,length);
  206. dMassSetCappedCylinder (&m2,DENSITY,3,radius,length);
  207. }
  208. dGeomTransformSetGeom (obj[i].geom[k],g2[k]);
  209. // set the transformation (adjust the mass too)
  210. dGeomSetPosition (g2[k],dpos[k][0],dpos[k][1],dpos[k][2]);
  211. dMassTranslate (&m2,dpos[k][0],dpos[k][1],dpos[k][2]);
  212. dMatrix3 Rtx;
  213. dRFromAxisAndAngle (Rtx,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
  214. dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
  215. dGeomSetRotation (g2[k],Rtx);
  216. dMassRotate (&m2,Rtx);
  217. // add to the total mass
  218. dMassAdd (&m,&m2);
  219. }
  220. // move all encapsulated objects so that the center of mass is (0,0,0)
  221. for (k=0; k<2; k++) {
  222. dGeomSetPosition (g2[k],
  223. dpos[k][0]-m.c[0],
  224. dpos[k][1]-m.c[1],
  225. dpos[k][2]-m.c[2]);
  226. }
  227. dMassTranslate (&m,-m.c[0],-m.c[1],-m.c[2]);
  228. }
  229. for (k=0; k < GPB; k++) {
  230. if (obj[i].geom[k]) dGeomSetBody (obj[i].geom[k],obj[i].body);
  231. }
  232. dBodySetMass (obj[i].body,&m);
  233. }
  234. if (cmd == ' ') {
  235. selected++;
  236. if (selected >= num) selected = 0;
  237. if (selected < 0) selected = 0;
  238. }
  239. else if (cmd == 'd' && selected >= 0 && selected < num) {
  240. dBodyDisable (obj[selected].body);
  241. }
  242. else if (cmd == 'e' && selected >= 0 && selected < num) {
  243. dBodyEnable (obj[selected].body);
  244. }
  245. else if (cmd == 'a') {
  246. show_aabb ^= 1;
  247. }
  248. else if (cmd == 't') {
  249. show_contacts ^= 1;
  250. }
  251. else if (cmd == 'r') {
  252. random_pos ^= 1;
  253. }
  254. }
  255. // draw a geom
  256. void drawGeom (dGeomID g, const dReal *pos, const dReal *R, int show_aabb)
  257. {
  258. int i;
  259. if (!g) return;
  260. if (!pos) pos = dGeomGetPosition (g);
  261. if (!R) R = dGeomGetRotation (g);
  262. int type = dGeomGetClass (g);
  263. if (type == dBoxClass) {
  264. dVector3 sides;
  265. dGeomBoxGetLengths (g,sides);
  266. dsDrawBox (pos,R,sides);
  267. }
  268. else if (type == dSphereClass) {
  269. dsDrawSphere (pos,R,dGeomSphereGetRadius (g));
  270. }
  271. else if (type == dCCylinderClass) {
  272. dReal radius,length;
  273. dGeomCCylinderGetParams (g,&radius,&length);
  274. dsDrawCappedCylinder (pos,R,length,radius);
  275. }
  276. /*
  277. // cylinder option not yet implemented
  278. else if (type == dCylinderClass) {
  279. dReal radius,length;
  280. dGeomCylinderGetParams (g,&radius,&length);
  281. dsDrawCylinder (pos,R,length,radius);
  282. }
  283. */
  284. else if (type == dGeomTransformClass) {
  285. dGeomID g2 = dGeomTransformGetGeom (g);
  286. const dReal *pos2 = dGeomGetPosition (g2);
  287. const dReal *R2 = dGeomGetRotation (g2);
  288. dVector3 actual_pos;
  289. dMatrix3 actual_R;
  290. dMULTIPLY0_331 (actual_pos,R,pos2);
  291. actual_pos[0] += pos[0];
  292. actual_pos[1] += pos[1];
  293. actual_pos[2] += pos[2];
  294. dMULTIPLY0_333 (actual_R,R,R2);
  295. drawGeom (g2,actual_pos,actual_R,0);
  296. }
  297. if (show_aabb) {
  298. // draw the bounding box for this geom
  299. dReal aabb[6];
  300. dGeomGetAABB (g,aabb);
  301. dVector3 bbpos;
  302. for (i=0; i<3; i++) bbpos[i] = 0.5*(aabb[i*2] + aabb[i*2+1]);
  303. dVector3 bbsides;
  304. for (i=0; i<3; i++) bbsides[i] = aabb[i*2+1] - aabb[i*2];
  305. dMatrix3 RI;
  306. dRSetIdentity (RI);
  307. dsSetColorAlpha (1,0,0,0.5);
  308. dsDrawBox (bbpos,RI,bbsides);
  309. }
  310. }
  311. // simulation loop
  312. static void simLoop (int pause)
  313. {
  314. dsSetColor (0,0,2);
  315. dSpaceCollide (space,0,&nearCallback);
  316. if (!pause) dWorldStep (world,0.05);
  317. dAASSERT(terrainY);
  318. dAASSERT(terrainZ);
  319. dsSetColor (0,1,0);
  320. dsDrawTerrainY(0,0,vTerrainLength,vTerrainLength/TERRAINNODES,TERRAINNODES,pTerrainHeights,dGeomGetRotation(terrainY),dGeomGetPosition(terrainY));
  321. dsDrawTerrainZ(0,0,vTerrainLength,vTerrainLength/TERRAINNODES,TERRAINNODES,pTerrainHeights,dGeomGetRotation(terrainZ),dGeomGetPosition(terrainZ));
  322. if (show_aabb)
  323. {
  324. dReal aabb[6];
  325. dGeomGetAABB (terrainY,aabb);
  326. dVector3 bbpos;
  327. int i;
  328. for (i=0; i<3; i++) bbpos[i] = 0.5*(aabb[i*2] + aabb[i*2+1]);
  329. dVector3 bbsides;
  330. for (i=0; i<3; i++) bbsides[i] = aabb[i*2+1] - aabb[i*2];
  331. dMatrix3 RI;
  332. dRSetIdentity (RI);
  333. dsSetColorAlpha (1,0,0,0.5);
  334. dsDrawBox (bbpos,RI,bbsides);
  335. dGeomGetAABB (terrainZ,aabb);
  336. for (i=0; i<3; i++) bbpos[i] = 0.5*(aabb[i*2] + aabb[i*2+1]);
  337. for (i=0; i<3; i++) bbsides[i] = aabb[i*2+1] - aabb[i*2];
  338. dsDrawBox (bbpos,RI,bbsides);
  339. }
  340. dsSetColor (1,1,0);
  341. // remove all contact joints
  342. dJointGroupEmpty (contactgroup);
  343. dsSetColor (1,1,0);
  344. dsSetTexture (DS_WOOD);
  345. for (int i=0; i<num; i++) {
  346. for (int j=0; j < GPB; j++) {
  347. if (i==selected) {
  348. dsSetColor (0,0.7,1);
  349. }
  350. else if (! dBodyIsEnabled (obj[i].body)) {
  351. dsSetColor (1,0,0);
  352. }
  353. else {
  354. dsSetColor (1,1,0);
  355. }
  356. drawGeom (obj[i].geom[j],0,0,show_aabb);
  357. }
  358. }
  359. }
  360. int main (int argc, char **argv)
  361. {
  362. // setup pointers to drawstuff callback functions
  363. dsFunctions fn;
  364. fn.version = DS_VERSION;
  365. fn.start = &start;
  366. fn.step = &simLoop;
  367. fn.command = &command;
  368. fn.stop = 0;
  369. fn.path_to_textures = "../../drawstuff/textures";
  370. if(argc==2)
  371. {
  372. fn.path_to_textures = argv[1];
  373. }
  374. // create world
  375. world = dWorldCreate();
  376. space = dHashSpaceCreate (0);
  377. contactgroup = dJointGroupCreate (0);
  378. dWorldSetGravity (world,0,0,-0.5); //-0.5
  379. dWorldSetCFM (world,1e-5);
  380. dCreatePlane (space,0,0,1,0);
  381. memset (obj,0,sizeof(obj));
  382. for (int i=0;i<TERRAINNODES*TERRAINNODES;i++) pTerrainHeights[i] = vTerrainHeight * dRandReal();
  383. terrainY = dCreateTerrainY(space,pTerrainHeights,vTerrainLength,TERRAINNODES,1,1);
  384. terrainZ = dCreateTerrainZ(space,pTerrainHeights,vTerrainLength,TERRAINNODES,1,1);
  385. dMatrix3 R;
  386. dRFromZAxis(R, 0.2f, 0.2f, 0.2f);
  387. dGeomSetPosition(terrainY,0.f,0.f,0.5f);
  388. dGeomSetRotation(terrainY,R);
  389. dGeomSetPosition(terrainZ,0.f,0.f,0.5f);
  390. dGeomSetRotation(terrainZ,R);
  391. // run simulation
  392. dsSimulationLoop (argc,argv,352,288,&fn);
  393. dJointGroupDestroy (contactgroup);
  394. dSpaceDestroy (space);
  395. dWorldDestroy (world);
  396. return 0;
  397. }