test_stability1.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  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. #define DENSITY (5.0) // density of all objects
  36. // dynamics and collision objects
  37. struct MyObject {
  38. dBodyID body; // the body
  39. dGeomID geom; // geometry representing this body
  40. };
  41. static dWorldID world;
  42. static dSpaceID space;
  43. static MyObject fallingObject;
  44. static dGeomID box1, box2;
  45. static dJointGroupID contactgroup;
  46. // this is called by dSpaceCollide when two objects in space are
  47. // potentially colliding.
  48. static void nearCallback (void *data, dGeomID o1, dGeomID o2)
  49. {
  50. int i;
  51. // if (o1->body && o2->body) return;
  52. // exit without doing anything if the two bodies are connected by a joint
  53. dBodyID b1 = dGeomGetBody(o1);
  54. dBodyID b2 = dGeomGetBody(o2);
  55. if (b1 && b2 && dAreConnected (b1,b2)) return;
  56. dContact contact[4]; // up to 3 contacts per box
  57. for (i=0; i<4; i++) {
  58. contact[i].surface.mode = dContactBounce; //dContactMu2;
  59. contact[i].surface.mu = dInfinity;
  60. contact[i].surface.mu2 = 0;
  61. contact[i].surface.bounce = 0.5;
  62. contact[i].surface.bounce_vel = 0.1;
  63. }
  64. if (int numc = dCollide (o1,o2,4,&contact[0].geom,sizeof(dContact))) {
  65. // dMatrix3 RI;
  66. // dRSetIdentity (RI);
  67. // const dReal ss[3] = {0.02,0.02,0.02};
  68. for (i=0; i<numc; i++) {
  69. dJointID c = dJointCreateContact (world,contactgroup,contact+i);
  70. dJointAttach (c,b1,b2);
  71. // dsDrawBox (contact[i].geom.pos,RI,ss);
  72. }
  73. }
  74. }
  75. // start simulation - set viewpoint
  76. static void start()
  77. {
  78. static float xyz[3] = {-4.0f, 0.0f, 3.0f};
  79. static float hpr[3] = {0.0f,-15.0f,0.0f};
  80. dsSetViewpoint (xyz,hpr);
  81. printf ("To drop another object, press:\n");
  82. printf (" b for box.\n");
  83. printf (" s for sphere.\n");
  84. printf (" c for cylinder.\n");
  85. printf ("To select an object, press space.\n");
  86. }
  87. char locase (char c)
  88. {
  89. if (c >= 'A' && c <= 'Z') return c - ('a'-'A');
  90. else return c;
  91. }
  92. // called when a key pressed
  93. static void command (int cmd)
  94. {
  95. int i,k;
  96. dReal sides[3];
  97. dMass m;
  98. cmd = locase (cmd);
  99. if (cmd == 'b' || cmd == 's' || cmd == 'c') {
  100. // Destroy the currently falling object and replace it by an instance of the requested type
  101. if (fallingObject.body) {
  102. dBodyDestroy (fallingObject.body);
  103. dGeomDestroy (fallingObject.geom);
  104. memset (&fallingObject, 0, sizeof(fallingObject));
  105. }
  106. fallingObject.body = dBodyCreate (world);
  107. for (k=0; k<3; k++) sides[k] = dRandReal()*0.5+0.1;
  108. // Start out centered above the V-gap
  109. dBodySetPosition (fallingObject.body, 0,0,5);
  110. #if 0
  111. dMatrix3 R;
  112. dRFromAxisAndAngle (R,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
  113. dRandReal()*2.0-1.0,dRandReal()*10.0-5.0);
  114. dBodySetRotation (fallingObject.body,R);
  115. dBodySetData (fallingObject.body,(void*) i);
  116. #endif
  117. if (cmd == 'b') {
  118. dMassSetBox (&m,DENSITY,sides[0],sides[1],sides[2]);
  119. fallingObject.geom = dCreateBox (space,sides[0],sides[1],sides[2]);
  120. }
  121. else if (cmd == 'c') {
  122. sides[0] *= 0.5;
  123. dMassSetCappedCylinder (&m,DENSITY,3,sides[0],sides[1]);
  124. fallingObject.geom = dCreateCCylinder (space,sides[0],sides[1]);
  125. }
  126. else if (cmd == 's') {
  127. sides[0] *= 0.5;
  128. dMassSetSphere (&m,DENSITY,sides[0]);
  129. fallingObject.geom = dCreateSphere (space,sides[0]);
  130. }
  131. dGeomSetBody (fallingObject.geom,fallingObject.body);
  132. dBodySetMass (fallingObject.body,&m);
  133. }
  134. }
  135. // draw a geom
  136. void drawGeom (dGeomID g, const dReal *pos, const dReal *R)
  137. {
  138. if (!g) return;
  139. if (!pos) pos = dGeomGetPosition (g);
  140. if (!R) R = dGeomGetRotation (g);
  141. int type = dGeomGetClass (g);
  142. if (type == dBoxClass) {
  143. dVector3 sides;
  144. dGeomBoxGetLengths (g,sides);
  145. dsDrawBox (pos,R,sides);
  146. }
  147. else if (type == dSphereClass) {
  148. dsDrawSphere (pos,R,dGeomSphereGetRadius (g));
  149. }
  150. else if (type == dCCylinderClass) {
  151. dReal radius,length;
  152. dGeomCCylinderGetParams (g,&radius,&length);
  153. dsDrawCappedCylinder (pos,R,length,radius);
  154. }
  155. /*
  156. else if (type == dGeomTransformClass) {
  157. dGeomID g2 = dGeomTransformGetGeom (g);
  158. const dReal *pos2 = dGeomGetPosition (g2);
  159. const dReal *R2 = dGeomGetRotation (g2);
  160. dVector3 actual_pos;
  161. dMatrix3 actual_R;
  162. dMULTIPLY0_331 (actual_pos,R,pos2);
  163. actual_pos[0] += pos[0];
  164. actual_pos[1] += pos[1];
  165. actual_pos[2] += pos[2];
  166. dMULTIPLY0_333 (actual_R,R,R2);
  167. drawGeom (g2,actual_pos,actual_R);
  168. }
  169. */
  170. }
  171. // simulation loop
  172. static void simLoop (int pause)
  173. {
  174. dsSetColor (0,0,2);
  175. dSpaceCollide (space,0,&nearCallback);
  176. if (!pause) dWorldStep (world,0.0005);
  177. // remove all contact joints
  178. dJointGroupEmpty (contactgroup);
  179. dsSetColor (1,1,0);
  180. dsSetTexture (DS_WOOD);
  181. // draw the falling object
  182. dsSetColor (1,0,0);
  183. drawGeom (fallingObject.geom,0,0);
  184. // draw the constraining boxes
  185. dsSetColor(0.8, 1, 0.8);
  186. drawGeom (box1,0,0);
  187. drawGeom (box2,0,0);
  188. }
  189. int main (int argc, char **argv)
  190. {
  191. // setup pointers to drawstuff callback functions
  192. dsFunctions fn;
  193. fn.version = DS_VERSION;
  194. fn.start = &start;
  195. fn.step = &simLoop;
  196. fn.command = &command;
  197. fn.stop = 0;
  198. fn.path_to_textures = "../../drawstuff/textures";
  199. if(argc==2)
  200. {
  201. fn.path_to_textures = argv[1];
  202. }
  203. // create world
  204. world = dWorldCreate();
  205. space = dHashSpaceCreate();
  206. contactgroup = dJointGroupCreate (0);
  207. dWorldSetGravity (world,0,0,-0.5);
  208. dWorldSetCFM (world,1e-5);
  209. dCreatePlane (space,0,0,1,0);
  210. memset (&fallingObject,0,sizeof(fallingObject));
  211. // Create two flat boxes, just slightly off vertical and a bit apart for stuff to fall in between.
  212. // Don't create bodies for these boxes -- they'll be immovable instead.
  213. {
  214. dReal sides[3];
  215. dMatrix3 R;
  216. sides[0] = 4;
  217. sides[1] = 0.2;
  218. sides[2] = 3;
  219. box1 = dCreateBox (space,sides[0],sides[1],sides[2]);
  220. dGeomSetPosition (box1, 0, sides[1], sides[2]/2);
  221. dRFromAxisAndAngle (R, 1, 0, 0, -0.1);
  222. dGeomSetRotation (box1, R);
  223. box2 = dCreateBox (space,sides[0],sides[1],sides[2]);
  224. dGeomSetPosition (box2, 0, -sides[1], sides[2]/2);
  225. dRFromAxisAndAngle (R, 1, 0, 0, 0.1);
  226. dGeomSetRotation (box2, R);
  227. }
  228. // Pretend to drop a box to start
  229. command('b');
  230. // run simulation
  231. dsSimulationLoop (argc,argv,640,480,&fn);
  232. dJointGroupDestroy (contactgroup);
  233. dSpaceDestroy (space);
  234. dWorldDestroy (world);
  235. return 0;
  236. }