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