aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs4
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs502
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSMotors.cs63
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs33
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs25
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs4
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs4
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs4
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs71
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt117
10 files changed, 551 insertions, 276 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index 1dfc420..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
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index a398b74..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,14 +442,15 @@ 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
446 | VehicleFlag.HOVER_GLOBAL_HEIGHT 449 | VehicleFlag.HOVER_GLOBAL_HEIGHT
447 | VehicleFlag.LIMIT_ROLL_ONLY 450 | VehicleFlag.LIMIT_ROLL_ONLY
448 | VehicleFlag.LIMIT_MOTOR_UP
449 | VehicleFlag.HOVER_UP_ONLY); 451 | VehicleFlag.HOVER_UP_ONLY);
450 m_flags |= (VehicleFlag.NO_DEFLECTION_UP 452 m_flags |= (VehicleFlag.NO_DEFLECTION_UP
453 | VehicleFlag.LIMIT_MOTOR_UP
451 | VehicleFlag.HOVER_WATER_ONLY); 454 | VehicleFlag.HOVER_WATER_ONLY);
452 break; 455 break;
453 case Vehicle.TYPE_AIRPLANE: 456 case Vehicle.TYPE_AIRPLANE:
@@ -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
636 Vector3 terrainHeightContribution = ComputeLinearTerrainHeightCorrection(pTimestep, ref pos, terrainHeight);
637 778
638 Vector3 hoverContribution = ComputeLinearHover(pTimestep, ref pos, terrainHeight); 779 Vector3 hoverContribution = ComputeLinearHover(pTimestep);
639 780
640 ComputeLinearBlockingEndPoint(pTimestep, ref pos); 781 ComputeLinearBlockingEndPoint(pTimestep);
641 782
642 Vector3 limitMotorUpContribution = ComputeLinearMotorUp(pTimestep, pos, terrainHeight); 783 Vector3 limitMotorUpContribution = ComputeLinearMotorUp(pTimestep);
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.TerrainManager.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,46 +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 }
733 871
734 if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) 872 if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0)
735 { 873 {
736 if (Math.Abs(pos.Z - m_VhoverTargetHeight) > 0.2f) 874 if (Math.Abs(VehiclePosition.Z - m_VhoverTargetHeight) > 0.2f)
737 { 875 {
876 Vector3 pos = VehiclePosition;
738 pos.Z = m_VhoverTargetHeight; 877 pos.Z = m_VhoverTargetHeight;
739 Prim.ForcePosition = pos; 878 VehiclePosition = pos;
740 } 879 }
741 } 880 }
742 else 881 else
743 { 882 {
744 float verticalError = pos.Z - m_VhoverTargetHeight; 883 // Error is positive if below the target and negative if above.
745 float verticalCorrectionVelocity = pTimestep * (verticalError / m_VhoverTimescale); 884 float verticalError = m_VhoverTargetHeight - VehiclePosition.Z;
885 float verticalCorrectionVelocity = verticalError / m_VhoverTimescale;
746 886
747 // TODO: implement m_VhoverEfficiency 887 // TODO: implement m_VhoverEfficiency correctly
748 if (verticalError > 0.01f) 888 if (Math.Abs(verticalError) > m_VhoverEfficiency)
749 {
750 // If error is positive (we're above the target height), push down
751 ret = new Vector3(0f, 0f, -verticalCorrectionVelocity);
752 }
753 else if (verticalError < -0.01)
754 { 889 {
755 ret = new Vector3(0f, 0f, verticalCorrectionVelocity); 890 ret = new Vector3(0f, 0f, verticalCorrectionVelocity);
756 } 891 }
757 } 892 }
758 893
759 VDetailLog("{0},MoveLinear,hover,pos={1},ret={2},hoverTS={3},height={4},target={5}", 894 VDetailLog("{0}, MoveLinear,hover,pos={1},ret={2},hoverTS={3},height={4},target={5}",
760 Prim.LocalID, pos, ret, m_VhoverTimescale, m_VhoverHeight, m_VhoverTargetHeight); 895 Prim.LocalID, VehiclePosition, ret, m_VhoverTimescale, m_VhoverHeight, m_VhoverTargetHeight);
761 } 896 }
762 897
763 return ret; 898 return ret;
764 } 899 }
765 900
766 public bool ComputeLinearBlockingEndPoint(float pTimestep, ref Vector3 pos) 901 public bool ComputeLinearBlockingEndPoint(float pTimestep)
767 { 902 {
768 bool changed = false; 903 bool changed = false;
769 904
905 Vector3 pos = VehiclePosition;
770 Vector3 posChange = pos - m_lastPositionVector; 906 Vector3 posChange = pos - m_lastPositionVector;
771 if (m_BlockingEndPoint != Vector3.Zero) 907 if (m_BlockingEndPoint != Vector3.Zero)
772 { 908 {
@@ -797,8 +933,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
797 } 933 }
798 if (changed) 934 if (changed)
799 { 935 {
800 Prim.ForcePosition = pos; 936 VehiclePosition = pos;
801 VDetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", 937 VDetailLog("{0}, MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}",
802 Prim.LocalID, m_BlockingEndPoint, posChange, pos); 938 Prim.LocalID, m_BlockingEndPoint, posChange, pos);
803 } 939 }
804 } 940 }
@@ -812,13 +948,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin
812 // VEHICLE_BANKING_TIMESCALE. This is to help prevent ground vehicles from steering 948 // VEHICLE_BANKING_TIMESCALE. This is to help prevent ground vehicles from steering
813 // when they are in mid jump. 949 // when they are in mid jump.
814 // TODO: this code is wrong. Also, what should it do for boats? 950 // TODO: this code is wrong. Also, what should it do for boats?
815 public Vector3 ComputeLinearMotorUp(float pTimestep, Vector3 pos, float terrainHeight) 951 public Vector3 ComputeLinearMotorUp(float pTimestep)
816 { 952 {
817 Vector3 ret = Vector3.Zero; 953 Vector3 ret = Vector3.Zero;
818 if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) 954 if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0)
819 { 955 {
820 // 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.
821 float distanceAboveGround = pos.Z - terrainHeight; 957 // float distanceAboveGround = pos.Z - Math.Max(GetTerrainHeight(pos), GetWaterLevel(pos));
958 float distanceAboveGround = VehiclePosition.Z - GetTerrainHeight(VehiclePosition);
822 if (distanceAboveGround > 1f) 959 if (distanceAboveGround > 1f)
823 { 960 {
824 // downForce = new Vector3(0, 0, (-distanceAboveGround / m_bankingTimescale) * pTimestep); 961 // downForce = new Vector3(0, 0, (-distanceAboveGround / m_bankingTimescale) * pTimestep);
@@ -830,7 +967,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
830 // has a decay factor. This says this force should 967 // has a decay factor. This says this force should
831 // be computed with a motor. 968 // be computed with a motor.
832 // TODO: add interaction with banking. 969 // TODO: add interaction with banking.
833 VDetailLog("{0},MoveLinear,limitMotorUp,distAbove={1},downForce={2}", 970 VDetailLog("{0}, MoveLinear,limitMotorUp,distAbove={1},downForce={2}",
834 Prim.LocalID, distanceAboveGround, ret); 971 Prim.LocalID, distanceAboveGround, ret);
835 } 972 }
836 return ret; 973 return ret;
@@ -839,36 +976,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
839 // ======================================================================= 976 // =======================================================================
840 // ======================================================================= 977 // =======================================================================
841 // 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.
842 private void MoveAngular(float pTimestep) 982 private void MoveAngular(float pTimestep)
843 { 983 {
844 // m_angularMotorDirection // angular velocity requested by LSL motor 984 // The user wants how many radians per second angular change?
845 // m_angularMotorVelocity // current angular motor velocity (ramps up and down)
846 // m_angularMotorTimescale // motor angular velocity ramp up time
847 // m_angularMotorDecayTimescale // motor angular velocity decay rate
848 // m_angularFrictionTimescale // body angular velocity decay rate
849 // m_lastAngularVelocity // what was last applied to body
850
851 /*
852 if (m_angularMotorDirection.LengthSquared() > 0.0001)
853 {
854 Vector3 origVel = m_angularMotorVelocity;
855 Vector3 origDir = m_angularMotorDirection;
856
857 // new velocity += error / ( time to get there / step interval)
858 // requested direction - current vehicle direction
859 m_angularMotorVelocity += (m_angularMotorDirection - m_angularMotorVelocity) / (m_angularMotorTimescale / pTimestep);
860 // decay requested direction
861 m_angularMotorDirection *= (1.0f - (pTimestep * 1.0f/m_angularMotorDecayTimescale));
862
863 VDetailLog("{0},MoveAngular,angularMotorApply,angTScale={1},timeStep={2},origvel={3},origDir={4},vel={5}",
864 Prim.LocalID, m_angularMotorTimescale, pTimestep, origVel, origDir, m_angularMotorVelocity);
865 }
866 else
867 {
868 m_angularMotorVelocity = Vector3.Zero;
869 }
870 */
871
872 Vector3 angularMotorContribution = m_angularMotor.Step(pTimestep); 985 Vector3 angularMotorContribution = m_angularMotor.Step(pTimestep);
873 986
874 // ================================================================== 987 // ==================================================================
@@ -881,25 +994,47 @@ namespace OpenSim.Region.Physics.BulletSPlugin
881 { 994 {
882 angularMotorContribution.X = 0f; 995 angularMotorContribution.X = 0f;
883 angularMotorContribution.Y = 0f; 996 angularMotorContribution.Y = 0f;
884 VDetailLog("{0},MoveAngular,noDeflectionUp,angularMotorContrib={1}", Prim.LocalID, angularMotorContribution); 997 VDetailLog("{0}, MoveAngular,noDeflectionUp,angularMotorContrib={1}", Prim.LocalID, angularMotorContribution);
885 } 998 }
886 999
887 Vector3 verticalAttractionContribution = ComputeAngularVerticalAttraction(pTimestep); 1000 Vector3 verticalAttractionContribution = ComputeAngularVerticalAttraction();
888 1001
889 Vector3 deflectionContribution = ComputeAngularDeflection(pTimestep); 1002 Vector3 deflectionContribution = ComputeAngularDeflection();
890 1003
891 Vector3 bankingContribution = ComputeAngularBanking(pTimestep); 1004 Vector3 bankingContribution = ComputeAngularBanking(angularMotorContribution.Z);
892 1005
893 // ================================================================== 1006 // ==================================================================
894 m_lastVertAttractor = verticalAttractionContribution; 1007 m_lastVertAttractor = verticalAttractionContribution;
895 1008
896 // Sum velocities 1009 // Sum corrections
897 m_lastAngularVelocity = angularMotorContribution 1010 m_lastAngularCorrection = angularMotorContribution
898 + verticalAttractionContribution 1011 + verticalAttractionContribution
899 + deflectionContribution 1012 + deflectionContribution
900 + bankingContribution; 1013 + bankingContribution;
901 1014
902 // ================================================================== 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 }
1036
1037 // ==================================================================
903 //Offset section 1038 //Offset section
904 if (m_linearMotorOffset != Vector3.Zero) 1039 if (m_linearMotorOffset != Vector3.Zero)
905 { 1040 {
@@ -927,53 +1062,20 @@ namespace OpenSim.Region.Physics.BulletSPlugin
927 torqueFromOffset.Z = 0; 1062 torqueFromOffset.Z = 0;
928 torqueFromOffset *= m_vehicleMass; 1063 torqueFromOffset *= m_vehicleMass;
929 Prim.ApplyTorqueImpulse(torqueFromOffset, true); 1064 Prim.ApplyTorqueImpulse(torqueFromOffset, true);
930 VDetailLog("{0},BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", Prim.LocalID, torqueFromOffset); 1065 VDetailLog("{0}, BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", Prim.LocalID, torqueFromOffset);
931 } 1066 }
932 1067
933 // ==================================================================
934 if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f))
935 {
936 m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero.
937 // TODO: zeroing is good but it also sets values in unmanaged code. Remove the stores when idle.
938 VDetailLog("{0},MoveAngular,zeroAngularMotion,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity);
939 Prim.ZeroAngularMotion(true);
940 }
941 else
942 {
943 // Apply to the body.
944 // The above calculates the absolute angular velocity needed. Angular velocity is massless.
945 // Since we are stuffing the angular velocity directly into the object, the computed
946 // velocity needs to be scaled by the timestep.
947 // Also remove any motion that is on the object so added motion is only from vehicle.
948 Vector3 applyAngularForce = ((m_lastAngularVelocity * pTimestep)
949 - Prim.ForceRotationalVelocity);
950 // Unscale the force by the angular factor so it overwhelmes the Bullet additions.
951 Prim.ForceRotationalVelocity = applyAngularForce;
952
953 VDetailLog("{0},MoveAngular,done,angMotor={1},vertAttr={2},bank={3},deflect={4},newAngForce={5},lastAngular={6}",
954 Prim.LocalID,
955 angularMotorContribution, verticalAttractionContribution,
956 bankingContribution, deflectionContribution,
957 applyAngularForce, m_lastAngularVelocity
958 );
959 }
960 } 1068 }
961 1069
962 public Vector3 ComputeAngularVerticalAttraction(float pTimestep) 1070 public Vector3 ComputeAngularVerticalAttraction()
963 { 1071 {
964 Vector3 ret = Vector3.Zero; 1072 Vector3 ret = Vector3.Zero;
965 1073
966 // 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...
967 if (m_verticalAttractionTimescale < 500) 1075 if (m_verticalAttractionTimescale < 500)
968 { 1076 {
969 Vector3 verticalError = Vector3.UnitZ * Prim.ForceOrientation;
970 verticalError.Normalize();
971 m_verticalAttractionMotor.SetCurrent(verticalError);
972 m_verticalAttractionMotor.SetTarget(Vector3.UnitZ);
973 ret = m_verticalAttractionMotor.Step(pTimestep);
974 /*
975 // 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.
976 Vector3 verticalError = Vector3.UnitZ * Prim.ForceOrientation; 1078 Vector3 verticalError = Vector3.UnitZ * VehicleOrientation;
977 verticalError.Normalize(); 1079 verticalError.Normalize();
978 1080
979 // 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)
@@ -991,63 +1093,70 @@ namespace OpenSim.Region.Physics.BulletSPlugin
991 } 1093 }
992 1094
993 // Y error means needed rotation around X axis and visa versa. 1095 // Y error means needed rotation around X axis and visa versa.
994 verticalAttractionContribution.X = verticalError.Y; 1096 ret.X = verticalError.Y;
995 verticalAttractionContribution.Y = - verticalError.X; 1097 ret.Y = - verticalError.X;
996 verticalAttractionContribution.Z = 0f; 1098 ret.Z = 0f;
997 1099
998 // scale by the time scale and timestep 1100 // scale by the time scale and timestep
999 Vector3 unscaledContrib = verticalAttractionContribution; 1101 Vector3 unscaledContrib = ret;
1000 verticalAttractionContribution /= m_verticalAttractionTimescale; 1102 ret /= m_verticalAttractionTimescale;
1001 verticalAttractionContribution *= pTimestep; 1103 // This returns the angular correction desired. Timestep is added later.
1104 // ret *= pTimestep;
1002 1105
1003 // apply efficiency 1106 // apply efficiency
1004 Vector3 preEfficiencyContrib = verticalAttractionContribution; 1107 Vector3 preEfficiencyContrib = ret;
1108 // TODO: implement efficiency.
1109 // Effenciency squared seems to give a more realistic effect
1005 float efficencySquared = m_verticalAttractionEfficiency * m_verticalAttractionEfficiency; 1110 float efficencySquared = m_verticalAttractionEfficiency * m_verticalAttractionEfficiency;
1006 verticalAttractionContribution *= (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); 1111 // ret *= efficencySquared;
1007 1112
1008 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}",
1009 Prim.LocalID, verticalError, unscaledContrib, preEfficiencyContrib, 1114 Prim.LocalID, verticalError, unscaledContrib, preEfficiencyContrib,
1010 m_verticalAttractionEfficiency, efficencySquared, 1115 m_verticalAttractionEfficiency, efficencySquared,
1011 verticalAttractionContribution); 1116 ret);
1012 */
1013
1014 } 1117 }
1015 return ret; 1118 return ret;
1016 } 1119 }
1017 1120
1018 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()
1019 { 1124 {
1020 Vector3 ret = Vector3.Zero; 1125 Vector3 ret = Vector3.Zero;
1021 1126
1022 if (m_angularDeflectionEfficiency != 0) 1127 if (m_angularDeflectionEfficiency != 0)
1023 { 1128 {
1024 // Compute a scaled vector that points in the preferred axis (X direction) 1129 // Where the vehicle should want to point relative to the vehicle
1025 Vector3 scaledDefaultDirection = 1130 Vector3 preferredDirection = Vector3.UnitX * m_referenceFrame;
1026 new Vector3((pTimestep * 10 * (m_angularDeflectionEfficiency / m_angularDeflectionTimescale)), 0, 0);
1027 // Adding the current vehicle orientation and reference frame displaces the orientation to the frame.
1028 // Rotate the scaled default axix relative to the actual vehicle direction giving where it should point.
1029 Vector3 preferredAxisOfMotion = scaledDefaultDirection * Quaternion.Add(Prim.ForceOrientation, m_referenceFrame);
1030 1131
1031 // Scale by efficiency and timescale 1132 // Where the vehicle is pointing relative to the vehicle.
1032 ret = (preferredAxisOfMotion * (m_angularDeflectionEfficiency) / m_angularDeflectionTimescale) * pTimestep; 1133 Vector3 currentDirection = Vector3.UnitX * Quaternion.Add(VehicleOrientation, m_referenceFrame);
1033 1134
1034 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;
1035 1137
1036 // This deflection computation is not correct. 1138 // Scale the correction by recovery timescale and efficiency
1037 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);
1038 } 1143 }
1039 return ret; 1144 return ret;
1040 } 1145 }
1041 1146
1042 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)
1043 { 1151 {
1044 Vector3 ret = Vector3.Zero; 1152 Vector3 ret = Vector3.Zero;
1153 Vector3 computedBanking = Vector3.Zero;
1045 1154
1046 if (m_bankingEfficiency != 0) 1155 if (m_bankingEfficiency != 0)
1047 { 1156 {
1048 Vector3 dir = Vector3.One * Prim.ForceOrientation; 1157 Vector3 currentDirection = Vector3.UnitX * VehicleOrientation;
1158
1049 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);
1050 //Changes which way it banks in and out of turns
1051 1160
1052 //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
1053 float effSquared = (m_bankingEfficiency * m_bankingEfficiency); 1162 float effSquared = (m_bankingEfficiency * m_bankingEfficiency);
@@ -1055,58 +1164,34 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1055 effSquared *= -1; //Keep the negative! 1164 effSquared *= -1; //Keep the negative!
1056 1165
1057 float mix = Math.Abs(m_bankingMix); 1166 float mix = Math.Abs(m_bankingMix);
1058 if (m_angularMotorVelocity.X == 0) 1167 // TODO: Must include reference frame.
1059 { 1168 float forwardSpeed = VehicleVelocity.X;
1060 // The vehicle is stopped
1061 /*if (!parent.Orientation.ApproxEquals(this.m_referenceFrame, 0.25f))
1062 {
1063 Vector3 axisAngle;
1064 float angle;
1065 parent.Orientation.GetAxisAngle(out axisAngle, out angle);
1066 Vector3 rotatedVel = parent.Velocity * parent.Orientation;
1067 if ((rotatedVel.X < 0 && axisAngle.Y > 0) || (rotatedVel.X > 0 && axisAngle.Y < 0))
1068 m_angularMotorVelocity.X += (effSquared * (mult * mix)) * (1f) * 10;
1069 else
1070 m_angularMotorVelocity.X += (effSquared * (mult * mix)) * (-1f) * 10;
1071 }*/
1072 }
1073 else
1074 {
1075 ret.Z += (effSquared * (mult * mix)) * (m_angularMotorVelocity.X) * 4;
1076 }
1077 1169
1078 //If they are colliding, we probably shouldn't shove the prim around... probably 1170 if (!Prim.IsColliding && forwardSpeed > mix)
1079 if (!Prim.IsColliding && Math.Abs(m_angularMotorVelocity.X) > mix)
1080 { 1171 {
1081 float angVelZ = m_angularMotorVelocity.X * -1; 1172 computedBanking.X = ClampInRange(-3f, turningFactor * (effSquared * mult), 3f);
1082 /*if(angVelZ > mix)
1083 angVelZ = mix;
1084 else if(angVelZ < -mix)
1085 angVelZ = -mix;*/
1086 //This controls how fast and how far the banking occurs
1087 Vector3 bankingRot = new Vector3(angVelZ * (effSquared * mult), 0, 0);
1088 if (bankingRot.X > 3)
1089 bankingRot.X = 3;
1090 else if (bankingRot.X < -3)
1091 bankingRot.X = -3;
1092 bankingRot *= Prim.ForceOrientation;
1093 ret += bankingRot;
1094 } 1173 }
1095 m_angularMotorVelocity.X *= m_bankingEfficiency == 1 ? 0.0f : 1 - m_bankingEfficiency; 1174
1096 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.
1097 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);
1098 } 1183 }
1184 m_lastBanking = computedBanking;
1099 return ret; 1185 return ret;
1100 } 1186 }
1101 1187
1102
1103 // This is from previous instantiations of XXXDynamics.cs. 1188 // This is from previous instantiations of XXXDynamics.cs.
1104 // Applies roll reference frame. 1189 // Applies roll reference frame.
1105 // 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?
1106 // Should this be in MoveAngular()? 1191 // Should this be in MoveAngular()?
1107 internal void LimitRotation(float timestep) 1192 internal void LimitRotation(float timestep)
1108 { 1193 {
1109 Quaternion rotq = Prim.ForceOrientation; 1194 Quaternion rotq = VehicleOrientation;
1110 Quaternion m_rot = rotq; 1195 Quaternion m_rot = rotq;
1111 if (m_RollreferenceFrame != Quaternion.Identity) 1196 if (m_RollreferenceFrame != Quaternion.Identity)
1112 { 1197 {
@@ -1134,12 +1219,17 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1134 } 1219 }
1135 if (rotq != m_rot) 1220 if (rotq != m_rot)
1136 { 1221 {
1137 Prim.ForceOrientation = m_rot; 1222 VehicleOrientation = m_rot;
1138 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);
1139 } 1224 }
1140 1225
1141 } 1226 }
1142 1227
1228 private float ClampInRange(float low, float val, float high)
1229 {
1230 return Math.Max(low, Math.Min(val, high));
1231 }
1232
1143 // Invoke the detailed logger and output something if it's enabled. 1233 // Invoke the detailed logger and output something if it's enabled.
1144 private void VDetailLog(string msg, params Object[] args) 1234 private void VDetailLog(string msg, params Object[] args)
1145 { 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 3fb0300..ea1f71a 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -348,7 +348,9 @@ public sealed class BSPrim : BSPhysObject
348 if (ret) 348 if (ret)
349 { 349 {
350 // Apply upforce and overcome gravity. 350 // Apply upforce and overcome gravity.
351 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);
352 } 354 }
353 return ret; 355 return ret;
354 } 356 }
@@ -644,9 +646,13 @@ public sealed class BSPrim : BSPhysObject
644 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr); 646 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr);
645 647
646 // 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
647 if (PhysBody.collisionFilter != 0 || PhysBody.collisionMask != 0) 649 if (PhysBody.collisionGroup != 0 || PhysBody.collisionMask != 0)
648 { 650 {
649 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 }
650 } 656 }
651 657
652 // Recompute any linkset parameters. 658 // Recompute any linkset parameters.
@@ -685,11 +691,11 @@ public sealed class BSPrim : BSPhysObject
685 // There can be special things needed for implementing linksets 691 // There can be special things needed for implementing linksets
686 Linkset.MakeStatic(this); 692 Linkset.MakeStatic(this);
687 // 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.
688 BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.DISABLE_SIMULATION); 694 // BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.DISABLE_SIMULATION);
689 // Start it out sleeping and physical actions could wake it up. 695 // Start it out sleeping and physical actions could wake it up.
690 // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING); 696 BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ISLAND_SLEEPING);
691 697
692 PhysBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter; 698 PhysBody.collisionGroup = CollisionFilterGroups.StaticObjectGroup;
693 PhysBody.collisionMask = CollisionFilterGroups.StaticObjectMask; 699 PhysBody.collisionMask = CollisionFilterGroups.StaticObjectMask;
694 } 700 }
695 else 701 else
@@ -735,7 +741,7 @@ public sealed class BSPrim : BSPhysObject
735 BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ACTIVE_TAG); 741 BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ACTIVE_TAG);
736 // BulletSimAPI.Activate2(BSBody.ptr, true); 742 // BulletSimAPI.Activate2(BSBody.ptr, true);
737 743
738 PhysBody.collisionFilter = CollisionFilterGroups.ObjectFilter; 744 PhysBody.collisionGroup = CollisionFilterGroups.ObjectGroup;
739 PhysBody.collisionMask = CollisionFilterGroups.ObjectMask; 745 PhysBody.collisionMask = CollisionFilterGroups.ObjectMask;
740 } 746 }
741 } 747 }
@@ -763,7 +769,7 @@ public sealed class BSPrim : BSPhysObject
763 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);
764 } 770 }
765 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); 771 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
766 PhysBody.collisionFilter = CollisionFilterGroups.VolumeDetectFilter; 772 PhysBody.collisionGroup = CollisionFilterGroups.VolumeDetectGroup;
767 PhysBody.collisionMask = CollisionFilterGroups.VolumeDetectMask; 773 PhysBody.collisionMask = CollisionFilterGroups.VolumeDetectMask;
768 } 774 }
769 } 775 }
@@ -839,15 +845,6 @@ public sealed class BSPrim : BSPhysObject
839 } 845 }
840 public override OMV.Vector3 RotationalVelocity { 846 public override OMV.Vector3 RotationalVelocity {
841 get { 847 get {
842 /*
843 OMV.Vector3 pv = OMV.Vector3.Zero;
844 // if close to zero, report zero
845 // This is copied from ODE but I'm not sure why it returns zero but doesn't
846 // zero the property in the physics engine.
847 if (_rotationalVelocity.ApproxEquals(pv, 0.2f))
848 return pv;
849 */
850
851 return _rotationalVelocity; 848 return _rotationalVelocity;
852 } 849 }
853 set { 850 set {
@@ -1409,7 +1406,7 @@ public sealed class BSPrim : BSPhysObject
1409 LastEntityProperties = CurrentEntityProperties; 1406 LastEntityProperties = CurrentEntityProperties;
1410 CurrentEntityProperties = entprop; 1407 CurrentEntityProperties = entprop;
1411 1408
1412 OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; 1409 OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; // DEBUG DEBUG DEBUG
1413 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}",
1414 LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity); 1411 LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity);
1415 1412
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 0c80611..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; }
@@ -487,8 +490,10 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
487 ProcessTaints(); 490 ProcessTaints();
488 491
489 // Some of the prims operate with special vehicle properties 492 // Some of the prims operate with special vehicle properties
490 ProcessVehicles(timeStep); 493 DoPreStepActions(timeStep);
491 ProcessTaints(); // the vehicles might have added taints 494
495 // the prestep actions might have added taints
496 ProcessTaints();
492 497
493 // step the physical world one interval 498 // step the physical world one interval
494 m_simulationStep++; 499 m_simulationStep++;
@@ -496,7 +501,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
496 501
497 try 502 try
498 { 503 {
499 // if (VehicleLoggingEnabled) DumpVehicles(); // DEBUG 504 if (VehicleLoggingEnabled) DumpVehicles(); // DEBUG
500 if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount(); 505 if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount();
501 506
502 numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep, 507 numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep,
@@ -505,7 +510,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
505 if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime); 510 if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime);
506 DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}", 511 DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}",
507 DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount); 512 DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount);
508 // if (VehicleLoggingEnabled) DumpVehicles(); // DEBUG 513 if (VehicleLoggingEnabled) DumpVehicles(); // DEBUG
509 } 514 }
510 catch (Exception e) 515 catch (Exception e)
511 { 516 {
@@ -907,6 +912,16 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
907 } 912 }
908 } 913 }
909 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
910 // Some prims have extra vehicle actions 925 // Some prims have extra vehicle actions
911 // Called at taint time! 926 // Called at taint time!
912 private void ProcessVehicles(float timeStep) 927 private void ProcessVehicles(float timeStep)
@@ -971,6 +986,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
971 // 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.
972 // -- a delegate for getting the value as a float 987 // -- a delegate for getting the value as a float
973 // -- 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.
974 // 991 //
975 // The single letter parameters for the delegates are: 992 // The single letter parameters for the delegates are:
976 // s = BSScene 993 // s = BSScene
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
index 0cb151e..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.
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
index 17d9536..83df360 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
@@ -140,8 +140,8 @@ public sealed class BSTerrainManager
140 // Ground plane does not move 140 // Ground plane does not move
141 BulletSimAPI.ForceActivationState2(m_groundPlane.ptr, ActivationState.DISABLE_SIMULATION); 141 BulletSimAPI.ForceActivationState2(m_groundPlane.ptr, ActivationState.DISABLE_SIMULATION);
142 // Everything collides with the ground plane. 142 // Everything collides with the ground plane.
143 BulletSimAPI.SetCollisionFilterMask2(m_groundPlane.ptr, 143 BulletSimAPI.SetCollisionGroupMask2(m_groundPlane.ptr,
144 (uint)CollisionFilterGroups.GroundPlaneFilter, (uint)CollisionFilterGroups.GroundPlaneMask); 144 (uint)CollisionFilterGroups.GroundPlaneGroup, (uint)CollisionFilterGroups.GroundPlaneMask);
145 145
146 // 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.
147 BSTerrainPhys initialTerrain = new BSTerrainHeightmap(PhysicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize); 147 BSTerrainPhys initialTerrain = new BSTerrainHeightmap(PhysicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs
index 7e93ab4..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.
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