demo_cards.cpp 6.5 KB

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