diff options
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs')
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 647 |
1 files changed, 416 insertions, 231 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 65df741..7b98f9d 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | |||
@@ -40,13 +40,14 @@ using OpenSim.Region.Physics.Manager; | |||
40 | 40 | ||
41 | namespace OpenSim.Region.Physics.BulletSPlugin | 41 | namespace OpenSim.Region.Physics.BulletSPlugin |
42 | { | 42 | { |
43 | public sealed class BSDynamics | 43 | public sealed class BSDynamics : BSActor |
44 | { | 44 | { |
45 | private static string LogHeader = "[BULLETSIM VEHICLE]"; | 45 | private static string LogHeader = "[BULLETSIM VEHICLE]"; |
46 | 46 | ||
47 | private BSScene PhysicsScene { get; set; } | ||
48 | // the prim this dynamic controller belongs to | 47 | // the prim this dynamic controller belongs to |
49 | private BSPrim Prim { get; set; } | 48 | private BSPrimLinkable ControllingPrim { get; set; } |
49 | |||
50 | private bool m_haveRegisteredForSceneEvents; | ||
50 | 51 | ||
51 | // mass of the vehicle fetched each time we're calles | 52 | // mass of the vehicle fetched each time we're calles |
52 | private float m_vehicleMass; | 53 | private float m_vehicleMass; |
@@ -124,38 +125,24 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
124 | static readonly float PIOverFour = ((float)Math.PI) / 4f; | 125 | static readonly float PIOverFour = ((float)Math.PI) / 4f; |
125 | static readonly float PIOverTwo = ((float)Math.PI) / 2f; | 126 | static readonly float PIOverTwo = ((float)Math.PI) / 2f; |
126 | 127 | ||
127 | // For debugging, flags to turn on and off individual corrections. | 128 | public BSDynamics(BSScene myScene, BSPrim myPrim, string actorName) |
128 | public bool enableAngularVerticalAttraction; | 129 | : base(myScene, myPrim, actorName) |
129 | public bool enableAngularDeflection; | ||
130 | public bool enableAngularBanking; | ||
131 | |||
132 | public BSDynamics(BSScene myScene, BSPrim myPrim) | ||
133 | { | 130 | { |
134 | PhysicsScene = myScene; | ||
135 | Prim = myPrim; | ||
136 | Type = Vehicle.TYPE_NONE; | 131 | Type = Vehicle.TYPE_NONE; |
137 | SetupVehicleDebugging(); | 132 | m_haveRegisteredForSceneEvents = false; |
138 | } | ||
139 | 133 | ||
140 | // Stopgap debugging enablement. Allows source level debugging but still checking | 134 | ControllingPrim = myPrim as BSPrimLinkable; |
141 | // in changes by making enablement of debugging flags from INI file. | 135 | if (ControllingPrim == null) |
142 | public void SetupVehicleDebugging() | ||
143 | { | ||
144 | enableAngularVerticalAttraction = true; | ||
145 | enableAngularDeflection = false; | ||
146 | enableAngularBanking = true; | ||
147 | if (BSParam.VehicleDebuggingEnabled) | ||
148 | { | 136 | { |
149 | enableAngularVerticalAttraction = true; | 137 | // THIS CANNOT HAPPEN!! |
150 | enableAngularDeflection = false; | ||
151 | enableAngularBanking = false; | ||
152 | } | 138 | } |
139 | VDetailLog("{0},Creation", ControllingPrim.LocalID); | ||
153 | } | 140 | } |
154 | 141 | ||
155 | // Return 'true' if this vehicle is doing vehicle things | 142 | // Return 'true' if this vehicle is doing vehicle things |
156 | public bool IsActive | 143 | public bool IsActive |
157 | { | 144 | { |
158 | get { return (Type != Vehicle.TYPE_NONE && Prim.IsPhysicallyActive); } | 145 | get { return (Type != Vehicle.TYPE_NONE && ControllingPrim.IsPhysicallyActive); } |
159 | } | 146 | } |
160 | 147 | ||
161 | // Return 'true' if this a vehicle that should be sitting on the ground | 148 | // Return 'true' if this a vehicle that should be sitting on the ground |
@@ -167,11 +154,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
167 | #region Vehicle parameter setting | 154 | #region Vehicle parameter setting |
168 | public void ProcessFloatVehicleParam(Vehicle pParam, float pValue) | 155 | public void ProcessFloatVehicleParam(Vehicle pParam, float pValue) |
169 | { | 156 | { |
170 | VDetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue); | 157 | VDetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", ControllingPrim.LocalID, pParam, pValue); |
171 | switch (pParam) | 158 | switch (pParam) |
172 | { | 159 | { |
173 | case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: | 160 | case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: |
174 | m_angularDeflectionEfficiency = Math.Max(pValue, 0.01f); | 161 | m_angularDeflectionEfficiency = ClampInRange(0f, pValue, 1f); |
175 | break; | 162 | break; |
176 | case Vehicle.ANGULAR_DEFLECTION_TIMESCALE: | 163 | case Vehicle.ANGULAR_DEFLECTION_TIMESCALE: |
177 | m_angularDeflectionTimescale = Math.Max(pValue, 0.01f); | 164 | m_angularDeflectionTimescale = Math.Max(pValue, 0.01f); |
@@ -195,7 +182,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
195 | break; | 182 | break; |
196 | case Vehicle.BUOYANCY: | 183 | case Vehicle.BUOYANCY: |
197 | m_VehicleBuoyancy = ClampInRange(-1f, pValue, 1f); | 184 | m_VehicleBuoyancy = ClampInRange(-1f, pValue, 1f); |
198 | m_VehicleGravity = Prim.ComputeGravity(m_VehicleBuoyancy); | 185 | m_VehicleGravity = ControllingPrim.ComputeGravity(m_VehicleBuoyancy); |
199 | break; | 186 | break; |
200 | case Vehicle.HOVER_EFFICIENCY: | 187 | case Vehicle.HOVER_EFFICIENCY: |
201 | m_VhoverEfficiency = ClampInRange(0f, pValue, 1f); | 188 | m_VhoverEfficiency = ClampInRange(0f, pValue, 1f); |
@@ -207,7 +194,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
207 | m_VhoverTimescale = Math.Max(pValue, 0.01f); | 194 | m_VhoverTimescale = Math.Max(pValue, 0.01f); |
208 | break; | 195 | break; |
209 | case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: | 196 | case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: |
210 | m_linearDeflectionEfficiency = Math.Max(pValue, 0.01f); | 197 | m_linearDeflectionEfficiency = ClampInRange(0f, pValue, 1f); |
211 | break; | 198 | break; |
212 | case Vehicle.LINEAR_DEFLECTION_TIMESCALE: | 199 | case Vehicle.LINEAR_DEFLECTION_TIMESCALE: |
213 | m_linearDeflectionTimescale = Math.Max(pValue, 0.01f); | 200 | m_linearDeflectionTimescale = Math.Max(pValue, 0.01f); |
@@ -233,7 +220,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
233 | // set all of the components to the same value | 220 | // set all of the components to the same value |
234 | case Vehicle.ANGULAR_FRICTION_TIMESCALE: | 221 | case Vehicle.ANGULAR_FRICTION_TIMESCALE: |
235 | m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue); | 222 | m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue); |
236 | m_angularMotor.FrictionTimescale = m_angularFrictionTimescale; | ||
237 | break; | 223 | break; |
238 | case Vehicle.ANGULAR_MOTOR_DIRECTION: | 224 | case Vehicle.ANGULAR_MOTOR_DIRECTION: |
239 | m_angularMotorDirection = new Vector3(pValue, pValue, pValue); | 225 | m_angularMotorDirection = new Vector3(pValue, pValue, pValue); |
@@ -242,7 +228,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
242 | break; | 228 | break; |
243 | case Vehicle.LINEAR_FRICTION_TIMESCALE: | 229 | case Vehicle.LINEAR_FRICTION_TIMESCALE: |
244 | m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); | 230 | m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); |
245 | m_linearMotor.FrictionTimescale = m_linearFrictionTimescale; | ||
246 | break; | 231 | break; |
247 | case Vehicle.LINEAR_MOTOR_DIRECTION: | 232 | case Vehicle.LINEAR_MOTOR_DIRECTION: |
248 | m_linearMotorDirection = new Vector3(pValue, pValue, pValue); | 233 | m_linearMotorDirection = new Vector3(pValue, pValue, pValue); |
@@ -258,12 +243,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
258 | 243 | ||
259 | internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue) | 244 | internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue) |
260 | { | 245 | { |
261 | VDetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue); | 246 | VDetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", ControllingPrim.LocalID, pParam, pValue); |
262 | switch (pParam) | 247 | switch (pParam) |
263 | { | 248 | { |
264 | case Vehicle.ANGULAR_FRICTION_TIMESCALE: | 249 | case Vehicle.ANGULAR_FRICTION_TIMESCALE: |
265 | m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); | 250 | m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); |
266 | m_angularMotor.FrictionTimescale = m_angularFrictionTimescale; | ||
267 | break; | 251 | break; |
268 | case Vehicle.ANGULAR_MOTOR_DIRECTION: | 252 | case Vehicle.ANGULAR_MOTOR_DIRECTION: |
269 | // Limit requested angular speed to 2 rps= 4 pi rads/sec | 253 | // Limit requested angular speed to 2 rps= 4 pi rads/sec |
@@ -276,7 +260,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
276 | break; | 260 | break; |
277 | case Vehicle.LINEAR_FRICTION_TIMESCALE: | 261 | case Vehicle.LINEAR_FRICTION_TIMESCALE: |
278 | m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); | 262 | m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); |
279 | m_linearMotor.FrictionTimescale = m_linearFrictionTimescale; | ||
280 | break; | 263 | break; |
281 | case Vehicle.LINEAR_MOTOR_DIRECTION: | 264 | case Vehicle.LINEAR_MOTOR_DIRECTION: |
282 | m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); | 265 | m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); |
@@ -294,7 +277,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
294 | 277 | ||
295 | internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) | 278 | internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) |
296 | { | 279 | { |
297 | VDetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue); | 280 | VDetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", ControllingPrim.LocalID, pParam, pValue); |
298 | switch (pParam) | 281 | switch (pParam) |
299 | { | 282 | { |
300 | case Vehicle.REFERENCE_FRAME: | 283 | case Vehicle.REFERENCE_FRAME: |
@@ -308,7 +291,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
308 | 291 | ||
309 | internal void ProcessVehicleFlags(int pParam, bool remove) | 292 | internal void ProcessVehicleFlags(int pParam, bool remove) |
310 | { | 293 | { |
311 | VDetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", Prim.LocalID, pParam, remove); | 294 | VDetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", ControllingPrim.LocalID, pParam, remove); |
312 | VehicleFlag parm = (VehicleFlag)pParam; | 295 | VehicleFlag parm = (VehicleFlag)pParam; |
313 | if (pParam == -1) | 296 | if (pParam == -1) |
314 | m_flags = (VehicleFlag)0; | 297 | m_flags = (VehicleFlag)0; |
@@ -323,7 +306,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
323 | 306 | ||
324 | public void ProcessTypeChange(Vehicle pType) | 307 | public void ProcessTypeChange(Vehicle pType) |
325 | { | 308 | { |
326 | VDetailLog("{0},ProcessTypeChange,type={1}", Prim.LocalID, pType); | 309 | VDetailLog("{0},ProcessTypeChange,type={1}", ControllingPrim.LocalID, pType); |
327 | // Set Defaults For Type | 310 | // Set Defaults For Type |
328 | Type = pType; | 311 | Type = pType; |
329 | switch (pType) | 312 | switch (pType) |
@@ -557,34 +540,40 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
557 | break; | 540 | break; |
558 | } | 541 | } |
559 | 542 | ||
560 | // Update any physical parameters based on this type. | 543 | m_linearMotor = new BSVMotor("LinearMotor", m_linearMotorTimescale, m_linearMotorDecayTimescale, 1f); |
561 | Refresh(); | 544 | // m_linearMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG DEBUG (enables detail logging) |
562 | |||
563 | m_linearMotor = new BSVMotor("LinearMotor", m_linearMotorTimescale, | ||
564 | m_linearMotorDecayTimescale, m_linearFrictionTimescale, | ||
565 | 1f); | ||
566 | m_linearMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging) | ||
567 | 545 | ||
568 | m_angularMotor = new BSVMotor("AngularMotor", m_angularMotorTimescale, | 546 | m_angularMotor = new BSVMotor("AngularMotor", m_angularMotorTimescale, m_angularMotorDecayTimescale, 1f); |
569 | m_angularMotorDecayTimescale, m_angularFrictionTimescale, | 547 | // m_angularMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG DEBUG (enables detail logging) |
570 | 1f); | ||
571 | m_angularMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging) | ||
572 | 548 | ||
573 | /* Not implemented | 549 | /* Not implemented |
574 | m_verticalAttractionMotor = new BSVMotor("VerticalAttraction", m_verticalAttractionTimescale, | 550 | m_verticalAttractionMotor = new BSVMotor("VerticalAttraction", m_verticalAttractionTimescale, |
575 | BSMotor.Infinite, BSMotor.InfiniteVector, | 551 | BSMotor.Infinite, BSMotor.InfiniteVector, |
576 | m_verticalAttractionEfficiency); | 552 | m_verticalAttractionEfficiency); |
577 | // Z goes away and we keep X and Y | 553 | // Z goes away and we keep X and Y |
578 | m_verticalAttractionMotor.FrictionTimescale = new Vector3(BSMotor.Infinite, BSMotor.Infinite, 0.1f); | ||
579 | m_verticalAttractionMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging) | 554 | m_verticalAttractionMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging) |
580 | */ | 555 | */ |
556 | |||
557 | if (this.Type == Vehicle.TYPE_NONE) | ||
558 | { | ||
559 | UnregisterForSceneEvents(); | ||
560 | } | ||
561 | else | ||
562 | { | ||
563 | RegisterForSceneEvents(); | ||
564 | } | ||
565 | |||
566 | // Update any physical parameters based on this type. | ||
567 | Refresh(); | ||
581 | } | 568 | } |
582 | #endregion // Vehicle parameter setting | 569 | #endregion // Vehicle parameter setting |
583 | 570 | ||
584 | public void Refresh() | 571 | // BSActor.Refresh() |
572 | public override void Refresh() | ||
585 | { | 573 | { |
586 | // If asking for a refresh, reset the physical parameters before the next simulation step. | 574 | // If asking for a refresh, reset the physical parameters before the next simulation step. |
587 | PhysicsScene.PostTaintObject("BSDynamics.Refresh", Prim.LocalID, delegate() | 575 | // Called whether active or not since the active state may be updated before the next step. |
576 | m_physicsScene.PostTaintObject("BSDynamics.Refresh", ControllingPrim.LocalID, delegate() | ||
588 | { | 577 | { |
589 | SetPhysicalParameters(); | 578 | SetPhysicalParameters(); |
590 | }); | 579 | }); |
@@ -597,49 +586,98 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
597 | if (IsActive) | 586 | if (IsActive) |
598 | { | 587 | { |
599 | // Remember the mass so we don't have to fetch it every step | 588 | // Remember the mass so we don't have to fetch it every step |
600 | m_vehicleMass = Prim.TotalMass; | 589 | m_vehicleMass = ControllingPrim.TotalMass; |
601 | 590 | ||
602 | // Friction affects are handled by this vehicle code | 591 | // Friction affects are handled by this vehicle code |
603 | PhysicsScene.PE.SetFriction(Prim.PhysBody, BSParam.VehicleFriction); | 592 | // m_physicsScene.PE.SetFriction(ControllingPrim.PhysBody, BSParam.VehicleFriction); |
604 | PhysicsScene.PE.SetRestitution(Prim.PhysBody, BSParam.VehicleRestitution); | 593 | // m_physicsScene.PE.SetRestitution(ControllingPrim.PhysBody, BSParam.VehicleRestitution); |
594 | ControllingPrim.Linkset.SetPhysicalFriction(BSParam.VehicleFriction); | ||
595 | ControllingPrim.Linkset.SetPhysicalRestitution(BSParam.VehicleRestitution); | ||
605 | 596 | ||
606 | // Moderate angular movement introduced by Bullet. | 597 | // Moderate angular movement introduced by Bullet. |
607 | // TODO: possibly set AngularFactor and LinearFactor for the type of vehicle. | 598 | // TODO: possibly set AngularFactor and LinearFactor for the type of vehicle. |
608 | // Maybe compute linear and angular factor and damping from params. | 599 | // Maybe compute linear and angular factor and damping from params. |
609 | PhysicsScene.PE.SetAngularDamping(Prim.PhysBody, BSParam.VehicleAngularDamping); | 600 | m_physicsScene.PE.SetAngularDamping(ControllingPrim.PhysBody, BSParam.VehicleAngularDamping); |
610 | PhysicsScene.PE.SetLinearFactor(Prim.PhysBody, BSParam.VehicleLinearFactor); | 601 | m_physicsScene.PE.SetLinearFactor(ControllingPrim.PhysBody, BSParam.VehicleLinearFactor); |
611 | PhysicsScene.PE.SetAngularFactorV(Prim.PhysBody, BSParam.VehicleAngularFactor); | 602 | m_physicsScene.PE.SetAngularFactorV(ControllingPrim.PhysBody, BSParam.VehicleAngularFactor); |
612 | 603 | ||
613 | // Vehicles report collision events so we know when it's on the ground | 604 | // Vehicles report collision events so we know when it's on the ground |
614 | PhysicsScene.PE.AddToCollisionFlags(Prim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); | 605 | // m_physicsScene.PE.AddToCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); |
606 | ControllingPrim.Linkset.AddToPhysicalCollisionFlags(CollisionFlags.BS_VEHICLE_COLLISIONS); | ||
615 | 607 | ||
616 | Prim.Inertia = PhysicsScene.PE.CalculateLocalInertia(Prim.PhysShape, m_vehicleMass); | 608 | // Vector3 inertia = m_physicsScene.PE.CalculateLocalInertia(ControllingPrim.PhysShape.physShapeInfo, m_vehicleMass); |
617 | PhysicsScene.PE.SetMassProps(Prim.PhysBody, m_vehicleMass, Prim.Inertia); | 609 | // ControllingPrim.Inertia = inertia * BSParam.VehicleInertiaFactor; |
618 | PhysicsScene.PE.UpdateInertiaTensor(Prim.PhysBody); | 610 | // m_physicsScene.PE.SetMassProps(ControllingPrim.PhysBody, m_vehicleMass, ControllingPrim.Inertia); |
611 | // m_physicsScene.PE.UpdateInertiaTensor(ControllingPrim.PhysBody); | ||
612 | ControllingPrim.Linkset.ComputeAndSetLocalInertia(BSParam.VehicleInertiaFactor, m_vehicleMass); | ||
619 | 613 | ||
620 | // Set the gravity for the vehicle depending on the buoyancy | 614 | // Set the gravity for the vehicle depending on the buoyancy |
621 | // TODO: what should be done if prim and vehicle buoyancy differ? | 615 | // TODO: what should be done if prim and vehicle buoyancy differ? |
622 | m_VehicleGravity = Prim.ComputeGravity(m_VehicleBuoyancy); | 616 | m_VehicleGravity = ControllingPrim.ComputeGravity(m_VehicleBuoyancy); |
623 | // The actual vehicle gravity is set to zero in Bullet so we can do all the application of same. | 617 | // The actual vehicle gravity is set to zero in Bullet so we can do all the application of same. |
624 | PhysicsScene.PE.SetGravity(Prim.PhysBody, Vector3.Zero); | 618 | // m_physicsScene.PE.SetGravity(ControllingPrim.PhysBody, Vector3.Zero); |
619 | ControllingPrim.Linkset.SetPhysicalGravity(Vector3.Zero); | ||
625 | 620 | ||
626 | VDetailLog("{0},BSDynamics.SetPhysicalParameters,mass={1},inert={2},vehGrav={3},aDamp={4},frict={5},rest={6},lFact={7},aFact={8}", | 621 | VDetailLog("{0},BSDynamics.SetPhysicalParameters,mass={1},inert={2},vehGrav={3},aDamp={4},frict={5},rest={6},lFact={7},aFact={8}", |
627 | Prim.LocalID, m_vehicleMass, Prim.Inertia, m_VehicleGravity, | 622 | ControllingPrim.LocalID, m_vehicleMass, ControllingPrim.Inertia, m_VehicleGravity, |
628 | BSParam.VehicleAngularDamping, BSParam.VehicleFriction, BSParam.VehicleRestitution, | 623 | BSParam.VehicleAngularDamping, BSParam.VehicleFriction, BSParam.VehicleRestitution, |
629 | BSParam.VehicleLinearFactor, BSParam.VehicleAngularFactor | 624 | BSParam.VehicleLinearFactor, BSParam.VehicleAngularFactor |
630 | ); | 625 | ); |
631 | } | 626 | } |
632 | else | 627 | else |
633 | { | 628 | { |
634 | if (Prim.PhysBody.HasPhysicalBody) | 629 | if (ControllingPrim.PhysBody.HasPhysicalBody) |
635 | PhysicsScene.PE.RemoveFromCollisionFlags(Prim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); | 630 | m_physicsScene.PE.RemoveFromCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); |
631 | // ControllingPrim.Linkset.RemoveFromPhysicalCollisionFlags(CollisionFlags.BS_VEHICLE_COLLISIONS); | ||
636 | } | 632 | } |
637 | } | 633 | } |
638 | 634 | ||
639 | public bool RemoveBodyDependencies(BSPhysObject prim) | 635 | // BSActor.RemoveBodyDependencies |
636 | public override void RemoveDependencies() | ||
640 | { | 637 | { |
641 | Refresh(); | 638 | Refresh(); |
642 | return IsActive; | 639 | } |
640 | |||
641 | // BSActor.Release() | ||
642 | public override void Dispose() | ||
643 | { | ||
644 | VDetailLog("{0},Dispose", ControllingPrim.LocalID); | ||
645 | UnregisterForSceneEvents(); | ||
646 | Type = Vehicle.TYPE_NONE; | ||
647 | Enabled = false; | ||
648 | return; | ||
649 | } | ||
650 | |||
651 | private void RegisterForSceneEvents() | ||
652 | { | ||
653 | if (!m_haveRegisteredForSceneEvents) | ||
654 | { | ||
655 | m_physicsScene.BeforeStep += this.Step; | ||
656 | m_physicsScene.AfterStep += this.PostStep; | ||
657 | ControllingPrim.OnPreUpdateProperty += this.PreUpdateProperty; | ||
658 | m_haveRegisteredForSceneEvents = true; | ||
659 | } | ||
660 | } | ||
661 | |||
662 | private void UnregisterForSceneEvents() | ||
663 | { | ||
664 | if (m_haveRegisteredForSceneEvents) | ||
665 | { | ||
666 | m_physicsScene.BeforeStep -= this.Step; | ||
667 | m_physicsScene.AfterStep -= this.PostStep; | ||
668 | ControllingPrim.OnPreUpdateProperty -= this.PreUpdateProperty; | ||
669 | m_haveRegisteredForSceneEvents = false; | ||
670 | } | ||
671 | } | ||
672 | |||
673 | private void PreUpdateProperty(ref EntityProperties entprop) | ||
674 | { | ||
675 | // A temporary kludge to suppress the rotational effects introduced on vehicles by Bullet | ||
676 | // TODO: handle physics introduced by Bullet with computed vehicle physics. | ||
677 | if (IsActive) | ||
678 | { | ||
679 | entprop.RotationalVelocity = Vector3.Zero; | ||
680 | } | ||
643 | } | 681 | } |
644 | 682 | ||
645 | #region Known vehicle value functions | 683 | #region Known vehicle value functions |
@@ -661,7 +699,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
661 | private Vector3 m_knownRotationalVelocity; | 699 | private Vector3 m_knownRotationalVelocity; |
662 | private Vector3 m_knownRotationalForce; | 700 | private Vector3 m_knownRotationalForce; |
663 | private Vector3 m_knownRotationalImpulse; | 701 | private Vector3 m_knownRotationalImpulse; |
664 | private Vector3 m_knownForwardVelocity; // vehicle relative forward speed | ||
665 | 702 | ||
666 | private const int m_knownChangedPosition = 1 << 0; | 703 | private const int m_knownChangedPosition = 1 << 0; |
667 | private const int m_knownChangedVelocity = 1 << 1; | 704 | private const int m_knownChangedVelocity = 1 << 1; |
@@ -673,7 +710,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
673 | private const int m_knownChangedRotationalImpulse = 1 << 7; | 710 | private const int m_knownChangedRotationalImpulse = 1 << 7; |
674 | private const int m_knownChangedTerrainHeight = 1 << 8; | 711 | private const int m_knownChangedTerrainHeight = 1 << 8; |
675 | private const int m_knownChangedWaterLevel = 1 << 9; | 712 | private const int m_knownChangedWaterLevel = 1 << 9; |
676 | private const int m_knownChangedForwardVelocity = 1 <<10; | ||
677 | 713 | ||
678 | public void ForgetKnownVehicleProperties() | 714 | public void ForgetKnownVehicleProperties() |
679 | { | 715 | { |
@@ -686,14 +722,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
686 | if (m_knownChanged != 0) | 722 | if (m_knownChanged != 0) |
687 | { | 723 | { |
688 | if ((m_knownChanged & m_knownChangedPosition) != 0) | 724 | if ((m_knownChanged & m_knownChangedPosition) != 0) |
689 | Prim.ForcePosition = m_knownPosition; | 725 | ControllingPrim.ForcePosition = m_knownPosition; |
690 | 726 | ||
691 | if ((m_knownChanged & m_knownChangedOrientation) != 0) | 727 | if ((m_knownChanged & m_knownChangedOrientation) != 0) |
692 | Prim.ForceOrientation = m_knownOrientation; | 728 | ControllingPrim.ForceOrientation = m_knownOrientation; |
693 | 729 | ||
694 | if ((m_knownChanged & m_knownChangedVelocity) != 0) | 730 | if ((m_knownChanged & m_knownChangedVelocity) != 0) |
695 | { | 731 | { |
696 | Prim.ForceVelocity = m_knownVelocity; | 732 | ControllingPrim.ForceVelocity = m_knownVelocity; |
697 | // Fake out Bullet by making it think the velocity is the same as last time. | 733 | // Fake out Bullet by making it think the velocity is the same as last time. |
698 | // Bullet does a bunch of smoothing for changing parameters. | 734 | // Bullet does a bunch of smoothing for changing parameters. |
699 | // Since the vehicle is demanding this setting, we override Bullet's smoothing | 735 | // Since the vehicle is demanding this setting, we override Bullet's smoothing |
@@ -702,41 +738,41 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
702 | } | 738 | } |
703 | 739 | ||
704 | if ((m_knownChanged & m_knownChangedForce) != 0) | 740 | if ((m_knownChanged & m_knownChangedForce) != 0) |
705 | Prim.AddForce((Vector3)m_knownForce, false /*pushForce*/, true /*inTaintTime*/); | 741 | ControllingPrim.AddForce((Vector3)m_knownForce, false /*pushForce*/, true /*inTaintTime*/); |
706 | 742 | ||
707 | if ((m_knownChanged & m_knownChangedForceImpulse) != 0) | 743 | if ((m_knownChanged & m_knownChangedForceImpulse) != 0) |
708 | Prim.AddForceImpulse((Vector3)m_knownForceImpulse, false /*pushforce*/, true /*inTaintTime*/); | 744 | ControllingPrim.AddForceImpulse((Vector3)m_knownForceImpulse, false /*pushforce*/, true /*inTaintTime*/); |
709 | 745 | ||
710 | if ((m_knownChanged & m_knownChangedRotationalVelocity) != 0) | 746 | if ((m_knownChanged & m_knownChangedRotationalVelocity) != 0) |
711 | { | 747 | { |
712 | Prim.ForceRotationalVelocity = m_knownRotationalVelocity; | 748 | ControllingPrim.ForceRotationalVelocity = m_knownRotationalVelocity; |
713 | // PhysicsScene.PE.SetInterpolationAngularVelocity(Prim.PhysBody, m_knownRotationalVelocity); | 749 | // PhysicsScene.PE.SetInterpolationAngularVelocity(Prim.PhysBody, m_knownRotationalVelocity); |
714 | } | 750 | } |
715 | 751 | ||
716 | if ((m_knownChanged & m_knownChangedRotationalImpulse) != 0) | 752 | if ((m_knownChanged & m_knownChangedRotationalImpulse) != 0) |
717 | Prim.ApplyTorqueImpulse((Vector3)m_knownRotationalImpulse, true /*inTaintTime*/); | 753 | ControllingPrim.ApplyTorqueImpulse((Vector3)m_knownRotationalImpulse, true /*inTaintTime*/); |
718 | 754 | ||
719 | if ((m_knownChanged & m_knownChangedRotationalForce) != 0) | 755 | if ((m_knownChanged & m_knownChangedRotationalForce) != 0) |
720 | { | 756 | { |
721 | Prim.AddAngularForce((Vector3)m_knownRotationalForce, false /*pushForce*/, true /*inTaintTime*/); | 757 | ControllingPrim.AddAngularForce((Vector3)m_knownRotationalForce, false /*pushForce*/, true /*inTaintTime*/); |
722 | } | 758 | } |
723 | 759 | ||
724 | // If we set one of the values (ie, the physics engine didn't do it) we must force | 760 | // If we set one of the values (ie, the physics engine didn't do it) we must force |
725 | // an UpdateProperties event to send the changes up to the simulator. | 761 | // an UpdateProperties event to send the changes up to the simulator. |
726 | PhysicsScene.PE.PushUpdate(Prim.PhysBody); | 762 | m_physicsScene.PE.PushUpdate(ControllingPrim.PhysBody); |
727 | } | 763 | } |
728 | m_knownChanged = 0; | 764 | m_knownChanged = 0; |
729 | } | 765 | } |
730 | 766 | ||
731 | // Since the computation of terrain height can be a little involved, this routine | 767 | // Since the computation of terrain height can be a little involved, this routine |
732 | // is used to fetch the height only once for each vehicle simulation step. | 768 | // is used to fetch the height only once for each vehicle simulation step. |
733 | Vector3 lastRememberedHeightPos; | 769 | Vector3 lastRememberedHeightPos = new Vector3(-1, -1, -1); |
734 | private float GetTerrainHeight(Vector3 pos) | 770 | private float GetTerrainHeight(Vector3 pos) |
735 | { | 771 | { |
736 | if ((m_knownHas & m_knownChangedTerrainHeight) == 0 || pos != lastRememberedHeightPos) | 772 | if ((m_knownHas & m_knownChangedTerrainHeight) == 0 || pos != lastRememberedHeightPos) |
737 | { | 773 | { |
738 | lastRememberedHeightPos = pos; | 774 | lastRememberedHeightPos = pos; |
739 | m_knownTerrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos); | 775 | m_knownTerrainHeight = ControllingPrim.PhysScene.TerrainManager.GetTerrainHeightAtXYZ(pos); |
740 | m_knownHas |= m_knownChangedTerrainHeight; | 776 | m_knownHas |= m_knownChangedTerrainHeight; |
741 | } | 777 | } |
742 | return m_knownTerrainHeight; | 778 | return m_knownTerrainHeight; |
@@ -744,14 +780,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
744 | 780 | ||
745 | // Since the computation of water level can be a little involved, this routine | 781 | // Since the computation of water level can be a little involved, this routine |
746 | // is used ot fetch the level only once for each vehicle simulation step. | 782 | // is used ot fetch the level only once for each vehicle simulation step. |
783 | Vector3 lastRememberedWaterHeightPos = new Vector3(-1, -1, -1); | ||
747 | private float GetWaterLevel(Vector3 pos) | 784 | private float GetWaterLevel(Vector3 pos) |
748 | { | 785 | { |
749 | if ((m_knownHas & m_knownChangedWaterLevel) == 0) | 786 | if ((m_knownHas & m_knownChangedWaterLevel) == 0 || pos != lastRememberedWaterHeightPos) |
750 | { | 787 | { |
751 | m_knownWaterLevel = Prim.PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(pos); | 788 | lastRememberedWaterHeightPos = pos; |
789 | m_knownWaterLevel = ControllingPrim.PhysScene.TerrainManager.GetWaterLevelAtXYZ(pos); | ||
752 | m_knownHas |= m_knownChangedWaterLevel; | 790 | m_knownHas |= m_knownChangedWaterLevel; |
753 | } | 791 | } |
754 | return (float)m_knownWaterLevel; | 792 | return m_knownWaterLevel; |
755 | } | 793 | } |
756 | 794 | ||
757 | private Vector3 VehiclePosition | 795 | private Vector3 VehiclePosition |
@@ -760,7 +798,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
760 | { | 798 | { |
761 | if ((m_knownHas & m_knownChangedPosition) == 0) | 799 | if ((m_knownHas & m_knownChangedPosition) == 0) |
762 | { | 800 | { |
763 | m_knownPosition = Prim.ForcePosition; | 801 | m_knownPosition = ControllingPrim.ForcePosition; |
764 | m_knownHas |= m_knownChangedPosition; | 802 | m_knownHas |= m_knownChangedPosition; |
765 | } | 803 | } |
766 | return m_knownPosition; | 804 | return m_knownPosition; |
@@ -779,7 +817,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
779 | { | 817 | { |
780 | if ((m_knownHas & m_knownChangedOrientation) == 0) | 818 | if ((m_knownHas & m_knownChangedOrientation) == 0) |
781 | { | 819 | { |
782 | m_knownOrientation = Prim.ForceOrientation; | 820 | m_knownOrientation = ControllingPrim.ForceOrientation; |
783 | m_knownHas |= m_knownChangedOrientation; | 821 | m_knownHas |= m_knownChangedOrientation; |
784 | } | 822 | } |
785 | return m_knownOrientation; | 823 | return m_knownOrientation; |
@@ -798,7 +836,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
798 | { | 836 | { |
799 | if ((m_knownHas & m_knownChangedVelocity) == 0) | 837 | if ((m_knownHas & m_knownChangedVelocity) == 0) |
800 | { | 838 | { |
801 | m_knownVelocity = Prim.ForceVelocity; | 839 | m_knownVelocity = ControllingPrim.ForceVelocity; |
802 | m_knownHas |= m_knownChangedVelocity; | 840 | m_knownHas |= m_knownChangedVelocity; |
803 | } | 841 | } |
804 | return m_knownVelocity; | 842 | return m_knownVelocity; |
@@ -839,7 +877,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
839 | { | 877 | { |
840 | if ((m_knownHas & m_knownChangedRotationalVelocity) == 0) | 878 | if ((m_knownHas & m_knownChangedRotationalVelocity) == 0) |
841 | { | 879 | { |
842 | m_knownRotationalVelocity = Prim.ForceRotationalVelocity; | 880 | m_knownRotationalVelocity = ControllingPrim.ForceRotationalVelocity; |
843 | m_knownHas |= m_knownChangedRotationalVelocity; | 881 | m_knownHas |= m_knownChangedRotationalVelocity; |
844 | } | 882 | } |
845 | return (Vector3)m_knownRotationalVelocity; | 883 | return (Vector3)m_knownRotationalVelocity; |
@@ -877,14 +915,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
877 | { | 915 | { |
878 | get | 916 | get |
879 | { | 917 | { |
880 | if ((m_knownHas & m_knownChangedForwardVelocity) == 0) | 918 | return VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleOrientation)); |
881 | { | ||
882 | m_knownForwardVelocity = VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleOrientation)); | ||
883 | m_knownHas |= m_knownChangedForwardVelocity; | ||
884 | } | ||
885 | return m_knownForwardVelocity; | ||
886 | } | 919 | } |
887 | } | 920 | } |
921 | |||
888 | private float VehicleForwardSpeed | 922 | private float VehicleForwardSpeed |
889 | { | 923 | { |
890 | get | 924 | get |
@@ -914,11 +948,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
914 | // for the physics engine to note the changes so an UpdateProperties event will happen. | 948 | // for the physics engine to note the changes so an UpdateProperties event will happen. |
915 | PushKnownChanged(); | 949 | PushKnownChanged(); |
916 | 950 | ||
917 | if (PhysicsScene.VehiclePhysicalLoggingEnabled) | 951 | if (m_physicsScene.VehiclePhysicalLoggingEnabled) |
918 | PhysicsScene.PE.DumpRigidBody(PhysicsScene.World, Prim.PhysBody); | 952 | m_physicsScene.PE.DumpRigidBody(m_physicsScene.World, ControllingPrim.PhysBody); |
919 | 953 | ||
920 | VDetailLog("{0},BSDynamics.Step,done,pos={1}, force={2},velocity={3},angvel={4}", | 954 | VDetailLog("{0},BSDynamics.Step,done,pos={1}, force={2},velocity={3},angvel={4}", |
921 | Prim.LocalID, VehiclePosition, m_knownForce, VehicleVelocity, VehicleRotationalVelocity); | 955 | ControllingPrim.LocalID, VehiclePosition, m_knownForce, VehicleVelocity, VehicleRotationalVelocity); |
922 | } | 956 | } |
923 | 957 | ||
924 | // Called after the simulation step | 958 | // Called after the simulation step |
@@ -926,8 +960,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
926 | { | 960 | { |
927 | if (!IsActive) return; | 961 | if (!IsActive) return; |
928 | 962 | ||
929 | if (PhysicsScene.VehiclePhysicalLoggingEnabled) | 963 | if (m_physicsScene.VehiclePhysicalLoggingEnabled) |
930 | PhysicsScene.PE.DumpRigidBody(PhysicsScene.World, Prim.PhysBody); | 964 | m_physicsScene.PE.DumpRigidBody(m_physicsScene.World, ControllingPrim.PhysBody); |
931 | } | 965 | } |
932 | 966 | ||
933 | // Apply the effect of the linear motor and other linear motions (like hover and float). | 967 | // Apply the effect of the linear motor and other linear motions (like hover and float). |
@@ -935,6 +969,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
935 | { | 969 | { |
936 | ComputeLinearVelocity(pTimestep); | 970 | ComputeLinearVelocity(pTimestep); |
937 | 971 | ||
972 | ComputeLinearDeflection(pTimestep); | ||
973 | |||
938 | ComputeLinearTerrainHeightCorrection(pTimestep); | 974 | ComputeLinearTerrainHeightCorrection(pTimestep); |
939 | 975 | ||
940 | ComputeLinearHover(pTimestep); | 976 | ComputeLinearHover(pTimestep); |
@@ -950,11 +986,17 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
950 | { | 986 | { |
951 | Vector3 vel = VehicleVelocity; | 987 | Vector3 vel = VehicleVelocity; |
952 | if ((m_flags & (VehicleFlag.NO_X)) != 0) | 988 | if ((m_flags & (VehicleFlag.NO_X)) != 0) |
989 | { | ||
953 | vel.X = 0; | 990 | vel.X = 0; |
991 | } | ||
954 | if ((m_flags & (VehicleFlag.NO_Y)) != 0) | 992 | if ((m_flags & (VehicleFlag.NO_Y)) != 0) |
993 | { | ||
955 | vel.Y = 0; | 994 | vel.Y = 0; |
995 | } | ||
956 | if ((m_flags & (VehicleFlag.NO_Z)) != 0) | 996 | if ((m_flags & (VehicleFlag.NO_Z)) != 0) |
997 | { | ||
957 | vel.Z = 0; | 998 | vel.Z = 0; |
999 | } | ||
958 | VehicleVelocity = vel; | 1000 | VehicleVelocity = vel; |
959 | } | 1001 | } |
960 | 1002 | ||
@@ -966,13 +1008,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
966 | Vector3 origVelW = VehicleVelocity; // DEBUG DEBUG | 1008 | Vector3 origVelW = VehicleVelocity; // DEBUG DEBUG |
967 | VehicleVelocity /= VehicleVelocity.Length(); | 1009 | VehicleVelocity /= VehicleVelocity.Length(); |
968 | VehicleVelocity *= BSParam.VehicleMaxLinearVelocity; | 1010 | VehicleVelocity *= BSParam.VehicleMaxLinearVelocity; |
969 | VDetailLog("{0}, MoveLinear,clampMax,origVelW={1},lenSq={2},maxVelSq={3},,newVelW={4}", | 1011 | VDetailLog("{0}, MoveLinear,clampMax,origVelW={1},lenSq={2},maxVelSq={3},,newVelW={4}", |
970 | Prim.LocalID, origVelW, newVelocityLengthSq, BSParam.VehicleMaxLinearVelocitySquared, VehicleVelocity); | 1012 | ControllingPrim.LocalID, origVelW, newVelocityLengthSq, BSParam.VehicleMaxLinearVelocitySquared, VehicleVelocity); |
971 | } | 1013 | } |
972 | else if (newVelocityLengthSq < 0.001f) | 1014 | else if (newVelocityLengthSq < 0.001f) |
973 | VehicleVelocity = Vector3.Zero; | 1015 | VehicleVelocity = Vector3.Zero; |
974 | 1016 | ||
975 | VDetailLog("{0}, MoveLinear,done,isColl={1},newVel={2}", Prim.LocalID, Prim.IsColliding, VehicleVelocity ); | 1017 | VDetailLog("{0}, MoveLinear,done,isColl={1},newVel={2}", ControllingPrim.LocalID, ControllingPrim.HasSomeCollision, VehicleVelocity ); |
976 | 1018 | ||
977 | } // end MoveLinear() | 1019 | } // end MoveLinear() |
978 | 1020 | ||
@@ -980,9 +1022,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
980 | { | 1022 | { |
981 | // Step the motor from the current value. Get the correction needed this step. | 1023 | // Step the motor from the current value. Get the correction needed this step. |
982 | Vector3 origVelW = VehicleVelocity; // DEBUG | 1024 | Vector3 origVelW = VehicleVelocity; // DEBUG |
983 | Vector3 currentVelV = VehicleVelocity * Quaternion.Inverse(VehicleOrientation); | 1025 | Vector3 currentVelV = VehicleForwardVelocity; |
984 | Vector3 linearMotorCorrectionV = m_linearMotor.Step(pTimestep, currentVelV); | 1026 | Vector3 linearMotorCorrectionV = m_linearMotor.Step(pTimestep, currentVelV); |
985 | 1027 | ||
1028 | // Friction reduces vehicle motion based on absolute speed. Slow vehicle down by friction. | ||
1029 | Vector3 frictionFactorV = ComputeFrictionFactor(m_linearFrictionTimescale, pTimestep); | ||
1030 | linearMotorCorrectionV -= (currentVelV * frictionFactorV); | ||
1031 | |||
986 | // Motor is vehicle coordinates. Rotate it to world coordinates | 1032 | // Motor is vehicle coordinates. Rotate it to world coordinates |
987 | Vector3 linearMotorVelocityW = linearMotorCorrectionV * VehicleOrientation; | 1033 | Vector3 linearMotorVelocityW = linearMotorCorrectionV * VehicleOrientation; |
988 | 1034 | ||
@@ -996,8 +1042,49 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
996 | // Add this correction to the velocity to make it faster/slower. | 1042 | // Add this correction to the velocity to make it faster/slower. |
997 | VehicleVelocity += linearMotorVelocityW; | 1043 | VehicleVelocity += linearMotorVelocityW; |
998 | 1044 | ||
999 | VDetailLog("{0}, MoveLinear,velocity,origVelW={1},velV={2},correctV={3},correctW={4},newVelW={5}", | 1045 | VDetailLog("{0}, MoveLinear,velocity,origVelW={1},velV={2},tgt={3},correctV={4},correctW={5},newVelW={6},fricFact={7}", |
1000 | Prim.LocalID, origVelW, currentVelV, linearMotorCorrectionV, linearMotorVelocityW, VehicleVelocity); | 1046 | ControllingPrim.LocalID, origVelW, currentVelV, m_linearMotor.TargetValue, linearMotorCorrectionV, |
1047 | linearMotorVelocityW, VehicleVelocity, frictionFactorV); | ||
1048 | } | ||
1049 | |||
1050 | //Given a Deflection Effiency and a Velocity, Returns a Velocity that is Partially Deflected onto the X Axis | ||
1051 | //Clamped so that a DeflectionTimescale of less then 1 does not increase force over original velocity | ||
1052 | private void ComputeLinearDeflection(float pTimestep) | ||
1053 | { | ||
1054 | Vector3 linearDeflectionV = Vector3.Zero; | ||
1055 | Vector3 velocityV = VehicleForwardVelocity; | ||
1056 | |||
1057 | if (BSParam.VehicleEnableLinearDeflection) | ||
1058 | { | ||
1059 | // Velocity in Y and Z dimensions is movement to the side or turning. | ||
1060 | // Compute deflection factor from the to the side and rotational velocity | ||
1061 | linearDeflectionV.Y = SortedClampInRange(0, (velocityV.Y * m_linearDeflectionEfficiency) / m_linearDeflectionTimescale, velocityV.Y); | ||
1062 | linearDeflectionV.Z = SortedClampInRange(0, (velocityV.Z * m_linearDeflectionEfficiency) / m_linearDeflectionTimescale, velocityV.Z); | ||
1063 | |||
1064 | // Velocity to the side and around is corrected and moved into the forward direction | ||
1065 | linearDeflectionV.X += Math.Abs(linearDeflectionV.Y); | ||
1066 | linearDeflectionV.X += Math.Abs(linearDeflectionV.Z); | ||
1067 | |||
1068 | // Scale the deflection to the fractional simulation time | ||
1069 | linearDeflectionV *= pTimestep; | ||
1070 | |||
1071 | // Subtract the sideways and rotational velocity deflection factors while adding the correction forward | ||
1072 | linearDeflectionV *= new Vector3(1, -1, -1); | ||
1073 | |||
1074 | // Correction is vehicle relative. Convert to world coordinates. | ||
1075 | Vector3 linearDeflectionW = linearDeflectionV * VehicleOrientation; | ||
1076 | |||
1077 | // Optionally, if not colliding, don't effect world downward velocity. Let falling things fall. | ||
1078 | if (BSParam.VehicleLinearDeflectionNotCollidingNoZ && !m_controllingPrim.HasSomeCollision) | ||
1079 | { | ||
1080 | linearDeflectionW.Z = 0f; | ||
1081 | } | ||
1082 | |||
1083 | VehicleVelocity += linearDeflectionW; | ||
1084 | |||
1085 | VDetailLog("{0}, MoveLinear,LinearDeflection,linDefEff={1},linDefTS={2},linDeflectionV={3}", | ||
1086 | ControllingPrim.LocalID, m_linearDeflectionEfficiency, m_linearDeflectionTimescale, linearDeflectionV); | ||
1087 | } | ||
1001 | } | 1088 | } |
1002 | 1089 | ||
1003 | public void ComputeLinearTerrainHeightCorrection(float pTimestep) | 1090 | public void ComputeLinearTerrainHeightCorrection(float pTimestep) |
@@ -1011,7 +1098,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1011 | newPosition.Z = GetTerrainHeight(VehiclePosition) + 1f; | 1098 | newPosition.Z = GetTerrainHeight(VehiclePosition) + 1f; |
1012 | VehiclePosition = newPosition; | 1099 | VehiclePosition = newPosition; |
1013 | VDetailLog("{0}, MoveLinear,terrainHeight,terrainHeight={1},pos={2}", | 1100 | VDetailLog("{0}, MoveLinear,terrainHeight,terrainHeight={1},pos={2}", |
1014 | Prim.LocalID, GetTerrainHeight(VehiclePosition), VehiclePosition); | 1101 | ControllingPrim.LocalID, GetTerrainHeight(VehiclePosition), VehiclePosition); |
1015 | } | 1102 | } |
1016 | } | 1103 | } |
1017 | 1104 | ||
@@ -1034,14 +1121,25 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1034 | { | 1121 | { |
1035 | m_VhoverTargetHeight = m_VhoverHeight; | 1122 | m_VhoverTargetHeight = m_VhoverHeight; |
1036 | } | 1123 | } |
1037 | |||
1038 | if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0) | 1124 | if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0) |
1039 | { | 1125 | { |
1040 | // If body is already heigher, use its height as target height | 1126 | // If body is already heigher, use its height as target height |
1041 | if (VehiclePosition.Z > m_VhoverTargetHeight) | 1127 | if (VehiclePosition.Z > m_VhoverTargetHeight) |
1128 | { | ||
1042 | m_VhoverTargetHeight = VehiclePosition.Z; | 1129 | m_VhoverTargetHeight = VehiclePosition.Z; |
1130 | |||
1131 | // A 'misfeature' of this flag is that if the vehicle is above it's hover height, | ||
1132 | // the vehicle's buoyancy goes away. This is an SL bug that got used by so many | ||
1133 | // scripts that it could not be changed. | ||
1134 | // So, if above the height, reapply gravity if buoyancy had it turned off. | ||
1135 | if (m_VehicleBuoyancy != 0) | ||
1136 | { | ||
1137 | Vector3 appliedGravity = ControllingPrim.ComputeGravity(ControllingPrim.Buoyancy) * m_vehicleMass; | ||
1138 | VehicleAddForce(appliedGravity); | ||
1139 | } | ||
1140 | } | ||
1043 | } | 1141 | } |
1044 | 1142 | ||
1045 | if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) | 1143 | if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) |
1046 | { | 1144 | { |
1047 | if (Math.Abs(VehiclePosition.Z - m_VhoverTargetHeight) > 0.2f) | 1145 | if (Math.Abs(VehiclePosition.Z - m_VhoverTargetHeight) > 0.2f) |
@@ -1050,7 +1148,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1050 | pos.Z = m_VhoverTargetHeight; | 1148 | pos.Z = m_VhoverTargetHeight; |
1051 | VehiclePosition = pos; | 1149 | VehiclePosition = pos; |
1052 | 1150 | ||
1053 | VDetailLog("{0}, MoveLinear,hover,pos={1},lockHoverHeight", Prim.LocalID, pos); | 1151 | VDetailLog("{0}, MoveLinear,hover,pos={1},lockHoverHeight", ControllingPrim.LocalID, pos); |
1054 | } | 1152 | } |
1055 | } | 1153 | } |
1056 | else | 1154 | else |
@@ -1079,11 +1177,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1079 | */ | 1177 | */ |
1080 | 1178 | ||
1081 | VDetailLog("{0}, MoveLinear,hover,pos={1},eff={2},hoverTS={3},height={4},target={5},err={6},corr={7}", | 1179 | VDetailLog("{0}, MoveLinear,hover,pos={1},eff={2},hoverTS={3},height={4},target={5},err={6},corr={7}", |
1082 | Prim.LocalID, VehiclePosition, m_VhoverEfficiency, | 1180 | ControllingPrim.LocalID, VehiclePosition, m_VhoverEfficiency, |
1083 | m_VhoverTimescale, m_VhoverHeight, m_VhoverTargetHeight, | 1181 | m_VhoverTimescale, m_VhoverHeight, m_VhoverTargetHeight, |
1084 | verticalError, verticalCorrection); | 1182 | verticalError, verticalCorrection); |
1085 | } | 1183 | } |
1086 | |||
1087 | } | 1184 | } |
1088 | } | 1185 | } |
1089 | 1186 | ||
@@ -1124,7 +1221,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1124 | { | 1221 | { |
1125 | VehiclePosition = pos; | 1222 | VehiclePosition = pos; |
1126 | VDetailLog("{0}, MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", | 1223 | VDetailLog("{0}, MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", |
1127 | Prim.LocalID, m_BlockingEndPoint, posChange, pos); | 1224 | ControllingPrim.LocalID, m_BlockingEndPoint, posChange, pos); |
1128 | } | 1225 | } |
1129 | } | 1226 | } |
1130 | return changed; | 1227 | return changed; |
@@ -1135,7 +1232,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1135 | // used with conjunction with banking: the strength of the banking will decay when the | 1232 | // used with conjunction with banking: the strength of the banking will decay when the |
1136 | // vehicle no longer experiences collisions. The decay timescale is the same as | 1233 | // vehicle no longer experiences collisions. The decay timescale is the same as |
1137 | // VEHICLE_BANKING_TIMESCALE. This is to help prevent ground vehicles from steering | 1234 | // VEHICLE_BANKING_TIMESCALE. This is to help prevent ground vehicles from steering |
1138 | // when they are in mid jump. | 1235 | // when they are in mid jump. |
1139 | // TODO: this code is wrong. Also, what should it do for boats (height from water)? | 1236 | // TODO: this code is wrong. Also, what should it do for boats (height from water)? |
1140 | // This is just using the ground and a general collision check. Should really be using | 1237 | // This is just using the ground and a general collision check. Should really be using |
1141 | // a downward raycast to find what is below. | 1238 | // a downward raycast to find what is below. |
@@ -1148,7 +1245,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1148 | float targetHeight = Type == Vehicle.TYPE_BOAT ? GetWaterLevel(VehiclePosition) : GetTerrainHeight(VehiclePosition); | 1245 | float targetHeight = Type == Vehicle.TYPE_BOAT ? GetWaterLevel(VehiclePosition) : GetTerrainHeight(VehiclePosition); |
1149 | distanceAboveGround = VehiclePosition.Z - targetHeight; | 1246 | distanceAboveGround = VehiclePosition.Z - targetHeight; |
1150 | // Not colliding if the vehicle is off the ground | 1247 | // Not colliding if the vehicle is off the ground |
1151 | if (!Prim.IsColliding) | 1248 | if (!Prim.HasSomeCollision) |
1152 | { | 1249 | { |
1153 | // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale); | 1250 | // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale); |
1154 | VehicleVelocity += new Vector3(0, 0, -distanceAboveGround); | 1251 | VehicleVelocity += new Vector3(0, 0, -distanceAboveGround); |
@@ -1159,12 +1256,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1159 | // be computed with a motor. | 1256 | // be computed with a motor. |
1160 | // TODO: add interaction with banking. | 1257 | // TODO: add interaction with banking. |
1161 | VDetailLog("{0}, MoveLinear,limitMotorUp,distAbove={1},colliding={2},ret={3}", | 1258 | VDetailLog("{0}, MoveLinear,limitMotorUp,distAbove={1},colliding={2},ret={3}", |
1162 | Prim.LocalID, distanceAboveGround, Prim.IsColliding, ret); | 1259 | Prim.LocalID, distanceAboveGround, Prim.HasSomeCollision, ret); |
1163 | */ | 1260 | */ |
1164 | 1261 | ||
1165 | // Another approach is to measure if we're going up. If going up and not colliding, | 1262 | // Another approach is to measure if we're going up. If going up and not colliding, |
1166 | // the vehicle is in the air. Fix that by pushing down. | 1263 | // the vehicle is in the air. Fix that by pushing down. |
1167 | if (!Prim.IsColliding && VehicleVelocity.Z > 0.1) | 1264 | if (!ControllingPrim.HasSomeCollision && VehicleVelocity.Z > 0.1) |
1168 | { | 1265 | { |
1169 | // Get rid of any of the velocity vector that is pushing us up. | 1266 | // Get rid of any of the velocity vector that is pushing us up. |
1170 | float upVelocity = VehicleVelocity.Z; | 1267 | float upVelocity = VehicleVelocity.Z; |
@@ -1186,7 +1283,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1186 | } | 1283 | } |
1187 | */ | 1284 | */ |
1188 | VDetailLog("{0}, MoveLinear,limitMotorUp,collide={1},upVel={2},newVel={3}", | 1285 | VDetailLog("{0}, MoveLinear,limitMotorUp,collide={1},upVel={2},newVel={3}", |
1189 | Prim.LocalID, Prim.IsColliding, upVelocity, VehicleVelocity); | 1286 | ControllingPrim.LocalID, ControllingPrim.HasSomeCollision, upVelocity, VehicleVelocity); |
1190 | } | 1287 | } |
1191 | } | 1288 | } |
1192 | } | 1289 | } |
@@ -1196,14 +1293,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1196 | Vector3 appliedGravity = m_VehicleGravity * m_vehicleMass; | 1293 | Vector3 appliedGravity = m_VehicleGravity * m_vehicleMass; |
1197 | 1294 | ||
1198 | // Hack to reduce downward force if the vehicle is probably sitting on the ground | 1295 | // Hack to reduce downward force if the vehicle is probably sitting on the ground |
1199 | if (Prim.IsColliding && IsGroundVehicle) | 1296 | if (ControllingPrim.HasSomeCollision && IsGroundVehicle) |
1200 | appliedGravity *= BSParam.VehicleGroundGravityFudge; | 1297 | appliedGravity *= BSParam.VehicleGroundGravityFudge; |
1201 | 1298 | ||
1202 | VehicleAddForce(appliedGravity); | 1299 | VehicleAddForce(appliedGravity); |
1203 | 1300 | ||
1204 | VDetailLog("{0}, MoveLinear,applyGravity,vehGrav={1},collid={2},fudge={3},mass={4},appliedForce={3}", | 1301 | VDetailLog("{0}, MoveLinear,applyGravity,vehGrav={1},collid={2},fudge={3},mass={4},appliedForce={5}", |
1205 | Prim.LocalID, m_VehicleGravity, | 1302 | ControllingPrim.LocalID, m_VehicleGravity, |
1206 | Prim.IsColliding, BSParam.VehicleGroundGravityFudge, m_vehicleMass, appliedGravity); | 1303 | ControllingPrim.HasSomeCollision, BSParam.VehicleGroundGravityFudge, m_vehicleMass, appliedGravity); |
1207 | } | 1304 | } |
1208 | 1305 | ||
1209 | // ======================================================================= | 1306 | // ======================================================================= |
@@ -1227,11 +1324,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1227 | { | 1324 | { |
1228 | // The vehicle is not adding anything angular wise. | 1325 | // The vehicle is not adding anything angular wise. |
1229 | VehicleRotationalVelocity = Vector3.Zero; | 1326 | VehicleRotationalVelocity = Vector3.Zero; |
1230 | VDetailLog("{0}, MoveAngular,done,zero", Prim.LocalID); | 1327 | VDetailLog("{0}, MoveAngular,done,zero", ControllingPrim.LocalID); |
1231 | } | 1328 | } |
1232 | else | 1329 | else |
1233 | { | 1330 | { |
1234 | VDetailLog("{0}, MoveAngular,done,nonZero,angVel={1}", Prim.LocalID, VehicleRotationalVelocity); | 1331 | VDetailLog("{0}, MoveAngular,done,nonZero,angVel={1}", ControllingPrim.LocalID, VehicleRotationalVelocity); |
1235 | } | 1332 | } |
1236 | 1333 | ||
1237 | // ================================================================== | 1334 | // ================================================================== |
@@ -1262,7 +1359,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1262 | torqueFromOffset.Z = 0; | 1359 | torqueFromOffset.Z = 0; |
1263 | 1360 | ||
1264 | VehicleAddAngularForce(torqueFromOffset * m_vehicleMass); | 1361 | VehicleAddAngularForce(torqueFromOffset * m_vehicleMass); |
1265 | VDetailLog("{0}, BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", Prim.LocalID, torqueFromOffset); | 1362 | VDetailLog("{0}, BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", ControllingPrim.LocalID, torqueFromOffset); |
1266 | } | 1363 | } |
1267 | 1364 | ||
1268 | } | 1365 | } |
@@ -1270,6 +1367,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1270 | private void ComputeAngularTurning(float pTimestep) | 1367 | private void ComputeAngularTurning(float pTimestep) |
1271 | { | 1368 | { |
1272 | // The user wants this many radians per second angular change? | 1369 | // The user wants this many radians per second angular change? |
1370 | Vector3 origVehicleRotationalVelocity = VehicleRotationalVelocity; // DEBUG DEBUG | ||
1273 | Vector3 currentAngularV = VehicleRotationalVelocity * Quaternion.Inverse(VehicleOrientation); | 1371 | Vector3 currentAngularV = VehicleRotationalVelocity * Quaternion.Inverse(VehicleOrientation); |
1274 | Vector3 angularMotorContributionV = m_angularMotor.Step(pTimestep, currentAngularV); | 1372 | Vector3 angularMotorContributionV = m_angularMotor.Step(pTimestep, currentAngularV); |
1275 | 1373 | ||
@@ -1277,18 +1375,25 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1277 | // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags : | 1375 | // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags : |
1278 | // This flag prevents linear deflection parallel to world z-axis. This is useful | 1376 | // This flag prevents linear deflection parallel to world z-axis. This is useful |
1279 | // for preventing ground vehicles with large linear deflection, like bumper cars, | 1377 | // for preventing ground vehicles with large linear deflection, like bumper cars, |
1280 | // from climbing their linear deflection into the sky. | 1378 | // from climbing their linear deflection into the sky. |
1281 | // That is, NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement | 1379 | // That is, NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement |
1282 | // TODO: This is here because this is where ODE put it but documentation says it | 1380 | // TODO: This is here because this is where ODE put it but documentation says it |
1283 | // is a linear effect. Where should this check go? | 1381 | // is a linear effect. Where should this check go? |
1284 | //if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) | 1382 | //if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) |
1285 | // { | 1383 | // { |
1286 | // angularMotorContributionV.X = 0f; | 1384 | // angularMotorContributionV.X = 0f; |
1287 | // angularMotorContributionV.Y = 0f; | 1385 | // angularMotorContributionV.Y = 0f; |
1288 | // } | 1386 | // } |
1387 | |||
1388 | // Reduce any velocity by friction. | ||
1389 | Vector3 frictionFactorW = ComputeFrictionFactor(m_angularFrictionTimescale, pTimestep); | ||
1390 | angularMotorContributionV -= (currentAngularV * frictionFactorW); | ||
1391 | |||
1392 | Vector3 angularMotorContributionW = angularMotorContributionV * VehicleOrientation; | ||
1393 | VehicleRotationalVelocity += angularMotorContributionW; | ||
1289 | 1394 | ||
1290 | VehicleRotationalVelocity += angularMotorContributionV * VehicleOrientation; | 1395 | VDetailLog("{0}, MoveAngular,angularTurning,curAngVelV={1},origVehRotVel={2},vehRotVel={3},frictFact={4}, angContribV={5},angContribW={6}", |
1291 | VDetailLog("{0}, MoveAngular,angularTurning,angularMotorContrib={1}", Prim.LocalID, angularMotorContributionV); | 1396 | ControllingPrim.LocalID, currentAngularV, origVehicleRotationalVelocity, VehicleRotationalVelocity, frictionFactorW, angularMotorContributionV, angularMotorContributionW); |
1292 | } | 1397 | } |
1293 | 1398 | ||
1294 | // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial: | 1399 | // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial: |
@@ -1303,86 +1408,136 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1303 | { | 1408 | { |
1304 | 1409 | ||
1305 | // If vertical attaction timescale is reasonable | 1410 | // If vertical attaction timescale is reasonable |
1306 | if (enableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff) | 1411 | if (BSParam.VehicleEnableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff) |
1307 | { | 1412 | { |
1308 | // Possible solution derived from a discussion at: | 1413 | Vector3 vehicleUpAxis = Vector3.UnitZ * VehicleOrientation; |
1309 | // http://stackoverflow.com/questions/14939657/computing-vector-from-quaternion-works-computing-quaternion-from-vector-does-no | 1414 | switch (BSParam.VehicleAngularVerticalAttractionAlgorithm) |
1310 | |||
1311 | // Create a rotation that is only the vehicle's rotation around Z | ||
1312 | Vector3 currentEuler = Vector3.Zero; | ||
1313 | VehicleOrientation.GetEulerAngles(out currentEuler.X, out currentEuler.Y, out currentEuler.Z); | ||
1314 | Quaternion justZOrientation = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, currentEuler.Z); | ||
1315 | |||
1316 | // Create the axis that is perpendicular to the up vector and the rotated up vector. | ||
1317 | Vector3 differenceAxis = Vector3.Cross(Vector3.UnitZ * justZOrientation, Vector3.UnitZ * VehicleOrientation); | ||
1318 | // Compute the angle between those to vectors. | ||
1319 | double differenceAngle = Math.Acos((double)Vector3.Dot(Vector3.UnitZ, Vector3.Normalize(Vector3.UnitZ * VehicleOrientation))); | ||
1320 | // 'differenceAngle' is the angle to rotate and 'differenceAxis' is the plane to rotate in to get the vehicle vertical | ||
1321 | |||
1322 | // Reduce the change by the time period it is to change in. Timestep is handled when velocity is applied. | ||
1323 | // TODO: add 'efficiency'. | ||
1324 | differenceAngle /= m_verticalAttractionTimescale; | ||
1325 | |||
1326 | // Create the quaterian representing the correction angle | ||
1327 | Quaternion correctionRotation = Quaternion.CreateFromAxisAngle(differenceAxis, (float)differenceAngle); | ||
1328 | |||
1329 | // Turn that quaternion into Euler values to make it into velocities to apply. | ||
1330 | Vector3 vertContributionV = Vector3.Zero; | ||
1331 | correctionRotation.GetEulerAngles(out vertContributionV.X, out vertContributionV.Y, out vertContributionV.Z); | ||
1332 | vertContributionV *= -1f; | ||
1333 | |||
1334 | VehicleRotationalVelocity += vertContributionV; | ||
1335 | |||
1336 | VDetailLog("{0}, MoveAngular,verticalAttraction,diffAxis={1},diffAng={2},corrRot={3},contrib={4}", | ||
1337 | Prim.LocalID, | ||
1338 | differenceAxis, | ||
1339 | differenceAngle, | ||
1340 | correctionRotation, | ||
1341 | vertContributionV); | ||
1342 | |||
1343 | // =================================================================== | ||
1344 | /* | ||
1345 | Vector3 vertContributionV = Vector3.Zero; | ||
1346 | Vector3 origRotVelW = VehicleRotationalVelocity; // DEBUG DEBUG | ||
1347 | |||
1348 | // Take a vector pointing up and convert it from world to vehicle relative coords. | ||
1349 | Vector3 verticalError = Vector3.Normalize(Vector3.UnitZ * VehicleOrientation); | ||
1350 | |||
1351 | // If vertical attraction correction is needed, the vector that was pointing up (UnitZ) | ||
1352 | // is now: | ||
1353 | // leaning to one side: rotated around the X axis with the Y value going | ||
1354 | // from zero (nearly straight up) to one (completely to the side)) or | ||
1355 | // leaning front-to-back: rotated around the Y axis with the value of X being between | ||
1356 | // zero and one. | ||
1357 | // The value of Z is how far the rotation is off with 1 meaning none and 0 being 90 degrees. | ||
1358 | |||
1359 | // Y error means needed rotation around X axis and visa versa. | ||
1360 | // Since the error goes from zero to one, the asin is the corresponding angle. | ||
1361 | vertContributionV.X = (float)Math.Asin(verticalError.Y); | ||
1362 | // (Tilt forward (positive X) needs to tilt back (rotate negative) around Y axis.) | ||
1363 | vertContributionV.Y = -(float)Math.Asin(verticalError.X); | ||
1364 | |||
1365 | // If verticalError.Z is negative, the vehicle is upside down. Add additional push. | ||
1366 | if (verticalError.Z < 0f) | ||
1367 | { | 1415 | { |
1368 | vertContributionV.X += Math.Sign(vertContributionV.X) * PIOverFour; | 1416 | case 0: |
1369 | // vertContribution.Y -= PIOverFour; | 1417 | { |
1418 | //Another formula to try got from : | ||
1419 | //http://answers.unity3d.com/questions/10425/how-to-stabilize-angular-motion-alignment-of-hover.html | ||
1420 | |||
1421 | // Flipping what was originally a timescale into a speed variable and then multiplying it by 2 | ||
1422 | // since only computing half the distance between the angles. | ||
1423 | float verticalAttractionSpeed = (1 / m_verticalAttractionTimescale) * 2.0f; | ||
1424 | |||
1425 | // Make a prediction of where the up axis will be when this is applied rather then where it is now as | ||
1426 | // this makes for a smoother adjustment and less fighting between the various forces. | ||
1427 | Vector3 predictedUp = vehicleUpAxis * Quaternion.CreateFromAxisAngle(VehicleRotationalVelocity, 0f); | ||
1428 | |||
1429 | // This is only half the distance to the target so it will take 2 seconds to complete the turn. | ||
1430 | Vector3 torqueVector = Vector3.Cross(predictedUp, Vector3.UnitZ); | ||
1431 | |||
1432 | // Scale vector by our timescale since it is an acceleration it is r/s^2 or radians a timescale squared | ||
1433 | Vector3 vertContributionV = torqueVector * verticalAttractionSpeed * verticalAttractionSpeed; | ||
1434 | |||
1435 | VehicleRotationalVelocity += vertContributionV; | ||
1436 | |||
1437 | VDetailLog("{0}, MoveAngular,verticalAttraction,vertAttrSpeed={1},upAxis={2},PredictedUp={3},torqueVector={4},contrib={5}", | ||
1438 | ControllingPrim.LocalID, | ||
1439 | verticalAttractionSpeed, | ||
1440 | vehicleUpAxis, | ||
1441 | predictedUp, | ||
1442 | torqueVector, | ||
1443 | vertContributionV); | ||
1444 | break; | ||
1445 | } | ||
1446 | case 1: | ||
1447 | { | ||
1448 | // Possible solution derived from a discussion at: | ||
1449 | // http://stackoverflow.com/questions/14939657/computing-vector-from-quaternion-works-computing-quaternion-from-vector-does-no | ||
1450 | |||
1451 | // Create a rotation that is only the vehicle's rotation around Z | ||
1452 | Vector3 currentEulerW = Vector3.Zero; | ||
1453 | VehicleOrientation.GetEulerAngles(out currentEulerW.X, out currentEulerW.Y, out currentEulerW.Z); | ||
1454 | Quaternion justZOrientation = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, currentEulerW.Z); | ||
1455 | |||
1456 | // Create the axis that is perpendicular to the up vector and the rotated up vector. | ||
1457 | Vector3 differenceAxisW = Vector3.Cross(Vector3.UnitZ * justZOrientation, Vector3.UnitZ * VehicleOrientation); | ||
1458 | // Compute the angle between those to vectors. | ||
1459 | double differenceAngle = Math.Acos((double)Vector3.Dot(Vector3.UnitZ, Vector3.Normalize(Vector3.UnitZ * VehicleOrientation))); | ||
1460 | // 'differenceAngle' is the angle to rotate and 'differenceAxis' is the plane to rotate in to get the vehicle vertical | ||
1461 | |||
1462 | // Reduce the change by the time period it is to change in. Timestep is handled when velocity is applied. | ||
1463 | // TODO: add 'efficiency'. | ||
1464 | // differenceAngle /= m_verticalAttractionTimescale; | ||
1465 | |||
1466 | // Create the quaterian representing the correction angle | ||
1467 | Quaternion correctionRotationW = Quaternion.CreateFromAxisAngle(differenceAxisW, (float)differenceAngle); | ||
1468 | |||
1469 | // Turn that quaternion into Euler values to make it into velocities to apply. | ||
1470 | Vector3 vertContributionW = Vector3.Zero; | ||
1471 | correctionRotationW.GetEulerAngles(out vertContributionW.X, out vertContributionW.Y, out vertContributionW.Z); | ||
1472 | vertContributionW *= -1f; | ||
1473 | vertContributionW /= m_verticalAttractionTimescale; | ||
1474 | |||
1475 | VehicleRotationalVelocity += vertContributionW; | ||
1476 | |||
1477 | VDetailLog("{0}, MoveAngular,verticalAttraction,upAxis={1},diffAxis={2},diffAng={3},corrRot={4},contrib={5}", | ||
1478 | ControllingPrim.LocalID, | ||
1479 | vehicleUpAxis, | ||
1480 | differenceAxisW, | ||
1481 | differenceAngle, | ||
1482 | correctionRotationW, | ||
1483 | vertContributionW); | ||
1484 | break; | ||
1485 | } | ||
1486 | case 2: | ||
1487 | { | ||
1488 | Vector3 vertContributionV = Vector3.Zero; | ||
1489 | Vector3 origRotVelW = VehicleRotationalVelocity; // DEBUG DEBUG | ||
1490 | |||
1491 | // Take a vector pointing up and convert it from world to vehicle relative coords. | ||
1492 | Vector3 verticalError = Vector3.Normalize(Vector3.UnitZ * VehicleOrientation); | ||
1493 | |||
1494 | // If vertical attraction correction is needed, the vector that was pointing up (UnitZ) | ||
1495 | // is now: | ||
1496 | // leaning to one side: rotated around the X axis with the Y value going | ||
1497 | // from zero (nearly straight up) to one (completely to the side)) or | ||
1498 | // leaning front-to-back: rotated around the Y axis with the value of X being between | ||
1499 | // zero and one. | ||
1500 | // The value of Z is how far the rotation is off with 1 meaning none and 0 being 90 degrees. | ||
1501 | |||
1502 | // Y error means needed rotation around X axis and visa versa. | ||
1503 | // Since the error goes from zero to one, the asin is the corresponding angle. | ||
1504 | vertContributionV.X = (float)Math.Asin(verticalError.Y); | ||
1505 | // (Tilt forward (positive X) needs to tilt back (rotate negative) around Y axis.) | ||
1506 | vertContributionV.Y = -(float)Math.Asin(verticalError.X); | ||
1507 | |||
1508 | // If verticalError.Z is negative, the vehicle is upside down. Add additional push. | ||
1509 | if (verticalError.Z < 0f) | ||
1510 | { | ||
1511 | vertContributionV.X += Math.Sign(vertContributionV.X) * PIOverFour; | ||
1512 | // vertContribution.Y -= PIOverFour; | ||
1513 | } | ||
1514 | |||
1515 | // 'vertContrbution' is now the necessary angular correction to correct tilt in one second. | ||
1516 | // Correction happens over a number of seconds. | ||
1517 | Vector3 unscaledContribVerticalErrorV = vertContributionV; // DEBUG DEBUG | ||
1518 | |||
1519 | // The correction happens over the user's time period | ||
1520 | vertContributionV /= m_verticalAttractionTimescale; | ||
1521 | |||
1522 | // Rotate the vehicle rotation to the world coordinates. | ||
1523 | VehicleRotationalVelocity += (vertContributionV * VehicleOrientation); | ||
1524 | |||
1525 | VDetailLog("{0}, MoveAngular,verticalAttraction,,upAxis={1},origRotVW={2},vertError={3},unscaledV={4},eff={5},ts={6},vertContribV={7}", | ||
1526 | ControllingPrim.LocalID, | ||
1527 | vehicleUpAxis, | ||
1528 | origRotVelW, | ||
1529 | verticalError, | ||
1530 | unscaledContribVerticalErrorV, | ||
1531 | m_verticalAttractionEfficiency, | ||
1532 | m_verticalAttractionTimescale, | ||
1533 | vertContributionV); | ||
1534 | break; | ||
1535 | } | ||
1536 | default: | ||
1537 | { | ||
1538 | break; | ||
1539 | } | ||
1370 | } | 1540 | } |
1371 | |||
1372 | // 'vertContrbution' is now the necessary angular correction to correct tilt in one second. | ||
1373 | // Correction happens over a number of seconds. | ||
1374 | Vector3 unscaledContribVerticalErrorV = vertContributionV; // DEBUG DEBUG | ||
1375 | |||
1376 | // The correction happens over the user's time period | ||
1377 | vertContributionV /= m_verticalAttractionTimescale; | ||
1378 | |||
1379 | // Rotate the vehicle rotation to the world coordinates. | ||
1380 | VehicleRotationalVelocity += (vertContributionV * VehicleOrientation); | ||
1381 | |||
1382 | VDetailLog("{0}, MoveAngular,verticalAttraction,,origRotVW={1},vertError={2},unscaledV={3},eff={4},ts={5},vertContribV={6}", | ||
1383 | Prim.LocalID, origRotVelW, verticalError, unscaledContribVerticalErrorV, | ||
1384 | m_verticalAttractionEfficiency, m_verticalAttractionTimescale, vertContributionV); | ||
1385 | */ | ||
1386 | } | 1541 | } |
1387 | } | 1542 | } |
1388 | 1543 | ||
@@ -1392,13 +1547,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1392 | // in that direction. | 1547 | // in that direction. |
1393 | // TODO: implement reference frame. | 1548 | // TODO: implement reference frame. |
1394 | public void ComputeAngularDeflection() | 1549 | public void ComputeAngularDeflection() |
1395 | { | 1550 | { |
1396 | // Since angularMotorUp and angularDeflection are computed independently, they will calculate | ||
1397 | // approximately the same X or Y correction. When added together (when contributions are combined) | ||
1398 | // this creates an over-correction and then wabbling as the target is overshot. | ||
1399 | // TODO: rethink how the different correction computations inter-relate. | ||
1400 | 1551 | ||
1401 | if (enableAngularDeflection && m_angularDeflectionEfficiency != 0 && VehicleForwardSpeed > 0.2) | 1552 | if (BSParam.VehicleEnableAngularDeflection && m_angularDeflectionEfficiency != 0 && VehicleForwardSpeed > 0.2) |
1402 | { | 1553 | { |
1403 | Vector3 deflectContributionV = Vector3.Zero; | 1554 | Vector3 deflectContributionV = Vector3.Zero; |
1404 | 1555 | ||
@@ -1411,10 +1562,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1411 | 1562 | ||
1412 | // The direction the vehicle is pointing | 1563 | // The direction the vehicle is pointing |
1413 | Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation; | 1564 | Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation; |
1414 | pointingDirection.Normalize(); | 1565 | //Predict where the Vehicle will be pointing after AngularVelocity change is applied. This will keep |
1566 | // from overshooting and allow this correction to merge with the Vertical Attraction peacefully. | ||
1567 | Vector3 predictedPointingDirection = pointingDirection * Quaternion.CreateFromAxisAngle(VehicleRotationalVelocity, 0f); | ||
1568 | predictedPointingDirection.Normalize(); | ||
1415 | 1569 | ||
1416 | // The difference between what is and what should be. | 1570 | // The difference between what is and what should be. |
1417 | Vector3 deflectionError = movingDirection - pointingDirection; | 1571 | // Vector3 deflectionError = movingDirection - predictedPointingDirection; |
1572 | Vector3 deflectionError = Vector3.Cross(movingDirection, predictedPointingDirection); | ||
1418 | 1573 | ||
1419 | // Don't try to correct very large errors (not our job) | 1574 | // Don't try to correct very large errors (not our job) |
1420 | // if (Math.Abs(deflectionError.X) > PIOverFour) deflectionError.X = PIOverTwo * Math.Sign(deflectionError.X); | 1575 | // if (Math.Abs(deflectionError.X) > PIOverFour) deflectionError.X = PIOverTwo * Math.Sign(deflectionError.X); |
@@ -1427,15 +1582,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1427 | // ret = m_angularDeflectionCorrectionMotor(1f, deflectionError); | 1582 | // ret = m_angularDeflectionCorrectionMotor(1f, deflectionError); |
1428 | 1583 | ||
1429 | // Scale the correction by recovery timescale and efficiency | 1584 | // Scale the correction by recovery timescale and efficiency |
1430 | deflectContributionV = (-deflectionError) * m_angularDeflectionEfficiency; | 1585 | // Not modeling a spring so clamp the scale to no more then the arc |
1431 | deflectContributionV /= m_angularDeflectionTimescale; | 1586 | deflectContributionV = (-deflectionError) * ClampInRange(0, m_angularDeflectionEfficiency/m_angularDeflectionTimescale,1f); |
1432 | 1587 | //deflectContributionV /= m_angularDeflectionTimescale; | |
1433 | VehicleRotationalVelocity += deflectContributionV * VehicleOrientation; | ||
1434 | 1588 | ||
1589 | // VehicleRotationalVelocity += deflectContributionV * VehicleOrientation; | ||
1590 | VehicleRotationalVelocity += deflectContributionV; | ||
1435 | VDetailLog("{0}, MoveAngular,Deflection,movingDir={1},pointingDir={2},deflectError={3},ret={4}", | 1591 | VDetailLog("{0}, MoveAngular,Deflection,movingDir={1},pointingDir={2},deflectError={3},ret={4}", |
1436 | Prim.LocalID, movingDirection, pointingDirection, deflectionError, deflectContributionV); | 1592 | ControllingPrim.LocalID, movingDirection, pointingDirection, deflectionError, deflectContributionV); |
1437 | VDetailLog("{0}, MoveAngular,Deflection,fwdSpd={1},defEff={2},defTS={3}", | 1593 | VDetailLog("{0}, MoveAngular,Deflection,fwdSpd={1},defEff={2},defTS={3},PredictedPointingDir={4}", |
1438 | Prim.LocalID, VehicleForwardSpeed, m_angularDeflectionEfficiency, m_angularDeflectionTimescale); | 1594 | ControllingPrim.LocalID, VehicleForwardSpeed, m_angularDeflectionEfficiency, m_angularDeflectionTimescale, predictedPointingDirection); |
1439 | } | 1595 | } |
1440 | } | 1596 | } |
1441 | 1597 | ||
@@ -1447,13 +1603,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1447 | // produce a angular velocity around the yaw-axis, causing the vehicle to turn. The magnitude | 1603 | // produce a angular velocity around the yaw-axis, causing the vehicle to turn. The magnitude |
1448 | // of the yaw effect will be proportional to the | 1604 | // of the yaw effect will be proportional to the |
1449 | // VEHICLE_BANKING_EFFICIENCY, the angle of the roll rotation, and sometimes the vehicle's | 1605 | // VEHICLE_BANKING_EFFICIENCY, the angle of the roll rotation, and sometimes the vehicle's |
1450 | // velocity along its preferred axis of motion. | 1606 | // velocity along its preferred axis of motion. |
1451 | // The VEHICLE_BANKING_EFFICIENCY can vary between -1 and +1. When it is positive then any | 1607 | // The VEHICLE_BANKING_EFFICIENCY can vary between -1 and +1. When it is positive then any |
1452 | // positive rotation (by the right-hand rule) about the roll-axis will effect a | 1608 | // positive rotation (by the right-hand rule) about the roll-axis will effect a |
1453 | // (negative) torque around the yaw-axis, making it turn to the right--that is the | 1609 | // (negative) torque around the yaw-axis, making it turn to the right--that is the |
1454 | // vehicle will lean into the turn, which is how real airplanes and motorcycle's work. | 1610 | // vehicle will lean into the turn, which is how real airplanes and motorcycle's work. |
1455 | // Negating the banking coefficient will make it so that the vehicle leans to the | 1611 | // Negating the banking coefficient will make it so that the vehicle leans to the |
1456 | // outside of the turn (not very "physical" but might allow interesting vehicles so why not?). | 1612 | // outside of the turn (not very "physical" but might allow interesting vehicles so why not?). |
1457 | // The VEHICLE_BANKING_MIX is a fake (i.e. non-physical) parameter that is useful for making | 1613 | // The VEHICLE_BANKING_MIX is a fake (i.e. non-physical) parameter that is useful for making |
1458 | // banking vehicles do what you want rather than what the laws of physics allow. | 1614 | // banking vehicles do what you want rather than what the laws of physics allow. |
1459 | // For example, consider a real motorcycle...it must be moving forward in order for | 1615 | // For example, consider a real motorcycle...it must be moving forward in order for |
@@ -1465,14 +1621,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1465 | // totally static (0.0) and totally dynamic (1.0). By "static" we mean that the | 1621 | // totally static (0.0) and totally dynamic (1.0). By "static" we mean that the |
1466 | // banking effect depends only on the vehicle's rotation about its roll-axis compared | 1622 | // banking effect depends only on the vehicle's rotation about its roll-axis compared |
1467 | // to "dynamic" where the banking is also proportional to its velocity along its | 1623 | // to "dynamic" where the banking is also proportional to its velocity along its |
1468 | // roll-axis. Finding the best value of the "mixture" will probably require trial and error. | 1624 | // roll-axis. Finding the best value of the "mixture" will probably require trial and error. |
1469 | // The time it takes for the banking behavior to defeat a preexisting angular velocity about the | 1625 | // The time it takes for the banking behavior to defeat a preexisting angular velocity about the |
1470 | // world z-axis is determined by the VEHICLE_BANKING_TIMESCALE. So if you want the vehicle to | 1626 | // world z-axis is determined by the VEHICLE_BANKING_TIMESCALE. So if you want the vehicle to |
1471 | // bank quickly then give it a banking timescale of about a second or less, otherwise you can | 1627 | // bank quickly then give it a banking timescale of about a second or less, otherwise you can |
1472 | // make a sluggish vehicle by giving it a timescale of several seconds. | 1628 | // make a sluggish vehicle by giving it a timescale of several seconds. |
1473 | public void ComputeAngularBanking() | 1629 | public void ComputeAngularBanking() |
1474 | { | 1630 | { |
1475 | if (enableAngularBanking && m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff) | 1631 | if (BSParam.VehicleEnableAngularBanking && m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff) |
1476 | { | 1632 | { |
1477 | Vector3 bankingContributionV = Vector3.Zero; | 1633 | Vector3 bankingContributionV = Vector3.Zero; |
1478 | 1634 | ||
@@ -1498,10 +1654,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1498 | 1654 | ||
1499 | //VehicleRotationalVelocity += bankingContributionV * VehicleOrientation; | 1655 | //VehicleRotationalVelocity += bankingContributionV * VehicleOrientation; |
1500 | VehicleRotationalVelocity += bankingContributionV; | 1656 | VehicleRotationalVelocity += bankingContributionV; |
1501 | 1657 | ||
1502 | 1658 | ||
1503 | VDetailLog("{0}, MoveAngular,Banking,rollComp={1},speed={2},rollComp={3},yAng={4},mYAng={5},ret={6}", | 1659 | VDetailLog("{0}, MoveAngular,Banking,rollComp={1},speed={2},rollComp={3},yAng={4},mYAng={5},ret={6}", |
1504 | Prim.LocalID, rollComponents, VehicleForwardSpeed, rollComponents, yawAngle, mixedYawAngle, bankingContributionV); | 1660 | ControllingPrim.LocalID, rollComponents, VehicleForwardSpeed, rollComponents, yawAngle, mixedYawAngle, bankingContributionV); |
1505 | } | 1661 | } |
1506 | } | 1662 | } |
1507 | 1663 | ||
@@ -1540,8 +1696,37 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1540 | if (rotq != m_rot) | 1696 | if (rotq != m_rot) |
1541 | { | 1697 | { |
1542 | VehicleOrientation = m_rot; | 1698 | VehicleOrientation = m_rot; |
1543 | VDetailLog("{0}, LimitRotation,done,orig={1},new={2}", Prim.LocalID, rotq, m_rot); | 1699 | VDetailLog("{0}, LimitRotation,done,orig={1},new={2}", ControllingPrim.LocalID, rotq, m_rot); |
1700 | } | ||
1701 | |||
1702 | } | ||
1703 | |||
1704 | // Given a friction vector (reduction in seconds) and a timestep, return the factor to reduce | ||
1705 | // some value by to apply this friction. | ||
1706 | private Vector3 ComputeFrictionFactor(Vector3 friction, float pTimestep) | ||
1707 | { | ||
1708 | Vector3 frictionFactor = Vector3.Zero; | ||
1709 | if (friction != BSMotor.InfiniteVector) | ||
1710 | { | ||
1711 | // frictionFactor = (Vector3.One / FrictionTimescale) * timeStep; | ||
1712 | // Individual friction components can be 'infinite' so compute each separately. | ||
1713 | frictionFactor.X = (friction.X == BSMotor.Infinite) ? 0f : (1f / friction.X); | ||
1714 | frictionFactor.Y = (friction.Y == BSMotor.Infinite) ? 0f : (1f / friction.Y); | ||
1715 | frictionFactor.Z = (friction.Z == BSMotor.Infinite) ? 0f : (1f / friction.Z); | ||
1716 | frictionFactor *= pTimestep; | ||
1717 | } | ||
1718 | return frictionFactor; | ||
1719 | } | ||
1720 | |||
1721 | private float SortedClampInRange(float clampa, float val, float clampb) | ||
1722 | { | ||
1723 | if (clampa > clampb) | ||
1724 | { | ||
1725 | float temp = clampa; | ||
1726 | clampa = clampb; | ||
1727 | clampb = temp; | ||
1544 | } | 1728 | } |
1729 | return ClampInRange(clampa, val, clampb); | ||
1545 | 1730 | ||
1546 | } | 1731 | } |
1547 | 1732 | ||
@@ -1554,8 +1739,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1554 | // Invoke the detailed logger and output something if it's enabled. | 1739 | // Invoke the detailed logger and output something if it's enabled. |
1555 | private void VDetailLog(string msg, params Object[] args) | 1740 | private void VDetailLog(string msg, params Object[] args) |
1556 | { | 1741 | { |
1557 | if (Prim.PhysicsScene.VehicleLoggingEnabled) | 1742 | if (ControllingPrim.PhysScene.VehicleLoggingEnabled) |
1558 | Prim.PhysicsScene.DetailLog(msg, args); | 1743 | ControllingPrim.PhysScene.DetailLog(msg, args); |
1559 | } | 1744 | } |
1560 | } | 1745 | } |
1561 | } | 1746 | } |