PageRenderTime 166ms CodeModel.GetById 80ms app.highlight 43ms RepoModel.GetById 38ms app.codeStats 0ms

/PhysicsEngines/Tests3D/Tutorials.cs

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