aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs325
1 files changed, 196 insertions, 129 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 38ab3de..aaa0d93 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -111,8 +111,8 @@ public sealed class BSPrim : BSPhysObject
111 _mass = CalculateMass(); 111 _mass = CalculateMass();
112 112
113 // No body or shape yet 113 // No body or shape yet
114 BSBody = new BulletBody(LocalID, IntPtr.Zero); 114 PhysBody = new BulletBody(LocalID, IntPtr.Zero);
115 BSShape = new BulletShape(IntPtr.Zero); 115 PhysShape = new BulletShape(IntPtr.Zero);
116 116
117 DetailLog("{0},BSPrim.constructor,call", LocalID); 117 DetailLog("{0},BSPrim.constructor,call", LocalID);
118 // do the actual object creation at taint time 118 // do the actual object creation at taint time
@@ -120,7 +120,7 @@ public sealed class BSPrim : BSPhysObject
120 { 120 {
121 CreateGeomAndObject(true); 121 CreateGeomAndObject(true);
122 122
123 CurrentCollisionFlags = BulletSimAPI.GetCollisionFlags2(BSBody.ptr); 123 CurrentCollisionFlags = BulletSimAPI.GetCollisionFlags2(PhysBody.ptr);
124 }); 124 });
125 } 125 }
126 126
@@ -145,8 +145,8 @@ public sealed class BSPrim : BSPhysObject
145 { 145 {
146 DetailLog("{0},BSPrim.Destroy,taint,", LocalID); 146 DetailLog("{0},BSPrim.Destroy,taint,", LocalID);
147 // If there are physical body and shape, release my use of same. 147 // If there are physical body and shape, release my use of same.
148 PhysicsScene.Shapes.DereferenceBody(BSBody, true, null); 148 PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null);
149 PhysicsScene.Shapes.DereferenceShape(BSShape, true, null); 149 PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null);
150 }); 150 });
151 } 151 }
152 152
@@ -171,18 +171,18 @@ public sealed class BSPrim : BSPhysObject
171 ForceBodyShapeRebuild(false); 171 ForceBodyShapeRebuild(false);
172 } 172 }
173 } 173 }
174 // Whatever the linkset wants is what I want.
175 public override ShapeData.PhysicsShapeType PreferredPhysicalShape
176 { get { return Linkset.PreferredPhysicalShape(this); } }
177
174 public override bool ForceBodyShapeRebuild(bool inTaintTime) 178 public override bool ForceBodyShapeRebuild(bool inTaintTime)
175 { 179 {
176 LastAssetBuildFailed = false; 180 LastAssetBuildFailed = false;
177 BSScene.TaintCallback rebuildOperation = delegate() 181 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ForceBodyShapeRebuild", delegate()
178 { 182 {
179 _mass = CalculateMass(); // changing the shape changes the mass 183 _mass = CalculateMass(); // changing the shape changes the mass
180 CreateGeomAndObject(true); 184 CreateGeomAndObject(true);
181 }; 185 });
182 if (inTaintTime)
183 rebuildOperation();
184 else
185 PhysicsScene.TaintedObject("BSPrim.ForceBodyShapeRebuild", rebuildOperation);
186 return true; 186 return true;
187 } 187 }
188 public override bool Grabbed { 188 public override bool Grabbed {
@@ -242,8 +242,8 @@ public sealed class BSPrim : BSPhysObject
242 _acceleration = OMV.Vector3.Zero; 242 _acceleration = OMV.Vector3.Zero;
243 _rotationalVelocity = OMV.Vector3.Zero; 243 _rotationalVelocity = OMV.Vector3.Zero;
244 244
245 // Zero some other properties directly into the physics engine 245 // Zero some other properties in the physics engine
246 BulletSimAPI.ClearForces2(BSBody.ptr); 246 BulletSimAPI.ClearAllForces2(PhysBody.ptr);
247 } 247 }
248 248
249 public override void LockAngularMotion(OMV.Vector3 axis) 249 public override void LockAngularMotion(OMV.Vector3 axis)
@@ -252,11 +252,16 @@ public sealed class BSPrim : BSPhysObject
252 return; 252 return;
253 } 253 }
254 254
255 public override OMV.Vector3 RawPosition
256 {
257 get { return _position; }
258 set { _position = value; }
259 }
255 public override OMV.Vector3 Position { 260 public override OMV.Vector3 Position {
256 get { 261 get {
262 // child prims move around based on their parent. Need to get the latest location
257 if (!Linkset.IsRoot(this)) 263 if (!Linkset.IsRoot(this))
258 // child prims move around based on their parent. Need to get the latest location 264 _position = Linkset.Position(this);
259 _position = BulletSimAPI.GetPosition2(BSBody.ptr);
260 265
261 // don't do the GetObjectPosition for root elements because this function is called a zillion times 266 // don't do the GetObjectPosition for root elements because this function is called a zillion times
262 // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); 267 // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr);
@@ -274,19 +279,21 @@ public sealed class BSPrim : BSPhysObject
274 PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() 279 PhysicsScene.TaintedObject("BSPrim.setPosition", delegate()
275 { 280 {
276 // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 281 // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
277 BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); 282 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
283 ActivateIfPhysical(false);
278 }); 284 });
279 } 285 }
280 } 286 }
281 public override OMV.Vector3 ForcePosition { 287 public override OMV.Vector3 ForcePosition {
282 get { 288 get {
283 _position = BulletSimAPI.GetPosition2(BSBody.ptr); 289 _position = BulletSimAPI.GetPosition2(PhysBody.ptr);
284 return _position; 290 return _position;
285 } 291 }
286 set { 292 set {
287 _position = value; 293 _position = value;
288 PositionSanityCheck(); 294 PositionSanityCheck();
289 BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); 295 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
296 ActivateIfPhysical(false);
290 } 297 }
291 } 298 }
292 299
@@ -311,6 +318,7 @@ public sealed class BSPrim : BSPhysObject
311 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) 318 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
312 { 319 {
313 float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position); 320 float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position);
321 // TODO: a floating motor so object will bob in the water
314 if (Position.Z < waterHeight) 322 if (Position.Z < waterHeight)
315 { 323 {
316 _position.Z = waterHeight; 324 _position.Z = waterHeight;
@@ -332,16 +340,11 @@ public sealed class BSPrim : BSPhysObject
332 { 340 {
333 // The new position value must be pushed into the physics engine but we can't 341 // The new position value must be pushed into the physics engine but we can't
334 // just assign to "Position" because of potential call loops. 342 // just assign to "Position" because of potential call loops.
335 BSScene.TaintCallback sanityOperation = delegate() 343 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.PositionSanityCheck", delegate()
336 { 344 {
337 DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); 345 DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
338 ForcePosition = _position; 346 ForcePosition = _position;
339 }; 347 });
340 if (inTaintTime)
341 sanityOperation();
342 else
343 PhysicsScene.TaintedObject("BSPrim.PositionSanityCheck", sanityOperation);
344
345 ret = true; 348 ret = true;
346 } 349 }
347 return ret; 350 return ret;
@@ -353,13 +356,34 @@ public sealed class BSPrim : BSPhysObject
353 { 356 {
354 get 357 get
355 { 358 {
356 // return Linkset.LinksetMass; 359 return Linkset.LinksetMass;
357 return _mass; 360 // return _mass;
358 } 361 }
359 } 362 }
360 363
361 // used when we only want this prim's mass and not the linkset thing 364 // used when we only want this prim's mass and not the linkset thing
362 public override float MassRaw { get { return _mass; } } 365 public override float RawMass {
366 get { return _mass; }
367 }
368 // Set the physical mass to the passed mass.
369 // Note that this does not change _mass!
370 public override void UpdatePhysicalMassProperties(float physMass)
371 {
372 if (IsStatic)
373 {
374 BulletSimAPI.SetMassProps2(PhysBody.ptr, 0f, OMV.Vector3.Zero);
375 BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr);
376 }
377 else
378 {
379 OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass);
380 BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, localInertia);
381 // center of mass is at the zero of the object
382 BulletSimAPI.SetCenterOfMassByPosRot2(PhysBody.ptr, ForcePosition, ForceOrientation);
383 // BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr);
384 DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2}", LocalID, physMass, localInertia);
385 }
386 }
363 387
364 // Is this used? 388 // Is this used?
365 public override OMV.Vector3 CenterOfMass 389 public override OMV.Vector3 CenterOfMass
@@ -380,7 +404,7 @@ public sealed class BSPrim : BSPhysObject
380 PhysicsScene.TaintedObject("BSPrim.setForce", delegate() 404 PhysicsScene.TaintedObject("BSPrim.setForce", delegate()
381 { 405 {
382 // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); 406 // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force);
383 BulletSimAPI.SetObjectForce2(BSBody.ptr, _force); 407 BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force);
384 }); 408 });
385 } 409 }
386 } 410 }
@@ -400,6 +424,7 @@ public sealed class BSPrim : BSPhysObject
400 // Done at taint time so we're sure the physics engine is not using the variables 424 // Done at taint time so we're sure the physics engine is not using the variables
401 // Vehicle code changes the parameters for this vehicle type. 425 // Vehicle code changes the parameters for this vehicle type.
402 _vehicle.ProcessTypeChange(type); 426 _vehicle.ProcessTypeChange(type);
427 ActivateIfPhysical(false);
403 }); 428 });
404 } 429 }
405 } 430 }
@@ -408,6 +433,7 @@ public sealed class BSPrim : BSPhysObject
408 PhysicsScene.TaintedObject("BSPrim.VehicleFloatParam", delegate() 433 PhysicsScene.TaintedObject("BSPrim.VehicleFloatParam", delegate()
409 { 434 {
410 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value); 435 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value);
436 ActivateIfPhysical(false);
411 }); 437 });
412 } 438 }
413 public override void VehicleVectorParam(int param, OMV.Vector3 value) 439 public override void VehicleVectorParam(int param, OMV.Vector3 value)
@@ -415,6 +441,7 @@ public sealed class BSPrim : BSPhysObject
415 PhysicsScene.TaintedObject("BSPrim.VehicleVectorParam", delegate() 441 PhysicsScene.TaintedObject("BSPrim.VehicleVectorParam", delegate()
416 { 442 {
417 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value); 443 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value);
444 ActivateIfPhysical(false);
418 }); 445 });
419 } 446 }
420 public override void VehicleRotationParam(int param, OMV.Quaternion rotation) 447 public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
@@ -422,6 +449,7 @@ public sealed class BSPrim : BSPhysObject
422 PhysicsScene.TaintedObject("BSPrim.VehicleRotationParam", delegate() 449 PhysicsScene.TaintedObject("BSPrim.VehicleRotationParam", delegate()
423 { 450 {
424 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); 451 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
452 ActivateIfPhysical(false);
425 }); 453 });
426 } 454 }
427 public override void VehicleFlags(int param, bool remove) 455 public override void VehicleFlags(int param, bool remove)
@@ -436,9 +464,16 @@ public sealed class BSPrim : BSPhysObject
436 // Called from Scene when doing simulation step so we're in taint processing time. 464 // Called from Scene when doing simulation step so we're in taint processing time.
437 public override void StepVehicle(float timeStep) 465 public override void StepVehicle(float timeStep)
438 { 466 {
439 if (IsPhysical) 467 if (IsPhysical && _vehicle.IsActive)
440 { 468 {
441 _vehicle.Step(timeStep); 469 _vehicle.Step(timeStep);
470 /* // TEST TEST DEBUG DEBUG -- trying to reduce the extra action of Bullet simulation step
471 PhysicsScene.PostTaintObject("BSPrim.StepVehicles", LocalID, delegate()
472 {
473 // This resets the interpolation values and recomputes the tensor variables
474 BulletSimAPI.SetCenterOfMassByPosRot2(BSBody.ptr, ForcePosition, ForceOrientation);
475 });
476 */
442 } 477 }
443 } 478 }
444 479
@@ -463,7 +498,7 @@ public sealed class BSPrim : BSPhysObject
463 PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate() 498 PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate()
464 { 499 {
465 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); 500 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity);
466 BulletSimAPI.SetLinearVelocity2(BSBody.ptr, _velocity); 501 BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity);
467 }); 502 });
468 } 503 }
469 } 504 }
@@ -471,12 +506,14 @@ public sealed class BSPrim : BSPhysObject
471 get { return _velocity; } 506 get { return _velocity; }
472 set { 507 set {
473 _velocity = value; 508 _velocity = value;
474 BulletSimAPI.SetLinearVelocity2(BSBody.ptr, _velocity); 509 BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity);
475 } 510 }
476 } 511 }
477 public override OMV.Vector3 Torque { 512 public override OMV.Vector3 Torque {
478 get { return _torque; } 513 get { return _torque; }
479 set { _torque = value; 514 set {
515 _torque = value;
516 AddAngularForce(_torque, false, false);
480 // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); 517 // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque);
481 } 518 }
482 } 519 }
@@ -489,12 +526,17 @@ public sealed class BSPrim : BSPhysObject
489 get { return _acceleration; } 526 get { return _acceleration; }
490 set { _acceleration = value; } 527 set { _acceleration = value; }
491 } 528 }
529 public override OMV.Quaternion RawOrientation
530 {
531 get { return _orientation; }
532 set { _orientation = value; }
533 }
492 public override OMV.Quaternion Orientation { 534 public override OMV.Quaternion Orientation {
493 get { 535 get {
536 // Children move around because tied to parent. Get a fresh value.
494 if (!Linkset.IsRoot(this)) 537 if (!Linkset.IsRoot(this))
495 { 538 {
496 // Children move around because tied to parent. Get a fresh value. 539 _orientation = Linkset.Orientation(this);
497 _orientation = BulletSimAPI.GetOrientation2(BSBody.ptr);
498 } 540 }
499 return _orientation; 541 return _orientation;
500 } 542 }
@@ -507,7 +549,7 @@ public sealed class BSPrim : BSPhysObject
507 { 549 {
508 // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); 550 // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr);
509 // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); 551 // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation);
510 BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); 552 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
511 }); 553 });
512 } 554 }
513 } 555 }
@@ -516,13 +558,13 @@ public sealed class BSPrim : BSPhysObject
516 { 558 {
517 get 559 get
518 { 560 {
519 _orientation = BulletSimAPI.GetOrientation2(BSBody.ptr); 561 _orientation = BulletSimAPI.GetOrientation2(PhysBody.ptr);
520 return _orientation; 562 return _orientation;
521 } 563 }
522 set 564 set
523 { 565 {
524 _orientation = value; 566 _orientation = value;
525 BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); 567 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
526 } 568 }
527 } 569 }
528 public override int PhysicsActorType { 570 public override int PhysicsActorType {
@@ -539,6 +581,8 @@ public sealed class BSPrim : BSPhysObject
539 { 581 {
540 // DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical); 582 // DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical);
541 SetObjectDynamic(true); 583 SetObjectDynamic(true);
584 // whether phys-to-static or static-to-phys, the object is not moving.
585 ZeroMotion();
542 }); 586 });
543 } 587 }
544 } 588 }
@@ -576,7 +620,7 @@ public sealed class BSPrim : BSPhysObject
576 620
577 // Mangling all the physical properties requires the object not be in the physical world. 621 // Mangling all the physical properties requires the object not be in the physical world.
578 // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found). 622 // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found).
579 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, BSBody.ptr); 623 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, PhysBody.ptr);
580 624
581 // Set up the object physicalness (does gravity and collisions move this object) 625 // Set up the object physicalness (does gravity and collisions move this object)
582 MakeDynamic(IsStatic); 626 MakeDynamic(IsStatic);
@@ -590,24 +634,24 @@ public sealed class BSPrim : BSPhysObject
590 // Make solid or not (do things bounce off or pass through this object). 634 // Make solid or not (do things bounce off or pass through this object).
591 MakeSolid(IsSolid); 635 MakeSolid(IsSolid);
592 636
593 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, BSBody.ptr); 637 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, PhysBody.ptr);
594 638
595 // Rebuild its shape 639 // Rebuild its shape
596 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, BSBody.ptr); 640 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr);
597 641
598 // Collision filter can be set only when the object is in the world 642 // Collision filter can be set only when the object is in the world
599 if (BSBody.collisionFilter != 0 || BSBody.collisionMask != 0) 643 if (PhysBody.collisionFilter != 0 || PhysBody.collisionMask != 0)
600 { 644 {
601 BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr, (uint)BSBody.collisionFilter, (uint)BSBody.collisionMask); 645 BulletSimAPI.SetCollisionFilterMask2(PhysBody.ptr, (uint)PhysBody.collisionFilter, (uint)PhysBody.collisionMask);
602 } 646 }
603 647
604 // Recompute any linkset parameters. 648 // Recompute any linkset parameters.
605 // When going from non-physical to physical, this re-enables the constraints that 649 // When going from non-physical to physical, this re-enables the constraints that
606 // had been automatically disabled when the mass was set to zero. 650 // had been automatically disabled when the mass was set to zero.
607 Linkset.Refresh(this, true); 651 Linkset.Refresh(this);
608 652
609 DetailLog("{0},BSPrim.UpdatePhysicalParameters,exit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}", 653 DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}",
610 LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags, BSBody, BSShape); 654 LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags, PhysBody, PhysShape);
611 } 655 }
612 656
613 // "Making dynamic" means changing to and from static. 657 // "Making dynamic" means changing to and from static.
@@ -620,75 +664,74 @@ public sealed class BSPrim : BSPhysObject
620 if (makeStatic) 664 if (makeStatic)
621 { 665 {
622 // Become a Bullet 'static' object type 666 // Become a Bullet 'static' object type
623 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_STATIC_OBJECT); 667 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_STATIC_OBJECT);
624 // Stop all movement 668 // Stop all movement
625 BulletSimAPI.ClearAllForces2(BSBody.ptr); 669 ZeroMotion();
626 // Center of mass is at the center of the object 670 // Center of mass is at the center of the object
627 BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.BSBody.ptr, _position, _orientation); 671 BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation);
628 // Mass is zero which disables a bunch of physics stuff in Bullet 672 // Mass is zero which disables a bunch of physics stuff in Bullet
629 BulletSimAPI.SetMassProps2(BSBody.ptr, 0f, OMV.Vector3.Zero); 673 UpdatePhysicalMassProperties(0f);
630 // There is no inertia in a static object
631 BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr);
632 // Set collision detection parameters 674 // Set collision detection parameters
633 if (PhysicsScene.Params.ccdMotionThreshold > 0f) 675 if (PhysicsScene.Params.ccdMotionThreshold > 0f)
634 { 676 {
635 BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold); 677 BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold);
636 BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); 678 BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius);
637 } 679 }
638 // There can be special things needed for implementing linksets 680 // There can be special things needed for implementing linksets
639 Linkset.MakeStatic(this); 681 Linkset.MakeStatic(this);
640 // The activation state is 'disabled' so Bullet will not try to act on it. 682 // The activation state is 'disabled' so Bullet will not try to act on it.
641 BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_SIMULATION); 683 BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.DISABLE_SIMULATION);
642 // Start it out sleeping and physical actions could wake it up. 684 // Start it out sleeping and physical actions could wake it up.
643 // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING); 685 // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING);
644 686
645 BSBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter; 687 PhysBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter;
646 BSBody.collisionMask = CollisionFilterGroups.StaticObjectMask; 688 PhysBody.collisionMask = CollisionFilterGroups.StaticObjectMask;
647 } 689 }
648 else 690 else
649 { 691 {
650 // Not a Bullet static object 692 // Not a Bullet static object
651 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.CF_STATIC_OBJECT); 693 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_STATIC_OBJECT);
652 694
653 // Set various physical properties so internal dynamic properties will get computed correctly as they are set 695 // Set various physical properties so internal dynamic properties will get computed correctly as they are set
654 BulletSimAPI.SetFriction2(BSBody.ptr, PhysicsScene.Params.defaultFriction); 696 BulletSimAPI.SetFriction2(PhysBody.ptr, PhysicsScene.Params.defaultFriction);
655 BulletSimAPI.SetRestitution2(BSBody.ptr, PhysicsScene.Params.defaultRestitution); 697 BulletSimAPI.SetRestitution2(PhysBody.ptr, PhysicsScene.Params.defaultRestitution);
656 698
657 // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 699 // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382
658 BulletSimAPI.ClearAllForces2(BSBody.ptr); 700 // Since this can be called multiple times, only zero forces when becoming physical
701 // BulletSimAPI.ClearAllForces2(BSBody.ptr);
659 702
660 // For good measure, make sure the transform is set through to the motion state 703 // For good measure, make sure the transform is set through to the motion state
661 BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); 704 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
705
706 // Center of mass is at the center of the object
707 BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation);
662 708
663 // A dynamic object has mass 709 // A dynamic object has mass
664 IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.ptr); 710 UpdatePhysicalMassProperties(RawMass);
665 OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, Mass);
666 BulletSimAPI.SetMassProps2(BSBody.ptr, _mass, inertia);
667 BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr);
668 711
669 // Set collision detection parameters 712 // Set collision detection parameters
670 if (PhysicsScene.Params.ccdMotionThreshold > 0f) 713 if (PhysicsScene.Params.ccdMotionThreshold > 0f)
671 { 714 {
672 BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold); 715 BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold);
673 BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); 716 BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius);
674 } 717 }
675 718
676 // Various values for simulation limits 719 // Various values for simulation limits
677 BulletSimAPI.SetDamping2(BSBody.ptr, PhysicsScene.Params.linearDamping, PhysicsScene.Params.angularDamping); 720 BulletSimAPI.SetDamping2(PhysBody.ptr, PhysicsScene.Params.linearDamping, PhysicsScene.Params.angularDamping);
678 BulletSimAPI.SetDeactivationTime2(BSBody.ptr, PhysicsScene.Params.deactivationTime); 721 BulletSimAPI.SetDeactivationTime2(PhysBody.ptr, PhysicsScene.Params.deactivationTime);
679 BulletSimAPI.SetSleepingThresholds2(BSBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold); 722 BulletSimAPI.SetSleepingThresholds2(PhysBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold);
680 BulletSimAPI.SetContactProcessingThreshold2(BSBody.ptr, PhysicsScene.Params.contactProcessingThreshold); 723 BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, PhysicsScene.Params.contactProcessingThreshold);
681 724
682 // There might be special things needed for implementing linksets. 725 // There might be special things needed for implementing linksets.
683 Linkset.MakeDynamic(this); 726 Linkset.MakeDynamic(this);
684 727
685 // Force activation of the object so Bullet will act on it. 728 // Force activation of the object so Bullet will act on it.
686 // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects. 729 // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects.
687 BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ACTIVE_TAG); 730 BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ACTIVE_TAG);
688 // BulletSimAPI.Activate2(BSBody.ptr, true); 731 // BulletSimAPI.Activate2(BSBody.ptr, true);
689 732
690 BSBody.collisionFilter = CollisionFilterGroups.ObjectFilter; 733 PhysBody.collisionFilter = CollisionFilterGroups.ObjectFilter;
691 BSBody.collisionMask = CollisionFilterGroups.ObjectMask; 734 PhysBody.collisionMask = CollisionFilterGroups.ObjectMask;
692 } 735 }
693 } 736 }
694 737
@@ -698,7 +741,7 @@ public sealed class BSPrim : BSPhysObject
698 // the functions after this one set up the state of a possibly newly created collision body. 741 // the functions after this one set up the state of a possibly newly created collision body.
699 private void MakeSolid(bool makeSolid) 742 private void MakeSolid(bool makeSolid)
700 { 743 {
701 CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(BSBody.ptr); 744 CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(PhysBody.ptr);
702 if (makeSolid) 745 if (makeSolid)
703 { 746 {
704 // Verify the previous code created the correct shape for this type of thing. 747 // Verify the previous code created the correct shape for this type of thing.
@@ -706,7 +749,7 @@ public sealed class BSPrim : BSPhysObject
706 { 749 {
707 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for solidity. id={1}, type={2}", LogHeader, LocalID, bodyType); 750 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for solidity. id={1}, type={2}", LogHeader, LocalID, bodyType);
708 } 751 }
709 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); 752 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
710 } 753 }
711 else 754 else
712 { 755 {
@@ -714,22 +757,31 @@ public sealed class BSPrim : BSPhysObject
714 { 757 {
715 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType); 758 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType);
716 } 759 }
717 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); 760 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
718 BSBody.collisionFilter = CollisionFilterGroups.VolumeDetectFilter; 761 PhysBody.collisionFilter = CollisionFilterGroups.VolumeDetectFilter;
719 BSBody.collisionMask = CollisionFilterGroups.VolumeDetectMask; 762 PhysBody.collisionMask = CollisionFilterGroups.VolumeDetectMask;
720 } 763 }
721 } 764 }
722 765
766 // Enable physical actions. Bullet will keep sleeping non-moving physical objects so
767 // they need waking up when parameters are changed.
768 // Called in taint-time!!
769 private void ActivateIfPhysical(bool forceIt)
770 {
771 if (IsPhysical)
772 BulletSimAPI.Activate2(PhysBody.ptr, forceIt);
773 }
774
723 // Turn on or off the flag controlling whether collision events are returned to the simulator. 775 // Turn on or off the flag controlling whether collision events are returned to the simulator.
724 private void EnableCollisions(bool wantsCollisionEvents) 776 private void EnableCollisions(bool wantsCollisionEvents)
725 { 777 {
726 if (wantsCollisionEvents) 778 if (wantsCollisionEvents)
727 { 779 {
728 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 780 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
729 } 781 }
730 else 782 else
731 { 783 {
732 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 784 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
733 } 785 }
734 } 786 }
735 787
@@ -774,9 +826,9 @@ public sealed class BSPrim : BSPhysObject
774 PhysicsScene.TaintedObject("BSPrim.setFloatOnWater", delegate() 826 PhysicsScene.TaintedObject("BSPrim.setFloatOnWater", delegate()
775 { 827 {
776 if (_floatOnWater) 828 if (_floatOnWater)
777 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); 829 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER);
778 else 830 else
779 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); 831 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER);
780 }); 832 });
781 } 833 }
782 } 834 }
@@ -798,8 +850,8 @@ public sealed class BSPrim : BSPhysObject
798 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); 850 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
799 PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate() 851 PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate()
800 { 852 {
801 // DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); 853 DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
802 BulletSimAPI.SetAngularVelocity2(BSBody.ptr, _rotationalVelocity); 854 BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity);
803 }); 855 });
804 } 856 }
805 } 857 }
@@ -809,7 +861,7 @@ public sealed class BSPrim : BSPhysObject
809 } 861 }
810 set { 862 set {
811 _rotationalVelocity = value; 863 _rotationalVelocity = value;
812 BulletSimAPI.SetAngularVelocity2(BSBody.ptr, _rotationalVelocity); 864 BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity);
813 } 865 }
814 } 866 }
815 public override bool Kinematic { 867 public override bool Kinematic {
@@ -835,7 +887,7 @@ public sealed class BSPrim : BSPhysObject
835 // DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 887 // DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
836 // Buoyancy is faked by changing the gravity applied to the object 888 // Buoyancy is faked by changing the gravity applied to the object
837 float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); 889 float grav = PhysicsScene.Params.gravity * (1f - _buoyancy);
838 BulletSimAPI.SetGravity2(BSBody.ptr, new OMV.Vector3(0f, 0f, grav)); 890 BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav));
839 } 891 }
840 } 892 }
841 893
@@ -888,7 +940,7 @@ public sealed class BSPrim : BSPhysObject
888 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); 940 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID);
889 return; 941 return;
890 } 942 }
891 BSScene.TaintCallback addForceOperation = delegate() 943 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate()
892 { 944 {
893 OMV.Vector3 fSum = OMV.Vector3.Zero; 945 OMV.Vector3 fSum = OMV.Vector3.Zero;
894 lock (m_accumulatedForces) 946 lock (m_accumulatedForces)
@@ -900,20 +952,60 @@ public sealed class BSPrim : BSPhysObject
900 } 952 }
901 m_accumulatedForces.Clear(); 953 m_accumulatedForces.Clear();
902 } 954 }
903 // DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, fSum); 955 DetailLog("{0},BSPrim.AddForce,taint,force={1}", LocalID, fSum);
904 // For unknown reasons, "ApplyCentralForce" adds this force to the total force on the object. 956 if (fSum != OMV.Vector3.Zero)
905 BulletSimAPI.ApplyCentralForce2(BSBody.ptr, fSum); 957 BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, fSum);
906 }; 958 });
907 if (inTaintTime)
908 addForceOperation();
909 else
910 PhysicsScene.TaintedObject("BSPrim.AddForce", addForceOperation);
911 } 959 }
912 960
961 private List<OMV.Vector3> m_accumulatedAngularForces = new List<OMV.Vector3>();
913 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { 962 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
914 // DetailLog("{0},BSPrim.AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce); 963 AddAngularForce(force, pushforce, false);
915 // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce);
916 } 964 }
965 public void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime)
966 {
967 if (force.IsFinite())
968 {
969 // _force += force;
970 lock (m_accumulatedAngularForces)
971 m_accumulatedAngularForces.Add(new OMV.Vector3(force));
972 }
973 else
974 {
975 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID);
976 return;
977 }
978 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddAngularForce", delegate()
979 {
980 OMV.Vector3 fSum = OMV.Vector3.Zero;
981 lock (m_accumulatedAngularForces)
982 {
983 // Sum the accumulated additional forces for one big force to apply once.
984 foreach (OMV.Vector3 v in m_accumulatedAngularForces)
985 {
986 fSum += v;
987 }
988 m_accumulatedAngularForces.Clear();
989 }
990 DetailLog("{0},BSPrim.AddAngularForce,taint,aForce={1}", LocalID, fSum);
991 if (fSum != OMV.Vector3.Zero)
992 {
993 BulletSimAPI.ApplyTorque2(PhysBody.ptr, fSum);
994 _torque = fSum;
995 }
996 });
997 }
998 // A torque impulse.
999 public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime)
1000 {
1001 OMV.Vector3 applyImpulse = impulse;
1002 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate()
1003 {
1004 DetailLog("{0},BSPrim.ApplyTorqueImpulse,taint,tImpulse={1}", LocalID, applyImpulse);
1005 BulletSimAPI.ApplyTorqueImpulse2(PhysBody.ptr, applyImpulse);
1006 });
1007 }
1008
917 public override void SetMomentum(OMV.Vector3 momentum) { 1009 public override void SetMomentum(OMV.Vector3 momentum) {
918 // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); 1010 // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum);
919 } 1011 }
@@ -1195,9 +1287,7 @@ public sealed class BSPrim : BSPhysObject
1195 1287
1196 returnMass = _density * volume; 1288 returnMass = _density * volume;
1197 1289
1198 /* 1290 /* Comment out code that computes the mass of the linkset. That is done in the Linkset class.
1199 * This change means each object keeps its own mass and the Mass property
1200 * will return the sum if we're part of a linkset.
1201 if (IsRootOfLinkset) 1291 if (IsRootOfLinkset)
1202 { 1292 {
1203 foreach (BSPrim prim in _childrenPrims) 1293 foreach (BSPrim prim in _childrenPrims)
@@ -1217,34 +1307,11 @@ public sealed class BSPrim : BSPhysObject
1217 }// end CalculateMass 1307 }// end CalculateMass
1218 #endregion Mass Calculation 1308 #endregion Mass Calculation
1219 1309
1220 // Copy prim's info into the BulletSim shape description structure
1221 public void FillShapeInfo(out ShapeData shape)
1222 {
1223 shape.ID = LocalID;
1224 shape.Type = ShapeData.PhysicsShapeType.SHAPE_UNKNOWN;
1225 shape.Position = _position;
1226 shape.Rotation = _orientation;
1227 shape.Velocity = _velocity;
1228 shape.Size = _size;
1229 shape.Scale = Scale;
1230 shape.Mass = _isPhysical ? _mass : 0f;
1231 shape.Buoyancy = _buoyancy;
1232 shape.HullKey = 0;
1233 shape.MeshKey = 0;
1234 shape.Friction = _friction;
1235 shape.Restitution = _restitution;
1236 shape.Collidable = (!IsPhantom) ? ShapeData.numericTrue : ShapeData.numericFalse;
1237 shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue;
1238 shape.Solid = IsSolid ? ShapeData.numericFalse : ShapeData.numericTrue;
1239 }
1240 // Rebuild the geometry and object. 1310 // Rebuild the geometry and object.
1241 // This is called when the shape changes so we need to recreate the mesh/hull. 1311 // This is called when the shape changes so we need to recreate the mesh/hull.
1242 // Called at taint-time!!! 1312 // Called at taint-time!!!
1243 private void CreateGeomAndObject(bool forceRebuild) 1313 private void CreateGeomAndObject(bool forceRebuild)
1244 { 1314 {
1245 ShapeData shapeData;
1246 FillShapeInfo(out shapeData);
1247
1248 // If this prim is part of a linkset, we must remove and restore the physical 1315 // If this prim is part of a linkset, we must remove and restore the physical
1249 // links if the body is rebuilt. 1316 // links if the body is rebuilt.
1250 bool needToRestoreLinkset = false; 1317 bool needToRestoreLinkset = false;
@@ -1253,8 +1320,7 @@ public sealed class BSPrim : BSPhysObject
1253 // Updates BSBody and BSShape with the new information. 1320 // Updates BSBody and BSShape with the new information.
1254 // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. 1321 // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary.
1255 // Returns 'true' if either the body or the shape was changed. 1322 // Returns 'true' if either the body or the shape was changed.
1256 PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, shapeData, BaseShape, 1323 PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, null, delegate(BulletBody dBody)
1257 null, delegate(BulletBody dBody)
1258 { 1324 {
1259 // Called if the current prim body is about to be destroyed. 1325 // Called if the current prim body is about to be destroyed.
1260 // Remove all the physical dependencies on the old body. 1326 // Remove all the physical dependencies on the old body.
@@ -1353,8 +1419,9 @@ public sealed class BSPrim : BSPhysObject
1353 1419
1354 PositionSanityCheck(true); 1420 PositionSanityCheck(true);
1355 1421
1356 DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 1422 OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation;
1357 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); 1423 DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}",
1424 LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity);
1358 1425
1359 // BulletSimAPI.DumpRigidBody2(PhysicsScene.World.ptr, BSBody.ptr); // DEBUG DEBUG DEBUG 1426 // BulletSimAPI.DumpRigidBody2(PhysicsScene.World.ptr, BSBody.ptr); // DEBUG DEBUG DEBUG
1360 1427