aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs69
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs187
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs331
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs137
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs51
5 files changed, 533 insertions, 242 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index dc0c008..09e1f0c 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -41,7 +41,7 @@ public class BSCharacter : PhysicsActor
41 41
42 private BSScene _scene; 42 private BSScene _scene;
43 private String _avName; 43 private String _avName;
44 private bool _stopped; 44 // private bool _stopped;
45 private Vector3 _size; 45 private Vector3 _size;
46 private Vector3 _scale; 46 private Vector3 _scale;
47 private PrimitiveBaseShape _pbs; 47 private PrimitiveBaseShape _pbs;
@@ -134,9 +134,9 @@ public class BSCharacter : PhysicsActor
134 { 134 {
135 base.RequestPhysicsterseUpdate(); 135 base.RequestPhysicsterseUpdate();
136 } 136 }
137 137 // No one calls this method so I don't know what it could possibly mean
138 public override bool Stopped { 138 public override bool Stopped {
139 get { return _stopped; } 139 get { return false; }
140 } 140 }
141 public override Vector3 Size { 141 public override Vector3 Size {
142 get { return _size; } 142 get { return _size; }
@@ -391,52 +391,47 @@ public class BSCharacter : PhysicsActor
391 _mass = _density * _avatarVolume; 391 _mass = _density * _avatarVolume;
392 } 392 }
393 393
394 // Set to 'true' if the individual changed items should be checked
395 // (someday RequestPhysicsTerseUpdate() will take a bitmap of changed properties)
396 const bool SHOULD_CHECK_FOR_INDIVIDUAL_CHANGES = false;
397
398 // The physics engine says that properties have updated. Update same and inform 394 // The physics engine says that properties have updated. Update same and inform
399 // the world that things have changed. 395 // the world that things have changed.
400 public void UpdateProperties(EntityProperties entprop) 396 public void UpdateProperties(EntityProperties entprop)
401 { 397 {
398 /*
402 bool changed = false; 399 bool changed = false;
403 if (SHOULD_CHECK_FOR_INDIVIDUAL_CHANGES) { 400 // we assign to the local variables so the normal set action does not happen
404 // we assign to the local variables so the normal set action does not happen 401 if (_position != entprop.Position) {
405 if (_position != entprop.Position) {
406 _position = entprop.Position;
407 changed = true;
408 }
409 if (_orientation != entprop.Rotation) {
410 _orientation = entprop.Rotation;
411 changed = true;
412 }
413 if (_velocity != entprop.Velocity) {
414 _velocity = entprop.Velocity;
415 changed = true;
416 }
417 if (_acceleration != entprop.Acceleration) {
418 _acceleration = entprop.Acceleration;
419 changed = true;
420 }
421 if (_rotationalVelocity != entprop.RotationalVelocity) {
422 _rotationalVelocity = entprop.RotationalVelocity;
423 changed = true;
424 }
425 if (changed) {
426 // m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation);
427 // Avatar movement is not done by generating this event. There is code in the heartbeat
428 // loop that updates avatars.
429 // base.RequestPhysicsterseUpdate();
430 }
431 }
432 else {
433 _position = entprop.Position; 402 _position = entprop.Position;
403 changed = true;
404 }
405 if (_orientation != entprop.Rotation) {
434 _orientation = entprop.Rotation; 406 _orientation = entprop.Rotation;
407 changed = true;
408 }
409 if (_velocity != entprop.Velocity) {
435 _velocity = entprop.Velocity; 410 _velocity = entprop.Velocity;
411 changed = true;
412 }
413 if (_acceleration != entprop.Acceleration) {
436 _acceleration = entprop.Acceleration; 414 _acceleration = entprop.Acceleration;
415 changed = true;
416 }
417 if (_rotationalVelocity != entprop.RotationalVelocity) {
437 _rotationalVelocity = entprop.RotationalVelocity; 418 _rotationalVelocity = entprop.RotationalVelocity;
419 changed = true;
420 }
421 if (changed) {
422 // m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation);
423 // Avatar movement is not done by generating this event. There is code in the heartbeat
424 // loop that updates avatars.
438 // base.RequestPhysicsterseUpdate(); 425 // base.RequestPhysicsterseUpdate();
439 } 426 }
427 */
428 _position = entprop.Position;
429 _orientation = entprop.Rotation;
430 _velocity = entprop.Velocity;
431 _acceleration = entprop.Acceleration;
432 _rotationalVelocity = entprop.RotationalVelocity;
433 // Avatars don't report theirr changes the usual way. Changes are checked for in the heartbeat loop.
434 // base.RequestPhysicsterseUpdate();
440 } 435 }
441 436
442 // Called by the scene when a collision with this object is reported 437 // Called by the scene when a collision with this object is reported
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index eb20eb3..c197e61 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -57,7 +57,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
57 private int frcount = 0; // Used to limit dynamics debug output to 57 private int frcount = 0; // Used to limit dynamics debug output to
58 // every 100th frame 58 // every 100th frame
59 59
60 // private BSScene m_parentScene = null;
61 private BSPrim m_prim; // the prim this dynamic controller belongs to 60 private BSPrim m_prim; // the prim this dynamic controller belongs to
62 61
63 // Vehicle properties 62 // Vehicle properties
@@ -131,8 +130,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
131 m_type = Vehicle.TYPE_NONE; 130 m_type = Vehicle.TYPE_NONE;
132 } 131 }
133 132
134 internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue) 133 internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue, float timestep)
135 { 134 {
135 DetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue);
136 switch (pParam) 136 switch (pParam)
137 { 137 {
138 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: 138 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
@@ -229,8 +229,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
229 } 229 }
230 }//end ProcessFloatVehicleParam 230 }//end ProcessFloatVehicleParam
231 231
232 internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue) 232 internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue, float timestep)
233 { 233 {
234 DetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue);
234 switch (pParam) 235 switch (pParam)
235 { 236 {
236 case Vehicle.ANGULAR_FRICTION_TIMESCALE: 237 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
@@ -265,6 +266,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
265 266
266 internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) 267 internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue)
267 { 268 {
269 DetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue);
268 switch (pParam) 270 switch (pParam)
269 { 271 {
270 case Vehicle.REFERENCE_FRAME: 272 case Vehicle.REFERENCE_FRAME:
@@ -278,6 +280,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
278 280
279 internal void ProcessVehicleFlags(int pParam, bool remove) 281 internal void ProcessVehicleFlags(int pParam, bool remove)
280 { 282 {
283 DetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", m_prim.LocalID, pParam, remove);
281 if (remove) 284 if (remove)
282 { 285 {
283 if (pParam == -1) 286 if (pParam == -1)
@@ -434,6 +437,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
434 437
435 internal void ProcessTypeChange(Vehicle pType) 438 internal void ProcessTypeChange(Vehicle pType)
436 { 439 {
440 DetailLog("{0},ProcessTypeChange,type={1}", m_prim.LocalID, pType);
437 // Set Defaults For Type 441 // Set Defaults For Type
438 m_type = pType; 442 m_type = pType;
439 switch (pType) 443 switch (pType)
@@ -594,11 +598,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
594 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); 598 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
595 m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT); 599 m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT);
596 break; 600 break;
597
598 } 601 }
599 }//end SetDefaultsForType 602 }//end SetDefaultsForType
600 603
601 internal void Step(float pTimestep, BSScene pParentScene) 604 internal void Step(float pTimestep)
602 { 605 {
603 if (m_type == Vehicle.TYPE_NONE) return; 606 if (m_type == Vehicle.TYPE_NONE) return;
604 607
@@ -606,21 +609,34 @@ namespace OpenSim.Region.Physics.BulletSPlugin
606 if (frcount > 100) 609 if (frcount > 100)
607 frcount = 0; 610 frcount = 0;
608 611
609 MoveLinear(pTimestep, pParentScene); 612 MoveLinear(pTimestep);
610 MoveAngular(pTimestep); 613 MoveAngular(pTimestep);
611 LimitRotation(pTimestep); 614 LimitRotation(pTimestep);
615
616 DetailLog("{0},Dynamics,done,pos={1},force={2},velocity={3},angvel={4}",
617 m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity);
612 }// end Step 618 }// end Step
613 619
614 private void MoveLinear(float pTimestep, BSScene _pParentScene) 620 private void MoveLinear(float pTimestep)
615 { 621 {
616 if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) // requested m_linearMotorDirection is significant 622 // requested m_linearMotorDirection is significant
623 // if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f))
624 if (m_linearMotorDirection.LengthSquared() > 0.0001f)
617 { 625 {
626 Vector3 origDir = m_linearMotorDirection;
627 Vector3 origVel = m_lastLinearVelocityVector;
628
618 // add drive to body 629 // add drive to body
619 Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep); 630 // Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep);
620 m_lastLinearVelocityVector += (addAmount*10); // lastLinearVelocityVector is the current body velocity vector? 631 Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale);
632 // lastLinearVelocityVector is the current body velocity vector?
633 // RA: Not sure what the *10 is for. A correction for pTimestep?
634 // m_lastLinearVelocityVector += (addAmount*10);
635 m_lastLinearVelocityVector += addAmount;
621 636
622 // This will work temporarily, but we really need to compare speed on an axis 637 // This will work temporarily, but we really need to compare speed on an axis
623 // KF: Limit body velocity to applied velocity? 638 // KF: Limit body velocity to applied velocity?
639 // Limit the velocity vector to less than the last set linear motor direction
624 if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X)) 640 if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X))
625 m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X; 641 m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X;
626 if (Math.Abs(m_lastLinearVelocityVector.Y) > Math.Abs(m_linearMotorDirectionLASTSET.Y)) 642 if (Math.Abs(m_lastLinearVelocityVector.Y) > Math.Abs(m_linearMotorDirectionLASTSET.Y))
@@ -630,76 +646,93 @@ namespace OpenSim.Region.Physics.BulletSPlugin
630 646
631 // decay applied velocity 647 // decay applied velocity
632 Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep))); 648 Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep)));
633 //Console.WriteLine("decay: " + decayfraction);
634 m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f; 649 m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f;
635 //Console.WriteLine("actual: " + m_linearMotorDirection); 650
651 /*
652 Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/m_linearMotorTimescale;
653 m_lastLinearVelocityVector += addAmount;
654
655 float decayfraction = (1.0f - 1.0f / m_linearMotorDecayTimescale);
656 m_linearMotorDirection *= decayfraction;
657
658 */
659
660 DetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},decay={4},dir={5},vel={6}",
661 m_prim.LocalID, origDir, origVel, addAmount, decayfraction, m_linearMotorDirection, m_lastLinearVelocityVector);
636 } 662 }
637 else 663 else
638 { // requested is not significant 664 {
639 // if what remains of applied is small, zero it. 665 // if what remains of applied is small, zero it.
640 if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f)) 666 // if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f))
641 m_lastLinearVelocityVector = Vector3.Zero; 667 // m_lastLinearVelocityVector = Vector3.Zero;
668 m_linearMotorDirection = Vector3.Zero;
669 m_lastLinearVelocityVector = Vector3.Zero;
642 } 670 }
643 671
644 // convert requested object velocity to world-referenced vector 672 // convert requested object velocity to world-referenced vector
645 m_dir = m_lastLinearVelocityVector; 673 Quaternion rotq = m_prim.Orientation;
646 Quaternion rot = m_prim.Orientation; 674 m_dir = m_lastLinearVelocityVector * rotq;
647 Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object 675
648 m_dir *= rotq; // apply obj rotation to velocity vector 676 // Add the various forces into m_dir which will be our new direction vector (velocity)
649 677
650 // add Gravity andBuoyancy 678 // add Gravity and Buoyancy
651 // KF: So far I have found no good method to combine a script-requested 679 // KF: So far I have found no good method to combine a script-requested
652 // .Z velocity and gravity. Therefore only 0g will used script-requested 680 // .Z velocity and gravity. Therefore only 0g will used script-requested
653 // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only. 681 // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only.
654 Vector3 grav = Vector3.Zero; 682 Vector3 grav = Vector3.Zero;
655 // There is some gravity, make a gravity force vector 683 // There is some gravity, make a gravity force vector that is applied after object velocity.
656 // that is applied after object velocity.
657 float objMass = m_prim.Mass;
658 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; 684 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
659 grav.Z = _pParentScene.DefaultGravity.Z * objMass * (1f - m_VehicleBuoyancy); 685 grav.Z = m_prim.Scene.DefaultGravity.Z * m_prim.Mass * (1f - m_VehicleBuoyancy);
660 // Preserve the current Z velocity 686 // Preserve the current Z velocity
661 Vector3 vel_now = m_prim.Velocity; 687 Vector3 vel_now = m_prim.Velocity;
662 m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity 688 m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity
663 689
664 Vector3 pos = m_prim.Position; 690 Vector3 pos = m_prim.Position;
691 Vector3 posChange = pos;
665// Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f); 692// Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f);
666 Vector3 posChange = new Vector3();
667 posChange.X = pos.X - m_lastPositionVector.X;
668 posChange.Y = pos.Y - m_lastPositionVector.Y;
669 posChange.Z = pos.Z - m_lastPositionVector.Z;
670 double Zchange = Math.Abs(posChange.Z); 693 double Zchange = Math.Abs(posChange.Z);
671 if (m_BlockingEndPoint != Vector3.Zero) 694 if (m_BlockingEndPoint != Vector3.Zero)
672 { 695 {
696 bool changed = false;
673 if (pos.X >= (m_BlockingEndPoint.X - (float)1)) 697 if (pos.X >= (m_BlockingEndPoint.X - (float)1))
674 { 698 {
675 pos.X -= posChange.X + 1; 699 pos.X -= posChange.X + 1;
676 m_prim.Position = pos; 700 changed = true;
677 } 701 }
678 if (pos.Y >= (m_BlockingEndPoint.Y - (float)1)) 702 if (pos.Y >= (m_BlockingEndPoint.Y - (float)1))
679 { 703 {
680 pos.Y -= posChange.Y + 1; 704 pos.Y -= posChange.Y + 1;
681 m_prim.Position = pos; 705 changed = true;
682 } 706 }
683 if (pos.Z >= (m_BlockingEndPoint.Z - (float)1)) 707 if (pos.Z >= (m_BlockingEndPoint.Z - (float)1))
684 { 708 {
685 pos.Z -= posChange.Z + 1; 709 pos.Z -= posChange.Z + 1;
686 m_prim.Position = pos; 710 changed = true;
687 } 711 }
688 if (pos.X <= 0) 712 if (pos.X <= 0)
689 { 713 {
690 pos.X += posChange.X + 1; 714 pos.X += posChange.X + 1;
691 m_prim.Position = pos; 715 changed = true;
692 } 716 }
693 if (pos.Y <= 0) 717 if (pos.Y <= 0)
694 { 718 {
695 pos.Y += posChange.Y + 1; 719 pos.Y += posChange.Y + 1;
720 changed = true;
721 }
722 if (changed)
723 {
696 m_prim.Position = pos; 724 m_prim.Position = pos;
725 DetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}",
726 m_prim.LocalID, m_BlockingEndPoint, posChange, pos);
697 } 727 }
698 } 728 }
699 if (pos.Z < _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y)) 729
730 // If below the terrain, move us above the ground a little.
731 if (pos.Z < m_prim.Scene.GetTerrainHeightAtXYZ(pos))
700 { 732 {
701 pos.Z = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + 2; 733 pos.Z = m_prim.Scene.GetTerrainHeightAtXYZ(pos) + 2;
702 m_prim.Position = pos; 734 m_prim.Position = pos;
735 DetailLog("{0},MoveLinear,terrainHeight,pos={1}", m_prim.LocalID, pos);
703 } 736 }
704 737
705 // Check if hovering 738 // Check if hovering
@@ -708,11 +741,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
708 // We should hover, get the target height 741 // We should hover, get the target height
709 if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != 0) 742 if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != 0)
710 { 743 {
711 m_VhoverTargetHeight = _pParentScene.GetWaterLevel() + m_VhoverHeight; 744 m_VhoverTargetHeight = m_prim.Scene.GetWaterLevel() + m_VhoverHeight;
712 } 745 }
713 if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) 746 if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
714 { 747 {
715 m_VhoverTargetHeight = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight; 748 m_VhoverTargetHeight = m_prim.Scene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight;
716 } 749 }
717 if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0) 750 if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0)
718 { 751 {
@@ -746,6 +779,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
746 } 779 }
747 } 780 }
748 781
782 DetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", m_prim.LocalID, pos, m_dir, m_VhoverHeight, m_VhoverTargetHeight);
783
749// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped 784// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped
750// m_VhoverTimescale = 0f; // time to acheive height 785// m_VhoverTimescale = 0f; // time to acheive height
751// pTimestep is time since last frame,in secs 786// pTimestep is time since last frame,in secs
@@ -774,12 +809,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
774 { 809 {
775 grav.Z = (float)(grav.Z * 1.125); 810 grav.Z = (float)(grav.Z * 1.125);
776 } 811 }
777 float terraintemp = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y); 812 float terraintemp = m_prim.Scene.GetTerrainHeightAtXYZ(pos);
778 float postemp = (pos.Z - terraintemp); 813 float postemp = (pos.Z - terraintemp);
779 if (postemp > 2.5f) 814 if (postemp > 2.5f)
780 { 815 {
781 grav.Z = (float)(grav.Z * 1.037125); 816 grav.Z = (float)(grav.Z * 1.037125);
782 } 817 }
818 DetailLog("{0},MoveLinear,limitMotorUp,grav={1}", m_prim.LocalID, grav);
783 //End Experimental Values 819 //End Experimental Values
784 } 820 }
785 if ((m_flags & (VehicleFlag.NO_X)) != 0) 821 if ((m_flags & (VehicleFlag.NO_X)) != 0)
@@ -800,32 +836,39 @@ namespace OpenSim.Region.Physics.BulletSPlugin
800 // Apply velocity 836 // Apply velocity
801 m_prim.Velocity = m_dir; 837 m_prim.Velocity = m_dir;
802 // apply gravity force 838 // apply gravity force
803 m_prim.Force = grav; 839 // Why is this set here? The physics engine already does gravity.
804 840 // m_prim.AddForce(grav, false);
841 // m_prim.Force = grav;
805 842
806 // apply friction 843 // Apply friction
807 Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep); 844 Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep);
808 m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount; 845 m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount;
846
847 DetailLog("{0},MoveLinear,done,pos={1},vel={2},force={3},decay={4}",
848 m_prim.LocalID, m_lastPositionVector, m_dir, grav, decayamount);
849
809 } // end MoveLinear() 850 } // end MoveLinear()
810 851
811 private void MoveAngular(float pTimestep) 852 private void MoveAngular(float pTimestep)
812 { 853 {
813 /* 854 // m_angularMotorDirection // angular velocity requested by LSL motor
814 private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor 855 // m_angularMotorApply // application frame counter
815 private int m_angularMotorApply = 0; // application frame counter 856 // m_angularMotorVelocity // current angular motor velocity (ramps up and down)
816 private float m_angularMotorVelocity = 0; // current angular motor velocity (ramps up and down) 857 // m_angularMotorTimescale // motor angular velocity ramp up rate
817 private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate 858 // m_angularMotorDecayTimescale // motor angular velocity decay rate
818 private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate 859 // m_angularFrictionTimescale // body angular velocity decay rate
819 private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate 860 // m_lastAngularVelocity // what was last applied to body
820 private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body
821 */
822 861
823 // Get what the body is doing, this includes 'external' influences 862 // Get what the body is doing, this includes 'external' influences
824 Vector3 angularVelocity = m_prim.RotationalVelocity; 863 Vector3 angularVelocity = m_prim.RotationalVelocity;
825 // Vector3 angularVelocity = Vector3.Zero;
826 864
827 if (m_angularMotorApply > 0) 865 if (m_angularMotorApply > 0)
828 { 866 {
867 // Rather than snapping the angular motor velocity from the old value to
868 // a newly set velocity, this routine steps the value from the previous
869 // value (m_angularMotorVelocity) to the requested value (m_angularMotorDirection).
870 // There are m_angularMotorApply steps.
871 Vector3 origAngularVelocity = m_angularMotorVelocity;
829 // ramp up to new value 872 // ramp up to new value
830 // current velocity += error / (time to get there / step interval) 873 // current velocity += error / (time to get there / step interval)
831 // requested speed - last motor speed 874 // requested speed - last motor speed
@@ -833,23 +876,21 @@ namespace OpenSim.Region.Physics.BulletSPlugin
833 m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep); 876 m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep);
834 m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep); 877 m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep);
835 878
879 DetailLog("{0},MoveAngular,angularMotorApply,apply={1},origvel={2},dir={3},vel={4}",
880 m_prim.LocalID,m_angularMotorApply,origAngularVelocity, m_angularMotorDirection, m_angularMotorVelocity);
881
836 m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected 882 m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected
837 // velocity may still be acheived. 883 // velocity may still be acheived.
838 } 884 }
839 else 885 else
840 { 886 {
841 // no motor recently applied, keep the body velocity 887 // No motor recently applied, keep the body velocity
842 /* m_angularMotorVelocity.X = angularVelocity.X;
843 m_angularMotorVelocity.Y = angularVelocity.Y;
844 m_angularMotorVelocity.Z = angularVelocity.Z; */
845
846 // and decay the velocity 888 // and decay the velocity
847 m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep); 889 m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep);
848 } // end motor section 890 } // end motor section
849 891
850 // Vertical attractor section 892 // Vertical attractor section
851 Vector3 vertattr = Vector3.Zero; 893 Vector3 vertattr = Vector3.Zero;
852
853 if (m_verticalAttractionTimescale < 300) 894 if (m_verticalAttractionTimescale < 300)
854 { 895 {
855 float VAservo = 0.2f / (m_verticalAttractionTimescale * pTimestep); 896 float VAservo = 0.2f / (m_verticalAttractionTimescale * pTimestep);
@@ -871,7 +912,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
871 // Error is 0 (no error) to +/- 2 (max error) 912 // Error is 0 (no error) to +/- 2 (max error)
872 // scale it by VAservo 913 // scale it by VAservo
873 verterr = verterr * VAservo; 914 verterr = verterr * VAservo;
874//if (frcount == 0) Console.WriteLine("VAerr=" + verterr);
875 915
876 // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so 916 // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so
877 // Change Body angular velocity X based on Y, and Y based on X. Z is not changed. 917 // Change Body angular velocity X based on Y, and Y based on X. Z is not changed.
@@ -884,11 +924,15 @@ namespace OpenSim.Region.Physics.BulletSPlugin
884 vertattr.X += bounce * angularVelocity.X; 924 vertattr.X += bounce * angularVelocity.X;
885 vertattr.Y += bounce * angularVelocity.Y; 925 vertattr.Y += bounce * angularVelocity.Y;
886 926
927 DetailLog("{0},MoveAngular,verticalAttraction,verterr={1},bounce={2},vertattr={3}",
928 m_prim.LocalID, verterr, bounce, vertattr);
929
887 } // else vertical attractor is off 930 } // else vertical attractor is off
888 931
889 // m_lastVertAttractor = vertattr; 932 // m_lastVertAttractor = vertattr;
890 933
891 // Bank section tba 934 // Bank section tba
935
892 // Deflection section tba 936 // Deflection section tba
893 937
894 // Sum velocities 938 // Sum velocities
@@ -898,11 +942,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
898 { 942 {
899 m_lastAngularVelocity.X = 0; 943 m_lastAngularVelocity.X = 0;
900 m_lastAngularVelocity.Y = 0; 944 m_lastAngularVelocity.Y = 0;
945 DetailLog("{0},MoveAngular,noDeflectionUp,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity);
901 } 946 }
902 947
903 if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) 948 if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f))
904 { 949 {
905 m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. 950 m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero.
951 DetailLog("{0},MoveAngular,zeroSmallValues,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity);
906 } 952 }
907 953
908 // apply friction 954 // apply friction
@@ -912,10 +958,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
912 // Apply to the body 958 // Apply to the body
913 m_prim.RotationalVelocity = m_lastAngularVelocity; 959 m_prim.RotationalVelocity = m_lastAngularVelocity;
914 960
961 DetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", m_prim.LocalID, decayamount, m_lastAngularVelocity);
915 } //end MoveAngular 962 } //end MoveAngular
963
916 internal void LimitRotation(float timestep) 964 internal void LimitRotation(float timestep)
917 { 965 {
918 Quaternion rotq = m_prim.Orientation; // rotq = rotation of object 966 Quaternion rotq = m_prim.Orientation;
919 Quaternion m_rot = rotq; 967 Quaternion m_rot = rotq;
920 bool changed = false; 968 bool changed = false;
921 if (m_RollreferenceFrame != Quaternion.Identity) 969 if (m_RollreferenceFrame != Quaternion.Identity)
@@ -923,18 +971,22 @@ namespace OpenSim.Region.Physics.BulletSPlugin
923 if (rotq.X >= m_RollreferenceFrame.X) 971 if (rotq.X >= m_RollreferenceFrame.X)
924 { 972 {
925 m_rot.X = rotq.X - (m_RollreferenceFrame.X / 2); 973 m_rot.X = rotq.X - (m_RollreferenceFrame.X / 2);
974 changed = true;
926 } 975 }
927 if (rotq.Y >= m_RollreferenceFrame.Y) 976 if (rotq.Y >= m_RollreferenceFrame.Y)
928 { 977 {
929 m_rot.Y = rotq.Y - (m_RollreferenceFrame.Y / 2); 978 m_rot.Y = rotq.Y - (m_RollreferenceFrame.Y / 2);
979 changed = true;
930 } 980 }
931 if (rotq.X <= -m_RollreferenceFrame.X) 981 if (rotq.X <= -m_RollreferenceFrame.X)
932 { 982 {
933 m_rot.X = rotq.X + (m_RollreferenceFrame.X / 2); 983 m_rot.X = rotq.X + (m_RollreferenceFrame.X / 2);
984 changed = true;
934 } 985 }
935 if (rotq.Y <= -m_RollreferenceFrame.Y) 986 if (rotq.Y <= -m_RollreferenceFrame.Y)
936 { 987 {
937 m_rot.Y = rotq.Y + (m_RollreferenceFrame.Y / 2); 988 m_rot.Y = rotq.Y + (m_RollreferenceFrame.Y / 2);
989 changed = true;
938 } 990 }
939 changed = true; 991 changed = true;
940 } 992 }
@@ -944,8 +996,23 @@ namespace OpenSim.Region.Physics.BulletSPlugin
944 m_rot.Y = 0; 996 m_rot.Y = 0;
945 changed = true; 997 changed = true;
946 } 998 }
999 if ((m_flags & VehicleFlag.LOCK_ROTATION) != 0)
1000 {
1001 m_rot.X = 0;
1002 m_rot.Y = 0;
1003 changed = true;
1004 }
947 if (changed) 1005 if (changed)
948 m_prim.Orientation = m_rot; 1006 m_prim.Orientation = m_rot;
1007
1008 DetailLog("{0},LimitRotation,done,changed={1},orig={2},new={3}", m_prim.LocalID, changed, rotq, m_rot);
1009 }
1010
1011 // Invoke the detailed logger and output something if it's enabled.
1012 private void DetailLog(string msg, params Object[] args)
1013 {
1014 if (m_prim.Scene.VehicleLoggingEnabled)
1015 m_prim.Scene.PhysicsLogging.Write(msg, args);
949 } 1016 }
950 } 1017 }
951} 1018}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 130f1ca..71a4303 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -42,6 +42,8 @@ public sealed class BSPrim : PhysicsActor
42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43 private static readonly string LogHeader = "[BULLETS PRIM]"; 43 private static readonly string LogHeader = "[BULLETS PRIM]";
44 44
45 private void DebugLog(string mm, params Object[] xx) { if (_scene.shouldDebugLog) m_log.DebugFormat(mm, xx); }
46
45 private IMesh _mesh; 47 private IMesh _mesh;
46 private PrimitiveBaseShape _pbs; 48 private PrimitiveBaseShape _pbs;
47 private ShapeData.PhysicsShapeType _shapeType; 49 private ShapeData.PhysicsShapeType _shapeType;
@@ -50,6 +52,7 @@ public sealed class BSPrim : PhysicsActor
50 private List<ConvexResult> _hulls; 52 private List<ConvexResult> _hulls;
51 53
52 private BSScene _scene; 54 private BSScene _scene;
55 public BSScene Scene { get { return _scene; } }
53 private String _avName; 56 private String _avName;
54 private uint _localID = 0; 57 private uint _localID = 0;
55 58
@@ -86,8 +89,8 @@ public sealed class BSPrim : PhysicsActor
86 private bool _kinematic; 89 private bool _kinematic;
87 private float _buoyancy; 90 private float _buoyancy;
88 91
89 private List<BSPrim> _childrenPrims;
90 private BSPrim _parentPrim; 92 private BSPrim _parentPrim;
93 private List<BSPrim> _childrenPrims;
91 94
92 private int _subscribedEventsMs = 0; 95 private int _subscribedEventsMs = 0;
93 private int _nextCollisionOkTime = 0; 96 private int _nextCollisionOkTime = 0;
@@ -145,9 +148,19 @@ public sealed class BSPrim : PhysicsActor
145 public void Destroy() 148 public void Destroy()
146 { 149 {
147 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); 150 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID);
151 // DetailLog("{0},Destroy", LocalID);
148 // Undo any vehicle properties 152 // Undo any vehicle properties
149 _vehicle.ProcessTypeChange(Vehicle.TYPE_NONE); 153 _vehicle.ProcessTypeChange(Vehicle.TYPE_NONE);
150 _scene.RemoveVehiclePrim(this); // just to make sure 154 _scene.RemoveVehiclePrim(this); // just to make sure
155
156 // undo any dependance with/on other objects
157 if (_parentPrim != null)
158 {
159 // If I'm someone's child, tell them to forget about me.
160 _parentPrim.RemoveChildFromLinkset(this);
161 _parentPrim = null;
162 }
163
151 _scene.TaintedObject(delegate() 164 _scene.TaintedObject(delegate()
152 { 165 {
153 // everything in the C# world will get garbage collected. Tell the C++ world to free stuff. 166 // everything in the C# world will get garbage collected. Tell the C++ world to free stuff.
@@ -202,7 +215,8 @@ public sealed class BSPrim : PhysicsActor
202 // link me to the specified parent 215 // link me to the specified parent
203 public override void link(PhysicsActor obj) { 216 public override void link(PhysicsActor obj) {
204 BSPrim parent = obj as BSPrim; 217 BSPrim parent = obj as BSPrim;
205 // m_log.DebugFormat("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, obj.LocalID); 218 DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, obj.LocalID);
219 DetailLog("{0},link,parent={1}", LocalID, obj.LocalID);
206 // TODO: decide if this parent checking needs to happen at taint time 220 // TODO: decide if this parent checking needs to happen at taint time
207 if (_parentPrim == null) 221 if (_parentPrim == null)
208 { 222 {
@@ -225,7 +239,7 @@ public sealed class BSPrim : PhysicsActor
225 else 239 else
226 { 240 {
227 // asking to reparent a prim should not happen 241 // asking to reparent a prim should not happen
228 m_log.ErrorFormat("{0}: Reparenting a prim. ", LogHeader); 242 m_log.ErrorFormat("{0}: link(): Reparenting a prim. ", LogHeader);
229 } 243 }
230 } 244 }
231 } 245 }
@@ -236,7 +250,9 @@ public sealed class BSPrim : PhysicsActor
236 public override void delink() { 250 public override void delink() {
237 // TODO: decide if this parent checking needs to happen at taint time 251 // TODO: decide if this parent checking needs to happen at taint time
238 // Race condition here: if link() and delink() in same simulation tick, the delink will not happen 252 // Race condition here: if link() and delink() in same simulation tick, the delink will not happen
239 // m_log.DebugFormat("{0}: delink {1}/{2}", LogHeader, _avName, _localID); 253 DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID,
254 (_parentPrim==null ? "NULL" : _parentPrim._avName+"/"+_parentPrim.LocalID.ToString()));
255 DetailLog("{0},delink,parent={1}", LocalID, (_parentPrim==null ? "NULL" : _parentPrim.LocalID.ToString()));
240 if (_parentPrim != null) 256 if (_parentPrim != null)
241 { 257 {
242 _parentPrim.RemoveChildFromLinkset(this); 258 _parentPrim.RemoveChildFromLinkset(this);
@@ -252,8 +268,10 @@ public sealed class BSPrim : PhysicsActor
252 { 268 {
253 if (!_childrenPrims.Contains(child)) 269 if (!_childrenPrims.Contains(child))
254 { 270 {
271 DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, this.LocalID);
272 DetailLog("{0},AddChildToLinkset,child={1}", LocalID, pchild.LocalID);
255 _childrenPrims.Add(child); 273 _childrenPrims.Add(child);
256 child.ParentPrim = this; // the child has gained a parent 274 child._parentPrim = this; // the child has gained a parent
257 RecreateGeomAndObject(); // rebuild my shape with the new child added 275 RecreateGeomAndObject(); // rebuild my shape with the new child added
258 } 276 }
259 }); 277 });
@@ -269,9 +287,14 @@ public sealed class BSPrim : PhysicsActor
269 { 287 {
270 if (_childrenPrims.Contains(child)) 288 if (_childrenPrims.Contains(child))
271 { 289 {
272 BulletSimAPI.RemoveConstraint(_scene.WorldID, child.LocalID, this.LocalID); 290 DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID);
291 DetailLog("{0},RemoveChildToLinkset,child={1}", LocalID, pchild.LocalID);
292 if (!BulletSimAPI.RemoveConstraintByID(_scene.WorldID, child.LocalID))
293 {
294 m_log.ErrorFormat("{0}: RemoveChildFromLinkset: Failed remove constraint for {1}", LogHeader, child.LocalID);
295 }
273 _childrenPrims.Remove(child); 296 _childrenPrims.Remove(child);
274 child.ParentPrim = null; // the child has lost its parent 297 child._parentPrim = null; // the child has lost its parent
275 RecreateGeomAndObject(); // rebuild my shape with the child removed 298 RecreateGeomAndObject(); // rebuild my shape with the child removed
276 } 299 }
277 else 300 else
@@ -282,11 +305,6 @@ public sealed class BSPrim : PhysicsActor
282 return; 305 return;
283 } 306 }
284 307
285 public BSPrim ParentPrim
286 {
287 set { _parentPrim = value; }
288 }
289
290 // return true if we are the root of a linkset (there are children to manage) 308 // return true if we are the root of a linkset (there are children to manage)
291 public bool IsRootOfLinkset 309 public bool IsRootOfLinkset
292 { 310 {
@@ -304,20 +322,28 @@ public sealed class BSPrim : PhysicsActor
304 base.RequestPhysicsterseUpdate(); 322 base.RequestPhysicsterseUpdate();
305 } 323 }
306 324
307 public override void LockAngularMotion(OMV.Vector3 axis) { return; } 325 public override void LockAngularMotion(OMV.Vector3 axis)
326 {
327 DetailLog("{0},LockAngularMotion,call,axis={1}", LocalID, axis);
328 return;
329 }
308 330
309 public override OMV.Vector3 Position { 331 public override OMV.Vector3 Position {
310 get { 332 get {
311 // don't do the following GetObjectPosition because this function is called a zillion times 333 // child prims move around based on their parent. Need to get the latest location
334 if (_parentPrim != null)
335 _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
336 // don't do the GetObjectPosition for root elements because this function is called a zillion times
312 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 337 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
313 return _position; 338 return _position;
314 } 339 }
315 set { 340 set {
316 _position = value; 341 _position = value;
342 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint?
317 _scene.TaintedObject(delegate() 343 _scene.TaintedObject(delegate()
318 { 344 {
345 DetailLog("{0},SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
319 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 346 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
320 // m_log.DebugFormat("{0}: setPosition: id={1}, position={2}", LogHeader, _localID, _position);
321 }); 347 });
322 } 348 }
323 } 349 }
@@ -330,6 +356,7 @@ public sealed class BSPrim : PhysicsActor
330 _force = value; 356 _force = value;
331 _scene.TaintedObject(delegate() 357 _scene.TaintedObject(delegate()
332 { 358 {
359 DetailLog("{0},SetForce,taint,force={1}", LocalID, _force);
333 BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); 360 BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force);
334 }); 361 });
335 } 362 }
@@ -341,15 +368,23 @@ public sealed class BSPrim : PhysicsActor
341 } 368 }
342 set { 369 set {
343 Vehicle type = (Vehicle)value; 370 Vehicle type = (Vehicle)value;
344 _vehicle.ProcessTypeChange(type);
345 _scene.TaintedObject(delegate() 371 _scene.TaintedObject(delegate()
346 { 372 {
373 DetailLog("{0},SetVehicleType,taint,type={1}", LocalID, type);
374 _vehicle.ProcessTypeChange(type);
347 if (type == Vehicle.TYPE_NONE) 375 if (type == Vehicle.TYPE_NONE)
348 { 376 {
349 _scene.RemoveVehiclePrim(this); 377 _scene.RemoveVehiclePrim(this);
350 } 378 }
351 else 379 else
352 { 380 {
381 _scene.TaintedObject(delegate()
382 {
383 // Tell the physics engine to clear state
384 IntPtr obj = BulletSimAPI.GetBodyHandleWorldID2(_scene.WorldID, LocalID);
385 BulletSimAPI.ClearForces2(obj);
386 });
387
353 // make it so the scene will call us each tick to do vehicle things 388 // make it so the scene will call us each tick to do vehicle things
354 _scene.AddVehiclePrim(this); 389 _scene.AddVehiclePrim(this);
355 } 390 }
@@ -359,37 +394,52 @@ public sealed class BSPrim : PhysicsActor
359 } 394 }
360 public override void VehicleFloatParam(int param, float value) 395 public override void VehicleFloatParam(int param, float value)
361 { 396 {
362 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value); 397 m_log.DebugFormat("{0} VehicleFloatParam. {1} <= {2}", LogHeader, param, value);
398 _scene.TaintedObject(delegate()
399 {
400 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep);
401 });
363 } 402 }
364 public override void VehicleVectorParam(int param, OMV.Vector3 value) 403 public override void VehicleVectorParam(int param, OMV.Vector3 value)
365 { 404 {
366 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value); 405 m_log.DebugFormat("{0} VehicleVectorParam. {1} <= {2}", LogHeader, param, value);
406 _scene.TaintedObject(delegate()
407 {
408 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep);
409 });
367 } 410 }
368 public override void VehicleRotationParam(int param, OMV.Quaternion rotation) 411 public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
369 { 412 {
370 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); 413 m_log.DebugFormat("{0} VehicleRotationParam. {1} <= {2}", LogHeader, param, rotation);
414 _scene.TaintedObject(delegate()
415 {
416 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
417 });
371 } 418 }
372 public override void VehicleFlags(int param, bool remove) 419 public override void VehicleFlags(int param, bool remove)
373 { 420 {
374 _vehicle.ProcessVehicleFlags(param, remove); 421 m_log.DebugFormat("{0} VehicleFlags. {1}. Remove={2}", LogHeader, param, remove);
422 _scene.TaintedObject(delegate()
423 {
424 _vehicle.ProcessVehicleFlags(param, remove);
425 });
375 } 426 }
376 // Called each simulation step to advance vehicle characteristics 427
428 // Called each simulation step to advance vehicle characteristics.
429 // Called from Scene when doing simulation step so we're in taint processing time.
377 public void StepVehicle(float timeStep) 430 public void StepVehicle(float timeStep)
378 { 431 {
379 _vehicle.Step(timeStep, _scene); 432 _vehicle.Step(timeStep);
380 } 433 }
381 434
382 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more 435 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
383 public override void SetVolumeDetect(int param) { 436 public override void SetVolumeDetect(int param) {
384 bool newValue = (param != 0); 437 bool newValue = (param != 0);
385 if (_isVolumeDetect != newValue) 438 _isVolumeDetect = newValue;
439 _scene.TaintedObject(delegate()
386 { 440 {
387 _isVolumeDetect = newValue; 441 SetObjectDynamic();
388 _scene.TaintedObject(delegate() 442 });
389 {
390 SetObjectDynamic();
391 });
392 }
393 return; 443 return;
394 } 444 }
395 445
@@ -397,9 +447,11 @@ public sealed class BSPrim : PhysicsActor
397 public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } } 447 public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } }
398 public override OMV.Vector3 Velocity { 448 public override OMV.Vector3 Velocity {
399 get { return _velocity; } 449 get { return _velocity; }
400 set { _velocity = value; 450 set {
451 _velocity = value;
401 _scene.TaintedObject(delegate() 452 _scene.TaintedObject(delegate()
402 { 453 {
454 DetailLog("{0},SetVelocity,taint,vel={1}", LocalID, _velocity);
403 BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity); 455 BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity);
404 }); 456 });
405 } 457 }
@@ -407,6 +459,7 @@ public sealed class BSPrim : PhysicsActor
407 public override OMV.Vector3 Torque { 459 public override OMV.Vector3 Torque {
408 get { return _torque; } 460 get { return _torque; }
409 set { _torque = value; 461 set { _torque = value;
462 DetailLog("{0},SetTorque,call,torque={1}", LocalID, _torque);
410 } 463 }
411 } 464 }
412 public override float CollisionScore { 465 public override float CollisionScore {
@@ -419,13 +472,21 @@ public sealed class BSPrim : PhysicsActor
419 set { _acceleration = value; } 472 set { _acceleration = value; }
420 } 473 }
421 public override OMV.Quaternion Orientation { 474 public override OMV.Quaternion Orientation {
422 get { return _orientation; } 475 get {
476 if (_parentPrim != null)
477 {
478 // children move around because tied to parent. Get a fresh value.
479 _orientation = BulletSimAPI.GetObjectOrientation(_scene.WorldID, LocalID);
480 }
481 return _orientation;
482 }
423 set { 483 set {
424 _orientation = value; 484 _orientation = value;
425 // m_log.DebugFormat("{0}: set orientation: id={1}, ori={2}", LogHeader, LocalID, _orientation); 485 // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint?
426 _scene.TaintedObject(delegate() 486 _scene.TaintedObject(delegate()
427 { 487 {
428 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 488 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
489 DetailLog("{0},SetOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation);
429 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 490 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
430 }); 491 });
431 } 492 }
@@ -458,8 +519,9 @@ public sealed class BSPrim : PhysicsActor
458 get { return !IsPhantom && !_isVolumeDetect; } 519 get { return !IsPhantom && !_isVolumeDetect; }
459 } 520 }
460 521
461 // make gravity work if the object is physical and not selected 522 // Make gravity work if the object is physical and not selected
462 // no locking here because only called when it is safe 523 // No locking here because only called when it is safe
524 // Only called at taint time so it is save to call into Bullet.
463 private void SetObjectDynamic() 525 private void SetObjectDynamic()
464 { 526 {
465 // m_log.DebugFormat("{0}: ID={1}, SetObjectDynamic: IsStatic={2}, IsSolid={3}", LogHeader, _localID, IsStatic, IsSolid); 527 // m_log.DebugFormat("{0}: ID={1}, SetObjectDynamic: IsStatic={2}, IsSolid={3}", LogHeader, _localID, IsStatic, IsSolid);
@@ -476,6 +538,7 @@ public sealed class BSPrim : PhysicsActor
476 RecreateGeomAndObject(); 538 RecreateGeomAndObject();
477 539
478 } 540 }
541 DetailLog("{0},SetObjectDynamic,taint,static={1},solid={2},mass={3}", LocalID, IsStatic, IsSolid, _mass);
479 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), _mass); 542 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), _mass);
480 } 543 }
481 544
@@ -516,11 +579,24 @@ public sealed class BSPrim : PhysicsActor
516 set { _floatOnWater = value; } 579 set { _floatOnWater = value; }
517 } 580 }
518 public override OMV.Vector3 RotationalVelocity { 581 public override OMV.Vector3 RotationalVelocity {
519 get { return _rotationalVelocity; } 582 get {
520 set { _rotationalVelocity = value; 583 /*
584 OMV.Vector3 pv = OMV.Vector3.Zero;
585 // if close to zero, report zero
586 // This is copied from ODE but I'm not sure why it returns zero but doesn't
587 // zero the property in the physics engine.
588 if (_rotationalVelocity.ApproxEquals(pv, 0.2f))
589 return pv;
590 */
591
592 return _rotationalVelocity;
593 }
594 set {
595 _rotationalVelocity = value;
521 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); 596 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
522 _scene.TaintedObject(delegate() 597 _scene.TaintedObject(delegate()
523 { 598 {
599 DetailLog("{0},SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
524 BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity); 600 BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity);
525 }); 601 });
526 } 602 }
@@ -533,11 +609,13 @@ public sealed class BSPrim : PhysicsActor
533 } 609 }
534 public override float Buoyancy { 610 public override float Buoyancy {
535 get { return _buoyancy; } 611 get { return _buoyancy; }
536 set { _buoyancy = value; 612 set {
537 _scene.TaintedObject(delegate() 613 _buoyancy = value;
538 { 614 _scene.TaintedObject(delegate()
539 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy); 615 {
540 }); 616 DetailLog("{0},SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
617 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy);
618 });
541 } 619 }
542 } 620 }
543 621
@@ -573,27 +651,45 @@ public sealed class BSPrim : PhysicsActor
573 public override float APIDStrength { set { return; } } 651 public override float APIDStrength { set { return; } }
574 public override float APIDDamping { set { return; } } 652 public override float APIDDamping { set { return; } }
575 653
654 private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>();
576 public override void AddForce(OMV.Vector3 force, bool pushforce) { 655 public override void AddForce(OMV.Vector3 force, bool pushforce) {
577 if (force.IsFinite()) 656 if (force.IsFinite())
578 { 657 {
579 _force.X += force.X; 658 // _force += force;
580 _force.Y += force.Y; 659 lock (m_accumulatedForces)
581 _force.Z += force.Z; 660 m_accumulatedForces.Add(new OMV.Vector3(force));
582 } 661 }
583 else 662 else
584 { 663 {
585 m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader); 664 m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader);
665 return;
586 } 666 }
587 _scene.TaintedObject(delegate() 667 _scene.TaintedObject(delegate()
588 { 668 {
589 BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); 669 lock (m_accumulatedForces)
670 {
671 if (m_accumulatedForces.Count > 0)
672 {
673 OMV.Vector3 fSum = OMV.Vector3.Zero;
674 foreach (OMV.Vector3 v in m_accumulatedForces)
675 {
676 fSum += v;
677 }
678 m_accumulatedForces.Clear();
679
680 DetailLog("{0},SetObjectForce,taint,force={1}", LocalID, fSum);
681 BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, fSum);
682 }
683 }
590 }); 684 });
591 } 685 }
592 686
593 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { 687 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
688 DetailLog("{0},AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce);
594 // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce); 689 // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce);
595 } 690 }
596 public override void SetMomentum(OMV.Vector3 momentum) { 691 public override void SetMomentum(OMV.Vector3 momentum) {
692 DetailLog("{0},SetMomentum,call,mom={1}", LocalID, momentum);
597 } 693 }
598 public override void SubscribeEvents(int ms) { 694 public override void SubscribeEvents(int ms) {
599 _subscribedEventsMs = ms; 695 _subscribedEventsMs = ms;
@@ -918,6 +1014,7 @@ public sealed class BSPrim : PhysicsActor
918 { 1014 {
919 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size); 1015 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size);
920 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; 1016 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE;
1017 DetailLog("{0},CreateGeom,sphere", LocalID);
921 // Bullet native objects are scaled by the Bullet engine so pass the size in 1018 // Bullet native objects are scaled by the Bullet engine so pass the size in
922 _scale = _size; 1019 _scale = _size;
923 } 1020 }
@@ -925,6 +1022,7 @@ public sealed class BSPrim : PhysicsActor
925 else 1022 else
926 { 1023 {
927 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, size={2}", LogHeader, LocalID, _size); 1024 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, size={2}", LogHeader, LocalID, _size);
1025 DetailLog("{0},CreateGeom,box", LocalID);
928 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; 1026 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX;
929 _scale = _size; 1027 _scale = _size;
930 } 1028 }
@@ -961,10 +1059,12 @@ public sealed class BSPrim : PhysicsActor
961 // if this new shape is the same as last time, don't recreate the mesh 1059 // if this new shape is the same as last time, don't recreate the mesh
962 if (_meshKey == newMeshKey) return; 1060 if (_meshKey == newMeshKey) return;
963 1061
1062 DetailLog("{0},CreateGeomMesh,create,key={1}", LocalID, _meshKey);
964 // Since we're recreating new, get rid of any previously generated shape 1063 // Since we're recreating new, get rid of any previously generated shape
965 if (_meshKey != 0) 1064 if (_meshKey != 0)
966 { 1065 {
967 // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey); 1066 // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey);
1067 DetailLog("{0},CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey);
968 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); 1068 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey);
969 _mesh = null; 1069 _mesh = null;
970 _meshKey = 0; 1070 _meshKey = 0;
@@ -981,7 +1081,6 @@ public sealed class BSPrim : PhysicsActor
981 int vi = 0; 1081 int vi = 0;
982 foreach (OMV.Vector3 vv in vertices) 1082 foreach (OMV.Vector3 vv in vertices)
983 { 1083 {
984 // m_log.DebugFormat("{0}: {1}: <{2:0.00}, {3:0.00}, {4:0.00}>", LogHeader, vi / 3, vv.X, vv.Y, vv.Z);
985 verticesAsFloats[vi++] = vv.X; 1084 verticesAsFloats[vi++] = vv.X;
986 verticesAsFloats[vi++] = vv.Y; 1085 verticesAsFloats[vi++] = vv.Y;
987 verticesAsFloats[vi++] = vv.Z; 1086 verticesAsFloats[vi++] = vv.Z;
@@ -995,6 +1094,7 @@ public sealed class BSPrim : PhysicsActor
995 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH; 1094 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH;
996 // meshes are already scaled by the meshmerizer 1095 // meshes are already scaled by the meshmerizer
997 _scale = new OMV.Vector3(1f, 1f, 1f); 1096 _scale = new OMV.Vector3(1f, 1f, 1f);
1097 DetailLog("{0},CreateGeomMesh,done", LocalID);
998 return; 1098 return;
999 } 1099 }
1000 1100
@@ -1008,13 +1108,17 @@ public sealed class BSPrim : PhysicsActor
1008 // if the hull hasn't changed, don't rebuild it 1108 // if the hull hasn't changed, don't rebuild it
1009 if (newHullKey == _hullKey) return; 1109 if (newHullKey == _hullKey) return;
1010 1110
1111 DetailLog("{0},CreateGeomHull,create,key={1}", LocalID, _meshKey);
1112
1011 // Since we're recreating new, get rid of any previously generated shape 1113 // Since we're recreating new, get rid of any previously generated shape
1012 if (_hullKey != 0) 1114 if (_hullKey != 0)
1013 { 1115 {
1014 // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey); 1116 // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey);
1117 DetailLog("{0},CreateGeomHull,deleteOldHull,key={1}", LocalID, _meshKey);
1015 BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey); 1118 BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey);
1016 _hullKey = 0; 1119 _hullKey = 0;
1017 _hulls.Clear(); 1120 _hulls.Clear();
1121 DetailLog("{0},CreateGeomHull,deleteOldMesh,key={1}", LocalID, _meshKey);
1018 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); 1122 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey);
1019 _mesh = null; // the mesh cannot match either 1123 _mesh = null; // the mesh cannot match either
1020 _meshKey = 0; 1124 _meshKey = 0;
@@ -1111,6 +1215,7 @@ public sealed class BSPrim : PhysicsActor
1111 _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL; 1215 _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL;
1112 // meshes are already scaled by the meshmerizer 1216 // meshes are already scaled by the meshmerizer
1113 _scale = new OMV.Vector3(1f, 1f, 1f); 1217 _scale = new OMV.Vector3(1f, 1f, 1f);
1218 DetailLog("{0},CreateGeomHull,done", LocalID);
1114 return; 1219 return;
1115 } 1220 }
1116 1221
@@ -1129,7 +1234,6 @@ public sealed class BSPrim : PhysicsActor
1129 if (IsRootOfLinkset) 1234 if (IsRootOfLinkset)
1130 { 1235 {
1131 // Create a linkset around this object 1236 // Create a linkset around this object
1132 // CreateLinksetWithCompoundHull();
1133 CreateLinksetWithConstraints(); 1237 CreateLinksetWithConstraints();
1134 } 1238 }
1135 else 1239 else
@@ -1191,33 +1295,33 @@ public sealed class BSPrim : PhysicsActor
1191 // TODO: make this more effeicient: a large linkset gets rebuilt over and over and prims are added 1295 // TODO: make this more effeicient: a large linkset gets rebuilt over and over and prims are added
1192 void CreateLinksetWithConstraints() 1296 void CreateLinksetWithConstraints()
1193 { 1297 {
1194 // m_log.DebugFormat("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, _childrenPrims.Count+1); 1298 DebugLog("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, _childrenPrims.Count+1);
1195 1299
1196 // remove any constraints that might be in place 1300 // remove any constraints that might be in place
1197 foreach (BSPrim prim in _childrenPrims) 1301 foreach (BSPrim prim in _childrenPrims)
1198 { 1302 {
1199 // m_log.DebugFormat("{0}: CreateLinkset: RemoveConstraint between root prim {1} and child prim {2}", LogHeader, LocalID, prim.LocalID); 1303 DebugLog("{0}: CreateLinkset: RemoveConstraint between root prim {1} and child prim {2}", LogHeader, LocalID, prim.LocalID);
1200 BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, prim.LocalID); 1304 BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, prim.LocalID);
1201 } 1305 }
1202 // create constraints between the root prim and each of the children 1306 // create constraints between the root prim and each of the children
1203 foreach (BSPrim prim in _childrenPrims) 1307 foreach (BSPrim prim in _childrenPrims)
1204 { 1308 {
1205 // m_log.DebugFormat("{0}: CreateLinkset: AddConstraint between root prim {1} and child prim {2}", LogHeader, LocalID, prim.LocalID);
1206
1207 // Zero motion for children so they don't interpolate 1309 // Zero motion for children so they don't interpolate
1208 prim.ZeroMotion(); 1310 prim.ZeroMotion();
1209 1311
1210 // relative position normalized to the root prim 1312 // relative position normalized to the root prim
1211 OMV.Vector3 childRelativePosition = (prim._position - this._position) * OMV.Quaternion.Inverse(this._orientation); 1313 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(this._orientation);
1314 OMV.Vector3 childRelativePosition = (prim._position - this._position) * invThisOrientation;
1212 1315
1213 // relative rotation of the child to the parent 1316 // relative rotation of the child to the parent
1214 OMV.Quaternion relativeRotation = OMV.Quaternion.Inverse(prim._orientation) * this._orientation; 1317 OMV.Quaternion childRelativeRotation = invThisOrientation * prim._orientation;
1215 1318
1216 // this is a constraint that allows no freedom of movement between the two objects 1319 // this is a constraint that allows no freedom of movement between the two objects
1217 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 1320 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
1321 DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, prim.LocalID);
1218 BulletSimAPI.AddConstraint(_scene.WorldID, LocalID, prim.LocalID, 1322 BulletSimAPI.AddConstraint(_scene.WorldID, LocalID, prim.LocalID,
1219 childRelativePosition, 1323 childRelativePosition,
1220 relativeRotation, 1324 childRelativeRotation,
1221 OMV.Vector3.Zero, 1325 OMV.Vector3.Zero,
1222 OMV.Quaternion.Identity, 1326 OMV.Quaternion.Identity,
1223 OMV.Vector3.Zero, OMV.Vector3.Zero, 1327 OMV.Vector3.Zero, OMV.Vector3.Zero,
@@ -1252,78 +1356,71 @@ public sealed class BSPrim : PhysicsActor
1252 const float POSITION_TOLERANCE = 0.05f; 1356 const float POSITION_TOLERANCE = 0.05f;
1253 const float ACCELERATION_TOLERANCE = 0.01f; 1357 const float ACCELERATION_TOLERANCE = 0.01f;
1254 const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f; 1358 const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f;
1255 const bool SHOULD_DAMP_UPDATES = false;
1256 1359
1257 public void UpdateProperties(EntityProperties entprop) 1360 public void UpdateProperties(EntityProperties entprop)
1258 { 1361 {
1362 /*
1259 UpdatedProperties changed = 0; 1363 UpdatedProperties changed = 0;
1260 if (SHOULD_DAMP_UPDATES) 1364 // assign to the local variables so the normal set action does not happen
1365 // if (_position != entprop.Position)
1366 if (!_position.ApproxEquals(entprop.Position, POSITION_TOLERANCE))
1261 { 1367 {
1262 // assign to the local variables so the normal set action does not happen 1368 _position = entprop.Position;
1263 // if (_position != entprop.Position) 1369 changed |= UpdatedProperties.Position;
1264 if (!_position.ApproxEquals(entprop.Position, POSITION_TOLERANCE))
1265 {
1266 _position = entprop.Position;
1267 // m_log.DebugFormat("{0}: UpdateProperties: id={1}, pos = {2}", LogHeader, LocalID, _position);
1268 changed |= UpdatedProperties.Position;
1269 }
1270 // if (_orientation != entprop.Rotation)
1271 if (!_orientation.ApproxEquals(entprop.Rotation, ROTATION_TOLERANCE))
1272 {
1273 _orientation = entprop.Rotation;
1274 // m_log.DebugFormat("{0}: UpdateProperties: id={1}, rot = {2}", LogHeader, LocalID, _orientation);
1275 changed |= UpdatedProperties.Rotation;
1276 }
1277 // if (_velocity != entprop.Velocity)
1278 if (!_velocity.ApproxEquals(entprop.Velocity, VELOCITY_TOLERANCE))
1279 {
1280 _velocity = entprop.Velocity;
1281 // m_log.DebugFormat("{0}: UpdateProperties: velocity = {1}", LogHeader, _velocity);
1282 changed |= UpdatedProperties.Velocity;
1283 }
1284 // if (_acceleration != entprop.Acceleration)
1285 if (!_acceleration.ApproxEquals(entprop.Acceleration, ACCELERATION_TOLERANCE))
1286 {
1287 _acceleration = entprop.Acceleration;
1288 // m_log.DebugFormat("{0}: UpdateProperties: acceleration = {1}", LogHeader, _acceleration);
1289 changed |= UpdatedProperties.Acceleration;
1290 }
1291 // if (_rotationalVelocity != entprop.RotationalVelocity)
1292 if (!_rotationalVelocity.ApproxEquals(entprop.RotationalVelocity, ROTATIONAL_VELOCITY_TOLERANCE))
1293 {
1294 _rotationalVelocity = entprop.RotationalVelocity;
1295 // m_log.DebugFormat("{0}: UpdateProperties: rotationalVelocity = {1}", LogHeader, _rotationalVelocity);
1296 changed |= UpdatedProperties.RotationalVel;
1297 }
1298 if (changed != 0)
1299 {
1300 // m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation);
1301 // Only update the position of single objects and linkset roots
1302 if (this._parentPrim == null)
1303 {
1304 // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation);
1305 base.RequestPhysicsterseUpdate();
1306 }
1307 }
1308 } 1370 }
1309 else 1371 // if (_orientation != entprop.Rotation)
1372 if (!_orientation.ApproxEquals(entprop.Rotation, ROTATION_TOLERANCE))
1310 { 1373 {
1311 // Don't check for damping here -- it's done in BulletSim and SceneObjectPart. 1374 _orientation = entprop.Rotation;
1312 1375 changed |= UpdatedProperties.Rotation;
1313 // Only updates only for individual prims and for the root object of a linkset. 1376 }
1377 // if (_velocity != entprop.Velocity)
1378 if (!_velocity.ApproxEquals(entprop.Velocity, VELOCITY_TOLERANCE))
1379 {
1380 _velocity = entprop.Velocity;
1381 changed |= UpdatedProperties.Velocity;
1382 }
1383 // if (_acceleration != entprop.Acceleration)
1384 if (!_acceleration.ApproxEquals(entprop.Acceleration, ACCELERATION_TOLERANCE))
1385 {
1386 _acceleration = entprop.Acceleration;
1387 changed |= UpdatedProperties.Acceleration;
1388 }
1389 // if (_rotationalVelocity != entprop.RotationalVelocity)
1390 if (!_rotationalVelocity.ApproxEquals(entprop.RotationalVelocity, ROTATIONAL_VELOCITY_TOLERANCE))
1391 {
1392 _rotationalVelocity = entprop.RotationalVelocity;
1393 changed |= UpdatedProperties.RotationalVel;
1394 }
1395 if (changed != 0)
1396 {
1397 // Only update the position of single objects and linkset roots
1314 if (this._parentPrim == null) 1398 if (this._parentPrim == null)
1315 { 1399 {
1316 // Assign to the local variables so the normal set action does not happen
1317 _position = entprop.Position;
1318 _orientation = entprop.Rotation;
1319 _velocity = entprop.Velocity;
1320 _acceleration = entprop.Acceleration;
1321 _rotationalVelocity = entprop.RotationalVelocity;
1322 // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}",
1323 // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
1324 base.RequestPhysicsterseUpdate(); 1400 base.RequestPhysicsterseUpdate();
1325 } 1401 }
1326 } 1402 }
1403 */
1404
1405 // Don't check for damping here -- it's done in BulletSim and SceneObjectPart.
1406
1407 // Updates only for individual prims and for the root object of a linkset.
1408 if (this._parentPrim == null)
1409 {
1410 // Assign to the local variables so the normal set action does not happen
1411 _position = entprop.Position;
1412 _orientation = entprop.Rotation;
1413 _velocity = entprop.Velocity;
1414 _acceleration = entprop.Acceleration;
1415 _rotationalVelocity = entprop.RotationalVelocity;
1416
1417 // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}",
1418 // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
1419 DetailLog("{0},UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1420 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
1421
1422 base.RequestPhysicsterseUpdate();
1423 }
1327 } 1424 }
1328 1425
1329 // I've collided with something 1426 // I've collided with something
@@ -1362,5 +1459,11 @@ public sealed class BSPrim : PhysicsActor
1362 collisionCollection.Clear(); 1459 collisionCollection.Clear();
1363 } 1460 }
1364 } 1461 }
1462
1463 // Invoke the detailed logger and output something if it's enabled.
1464 private void DetailLog(string msg, params Object[] args)
1465 {
1466 Scene.PhysicsLogging.Write(msg, args);
1467 }
1365} 1468}
1366} 1469}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 417cb5f..8773485 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -29,12 +29,14 @@ using System.Collections.Generic;
29using System.Runtime.InteropServices; 29using System.Runtime.InteropServices;
30using System.Text; 30using System.Text;
31using System.Threading; 31using System.Threading;
32using Nini.Config;
33using log4net;
34using OpenSim.Framework; 32using OpenSim.Framework;
33using OpenSim.Region.Framework;
34using OpenSim.Region.CoreModules;
35using Logging = OpenSim.Region.CoreModules.Framework.Statistics.Logging;
35using OpenSim.Region.Physics.Manager; 36using OpenSim.Region.Physics.Manager;
37using Nini.Config;
38using log4net;
36using OpenMetaverse; 39using OpenMetaverse;
37using OpenSim.Region.Framework;
38 40
39// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim) 41// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim)
40// Debug linkset 42// Debug linkset
@@ -44,15 +46,17 @@ using OpenSim.Region.Framework;
44// Compute physics FPS reasonably 46// Compute physics FPS reasonably
45// Based on material, set density and friction 47// Based on material, set density and friction
46// More efficient memory usage when passing hull information from BSPrim to BulletSim 48// More efficient memory usage when passing hull information from BSPrim to BulletSim
49// Move all logic out of the C++ code and into the C# code for easier future modifications.
47// Four states of prim: Physical, regular, phantom and selected. Are we modeling these correctly? 50// Four states of prim: Physical, regular, phantom and selected. Are we modeling these correctly?
48// In SL one can set both physical and phantom (gravity, does not effect others, makes collisions with ground) 51// In SL one can set both physical and phantom (gravity, does not effect others, makes collisions with ground)
49// At the moment, physical and phantom causes object to drop through the terrain 52// At the moment, physical and phantom causes object to drop through the terrain
50// Physical phantom objects and related typing (collision options ) 53// Physical phantom objects and related typing (collision options )
54// Use collision masks for collision with terrain and phantom objects
51// Check out llVolumeDetect. Must do something for that. 55// Check out llVolumeDetect. Must do something for that.
52// Should prim.link() and prim.delink() membership checking happen at taint time? 56// Should prim.link() and prim.delink() membership checking happen at taint time?
57// changing the position and orientation of a linked prim must rebuild the constraint with the root.
53// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once 58// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once
54// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect 59// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect
55// Use collision masks for collision with terrain and phantom objects
56// Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions) 60// Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions)
57// Implement LockAngularMotion 61// Implement LockAngularMotion
58// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation) 62// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation)
@@ -60,9 +64,6 @@ using OpenSim.Region.Framework;
60// Remove mesh and Hull stuff. Use mesh passed to bullet and use convexdecom from bullet. 64// Remove mesh and Hull stuff. Use mesh passed to bullet and use convexdecom from bullet.
61// Add PID movement operations. What does ScenePresence.MoveToTarget do? 65// Add PID movement operations. What does ScenePresence.MoveToTarget do?
62// Check terrain size. 128 or 127? 66// Check terrain size. 128 or 127?
63// Multiple contact points on collision?
64// See code in ode::near... calls to collision_accounting_events()
65// (This might not be a problem. ODE collects all the collisions with one object in one tick.)
66// Raycast 67// Raycast
67// 68//
68namespace OpenSim.Region.Physics.BulletSPlugin 69namespace OpenSim.Region.Physics.BulletSPlugin
@@ -72,6 +73,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
72 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 73 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
73 private static readonly string LogHeader = "[BULLETS SCENE]"; 74 private static readonly string LogHeader = "[BULLETS SCENE]";
74 75
76 private void DebugLog(string mm, params Object[] xx) { if (shouldDebugLog) m_log.DebugFormat(mm, xx); }
77
75 public string BulletSimVersion = "?"; 78 public string BulletSimVersion = "?";
76 79
77 private Dictionary<uint, BSCharacter> m_avatars = new Dictionary<uint, BSCharacter>(); 80 private Dictionary<uint, BSCharacter> m_avatars = new Dictionary<uint, BSCharacter>();
@@ -105,6 +108,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
105 private long m_simulationStep = 0; 108 private long m_simulationStep = 0;
106 public long SimulationStep { get { return m_simulationStep; } } 109 public long SimulationStep { get { return m_simulationStep; } }
107 110
111 public float LastSimulatedTimestep { get; private set; }
112
108 // A value of the time now so all the collision and update routines do not have to get their own 113 // A value of the time now so all the collision and update routines do not have to get their own
109 // Set to 'now' just before all the prims and actors are called for collisions and updates 114 // Set to 'now' just before all the prims and actors are called for collisions and updates
110 private int m_simulationNowTime; 115 private int m_simulationNowTime;
@@ -121,6 +126,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
121 private bool _meshSculptedPrim = true; // cause scuplted prims to get meshed 126 private bool _meshSculptedPrim = true; // cause scuplted prims to get meshed
122 private bool _forceSimplePrimMeshing = false; // if a cube or sphere, let Bullet do internal shapes 127 private bool _forceSimplePrimMeshing = false; // if a cube or sphere, let Bullet do internal shapes
123 128
129 public float PID_D { get; private set; } // derivative
130 public float PID_P { get; private set; } // proportional
131
124 public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero 132 public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero
125 public const uint GROUNDPLANE_ID = 1; 133 public const uint GROUNDPLANE_ID = 1;
126 134
@@ -147,8 +155,20 @@ public class BSScene : PhysicsScene, IPhysicsParameters
147 ConfigurationParameters[] m_params; 155 ConfigurationParameters[] m_params;
148 GCHandle m_paramsHandle; 156 GCHandle m_paramsHandle;
149 157
158 public bool shouldDebugLog { get; private set; }
159
150 private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle; 160 private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle;
151 161
162 // Sometimes you just have to log everything.
163 public Logging.LogWriter PhysicsLogging;
164 private bool m_physicsLoggingEnabled;
165 private string m_physicsLoggingDir;
166 private string m_physicsLoggingPrefix;
167 private int m_physicsLoggingFileMinutes;
168
169 private bool m_vehicleLoggingEnabled;
170 public bool VehicleLoggingEnabled { get { return m_vehicleLoggingEnabled; } }
171
152 public BSScene(string identifier) 172 public BSScene(string identifier)
153 { 173 {
154 m_initialized = false; 174 m_initialized = false;
@@ -169,17 +189,32 @@ public class BSScene : PhysicsScene, IPhysicsParameters
169 m_updateArray = new EntityProperties[m_maxUpdatesPerFrame]; 189 m_updateArray = new EntityProperties[m_maxUpdatesPerFrame];
170 m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned); 190 m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned);
171 191
192 // Enable very detailed logging.
193 // By creating an empty logger when not logging, the log message invocation code
194 // can be left in and every call doesn't have to check for null.
195 if (m_physicsLoggingEnabled)
196 {
197 PhysicsLogging = new Logging.LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes);
198 }
199 else
200 {
201 PhysicsLogging = new Logging.LogWriter();
202 }
203
172 // Get the version of the DLL 204 // Get the version of the DLL
173 // TODO: this doesn't work yet. Something wrong with marshaling the returned string. 205 // TODO: this doesn't work yet. Something wrong with marshaling the returned string.
174 // BulletSimVersion = BulletSimAPI.GetVersion(); 206 // BulletSimVersion = BulletSimAPI.GetVersion();
175 // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion); 207 // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion);
176 208
177 // if Debug, enable logging from the unmanaged code 209 // if Debug, enable logging from the unmanaged code
178 if (m_log.IsDebugEnabled) 210 if (m_log.IsDebugEnabled || PhysicsLogging.Enabled)
179 { 211 {
180 m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader); 212 m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader);
181 // the handle is saved to it doesn't get freed after this call 213 if (PhysicsLogging.Enabled)
182 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger); 214 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog);
215 else
216 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger);
217 // the handle is saved in a variable to make sure it doesn't get freed after this call
183 BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle); 218 BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle);
184 } 219 }
185 220
@@ -209,6 +244,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
209 m_meshLOD = 8f; 244 m_meshLOD = 8f;
210 m_sculptLOD = 32f; 245 m_sculptLOD = 32f;
211 246
247 shouldDebugLog = false;
212 m_detailedStatsStep = 0; // disabled 248 m_detailedStatsStep = 0; // disabled
213 249
214 m_maxSubSteps = 10; 250 m_maxSubSteps = 10;
@@ -217,6 +253,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
217 m_maxUpdatesPerFrame = 2048; 253 m_maxUpdatesPerFrame = 2048;
218 m_maximumObjectMass = 10000.01f; 254 m_maximumObjectMass = 10000.01f;
219 255
256 PID_D = 2200f;
257 PID_P = 900f;
258
220 parms.defaultFriction = 0.5f; 259 parms.defaultFriction = 0.5f;
221 parms.defaultDensity = 10.000006836f; // Aluminum g/cm3 260 parms.defaultDensity = 10.000006836f; // Aluminum g/cm3
222 parms.defaultRestitution = 0f; 261 parms.defaultRestitution = 0f;
@@ -261,7 +300,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
261 _meshSculptedPrim = pConfig.GetBoolean("MeshSculptedPrim", _meshSculptedPrim); 300 _meshSculptedPrim = pConfig.GetBoolean("MeshSculptedPrim", _meshSculptedPrim);
262 _forceSimplePrimMeshing = pConfig.GetBoolean("ForceSimplePrimMeshing", _forceSimplePrimMeshing); 301 _forceSimplePrimMeshing = pConfig.GetBoolean("ForceSimplePrimMeshing", _forceSimplePrimMeshing);
263 302
303 shouldDebugLog = pConfig.GetBoolean("ShouldDebugLog", shouldDebugLog);
264 m_detailedStatsStep = pConfig.GetInt("DetailedStatsStep", m_detailedStatsStep); 304 m_detailedStatsStep = pConfig.GetInt("DetailedStatsStep", m_detailedStatsStep);
305
265 m_meshLOD = pConfig.GetFloat("MeshLevelOfDetail", m_meshLOD); 306 m_meshLOD = pConfig.GetFloat("MeshLevelOfDetail", m_meshLOD);
266 m_sculptLOD = pConfig.GetFloat("SculptLevelOfDetail", m_sculptLOD); 307 m_sculptLOD = pConfig.GetFloat("SculptLevelOfDetail", m_sculptLOD);
267 308
@@ -271,6 +312,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
271 m_maxUpdatesPerFrame = pConfig.GetInt("MaxUpdatesPerFrame", m_maxUpdatesPerFrame); 312 m_maxUpdatesPerFrame = pConfig.GetInt("MaxUpdatesPerFrame", m_maxUpdatesPerFrame);
272 m_maximumObjectMass = pConfig.GetFloat("MaxObjectMass", m_maximumObjectMass); 313 m_maximumObjectMass = pConfig.GetFloat("MaxObjectMass", m_maximumObjectMass);
273 314
315 PID_D = pConfig.GetFloat("PIDDerivative", PID_D);
316 PID_P = pConfig.GetFloat("PIDProportional", PID_P);
317
274 parms.defaultFriction = pConfig.GetFloat("DefaultFriction", parms.defaultFriction); 318 parms.defaultFriction = pConfig.GetFloat("DefaultFriction", parms.defaultFriction);
275 parms.defaultDensity = pConfig.GetFloat("DefaultDensity", parms.defaultDensity); 319 parms.defaultDensity = pConfig.GetFloat("DefaultDensity", parms.defaultDensity);
276 parms.defaultRestitution = pConfig.GetFloat("DefaultRestitution", parms.defaultRestitution); 320 parms.defaultRestitution = pConfig.GetFloat("DefaultRestitution", parms.defaultRestitution);
@@ -303,6 +347,14 @@ public class BSScene : PhysicsScene, IPhysicsParameters
303 parms.shouldSplitSimulationIslands = ParamBoolean(pConfig, "ShouldSplitSimulationIslands", parms.shouldSplitSimulationIslands); 347 parms.shouldSplitSimulationIslands = ParamBoolean(pConfig, "ShouldSplitSimulationIslands", parms.shouldSplitSimulationIslands);
304 parms.shouldEnableFrictionCaching = ParamBoolean(pConfig, "ShouldEnableFrictionCaching", parms.shouldEnableFrictionCaching); 348 parms.shouldEnableFrictionCaching = ParamBoolean(pConfig, "ShouldEnableFrictionCaching", parms.shouldEnableFrictionCaching);
305 parms.numberOfSolverIterations = pConfig.GetFloat("NumberOfSolverIterations", parms.numberOfSolverIterations); 349 parms.numberOfSolverIterations = pConfig.GetFloat("NumberOfSolverIterations", parms.numberOfSolverIterations);
350
351 // Very detailed logging for physics debugging
352 m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false);
353 m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", ".");
354 m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-");
355 m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5);
356 // Very detailed logging for vehicle debugging
357 m_vehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false);
306 } 358 }
307 } 359 }
308 m_params[0] = parms; 360 m_params[0] = parms;
@@ -323,12 +375,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters
323 return ret; 375 return ret;
324 } 376 }
325 377
326
327 // Called directly from unmanaged code so don't do much 378 // Called directly from unmanaged code so don't do much
328 private void BulletLogger(string msg) 379 private void BulletLogger(string msg)
329 { 380 {
330 m_log.Debug("[BULLETS UNMANAGED]:" + msg); 381 m_log.Debug("[BULLETS UNMANAGED]:" + msg);
331 } 382 }
383
384 // Called directly from unmanaged code so don't do much
385 private void BulletLoggerPhysLog(string msg)
386 {
387 PhysicsLogging.Write("[BULLETS UNMANAGED]:" + msg);
388 }
332 389
333 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying) 390 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying)
334 { 391 {
@@ -347,34 +404,42 @@ public class BSScene : PhysicsScene, IPhysicsParameters
347 public override void RemoveAvatar(PhysicsActor actor) 404 public override void RemoveAvatar(PhysicsActor actor)
348 { 405 {
349 // m_log.DebugFormat("{0}: RemoveAvatar", LogHeader); 406 // m_log.DebugFormat("{0}: RemoveAvatar", LogHeader);
350 if (actor is BSCharacter) 407 BSCharacter bsactor = actor as BSCharacter;
351 { 408 if (bsactor != null)
352 ((BSCharacter)actor).Destroy();
353 }
354 try
355 { 409 {
356 lock (m_avatars) m_avatars.Remove(actor.LocalID); 410 try
357 } 411 {
358 catch (Exception e) 412 lock (m_avatars) m_avatars.Remove(actor.LocalID);
359 { 413 }
360 m_log.WarnFormat("{0}: Attempt to remove avatar that is not in physics scene: {1}", LogHeader, e); 414 catch (Exception e)
415 {
416 m_log.WarnFormat("{0}: Attempt to remove avatar that is not in physics scene: {1}", LogHeader, e);
417 }
418 bsactor.Destroy();
419 // bsactor.dispose();
361 } 420 }
362 } 421 }
363 422
364 public override void RemovePrim(PhysicsActor prim) 423 public override void RemovePrim(PhysicsActor prim)
365 { 424 {
366 // m_log.DebugFormat("{0}: RemovePrim", LogHeader); 425 BSPrim bsprim = prim as BSPrim;
367 if (prim is BSPrim) 426 if (bsprim != null)
368 {
369 ((BSPrim)prim).Destroy();
370 }
371 try
372 { 427 {
373 lock (m_prims) m_prims.Remove(prim.LocalID); 428 m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID);
429 try
430 {
431 lock (m_prims) m_prims.Remove(bsprim.LocalID);
432 }
433 catch (Exception e)
434 {
435 m_log.ErrorFormat("{0}: Attempt to remove prim that is not in physics scene: {1}", LogHeader, e);
436 }
437 bsprim.Destroy();
438 // bsprim.dispose();
374 } 439 }
375 catch (Exception e) 440 else
376 { 441 {
377 m_log.WarnFormat("{0}: Attempt to remove prim that is not in physics scene: {1}", LogHeader, e); 442 m_log.ErrorFormat("{0}: Attempt to remove prim that is not a BSPrim type.", LogHeader);
378 } 443 }
379 } 444 }
380 445
@@ -400,6 +465,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
400 int collidersCount; 465 int collidersCount;
401 IntPtr collidersPtr; 466 IntPtr collidersPtr;
402 467
468 LastSimulatedTimestep = timeStep;
469
403 // prevent simulation until we've been initialized 470 // prevent simulation until we've been initialized
404 if (!m_initialized) return 10.0f; 471 if (!m_initialized) return 10.0f;
405 472
@@ -459,7 +526,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
459 for (int ii = 0; ii < updatedEntityCount; ii++) 526 for (int ii = 0; ii < updatedEntityCount; ii++)
460 { 527 {
461 EntityProperties entprop = m_updateArray[ii]; 528 EntityProperties entprop = m_updateArray[ii];
462 // m_log.DebugFormat("{0}: entprop[{1}]: id={2}, pos={3}", LogHeader, ii, entprop.ID, entprop.Position);
463 BSPrim prim; 529 BSPrim prim;
464 if (m_prims.TryGetValue(entprop.ID, out prim)) 530 if (m_prims.TryGetValue(entprop.ID, out prim))
465 { 531 {
@@ -532,8 +598,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters
532 }); 598 });
533 } 599 }
534 600
601 // Someday we will have complex terrain with caves and tunnels
602 // For the moment, it's flat and convex
603 public float GetTerrainHeightAtXYZ(Vector3 loc)
604 {
605 return GetTerrainHeightAtXY(loc.X, loc.Y);
606 }
607
535 public float GetTerrainHeightAtXY(float tX, float tY) 608 public float GetTerrainHeightAtXY(float tX, float tY)
536 { 609 {
610 if (tX < 0 || tX >= Constants.RegionSize || tY < 0 || tY >= Constants.RegionSize)
611 return 30;
537 return m_heightMap[((int)tX) * Constants.RegionSize + ((int)tY)]; 612 return m_heightMap[((int)tX) * Constants.RegionSize + ((int)tY)];
538 } 613 }
539 614
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
index 086f0dc..babb707 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
@@ -146,6 +146,22 @@ public struct ConfigurationParameters
146 public const float numericFalse = 0f; 146 public const float numericFalse = 0f;
147} 147}
148 148
149// Values used by Bullet and BulletSim to control collisions
150public enum CollisionFlags : uint
151{
152 STATIC_OBJECT = 1 << 0,
153 KINEMATIC_OBJECT = 1 << 1,
154 NO_CONTACT_RESPONSE = 1 << 2,
155 CUSTOM_MATERIAL_CALLBACK = 1 << 3,
156 CHARACTER_OBJECT = 1 << 4,
157 DISABLE_VISUALIZE_OBJECT = 1 << 5,
158 DISABLE_SPU_COLLISION_PROCESS = 1 << 6,
159 // Following used by BulletSim to control collisions
160 VOLUME_DETECT_OBJECT = 1 << 10,
161 PHANTOM_OBJECT = 1 << 11,
162 PHYSICAL_OBJECT = 1 << 12,
163};
164
149static class BulletSimAPI { 165static class BulletSimAPI {
150 166
151[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 167[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@@ -214,6 +230,9 @@ public static extern bool RemoveConstraint(uint worldID, uint id1, uint id2);
214public static extern Vector3 GetObjectPosition(uint WorldID, uint id); 230public static extern Vector3 GetObjectPosition(uint WorldID, uint id);
215 231
216[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 232[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
233public static extern Quaternion GetObjectOrientation(uint WorldID, uint id);
234
235[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
217public static extern bool SetObjectTranslation(uint worldID, uint id, Vector3 position, Quaternion rotation); 236public static extern bool SetObjectTranslation(uint worldID, uint id, Vector3 position, Quaternion rotation);
218 237
219[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 238[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@@ -268,5 +287,37 @@ public static extern void DumpBulletStatistics();
268public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg); 287public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg);
269[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 288[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
270public static extern void SetDebugLogCallback(DebugLogCallback callback); 289public static extern void SetDebugLogCallback(DebugLogCallback callback);
290
291// ===============================================================================
292// ===============================================================================
293// ===============================================================================
294// A new version of the API that moves all the logic out of the C++ code and into
295// the C# code. This will make modifications easier for the next person.
296// This interface passes the actual pointers to the objects in the unmanaged
297// address space. All the management (calls for creation/destruction/lookup)
298// is done in the C# code.
299// The names have a 2 tacked on. This will be removed as the code gets rebuilt
300// and the old code is removed from the C# code.
301[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
302public static extern IntPtr GetSimHandle2(uint worldID);
303
304[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
305public static extern IntPtr GetBodyHandleWorldID2(uint worldID, uint id);
306
307[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
308public static extern IntPtr GetBodyHandle2(IntPtr sim, uint id);
309
310[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
311public static extern IntPtr ClearForces2(IntPtr obj);
312
313[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
314public static extern IntPtr SetCollisionFlags2(IntPtr obj, uint flags);
315
316[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
317public static extern IntPtr AddToCollisionFlags2(IntPtr obj, uint flags);
318
319[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
320public static extern IntPtr RemoveFromCollisionFlags2(IntPtr obj, uint flags);
321
271} 322}
272} 323}