PageRenderTime 42ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/PhysicsEngines/Tests3D/Tutorials.cs

#
C# | 452 lines | 293 code | 70 blank | 89 comment | 16 complexity | ee38d2a251ca96459bb3d447f5f5d054 MD5 | raw file
Possible License(s): Apache-2.0
  1. using System.Collections.Generic;
  2. using Delta.ContentSystem.Rendering;
  3. using Delta.Engine;
  4. using Delta.InputSystem;
  5. using Delta.PhysicsEngines.VisualShapes;
  6. using Delta.Rendering.Basics.Drawing;
  7. using Delta.Rendering.Basics.Fonts;
  8. using Delta.Rendering.Cameras;
  9. using Delta.Rendering.Models;
  10. using Delta.Utilities;
  11. using Delta.Utilities.Datatypes;
  12. using Delta.Utilities.Helpers;
  13. using NUnit.Framework;
  14. namespace Delta.PhysicsEngines.Tests3D
  15. {
  16. /// <summary>
  17. /// Tutorials
  18. /// </summary>
  19. public class Tutorials
  20. {
  21. #region Simple3DSimulation (Static)
  22. /// <summary>
  23. /// Tutorial: 3D Physics Tutorial 1: Simple 3D Simulation
  24. /// Difficulty: Easy
  25. /// Description: Simple physics simulation with a ground, box and sphere.
  26. /// Image: http://DeltaEngine.net/Icons/Physics3DTutorial1.png
  27. /// </summary>
  28. [Test, Category("Visual")]
  29. public static void Simple3DSimulation()
  30. {
  31. const float planeHeight = -2f;
  32. Physics.Instance.SetGroundPlane(true, planeHeight);
  33. Matrix groundTransform = Matrix.CreateTranslation(0, 0f, planeHeight);
  34. // Create two spheres...
  35. VisualPhysicsSphere visualSphere1 =
  36. new VisualPhysicsSphere(new Vector(2f, 0f, 5f), 2f, Color.Red);
  37. VisualPhysicsSphere visualSphere2 =
  38. new VisualPhysicsSphere(new Vector(3f, 0f, 10f), 2f, Color.Blue);
  39. // ... and two boxes.
  40. VisualPhysicsBox visualBox1 =
  41. new VisualPhysicsBox(new Vector(2f, 0f, 20f), 4f, Color.Orange);
  42. VisualPhysicsBox visualBox2 =
  43. new VisualPhysicsBox(new Vector(6f, 1f, 32f), 4f, Color.Yellow);
  44. // Create a camera for the 3d world.
  45. LookAtCamera camera = new LookAtCamera(new Vector(10, -25, 25));
  46. // And a mesh for drawing the ground plane.
  47. Mesh plane =
  48. Mesh.CreatePlane("GroundPlane", 50, 50, MaterialData.Default);
  49. Application.Start(delegate
  50. {
  51. // Draw the spheres
  52. visualSphere1.Draw();
  53. visualSphere2.Draw();
  54. // Draw the boxes
  55. visualBox1.Draw();
  56. visualBox2.Draw();
  57. // Draw the ground plane
  58. plane.Draw(ref groundTransform);
  59. });
  60. }
  61. #endregion
  62. #region RopeSimulation (Static)
  63. /// <summary>
  64. /// Tutorial: 3D Physics Tutorial 2: Rope Simulation
  65. /// Difficulty: Easy
  66. /// Description: Simple 3d physics rope simulation.
  67. /// Image: http://DeltaEngine.net/Icons/Physics3DTutorial2.png
  68. /// </summary>
  69. [Test, Category("Visual")]
  70. public static void RopeSimulation()
  71. {
  72. const int NumberOfRopeBoxes = 20;
  73. // add a plane to the physics world
  74. Physics.Instance.SetGroundPlane(true, 0f);
  75. // this line of code also sets the camera, i.e. ViewProjection matrix
  76. LookAtCamera camera = new LookAtCamera(new Vector(30, -30, 10));
  77. BaseVisualPhysicsShape[] ropeShapes =
  78. new BaseVisualPhysicsShape[NumberOfRopeBoxes];
  79. BaseVisualPhysicsShape last = null;
  80. for (int i = 0; i < NumberOfRopeBoxes; i++)
  81. {
  82. BaseVisualPhysicsShape shape = new VisualPhysicsBox(
  83. new Vector((i * 3.5f) - 20, 0, 12.5f), 2f);
  84. ropeShapes[i] = shape;
  85. Vector pos2 = shape.Body.Position;
  86. if (last != null)
  87. {
  88. Vector pos3 = last.Body.Position;
  89. Vector dif = pos2 - pos3;
  90. dif = dif * 0.5f;
  91. dif = pos2 - dif;
  92. PhysicsJoint joint = Physics.CreatePointOnPoint(last.Body,
  93. shape.Body, dif);
  94. }
  95. last = shape;
  96. }
  97. BaseVisualPhysicsShape controllerShape = ropeShapes[0];
  98. Mesh plane = Mesh.CreatePlane("Ground", 50, 50, MaterialData.Default);
  99. Application.Start(delegate
  100. {
  101. // Draw the ground plane
  102. plane.Draw();
  103. foreach (BaseVisualPhysicsShape shape in ropeShapes)
  104. {
  105. shape.Draw();
  106. }
  107. Font.Default.Draw("You can control a box with W/A/S/D",
  108. ScreenSpace.DrawArea);
  109. if (Input.Keyboard.IsPressed(InputButton.W))
  110. {
  111. controllerShape.Body.ApplyForce(new Vector(0f, 0f, 5f),
  112. controllerShape.Body.Position);
  113. }
  114. if (Input.Keyboard.IsPressed(InputButton.S))
  115. {
  116. controllerShape.Body.ApplyForce(new Vector(0f, 0f, -5f),
  117. controllerShape.Body.Position);
  118. }
  119. if (Input.Keyboard.IsPressed(InputButton.A))
  120. {
  121. controllerShape.Body.ApplyForce(new Vector(0f, 5f, 0f),
  122. controllerShape.Body.Position);
  123. }
  124. if (Input.Keyboard.IsPressed(InputButton.D))
  125. {
  126. controllerShape.Body.ApplyForce(new Vector(0f, -5f, 0f),
  127. controllerShape.Body.Position);
  128. }
  129. });
  130. }
  131. #endregion
  132. #region CollisionEvents (Static)
  133. /// <summary>
  134. /// Tutorial: 3D Physics Tutorial 3: Collision Events
  135. /// Difficulty: Easy
  136. /// Description: Simple tutorial showing how to use physic collision events.
  137. /// Image: http://DeltaEngine.net/Icons/Physics3DTutorial3.png
  138. /// </summary>
  139. [Test, Category("Visual")]
  140. public static void CollisionEvents()
  141. {
  142. // add a plane to the physics world
  143. Physics.Instance.SetGroundPlane(true, 0f);
  144. Physics.GroundBody.Name = "Plane";
  145. Physics.GroundBody.CollisionBegin += delegate(PhysicsBody other)
  146. {
  147. Log.Info("Given body '" + other.Name + "' collides with the plane.");
  148. };
  149. Physics.GroundBody.CollisionEnd += delegate(PhysicsBody other)
  150. {
  151. Log.Info(
  152. "Given body '" + other.Name + "' ends collision with the plane.");
  153. };
  154. // Create a camera for the 3d space.
  155. LookAtCamera camera = new LookAtCamera(new Vector(30, -30, 10));
  156. BaseVisualPhysicsShape[] drawable = new BaseVisualPhysicsShape[]
  157. {
  158. new VisualPhysicsBox(new Vector(0, 0, 27), 1.0f),
  159. new VisualPhysicsBox(new Vector(0, 0, 24), 1.0f),
  160. };
  161. drawable[0].Body.Name = "Body1";
  162. drawable[1].Body.Name = "Body2";
  163. Mesh plane =
  164. Mesh.CreatePlane("GroundPlane", 50, 50, MaterialData.Default);
  165. Application.Start(delegate
  166. {
  167. // Draw the ground plane
  168. plane.Draw();
  169. foreach (BaseVisualPhysicsShape shape in drawable)
  170. {
  171. shape.Draw();
  172. }
  173. });
  174. }
  175. #endregion
  176. #region ControlledSphere (Static)
  177. /// <summary>
  178. /// Tutorial: 3D Physics Tutorial 4: Controlled Sphere
  179. /// Difficulty: Easy
  180. /// Description: How to control a physic sphere with the keyboard.
  181. /// Image: http://DeltaEngine.net/Icons/Physics3DTutorial4.png
  182. /// </summary>
  183. [Test, Category("Visual")]
  184. public static void ControlledSphere()
  185. {
  186. Physics.Instance.SetGroundPlane(true, 0f);
  187. // Create the sphere
  188. PhysicsBody ball = Physics.CreateSphere(new Vector(2f, 0f, 5f), 2f);
  189. ball.IsStatic = false;
  190. ball.Friction = 0.4f;
  191. ball.Restitution = 1f;
  192. // Create a camera for the 3d world.
  193. LookAtCamera camera = new LookAtCamera(new Vector(10, -25, 25))
  194. {
  195. //do not lock the camera: IsLocked = true,
  196. };
  197. // And a mesh for drawing the ground plane.
  198. Mesh plane =
  199. Mesh.CreatePlane("GroundPlane", 50, 50, MaterialData.Default);
  200. Application.Start(delegate
  201. {
  202. Font.Default.Draw(
  203. "You can control the sphere with W/A/S/D or stop it with Space",
  204. ScreenSpace.DrawArea);
  205. // Draw the spheres
  206. Sphere.DrawOutline(ball.Position, 2f, Color.Red);
  207. // Draw the ground plane
  208. plane.Draw();
  209. if (Input.Keyboard.IsPressed(InputButton.W))
  210. {
  211. ball.ApplyForce(new Vector(10f, 0f, 0f), Vector.UnitZ);
  212. }
  213. if (Input.Keyboard.IsPressed(InputButton.S))
  214. {
  215. ball.ApplyForce(new Vector(-10f, 0f, 0f), -Vector.UnitZ);
  216. }
  217. if (Input.Keyboard.IsPressed(InputButton.A))
  218. {
  219. ball.ApplyForce(new Vector(0f, 10f, 0f), Vector.UnitY);
  220. }
  221. if (Input.Keyboard.IsPressed(InputButton.D))
  222. {
  223. ball.ApplyForce(new Vector(0f, -10f, 0f), -Vector.UnitY);
  224. }
  225. if (Input.Keyboard.IsPressed(InputButton.Space))
  226. {
  227. ball.Stop();
  228. }
  229. });
  230. }
  231. #endregion
  232. #region RayCasting3D (Static)
  233. /// <summary>
  234. /// Tutorial: 3D Physics Tutorial 5: Ray-Casting
  235. /// Difficulty: Medium
  236. /// Description: How to cast a ray into 3d and pick physic objects.
  237. /// Image: http://DeltaEngine.net/Icons/Physics3DTutorial5.png
  238. /// </summary>
  239. [Test, Category("Visual")]
  240. public static void RayCasting3D()
  241. {
  242. const int height = -5;
  243. // add a plane to the physics world
  244. Physics.Instance.SetGroundPlane(true, height);
  245. Matrix planeTransform = Matrix.CreateTranslation(0, 0, height);
  246. // create a box and a sphere
  247. VisualPhysicsBox visualBox = new VisualPhysicsBox(
  248. new Vector(-2, 0, 0), 4);
  249. VisualPhysicsSphere visualSphere = new VisualPhysicsSphere(
  250. new Vector(5, 0, 0), 2);
  251. // create a camera
  252. LookAtCamera cam = new LookAtCamera(new Vector(0, 25, 10));
  253. // create a moving ray
  254. Vector rayStart = new Vector(0, 0, 10);
  255. Vector lookTarget = Vector.Zero;
  256. Ray testRay = new Ray(rayStart, lookTarget - rayStart);
  257. Mesh plane =
  258. Mesh.CreatePlane("GroundPlane", 50, 50, MaterialData.Default);
  259. Application.Start(delegate
  260. {
  261. // Draw the ground plane
  262. plane.Draw(ref planeTransform);
  263. //Draw the sphere and box
  264. visualBox.Draw();
  265. visualSphere.Draw();
  266. PhysicsBody catchedBody;
  267. Vector normal;
  268. float fraction;
  269. // render the line according to the deleted intersection
  270. bool rayCastingHit = Physics.FindRayCast(testRay, false,
  271. out catchedBody, out normal, out fraction);
  272. // render up to the intersection point
  273. Line.Draw(testRay.Position,
  274. testRay.Position + 15.0f * testRay.Direction,
  275. rayCastingHit
  276. ? Color.Red
  277. : Color.Yellow);
  278. // update the direction of the ray
  279. lookTarget.X = 10f * MathHelper.Cos(90f * Time.CurrentExactTime);
  280. lookTarget.Y = 2f * MathHelper.Sin(25f * Time.CurrentExactTime);
  281. testRay.Direction = Vector.Normalize(lookTarget - testRay.Position);
  282. });
  283. }
  284. #endregion
  285. #region PyramidSimulation (Static)
  286. /// <summary>
  287. /// Tutorial: 3D Physics Tutorial 6: 3D Simulation with pyramid
  288. /// Difficulty: Normal
  289. /// Description: Physics simulation with a ground and pyramid shape created
  290. /// with boxes.
  291. /// Image: http://DeltaEngine.net/Icons/Physics3DTutorial6.png
  292. /// </summary>
  293. [Test, Category("Visual")]
  294. public static void PyramidSimulation()
  295. {
  296. // Enable debug rendering.
  297. //Physics.DebugEnabled = true;
  298. const float planeHeight = -2f;
  299. // Bullet is really slow for this test so only use 10 * 10 pyramid
  300. // And use 30 * 30 for Jitter and JigLib (they handle this much quicker)
  301. int pyramidSize =
  302. Settings.Modules.PhysicsModule == "Bullet"
  303. ? 10
  304. : 30;
  305. Physics.Instance.SetGroundPlane(true, planeHeight);
  306. Matrix groundTransform = Matrix.CreateTranslation(0, 0f, planeHeight);
  307. List<BaseVisualPhysicsShape> shapesToDraw =
  308. new List<BaseVisualPhysicsShape>();
  309. for (int i = 0; i < pyramidSize; i++)
  310. {
  311. for (int e = i; e < pyramidSize; e++)
  312. {
  313. VisualPhysicsBox box = new VisualPhysicsBox(
  314. new Vector((e - i * 0.5f) * 1.01f - 12.0f, 3.0f, 5.5f + i * 1.0f),
  315. 1.0f);
  316. shapesToDraw.Add(box);
  317. box.Body.Restitution = 0.0f;
  318. }
  319. }
  320. // Create a camera for the 3d world.
  321. LookAtCamera camera = new LookAtCamera(new Vector(10, -25, 25));
  322. // And a mesh for drawing the ground plane.
  323. Mesh plane =
  324. Mesh.CreatePlane("GroundPlane", 50, 50, MaterialData.Default);
  325. Application.Start(delegate
  326. {
  327. // Draw the spheres
  328. foreach (BaseVisualPhysicsShape shape in shapesToDraw)
  329. {
  330. shape.Draw();
  331. }
  332. // Draw the ground plane
  333. plane.Draw(ref groundTransform);
  334. });
  335. }
  336. #endregion
  337. #region BodyRestitution (Static)
  338. /// <summary>
  339. /// Tutorial: 3D Physics Tutorial 7: 3D Simulation with body restitution.
  340. /// Difficulty: Normal
  341. /// Description: Physics simulation with a ground, some spheres with
  342. /// different restitution.
  343. /// Image: http://DeltaEngine.net/Icons/Physics3DTutorial7.png
  344. /// </summary>
  345. [Test, Category("Visual")]
  346. public static void BodyRestitution()
  347. {
  348. // Enable debug rendering.
  349. Physics.DebugEnabled = true;
  350. const float planeHeight = -2f;
  351. Physics.Instance.SetGroundPlane(true, planeHeight);
  352. Matrix groundTransform = Matrix.CreateTranslation(0, 0f, planeHeight);
  353. List<BaseVisualPhysicsShape> shapesToDraw =
  354. new List<BaseVisualPhysicsShape>();
  355. for (int i = 0; i < 11; i++)
  356. {
  357. Vector position = new Vector(-15 + i * 3, 0, 5);
  358. VisualPhysicsSphere sphere =
  359. new VisualPhysicsSphere(position + Vector.UnitZ * 30, 1.0f);
  360. // Set restitution.
  361. sphere.Body.Restitution = i / 3.0f;
  362. shapesToDraw.Add(sphere);
  363. }
  364. // Create a camera for the 3d world.
  365. LookAtCamera camera = new LookAtCamera(new Vector(10, -25, 25));
  366. // And a mesh for drawing the ground plane.
  367. Mesh plane =
  368. Mesh.CreatePlane("GroundPlane", 50, 50, MaterialData.Default);
  369. Application.Start(delegate
  370. {
  371. // Draw the spheres
  372. foreach (BaseVisualPhysicsShape shape in shapesToDraw)
  373. {
  374. shape.Draw();
  375. }
  376. // Draw the ground plane
  377. plane.Draw(ref groundTransform);
  378. });
  379. }
  380. #endregion
  381. }
  382. }