PageRenderTime 50ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/PhysicsEngines/Bullet/BulletBody.cs

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