/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}