PageRenderTime 49ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/PhysicsEngines/JigLib/JiglibBody.cs

#
C# | 560 lines | 374 code | 61 blank | 125 comment | 8 complexity | e4fe6526f69687bc95ede557ce7b8c54 MD5 | raw file
Possible License(s): Apache-2.0
  1. using System.Collections.Generic;
  2. using Delta.PhysicsEngines.Enums;
  3. using Delta.Rendering.Models;
  4. using Delta.Utilities;
  5. using Delta.Utilities.Datatypes;
  6. using Delta.Utilities.Helpers;
  7. using JigLibX.Collision;
  8. using JigLibX.Geometry;
  9. using JigLibX.Math;
  10. using JigLibX.Physics;
  11. using Plane = JigLibX.Geometry.Plane;
  12. using XnaMatrix = Microsoft.Xna.Framework.Matrix;
  13. using XnaVector3 = Microsoft.Xna.Framework.Vector3;
  14. namespace Delta.PhysicsEngines.JigLib
  15. {
  16. internal class JigLibBody : PhysicsBody
  17. {
  18. #region Body (Public)
  19. /// <summary>
  20. /// The Body handles all the physics of motion: position, velocity,
  21. /// acceleration forces, torques, etc... A body can only be added to one
  22. /// physics system at a time!
  23. /// </summary>
  24. public Body Body
  25. {
  26. get
  27. {
  28. return jigLibBody;
  29. }
  30. }
  31. #endregion
  32. #region Skin (Public)
  33. /// <summary>
  34. /// The JigLib colllision skin.
  35. /// </summary>
  36. public CollisionSkin Skin
  37. {
  38. get
  39. {
  40. return jigLibSkin;
  41. }
  42. }
  43. #endregion
  44. #region Position (Public)
  45. /// <summary>
  46. /// Position given in world space.
  47. /// </summary>
  48. public override Vector Position
  49. {
  50. get
  51. {
  52. JigLibDatatypesMapping.Convert(jigLibBody.Position, out position);
  53. return position;
  54. }
  55. set
  56. {
  57. jigLibBody.MoveTo(JigLibDatatypesMapping.Convert(ref value),
  58. Body.Orientation);
  59. }
  60. }
  61. #endregion
  62. #region Position2D (Public)
  63. /// <summary>
  64. /// Position 2D given in world space (same as Position, just easier to
  65. /// access for 2D code not having to convert Position to a Point anymore).
  66. /// </summary>
  67. public override Point Position2D
  68. {
  69. get
  70. {
  71. position2D.X = jigLibBody.Position.X;
  72. position2D.Y = jigLibBody.Position.Y;
  73. return position2D;
  74. }
  75. set
  76. {
  77. // This is 3D physics engine, so do nothing by default.
  78. }
  79. }
  80. #endregion
  81. #region RotationMatrix (Public)
  82. /// <summary>
  83. /// Rotation matrix
  84. /// </summary>
  85. public override Matrix RotationMatrix
  86. {
  87. get
  88. {
  89. JigLibDatatypesMapping.Convert(Body.Orientation, ref rotationMatrix);
  90. return rotationMatrix;
  91. }
  92. set
  93. {
  94. if (Body != null)
  95. {
  96. XnaMatrix xnaMatrix;
  97. JigLibDatatypesMapping.Convert(ref value, out xnaMatrix);
  98. Body.MoveTo(Body.Position, xnaMatrix);
  99. }
  100. }
  101. }
  102. #endregion
  103. #region LinearVelocity (Public)
  104. /// <summary>
  105. /// The velocity of the body.
  106. /// </summary>
  107. public override Vector LinearVelocity
  108. {
  109. get
  110. {
  111. JigLibDatatypesMapping.Convert(jigLibBody.Velocity,
  112. out linearVelocity);
  113. return linearVelocity;
  114. }
  115. set
  116. {
  117. jigLibBody.Velocity = JigLibDatatypesMapping.Convert(ref value);
  118. }
  119. }
  120. #endregion
  121. #region AngularVelocity (Public)
  122. /// <summary>
  123. /// The angular velocity of the body.
  124. /// <remarks>
  125. /// For 2D physics simulation only X component is used.
  126. /// </remarks>
  127. /// </summary>
  128. public override Vector AngularVelocity
  129. {
  130. get
  131. {
  132. JigLibDatatypesMapping.Convert(jigLibBody.AngularVelocity,
  133. out angularVelocity);
  134. return angularVelocity;
  135. }
  136. set
  137. {
  138. jigLibBody.AngularVelocity = JigLibDatatypesMapping.Convert(ref value);
  139. }
  140. }
  141. #endregion
  142. #region AngularVelocity2D (Public)
  143. /// <summary>
  144. /// Angular velocity 2D as a float, for 2D only the .x component is used!
  145. /// </summary>
  146. public override float AngularVelocity2D
  147. {
  148. get
  149. {
  150. return jigLibBody.AngularVelocity.X;
  151. }
  152. set
  153. {
  154. xnaAngularVelocity2D.X = value;
  155. jigLibBody.AngularVelocity = xnaAngularVelocity2D;
  156. }
  157. }
  158. #endregion
  159. #region BoundingBox (Public)
  160. /// <summary>
  161. /// Gets the BoundingBox of the body.
  162. /// </summary>
  163. /// <remarks>
  164. /// Used during 3D simulation.
  165. /// </remarks>
  166. public override BoundingBox BoundingBox
  167. {
  168. get
  169. {
  170. JigLibDatatypesMapping.Convert(jigLibSkin.WorldBoundingBox.Min,
  171. out boundingBox.Min);
  172. JigLibDatatypesMapping.Convert(jigLibSkin.WorldBoundingBox.Max,
  173. out boundingBox.Max);
  174. return boundingBox;
  175. }
  176. }
  177. #endregion
  178. #region Mass (Public)
  179. /// <summary>
  180. /// It defines how heavy is the object in kg
  181. /// Note: If the mass is zero or below the object will be switch to
  182. /// "static collision behavior".
  183. /// </summary>
  184. public override float Mass
  185. {
  186. get
  187. {
  188. return base.Mass;
  189. }
  190. set
  191. {
  192. }
  193. }
  194. #endregion
  195. #region Private
  196. #region jigLibBody (Private)
  197. private readonly Body jigLibBody;
  198. #endregion
  199. #region jigLibSkin (Private)
  200. private readonly CollisionSkin jigLibSkin;
  201. #endregion
  202. #region jiglibPrimitive (Private)
  203. /// <summary>
  204. /// The internal representation of the sphere in Delta.PhysicsEngines.JigLib.
  205. /// </summary>
  206. private Primitive jiglibPrimitive;
  207. #endregion
  208. #region physicsManager (Private)
  209. private readonly JigLibPhysics physicsManager;
  210. #endregion
  211. #region position (Private)
  212. private Vector position;
  213. #endregion
  214. #region position2D (Private)
  215. private Point position2D;
  216. #endregion
  217. #region rotationMatrix (Private)
  218. private Matrix rotationMatrix;
  219. #endregion
  220. #region linearVelocity (Private)
  221. private Vector linearVelocity;
  222. #endregion
  223. #region angularVelocity (Private)
  224. private Vector angularVelocity;
  225. #endregion
  226. #region xnaAngularVelocity2D (Private)
  227. private XnaVector3 xnaAngularVelocity2D;
  228. #endregion
  229. #region boundingBox (Private)
  230. private BoundingBox boundingBox;
  231. #endregion
  232. #endregion
  233. #region Constructors
  234. /// <summary>
  235. /// Constructor
  236. /// </summary>
  237. /// <param name="physicsManager">The JigLib physics manager.</param>
  238. /// <param name="shape">The shape.</param>
  239. /// <param name="initialPosition">Body initial position.</param>
  240. internal JigLibBody(JigLibPhysics physicsManager,
  241. PhysicsShape shape, Vector initialPosition)
  242. : base(false, shape, initialPosition)
  243. {
  244. this.physicsManager = physicsManager;
  245. // create the body and the geometry structs
  246. jigLibBody = new Body();
  247. jigLibSkin = new CollisionSkin(jigLibBody);
  248. jigLibBody.CollisionSkin = jigLibSkin;
  249. CreateShape();
  250. jigLibSkin.callbackFn +=
  251. HandleCollisionDetection;
  252. }
  253. /// <summary>
  254. /// Internal constructor for creating ground body.
  255. /// </summary>
  256. /// <param name="physicsManager">The JigLib physics manager.</param>
  257. internal JigLibBody(JigLibPhysics physicsManager)
  258. : base(false, null, Vector.Zero)
  259. {
  260. this.physicsManager = physicsManager;
  261. // create the body and the geometry structs
  262. jigLibBody = new Body();
  263. jigLibSkin = new CollisionSkin(jigLibBody);
  264. jigLibBody.CollisionSkin = jigLibSkin;
  265. jiglibPrimitive = new Plane(
  266. XnaVector3.UnitZ, 0.0f);
  267. // Init primitive but don't add it to simulation.
  268. InitPrimitive(false);
  269. jigLibSkin.callbackFn += HandleCollisionDetection;
  270. }
  271. #endregion
  272. #region ApplyForce (Public)
  273. /// <summary>
  274. /// Applies a force at the center of mass.
  275. /// </summary>
  276. /// <param name="force">The force.</param>
  277. public override void ApplyForce(Vector force)
  278. {
  279. jigLibBody.Force = JigLibDatatypesMapping.Convert(ref force);
  280. }
  281. #endregion
  282. #region ApplyTorque (Public)
  283. /// <summary>
  284. /// Apply a torque. This affects the angular velocity without affecting the
  285. /// linear velocity of the center of mass.
  286. /// <remarks>
  287. /// This wakes up the body.
  288. /// </remarks>
  289. /// </summary>
  290. /// <param name="torque">Vector containing torque data for both 2D and 3D
  291. /// shapes.</param>
  292. public override void ApplyTorque(Vector torque)
  293. {
  294. jigLibBody.Torque = JigLibDatatypesMapping.Convert(ref torque);
  295. }
  296. #endregion
  297. #region ApplyLinearImpulse (Public)
  298. /// <summary>
  299. /// Apply an impulse at a point. This immediately modifies the velocity.
  300. /// <remarks>
  301. /// This wakes up the body.
  302. /// </remarks>
  303. /// </summary>
  304. /// <param name="impulse">Impulse vector data.</param>
  305. public override void ApplyLinearImpulse(Vector impulse)
  306. {
  307. Body.ApplyWorldImpulse(JigLibDatatypesMapping.Convert(ref impulse));
  308. }
  309. /// <summary>
  310. /// Apply an impulse at a point. This immediately modifies the velocity.
  311. /// It also modifies the angular velocity if the point of application
  312. /// is not at the center of mass.
  313. /// <remarks>
  314. /// This wakes up the body.
  315. /// </remarks>
  316. /// </summary>
  317. /// <param name="impulse">Impulse vector data.</param>
  318. /// <param name="position">Position in 3D where to apply impulse.</param>
  319. public override void ApplyLinearImpulse(Vector impulse, Vector position)
  320. {
  321. jigLibBody.ApplyWorldImpulse(
  322. JigLibDatatypesMapping.Convert(ref impulse),
  323. JigLibDatatypesMapping.Convert(ref position));
  324. }
  325. #endregion
  326. #region ApplyAngularImpulse (Public)
  327. /// <summary>
  328. /// Apply an angular impulse.
  329. /// </summary>
  330. /// <param name="impulse">Vector containing torque data for both 2D and 3D shapes.</param>
  331. public override void ApplyAngularImpulse(Vector impulse)
  332. {
  333. Body.ApplyWorldAngImpulse(JigLibDatatypesMapping.Convert(ref impulse));
  334. }
  335. #endregion
  336. #region Methods (Private)
  337. #region CreateShape
  338. /// <summary>
  339. /// Creates new physics shape from out cached properties.
  340. /// </summary>
  341. private void CreateShape()
  342. {
  343. Vector position = InitialPosition;
  344. Dictionary<PhysicsShape.PropertyType, object> properties =
  345. base.Shape.Properties;
  346. switch (Shape.ShapeType)
  347. {
  348. case ShapeType.Sphere:
  349. jiglibPrimitive = new Sphere(
  350. JigLibDatatypesMapping.Convert(ref position),
  351. ArrayHelper.SafeGet<PhysicsShape.PropertyType, float>(
  352. properties, PhysicsShape.PropertyType.Radius));
  353. break;
  354. case ShapeType.Box:
  355. Vector size = ArrayHelper.SafeGet<PhysicsShape.PropertyType, Vector>(
  356. properties, PhysicsShape.PropertyType.Size);
  357. jiglibPrimitive = new Box(
  358. JigLibDatatypesMapping.Convert(ref position),
  359. XnaMatrix.Identity,
  360. new XnaVector3(size.Y, size.Z, size.X)
  361. );
  362. break;
  363. case ShapeType.Capsule:
  364. jiglibPrimitive = new Capsule(
  365. JigLibDatatypesMapping.Convert(ref position),
  366. XnaMatrix.Identity,
  367. ArrayHelper.SafeGet<PhysicsShape.PropertyType, float>(
  368. properties, PhysicsShape.PropertyType.Radius),
  369. ArrayHelper.SafeGet<PhysicsShape.PropertyType, float>(
  370. properties, PhysicsShape.PropertyType.Depth));
  371. break;
  372. case ShapeType.Triangle:
  373. jiglibPrimitive = Helpers.CreateFrom(
  374. ArrayHelper.SafeGet<PhysicsShape.PropertyType, Mesh>(
  375. properties, PhysicsShape.PropertyType.Mesh),
  376. ArrayHelper.SafeGet<PhysicsShape.PropertyType, Matrix>(
  377. properties, PhysicsShape.PropertyType.LocalSpaceMatrix),
  378. ArrayHelper.SafeGet<PhysicsShape.PropertyType, bool>(
  379. properties, PhysicsShape.PropertyType.InvertTriangles));
  380. break;
  381. }
  382. // Finally initialize primitive
  383. InitPrimitive(true);
  384. }
  385. #endregion
  386. #region InitPrimitive
  387. /// <summary>
  388. /// Init JigLib primitive.
  389. /// </summary>
  390. /// <param name="addToWorld">True to add to world.</param>
  391. internal void InitPrimitive(bool addToWorld)
  392. {
  393. if (jiglibPrimitive == null)
  394. {
  395. Log.Warning("Can't create JigLib body with no primitive.");
  396. return;
  397. }
  398. jigLibSkin.AddPrimitive(
  399. jiglibPrimitive,
  400. new MaterialProperties(
  401. 0.8f, // elasticity
  402. 0.8f, // static roughness
  403. 0.7f // dynamic roughness
  404. ));
  405. XnaVector3 com = GestureMass(base.mass);
  406. // Apply initial position
  407. Vector initPosition = InitialPosition;
  408. jigLibBody.MoveTo(JigLibDatatypesMapping.Convert(ref initPosition),
  409. XnaMatrix.Identity);
  410. // in case the com is not the same as the mesh reference system
  411. jigLibSkin.ApplyLocalTransform(new Transform(-com,
  412. XnaMatrix.Identity));
  413. if (addToWorld)
  414. {
  415. // add the body to the physics world
  416. Body.EnableBody();
  417. }
  418. }
  419. #endregion
  420. #region GestureMass
  421. /// <summary>
  422. /// Init main settings for Mass and BodyInertia.
  423. /// </summary>
  424. /// <param name="value">Mass value used for calculating body inhertia.</param>
  425. /// <returns>Vector3 containing body inhertia newly calculated.</returns>
  426. private XnaVector3 GestureMass(float value)
  427. {
  428. PrimitiveProperties primitiveProperties = new PrimitiveProperties(
  429. PrimitiveProperties.MassDistributionEnum.Solid,
  430. PrimitiveProperties.MassTypeEnum.Mass,
  431. value);
  432. float junk;
  433. XnaVector3 com;
  434. XnaMatrix it, itCom;
  435. jigLibSkin.GetMassProperties(
  436. primitiveProperties, out junk, out com, out it, out itCom);
  437. jigLibBody.BodyInertia = itCom;
  438. jigLibBody.Mass = junk;
  439. base.mass = junk;
  440. return com;
  441. }
  442. #endregion
  443. #region HandleCollisionDetection
  444. /// <summary>
  445. /// Fired when collision is launch.
  446. /// </summary>
  447. /// <remarks>
  448. /// http://jiglibx.wikidot.com/catch-collisionevents
  449. /// </remarks>
  450. /// <param name="owner">JigLib collision owner skin.</param>
  451. /// <param name="collidee">JigLib collidee owner skin.</param>
  452. /// <returns>
  453. /// True whether to response on collision detection.
  454. /// </returns>
  455. private bool HandleCollisionDetection(CollisionSkin owner,
  456. CollisionSkin collidee)
  457. {
  458. // all other coll
  459. PhysicsBody body;
  460. if (physicsManager.skinBodiesMap.TryGetValue(collidee, out body))
  461. {
  462. base.OnCollisionBegin(body);
  463. }
  464. return true;
  465. }
  466. #endregion
  467. #region SetIsStatic
  468. /// <summary>
  469. /// Static physics body implementation.
  470. /// </summary>
  471. /// <param name="value">True to set static, false otherwise.</param>
  472. protected override void SetIsStatic(bool value)
  473. {
  474. jigLibBody.Immovable = value;
  475. }
  476. #endregion
  477. #region SetIsActive
  478. protected override void SetIsActive(bool value)
  479. {
  480. if (value)
  481. {
  482. jigLibBody.SetActive();
  483. }
  484. }
  485. #endregion
  486. #region SetFriction
  487. protected override void SetFriction(float value)
  488. {
  489. // Multiple shapes
  490. foreach (CollisionInfo iter in jigLibSkin.Collisions)
  491. {
  492. iter.MatPairProperties.StaticFriction = value;
  493. iter.MatPairProperties.DynamicFriction = value;
  494. }
  495. }
  496. #endregion
  497. #endregion
  498. }
  499. }