/PhysicsEngines/Tests3D/Tutorials.cs

#
C# | 452 lines | 293 code | 70 blank | 89 comment | 16 complexity | ee38d2a251ca96459bb3d447f5f5d054 MD5 | raw file
``````
using System.Collections.Generic;

using Delta.ContentSystem.Rendering;

using Delta.Engine;

using Delta.InputSystem;

using Delta.PhysicsEngines.VisualShapes;

using Delta.Rendering.Basics.Drawing;

using Delta.Rendering.Basics.Fonts;

using Delta.Rendering.Cameras;

using Delta.Rendering.Models;

using Delta.Utilities;

using Delta.Utilities.Datatypes;

using Delta.Utilities.Helpers;

using NUnit.Framework;

namespace Delta.PhysicsEngines.Tests3D

{

/// <summary>

/// Tutorials

/// </summary>

public class Tutorials

{

#region Simple3DSimulation (Static)

/// <summary>

/// Tutorial: 3D Physics Tutorial 1: Simple 3D Simulation

/// Difficulty: Easy

/// Description: Simple physics simulation with a ground, box and sphere.

/// Image: http://DeltaEngine.net/Icons/Physics3DTutorial1.png

/// </summary>

[Test, Category("Visual")]

public static void Simple3DSimulation()

{

const float planeHeight = -2f;

Physics.Instance.SetGroundPlane(true, planeHeight);

Matrix groundTransform = Matrix.CreateTranslation(0, 0f, planeHeight);

// Create two spheres...

VisualPhysicsSphere visualSphere1 =

new VisualPhysicsSphere(new Vector(2f, 0f, 5f), 2f, Color.Red);

VisualPhysicsSphere visualSphere2 =

new VisualPhysicsSphere(new Vector(3f, 0f, 10f), 2f, Color.Blue);

// ... and two boxes.

VisualPhysicsBox visualBox1 =

new VisualPhysicsBox(new Vector(2f, 0f, 20f), 4f, Color.Orange);

VisualPhysicsBox visualBox2 =

new VisualPhysicsBox(new Vector(6f, 1f, 32f), 4f, Color.Yellow);

// Create a camera for the 3d world.

LookAtCamera camera = new LookAtCamera(new Vector(10, -25, 25));

// And a mesh for drawing the ground plane.

Mesh plane =

Mesh.CreatePlane("GroundPlane", 50, 50, MaterialData.Default);

Application.Start(delegate

{

// Draw the spheres

visualSphere1.Draw();

visualSphere2.Draw();

// Draw the boxes

visualBox1.Draw();

visualBox2.Draw();

// Draw the ground plane

plane.Draw(ref groundTransform);

});

}

#endregion

#region RopeSimulation (Static)

/// <summary>

/// Tutorial: 3D Physics Tutorial 2: Rope Simulation

/// Difficulty: Easy

/// Description: Simple 3d physics rope simulation.

/// Image: http://DeltaEngine.net/Icons/Physics3DTutorial2.png

/// </summary>

[Test, Category("Visual")]

public static void RopeSimulation()

{

const int NumberOfRopeBoxes = 20;

// add a plane to the physics world

Physics.Instance.SetGroundPlane(true, 0f);

// this line of code also sets the camera, i.e. ViewProjection matrix

LookAtCamera camera = new LookAtCamera(new Vector(30, -30, 10));

BaseVisualPhysicsShape[] ropeShapes =

new BaseVisualPhysicsShape[NumberOfRopeBoxes];

BaseVisualPhysicsShape last = null;

for (int i = 0; i < NumberOfRopeBoxes; i++)

{

BaseVisualPhysicsShape shape = new VisualPhysicsBox(

new Vector((i * 3.5f) - 20, 0, 12.5f), 2f);

ropeShapes[i] = shape;

Vector pos2 = shape.Body.Position;

if (last != null)

{

Vector pos3 = last.Body.Position;

Vector dif = pos2 - pos3;

dif = dif * 0.5f;

dif = pos2 - dif;

PhysicsJoint joint = Physics.CreatePointOnPoint(last.Body,

shape.Body, dif);

}

last = shape;

}

BaseVisualPhysicsShape controllerShape = ropeShapes[0];

Mesh plane = Mesh.CreatePlane("Ground", 50, 50, MaterialData.Default);

Application.Start(delegate

{

// Draw the ground plane

plane.Draw();

foreach (BaseVisualPhysicsShape shape in ropeShapes)

{

shape.Draw();

}

Font.Default.Draw("You can control a box with W/A/S/D",

ScreenSpace.DrawArea);

if (Input.Keyboard.IsPressed(InputButton.W))

{

controllerShape.Body.ApplyForce(new Vector(0f, 0f, 5f),

controllerShape.Body.Position);

}

if (Input.Keyboard.IsPressed(InputButton.S))

{

controllerShape.Body.ApplyForce(new Vector(0f, 0f, -5f),

controllerShape.Body.Position);

}

if (Input.Keyboard.IsPressed(InputButton.A))

{

controllerShape.Body.ApplyForce(new Vector(0f, 5f, 0f),

controllerShape.Body.Position);

}

if (Input.Keyboard.IsPressed(InputButton.D))

{

controllerShape.Body.ApplyForce(new Vector(0f, -5f, 0f),

controllerShape.Body.Position);

}

});

}

#endregion

#region CollisionEvents (Static)

/// <summary>

/// Tutorial: 3D Physics Tutorial 3: Collision Events

/// Difficulty: Easy

/// Description: Simple tutorial showing how to use physic collision events.

/// Image: http://DeltaEngine.net/Icons/Physics3DTutorial3.png

/// </summary>

[Test, Category("Visual")]

public static void CollisionEvents()

{

// add a plane to the physics world

Physics.Instance.SetGroundPlane(true, 0f);

Physics.GroundBody.Name = "Plane";

Physics.GroundBody.CollisionBegin += delegate(PhysicsBody other)

{

Log.Info("Given body '" + other.Name + "' collides with the plane.");

};

Physics.GroundBody.CollisionEnd += delegate(PhysicsBody other)

{

Log.Info(

"Given body '" + other.Name + "' ends collision with the plane.");

};

// Create a camera for the 3d space.

LookAtCamera camera = new LookAtCamera(new Vector(30, -30, 10));

BaseVisualPhysicsShape[] drawable = new BaseVisualPhysicsShape[]

{

new VisualPhysicsBox(new Vector(0, 0, 27), 1.0f),

new VisualPhysicsBox(new Vector(0, 0, 24), 1.0f),

};

drawable[0].Body.Name = "Body1";

drawable[1].Body.Name = "Body2";

Mesh plane =

Mesh.CreatePlane("GroundPlane", 50, 50, MaterialData.Default);

Application.Start(delegate

{

// Draw the ground plane

plane.Draw();

foreach (BaseVisualPhysicsShape shape in drawable)

{

shape.Draw();

}

});

}

#endregion

#region ControlledSphere (Static)

/// <summary>

/// Tutorial: 3D Physics Tutorial 4: Controlled Sphere

/// Difficulty: Easy

/// Description: How to control a physic sphere with the keyboard.

/// Image: http://DeltaEngine.net/Icons/Physics3DTutorial4.png

/// </summary>

[Test, Category("Visual")]

public static void ControlledSphere()

{

Physics.Instance.SetGroundPlane(true, 0f);

// Create the sphere

PhysicsBody ball = Physics.CreateSphere(new Vector(2f, 0f, 5f), 2f);

ball.IsStatic = false;

ball.Friction = 0.4f;

ball.Restitution = 1f;

// Create a camera for the 3d world.

LookAtCamera camera = new LookAtCamera(new Vector(10, -25, 25))

{

//do not lock the camera: IsLocked = true,

};

// And a mesh for drawing the ground plane.

Mesh plane =

Mesh.CreatePlane("GroundPlane", 50, 50, MaterialData.Default);

Application.Start(delegate

{

Font.Default.Draw(

"You can control the sphere with W/A/S/D or stop it with Space",

ScreenSpace.DrawArea);

// Draw the spheres

Sphere.DrawOutline(ball.Position, 2f, Color.Red);

// Draw the ground plane

plane.Draw();

if (Input.Keyboard.IsPressed(InputButton.W))

{

ball.ApplyForce(new Vector(10f, 0f, 0f), Vector.UnitZ);

}

if (Input.Keyboard.IsPressed(InputButton.S))

{

ball.ApplyForce(new Vector(-10f, 0f, 0f), -Vector.UnitZ);

}

if (Input.Keyboard.IsPressed(InputButton.A))

{

ball.ApplyForce(new Vector(0f, 10f, 0f), Vector.UnitY);

}

if (Input.Keyboard.IsPressed(InputButton.D))

{

ball.ApplyForce(new Vector(0f, -10f, 0f), -Vector.UnitY);

}

if (Input.Keyboard.IsPressed(InputButton.Space))

{

ball.Stop();

}

});

}

#endregion

#region RayCasting3D (Static)

/// <summary>

/// Tutorial: 3D Physics Tutorial 5: Ray-Casting

/// Difficulty: Medium

/// Description: How to cast a ray into 3d and pick physic objects.

/// Image: http://DeltaEngine.net/Icons/Physics3DTutorial5.png

/// </summary>

[Test, Category("Visual")]

public static void RayCasting3D()

{

const int height = -5;

// add a plane to the physics world

Physics.Instance.SetGroundPlane(true, height);

Matrix planeTransform = Matrix.CreateTranslation(0, 0, height);

// create a box and a sphere

VisualPhysicsBox visualBox = new VisualPhysicsBox(

new Vector(-2, 0, 0), 4);

VisualPhysicsSphere visualSphere = new VisualPhysicsSphere(

new Vector(5, 0, 0), 2);

// create a camera

LookAtCamera cam = new LookAtCamera(new Vector(0, 25, 10));

// create a moving ray

Vector rayStart = new Vector(0, 0, 10);

Vector lookTarget = Vector.Zero;

Ray testRay = new Ray(rayStart, lookTarget - rayStart);

Mesh plane =

Mesh.CreatePlane("GroundPlane", 50, 50, MaterialData.Default);

Application.Start(delegate

{

// Draw the ground plane

plane.Draw(ref planeTransform);

//Draw the sphere and box

visualBox.Draw();

visualSphere.Draw();

PhysicsBody catchedBody;

Vector normal;

float fraction;

// render the line according to the deleted intersection

bool rayCastingHit = Physics.FindRayCast(testRay, false,

out catchedBody, out normal, out fraction);

// render up to the intersection point

Line.Draw(testRay.Position,

testRay.Position + 15.0f * testRay.Direction,

rayCastingHit

? Color.Red

: Color.Yellow);

// update the direction of the ray

lookTarget.X = 10f * MathHelper.Cos(90f * Time.CurrentExactTime);

lookTarget.Y = 2f * MathHelper.Sin(25f * Time.CurrentExactTime);

testRay.Direction = Vector.Normalize(lookTarget - testRay.Position);

});

}

#endregion

#region PyramidSimulation (Static)

/// <summary>

/// Tutorial: 3D Physics Tutorial 6: 3D Simulation with pyramid

/// Difficulty: Normal

/// Description: Physics simulation with a ground and pyramid shape created

/// with boxes.

/// Image: http://DeltaEngine.net/Icons/Physics3DTutorial6.png

/// </summary>

[Test, Category("Visual")]

public static void PyramidSimulation()

{

// Enable debug rendering.

//Physics.DebugEnabled = true;

const float planeHeight = -2f;

// Bullet is really slow for this test so only use 10 * 10 pyramid

// And use 30 * 30 for Jitter and JigLib (they handle this much quicker)

int pyramidSize =

Settings.Modules.PhysicsModule == "Bullet"

? 10

: 30;

Physics.Instance.SetGroundPlane(true, planeHeight);

Matrix groundTransform = Matrix.CreateTranslation(0, 0f, planeHeight);

List<BaseVisualPhysicsShape> shapesToDraw =

new List<BaseVisualPhysicsShape>();

for (int i = 0; i < pyramidSize; i++)

{

for (int e = i; e < pyramidSize; e++)

{

VisualPhysicsBox box = new VisualPhysicsBox(

new Vector((e - i * 0.5f) * 1.01f - 12.0f, 3.0f, 5.5f + i * 1.0f),

1.0f);

box.Body.Restitution = 0.0f;

}

}

// Create a camera for the 3d world.

LookAtCamera camera = new LookAtCamera(new Vector(10, -25, 25));

// And a mesh for drawing the ground plane.

Mesh plane =

Mesh.CreatePlane("GroundPlane", 50, 50, MaterialData.Default);

Application.Start(delegate

{

// Draw the spheres

foreach (BaseVisualPhysicsShape shape in shapesToDraw)

{

shape.Draw();

}

// Draw the ground plane

plane.Draw(ref groundTransform);

});

}

#endregion

#region BodyRestitution (Static)

/// <summary>

/// Tutorial: 3D Physics Tutorial 7: 3D Simulation with body restitution.

/// Difficulty: Normal

/// Description: Physics simulation with a ground, some spheres with

/// different restitution.

/// Image: http://DeltaEngine.net/Icons/Physics3DTutorial7.png

/// </summary>

[Test, Category("Visual")]

public static void BodyRestitution()

{

// Enable debug rendering.

Physics.DebugEnabled = true;

const float planeHeight = -2f;

Physics.Instance.SetGroundPlane(true, planeHeight);

Matrix groundTransform = Matrix.CreateTranslation(0, 0f, planeHeight);

List<BaseVisualPhysicsShape> shapesToDraw =

new List<BaseVisualPhysicsShape>();

for (int i = 0; i < 11; i++)

{

Vector position = new Vector(-15 + i * 3, 0, 5);

VisualPhysicsSphere sphere =

new VisualPhysicsSphere(position + Vector.UnitZ * 30, 1.0f);

// Set restitution.

sphere.Body.Restitution = i / 3.0f;

}

// Create a camera for the 3d world.

LookAtCamera camera = new LookAtCamera(new Vector(10, -25, 25));

// And a mesh for drawing the ground plane.

Mesh plane =

Mesh.CreatePlane("GroundPlane", 50, 50, MaterialData.Default);

Application.Start(delegate

{

// Draw the spheres

foreach (BaseVisualPhysicsShape shape in shapesToDraw)

{

shape.Draw();

}

// Draw the ground plane

plane.Draw(ref groundTransform);

});

}

#endregion

}

}

``````