demo_plane2d.cpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  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. // Test my Plane2D constraint.
  23. // Uses ode-0.35 collision API.
  24. # include <stdio.h>
  25. # include <stdlib.h>
  26. # include <math.h>
  27. # include <ode/ode.h>
  28. # include <drawstuff/drawstuff.h>
  29. #include "texturepath.h"
  30. # define drand48() ((double) (((double) rand()) / ((double) RAND_MAX)))
  31. # define N_BODIES 40
  32. # define STAGE_SIZE 8.0 // in m
  33. # define TIME_STEP 0.01
  34. # define K_SPRING 10.0
  35. # define K_DAMP 10.0
  36. //using namespace ode;
  37. static dWorld dyn_world;
  38. static dBody dyn_bodies[N_BODIES];
  39. static dReal bodies_sides[N_BODIES][3];
  40. static dSpaceID coll_space_id;
  41. static dJointID plane2d_joint_ids[N_BODIES];
  42. static dJointGroup
  43. coll_contacts;
  44. static void cb_start ()
  45. /*************************/
  46. {
  47. static float xyz[3] = { 0.5f*STAGE_SIZE, 0.5f*STAGE_SIZE, 0.65f*STAGE_SIZE};
  48. static float hpr[3] = { 90.0f, -90.0f, 0 };
  49. dsSetViewpoint (xyz, hpr);
  50. }
  51. static void cb_near_collision (void *data, dGeomID o1, dGeomID o2)
  52. /********************************************************************/
  53. {
  54. dBodyID b1 = dGeomGetBody (o1);
  55. dBodyID b2 = dGeomGetBody (o2);
  56. dContact contact;
  57. // exit without doing anything if the two bodies are static
  58. if (b1 == 0 && b2 == 0)
  59. return;
  60. // exit without doing anything if the two bodies are connected by a joint
  61. if (b1 && b2 && dAreConnected (b1, b2))
  62. {
  63. /* MTRAP; */
  64. return;
  65. }
  66. contact.surface.mode = 0;
  67. contact.surface.mu = 0; // frictionless
  68. if (dCollide (o1, o2, 1, &contact.geom, sizeof (dContactGeom)))
  69. {
  70. dJointID c = dJointCreateContact (dyn_world.id(),
  71. coll_contacts.id (), &contact);
  72. dJointAttach (c, b1, b2);
  73. }
  74. }
  75. static void track_to_pos (dBody &body, dJointID joint_id,
  76. dReal target_x, dReal target_y)
  77. /************************************************************************/
  78. {
  79. dReal curr_x = body.getPosition()[0];
  80. dReal curr_y = body.getPosition()[1];
  81. dJointSetPlane2DXParam (joint_id, dParamVel, 1 * (target_x - curr_x));
  82. dJointSetPlane2DYParam (joint_id, dParamVel, 1 * (target_y - curr_y));
  83. }
  84. static void cb_sim_step (int pause)
  85. /*************************************/
  86. {
  87. if (! pause)
  88. {
  89. static dReal angle = 0;
  90. angle += REAL( 0.01 );
  91. track_to_pos (dyn_bodies[0], plane2d_joint_ids[0],
  92. dReal( STAGE_SIZE/2 + STAGE_SIZE/2.0 * cos (angle) ),
  93. dReal( STAGE_SIZE/2 + STAGE_SIZE/2.0 * sin (angle) ));
  94. /* double f0 = 0.001; */
  95. /* for (int b = 0; b < N_BODIES; b ++) */
  96. /* { */
  97. /* double p = 1 + b / (double) N_BODIES; */
  98. /* double q = 2 - b / (double) N_BODIES; */
  99. /* dyn_bodies[b].addForce (f0 * cos (p*angle), f0 * sin (q*angle), 0); */
  100. /* } */
  101. /* dyn_bodies[0].addTorque (0, 0, 0.1); */
  102. const int n = 10;
  103. for (int i = 0; i < n; i ++)
  104. {
  105. dSpaceCollide (coll_space_id, 0, &cb_near_collision);
  106. dyn_world.step (dReal(TIME_STEP/n));
  107. coll_contacts.empty ();
  108. }
  109. }
  110. # if 1 /* [ */
  111. {
  112. // @@@ hack Plane2D constraint error reduction here:
  113. for (int b = 0; b < N_BODIES; b ++)
  114. {
  115. const dReal *rot = dBodyGetAngularVel (dyn_bodies[b].id());
  116. const dReal *quat_ptr;
  117. dReal quat[4],
  118. quat_len;
  119. quat_ptr = dBodyGetQuaternion (dyn_bodies[b].id());
  120. quat[0] = quat_ptr[0];
  121. quat[1] = 0;
  122. quat[2] = 0;
  123. quat[3] = quat_ptr[3];
  124. quat_len = sqrt (quat[0] * quat[0] + quat[3] * quat[3]);
  125. quat[0] /= quat_len;
  126. quat[3] /= quat_len;
  127. dBodySetQuaternion (dyn_bodies[b].id(), quat);
  128. dBodySetAngularVel (dyn_bodies[b].id(), 0, 0, rot[2]);
  129. }
  130. }
  131. # endif /* ] */
  132. # if 0 /* [ */
  133. {
  134. // @@@ friction
  135. for (int b = 0; b < N_BODIES; b ++)
  136. {
  137. const dReal *vel = dBodyGetLinearVel (dyn_bodies[b].id()),
  138. *rot = dBodyGetAngularVel (dyn_bodies[b].id());
  139. dReal s = 1.00;
  140. dReal t = 0.99;
  141. dBodySetLinearVel (dyn_bodies[b].id(), s*vel[0],s*vel[1],s*vel[2]);
  142. dBodySetAngularVel (dyn_bodies[b].id(),t*rot[0],t*rot[1],t*rot[2]);
  143. }
  144. }
  145. # endif /* ] */
  146. {
  147. // ode drawstuff
  148. dsSetTexture (DS_WOOD);
  149. for (int b = 0; b < N_BODIES; b ++)
  150. {
  151. if (b == 0)
  152. dsSetColor (1.0, 0.5, 1.0);
  153. else
  154. dsSetColor (0, 0.5, 1.0);
  155. #ifdef dDOUBLE
  156. dsDrawBoxD (dyn_bodies[b].getPosition(), dyn_bodies[b].getRotation(), bodies_sides[b]);
  157. #else
  158. dsDrawBox (dyn_bodies[b].getPosition(), dyn_bodies[b].getRotation(), bodies_sides[b]);
  159. #endif
  160. }
  161. }
  162. }
  163. extern int main
  164. /******************/
  165. (
  166. int argc,
  167. char **argv
  168. )
  169. {
  170. int b;
  171. dsFunctions drawstuff_functions;
  172. dInitODE();
  173. // dynamic world
  174. dReal cf_mixing;// = 1 / TIME_STEP * K_SPRING + K_DAMP;
  175. dReal err_reduct;// = TIME_STEP * K_SPRING * cf_mixing;
  176. err_reduct = REAL( 0.5 );
  177. cf_mixing = REAL( 0.001 );
  178. dWorldSetERP (dyn_world.id (), err_reduct);
  179. dWorldSetCFM (dyn_world.id (), cf_mixing);
  180. dyn_world.setGravity (0, 0.0, -1.0);
  181. coll_space_id = dSimpleSpaceCreate (0);
  182. // dynamic bodies
  183. for (b = 0; b < N_BODIES; b ++)
  184. {
  185. int l = (int) (1 + sqrt ((double) N_BODIES));
  186. dReal x = dReal( (0.5 + (b / l)) / l * STAGE_SIZE );
  187. dReal y = dReal( (0.5 + (b % l)) / l * STAGE_SIZE );
  188. dReal z = REAL( 1.0 ) + REAL( 0.1 ) * (dReal)drand48();
  189. bodies_sides[b][0] = dReal( 5 * (0.2 + 0.7*drand48()) / sqrt((double)N_BODIES) );
  190. bodies_sides[b][1] = dReal( 5 * (0.2 + 0.7*drand48()) / sqrt((double)N_BODIES) );
  191. bodies_sides[b][2] = z;
  192. dyn_bodies[b].create (dyn_world);
  193. dyn_bodies[b].setPosition (x, y, z/2);
  194. dyn_bodies[b].setData ((void*) (size_t)b);
  195. dBodySetLinearVel (dyn_bodies[b].id (),
  196. dReal( 3 * (drand48 () - 0.5) ),
  197. dReal( 3 * (drand48 () - 0.5) ), 0);
  198. dMass m;
  199. m.setBox (1, bodies_sides[b][0],bodies_sides[b][1],bodies_sides[b][2]);
  200. m.adjust (REAL(0.1) * bodies_sides[b][0] * bodies_sides[b][1]);
  201. dyn_bodies[b].setMass (&m);
  202. plane2d_joint_ids[b] = dJointCreatePlane2D (dyn_world.id (), 0);
  203. dJointAttach (plane2d_joint_ids[b], dyn_bodies[b].id (), 0);
  204. }
  205. dJointSetPlane2DXParam (plane2d_joint_ids[0], dParamFMax, 10);
  206. dJointSetPlane2DYParam (plane2d_joint_ids[0], dParamFMax, 10);
  207. // collision geoms and joints
  208. dCreatePlane (coll_space_id, 1, 0, 0, 0);
  209. dCreatePlane (coll_space_id, -1, 0, 0, -STAGE_SIZE);
  210. dCreatePlane (coll_space_id, 0, 1, 0, 0);
  211. dCreatePlane (coll_space_id, 0, -1, 0, -STAGE_SIZE);
  212. for (b = 0; b < N_BODIES; b ++)
  213. {
  214. dGeomID coll_box_id;
  215. coll_box_id = dCreateBox (coll_space_id,
  216. bodies_sides[b][0], bodies_sides[b][1], bodies_sides[b][2]);
  217. dGeomSetBody (coll_box_id, dyn_bodies[b].id ());
  218. }
  219. coll_contacts.create ();
  220. {
  221. // simulation loop (by drawstuff lib)
  222. drawstuff_functions.version = DS_VERSION;
  223. drawstuff_functions.start = &cb_start;
  224. drawstuff_functions.step = &cb_sim_step;
  225. drawstuff_functions.command = 0;
  226. drawstuff_functions.stop = 0;
  227. drawstuff_functions.path_to_textures = DRAWSTUFF_TEXTURE_PATH;
  228. dsSimulationLoop (argc, argv, 352,288,&drawstuff_functions);
  229. }
  230. dCloseODE();
  231. return 0;
  232. }