PageRenderTime 105ms CodeModel.GetById 60ms app.highlight 18ms RepoModel.GetById 22ms app.codeStats 0ms

/PhysicsEngines/Jitter/JitterBody.cs

#
C# | 521 lines | 346 code | 47 blank | 128 comment | 4 complexity | dde6c5eeb4661de6c078fb8741b3a6df MD5 | raw file
  1using System.Collections.Generic;
  2using Delta.PhysicsEngines.Enums;
  3using Delta.Rendering.Models;
  4using Delta.Utilities.Datatypes;
  5using Delta.Utilities.Helpers;
  6using Jitter.Collision.Shapes;
  7using Jitter.Dynamics;
  8using Jitter.LinearMath;
  9
 10namespace Delta.PhysicsEngines.Jitter
 11{
 12	/// <summary>
 13	/// Jitter body implementation.
 14	/// </summary>
 15	internal class JitterBody : PhysicsBody
 16	{
 17		#region Body (Public)
 18		/// <summary>
 19		/// Gets the body.
 20		/// </summary>
 21		public RigidBody Body
 22		{
 23			get
 24			{
 25				return jitterBody;
 26			}
 27		}
 28		#endregion
 29
 30		#region Position (Public)
 31		/// <summary>
 32		/// Position given in world space.
 33		/// </summary>
 34		public override Vector Position
 35		{
 36			get
 37			{
 38				JitterDatatypesMapping.Convert(jitterBody.Position, out position);
 39				return position;
 40			}
 41			set
 42			{
 43				jitterBody.Position = JitterDatatypesMapping.Convert(ref value);
 44			}
 45		}
 46		#endregion
 47
 48		#region Position2D (Public)
 49		/// <summary>
 50		/// Position 2D given in world space (same as Position, just easier to
 51		/// access for 2D code not having to convert Position to a Point anymore).
 52		/// </summary>
 53		public override Point Position2D
 54		{
 55			get
 56			{
 57				position2D.X = jitterBody.Position.X;
 58				position2D.Y = jitterBody.Position.Y;
 59				return position2D;
 60			}
 61			set
 62			{
 63				// This is 3D physics engine, so do nothing by default.
 64			}
 65		}
 66		#endregion
 67
 68		#region RotationMatrix (Public)
 69		/// <summary>
 70		/// Returns the rotation matrix from Jitter back for rendering.
 71		/// </summary>
 72		public override Matrix RotationMatrix
 73		{
 74			get
 75			{
 76				JitterDatatypesMapping.Convert(jitterBody.Orientation,
 77					ref rotationMatrix);
 78				return rotationMatrix;
 79			}
 80			set
 81			{
 82				if (jitterBody != null)
 83				{
 84					jitterBody.Orientation = JitterDatatypesMapping.Convert(ref value);
 85				}
 86			}
 87		}
 88		#endregion
 89
 90		#region LinearVelocity (Public)
 91		/// <summary>
 92		/// The linear velocity of the body.
 93		/// </summary>
 94		public override Vector LinearVelocity
 95		{
 96			get
 97			{
 98				JitterDatatypesMapping.Convert(jitterBody.LinearVelocity,
 99					out linearVelocity);
100				return linearVelocity;
101			}
102			set
103			{
104				jitterBody.LinearVelocity = JitterDatatypesMapping.Convert(ref value);
105			}
106		}
107		#endregion
108
109		#region AngularVelocity (Public)
110		/// <summary>
111		/// The angular velocity of the body.
112		/// <remarks>
113		/// For 2D physics simulation only X component is used.
114		/// </remarks>
115		/// </summary>
116		public override Vector AngularVelocity
117		{
118			get
119			{
120				JitterDatatypesMapping.Convert(jitterBody.AngularVelocity,
121					out angularVelocity);
122				return angularVelocity;
123			}
124			set
125			{
126				jitterBody.AngularVelocity = JitterDatatypesMapping.Convert(ref value);
127			}
128		}
129		#endregion
130
131		#region AngularVelocity2D (Public)
132		/// <summary>
133		/// Angular velocity 2D as a float, for 2D only the .x component is used!
134		/// </summary>
135		public override float AngularVelocity2D
136		{
137			get
138			{
139				return jitterBody.AngularVelocity.X;
140			}
141			set
142			{
143				jitterBody.AngularVelocity = new JVector(value, 0f, 0f);
144			}
145		}
146		#endregion
147
148		#region Mass (Public)
149		/// <summary>
150		/// Gets or sets the mass. Usually in kilograms (kg).
151		/// </summary>
152		public override float Mass
153		{
154			get
155			{
156				return base.Mass;
157			}
158			set
159			{
160				jitterBody.Mass = value;
161			}
162		}
163		#endregion
164
165		#region Restitution (Public)
166		/// <summary>
167		/// Gets the restitution of the body.
168		/// </summary>
169		public override float Restitution
170		{
171			get
172			{
173				return base.Restitution;
174			}
175			set
176			{
177				jitterBody.Material.Restitution = value;
178				base.Restitution = value;
179			}
180		}
181		#endregion
182
183		#region BoundingBox (Public)
184		/// <summary>
185		/// Gets the BoundingBox of the body.
186		/// <remarks>
187		/// Used during 3D simulation.
188		/// </remarks>
189		/// </summary>
190		public override BoundingBox BoundingBox
191		{
192			get
193			{
194				JitterDatatypesMapping.Convert(jitterBody.BoundingBox.Min,
195					out bounds.Min);
196				JitterDatatypesMapping.Convert(jitterBody.BoundingBox.Max,
197					out bounds.Max);
198				return bounds;
199			}
200		}
201		#endregion
202
203		#region Private
204
205		#region physicsManager (Private)
206		private JitterPhysics physicsManager;
207		#endregion
208
209		#region jitterBody (Private)
210		private readonly RigidBody jitterBody;
211		#endregion
212
213		#region jitterShape (Private)
214		private Shape jitterShape;
215		#endregion
216
217		#region position (Private)
218		private Vector position;
219		#endregion
220
221		#region position2D (Private)
222		private Point position2D;
223		#endregion
224
225		#region rotationMatrix (Private)
226		/// <summary>
227		/// Create rotation matrix to be filled in by the Jitter matrix. It is
228		/// very important that M44 is set to 1.0 to be rendered correctly!
229		/// </summary>
230		private Matrix rotationMatrix = Matrix.Identity;
231		#endregion
232
233		#region linearVelocity (Private)
234		private Vector linearVelocity;
235		#endregion
236
237		#region angularVelocity (Private)
238		private Vector angularVelocity;
239		#endregion
240
241		#region bounds (Private)
242		private BoundingBox bounds;
243		#endregion
244
245		#endregion
246
247		#region Constructors
248		/// <summary>
249		/// Constructor
250		/// </summary>
251		/// <param name="physicsManager">The physics manager.</param>
252		/// <param name="shape">The shape.</param>
253		/// <param name="setInitialPosition">Body initial position.</param>
254		public JitterBody(JitterPhysics physicsManager, PhysicsShape shape,
255			Vector setInitialPosition)
256			: base(false, shape, setInitialPosition)
257		{
258			this.physicsManager = physicsManager;
259
260			// First create shape
261			CreateShape();
262			// And set the rotation matrix again (needs created shape)
263			RotationMatrix = Matrix.Identity;
264
265			// Jitter needs the shape on body creation.
266			jitterBody = new RigidBody(jitterShape);
267			jitterBody.IsStatic = false;
268			jitterBody.Mass = base.mass;
269			jitterBody.Material.Restitution = base.restitution;
270			jitterBody.Position =
271				JitterDatatypesMapping.Convert(ref setInitialPosition);
272
273			jitterBody.Tag = this;
274
275			physicsManager.jitterWorld.AddBody(jitterBody);
276		}
277
278		/// <summary>
279		/// Internal constructor for creating GroundBody.
280		/// </summary>
281		/// <param name="physicsManager">Jitter physics manager.</param>
282		/// <param name="jitterBody">Initial jitter body created manually.</param>
283		internal JitterBody(JitterPhysics physicsManager, RigidBody jitterBody)
284			: base(false, null, Vector.Zero)
285		{
286			this.physicsManager = physicsManager;
287			this.jitterBody = jitterBody;
288			this.jitterBody.Tag = this;
289			jitterShape = jitterBody.Shape;
290		}
291		#endregion
292
293		#region ApplyForce (Public)
294		/// <summary>
295		/// Applies a force at the center of mass.
296		/// </summary>
297		/// <param name="force">The force.</param>
298		public override void ApplyForce(Vector force)
299		{
300			jitterBody.AddForce(JitterDatatypesMapping.Convert(ref force));
301		}
302
303		/// <summary>
304		/// Apply a force at a world point. If the force is not
305		/// applied at the center of mass, it will generate a torque and
306		/// affect the angular velocity. This wakes up the body.
307		/// </summary>
308		/// <param name="force">Force vector data.</param>
309		/// <param name="position">Position in 3D where to apply force.</param>
310		public override void ApplyForce(Vector force, Vector position)
311		{
312			jitterBody.AddForce(
313				JitterDatatypesMapping.Convert(ref force),
314				JitterDatatypesMapping.Convert(ref position)
315				);
316		}
317		#endregion
318
319		#region ApplyTorque (Public)
320		/// <summary>
321		/// Apply a torque. This affects the angular velocity without affecting the
322		/// linear velocity of the center of mass.
323		/// <remarks>
324		/// This wakes up the body.
325		/// </remarks>
326		/// </summary>
327		/// <param name="torque">
328		/// Vector containing torque data for both 2D and 3D shapes.
329		/// </param>
330		public override void ApplyTorque(Vector torque)
331		{
332			jitterBody.AddTorque(JitterDatatypesMapping.Convert(ref torque));
333		}
334		#endregion
335
336		#region ApplyLinearImpulse (Public)
337		/// <summary>
338		/// Apply an impulse at a point. This immediately modifies the velocity.
339		/// <remarks>
340		/// This wakes up the body.
341		/// </remarks>
342		/// </summary>
343		/// <param name="impulse">Impulse vector data.</param>
344		public override void ApplyLinearImpulse(Vector impulse)
345		{
346			jitterBody.ApplyImpulse(JitterDatatypesMapping.Convert(ref impulse));
347		}
348
349		/// <summary>
350		/// Apply an impulse at a point. This immediately modifies the velocity.
351		/// It also modifies the angular velocity if the point of application
352		/// is not at the center of mass.
353		/// <remarks>
354		/// This wakes up the body.
355		/// </remarks>
356		/// </summary>
357		/// <param name="impulse">Impulse vector data.</param>
358		/// <param name="position">Position in 3D where to apply impulse.</param>
359		public override void ApplyLinearImpulse(Vector impulse, Vector position)
360		{
361			jitterBody.ApplyImpulse(
362				JitterDatatypesMapping.Convert(ref impulse),
363				JitterDatatypesMapping.Convert(ref position));
364		}
365		#endregion
366
367		#region ApplyAngularImpulse (Public)
368		/// <summary>
369		/// Apply an angular impulse.
370		/// </summary>
371		/// <param name="impulse">
372		/// Vector containing impulse data for both 2D and 3D shapes.
373		/// </param>
374		public override void ApplyAngularImpulse(Vector impulse)
375		{
376			jitterBody.ApplyImpulse(JitterDatatypesMapping.Convert(ref impulse));
377		}
378		#endregion
379
380		#region Methods (Private)
381
382		#region CreateShape
383		/// <summary>
384		/// Creates Jitter shape from properties.
385		/// </summary>
386		private void CreateShape()
387		{
388			Dictionary<PhysicsShape.PropertyType, object> properties =
389				base.Shape.Properties;
390			switch (Shape.ShapeType)
391			{
392				case ShapeType.Sphere:
393					jitterShape = new SphereShape(
394						ArrayHelper.SafeGet<PhysicsShape.PropertyType, float>(
395							properties, PhysicsShape.PropertyType.Radius));
396					break;
397				case ShapeType.Box:
398					Vector size =
399						ArrayHelper.SafeGet<PhysicsShape.PropertyType, Vector>(
400							properties, PhysicsShape.PropertyType.Size);
401					jitterShape = new BoxShape(
402						size.Y, size.Z, size.X
403						);
404					break;
405
406				case ShapeType.Capsule:
407					jitterShape = new CapsuleShape(
408						ArrayHelper.SafeGet<PhysicsShape.PropertyType, float>(
409							properties, PhysicsShape.PropertyType.Depth),
410						ArrayHelper.SafeGet<PhysicsShape.PropertyType, float>(
411							properties, PhysicsShape.PropertyType.Radius)
412						);
413					break;
414
415				case ShapeType.Cone:
416					jitterShape = new ConeShape(
417						ArrayHelper.SafeGet<PhysicsShape.PropertyType, float>(
418							properties, PhysicsShape.PropertyType.Height),
419						ArrayHelper.SafeGet<PhysicsShape.PropertyType, float>(
420							properties, PhysicsShape.PropertyType.Radius)
421						);
422					break;
423
424				case ShapeType.Cylinder:
425					jitterShape = new CylinderShape(
426						ArrayHelper.SafeGet<PhysicsShape.PropertyType, float>(
427							properties, PhysicsShape.PropertyType.Height),
428						ArrayHelper.SafeGet<PhysicsShape.PropertyType, float>(
429							properties, PhysicsShape.PropertyType.Radius)
430						);
431					break;
432
433				case ShapeType.Triangle:
434					jitterShape = Helpers.CreateFrom(
435						ArrayHelper.SafeGet<PhysicsShape.PropertyType, Mesh>(
436							properties, PhysicsShape.PropertyType.Mesh),
437						ArrayHelper.SafeGet<PhysicsShape.PropertyType, Matrix>(
438							properties, PhysicsShape.PropertyType.LocalSpaceMatrix),
439						ArrayHelper.SafeGet<PhysicsShape.PropertyType, bool>(
440							properties, PhysicsShape.PropertyType.InvertTriangles));
441					break;
442
443				case ShapeType.Terrain:
444					jitterShape = new TerrainShape(
445						ArrayHelper.SafeGet<PhysicsShape.PropertyType, float[,]>(
446							properties, PhysicsShape.PropertyType.Height),
447						ArrayHelper.SafeGet<PhysicsShape.PropertyType, float>(
448							properties, PhysicsShape.PropertyType.ScaleX),
449						ArrayHelper.SafeGet<PhysicsShape.PropertyType, float>(
450							properties, PhysicsShape.PropertyType.ScaleY)
451						);
452					break;
453			}
454		}
455		#endregion
456
457		#region FireCollisionBegin
458		/// <summary>
459		/// Method for access collision event from JitterPhysicsManager.
460		/// </summary>
461		/// <param name="other">Other body with which collision begin.</param>
462		internal void FireCollisionBegin(PhysicsBody other)
463		{
464			base.OnCollisionBegin(other);
465		}
466		#endregion
467
468		#region FireCollisionEnd
469		/// <summary>
470		/// Method for access collision event from JitterPhysicsManager.
471		/// </summary>
472		/// <param name="other">Other body with which collision end.</param>
473		internal void FireCollisionEnd(PhysicsBody other)
474		{
475			base.OnCollisionEnd(other);
476		}
477		#endregion
478
479		#region SetIsStatic
480		/// <summary>
481		/// Set if the body should be static or not.
482		/// </summary>
483		/// <param name="value">True if body should be static, otherwise False.
484		/// </param>
485		protected override void SetIsStatic(bool value)
486		{
487			jitterBody.IsStatic = value;
488		}
489		#endregion
490
491		#region SetIsActive
492		/// <summary>
493		/// Set if the body should be active or not.
494		/// </summary>
495		/// <param name="value">True if body should be active, otherwise False.
496		/// </param>
497		protected override void SetIsActive(bool value)
498		{
499			jitterBody.IsActive = value;
500		}
501		#endregion
502
503		#region SetFriction
504		/// <summary>
505		/// Set the friction of the body.
506		/// </summary>
507		/// <param name="value">Friction value to set.</param>
508		protected override void SetFriction(float value)
509		{
510			Body.Material.DynamicFriction = value;
511
512			if (IsStatic)
513			{
514				jitterBody.Material.StaticFriction = value;
515			}
516		}
517		#endregion
518
519		#endregion
520	}
521}