PageRenderTime 120ms CodeModel.GetById 60ms app.highlight 30ms RepoModel.GetById 1ms app.codeStats 1ms

/PhysicsEngines/Bullet/BulletBody.cs

#
C# | 405 lines | 325 code | 46 blank | 34 comment | 4 complexity | 04c326574bc257b322bc30efef0e1690 MD5 | raw file
  1using System.Collections.Generic;
  2using BulletXNA;
  3using BulletXNA.BulletCollision;
  4using BulletXNA.BulletDynamics;
  5using Delta.PhysicsEngines.Enums;
  6using Delta.Rendering.Models;
  7using Delta.Utilities.Datatypes;
  8using Delta.Utilities.Helpers;
  9using BulletVector3 = Microsoft.Xna.Framework.Vector3;
 10using BulletMatrix = Microsoft.Xna.Framework.Matrix;
 11
 12namespace Delta.PhysicsEngines.Bullet
 13{
 14	/// <summary>
 15	/// Bullet implementation of PhysicsBody.
 16	/// </summary>
 17	internal class BulletBody : PhysicsBody
 18	{
 19		#region Position (Public)
 20		public override Vector Position
 21		{
 22			get
 23			{
 24				DefaultMotionState myMotionState =
 25					(DefaultMotionState)bulletBody.GetMotionState();
 26
 27				BulletMatrix bulletMatrix;
 28				myMotionState.GetWorldTransform(out bulletMatrix);
 29
 30				return BulletDatatypesMapping.Convert(
 31					bulletMatrix.Translation);
 32			}
 33			set
 34			{
 35				// Do we need to multiply here?
 36				var transMatrix = BulletMatrix.CreateTranslation(
 37					BulletDatatypesMapping.Convert(value));
 38
 39				DefaultMotionState motionState =
 40					(DefaultMotionState)bulletBody.GetMotionState();
 41
 42				motionState.m_graphicsWorldTrans = transMatrix;
 43			}
 44		}
 45		#endregion
 46
 47		#region Position2D (Public)
 48		public override Point Position2D
 49		{
 50			get
 51			{
 52				return Position.ToPoint();
 53			}
 54			set
 55			{
 56				// This is 3D physics engine, so do nothing by default.
 57			}
 58		}
 59		#endregion
 60
 61		#region LinearVelocity (Public)
 62		public override Vector LinearVelocity
 63		{
 64			get
 65			{
 66				BulletVector3 bulletVec = bulletBody.GetLinearVelocity();
 67				return BulletDatatypesMapping.Convert(bulletVec);
 68			}
 69			set
 70			{
 71				bulletBody.SetLinearVelocity(
 72					BulletDatatypesMapping.Convert(value));
 73			}
 74		}
 75		#endregion
 76
 77		#region AngularVelocity (Public)
 78		public override Vector AngularVelocity
 79		{
 80			get
 81			{
 82				BulletVector3 bulletVec = bulletBody.GetAngularVelocity();
 83				return BulletDatatypesMapping.Convert(bulletVec);
 84			}
 85			set
 86			{
 87				bulletBody.SetAngularVelocity(
 88					BulletDatatypesMapping.Convert(value));
 89			}
 90		}
 91		#endregion
 92
 93		#region AngularVelocity2D (Public)
 94		public override float AngularVelocity2D
 95		{
 96			get
 97			{
 98				return AngularVelocity.X;
 99			}
100			set
101			{
102				// This is 3D physics engine, so do nothing by default.
103			}
104		}
105		#endregion
106
107		#region Mass (Public)
108		public override float Mass
109		{
110			get
111			{
112				return base.Mass;
113			}
114			set
115			{
116				bulletBody.SetMassProps(value, initialInhertia);
117			}
118		}
119		#endregion
120
121		#region Restitution (Public)
122		public override float Restitution
123		{
124			get
125			{
126				return base.Restitution;
127			}
128			set
129			{
130				bulletBody.SetRestitution(value);
131				base.Restitution = value;
132			}
133		}
134		#endregion
135
136		#region BoundingBox (Public)
137		public override BoundingBox BoundingBox
138		{
139			get
140			{
141				// Probably this will be removed in future
142				BulletVector3 min, max;
143				bulletBody.GetAabb(out min, out max);
144				return new BoundingBox(
145					BulletDatatypesMapping.Convert(min),
146					BulletDatatypesMapping.Convert(max));
147			}
148		}
149		#endregion
150
151		#region Internal
152
153		#region bulletBody (Internal)
154		internal RigidBody bulletBody;
155		#endregion
156
157		#endregion
158
159		#region Private
160
161		#region bulletPhysics (Private)
162		private BulletPhysics bulletPhysics;
163		#endregion
164
165		#region bulletShape (Private)
166		private CollisionShape bulletShape;
167		#endregion
168
169		#region oldMass (Private)
170		private float oldMass;
171		#endregion
172
173		#region initialInhertia (Private)
174		private BulletVector3 initialInhertia;
175		#endregion
176
177		#endregion
178
179		#region Constructors
180		/// <summary>
181		/// Creates a new instance of <see cref="BulletBody"/>
182		/// </summary>
183		/// <param name="bulletPhysics">The physics manager.</param>
184		/// <param name="shape">The shape.</param>
185		public BulletBody(BulletPhysics bulletPhysics,
186			PhysicsShape shape, Vector initialPosition)
187			: base(false, shape, initialPosition)
188		{
189			this.bulletPhysics = bulletPhysics;
190
191			// First create shape.
192			CreateShape();
193
194			// Now create Bullet body.
195			CreateBody();
196
197			// Now add it to world simulation
198			bulletPhysics.bulletWorld.AddRigidBody(bulletBody);
199		}
200
201		/// <summary>
202		///  Internal constructor for creating GroundBody.
203		/// </summary>
204		/// <param name="bulletPhysics">The BulletPhysics implementation.</param>
205		/// <param name="bulletBody">The already create Bullet body.</param>
206		/// <param name="bulletShape">The already create Bullet CollisionShape.</param>
207		internal BulletBody(BulletPhysics bulletPhysics,
208			RigidBody bulletBody, CollisionShape bulletShape)
209			: base(false, null, Vector.Zero)
210		{
211			this.bulletPhysics = bulletPhysics;
212			this.bulletBody = bulletBody;
213			this.bulletShape = bulletShape;
214		}
215		#endregion
216
217		#region ApplyForce (Public)
218		public override void ApplyForce(Vector force)
219		{
220			BulletVector3 bulletVec = BulletDatatypesMapping.Convert(force);
221			BulletVector3 relPos = BulletVector3.Zero;
222			bulletBody.ApplyForce(ref bulletVec, ref relPos);
223		}
224
225		public override void ApplyForce(Vector force, Vector position)
226		{
227			BulletVector3 bulletVec = BulletDatatypesMapping.Convert(force);
228			BulletVector3 relPos = BulletDatatypesMapping.Convert(position);
229			bulletBody.ApplyForce(ref bulletVec, ref relPos);
230		}
231		#endregion
232
233		#region ApplyTorque (Public)
234		public override void ApplyTorque(Vector torque)
235		{
236			BulletVector3 bulletTorque = BulletDatatypesMapping.Convert(torque);
237			bulletBody.ApplyTorque(ref bulletTorque);
238		}
239		#endregion
240
241		#region ApplyLinearImpulse (Public)
242		public override void ApplyLinearImpulse(Vector impulse)
243		{
244			BulletVector3 bulletVec = BulletDatatypesMapping.Convert(impulse);
245			BulletVector3 relPos = BulletVector3.Zero;
246			bulletBody.ApplyImpulse(ref bulletVec, ref relPos);
247		}
248
249		public override void ApplyLinearImpulse(Vector impulse, Vector position)
250		{
251			BulletVector3 bulletVec = BulletDatatypesMapping.Convert(impulse);
252			BulletVector3 relPos = BulletDatatypesMapping.Convert(position);
253			bulletBody.ApplyImpulse(ref bulletVec, ref relPos);
254		}
255		#endregion
256
257		#region ApplyAngularImpulse (Public)
258		public override void ApplyAngularImpulse(Vector impulse)
259		{
260			BulletVector3 bulletVec = BulletDatatypesMapping.Convert(impulse);
261			BulletVector3 relPos = BulletVector3.Zero;
262			bulletBody.ApplyImpulse(ref bulletVec, ref relPos);
263		}
264		#endregion
265
266		#region Methods (Private)
267
268		#region CreateShape
269		/// <summary>
270		/// Creates Bullet CollsionShape from properties.
271		/// </summary>
272		private void CreateShape()
273		{
274			//http://www.bulletphysics.org/mediawiki-1.5.8/index.php/Collision_Shapes
275			Dictionary<PhysicsShape.PropertyType, object> properties =
276				base.Shape.Properties;
277			switch (Shape.ShapeType)
278			{
279				case ShapeType.Sphere:
280					bulletShape = new SphereShape(
281						ArrayHelper.SafeGet<PhysicsShape.PropertyType, float>(
282							properties, PhysicsShape.PropertyType.Radius));
283					break;
284				case ShapeType.Box:
285					Vector size =
286						ArrayHelper.SafeGet<PhysicsShape.PropertyType, Vector>(
287							properties, PhysicsShape.PropertyType.Size);
288					BulletVector3 bulletVector =
289						BulletDatatypesMapping.Convert(size / 2.0f);
290					bulletShape = new BoxShape(
291						ref bulletVector
292						);
293					break;
294				case ShapeType.Capsule:
295					bulletShape = new CapsuleShape(
296						ArrayHelper.SafeGet<PhysicsShape.PropertyType, float>(
297							properties, PhysicsShape.PropertyType.Radius),
298						ArrayHelper.SafeGet<PhysicsShape.PropertyType, float>(
299							properties, PhysicsShape.PropertyType.Depth));
300					break;
301				case ShapeType.Cone:
302					bulletShape = new ConeShape(
303						ArrayHelper.SafeGet<PhysicsShape.PropertyType, float>(
304							properties, PhysicsShape.PropertyType.Radius),
305						ArrayHelper.SafeGet<PhysicsShape.PropertyType, float>(
306							properties, PhysicsShape.PropertyType.Height));
307					break;
308				case ShapeType.Cylinder:
309					BulletVector3 bulletVec = new BulletVector3(
310						ArrayHelper.SafeGet<PhysicsShape.PropertyType, float>(
311							properties, PhysicsShape.PropertyType.Height),
312						ArrayHelper.SafeGet<PhysicsShape.PropertyType, float>(
313							properties, PhysicsShape.PropertyType.Radius),
314						ArrayHelper.SafeGet<PhysicsShape.PropertyType, float>(
315							properties, PhysicsShape.PropertyType.Height));
316					bulletShape = new CylinderShape(bulletVec);
317					break;
318
319				case ShapeType.Triangle:
320					bulletShape = Helpers.CreateFrom(
321						ArrayHelper.SafeGet<PhysicsShape.PropertyType, Mesh>(
322							properties, PhysicsShape.PropertyType.Mesh),
323						ArrayHelper.SafeGet<PhysicsShape.PropertyType, Matrix>(
324							properties, PhysicsShape.PropertyType.LocalSpaceMatrix),
325						ArrayHelper.SafeGet<PhysicsShape.PropertyType, bool>(
326							properties, PhysicsShape.PropertyType.InvertTriangles));
327					break;
328			}
329
330			// Store our body to collision user data.
331			bulletShape.SetUserPointer(this);
332		}
333		#endregion
334
335		#region CreateBody
336		/// <summary>
337		/// Creates Bullet body just after we create CollisionShape.
338		/// </summary>
339		private void CreateBody()
340		{
341			bool isDynamic = Mass != 0.0f;
342
343			initialInhertia = BulletVector3.Zero;
344			if (isDynamic)
345			{
346				bulletShape.CalculateLocalInertia(Mass, out initialInhertia);
347			}
348
349			BulletMatrix initialTransform =
350				BulletMatrix.CreateTranslation(
351					base.InitialPosition.X, base.InitialPosition.Y, base.InitialPosition.Z
352					);
353			// Using motionstate is recommended, it provides interpolation 
354			// capabilities, and only synchronizes 'active' objects
355			DefaultMotionState initialMotionState = new DefaultMotionState(
356				initialTransform, BulletMatrix.Identity);
357
358			RigidBodyConstructionInfo rbInfo = new RigidBodyConstructionInfo(
359				Mass, initialMotionState, bulletShape, initialInhertia);
360			rbInfo.m_restitution = base.restitution;
361
362			bulletBody = new RigidBody(rbInfo);
363			// Store our body to collision user data.
364			bulletBody.SetUserPointer(this);
365
366			// Apply mass and resitution too.
367			bulletBody.SetMassProps(base.Mass, initialInhertia);
368		}
369		#endregion
370
371		#region SetIsStatic
372		protected override void SetIsStatic(bool value)
373		{
374			if (value)
375			{
376				oldMass = base.Mass;
377				// By setting mass = 0.0 body is static in bullet
378				bulletBody.SetMassProps(0.0f, BulletVector3.Zero);
379			}
380			else
381			{
382				bulletBody.SetMassProps(oldMass, ref initialInhertia);
383			}
384		}
385		#endregion
386
387		#region SetIsActive
388		protected override void SetIsActive(bool value)
389		{
390			bulletBody.SetActivationState(value
391			                              	? ActivationState.ACTIVE_TAG
392			                              	: ActivationState.DISABLE_SIMULATION);
393		}
394		#endregion
395
396		#region SetFriction
397		protected override void SetFriction(float value)
398		{
399			bulletBody.SetFriction(value);
400		}
401		#endregion
402
403		#endregion
404	}
405}