aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics
diff options
context:
space:
mode:
authorDiva Canto2012-12-04 08:08:58 -0800
committerDiva Canto2012-12-04 08:08:58 -0800
commita4821c5e01da394ba0968e6206a52f4db45cd7bd (patch)
tree68dae4719fe4100ce272ba7e9cd07018052c825b /OpenSim/Region/Physics
parentImprovement in HGInstantMessageService: account for the existence of an offli... (diff)
parentMerge branch 'master' of ssh://opensimulator.org/var/git/opensim (diff)
downloadopensim-SC_OLD-a4821c5e01da394ba0968e6206a52f4db45cd7bd.zip
opensim-SC_OLD-a4821c5e01da394ba0968e6206a52f4db45cd7bd.tar.gz
opensim-SC_OLD-a4821c5e01da394ba0968e6206a52f4db45cd7bd.tar.bz2
opensim-SC_OLD-a4821c5e01da394ba0968e6206a52f4db45cd7bd.tar.xz
Merge branch 'master' of ssh://opensimulator.org/var/git/opensim
Diffstat (limited to 'OpenSim/Region/Physics')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs6
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs522
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSMotors.cs63
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs40
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs34
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs7
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs12
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs37
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs12
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs71
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt117
-rw-r--r--OpenSim/Region/Physics/Manager/IMesher.cs1
-rw-r--r--OpenSim/Region/Physics/Manager/ZeroMesher.cs7
-rw-r--r--OpenSim/Region/Physics/Meshing/Meshmerizer.cs21
14 files changed, 647 insertions, 303 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index 4c195e1..21aa9be 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -165,8 +165,8 @@ public sealed class BSCharacter : BSPhysObject
165 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr); 165 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr);
166 166
167 // Do this after the object has been added to the world 167 // Do this after the object has been added to the world
168 BulletSimAPI.SetCollisionFilterMask2(PhysBody.ptr, 168 BulletSimAPI.SetCollisionGroupMask2(PhysBody.ptr,
169 (uint)CollisionFilterGroups.AvatarFilter, 169 (uint)CollisionFilterGroups.AvatarGroup,
170 (uint)CollisionFilterGroups.AvatarMask); 170 (uint)CollisionFilterGroups.AvatarMask);
171 } 171 }
172 172
@@ -307,7 +307,7 @@ public sealed class BSCharacter : BSPhysObject
307 } 307 }
308 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) 308 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
309 { 309 {
310 float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position); 310 float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(_position);
311 if (Position.Z < waterHeight) 311 if (Position.Z < waterHeight)
312 { 312 {
313 _position.Z = waterHeight; 313 _position.Z = waterHeight;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index 74eb9ab..be8a502 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -45,9 +45,7 @@ using System;
45using System.Collections.Generic; 45using System.Collections.Generic;
46using System.Reflection; 46using System.Reflection;
47using System.Runtime.InteropServices; 47using System.Runtime.InteropServices;
48using log4net;
49using OpenMetaverse; 48using OpenMetaverse;
50using OpenSim.Framework;
51using OpenSim.Region.Physics.Manager; 49using OpenSim.Region.Physics.Manager;
52 50
53namespace OpenSim.Region.Physics.BulletSPlugin 51namespace OpenSim.Region.Physics.BulletSPlugin
@@ -100,7 +98,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
100 private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate 98 private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate
101 private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate 99 private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate
102 private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate 100 private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate
103 private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body 101 private Vector3 m_lastAngularCorrection = Vector3.Zero;
104 private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body 102 private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body
105 103
106 //Deflection properties 104 //Deflection properties
@@ -113,6 +111,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
113 private float m_bankingEfficiency = 0; 111 private float m_bankingEfficiency = 0;
114 private float m_bankingMix = 0; 112 private float m_bankingMix = 0;
115 private float m_bankingTimescale = 0; 113 private float m_bankingTimescale = 0;
114 private Vector3 m_lastBanking = Vector3.Zero;
116 115
117 //Hover and Buoyancy properties 116 //Hover and Buoyancy properties
118 private float m_VhoverHeight = 0f; 117 private float m_VhoverHeight = 0f;
@@ -127,7 +126,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
127 //Attractor properties 126 //Attractor properties
128 private BSVMotor m_verticalAttractionMotor = new BSVMotor("VerticalAttraction"); 127 private BSVMotor m_verticalAttractionMotor = new BSVMotor("VerticalAttraction");
129 private float m_verticalAttractionEfficiency = 1.0f; // damped 128 private float m_verticalAttractionEfficiency = 1.0f; // damped
130 private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor. 129 private float m_verticalAttractionTimescale = 600f; // Timescale > 500 means no vert attractor.
131 130
132 public BSDynamics(BSScene myScene, BSPrim myPrim) 131 public BSDynamics(BSScene myScene, BSPrim myPrim)
133 { 132 {
@@ -154,7 +153,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
154 m_angularDeflectionTimescale = Math.Max(pValue, 0.01f); 153 m_angularDeflectionTimescale = Math.Max(pValue, 0.01f);
155 break; 154 break;
156 case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE: 155 case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
157 m_angularMotorDecayTimescale = Math.Max(0.01f, Math.Min(pValue,120)); 156 m_angularMotorDecayTimescale = ClampInRange(0.01f, pValue, 120);
158 m_angularMotor.TargetValueDecayTimeScale = m_angularMotorDecayTimescale; 157 m_angularMotor.TargetValueDecayTimeScale = m_angularMotorDecayTimescale;
159 break; 158 break;
160 case Vehicle.ANGULAR_MOTOR_TIMESCALE: 159 case Vehicle.ANGULAR_MOTOR_TIMESCALE:
@@ -162,7 +161,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
162 m_angularMotor.TimeScale = m_angularMotorTimescale; 161 m_angularMotor.TimeScale = m_angularMotorTimescale;
163 break; 162 break;
164 case Vehicle.BANKING_EFFICIENCY: 163 case Vehicle.BANKING_EFFICIENCY:
165 m_bankingEfficiency = Math.Max(-1f, Math.Min(pValue, 1f)); 164 m_bankingEfficiency = ClampInRange(-1f, pValue, 1f);
166 break; 165 break;
167 case Vehicle.BANKING_MIX: 166 case Vehicle.BANKING_MIX:
168 m_bankingMix = Math.Max(pValue, 0.01f); 167 m_bankingMix = Math.Max(pValue, 0.01f);
@@ -171,10 +170,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
171 m_bankingTimescale = Math.Max(pValue, 0.01f); 170 m_bankingTimescale = Math.Max(pValue, 0.01f);
172 break; 171 break;
173 case Vehicle.BUOYANCY: 172 case Vehicle.BUOYANCY:
174 m_VehicleBuoyancy = Math.Max(-1f, Math.Min(pValue, 1f)); 173 m_VehicleBuoyancy = ClampInRange(-1f, pValue, 1f);
175 break; 174 break;
176 case Vehicle.HOVER_EFFICIENCY: 175 case Vehicle.HOVER_EFFICIENCY:
177 m_VhoverEfficiency = Math.Max(0f, Math.Min(pValue, 1f)); 176 m_VhoverEfficiency = ClampInRange(0f, pValue, 1f);
178 break; 177 break;
179 case Vehicle.HOVER_HEIGHT: 178 case Vehicle.HOVER_HEIGHT:
180 m_VhoverHeight = pValue; 179 m_VhoverHeight = pValue;
@@ -189,7 +188,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
189 m_linearDeflectionTimescale = Math.Max(pValue, 0.01f); 188 m_linearDeflectionTimescale = Math.Max(pValue, 0.01f);
190 break; 189 break;
191 case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE: 190 case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
192 m_linearMotorDecayTimescale = Math.Max(0.01f, Math.Min(pValue,120)); 191 m_linearMotorDecayTimescale = ClampInRange(0.01f, pValue, 120);
193 m_linearMotor.TargetValueDecayTimeScale = m_linearMotorDecayTimescale; 192 m_linearMotor.TargetValueDecayTimeScale = m_linearMotorDecayTimescale;
194 break; 193 break;
195 case Vehicle.LINEAR_MOTOR_TIMESCALE: 194 case Vehicle.LINEAR_MOTOR_TIMESCALE:
@@ -197,7 +196,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
197 m_linearMotor.TimeScale = m_linearMotorTimescale; 196 m_linearMotor.TimeScale = m_linearMotorTimescale;
198 break; 197 break;
199 case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY: 198 case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
200 m_verticalAttractionEfficiency = Math.Max(0.1f, Math.Min(pValue, 1f)); 199 m_verticalAttractionEfficiency = ClampInRange(0.1f, pValue, 1f);
201 m_verticalAttractionMotor.Efficiency = m_verticalAttractionEfficiency; 200 m_verticalAttractionMotor.Efficiency = m_verticalAttractionEfficiency;
202 break; 201 break;
203 case Vehicle.VERTICAL_ATTRACTION_TIMESCALE: 202 case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
@@ -242,9 +241,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
242 break; 241 break;
243 case Vehicle.ANGULAR_MOTOR_DIRECTION: 242 case Vehicle.ANGULAR_MOTOR_DIRECTION:
244 // Limit requested angular speed to 2 rps= 4 pi rads/sec 243 // Limit requested angular speed to 2 rps= 4 pi rads/sec
245 pValue.X = Math.Max(-12.56f, Math.Min(pValue.X, 12.56f)); 244 pValue.X = ClampInRange(-12.56f, pValue.X, 12.56f);
246 pValue.Y = Math.Max(-12.56f, Math.Min(pValue.Y, 12.56f)); 245 pValue.Y = ClampInRange(-12.56f, pValue.Y, 12.56f);
247 pValue.Z = Math.Max(-12.56f, Math.Min(pValue.Z, 12.56f)); 246 pValue.Z = ClampInRange(-12.56f, pValue.Z, 12.56f);
248 m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); 247 m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
249 m_angularMotor.SetTarget(m_angularMotorDirection); 248 m_angularMotor.SetTarget(m_angularMotorDirection);
250 break; 249 break;
@@ -330,6 +329,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
330 m_bankingEfficiency = 0; 329 m_bankingEfficiency = 0;
331 m_bankingTimescale = 1000; 330 m_bankingTimescale = 1000;
332 m_bankingMix = 1; 331 m_bankingMix = 1;
332 m_lastBanking = Vector3.Zero;
333 333
334 m_referenceFrame = Quaternion.Identity; 334 m_referenceFrame = Quaternion.Identity;
335 m_flags = (VehicleFlag)0; 335 m_flags = (VehicleFlag)0;
@@ -364,6 +364,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
364 m_bankingEfficiency = 0; 364 m_bankingEfficiency = 0;
365 m_bankingTimescale = 10; 365 m_bankingTimescale = 10;
366 m_bankingMix = 1; 366 m_bankingMix = 1;
367 m_lastBanking = Vector3.Zero;
367 368
368 m_referenceFrame = Quaternion.Identity; 369 m_referenceFrame = Quaternion.Identity;
369 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY 370 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY
@@ -402,6 +403,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
402 m_bankingEfficiency = -0.2f; 403 m_bankingEfficiency = -0.2f;
403 m_bankingMix = 1; 404 m_bankingMix = 1;
404 m_bankingTimescale = 1; 405 m_bankingTimescale = 1;
406 m_lastBanking = Vector3.Zero;
405 407
406 m_referenceFrame = Quaternion.Identity; 408 m_referenceFrame = Quaternion.Identity;
407 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY 409 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY
@@ -440,6 +442,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
440 m_bankingEfficiency = -0.3f; 442 m_bankingEfficiency = -0.3f;
441 m_bankingMix = 0.8f; 443 m_bankingMix = 0.8f;
442 m_bankingTimescale = 1; 444 m_bankingTimescale = 1;
445 m_lastBanking = Vector3.Zero;
443 446
444 m_referenceFrame = Quaternion.Identity; 447 m_referenceFrame = Quaternion.Identity;
445 m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY 448 m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY
@@ -478,6 +481,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
478 m_bankingEfficiency = 1; 481 m_bankingEfficiency = 1;
479 m_bankingMix = 0.7f; 482 m_bankingMix = 0.7f;
480 m_bankingTimescale = 2; 483 m_bankingTimescale = 2;
484 m_lastBanking = Vector3.Zero;
481 485
482 m_referenceFrame = Quaternion.Identity; 486 m_referenceFrame = Quaternion.Identity;
483 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY 487 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY
@@ -516,6 +520,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
516 m_bankingEfficiency = 0; 520 m_bankingEfficiency = 0;
517 m_bankingMix = 0.7f; 521 m_bankingMix = 0.7f;
518 m_bankingTimescale = 5; 522 m_bankingTimescale = 5;
523 m_lastBanking = Vector3.Zero;
524
519 m_referenceFrame = Quaternion.Identity; 525 m_referenceFrame = Quaternion.Identity;
520 526
521 m_referenceFrame = Quaternion.Identity; 527 m_referenceFrame = Quaternion.Identity;
@@ -558,9 +564,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
558 { 564 {
559 if (IsActive) 565 if (IsActive)
560 { 566 {
567 // Remember the mass so we don't have to fetch it every step
561 m_vehicleMass = Prim.Linkset.LinksetMass; 568 m_vehicleMass = Prim.Linkset.LinksetMass;
562 569
563 // Friction effects are handled by this vehicle code 570 // Friction affects are handled by this vehicle code
564 float friction = 0f; 571 float friction = 0f;
565 BulletSimAPI.SetFriction2(Prim.PhysBody.ptr, friction); 572 BulletSimAPI.SetFriction2(Prim.PhysBody.ptr, friction);
566 573
@@ -574,6 +581,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
574 // Vector3 localInertia = new Vector3(1f, 1f, 1f); 581 // Vector3 localInertia = new Vector3(1f, 1f, 1f);
575 Vector3 localInertia = new Vector3(m_vehicleMass, m_vehicleMass, m_vehicleMass); 582 Vector3 localInertia = new Vector3(m_vehicleMass, m_vehicleMass, m_vehicleMass);
576 BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia); 583 BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia);
584 BulletSimAPI.UpdateInertiaTensor2(Prim.PhysBody.ptr);
577 585
578 VDetailLog("{0},BSDynamics.Refresh,frict={1},inert={2},aDamp={3}", 586 VDetailLog("{0},BSDynamics.Refresh,frict={1},inert={2},aDamp={3}",
579 Prim.LocalID, friction, localInertia, angularDamping); 587 Prim.LocalID, friction, localInertia, angularDamping);
@@ -598,31 +606,167 @@ namespace OpenSim.Region.Physics.BulletSPlugin
598 Refresh(); 606 Refresh();
599 } 607 }
600 608
609 #region Known vehicle value functions
610 // Vehicle physical parameters that we buffer from constant getting and setting.
611 // The "m_known*" variables are initialized to 'null', fetched only if referenced
612 // and stored back into the physics engine only if updated.
613 // This does two things: 1) saves continuious calls into unmanaged code, and
614 // 2) signals when a physics property update must happen back to the simulator
615 // to update values modified for the vehicle.
616 private int m_knownChanged;
617 private float? m_knownTerrainHeight;
618 private float? m_knownWaterLevel;
619 private Vector3? m_knownPosition;
620 private Vector3? m_knownVelocity;
621 private Quaternion? m_knownOrientation;
622 private Vector3? m_knownRotationalVelocity;
623
624 private const int m_knownChangedPosition = 1 << 0;
625 private const int m_knownChangedVelocity = 1 << 1;
626 private const int m_knownChangedOrientation = 1 << 2;
627 private const int m_knownChangedRotationalVelocity = 1 << 3;
628
629 private void ForgetKnownVehicleProperties()
630 {
631 m_knownTerrainHeight = null;
632 m_knownWaterLevel = null;
633 m_knownPosition = null;
634 m_knownVelocity = null;
635 m_knownOrientation = null;
636 m_knownRotationalVelocity = null;
637 m_knownChanged = 0;
638 }
639 private void PushKnownChanged()
640 {
641 if (m_knownChanged != 0)
642 {
643 if ((m_knownChanged & m_knownChangedPosition) != 0)
644 Prim.ForcePosition = VehiclePosition;
645 if ((m_knownChanged & m_knownChangedOrientation) != 0)
646 Prim.ForceOrientation = VehicleOrientation;
647 if ((m_knownChanged & m_knownChangedVelocity) != 0)
648 Prim.ForceVelocity = VehicleVelocity;
649 if ((m_knownChanged & m_knownChangedRotationalVelocity) != 0)
650 {
651 Prim.ForceRotationalVelocity = VehicleRotationalVelocity;
652 BulletSimAPI.SetInterpolationAngularVelocity2(Prim.PhysBody.ptr, VehicleRotationalVelocity);
653 }
654 // If we set one of the values (ie, the physics engine didn't do it) we must force
655 // an UpdateProperties event to send the changes up to the simulator.
656 BulletSimAPI.PushUpdate2(Prim.PhysBody.ptr);
657 }
658 }
659
660 // Since the computation of terrain height can be a little involved, this routine
661 // is used ot fetch the height only once for each vehicle simulation step.
662 private float GetTerrainHeight(Vector3 pos)
663 {
664 if (m_knownTerrainHeight == null)
665 m_knownTerrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos);
666 return (float)m_knownTerrainHeight;
667 }
668
669 // Since the computation of water level can be a little involved, this routine
670 // is used ot fetch the level only once for each vehicle simulation step.
671 private float GetWaterLevel(Vector3 pos)
672 {
673 if (m_knownWaterLevel == null)
674 m_knownWaterLevel = Prim.PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(pos);
675 return (float)m_knownWaterLevel;
676 }
677
678 private Vector3 VehiclePosition
679 {
680 get
681 {
682 if (m_knownPosition == null)
683 m_knownPosition = Prim.ForcePosition;
684 return (Vector3)m_knownPosition;
685 }
686 set
687 {
688 m_knownPosition = value;
689 m_knownChanged |= m_knownChangedPosition;
690 }
691 }
692
693 private Quaternion VehicleOrientation
694 {
695 get
696 {
697 if (m_knownOrientation == null)
698 m_knownOrientation = Prim.ForceOrientation;
699 return (Quaternion)m_knownOrientation;
700 }
701 set
702 {
703 m_knownOrientation = value;
704 m_knownChanged |= m_knownChangedOrientation;
705 }
706 }
707
708 private Vector3 VehicleVelocity
709 {
710 get
711 {
712 if (m_knownVelocity == null)
713 m_knownVelocity = Prim.ForceVelocity;
714 return (Vector3)m_knownVelocity;
715 }
716 set
717 {
718 m_knownVelocity = value;
719 m_knownChanged |= m_knownChangedVelocity;
720 }
721 }
722
723 private Vector3 VehicleRotationalVelocity
724 {
725 get
726 {
727 if (m_knownRotationalVelocity == null)
728 m_knownRotationalVelocity = Prim.ForceRotationalVelocity;
729 return (Vector3)m_knownRotationalVelocity;
730 }
731 set
732 {
733 m_knownRotationalVelocity = value;
734 m_knownChanged |= m_knownChangedRotationalVelocity;
735 }
736 }
737 #endregion // Known vehicle value functions
738
601 // One step of the vehicle properties for the next 'pTimestep' seconds. 739 // One step of the vehicle properties for the next 'pTimestep' seconds.
602 internal void Step(float pTimestep) 740 internal void Step(float pTimestep)
603 { 741 {
604 if (!IsActive) return; 742 if (!IsActive) return;
605 743
744 ForgetKnownVehicleProperties();
745
606 MoveLinear(pTimestep); 746 MoveLinear(pTimestep);
607 MoveAngular(pTimestep); 747 MoveAngular(pTimestep);
608 748
609 LimitRotation(pTimestep); 749 LimitRotation(pTimestep);
610 750
611 // remember the position so next step we can limit absolute movement effects 751 // remember the position so next step we can limit absolute movement effects
612 m_lastPositionVector = Prim.ForcePosition; 752 m_lastPositionVector = VehiclePosition;
753
754 // If we forced the changing of some vehicle parameters, update the values and
755 // for the physics engine to note the changes so an UpdateProperties event will happen.
756 PushKnownChanged();
613 757
614 VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", 758 VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}",
615 Prim.LocalID, Prim.ForcePosition, Prim.Force, Prim.ForceVelocity, Prim.RotationalVelocity); 759 Prim.LocalID, VehiclePosition, Prim.Force, VehicleVelocity, VehicleRotationalVelocity);
616 } 760 }
617 761
618 // Apply the effect of the linear motor. 762 // Apply the effect of the linear motor and other linear motions (like hover and float).
619 // Also does hover and float.
620 private void MoveLinear(float pTimestep) 763 private void MoveLinear(float pTimestep)
621 { 764 {
622 Vector3 linearMotorContribution = m_linearMotor.Step(pTimestep); 765 Vector3 linearMotorContribution = m_linearMotor.Step(pTimestep);
623 766
624 // Rotate new object velocity from vehicle relative to world coordinates 767 // The movement computed in the linear motor is relative to the vehicle
625 linearMotorContribution *= Prim.ForceOrientation; 768 // coordinates. Rotate the movement to world coordinates.
769 linearMotorContribution *= VehicleOrientation;
626 770
627 // ================================================================== 771 // ==================================================================
628 // Gravity and Buoyancy 772 // Gravity and Buoyancy
@@ -630,16 +774,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
630 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; 774 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
631 Vector3 grav = Prim.PhysicsScene.DefaultGravity * (1f - m_VehicleBuoyancy); 775 Vector3 grav = Prim.PhysicsScene.DefaultGravity * (1f - m_VehicleBuoyancy);
632 776
633 Vector3 pos = Prim.ForcePosition; 777 Vector3 terrainHeightContribution = ComputeLinearTerrainHeightCorrection(pTimestep);
634 float terrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos);
635 778
636 Vector3 terrainHeightContribution = ComputeLinearTerrainHeightCorrection(pTimestep, ref pos, terrainHeight); 779 Vector3 hoverContribution = ComputeLinearHover(pTimestep);
637 780
638 Vector3 hoverContribution = ComputeLinearHover(pTimestep, ref pos, terrainHeight); 781 ComputeLinearBlockingEndPoint(pTimestep);
639 782
640 ComputeLinearBlockingEndPoint(pTimestep, ref pos); 783 Vector3 limitMotorUpContribution = ComputeLinearMotorUp(pTimestep);
641
642 Vector3 limitMotorUpContribution = ComputeLinearMotorUp(pTimestep, pos, terrainHeight);
643 784
644 // ================================================================== 785 // ==================================================================
645 Vector3 newVelocity = linearMotorContribution 786 Vector3 newVelocity = linearMotorContribution
@@ -667,42 +808,39 @@ namespace OpenSim.Region.Physics.BulletSPlugin
667 newVelocity = Vector3.Zero; 808 newVelocity = Vector3.Zero;
668 809
669 // ================================================================== 810 // ==================================================================
670 // Stuff new linear velocity into the vehicle 811 // Stuff new linear velocity into the vehicle.
671 Prim.ForceVelocity = newVelocity; 812 // Since the velocity is just being set, it is not scaled by pTimeStep. Bullet will do that for us.
672 // Prim.ApplyForceImpulse((m_newVelocity - Prim.Velocity) * m_vehicleMass, false); // DEBUG DEBUG 813 VehicleVelocity = newVelocity;
673 814
674 // Other linear forces are applied as forces. 815 // Other linear forces are applied as forces.
675 Vector3 totalDownForce = grav * m_vehicleMass; 816 Vector3 totalDownForce = grav * m_vehicleMass * pTimestep;
676 if (totalDownForce != Vector3.Zero) 817 if (totalDownForce != Vector3.Zero)
677 { 818 {
678 Prim.AddForce(totalDownForce, false); 819 Prim.AddForce(totalDownForce, false);
679 } 820 }
680 821
681 VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},primVel={4},totalDown={5}", 822 VDetailLog("{0}, MoveLinear,done,newVel={1},totDown={2},linContrib={3},terrContrib={4},hoverContrib={5},limitContrib={6}",
682 Prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector, 823 Prim.LocalID, newVelocity, totalDownForce,
683 newVelocity, Prim.Velocity, totalDownForce); 824 linearMotorContribution, terrainHeightContribution, hoverContribution, limitMotorUpContribution
825 );
684 826
685 } // end MoveLinear() 827 } // end MoveLinear()
686 828
687 public Vector3 ComputeLinearTerrainHeightCorrection(float pTimestep, ref Vector3 pos, float terrainHeight) 829 public Vector3 ComputeLinearTerrainHeightCorrection(float pTimestep)
688 { 830 {
689 Vector3 ret = Vector3.Zero; 831 Vector3 ret = Vector3.Zero;
690 // If below the terrain, move us above the ground a little. 832 // If below the terrain, move us above the ground a little.
691 // Taking the rotated size doesn't work here because m_prim.Size is the size of the root prim and not the linkset. 833 // TODO: Consider taking the rotated size of the object or possibly casting a ray.
692 // TODO: Add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass. 834 if (VehiclePosition.Z < GetTerrainHeight(VehiclePosition))
693 // Vector3 rotatedSize = m_prim.Size * m_prim.ForceOrientation;
694 // if (rotatedSize.Z < terrainHeight)
695 if (pos.Z < terrainHeight)
696 { 835 {
697 // TODO: correct position by applying force rather than forcing position. 836 // TODO: correct position by applying force rather than forcing position.
698 pos.Z = terrainHeight + 2; 837 VehiclePosition += new Vector3(0f, 0f, GetTerrainHeight(VehiclePosition) + 2f);
699 Prim.ForcePosition = pos; 838 VDetailLog("{0}, MoveLinear,terrainHeight,terrainHeight={1},pos={2}", Prim.LocalID, GetTerrainHeight(VehiclePosition), VehiclePosition);
700 VDetailLog("{0},MoveLinear,terrainHeight,terrainHeight={1},pos={2}", Prim.LocalID, terrainHeight, pos);
701 } 839 }
702 return ret; 840 return ret;
703 } 841 }
704 842
705 public Vector3 ComputeLinearHover(float pTimestep, ref Vector3 pos, float terrainHeight) 843 public Vector3 ComputeLinearHover(float pTimestep)
706 { 844 {
707 Vector3 ret = Vector3.Zero; 845 Vector3 ret = Vector3.Zero;
708 846
@@ -713,11 +851,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
713 // We should hover, get the target height 851 // We should hover, get the target height
714 if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0) 852 if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0)
715 { 853 {
716 m_VhoverTargetHeight = Prim.PhysicsScene.GetWaterLevelAtXYZ(pos) + m_VhoverHeight; 854 m_VhoverTargetHeight = GetWaterLevel(VehiclePosition) + m_VhoverHeight;
717 } 855 }
718 if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) 856 if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
719 { 857 {
720 m_VhoverTargetHeight = terrainHeight + m_VhoverHeight; 858 m_VhoverTargetHeight = GetTerrainHeight(VehiclePosition) + m_VhoverHeight;
721 } 859 }
722 if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0) 860 if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0)
723 { 861 {
@@ -727,45 +865,44 @@ namespace OpenSim.Region.Physics.BulletSPlugin
727 if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0) 865 if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0)
728 { 866 {
729 // If body is already heigher, use its height as target height 867 // If body is already heigher, use its height as target height
730 if (pos.Z > m_VhoverTargetHeight) 868 if (VehiclePosition.Z > m_VhoverTargetHeight)
731 m_VhoverTargetHeight = pos.Z; 869 m_VhoverTargetHeight = VehiclePosition.Z;
732 } 870 }
871
733 if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) 872 if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0)
734 { 873 {
735 if (Math.Abs(pos.Z - m_VhoverTargetHeight) > 0.2f) 874 if (Math.Abs(VehiclePosition.Z - m_VhoverTargetHeight) > 0.2f)
736 { 875 {
876 Vector3 pos = VehiclePosition;
737 pos.Z = m_VhoverTargetHeight; 877 pos.Z = m_VhoverTargetHeight;
738 Prim.ForcePosition = pos; 878 VehiclePosition = pos;
739 } 879 }
740 } 880 }
741 else 881 else
742 { 882 {
743 float verticalError = pos.Z - m_VhoverTargetHeight; 883 // Error is positive if below the target and negative if above.
744 // RA: where does the 50 come from? 884 float verticalError = m_VhoverTargetHeight - VehiclePosition.Z;
745 float verticalCorrectionVelocity = pTimestep * ((verticalError * 50.0f) / m_VhoverTimescale); 885 float verticalCorrectionVelocity = verticalError / m_VhoverTimescale;
746 // Replace Vertical speed with correction figure if significant 886
747 if (verticalError > 0.01f) 887 // TODO: implement m_VhoverEfficiency correctly
888 if (Math.Abs(verticalError) > m_VhoverEfficiency)
748 { 889 {
749 ret = new Vector3(0f, 0f, verticalCorrectionVelocity); 890 ret = new Vector3(0f, 0f, verticalCorrectionVelocity);
750 //KF: m_VhoverEfficiency is not yet implemented
751 }
752 else if (verticalError < -0.01)
753 {
754 ret = new Vector3(0f, 0f, -verticalCorrectionVelocity);
755 } 891 }
756 } 892 }
757 893
758 VDetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", 894 VDetailLog("{0}, MoveLinear,hover,pos={1},ret={2},hoverTS={3},height={4},target={5}",
759 Prim.LocalID, pos, ret, m_VhoverHeight, m_VhoverTargetHeight); 895 Prim.LocalID, VehiclePosition, ret, m_VhoverTimescale, m_VhoverHeight, m_VhoverTargetHeight);
760 } 896 }
761 897
762 return ret; 898 return ret;
763 } 899 }
764 900
765 public bool ComputeLinearBlockingEndPoint(float pTimestep, ref Vector3 pos) 901 public bool ComputeLinearBlockingEndPoint(float pTimestep)
766 { 902 {
767 bool changed = false; 903 bool changed = false;
768 904
905 Vector3 pos = VehiclePosition;
769 Vector3 posChange = pos - m_lastPositionVector; 906 Vector3 posChange = pos - m_lastPositionVector;
770 if (m_BlockingEndPoint != Vector3.Zero) 907 if (m_BlockingEndPoint != Vector3.Zero)
771 { 908 {
@@ -796,32 +933,41 @@ namespace OpenSim.Region.Physics.BulletSPlugin
796 } 933 }
797 if (changed) 934 if (changed)
798 { 935 {
799 Prim.ForcePosition = pos; 936 VehiclePosition = pos;
800 VDetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", 937 VDetailLog("{0}, MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}",
801 Prim.LocalID, m_BlockingEndPoint, posChange, pos); 938 Prim.LocalID, m_BlockingEndPoint, posChange, pos);
802 } 939 }
803 } 940 }
804 return changed; 941 return changed;
805 } 942 }
806 943
807 public Vector3 ComputeLinearMotorUp(float pTimestep, Vector3 pos, float terrainHeight) 944 // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags :
945 // Prevent ground vehicles from motoring into the sky.This flag has a subtle effect when
946 // used with conjunction with banking: the strength of the banking will decay when the
947 // vehicle no longer experiences collisions. The decay timescale is the same as
948 // VEHICLE_BANKING_TIMESCALE. This is to help prevent ground vehicles from steering
949 // when they are in mid jump.
950 // TODO: this code is wrong. Also, what should it do for boats?
951 public Vector3 ComputeLinearMotorUp(float pTimestep)
808 { 952 {
809 Vector3 ret = Vector3.Zero; 953 Vector3 ret = Vector3.Zero;
810 if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) 954 if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0)
811 { 955 {
812 // If the vehicle is motoring into the sky, get it going back down. 956 // If the vehicle is motoring into the sky, get it going back down.
813 float distanceAboveGround = pos.Z - terrainHeight; 957 // float distanceAboveGround = pos.Z - Math.Max(GetTerrainHeight(pos), GetWaterLevel(pos));
958 float distanceAboveGround = VehiclePosition.Z - GetTerrainHeight(VehiclePosition);
814 if (distanceAboveGround > 1f) 959 if (distanceAboveGround > 1f)
815 { 960 {
816 // downForce = new Vector3(0, 0, (-distanceAboveGround / m_bankingTimescale) * pTimestep); 961 // downForce = new Vector3(0, 0, (-distanceAboveGround / m_bankingTimescale) * pTimestep);
817 // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale); 962 // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale);
818 ret = new Vector3(0, 0, -distanceAboveGround); 963 ret = new Vector3(0, 0, -distanceAboveGround);
819 } 964 }
820 // TODO: this calculation is all wrong. From the description at 965 // TODO: this calculation is wrong. From the description at
821 // (http://wiki.secondlife.com/wiki/Category:LSL_Vehicle), the downForce 966 // (http://wiki.secondlife.com/wiki/Category:LSL_Vehicle), the downForce
822 // has a decay factor. This says this force should 967 // has a decay factor. This says this force should
823 // be computed with a motor. 968 // be computed with a motor.
824 VDetailLog("{0},MoveLinear,limitMotorUp,distAbove={1},downForce={2}", 969 // TODO: add interaction with banking.
970 VDetailLog("{0}, MoveLinear,limitMotorUp,distAbove={1},downForce={2}",
825 Prim.LocalID, distanceAboveGround, ret); 971 Prim.LocalID, distanceAboveGround, ret);
826 } 972 }
827 return ret; 973 return ret;
@@ -830,61 +976,63 @@ namespace OpenSim.Region.Physics.BulletSPlugin
830 // ======================================================================= 976 // =======================================================================
831 // ======================================================================= 977 // =======================================================================
832 // Apply the effect of the angular motor. 978 // Apply the effect of the angular motor.
979 // The 'contribution' is how much angular correction velocity each function wants.
980 // All the contributions are added together and the orientation of the vehicle
981 // is changed by all the contributed corrections.
833 private void MoveAngular(float pTimestep) 982 private void MoveAngular(float pTimestep)
834 { 983 {
835 // m_angularMotorDirection // angular velocity requested by LSL motor 984 // The user wants how many radians per second angular change?
836 // m_angularMotorVelocity // current angular motor velocity (ramps up and down)
837 // m_angularMotorTimescale // motor angular velocity ramp up time
838 // m_angularMotorDecayTimescale // motor angular velocity decay rate
839 // m_angularFrictionTimescale // body angular velocity decay rate
840 // m_lastAngularVelocity // what was last applied to body
841
842 /*
843 if (m_angularMotorDirection.LengthSquared() > 0.0001)
844 {
845 Vector3 origVel = m_angularMotorVelocity;
846 Vector3 origDir = m_angularMotorDirection;
847
848 // new velocity += error / ( time to get there / step interval)
849 // requested direction - current vehicle direction
850 m_angularMotorVelocity += (m_angularMotorDirection - m_angularMotorVelocity) / (m_angularMotorTimescale / pTimestep);
851 // decay requested direction
852 m_angularMotorDirection *= (1.0f - (pTimestep * 1.0f/m_angularMotorDecayTimescale));
853
854 VDetailLog("{0},MoveAngular,angularMotorApply,angTScale={1},timeStep={2},origvel={3},origDir={4},vel={5}",
855 Prim.LocalID, m_angularMotorTimescale, pTimestep, origVel, origDir, m_angularMotorVelocity);
856 }
857 else
858 {
859 m_angularMotorVelocity = Vector3.Zero;
860 }
861 */
862
863 Vector3 angularMotorContribution = m_angularMotor.Step(pTimestep); 985 Vector3 angularMotorContribution = m_angularMotor.Step(pTimestep);
864 986
865 // ================================================================== 987 // ==================================================================
866 // NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement 988 // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags :
989 // This flag prevents linear deflection parallel to world z-axis. This is useful
990 // for preventing ground vehicles with large linear deflection, like bumper cars,
991 // from climbing their linear deflection into the sky.
992 // That is, NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement
867 if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) 993 if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0)
868 { 994 {
869 angularMotorContribution.X = 0f; 995 angularMotorContribution.X = 0f;
870 angularMotorContribution.Y = 0f; 996 angularMotorContribution.Y = 0f;
871 VDetailLog("{0},MoveAngular,noDeflectionUp,angularMotorContrib={1}", Prim.LocalID, angularMotorContribution); 997 VDetailLog("{0}, MoveAngular,noDeflectionUp,angularMotorContrib={1}", Prim.LocalID, angularMotorContribution);
872 } 998 }
873 999
874 Vector3 verticalAttractionContribution = ComputeAngularVerticalAttraction(pTimestep); 1000 Vector3 verticalAttractionContribution = ComputeAngularVerticalAttraction();
875 1001
876 Vector3 deflectionContribution = ComputeAngularDeflection(pTimestep); 1002 Vector3 deflectionContribution = ComputeAngularDeflection();
877 1003
878 Vector3 bankingContribution = ComputeAngularBanking(pTimestep); 1004 Vector3 bankingContribution = ComputeAngularBanking(angularMotorContribution.Z);
879 1005
880 // ================================================================== 1006 // ==================================================================
881 m_lastVertAttractor = verticalAttractionContribution; 1007 m_lastVertAttractor = verticalAttractionContribution;
882 1008
883 // Sum velocities 1009 // Sum corrections
884 m_lastAngularVelocity = angularMotorContribution 1010 m_lastAngularCorrection = angularMotorContribution
885 + verticalAttractionContribution 1011 + verticalAttractionContribution
886 + bankingContribution 1012 + deflectionContribution
887 + deflectionContribution; 1013 + bankingContribution;
1014
1015 // ==================================================================
1016 // The correction is applied to the current orientation.
1017 if (!m_lastAngularCorrection.ApproxEquals(Vector3.Zero, 0.01f))
1018 {
1019 Vector3 scaledCorrection = m_lastAngularCorrection * pTimestep;
1020
1021 VehicleRotationalVelocity = scaledCorrection;
1022
1023 VDetailLog("{0}, MoveAngular,done,nonZero,angMotorContrib={1},vertAttrContrib={2},bankContrib={3},deflectContrib={4},totalContrib={5},scaledCorr={6}",
1024 Prim.LocalID,
1025 angularMotorContribution, verticalAttractionContribution,
1026 bankingContribution, deflectionContribution,
1027 m_lastAngularCorrection, scaledCorrection
1028 );
1029 }
1030 else
1031 {
1032 // The vehicle is not adding anything velocity wise.
1033 VehicleRotationalVelocity = Vector3.Zero;
1034 VDetailLog("{0}, MoveAngular,done,zero", Prim.LocalID);
1035 }
888 1036
889 // ================================================================== 1037 // ==================================================================
890 //Offset section 1038 //Offset section
@@ -914,52 +1062,20 @@ namespace OpenSim.Region.Physics.BulletSPlugin
914 torqueFromOffset.Z = 0; 1062 torqueFromOffset.Z = 0;
915 torqueFromOffset *= m_vehicleMass; 1063 torqueFromOffset *= m_vehicleMass;
916 Prim.ApplyTorqueImpulse(torqueFromOffset, true); 1064 Prim.ApplyTorqueImpulse(torqueFromOffset, true);
917 VDetailLog("{0},BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", Prim.LocalID, torqueFromOffset); 1065 VDetailLog("{0}, BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", Prim.LocalID, torqueFromOffset);
918 } 1066 }
919 1067
920 // ==================================================================
921 if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f))
922 {
923 m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero.
924 Prim.ZeroAngularMotion(true);
925 VDetailLog("{0},MoveAngular,zeroAngularMotion,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity);
926 }
927 else
928 {
929 // Apply to the body.
930 // The above calculates the absolute angular velocity needed. Angular velocity is massless.
931 // Since we are stuffing the angular velocity directly into the object, the computed
932 // velocity needs to be scaled by the timestep.
933 // Also remove any motion that is on the object so added motion is only from vehicle.
934 Vector3 applyAngularForce = ((m_lastAngularVelocity * pTimestep)
935 - Prim.ForceRotationalVelocity);
936 // Unscale the force by the angular factor so it overwhelmes the Bullet additions.
937 Prim.ForceRotationalVelocity = applyAngularForce;
938
939 VDetailLog("{0},MoveAngular,done,angMotor={1},vertAttr={2},bank={3},deflect={4},newAngForce={5},lastAngular={6}",
940 Prim.LocalID,
941 angularMotorContribution, verticalAttractionContribution,
942 bankingContribution, deflectionContribution,
943 applyAngularForce, m_lastAngularVelocity
944 );
945 }
946 } 1068 }
947 1069
948 public Vector3 ComputeAngularVerticalAttraction(float pTimestep) 1070 public Vector3 ComputeAngularVerticalAttraction()
949 { 1071 {
950 Vector3 ret = Vector3.Zero; 1072 Vector3 ret = Vector3.Zero;
951 1073
952 // If vertical attaction timescale is reasonable and we applied an angular force last time... 1074 // If vertical attaction timescale is reasonable and we applied an angular force last time...
953 if (m_verticalAttractionTimescale < 500) 1075 if (m_verticalAttractionTimescale < 500)
954 { 1076 {
955 Vector3 verticalError = Vector3.UnitZ * Prim.ForceOrientation;
956 verticalError.Normalize();
957 m_verticalAttractionMotor.SetCurrent(verticalError);
958 m_verticalAttractionMotor.SetTarget(Vector3.UnitZ);
959 ret = m_verticalAttractionMotor.Step(pTimestep);
960 /*
961 // Take a vector pointing up and convert it from world to vehicle relative coords. 1077 // Take a vector pointing up and convert it from world to vehicle relative coords.
962 Vector3 verticalError = Vector3.UnitZ * Prim.ForceOrientation; 1078 Vector3 verticalError = Vector3.UnitZ * VehicleOrientation;
963 verticalError.Normalize(); 1079 verticalError.Normalize();
964 1080
965 // If vertical attraction correction is needed, the vector that was pointing up (UnitZ) 1081 // If vertical attraction correction is needed, the vector that was pointing up (UnitZ)
@@ -977,63 +1093,70 @@ namespace OpenSim.Region.Physics.BulletSPlugin
977 } 1093 }
978 1094
979 // Y error means needed rotation around X axis and visa versa. 1095 // Y error means needed rotation around X axis and visa versa.
980 verticalAttractionContribution.X = verticalError.Y; 1096 ret.X = verticalError.Y;
981 verticalAttractionContribution.Y = - verticalError.X; 1097 ret.Y = - verticalError.X;
982 verticalAttractionContribution.Z = 0f; 1098 ret.Z = 0f;
983 1099
984 // scale by the time scale and timestep 1100 // scale by the time scale and timestep
985 Vector3 unscaledContrib = verticalAttractionContribution; 1101 Vector3 unscaledContrib = ret;
986 verticalAttractionContribution /= m_verticalAttractionTimescale; 1102 ret /= m_verticalAttractionTimescale;
987 verticalAttractionContribution *= pTimestep; 1103 // This returns the angular correction desired. Timestep is added later.
1104 // ret *= pTimestep;
988 1105
989 // apply efficiency 1106 // apply efficiency
990 Vector3 preEfficiencyContrib = verticalAttractionContribution; 1107 Vector3 preEfficiencyContrib = ret;
1108 // TODO: implement efficiency.
1109 // Effenciency squared seems to give a more realistic effect
991 float efficencySquared = m_verticalAttractionEfficiency * m_verticalAttractionEfficiency; 1110 float efficencySquared = m_verticalAttractionEfficiency * m_verticalAttractionEfficiency;
992 verticalAttractionContribution *= (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); 1111 // ret *= efficencySquared;
993 1112
994 VDetailLog("{0},MoveAngular,verticalAttraction,,verticalError={1},unscaled={2},preEff={3},eff={4},effSq={5},vertAttr={6}", 1113 VDetailLog("{0}, MoveAngular,verticalAttraction,,verticalError={1},unscaled={2},preEff={3},eff={4},effSq={5},vertAttr={6}",
995 Prim.LocalID, verticalError, unscaledContrib, preEfficiencyContrib, 1114 Prim.LocalID, verticalError, unscaledContrib, preEfficiencyContrib,
996 m_verticalAttractionEfficiency, efficencySquared, 1115 m_verticalAttractionEfficiency, efficencySquared,
997 verticalAttractionContribution); 1116 ret);
998 */
999
1000 } 1117 }
1001 return ret; 1118 return ret;
1002 } 1119 }
1003 1120
1004 public Vector3 ComputeAngularDeflection(float pTimestep) 1121 // Return the angular correction to correct the direction the vehicle is pointing to be
1122 // the direction is should want to be pointing.
1123 public Vector3 ComputeAngularDeflection()
1005 { 1124 {
1006 Vector3 ret = Vector3.Zero; 1125 Vector3 ret = Vector3.Zero;
1007 1126
1008 if (m_angularDeflectionEfficiency != 0) 1127 if (m_angularDeflectionEfficiency != 0)
1009 { 1128 {
1010 // Compute a scaled vector that points in the preferred axis (X direction) 1129 // Where the vehicle should want to point relative to the vehicle
1011 Vector3 scaledDefaultDirection = 1130 Vector3 preferredDirection = Vector3.UnitX * m_referenceFrame;
1012 new Vector3((pTimestep * 10 * (m_angularDeflectionEfficiency / m_angularDeflectionTimescale)), 0, 0);
1013 // Adding the current vehicle orientation and reference frame displaces the orientation to the frame.
1014 // Rotate the scaled default axix relative to the actual vehicle direction giving where it should point.
1015 Vector3 preferredAxisOfMotion = scaledDefaultDirection * Quaternion.Add(Prim.ForceOrientation, m_referenceFrame);
1016 1131
1017 // Scale by efficiency and timescale 1132 // Where the vehicle is pointing relative to the vehicle.
1018 ret = (preferredAxisOfMotion * (m_angularDeflectionEfficiency) / m_angularDeflectionTimescale) * pTimestep; 1133 Vector3 currentDirection = Vector3.UnitX * Quaternion.Add(VehicleOrientation, m_referenceFrame);
1019 1134
1020 VDetailLog("{0},MoveAngular,Deflection,perfAxis={1},deflection={2}", Prim.LocalID, preferredAxisOfMotion, ret); 1135 // Difference between where vehicle is pointing and where it should wish to point
1136 Vector3 directionCorrection = preferredDirection - currentDirection;
1021 1137
1022 // This deflection computation is not correct. 1138 // Scale the correction by recovery timescale and efficiency
1023 ret = Vector3.Zero; 1139 ret = directionCorrection * m_angularDeflectionEfficiency / m_angularDeflectionTimescale;
1140
1141 VDetailLog("{0}, MoveAngular,Deflection,perfDir={1},currentDir={2},dirCorrection={3},ret={4}",
1142 Prim.LocalID, preferredDirection, currentDirection, directionCorrection, ret);
1024 } 1143 }
1025 return ret; 1144 return ret;
1026 } 1145 }
1027 1146
1028 public Vector3 ComputeAngularBanking(float pTimestep) 1147 // Return an angular change to tip the vehicle (around X axis) when turning (turned around Z).
1148 // Remembers the last banking value calculated and returns the difference needed this tick.
1149 // TurningFactor is rate going left or right (pos=left, neg=right, scale=0..1).
1150 public Vector3 ComputeAngularBanking(float turningFactor)
1029 { 1151 {
1030 Vector3 ret = Vector3.Zero; 1152 Vector3 ret = Vector3.Zero;
1153 Vector3 computedBanking = Vector3.Zero;
1031 1154
1032 if (m_bankingEfficiency != 0) 1155 if (m_bankingEfficiency != 0)
1033 { 1156 {
1034 Vector3 dir = Vector3.One * Prim.ForceOrientation; 1157 Vector3 currentDirection = Vector3.UnitX * VehicleOrientation;
1158
1035 float mult = (m_bankingMix * m_bankingMix) * -1 * (m_bankingMix < 0 ? -1 : 1); 1159 float mult = (m_bankingMix * m_bankingMix) * -1 * (m_bankingMix < 0 ? -1 : 1);
1036 //Changes which way it banks in and out of turns
1037 1160
1038 //Use the square of the efficiency, as it looks much more how SL banking works 1161 //Use the square of the efficiency, as it looks much more how SL banking works
1039 float effSquared = (m_bankingEfficiency * m_bankingEfficiency); 1162 float effSquared = (m_bankingEfficiency * m_bankingEfficiency);
@@ -1041,58 +1164,34 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1041 effSquared *= -1; //Keep the negative! 1164 effSquared *= -1; //Keep the negative!
1042 1165
1043 float mix = Math.Abs(m_bankingMix); 1166 float mix = Math.Abs(m_bankingMix);
1044 if (m_angularMotorVelocity.X == 0) 1167 // TODO: Must include reference frame.
1045 { 1168 float forwardSpeed = VehicleVelocity.X;
1046 // The vehicle is stopped
1047 /*if (!parent.Orientation.ApproxEquals(this.m_referenceFrame, 0.25f))
1048 {
1049 Vector3 axisAngle;
1050 float angle;
1051 parent.Orientation.GetAxisAngle(out axisAngle, out angle);
1052 Vector3 rotatedVel = parent.Velocity * parent.Orientation;
1053 if ((rotatedVel.X < 0 && axisAngle.Y > 0) || (rotatedVel.X > 0 && axisAngle.Y < 0))
1054 m_angularMotorVelocity.X += (effSquared * (mult * mix)) * (1f) * 10;
1055 else
1056 m_angularMotorVelocity.X += (effSquared * (mult * mix)) * (-1f) * 10;
1057 }*/
1058 }
1059 else
1060 {
1061 ret.Z += (effSquared * (mult * mix)) * (m_angularMotorVelocity.X) * 4;
1062 }
1063 1169
1064 //If they are colliding, we probably shouldn't shove the prim around... probably 1170 if (!Prim.IsColliding && forwardSpeed > mix)
1065 if (!Prim.IsColliding && Math.Abs(m_angularMotorVelocity.X) > mix)
1066 { 1171 {
1067 float angVelZ = m_angularMotorVelocity.X * -1; 1172 computedBanking.X = ClampInRange(-3f, turningFactor * (effSquared * mult), 3f);
1068 /*if(angVelZ > mix)
1069 angVelZ = mix;
1070 else if(angVelZ < -mix)
1071 angVelZ = -mix;*/
1072 //This controls how fast and how far the banking occurs
1073 Vector3 bankingRot = new Vector3(angVelZ * (effSquared * mult), 0, 0);
1074 if (bankingRot.X > 3)
1075 bankingRot.X = 3;
1076 else if (bankingRot.X < -3)
1077 bankingRot.X = -3;
1078 bankingRot *= Prim.ForceOrientation;
1079 ret += bankingRot;
1080 } 1173 }
1081 m_angularMotorVelocity.X *= m_bankingEfficiency == 1 ? 0.0f : 1 - m_bankingEfficiency; 1174
1082 VDetailLog("{0},MoveAngular,Banking,bEff={1},angMotVel={2},effSq={3},mult={4},mix={5},banking={6}", 1175 // 'computedBanking' is now how much banking that should be happening.
1083 Prim.LocalID, m_bankingEfficiency, m_angularMotorVelocity, effSquared, mult, mix, ret); 1176 ret = computedBanking - m_lastBanking;
1177
1178 // Scale the correction by timescale and efficiency
1179 ret /= m_bankingTimescale * m_bankingEfficiency;
1180
1181 VDetailLog("{0}, MoveAngular,Banking,computedB={1},lastB={2},bEff={3},effSq={4},mult={5},mix={6},banking={7}",
1182 Prim.LocalID, computedBanking, m_lastBanking, m_bankingEfficiency, effSquared, mult, mix, ret);
1084 } 1183 }
1184 m_lastBanking = computedBanking;
1085 return ret; 1185 return ret;
1086 } 1186 }
1087 1187
1088
1089 // This is from previous instantiations of XXXDynamics.cs. 1188 // This is from previous instantiations of XXXDynamics.cs.
1090 // Applies roll reference frame. 1189 // Applies roll reference frame.
1091 // TODO: is this the right way to separate the code to do this operation? 1190 // TODO: is this the right way to separate the code to do this operation?
1092 // Should this be in MoveAngular()? 1191 // Should this be in MoveAngular()?
1093 internal void LimitRotation(float timestep) 1192 internal void LimitRotation(float timestep)
1094 { 1193 {
1095 Quaternion rotq = Prim.ForceOrientation; 1194 Quaternion rotq = VehicleOrientation;
1096 Quaternion m_rot = rotq; 1195 Quaternion m_rot = rotq;
1097 if (m_RollreferenceFrame != Quaternion.Identity) 1196 if (m_RollreferenceFrame != Quaternion.Identity)
1098 { 1197 {
@@ -1120,12 +1219,17 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1120 } 1219 }
1121 if (rotq != m_rot) 1220 if (rotq != m_rot)
1122 { 1221 {
1123 Prim.ForceOrientation = m_rot; 1222 VehicleOrientation = m_rot;
1124 VDetailLog("{0},LimitRotation,done,orig={1},new={2}", Prim.LocalID, rotq, m_rot); 1223 VDetailLog("{0}, LimitRotation,done,orig={1},new={2}", Prim.LocalID, rotq, m_rot);
1125 } 1224 }
1126 1225
1127 } 1226 }
1128 1227
1228 private float ClampInRange(float low, float val, float high)
1229 {
1230 return Math.Max(low, Math.Min(val, high));
1231 }
1232
1129 // Invoke the detailed logger and output something if it's enabled. 1233 // Invoke the detailed logger and output something if it's enabled.
1130 private void VDetailLog(string msg, params Object[] args) 1234 private void VDetailLog(string msg, params Object[] args)
1131 { 1235 {
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs b/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
index e91bfa8..851d508 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
@@ -1,3 +1,30 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 */
1using System; 28using System;
2using System.Collections.Generic; 29using System.Collections.Generic;
3using System.Text; 30using System.Text;
@@ -8,7 +35,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
8public abstract class BSMotor 35public abstract class BSMotor
9{ 36{
10 // Timescales and other things can be turned off by setting them to 'infinite'. 37 // Timescales and other things can be turned off by setting them to 'infinite'.
11 public const float Infinite = 10000f; 38 public const float Infinite = 12345f;
12 public readonly static Vector3 InfiniteVector = new Vector3(BSMotor.Infinite, BSMotor.Infinite, BSMotor.Infinite); 39 public readonly static Vector3 InfiniteVector = new Vector3(BSMotor.Infinite, BSMotor.Infinite, BSMotor.Infinite);
13 40
14 public BSMotor(string useName) 41 public BSMotor(string useName)
@@ -19,7 +46,9 @@ public abstract class BSMotor
19 public virtual void Reset() { } 46 public virtual void Reset() { }
20 public virtual void Zero() { } 47 public virtual void Zero() { }
21 48
49 // A name passed at motor creation for easily identifyable debugging messages.
22 public string UseName { get; private set; } 50 public string UseName { get; private set; }
51
23 // Used only for outputting debug information. Might not be set so check for null. 52 // Used only for outputting debug information. Might not be set so check for null.
24 public BSScene PhysicsScene { get; set; } 53 public BSScene PhysicsScene { get; set; }
25 protected void MDetailLog(string msg, params Object[] parms) 54 protected void MDetailLog(string msg, params Object[] parms)
@@ -34,10 +63,23 @@ public abstract class BSMotor
34 } 63 }
35} 64}
36// Can all the incremental stepping be replaced with motor classes? 65// Can all the incremental stepping be replaced with motor classes?
66
67// Motor which moves CurrentValue to TargetValue over TimeScale seconds.
68// The TargetValue is decays in TargetValueDecayTimeScale and
69// the CurrentValue will be held back by FrictionTimeScale.
70// TimeScale and TargetDelayTimeScale may be 'infinite' which means go decay.
71
72// For instance, if something is moving at speed X and the desired speed is Y,
73// CurrentValue is X and TargetValue is Y. As the motor is stepped, new
74// values of CurrentValue are returned that approach the TargetValue.
75// The feature of decaying TargetValue is so vehicles will eventually
76// come to a stop rather than run forever. This can be disabled by
77// setting TargetValueDecayTimescale to 'infinite'.
78// The change from CurrentValue to TargetValue is linear over TimeScale seconds.
37public class BSVMotor : BSMotor 79public class BSVMotor : BSMotor
38{ 80{
39 public Vector3 FrameOfReference { get; set; } 81 // public Vector3 FrameOfReference { get; set; }
40 public Vector3 Offset { get; set; } 82 // public Vector3 Offset { get; set; }
41 83
42 public float TimeScale { get; set; } 84 public float TimeScale { get; set; }
43 public float TargetValueDecayTimeScale { get; set; } 85 public float TargetValueDecayTimeScale { get; set; }
@@ -72,6 +114,14 @@ public class BSVMotor : BSMotor
72 { 114 {
73 TargetValue = target; 115 TargetValue = target;
74 } 116 }
117
118 // A form of stepping that does not take the time quantum into account.
119 // The caller must do the right thing later.
120 public Vector3 Step()
121 {
122 return Step(1f);
123 }
124
75 public Vector3 Step(float timeStep) 125 public Vector3 Step(float timeStep)
76 { 126 {
77 Vector3 returnCurrent = Vector3.Zero; 127 Vector3 returnCurrent = Vector3.Zero;
@@ -99,18 +149,19 @@ public class BSVMotor : BSMotor
99 if (FrictionTimescale != BSMotor.InfiniteVector) 149 if (FrictionTimescale != BSMotor.InfiniteVector)
100 { 150 {
101 // frictionFactor = (Vector3.One / FrictionTimescale) * timeStep; 151 // frictionFactor = (Vector3.One / FrictionTimescale) * timeStep;
152 // Individual friction components can be 'infinite' so compute each separately.
102 frictionFactor.X = FrictionTimescale.X == BSMotor.Infinite ? 0f : (1f / FrictionTimescale.X) * timeStep; 153 frictionFactor.X = FrictionTimescale.X == BSMotor.Infinite ? 0f : (1f / FrictionTimescale.X) * timeStep;
103 frictionFactor.Y = FrictionTimescale.Y == BSMotor.Infinite ? 0f : (1f / FrictionTimescale.Y) * timeStep; 154 frictionFactor.Y = FrictionTimescale.Y == BSMotor.Infinite ? 0f : (1f / FrictionTimescale.Y) * timeStep;
104 frictionFactor.Z = FrictionTimescale.Z == BSMotor.Infinite ? 0f : (1f / FrictionTimescale.Z) * timeStep; 155 frictionFactor.Z = FrictionTimescale.Z == BSMotor.Infinite ? 0f : (1f / FrictionTimescale.Z) * timeStep;
105 CurrentValue *= (Vector3.One - frictionFactor); 156 CurrentValue *= (Vector3.One - frictionFactor);
106 } 157 }
107 158
108 MDetailLog("{0},BSVMotor.Step,nonZero,{1},origCurr={2},origTarget={3},timeStep={4},timeScale={5},addAmnt={6},targetDecay={7},decayFact={8},fricTS={9},frictFact={10}", 159 MDetailLog("{0}, BSVMotor.Step,nonZero,{1},origCurr={2},origTarget={3},timeStep={4},timeScale={5},addAmnt={6},targetDecay={7},decayFact={8},fricTS={9},frictFact={10}",
109 BSScene.DetailLogZero, UseName, origCurrVal, origTarget, 160 BSScene.DetailLogZero, UseName, origCurrVal, origTarget,
110 timeStep, TimeScale, addAmount, 161 timeStep, TimeScale, addAmount,
111 TargetValueDecayTimeScale, decayFactor, 162 TargetValueDecayTimeScale, decayFactor,
112 FrictionTimescale, frictionFactor); 163 FrictionTimescale, frictionFactor);
113 MDetailLog("{0},BSVMotor.Step,nonZero,{1},curr={2},target={3},add={4},decay={5},frict={6},ret={7}", 164 MDetailLog("{0}, BSVMotor.Step,nonZero,{1},curr={2},target={3},add={4},decay={5},frict={6},ret={7}",
114 BSScene.DetailLogZero, UseName, CurrentValue, TargetValue, 165 BSScene.DetailLogZero, UseName, CurrentValue, TargetValue,
115 addAmount, decayFactor, frictionFactor, returnCurrent); 166 addAmount, decayFactor, frictionFactor, returnCurrent);
116 } 167 }
@@ -120,7 +171,7 @@ public class BSVMotor : BSMotor
120 CurrentValue = Vector3.Zero; 171 CurrentValue = Vector3.Zero;
121 TargetValue = Vector3.Zero; 172 TargetValue = Vector3.Zero;
122 173
123 MDetailLog("{0},BSVMotor.Step,zero,{1},curr={2},target={3},ret={4}", 174 MDetailLog("{0}, BSVMotor.Step,zero,{1},curr={2},target={3},ret={4}",
124 BSScene.DetailLogZero, UseName, TargetValue, CurrentValue, returnCurrent); 175 BSScene.DetailLogZero, UseName, TargetValue, CurrentValue, returnCurrent);
125 176
126 } 177 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index c62c79a..ea1f71a 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -253,8 +253,9 @@ public sealed class BSPrim : BSPhysObject
253 // Zero some other properties in the physics engine 253 // Zero some other properties in the physics engine
254 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate() 254 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate()
255 { 255 {
256 BulletSimAPI.SetInterpolationAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero); 256 // DetailLog("{0},BSPrim.ZeroAngularMotion,call,rotVel={1}", LocalID, _rotationalVelocity);
257 BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero); 257 BulletSimAPI.SetInterpolationAngularVelocity2(PhysBody.ptr, _rotationalVelocity);
258 BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity);
258 }); 259 });
259 } 260 }
260 261
@@ -329,7 +330,7 @@ public sealed class BSPrim : BSPhysObject
329 330
330 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) 331 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
331 { 332 {
332 float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position); 333 float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(_position);
333 // TODO: a floating motor so object will bob in the water 334 // TODO: a floating motor so object will bob in the water
334 if (Math.Abs(Position.Z - waterHeight) > 0.1f) 335 if (Math.Abs(Position.Z - waterHeight) > 0.1f)
335 { 336 {
@@ -347,7 +348,9 @@ public sealed class BSPrim : BSPhysObject
347 if (ret) 348 if (ret)
348 { 349 {
349 // Apply upforce and overcome gravity. 350 // Apply upforce and overcome gravity.
350 AddForce(upForce - PhysicsScene.DefaultGravity, false, inTaintTime); 351 OMV.Vector3 correctionForce = upForce - PhysicsScene.DefaultGravity;
352 DetailLog("{0},BSPrim.PositionSanityCheck,applyForce,pos={1},upForce={2},correctionForce={3}", LocalID, _position, upForce, correctionForce);
353 AddForce(correctionForce, false, inTaintTime);
351 } 354 }
352 return ret; 355 return ret;
353 } 356 }
@@ -643,9 +646,13 @@ public sealed class BSPrim : BSPhysObject
643 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr); 646 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr);
644 647
645 // Collision filter can be set only when the object is in the world 648 // Collision filter can be set only when the object is in the world
646 if (PhysBody.collisionFilter != 0 || PhysBody.collisionMask != 0) 649 if (PhysBody.collisionGroup != 0 || PhysBody.collisionMask != 0)
647 { 650 {
648 BulletSimAPI.SetCollisionFilterMask2(PhysBody.ptr, (uint)PhysBody.collisionFilter, (uint)PhysBody.collisionMask); 651 if (!BulletSimAPI.SetCollisionGroupMask2(PhysBody.ptr, (uint)PhysBody.collisionGroup, (uint)PhysBody.collisionMask))
652 {
653 PhysicsScene.Logger.ErrorFormat("{0} Failure setting prim collision mask. localID={1}, grp={2:X}, mask={3:X}",
654 LogHeader, LocalID, PhysBody.collisionGroup, PhysBody.collisionMask);
655 }
649 } 656 }
650 657
651 // Recompute any linkset parameters. 658 // Recompute any linkset parameters.
@@ -684,11 +691,11 @@ public sealed class BSPrim : BSPhysObject
684 // There can be special things needed for implementing linksets 691 // There can be special things needed for implementing linksets
685 Linkset.MakeStatic(this); 692 Linkset.MakeStatic(this);
686 // The activation state is 'disabled' so Bullet will not try to act on it. 693 // The activation state is 'disabled' so Bullet will not try to act on it.
687 BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.DISABLE_SIMULATION); 694 // BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.DISABLE_SIMULATION);
688 // Start it out sleeping and physical actions could wake it up. 695 // Start it out sleeping and physical actions could wake it up.
689 // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING); 696 BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ISLAND_SLEEPING);
690 697
691 PhysBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter; 698 PhysBody.collisionGroup = CollisionFilterGroups.StaticObjectGroup;
692 PhysBody.collisionMask = CollisionFilterGroups.StaticObjectMask; 699 PhysBody.collisionMask = CollisionFilterGroups.StaticObjectMask;
693 } 700 }
694 else 701 else
@@ -734,7 +741,7 @@ public sealed class BSPrim : BSPhysObject
734 BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ACTIVE_TAG); 741 BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ACTIVE_TAG);
735 // BulletSimAPI.Activate2(BSBody.ptr, true); 742 // BulletSimAPI.Activate2(BSBody.ptr, true);
736 743
737 PhysBody.collisionFilter = CollisionFilterGroups.ObjectFilter; 744 PhysBody.collisionGroup = CollisionFilterGroups.ObjectGroup;
738 PhysBody.collisionMask = CollisionFilterGroups.ObjectMask; 745 PhysBody.collisionMask = CollisionFilterGroups.ObjectMask;
739 } 746 }
740 } 747 }
@@ -762,7 +769,7 @@ public sealed class BSPrim : BSPhysObject
762 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType); 769 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType);
763 } 770 }
764 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); 771 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
765 PhysBody.collisionFilter = CollisionFilterGroups.VolumeDetectFilter; 772 PhysBody.collisionGroup = CollisionFilterGroups.VolumeDetectGroup;
766 PhysBody.collisionMask = CollisionFilterGroups.VolumeDetectMask; 773 PhysBody.collisionMask = CollisionFilterGroups.VolumeDetectMask;
767 } 774 }
768 } 775 }
@@ -838,15 +845,6 @@ public sealed class BSPrim : BSPhysObject
838 } 845 }
839 public override OMV.Vector3 RotationalVelocity { 846 public override OMV.Vector3 RotationalVelocity {
840 get { 847 get {
841 /*
842 OMV.Vector3 pv = OMV.Vector3.Zero;
843 // if close to zero, report zero
844 // This is copied from ODE but I'm not sure why it returns zero but doesn't
845 // zero the property in the physics engine.
846 if (_rotationalVelocity.ApproxEquals(pv, 0.2f))
847 return pv;
848 */
849
850 return _rotationalVelocity; 848 return _rotationalVelocity;
851 } 849 }
852 set { 850 set {
@@ -1408,7 +1406,7 @@ public sealed class BSPrim : BSPhysObject
1408 LastEntityProperties = CurrentEntityProperties; 1406 LastEntityProperties = CurrentEntityProperties;
1409 CurrentEntityProperties = entprop; 1407 CurrentEntityProperties = entprop;
1410 1408
1411 OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; 1409 OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; // DEBUG DEBUG DEBUG
1412 DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}", 1410 DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}",
1413 LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity); 1411 LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity);
1414 1412
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 09b1423..f72bd74 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -96,6 +96,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
96 public long SimulationStep { get { return m_simulationStep; } } 96 public long SimulationStep { get { return m_simulationStep; } }
97 private int m_taintsToProcessPerStep; 97 private int m_taintsToProcessPerStep;
98 98
99 public delegate void PreStepAction(float timeStep);
100 public event PreStepAction BeforeStep;
101
99 // A value of the time now so all the collision and update routines do not have to get their own 102 // A value of the time now so all the collision and update routines do not have to get their own
100 // Set to 'now' just before all the prims and actors are called for collisions and updates 103 // Set to 'now' just before all the prims and actors are called for collisions and updates
101 public int SimulationNowTime { get; private set; } 104 public int SimulationNowTime { get; private set; }
@@ -127,7 +130,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
127 public const uint GROUNDPLANE_ID = 1; 130 public const uint GROUNDPLANE_ID = 1;
128 public const uint CHILDTERRAIN_ID = 2; // Terrain allocated based on our mega-prim childre start here 131 public const uint CHILDTERRAIN_ID = 2; // Terrain allocated based on our mega-prim childre start here
129 132
130 private float m_waterLevel; 133 public float SimpleWaterLevel { get; set; }
131 public BSTerrainManager TerrainManager { get; private set; } 134 public BSTerrainManager TerrainManager { get; private set; }
132 135
133 public ConfigurationParameters Params 136 public ConfigurationParameters Params
@@ -182,6 +185,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
182 private string m_physicsLoggingDir; 185 private string m_physicsLoggingDir;
183 private string m_physicsLoggingPrefix; 186 private string m_physicsLoggingPrefix;
184 private int m_physicsLoggingFileMinutes; 187 private int m_physicsLoggingFileMinutes;
188 private bool m_physicsLoggingDoFlush;
185 // 'true' of the vehicle code is to log lots of details 189 // 'true' of the vehicle code is to log lots of details
186 public bool VehicleLoggingEnabled { get; private set; } 190 public bool VehicleLoggingEnabled { get; private set; }
187 191
@@ -290,6 +294,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
290 m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", "."); 294 m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", ".");
291 m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-%REGIONNAME%-"); 295 m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-%REGIONNAME%-");
292 m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5); 296 m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5);
297 m_physicsLoggingDoFlush = pConfig.GetBoolean("PhysicsLoggingDoFlush", false);
293 // Very detailed logging for vehicle debugging 298 // Very detailed logging for vehicle debugging
294 VehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false); 299 VehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false);
295 300
@@ -485,8 +490,10 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
485 ProcessTaints(); 490 ProcessTaints();
486 491
487 // Some of the prims operate with special vehicle properties 492 // Some of the prims operate with special vehicle properties
488 ProcessVehicles(timeStep); 493 DoPreStepActions(timeStep);
489 ProcessTaints(); // the vehicles might have added taints 494
495 // the prestep actions might have added taints
496 ProcessTaints();
490 497
491 // step the physical world one interval 498 // step the physical world one interval
492 m_simulationStep++; 499 m_simulationStep++;
@@ -634,12 +641,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
634 641
635 public override void SetWaterLevel(float baseheight) 642 public override void SetWaterLevel(float baseheight)
636 { 643 {
637 m_waterLevel = baseheight; 644 SimpleWaterLevel = baseheight;
638 }
639 // Someday....
640 public float GetWaterLevelAtXYZ(Vector3 loc)
641 {
642 return m_waterLevel;
643 } 645 }
644 646
645 public override void DeleteTerrain() 647 public override void DeleteTerrain()
@@ -910,6 +912,16 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
910 } 912 }
911 } 913 }
912 914
915 private void DoPreStepActions(float timeStep)
916 {
917 ProcessVehicles(timeStep);
918
919 PreStepAction actions = BeforeStep;
920 if (actions != null)
921 actions(timeStep);
922
923 }
924
913 // Some prims have extra vehicle actions 925 // Some prims have extra vehicle actions
914 // Called at taint time! 926 // Called at taint time!
915 private void ProcessVehicles(float timeStep) 927 private void ProcessVehicles(float timeStep)
@@ -974,6 +986,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
974 // Should handle fetching the right type from the ini file and converting it. 986 // Should handle fetching the right type from the ini file and converting it.
975 // -- a delegate for getting the value as a float 987 // -- a delegate for getting the value as a float
976 // -- a delegate for setting the value from a float 988 // -- a delegate for setting the value from a float
989 // -- an optional delegate to update the value in the world. Most often used to
990 // push the new value to an in-world object.
977 // 991 //
978 // The single letter parameters for the delegates are: 992 // The single letter parameters for the delegates are:
979 // s = BSScene 993 // s = BSScene
@@ -1493,7 +1507,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1493 { 1507 {
1494 PhysicsLogging.Write(msg, args); 1508 PhysicsLogging.Write(msg, args);
1495 // Add the Flush() if debugging crashes. Gets all the messages written out. 1509 // Add the Flush() if debugging crashes. Gets all the messages written out.
1496 // PhysicsLogging.Flush(); 1510 if (m_physicsLoggingDoFlush) PhysicsLogging.Flush();
1497 } 1511 }
1498 // Used to fill in the LocalID when there isn't one. It's the correct number of characters. 1512 // Used to fill in the LocalID when there isn't one. It's the correct number of characters.
1499 public const string DetailLogZero = "0000000000"; 1513 public const string DetailLogZero = "0000000000";
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index 892c34b..b94dcf6 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -620,8 +620,7 @@ public sealed class BSShapeCollection : IDisposable
620 } 620 }
621 else 621 else
622 { 622 {
623 // Pass false for physicalness as this creates some sort of bounding box which we don't need 623 meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true, false);
624 meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false);
625 624
626 if (meshData != null) 625 if (meshData != null)
627 { 626 {
@@ -694,8 +693,8 @@ public sealed class BSShapeCollection : IDisposable
694 else 693 else
695 { 694 {
696 // Build a new hull in the physical world 695 // Build a new hull in the physical world
697 // Pass false for physicalness as this creates some sort of bounding box which we don't need 696 // Pass true for physicalness as this creates some sort of bounding box which we don't need
698 IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false); 697 IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true, false);
699 if (meshData != null) 698 if (meshData != null)
700 { 699 {
701 700
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
index 1450f66..83b9c37 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
@@ -121,8 +121,8 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
121 // redo its bounding box now that it is in the world 121 // redo its bounding box now that it is in the world
122 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); 122 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr);
123 123
124 BulletSimAPI.SetCollisionFilterMask2(m_mapInfo.terrainBody.ptr, 124 BulletSimAPI.SetCollisionGroupMask2(m_mapInfo.terrainBody.ptr,
125 (uint)CollisionFilterGroups.TerrainFilter, 125 (uint)CollisionFilterGroups.TerrainGroup,
126 (uint)CollisionFilterGroups.TerrainMask); 126 (uint)CollisionFilterGroups.TerrainMask);
127 127
128 // Make it so the terrain will not move or be considered for movement. 128 // Make it so the terrain will not move or be considered for movement.
@@ -148,7 +148,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
148 } 148 }
149 149
150 // The passed position is relative to the base of the region. 150 // The passed position is relative to the base of the region.
151 public override float GetHeightAtXYZ(Vector3 pos) 151 public override float GetTerrainHeightAtXYZ(Vector3 pos)
152 { 152 {
153 float ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; 153 float ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET;
154 154
@@ -166,5 +166,11 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
166 } 166 }
167 return ret; 167 return ret;
168 } 168 }
169
170 // The passed position is relative to the base of the region.
171 public override float GetWaterLevelAtXYZ(Vector3 pos)
172 {
173 return PhysicsScene.SimpleWaterLevel;
174 }
169} 175}
170} 176}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
index cd623f1..83df360 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
@@ -62,7 +62,8 @@ public abstract class BSTerrainPhys : IDisposable
62 ID = id; 62 ID = id;
63 } 63 }
64 public abstract void Dispose(); 64 public abstract void Dispose();
65 public abstract float GetHeightAtXYZ(Vector3 pos); 65 public abstract float GetTerrainHeightAtXYZ(Vector3 pos);
66 public abstract float GetWaterLevelAtXYZ(Vector3 pos);
66} 67}
67 68
68// ========================================================================================== 69// ==========================================================================================
@@ -75,6 +76,7 @@ public sealed class BSTerrainManager
75 public const float HEIGHT_INITIALIZATION = 24.987f; 76 public const float HEIGHT_INITIALIZATION = 24.987f;
76 public const float HEIGHT_INITIAL_LASTHEIGHT = 24.876f; 77 public const float HEIGHT_INITIAL_LASTHEIGHT = 24.876f;
77 public const float HEIGHT_GETHEIGHT_RET = 24.765f; 78 public const float HEIGHT_GETHEIGHT_RET = 24.765f;
79 public const float WATER_HEIGHT_GETHEIGHT_RET = 19.998f;
78 80
79 // If the min and max height are equal, we reduce the min by this 81 // If the min and max height are equal, we reduce the min by this
80 // amount to make sure that a bounding box is built for the terrain. 82 // amount to make sure that a bounding box is built for the terrain.
@@ -138,8 +140,8 @@ public sealed class BSTerrainManager
138 // Ground plane does not move 140 // Ground plane does not move
139 BulletSimAPI.ForceActivationState2(m_groundPlane.ptr, ActivationState.DISABLE_SIMULATION); 141 BulletSimAPI.ForceActivationState2(m_groundPlane.ptr, ActivationState.DISABLE_SIMULATION);
140 // Everything collides with the ground plane. 142 // Everything collides with the ground plane.
141 BulletSimAPI.SetCollisionFilterMask2(m_groundPlane.ptr, 143 BulletSimAPI.SetCollisionGroupMask2(m_groundPlane.ptr,
142 (uint)CollisionFilterGroups.GroundPlaneFilter, (uint)CollisionFilterGroups.GroundPlaneMask); 144 (uint)CollisionFilterGroups.GroundPlaneGroup, (uint)CollisionFilterGroups.GroundPlaneMask);
143 145
144 // Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain. 146 // Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain.
145 BSTerrainPhys initialTerrain = new BSTerrainHeightmap(PhysicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize); 147 BSTerrainPhys initialTerrain = new BSTerrainHeightmap(PhysicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize);
@@ -358,7 +360,7 @@ public sealed class BSTerrainManager
358 BSTerrainPhys physTerrain; 360 BSTerrainPhys physTerrain;
359 if (m_terrains.TryGetValue(terrainBaseXYZ, out physTerrain)) 361 if (m_terrains.TryGetValue(terrainBaseXYZ, out physTerrain))
360 { 362 {
361 ret = physTerrain.GetHeightAtXYZ(loc - terrainBaseXYZ); 363 ret = physTerrain.GetTerrainHeightAtXYZ(loc - terrainBaseXYZ);
362 } 364 }
363 else 365 else
364 { 366 {
@@ -370,6 +372,33 @@ public sealed class BSTerrainManager
370 return ret; 372 return ret;
371 } 373 }
372 374
375 public float GetWaterLevelAtXYZ(Vector3 pos)
376 {
377 float ret = WATER_HEIGHT_GETHEIGHT_RET;
378
379 float tX = pos.X;
380 float tY = pos.Y;
381
382 Vector3 terrainBaseXYZ = Vector3.Zero;
383 terrainBaseXYZ.X = ((int)(tX / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X;
384 terrainBaseXYZ.Y = ((int)(tY / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y;
385
386 lock (m_terrains)
387 {
388 BSTerrainPhys physTerrain;
389 if (m_terrains.TryGetValue(terrainBaseXYZ, out physTerrain))
390 {
391 ret = physTerrain.GetWaterLevelAtXYZ(pos);
392 }
393 else
394 {
395 PhysicsScene.Logger.ErrorFormat("{0} GetWaterHeightAtXY: terrain not found: region={1}, x={2}, y={3}",
396 LogHeader, PhysicsScene.RegionName, tX, tY);
397 }
398 }
399 return ret;
400 }
401
373 // Although no one seems to check this, I do support combining. 402 // Although no one seems to check this, I do support combining.
374 public bool SupportsCombining() 403 public bool SupportsCombining()
375 { 404 {
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs
index 5f6675d..6ce767d 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs
@@ -130,8 +130,8 @@ public sealed class BSTerrainMesh : BSTerrainPhys
130 // Redo its bounding box now that it is in the world 130 // Redo its bounding box now that it is in the world
131 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_terrainBody.ptr); 131 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_terrainBody.ptr);
132 132
133 BulletSimAPI.SetCollisionFilterMask2(m_terrainBody.ptr, 133 BulletSimAPI.SetCollisionGroupMask2(m_terrainBody.ptr,
134 (uint)CollisionFilterGroups.TerrainFilter, 134 (uint)CollisionFilterGroups.TerrainGroup,
135 (uint)CollisionFilterGroups.TerrainMask); 135 (uint)CollisionFilterGroups.TerrainMask);
136 136
137 // Make it so the terrain will not move or be considered for movement. 137 // Make it so the terrain will not move or be considered for movement.
@@ -148,7 +148,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
148 } 148 }
149 } 149 }
150 150
151 public override float GetHeightAtXYZ(Vector3 pos) 151 public override float GetTerrainHeightAtXYZ(Vector3 pos)
152 { 152 {
153 // For the moment use the saved heightmap to get the terrain height. 153 // For the moment use the saved heightmap to get the terrain height.
154 // TODO: raycast downward to find the true terrain below the position. 154 // TODO: raycast downward to find the true terrain below the position.
@@ -169,6 +169,12 @@ public sealed class BSTerrainMesh : BSTerrainPhys
169 return ret; 169 return ret;
170 } 170 }
171 171
172 // The passed position is relative to the base of the region.
173 public override float GetWaterLevelAtXYZ(Vector3 pos)
174 {
175 return PhysicsScene.SimpleWaterLevel;
176 }
177
172 // Convert the passed heightmap to mesh information suitable for CreateMeshShape2(). 178 // Convert the passed heightmap to mesh information suitable for CreateMeshShape2().
173 // Return 'true' if successfully created. 179 // Return 'true' if successfully created.
174 public static bool ConvertHeightmapToMesh( 180 public static bool ConvertHeightmapToMesh(
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
index 1e003e6..a5acfd1 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
@@ -57,12 +57,12 @@ public struct BulletBody
57 { 57 {
58 ID = id; 58 ID = id;
59 ptr = xx; 59 ptr = xx;
60 collisionFilter = 0; 60 collisionGroup = 0;
61 collisionMask = 0; 61 collisionMask = 0;
62 } 62 }
63 public IntPtr ptr; 63 public IntPtr ptr;
64 public uint ID; 64 public uint ID;
65 public CollisionFilterGroups collisionFilter; 65 public CollisionFilterGroups collisionGroup;
66 public CollisionFilterGroups collisionMask; 66 public CollisionFilterGroups collisionMask;
67 public override string ToString() 67 public override string ToString()
68 { 68 {
@@ -71,10 +71,10 @@ public struct BulletBody
71 buff.Append(ID.ToString()); 71 buff.Append(ID.ToString());
72 buff.Append(",p="); 72 buff.Append(",p=");
73 buff.Append(ptr.ToString("X")); 73 buff.Append(ptr.ToString("X"));
74 if (collisionFilter != 0 || collisionMask != 0) 74 if (collisionGroup != 0 || collisionMask != 0)
75 { 75 {
76 buff.Append(",f="); 76 buff.Append(",g=");
77 buff.Append(collisionFilter.ToString("X")); 77 buff.Append(collisionGroup.ToString("X"));
78 buff.Append(",m="); 78 buff.Append(",m=");
79 buff.Append(collisionMask.ToString("X")); 79 buff.Append(collisionMask.ToString("X"));
80 } 80 }
@@ -376,36 +376,36 @@ public enum CollisionFilterGroups : uint
376 // Don't use the bit definitions!! Define the use in a 376 // Don't use the bit definitions!! Define the use in a
377 // filter/mask definition below. This way collision interactions 377 // filter/mask definition below. This way collision interactions
378 // are more easily debugged. 378 // are more easily debugged.
379 BNoneFilter = 0, 379 BNoneGroup = 0,
380 BDefaultFilter = 1 << 0, 380 BDefaultGroup = 1 << 0,
381 BStaticFilter = 1 << 1, 381 BStaticGroup = 1 << 1,
382 BKinematicFilter = 1 << 2, 382 BKinematicGroup = 1 << 2,
383 BDebrisFilter = 1 << 3, 383 BDebrisGroup = 1 << 3,
384 BSensorTrigger = 1 << 4, 384 BSensorTrigger = 1 << 4,
385 BCharacterFilter = 1 << 5, 385 BCharacterGroup = 1 << 5,
386 BAllFilter = 0xFFFFFFFF, 386 BAllGroup = 0xFFFFFFFF,
387 // Filter groups defined by BulletSim 387 // Filter groups defined by BulletSim
388 BGroundPlaneFilter = 1 << 10, 388 BGroundPlaneGroup = 1 << 10,
389 BTerrainFilter = 1 << 11, 389 BTerrainGroup = 1 << 11,
390 BRaycastFilter = 1 << 12, 390 BRaycastGroup = 1 << 12,
391 BSolidFilter = 1 << 13, 391 BSolidGroup = 1 << 13,
392 BLinksetFilter = 1 << 14, 392 BLinksetGroup = 1 << 14,
393 393
394 // The collsion filters and masked are defined in one place -- don't want them scattered 394 // The collsion filters and masked are defined in one place -- don't want them scattered
395 AvatarFilter = BCharacterFilter, 395 AvatarGroup = BCharacterGroup,
396 AvatarMask = BAllFilter, 396 AvatarMask = BAllGroup,
397 ObjectFilter = BSolidFilter, 397 ObjectGroup = BSolidGroup,
398 ObjectMask = BAllFilter, 398 ObjectMask = BAllGroup,
399 StaticObjectFilter = BStaticFilter, 399 StaticObjectGroup = BStaticGroup,
400 StaticObjectMask = BAllFilter & ~BStaticFilter, // static objects don't collide with each other 400 StaticObjectMask = AvatarGroup | ObjectGroup, // static things don't interact with much
401 LinksetFilter = BLinksetFilter, 401 LinksetGroup = BLinksetGroup,
402 LinksetMask = BAllFilter & ~BLinksetFilter, // linkset objects don't collide with each other 402 LinksetMask = BAllGroup & ~BLinksetGroup, // linkset objects don't collide with each other
403 VolumeDetectFilter = BSensorTrigger, 403 VolumeDetectGroup = BSensorTrigger,
404 VolumeDetectMask = ~BSensorTrigger, 404 VolumeDetectMask = ~BSensorTrigger,
405 TerrainFilter = BTerrainFilter, 405 TerrainGroup = BTerrainGroup,
406 TerrainMask = BAllFilter & ~BStaticFilter, // static objects on the ground don't collide 406 TerrainMask = BAllGroup & ~BStaticGroup, // static objects on the ground don't collide
407 GroundPlaneFilter = BGroundPlaneFilter, 407 GroundPlaneGroup = BGroundPlaneGroup,
408 GroundPlaneMask = BAllFilter 408 GroundPlaneMask = BAllGroup
409 409
410}; 410};
411 411
@@ -945,7 +945,7 @@ public static extern IntPtr GetConstraintRef2(IntPtr obj, int index);
945public static extern int GetNumConstraintRefs2(IntPtr obj); 945public static extern int GetNumConstraintRefs2(IntPtr obj);
946 946
947[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 947[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
948public static extern void SetCollisionFilterMask2(IntPtr body, uint filter, uint mask); 948public static extern bool SetCollisionGroupMask2(IntPtr body, uint filter, uint mask);
949 949
950// ===================================================================================== 950// =====================================================================================
951// btCollisionShape entries 951// btCollisionShape entries
@@ -1007,13 +1007,16 @@ public static extern void DumpRigidBody2(IntPtr sim, IntPtr collisionObject);
1007public static extern void DumpCollisionShape2(IntPtr sim, IntPtr collisionShape); 1007public static extern void DumpCollisionShape2(IntPtr sim, IntPtr collisionShape);
1008 1008
1009[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1009[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1010public static extern void DumpMapInfo2(IntPtr sim, IntPtr manInfo);
1011
1012[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1010public static extern void DumpConstraint2(IntPtr sim, IntPtr constrain); 1013public static extern void DumpConstraint2(IntPtr sim, IntPtr constrain);
1011 1014
1012[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1015[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1013public static extern void DumpAllInfo2(IntPtr sim); 1016public static extern void DumpActivationInfo2(IntPtr sim);
1014 1017
1015[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1018[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1016public static extern void DumpMapInfo2(IntPtr sim, IntPtr manInfo); 1019public static extern void DumpAllInfo2(IntPtr sim);
1017 1020
1018[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1021[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1019public static extern void DumpPhysicsStatistics2(IntPtr sim); 1022public static extern void DumpPhysicsStatistics2(IntPtr sim);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
new file mode 100755
index 0000000..68f25fc
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
@@ -0,0 +1,117 @@
1CRASHES
2=================================================
320121129.1411: editting/moving phys object across region boundries causes crash
4 getPos-> btRigidBody::upcast -> getBodyType -> BOOM
520121128.1600: mesh object not rezzing (no physics mesh).
6 Causes many errors. Doesn't stop after first error with box shape.
7 Eventually crashes when deleting the object.
8
9BULLETSIM TODO LIST:
10=================================================
11Neb car jiggling left and right
12Vehicles (Move smoothly)
13Light cycle falling over when driving
14Light cycle not banking
15Do single prim vehicles don't seem to properly vehiclize.
16Gun sending shooter flying
17Collision margin (gap between physical objects lying on each other)
18Boundry checking (crashes related to crossing boundry)
19 Add check for border edge position for avatars and objects.
20 Verify the events are created for border crossings.
21Avatar rotation (check out changes to ScenePresence for physical rotation)
22Avatar running (what does phys engine need to do?)
23Small physical objects do not interact correctly
24 Create chain of .5x.5x.1 torui and make all but top physical so to hang.
25 The chain will fall apart and pairs will dance around on ground
26 Chains of 1x1x.2 will stay connected but will dance.
27 Chains above 2x2x.4 are move stable and get stablier as torui get larger.
28Add material type linkage and input all the material property definitions.
29 Skeleton classes and table are in the sources but are not filled or used.
30Add PID motor for avatar movement (slow to stop, ...)
31Implement function efficiency for lineaar and angular motion.
32
33After getting off a vehicle, the root prim is phantom (can be walked through)
34 Need to force a position update for the root prim after compound shape destruction
35Find/remove avatar collision with ID=0.
36Test avatar walking up stairs. How does compare with SL.
37 Radius of the capsule affects ability to climb edges.
38Tune terrain/object friction to be closer to SL.
39Debounce avatar contact so legs don't keep folding up when standing.
40Implement LSL physics controls. Like STATUS_ROTATE_X.
41Add border extensions to terrain to help region crossings and objects leaving region.
42Linkset explosion after three "rides" on Nebadon lite vehicle (LinksetConstraint)
43
44Speed up creation of large physical linksets
45 For instance, sitting in Neb's car (130 prims) takes several seconds to become physical
46Performance test with lots of avatars. Can BulletSim support a thousand?
47Optimize collisions in C++: only send up to the object subscribed to collisions.
48 Use collision subscription and remove the collsion(A,B) and collision(B,A)
49Check wheter SimMotionState needs large if statement (see TODO).
50
51Implement 'top colliders' info.
52Avatar jump
53Implement meshes or just verify that they work.
54Do prim hash codes work for sculpties and meshes?
55Performance measurement and changes to make quicker.
56Implement detailed physics stats (GetStats()).
57
58Eliminate collisions between objects in a linkset. (LinksetConstraint)
59 Have UserPointer point to struct with localID and linksetID?
60 Objects in original linkset still collide with each other?
61
62Measure performance improvement from hulls
63Test not using ghost objects for volume detect implementation.
64Performance of closures and delegates for taint processing
65 Are there faster ways?
66 Is any slowdown introduced by the existing implementation significant?
67Is there are more efficient method of implementing pre and post step actions?
68 See http://www.codeproject.com/Articles/29922/Weak-Events-in-C
69
70Package Bullet source mods for Bullet internal stats output
71
72Physics Arena central pyramid: why is one side permiable?
73
74INTERNAL IMPROVEMENT/CLEANUP
75=================================================
76Remove unused fields from ShapeData (not used in API2)
77Breakout code for mesh/hull/compound/native into separate BSShape* classes
78 Standardize access to building and reference code.
79 The skeleton classes are in the sources but are not complete or linked in.
80Generalize Dynamics and PID with standardized motors.
81Generalize Linkset and vehicles into PropertyManagers
82 Methods for Refresh, RemoveBodyDependencies, RestoreBodyDependencies
83 Possibly generalized a 'pre step action' registration.
84Complete implemention of preStepActions
85 Replace vehicle step call with prestep event.
86 Is there a need for postStepActions? postStepTaints?
87Implement linkset by setting position of children when root updated. (LinksetManual)
88LinkablePrim class? Would that simplify/centralize the linkset logic?
89Linkset implementation using manual prim movement.
90Linkset implementation using compound shapes.
91 Compound shapes will need the LocalID in the shapes and collision
92 processing to get it from there.
93BSScene.UpdateParameterSet() is broken. How to set params on objects?
94Remove HeightmapInfo from terrain specification.
95 Since C++ code does not need terrain height, this structure et al are not needed.
96Add floating motor for BS_FLOATS_ON_WATER so prim and avatar will
97 bob at the water level. BSPrim.PositionSanityCheck().
98
99DONE DONE DONE DONE
100=================================================
101Cleanup code in BSDynamics by using motors.
102Consider implementing terrain with a mesh rather than heightmap.
103 Would have better and adjustable resolution.
104NOTDONE: Build terrain mesh so heighmap is height of the center of the square meter.
105 SL and ODE define meter square as being at one corner with one diagional.
106Terrain as mesh.
107How are static linksets seen by the physics engine?
108 A: they are not linked in physics. When moved, all the children are repositioned.
109Remember to remove BSScene.DetailLog Refresh call.
110Convert BSCharacter to use all API2
111Avatar pushing difficult (too heavy?)
112Use asset service passed to BulletSim to get sculptie bodies, etc.
113Vehicles (fix bouncing on terrain)
114Remove old code in DLL (all non-API2 stuff).
115Measurements of mega-physical prim performance (with graph)
116Debug Bullet internal stats output (why is timing all wrong?)
117 Bullet stats logging only works with a single instance of Bullet (one region). \ No newline at end of file
diff --git a/OpenSim/Region/Physics/Manager/IMesher.cs b/OpenSim/Region/Physics/Manager/IMesher.cs
index 3a9ca1b..10c4bd3 100644
--- a/OpenSim/Region/Physics/Manager/IMesher.cs
+++ b/OpenSim/Region/Physics/Manager/IMesher.cs
@@ -36,6 +36,7 @@ namespace OpenSim.Region.Physics.Manager
36 { 36 {
37 IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod); 37 IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod);
38 IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical); 38 IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical);
39 IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache);
39 } 40 }
40 41
41 // Values for level of detail to be passed to the mesher. 42 // Values for level of detail to be passed to the mesher.
diff --git a/OpenSim/Region/Physics/Manager/ZeroMesher.cs b/OpenSim/Region/Physics/Manager/ZeroMesher.cs
index ba19db6..270d2ec 100644
--- a/OpenSim/Region/Physics/Manager/ZeroMesher.cs
+++ b/OpenSim/Region/Physics/Manager/ZeroMesher.cs
@@ -64,11 +64,16 @@ namespace OpenSim.Region.Physics.Manager
64 { 64 {
65 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod) 65 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod)
66 { 66 {
67 return CreateMesh(primName, primShape, size, lod, false); 67 return CreateMesh(primName, primShape, size, lod, false, false);
68 } 68 }
69 69
70 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical) 70 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical)
71 { 71 {
72 return CreateMesh(primName, primShape, size, lod, false, false);
73 }
74
75 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache)
76 {
72 // Remove the reference to the encoded JPEG2000 data so it can be GCed 77 // Remove the reference to the encoded JPEG2000 data so it can be GCed
73 primShape.SculptData = OpenMetaverse.Utils.EmptyBytes; 78 primShape.SculptData = OpenMetaverse.Utils.EmptyBytes;
74 79
diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
index 6fa91ab..8145d61 100644
--- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
+++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
@@ -702,11 +702,16 @@ namespace OpenSim.Region.Physics.Meshing
702 702
703 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod) 703 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod)
704 { 704 {
705 return CreateMesh(primName, primShape, size, lod, false); 705 return CreateMesh(primName, primShape, size, lod, false, true);
706 } 706 }
707 707
708 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical) 708 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical)
709 { 709 {
710 return CreateMesh(primName, primShape, size, lod, isPhysical, true);
711 }
712
713 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache)
714 {
710#if SPAM 715#if SPAM
711 m_log.DebugFormat("[MESH]: Creating mesh for {0}", primName); 716 m_log.DebugFormat("[MESH]: Creating mesh for {0}", primName);
712#endif 717#endif
@@ -716,9 +721,12 @@ namespace OpenSim.Region.Physics.Meshing
716 721
717 // If this mesh has been created already, return it instead of creating another copy 722 // If this mesh has been created already, return it instead of creating another copy
718 // For large regions with 100k+ prims and hundreds of copies of each, this can save a GB or more of memory 723 // For large regions with 100k+ prims and hundreds of copies of each, this can save a GB or more of memory
719 key = primShape.GetMeshKey(size, lod); 724 if (shouldCache)
720 if (m_uniqueMeshes.TryGetValue(key, out mesh)) 725 {
721 return mesh; 726 key = primShape.GetMeshKey(size, lod);
727 if (m_uniqueMeshes.TryGetValue(key, out mesh))
728 return mesh;
729 }
722 730
723 if (size.X < 0.01f) size.X = 0.01f; 731 if (size.X < 0.01f) size.X = 0.01f;
724 if (size.Y < 0.01f) size.Y = 0.01f; 732 if (size.Y < 0.01f) size.Y = 0.01f;
@@ -741,7 +749,10 @@ namespace OpenSim.Region.Physics.Meshing
741 // trim the vertex and triangle lists to free up memory 749 // trim the vertex and triangle lists to free up memory
742 mesh.TrimExcess(); 750 mesh.TrimExcess();
743 751
744 m_uniqueMeshes.Add(key, mesh); 752 if (shouldCache)
753 {
754 m_uniqueMeshes.Add(key, mesh);
755 }
745 } 756 }
746 757
747 return mesh; 758 return mesh;