demo_cards.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. #include <vector>
  2. #include <ode/ode.h>
  3. #include <drawstuff/drawstuff.h>
  4. #include "texturepath.h"
  5. #ifdef dDOUBLE
  6. #define dsDrawBox dsDrawBoxD
  7. #endif
  8. static int levels = 5;
  9. static int ncards = 0;
  10. static dSpaceID space;
  11. static dWorldID world;
  12. static dJointGroupID contactgroup;
  13. struct Card {
  14. dBodyID body;
  15. dGeomID geom;
  16. static const dReal sides[3];
  17. Card()
  18. {
  19. body = dBodyCreate(world);
  20. geom = dCreateBox(space, sides[0], sides[1], sides[2]);
  21. dGeomSetBody(geom, body);
  22. dGeomSetData(geom, this);
  23. dMass mass;
  24. mass.setBox(1, sides[0], sides[1], sides[2]);
  25. dBodySetMass(body, &mass);
  26. }
  27. ~Card()
  28. {
  29. dBodyDestroy(body);
  30. dGeomDestroy(geom);
  31. }
  32. void draw() const
  33. {
  34. dsDrawBox(dBodyGetPosition(body),
  35. dBodyGetRotation(body), sides);
  36. }
  37. };
  38. static const dReal cwidth=.5, cthikness=.02, clength=1;
  39. const dReal Card::sides[3] = { cwidth, cthikness, clength };
  40. std::vector<Card*> cards;
  41. int getncards(int levels)
  42. {
  43. return (3*levels*levels + levels) / 2;
  44. }
  45. void place_cards()
  46. {
  47. ncards = getncards(levels);
  48. // destroy removed cards (if any)
  49. int oldcards = cards.size();
  50. for (int i=ncards; i<oldcards; ++i)
  51. delete cards[i];
  52. cards.resize(ncards);
  53. // construct new cards (if any)
  54. for (int i=oldcards; i<ncards; ++i)
  55. cards[i] = new Card;
  56. // for each level
  57. int c = 0;
  58. dMatrix3 right, left, hrot;
  59. dReal angle = 20*M_PI/180.;
  60. dRFromAxisAndAngle(right, 1, 0, 0, -angle);
  61. dRFromAxisAndAngle(left, 1, 0, 0, angle);
  62. dRFromAxisAndAngle(hrot, 1, 0, 0, 91*M_PI/180.);
  63. dReal eps = 0.05;
  64. dReal vstep = cos(angle)*clength + eps;
  65. dReal hstep = sin(angle)*clength + eps;
  66. for (int lvl=0; lvl<levels; ++lvl) {
  67. // there are 3*(levels-lvl)-1 cards in each level, except last
  68. int n = (levels-lvl);
  69. dReal height = (lvl)*vstep + vstep/2;
  70. // inclined cards
  71. for (int i=0; i<2*n; ++i, ++c) {
  72. dBodySetPosition(cards[c]->body,
  73. 0,
  74. -n*hstep + hstep*i,
  75. height
  76. );
  77. if (i%2)
  78. dBodySetRotation(cards[c]->body, left);
  79. else
  80. dBodySetRotation(cards[c]->body, right);
  81. }
  82. if (n==1) // top of the house
  83. break;
  84. // horizontal cards
  85. for (int i=0; i<n-1; ++i, ++c) {
  86. dBodySetPosition(cards[c]->body,
  87. 0,
  88. -(n-1 - (clength-hstep)/2)*hstep + 2*hstep*i,
  89. height + vstep/2);
  90. dBodySetRotation(cards[c]->body, hrot);
  91. }
  92. }
  93. }
  94. void start()
  95. {
  96. puts("Controls:");
  97. puts(" SPACE - reposition cards");
  98. puts(" - - one less level");
  99. puts(" = - one more level");
  100. }
  101. static void nearCallback (void *data, dGeomID o1, dGeomID o2)
  102. {
  103. // exit without doing anything if the two bodies are connected by a joint
  104. dBodyID b1 = dGeomGetBody(o1);
  105. dBodyID b2 = dGeomGetBody(o2);
  106. const int MAX_CONTACTS = 8;
  107. dContact contact[MAX_CONTACTS];
  108. int numc = dCollide (o1, o2, MAX_CONTACTS,
  109. &contact[0].geom,
  110. sizeof(dContact));
  111. for (int i=0; i<numc; i++) {
  112. contact[i].surface.mode = dContactApprox1;
  113. contact[i].surface.mu = 5;
  114. dJointID c = dJointCreateContact (world, contactgroup, contact+i);
  115. dJointAttach (c, b1, b2);
  116. }
  117. }
  118. void simLoop(int pause)
  119. {
  120. if (!pause) {
  121. dSpaceCollide (space, 0, &nearCallback);
  122. dWorldQuickStep(world, 0.01);
  123. dJointGroupEmpty(contactgroup);
  124. }
  125. dsSetColor (1,1,0);
  126. for (int i=0; i<ncards; ++i) {
  127. dsSetColor (1, dReal(i)/ncards, 0);
  128. cards[i]->draw();
  129. }
  130. }
  131. void command(int c)
  132. {
  133. switch (c) {
  134. case '=':
  135. levels++;
  136. place_cards();
  137. break;
  138. case '-':
  139. levels--;
  140. if (levels <= 0)
  141. levels++;
  142. place_cards();
  143. break;
  144. case ' ':
  145. place_cards();
  146. break;
  147. }
  148. }
  149. int main(int argc, char **argv)
  150. {
  151. dInitODE();
  152. // setup pointers to drawstuff callback functions
  153. dsFunctions fn;
  154. fn.version = DS_VERSION;
  155. fn.start = &start;
  156. fn.step = &simLoop;
  157. fn.command = &command;
  158. fn.stop = 0;
  159. fn.path_to_textures = DRAWSTUFF_TEXTURE_PATH;
  160. world = dWorldCreate();
  161. dWorldSetGravity(world, 0, 0, -0.5);
  162. dWorldSetQuickStepNumIterations(world, 50); // <-- increase for more stability
  163. space = dSimpleSpaceCreate(0);
  164. contactgroup = dJointGroupCreate(0);
  165. dGeomID ground = dCreatePlane(space, 0, 0, 1, 0);
  166. place_cards();
  167. // run simulation
  168. dsSimulationLoop (argc, argv, 640, 480, &fn);
  169. levels = 0;
  170. place_cards();
  171. dJointGroupDestroy(contactgroup);
  172. dWorldDestroy(world);
  173. dGeomDestroy(ground);
  174. dSpaceDestroy(space);
  175. dCloseODE();
  176. }