BoxStack.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. using System;
  2. using System.Collections.Generic;
  3. using Drawstuff.NET;
  4. namespace Ode.NET
  5. {
  6. #if dDOUBLE
  7. using dReal = System.Double;
  8. #else
  9. using dReal = System.Single;
  10. #endif
  11. public class TestBoxStack
  12. {
  13. #region Description of convex shape
  14. static dReal[] planes =
  15. {
  16. 1.0f, 0.0f, 0.0f, 0.25f,
  17. 0.0f, 1.0f, 0.0f, 0.25f,
  18. 0.0f, 0.0f, 1.0f, 0.25f,
  19. 0.0f, 0.0f, -1.0f, 0.25f,
  20. 0.0f, -1.0f, 0.0f, 0.25f,
  21. -1.0f, 0.0f , 0.0f, 0.25f
  22. };
  23. static dReal[] points =
  24. {
  25. 0.25f, 0.25f, 0.25f,
  26. -0.25f, 0.25f, 0.25f,
  27. 0.25f, -0.25f, 0.25f,
  28. -0.25f, -0.25f, 0.25f,
  29. 0.25f, 0.25f, -0.25f,
  30. -0.25f,0.25f,-0.25f,
  31. 0.25f,-0.25f,-0.25f,
  32. -0.25f,-0.25f,-0.25f,
  33. };
  34. static int[] polygons =
  35. {
  36. 4, 0, 2, 6, 4,
  37. 4, 1, 0, 4, 5,
  38. 4, 0, 1, 3, 2,
  39. 4, 3, 1, 5, 7,
  40. 4, 2, 3, 7, 6,
  41. 4, 5, 4, 6, 7,
  42. };
  43. #endregion
  44. const int NUM = 100;
  45. const float DENSITY = 5.0f;
  46. const int MAX_CONTACTS = 8;
  47. static IntPtr world;
  48. static IntPtr space;
  49. static IntPtr contactgroup;
  50. static Queue<IntPtr> obj = new Queue<IntPtr>();
  51. static d.Vector3 xyz = new d.Vector3(2.1640f, -1.3079f, 1.7600f);
  52. static d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f);
  53. static d.NearCallback nearCallback = near;
  54. static d.ContactGeom[] contacts = new d.ContactGeom[MAX_CONTACTS];
  55. static d.Contact contact;
  56. // Called when window is opened - sets up viewpoint and prints usage
  57. static void start(int unused)
  58. {
  59. ds.SetViewpoint(ref xyz, ref hpr);
  60. Console.WriteLine("To drop another object, press:");
  61. Console.WriteLine(" b for box.");
  62. Console.WriteLine(" s for sphere.");
  63. Console.WriteLine(" c for capsule.");
  64. Console.WriteLine(" y for cylinder.");
  65. Console.WriteLine(" v for a convex object.");
  66. Console.WriteLine(" x for a composite object.");
  67. Console.WriteLine("To select an object, press space.");
  68. Console.WriteLine("To disable the selected object, press d.");
  69. Console.WriteLine("To enable the selected object, press e.");
  70. Console.WriteLine("To toggle showing the geom AABBs, press a.");
  71. Console.WriteLine("To toggle showing the contact points, press t.");
  72. Console.WriteLine("To toggle dropping from random position/orientation, press r.");
  73. Console.WriteLine("To save the current state to 'state.dif', press 1.");
  74. }
  75. // Near callback - creates contact joints
  76. static void near(IntPtr space, IntPtr g1, IntPtr g2)
  77. {
  78. IntPtr b1 = d.GeomGetBody(g1);
  79. IntPtr b2 = d.GeomGetBody(g2);
  80. if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
  81. return;
  82. int count = d.Collide(g1, g2, MAX_CONTACTS, contacts, d.ContactGeom.SizeOf);
  83. for (int i = 0; i < count; ++i)
  84. {
  85. contact.geom = contacts[i];
  86. IntPtr joint = d.JointCreateContact(world, contactgroup, ref contact);
  87. d.JointAttach(joint, b1, b2);
  88. }
  89. }
  90. // Adds a new object to the scene - attaches a body to the geom and
  91. // sets the initial position and orientation
  92. static void addObject(IntPtr geom, d.Mass mass)
  93. {
  94. // Create a body for this object
  95. IntPtr body = d.BodyCreate(world);
  96. d.GeomSetBody(geom, body);
  97. d.BodySetMass(body, ref mass);
  98. obj.Enqueue(geom);
  99. // Set the position of the new object
  100. d.Matrix3 R;
  101. d.BodySetPosition(body, d.RandReal() * 2 - 1, d.RandReal() * 2 - 1, d.RandReal() + 2);
  102. d.RFromAxisAndAngle(out R, d.RandReal() * 2 - 1, d.RandReal() * 2 - 1, d.RandReal() * 2 - 1, d.RandReal() * 10 - 5);
  103. d.BodySetRotation(body, ref R);
  104. // Cap the total number of objects
  105. if (obj.Count > NUM)
  106. {
  107. geom = obj.Dequeue();
  108. body = d.GeomGetBody(geom);
  109. d.BodyDestroy(body);
  110. d.GeomDestroy(geom);
  111. }
  112. }
  113. // Keyboard callback
  114. static void command(int cmd)
  115. {
  116. IntPtr geom;
  117. d.Mass mass;
  118. d.Vector3 sides = new d.Vector3(d.RandReal() * 0.5f + 0.1f, d.RandReal() * 0.5f + 0.1f, d.RandReal() * 0.5f + 0.1f);
  119. Char ch = Char.ToLower((Char)cmd);
  120. switch ((Char)ch)
  121. {
  122. case 'b':
  123. d.MassSetBox(out mass, DENSITY, sides.X, sides.Y, sides.Z);
  124. geom = d.CreateBox(space, sides.X, sides.Y, sides.Z);
  125. addObject(geom, mass);
  126. break;
  127. case 'c':
  128. sides.X *= 0.5f;
  129. d.MassSetCapsule(out mass, DENSITY, 3, sides.X, sides.Y);
  130. geom = d.CreateCapsule(space, sides.X, sides.Y);
  131. addObject(geom, mass);
  132. break;
  133. case 'v':
  134. d.MassSetBox(out mass, DENSITY, 0.25f, 0.25f, 0.25f);
  135. geom = d.CreateConvex(space, planes, planes.Length / 4, points, points.Length / 3, polygons);
  136. addObject(geom, mass);
  137. break;
  138. }
  139. }
  140. // Draw an object in the scene
  141. static void drawGeom(IntPtr geom)
  142. {
  143. IntPtr body = d.GeomGetBody(geom);
  144. d.Vector3 pos;
  145. d.BodyCopyPosition(body, out pos);
  146. d.Matrix3 R;
  147. d.BodyCopyRotation(body, out R);
  148. d.GeomClassID type = d.GeomGetClass(geom);
  149. switch (type)
  150. {
  151. case d.GeomClassID.BoxClass:
  152. d.Vector3 sides;
  153. d.GeomBoxGetLengths(geom, out sides);
  154. ds.DrawBox(ref pos, ref R, ref sides);
  155. break;
  156. case d.GeomClassID.CapsuleClass:
  157. dReal radius, length;
  158. d.GeomCapsuleGetParams(geom, out radius, out length);
  159. ds.DrawCapsule(ref pos, ref R, length, radius);
  160. break;
  161. case d.GeomClassID.ConvexClass:
  162. ds.DrawConvex(ref pos, ref R, planes, planes.Length / 4, points, points.Length / 3, polygons);
  163. break;
  164. }
  165. }
  166. // Called once per frame; updates the scene
  167. static void step(int pause)
  168. {
  169. d.SpaceCollide(space, IntPtr.Zero, nearCallback);
  170. if (pause == 0)
  171. d.WorldQuickStep(world, 0.02f);
  172. d.JointGroupEmpty(contactgroup);
  173. ds.SetColor(1.0f, 1.0f, 0.0f);
  174. ds.SetTexture(ds.Texture.Wood);
  175. foreach (IntPtr geom in obj)
  176. {
  177. drawGeom(geom);
  178. }
  179. }
  180. static void Main(string[] args)
  181. {
  182. dInitODE();
  183. // Setup pointers to drawstuff callback functions
  184. ds.Functions fn;
  185. fn.version = ds.VERSION;
  186. fn.start = new ds.CallbackFunction(start);
  187. fn.step = new ds.CallbackFunction(step);
  188. fn.command = new ds.CallbackFunction(command);
  189. fn.stop = null;
  190. fn.path_to_textures = "../../../../drawstuff/textures";
  191. if (args.Length > 0)
  192. {
  193. fn.path_to_textures = args[0];
  194. }
  195. // Set up contact response parameters
  196. contact.surface.mode = d.ContactFlags.Bounce | d.ContactFlags.SoftCFM;
  197. contact.surface.mu = d.Infinity;
  198. contact.surface.mu2 = 0.0f;
  199. contact.surface.bounce = 0.1f;
  200. contact.surface.bounce_vel = 0.1f;
  201. contact.surface.soft_cfm = 0.01f;
  202. // Initialize the scene
  203. world = d.WorldCreate();
  204. space = d.HashSpaceCreate(IntPtr.Zero);
  205. contactgroup = d.JointGroupCreate(0);
  206. d.WorldSetGravity(world, 0.0f, 0.0f, -0.5f);
  207. d.WorldSetCFM(world, 1e-5f);
  208. d.WorldSetAutoDisableFlag(world, true);
  209. d.WorldSetContactMaxCorrectingVel(world, 0.1f);
  210. d.WorldSetContactSurfaceLayer(world, 0.001f);
  211. d.CreatePlane(space, 0, 0, 1, 0);
  212. // Run the scene
  213. ds.SimulationLoop(args.Length, args, 352, 288, ref fn);
  214. // Clean up
  215. d.JointGroupDestroy(contactgroup);
  216. d.SpaceDestroy(space);
  217. d.WorldDestroy(world);
  218. d.CloseODE();
  219. }
  220. }
  221. }