demo_kinematic.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  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 <iostream>
  23. #include <set>
  24. #include <algorithm>
  25. #include <functional>
  26. #include <ode/ode.h>
  27. #include <drawstuff/drawstuff.h>
  28. #include "texturepath.h"
  29. #ifdef dDOUBLE
  30. #define dsDrawBox dsDrawBoxD
  31. #define dsDrawCylinder dsDrawCylinderD
  32. #endif
  33. using namespace std;
  34. dWorld *world;
  35. dSpace *space;
  36. dPlane *ground;
  37. dBody *kbody;
  38. dBox *kbox;
  39. dJointGroup joints;
  40. dCylinder *kpole;
  41. dBody *matraca;
  42. dBox *matraca_geom;
  43. dHingeJoint *hinge;
  44. struct Box {
  45. dBody body;
  46. dBox geom;
  47. Box() :
  48. body(*world),
  49. geom(*space, 0.2, 0.2, 0.2)
  50. {
  51. dMass mass;
  52. mass.setBox(10, 0.2, 0.2, 0.2);
  53. body.setMass(mass);
  54. geom.setData(this);
  55. geom.setBody(body);
  56. }
  57. void draw() const
  58. {
  59. dVector3 lengths;
  60. geom.getLengths(lengths);
  61. dsSetTexture(DS_WOOD);
  62. dsSetColor(0,1,0);
  63. dsDrawBox(geom.getPosition(), geom.getRotation(), lengths);
  64. }
  65. };
  66. set<Box*> boxes;
  67. set<Box*> to_remove;
  68. void dropBox()
  69. {
  70. Box *box = new Box();
  71. dReal px = (rand() / float(RAND_MAX)) * 2 - 1;
  72. dReal py = (rand() / float(RAND_MAX)) * 2 - 1;
  73. dReal pz = 2.5;
  74. box->body.setPosition(px, py, pz);
  75. boxes.insert(box);
  76. }
  77. void queueRemoval(dGeomID g)
  78. {
  79. Box *b = (Box*)dGeomGetData(g);
  80. to_remove.insert(b);
  81. }
  82. void removeQueued()
  83. {
  84. while (!to_remove.empty()) {
  85. Box *b = *to_remove.begin();
  86. to_remove.erase(b);
  87. boxes.erase(b);
  88. delete b;
  89. }
  90. }
  91. void nearCallback(void *, dGeomID g1, dGeomID g2)
  92. {
  93. if (g1 == ground->id()) {
  94. queueRemoval(g2);
  95. return;
  96. }
  97. if (g2 == ground->id()) {
  98. queueRemoval(g1);
  99. return;
  100. }
  101. dBodyID b1 = dGeomGetBody(g1);
  102. dBodyID b2 = dGeomGetBody(g2);
  103. if (b1 && b2 && dAreConnectedExcluding(b1, b2, dJointTypeContact))
  104. return;
  105. const int MAX_CONTACTS = 10;
  106. dContact contact[MAX_CONTACTS];
  107. int n = dCollide(g1, g2, MAX_CONTACTS, &contact[0].geom, sizeof(dContact));
  108. for (int i=0; i<n; ++i) {
  109. contact[i].surface.mode = 0;
  110. contact[i].surface.mu = 1;
  111. dJointID j = dJointCreateContact (*world, joints.id(), contact+i);
  112. dJointAttach(j, b1, b2);
  113. }
  114. }
  115. void
  116. simLoop(int pause)
  117. {
  118. if (!pause) {
  119. const dReal timestep = 0.04;
  120. // this does a hard-coded circular motion animation
  121. static float t=0;
  122. t += timestep/4;
  123. if (t > 2*M_PI)
  124. t = 0;
  125. dVector3 next_pos = { dCos(t), dSin(t), REAL(0.5)};
  126. dVector3 vel;
  127. // vel = (next_pos - cur_pos) / timestep
  128. dSubtractVectors3(vel, next_pos, kbody->getPosition());
  129. dScaleVector3(vel, 1/timestep);
  130. kbody->setLinearVel(vel);
  131. // end of hard-coded animation
  132. space->collide(0, nearCallback);
  133. removeQueued();
  134. world->quickStep(timestep);
  135. joints.clear();
  136. }
  137. dVector3 lengths;
  138. // the moving platform
  139. kbox->getLengths(lengths);
  140. dsSetTexture(DS_WOOD);
  141. dsSetColor(.3, .3, 1);
  142. dsDrawBox(kbox->getPosition(), kbox->getRotation(), lengths);
  143. dReal length, radius;
  144. kpole->getParams(&radius, &length);
  145. dsSetTexture(DS_CHECKERED);
  146. dsSetColor(1, 1, 0);
  147. dsDrawCylinder(kpole->getPosition(), kpole->getRotation(), length, radius);
  148. // the matraca
  149. matraca_geom->getLengths(lengths);
  150. dsSetColor(1,0,0);
  151. dsSetTexture(DS_WOOD);
  152. dsDrawBox(matraca_geom->getPosition(), matraca_geom->getRotation(), lengths);
  153. // and the boxes
  154. for_each(boxes.begin(), boxes.end(), mem_fun(&Box::draw));
  155. }
  156. void command(int c)
  157. {
  158. switch (c) {
  159. case ' ':
  160. dropBox();
  161. break;
  162. }
  163. }
  164. int main(int argc, char **argv)
  165. {
  166. dInitODE();
  167. // setup pointers to drawstuff callback functions
  168. dsFunctions fn;
  169. fn.version = DS_VERSION;
  170. fn.start = 0;
  171. fn.step = &simLoop;
  172. fn.command = &command;
  173. fn.stop = 0;
  174. fn.path_to_textures = DRAWSTUFF_TEXTURE_PATH;
  175. cout << endl << "*** Press SPACE to drop boxes **" << endl;
  176. space = new dSimpleSpace();
  177. ground = new dPlane(*space, 0, 0, 1, 0);
  178. world = new dWorld;
  179. world->setGravity(0, 0, -.5);
  180. kbody = new dBody(*world);
  181. kbody->setKinematic();
  182. const dReal kx = 1, ky = 0, kz = .5;
  183. kbody->setPosition(kx, ky, kz);
  184. kbox = new dBox(*space, 3, 3, .5);
  185. kbox->setBody(*kbody);
  186. kpole = new dCylinder(*space, .125, 1.5);
  187. kpole->setBody(*kbody);
  188. dGeomSetOffsetPosition(kpole->id(), 0, 0, 0.8);
  189. matraca = new dBody(*world);
  190. matraca->setPosition(kx+0, ky+1, kz+1);
  191. matraca_geom = new dBox(*space, 0.5, 2, 0.75);
  192. matraca_geom->setBody(*matraca);
  193. dMass mass;
  194. mass.setBox(1, 0.5, 2, 0.75);
  195. matraca->setMass(mass);
  196. hinge = new dHingeJoint(*world);
  197. hinge->attach(*kbody, *matraca);
  198. hinge->setAnchor(kx, ky, kz+1);
  199. hinge->setAxis(0, 0, 1);
  200. dsSimulationLoop (argc, argv, 640, 480, &fn);
  201. dCloseODE();
  202. }