diff options
author | Robert Adams | 2013-05-08 06:02:12 -0700 |
---|---|---|
committer | Robert Adams | 2013-05-08 06:02:12 -0700 |
commit | eb0687f5af127ad6195b95965ce31346f2bc0a24 (patch) | |
tree | 8888b8d4c45874c646da0b475d09bd051b33e1cc /OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | |
parent | Add regression test for inventory item give, reject and subsequent trash fold... (diff) | |
download | opensim-SC-eb0687f5af127ad6195b95965ce31346f2bc0a24.zip opensim-SC-eb0687f5af127ad6195b95965ce31346f2bc0a24.tar.gz opensim-SC-eb0687f5af127ad6195b95965ce31346f2bc0a24.tar.bz2 opensim-SC-eb0687f5af127ad6195b95965ce31346f2bc0a24.tar.xz |
vh: update BulletSim (OpenSim/Region/Physics/BulletSPlugin
and DLL/SO) to ac6dcd35fb77f118fc6c3d72cb029591306c7e99
(Mon May 6 21:10:02 2013 -0400) on top of 0.7.5-postfixes.
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs')
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 826 |
1 files changed, 555 insertions, 271 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 13c2539..c16b7d3 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | |||
@@ -35,17 +35,19 @@ using System.Collections.Generic; | |||
35 | using System.Reflection; | 35 | using System.Reflection; |
36 | using System.Runtime.InteropServices; | 36 | using System.Runtime.InteropServices; |
37 | using OpenMetaverse; | 37 | using OpenMetaverse; |
38 | using OpenSim.Framework; | ||
38 | using OpenSim.Region.Physics.Manager; | 39 | using OpenSim.Region.Physics.Manager; |
39 | 40 | ||
40 | namespace OpenSim.Region.Physics.BulletSPlugin | 41 | namespace OpenSim.Region.Physics.BulletSPlugin |
41 | { | 42 | { |
42 | public sealed class BSDynamics | 43 | public sealed class BSDynamics : BSActor |
43 | { | 44 | { |
44 | private static string LogHeader = "[BULLETSIM VEHICLE]"; | 45 | private static string LogHeader = "[BULLETSIM VEHICLE]"; |
45 | 46 | ||
46 | private BSScene PhysicsScene { get; set; } | ||
47 | // the prim this dynamic controller belongs to | 47 | // the prim this dynamic controller belongs to |
48 | private BSPrim Prim { get; set; } | 48 | private BSPrim ControllingPrim { get; set; } |
49 | |||
50 | private bool m_haveRegisteredForSceneEvents; | ||
49 | 51 | ||
50 | // mass of the vehicle fetched each time we're calles | 52 | // mass of the vehicle fetched each time we're calles |
51 | private float m_vehicleMass; | 53 | private float m_vehicleMass; |
@@ -108,10 +110,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
108 | private float m_VhoverEfficiency = 0f; | 110 | private float m_VhoverEfficiency = 0f; |
109 | private float m_VhoverTimescale = 0f; | 111 | private float m_VhoverTimescale = 0f; |
110 | private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height | 112 | private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height |
111 | private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle. | 113 | // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity) |
112 | // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity) | 114 | private float m_VehicleBuoyancy = 0f; |
113 | // KF: So far I have found no good method to combine a script-requested .Z velocity and gravity. | 115 | private Vector3 m_VehicleGravity = Vector3.Zero; // Gravity computed when buoyancy set |
114 | // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity. | ||
115 | 116 | ||
116 | //Attractor properties | 117 | //Attractor properties |
117 | private BSVMotor m_verticalAttractionMotor = new BSVMotor("VerticalAttraction"); | 118 | private BSVMotor m_verticalAttractionMotor = new BSVMotor("VerticalAttraction"); |
@@ -124,22 +125,51 @@ 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 | public BSDynamics(BSScene myScene, BSPrim myPrim) | 128 | // For debugging, flags to turn on and off individual corrections. |
129 | public bool enableAngularVerticalAttraction; | ||
130 | public bool enableAngularDeflection; | ||
131 | public bool enableAngularBanking; | ||
132 | |||
133 | public BSDynamics(BSScene myScene, BSPrim myPrim, string actorName) | ||
134 | : base(myScene, myPrim, actorName) | ||
128 | { | 135 | { |
129 | PhysicsScene = myScene; | 136 | ControllingPrim = myPrim; |
130 | Prim = myPrim; | ||
131 | Type = Vehicle.TYPE_NONE; | 137 | Type = Vehicle.TYPE_NONE; |
138 | m_haveRegisteredForSceneEvents = false; | ||
139 | SetupVehicleDebugging(); | ||
140 | } | ||
141 | |||
142 | // Stopgap debugging enablement. Allows source level debugging but still checking | ||
143 | // in changes by making enablement of debugging flags from INI file. | ||
144 | public void SetupVehicleDebugging() | ||
145 | { | ||
146 | enableAngularVerticalAttraction = true; | ||
147 | enableAngularDeflection = false; | ||
148 | enableAngularBanking = true; | ||
149 | if (BSParam.VehicleDebuggingEnable) | ||
150 | { | ||
151 | enableAngularVerticalAttraction = true; | ||
152 | enableAngularDeflection = false; | ||
153 | enableAngularBanking = false; | ||
154 | } | ||
132 | } | 155 | } |
133 | 156 | ||
134 | // Return 'true' if this vehicle is doing vehicle things | 157 | // Return 'true' if this vehicle is doing vehicle things |
135 | public bool IsActive | 158 | public bool IsActive |
136 | { | 159 | { |
137 | get { return Type != Vehicle.TYPE_NONE && Prim.IsPhysical; } | 160 | get { return (Type != Vehicle.TYPE_NONE && ControllingPrim.IsPhysicallyActive); } |
161 | } | ||
162 | |||
163 | // Return 'true' if this a vehicle that should be sitting on the ground | ||
164 | public bool IsGroundVehicle | ||
165 | { | ||
166 | get { return (Type == Vehicle.TYPE_CAR || Type == Vehicle.TYPE_SLED); } | ||
138 | } | 167 | } |
139 | 168 | ||
140 | internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue) | 169 | #region Vehicle parameter setting |
170 | public void ProcessFloatVehicleParam(Vehicle pParam, float pValue) | ||
141 | { | 171 | { |
142 | VDetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue); | 172 | VDetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", ControllingPrim.LocalID, pParam, pValue); |
143 | switch (pParam) | 173 | switch (pParam) |
144 | { | 174 | { |
145 | case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: | 175 | case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: |
@@ -167,6 +197,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
167 | break; | 197 | break; |
168 | case Vehicle.BUOYANCY: | 198 | case Vehicle.BUOYANCY: |
169 | m_VehicleBuoyancy = ClampInRange(-1f, pValue, 1f); | 199 | m_VehicleBuoyancy = ClampInRange(-1f, pValue, 1f); |
200 | m_VehicleGravity = ControllingPrim.ComputeGravity(m_VehicleBuoyancy); | ||
170 | break; | 201 | break; |
171 | case Vehicle.HOVER_EFFICIENCY: | 202 | case Vehicle.HOVER_EFFICIENCY: |
172 | m_VhoverEfficiency = ClampInRange(0f, pValue, 1f); | 203 | m_VhoverEfficiency = ClampInRange(0f, pValue, 1f); |
@@ -204,15 +235,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
204 | // set all of the components to the same value | 235 | // set all of the components to the same value |
205 | case Vehicle.ANGULAR_FRICTION_TIMESCALE: | 236 | case Vehicle.ANGULAR_FRICTION_TIMESCALE: |
206 | m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue); | 237 | m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue); |
207 | m_angularMotor.FrictionTimescale = m_angularFrictionTimescale; | ||
208 | break; | 238 | break; |
209 | case Vehicle.ANGULAR_MOTOR_DIRECTION: | 239 | case Vehicle.ANGULAR_MOTOR_DIRECTION: |
210 | m_angularMotorDirection = new Vector3(pValue, pValue, pValue); | 240 | m_angularMotorDirection = new Vector3(pValue, pValue, pValue); |
241 | m_angularMotor.Zero(); | ||
211 | m_angularMotor.SetTarget(m_angularMotorDirection); | 242 | m_angularMotor.SetTarget(m_angularMotorDirection); |
212 | break; | 243 | break; |
213 | case Vehicle.LINEAR_FRICTION_TIMESCALE: | 244 | case Vehicle.LINEAR_FRICTION_TIMESCALE: |
214 | m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); | 245 | m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); |
215 | m_linearMotor.FrictionTimescale = m_linearFrictionTimescale; | ||
216 | break; | 246 | break; |
217 | case Vehicle.LINEAR_MOTOR_DIRECTION: | 247 | case Vehicle.LINEAR_MOTOR_DIRECTION: |
218 | m_linearMotorDirection = new Vector3(pValue, pValue, pValue); | 248 | m_linearMotorDirection = new Vector3(pValue, pValue, pValue); |
@@ -228,12 +258,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
228 | 258 | ||
229 | internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue) | 259 | internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue) |
230 | { | 260 | { |
231 | VDetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue); | 261 | VDetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", ControllingPrim.LocalID, pParam, pValue); |
232 | switch (pParam) | 262 | switch (pParam) |
233 | { | 263 | { |
234 | case Vehicle.ANGULAR_FRICTION_TIMESCALE: | 264 | case Vehicle.ANGULAR_FRICTION_TIMESCALE: |
235 | m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); | 265 | m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); |
236 | m_angularMotor.FrictionTimescale = m_angularFrictionTimescale; | ||
237 | break; | 266 | break; |
238 | case Vehicle.ANGULAR_MOTOR_DIRECTION: | 267 | case Vehicle.ANGULAR_MOTOR_DIRECTION: |
239 | // Limit requested angular speed to 2 rps= 4 pi rads/sec | 268 | // Limit requested angular speed to 2 rps= 4 pi rads/sec |
@@ -241,11 +270,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
241 | pValue.Y = ClampInRange(-12.56f, pValue.Y, 12.56f); | 270 | pValue.Y = ClampInRange(-12.56f, pValue.Y, 12.56f); |
242 | pValue.Z = ClampInRange(-12.56f, pValue.Z, 12.56f); | 271 | pValue.Z = ClampInRange(-12.56f, pValue.Z, 12.56f); |
243 | m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); | 272 | m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); |
273 | m_angularMotor.Zero(); | ||
244 | m_angularMotor.SetTarget(m_angularMotorDirection); | 274 | m_angularMotor.SetTarget(m_angularMotorDirection); |
245 | break; | 275 | break; |
246 | case Vehicle.LINEAR_FRICTION_TIMESCALE: | 276 | case Vehicle.LINEAR_FRICTION_TIMESCALE: |
247 | m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); | 277 | m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); |
248 | m_linearMotor.FrictionTimescale = m_linearFrictionTimescale; | ||
249 | break; | 278 | break; |
250 | case Vehicle.LINEAR_MOTOR_DIRECTION: | 279 | case Vehicle.LINEAR_MOTOR_DIRECTION: |
251 | m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); | 280 | m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); |
@@ -263,7 +292,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
263 | 292 | ||
264 | internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) | 293 | internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) |
265 | { | 294 | { |
266 | VDetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue); | 295 | VDetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", ControllingPrim.LocalID, pParam, pValue); |
267 | switch (pParam) | 296 | switch (pParam) |
268 | { | 297 | { |
269 | case Vehicle.REFERENCE_FRAME: | 298 | case Vehicle.REFERENCE_FRAME: |
@@ -277,7 +306,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
277 | 306 | ||
278 | internal void ProcessVehicleFlags(int pParam, bool remove) | 307 | internal void ProcessVehicleFlags(int pParam, bool remove) |
279 | { | 308 | { |
280 | VDetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", Prim.LocalID, pParam, remove); | 309 | VDetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", ControllingPrim.LocalID, pParam, remove); |
281 | VehicleFlag parm = (VehicleFlag)pParam; | 310 | VehicleFlag parm = (VehicleFlag)pParam; |
282 | if (pParam == -1) | 311 | if (pParam == -1) |
283 | m_flags = (VehicleFlag)0; | 312 | m_flags = (VehicleFlag)0; |
@@ -290,9 +319,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
290 | } | 319 | } |
291 | } | 320 | } |
292 | 321 | ||
293 | internal void ProcessTypeChange(Vehicle pType) | 322 | public void ProcessTypeChange(Vehicle pType) |
294 | { | 323 | { |
295 | VDetailLog("{0},ProcessTypeChange,type={1}", Prim.LocalID, pType); | 324 | VDetailLog("{0},ProcessTypeChange,type={1}", ControllingPrim.LocalID, pType); |
296 | // Set Defaults For Type | 325 | // Set Defaults For Type |
297 | Type = pType; | 326 | Type = pType; |
298 | switch (pType) | 327 | switch (pType) |
@@ -526,81 +555,136 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
526 | break; | 555 | break; |
527 | } | 556 | } |
528 | 557 | ||
529 | // Update any physical parameters based on this type. | 558 | m_linearMotor = new BSVMotor("LinearMotor", m_linearMotorTimescale, m_linearMotorDecayTimescale, 1f); |
530 | Refresh(); | 559 | m_linearMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG DEBUG (enables detail logging) |
531 | |||
532 | m_linearMotor = new BSVMotor("LinearMotor", m_linearMotorTimescale, | ||
533 | m_linearMotorDecayTimescale, m_linearFrictionTimescale, | ||
534 | 1f); | ||
535 | m_linearMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging) | ||
536 | 560 | ||
537 | m_angularMotor = new BSVMotor("AngularMotor", m_angularMotorTimescale, | 561 | m_angularMotor = new BSVMotor("AngularMotor", m_angularMotorTimescale, m_angularMotorDecayTimescale, 1f); |
538 | m_angularMotorDecayTimescale, m_angularFrictionTimescale, | 562 | m_angularMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG DEBUG (enables detail logging) |
539 | 1f); | ||
540 | m_angularMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging) | ||
541 | 563 | ||
564 | /* Not implemented | ||
542 | m_verticalAttractionMotor = new BSVMotor("VerticalAttraction", m_verticalAttractionTimescale, | 565 | m_verticalAttractionMotor = new BSVMotor("VerticalAttraction", m_verticalAttractionTimescale, |
543 | BSMotor.Infinite, BSMotor.InfiniteVector, | 566 | BSMotor.Infinite, BSMotor.InfiniteVector, |
544 | m_verticalAttractionEfficiency); | 567 | m_verticalAttractionEfficiency); |
545 | // Z goes away and we keep X and Y | 568 | // Z goes away and we keep X and Y |
546 | m_verticalAttractionMotor.FrictionTimescale = new Vector3(BSMotor.Infinite, BSMotor.Infinite, 0.1f); | ||
547 | m_verticalAttractionMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging) | 569 | m_verticalAttractionMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging) |
570 | */ | ||
571 | |||
572 | if (this.Type == Vehicle.TYPE_NONE) | ||
573 | { | ||
574 | UnregisterForSceneEvents(); | ||
575 | } | ||
576 | else | ||
577 | { | ||
578 | RegisterForSceneEvents(); | ||
579 | } | ||
580 | |||
581 | // Update any physical parameters based on this type. | ||
582 | Refresh(); | ||
583 | } | ||
584 | #endregion // Vehicle parameter setting | ||
585 | |||
586 | // BSActor.Refresh() | ||
587 | public override void Refresh() | ||
588 | { | ||
589 | // If asking for a refresh, reset the physical parameters before the next simulation step. | ||
590 | // Called whether active or not since the active state may be updated before the next step. | ||
591 | m_physicsScene.PostTaintObject("BSDynamics.Refresh", ControllingPrim.LocalID, delegate() | ||
592 | { | ||
593 | SetPhysicalParameters(); | ||
594 | }); | ||
548 | } | 595 | } |
549 | 596 | ||
550 | // Some of the properties of this prim may have changed. | 597 | // Some of the properties of this prim may have changed. |
551 | // Do any updating needed for a vehicle | 598 | // Do any updating needed for a vehicle |
552 | public void Refresh() | 599 | private void SetPhysicalParameters() |
553 | { | 600 | { |
554 | if (IsActive) | 601 | if (IsActive) |
555 | { | 602 | { |
556 | // Remember the mass so we don't have to fetch it every step | 603 | // Remember the mass so we don't have to fetch it every step |
557 | m_vehicleMass = Prim.Linkset.LinksetMass; | 604 | m_vehicleMass = ControllingPrim.TotalMass; |
558 | 605 | ||
559 | // Friction affects are handled by this vehicle code | 606 | // Friction affects are handled by this vehicle code |
560 | float friction = 0f; | 607 | m_physicsScene.PE.SetFriction(ControllingPrim.PhysBody, BSParam.VehicleFriction); |
561 | PhysicsScene.PE.SetFriction(Prim.PhysBody, friction); | 608 | m_physicsScene.PE.SetRestitution(ControllingPrim.PhysBody, BSParam.VehicleRestitution); |
562 | 609 | ||
563 | // Moderate angular movement introduced by Bullet. | 610 | // Moderate angular movement introduced by Bullet. |
564 | // TODO: possibly set AngularFactor and LinearFactor for the type of vehicle. | 611 | // TODO: possibly set AngularFactor and LinearFactor for the type of vehicle. |
565 | // Maybe compute linear and angular factor and damping from params. | 612 | // Maybe compute linear and angular factor and damping from params. |
566 | float angularDamping = BSParam.VehicleAngularDamping; | 613 | m_physicsScene.PE.SetAngularDamping(ControllingPrim.PhysBody, BSParam.VehicleAngularDamping); |
567 | PhysicsScene.PE.SetAngularDamping(Prim.PhysBody, angularDamping); | 614 | m_physicsScene.PE.SetLinearFactor(ControllingPrim.PhysBody, BSParam.VehicleLinearFactor); |
615 | m_physicsScene.PE.SetAngularFactorV(ControllingPrim.PhysBody, BSParam.VehicleAngularFactor); | ||
568 | 616 | ||
569 | // Vehicles report collision events so we know when it's on the ground | 617 | // Vehicles report collision events so we know when it's on the ground |
570 | PhysicsScene.PE.AddToCollisionFlags(Prim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); | 618 | m_physicsScene.PE.AddToCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); |
619 | |||
620 | ControllingPrim.Inertia = m_physicsScene.PE.CalculateLocalInertia(ControllingPrim.PhysShape.physShapeInfo, m_vehicleMass); | ||
621 | m_physicsScene.PE.SetMassProps(ControllingPrim.PhysBody, m_vehicleMass, ControllingPrim.Inertia); | ||
622 | m_physicsScene.PE.UpdateInertiaTensor(ControllingPrim.PhysBody); | ||
623 | |||
624 | // Set the gravity for the vehicle depending on the buoyancy | ||
625 | // TODO: what should be done if prim and vehicle buoyancy differ? | ||
626 | m_VehicleGravity = ControllingPrim.ComputeGravity(m_VehicleBuoyancy); | ||
627 | // The actual vehicle gravity is set to zero in Bullet so we can do all the application of same. | ||
628 | m_physicsScene.PE.SetGravity(ControllingPrim.PhysBody, Vector3.Zero); | ||
629 | |||
630 | VDetailLog("{0},BSDynamics.SetPhysicalParameters,mass={1},inert={2},vehGrav={3},aDamp={4},frict={5},rest={6},lFact={7},aFact={8}", | ||
631 | ControllingPrim.LocalID, m_vehicleMass, ControllingPrim.Inertia, m_VehicleGravity, | ||
632 | BSParam.VehicleAngularDamping, BSParam.VehicleFriction, BSParam.VehicleRestitution, | ||
633 | BSParam.VehicleLinearFactor, BSParam.VehicleAngularFactor | ||
634 | ); | ||
635 | } | ||
636 | else | ||
637 | { | ||
638 | if (ControllingPrim.PhysBody.HasPhysicalBody) | ||
639 | m_physicsScene.PE.RemoveFromCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); | ||
640 | } | ||
641 | } | ||
571 | 642 | ||
572 | Vector3 localInertia = PhysicsScene.PE.CalculateLocalInertia(Prim.PhysShape, m_vehicleMass); | 643 | // BSActor.RemoveBodyDependencies |
573 | PhysicsScene.PE.SetMassProps(Prim.PhysBody, m_vehicleMass, localInertia); | 644 | public override void RemoveDependencies() |
574 | PhysicsScene.PE.UpdateInertiaTensor(Prim.PhysBody); | 645 | { |
646 | Refresh(); | ||
647 | } | ||
575 | 648 | ||
576 | Vector3 grav = PhysicsScene.DefaultGravity * (1f - Prim.Buoyancy); | 649 | // BSActor.Release() |
577 | PhysicsScene.PE.SetGravity(Prim.PhysBody, grav); | 650 | public override void Dispose() |
651 | { | ||
652 | UnregisterForSceneEvents(); | ||
653 | Type = Vehicle.TYPE_NONE; | ||
654 | Enabled = false; | ||
655 | return; | ||
656 | } | ||
578 | 657 | ||
579 | VDetailLog("{0},BSDynamics.Refresh,mass={1},frict={2},inert={3},aDamp={4}", | 658 | private void RegisterForSceneEvents() |
580 | Prim.LocalID, m_vehicleMass, friction, localInertia, angularDamping); | 659 | { |
581 | } | 660 | if (!m_haveRegisteredForSceneEvents) |
582 | else | ||
583 | { | 661 | { |
584 | PhysicsScene.PE.RemoveFromCollisionFlags(Prim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); | 662 | m_physicsScene.BeforeStep += this.Step; |
663 | m_physicsScene.AfterStep += this.PostStep; | ||
664 | ControllingPrim.OnPreUpdateProperty += this.PreUpdateProperty; | ||
665 | m_haveRegisteredForSceneEvents = true; | ||
585 | } | 666 | } |
586 | } | 667 | } |
587 | 668 | ||
588 | public bool RemoveBodyDependencies(BSPhysObject prim) | 669 | private void UnregisterForSceneEvents() |
589 | { | 670 | { |
590 | // If active, we need to add our properties back when the body is rebuilt. | 671 | if (m_haveRegisteredForSceneEvents) |
591 | return IsActive; | 672 | { |
673 | m_physicsScene.BeforeStep -= this.Step; | ||
674 | m_physicsScene.AfterStep -= this.PostStep; | ||
675 | ControllingPrim.OnPreUpdateProperty -= this.PreUpdateProperty; | ||
676 | m_haveRegisteredForSceneEvents = false; | ||
677 | } | ||
592 | } | 678 | } |
593 | 679 | ||
594 | public void RestoreBodyDependencies(BSPhysObject prim) | 680 | private void PreUpdateProperty(ref EntityProperties entprop) |
595 | { | 681 | { |
596 | if (Prim.LocalID != prim.LocalID) | 682 | // A temporary kludge to suppress the rotational effects introduced on vehicles by Bullet |
683 | // TODO: handle physics introduced by Bullet with computed vehicle physics. | ||
684 | if (IsActive) | ||
597 | { | 685 | { |
598 | // The call should be on us by our prim. Error if not. | 686 | entprop.RotationalVelocity = Vector3.Zero; |
599 | PhysicsScene.Logger.ErrorFormat("{0} RestoreBodyDependencies: called by not my prim. passedLocalID={1}, vehiclePrimLocalID={2}", | ||
600 | LogHeader, prim.LocalID, Prim.LocalID); | ||
601 | return; | ||
602 | } | 687 | } |
603 | Refresh(); | ||
604 | } | 688 | } |
605 | 689 | ||
606 | #region Known vehicle value functions | 690 | #region Known vehicle value functions |
@@ -617,70 +701,87 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
617 | private Vector3 m_knownPosition; | 701 | private Vector3 m_knownPosition; |
618 | private Vector3 m_knownVelocity; | 702 | private Vector3 m_knownVelocity; |
619 | private Vector3 m_knownForce; | 703 | private Vector3 m_knownForce; |
704 | private Vector3 m_knownForceImpulse; | ||
620 | private Quaternion m_knownOrientation; | 705 | private Quaternion m_knownOrientation; |
621 | private Vector3 m_knownRotationalVelocity; | 706 | private Vector3 m_knownRotationalVelocity; |
622 | private Vector3 m_knownRotationalForce; | 707 | private Vector3 m_knownRotationalForce; |
708 | private Vector3 m_knownRotationalImpulse; | ||
623 | private Vector3 m_knownForwardVelocity; // vehicle relative forward speed | 709 | private Vector3 m_knownForwardVelocity; // vehicle relative forward speed |
624 | 710 | ||
625 | private const int m_knownChangedPosition = 1 << 0; | 711 | private const int m_knownChangedPosition = 1 << 0; |
626 | private const int m_knownChangedVelocity = 1 << 1; | 712 | private const int m_knownChangedVelocity = 1 << 1; |
627 | private const int m_knownChangedForce = 1 << 2; | 713 | private const int m_knownChangedForce = 1 << 2; |
628 | private const int m_knownChangedOrientation = 1 << 3; | 714 | private const int m_knownChangedForceImpulse = 1 << 3; |
629 | private const int m_knownChangedRotationalVelocity = 1 << 4; | 715 | private const int m_knownChangedOrientation = 1 << 4; |
630 | private const int m_knownChangedRotationalForce = 1 << 5; | 716 | private const int m_knownChangedRotationalVelocity = 1 << 5; |
631 | private const int m_knownChangedTerrainHeight = 1 << 6; | 717 | private const int m_knownChangedRotationalForce = 1 << 6; |
632 | private const int m_knownChangedWaterLevel = 1 << 7; | 718 | private const int m_knownChangedRotationalImpulse = 1 << 7; |
633 | private const int m_knownChangedForwardVelocity = 1 << 8; | 719 | private const int m_knownChangedTerrainHeight = 1 << 8; |
634 | 720 | private const int m_knownChangedWaterLevel = 1 << 9; | |
635 | private void ForgetKnownVehicleProperties() | 721 | private const int m_knownChangedForwardVelocity = 1 <<10; |
722 | |||
723 | public void ForgetKnownVehicleProperties() | ||
636 | { | 724 | { |
637 | m_knownHas = 0; | 725 | m_knownHas = 0; |
638 | m_knownChanged = 0; | 726 | m_knownChanged = 0; |
639 | } | 727 | } |
640 | // Push all the changed values back into the physics engine | 728 | // Push all the changed values back into the physics engine |
641 | private void PushKnownChanged() | 729 | public void PushKnownChanged() |
642 | { | 730 | { |
643 | if (m_knownChanged != 0) | 731 | if (m_knownChanged != 0) |
644 | { | 732 | { |
645 | if ((m_knownChanged & m_knownChangedPosition) != 0) | 733 | if ((m_knownChanged & m_knownChangedPosition) != 0) |
646 | Prim.ForcePosition = m_knownPosition; | 734 | ControllingPrim.ForcePosition = m_knownPosition; |
647 | 735 | ||
648 | if ((m_knownChanged & m_knownChangedOrientation) != 0) | 736 | if ((m_knownChanged & m_knownChangedOrientation) != 0) |
649 | Prim.ForceOrientation = m_knownOrientation; | 737 | ControllingPrim.ForceOrientation = m_knownOrientation; |
650 | 738 | ||
651 | if ((m_knownChanged & m_knownChangedVelocity) != 0) | 739 | if ((m_knownChanged & m_knownChangedVelocity) != 0) |
652 | { | 740 | { |
653 | Prim.ForceVelocity = m_knownVelocity; | 741 | ControllingPrim.ForceVelocity = m_knownVelocity; |
654 | PhysicsScene.PE.SetInterpolationLinearVelocity(Prim.PhysBody, VehicleVelocity); | 742 | // Fake out Bullet by making it think the velocity is the same as last time. |
743 | // Bullet does a bunch of smoothing for changing parameters. | ||
744 | // Since the vehicle is demanding this setting, we override Bullet's smoothing | ||
745 | // by telling Bullet the value was the same last time. | ||
746 | // PhysicsScene.PE.SetInterpolationLinearVelocity(Prim.PhysBody, m_knownVelocity); | ||
655 | } | 747 | } |
656 | 748 | ||
657 | if ((m_knownChanged & m_knownChangedForce) != 0) | 749 | if ((m_knownChanged & m_knownChangedForce) != 0) |
658 | Prim.AddForce((Vector3)m_knownForce, false, true); | 750 | ControllingPrim.AddForce((Vector3)m_knownForce, false /*pushForce*/, true /*inTaintTime*/); |
751 | |||
752 | if ((m_knownChanged & m_knownChangedForceImpulse) != 0) | ||
753 | ControllingPrim.AddForceImpulse((Vector3)m_knownForceImpulse, false /*pushforce*/, true /*inTaintTime*/); | ||
659 | 754 | ||
660 | if ((m_knownChanged & m_knownChangedRotationalVelocity) != 0) | 755 | if ((m_knownChanged & m_knownChangedRotationalVelocity) != 0) |
661 | { | 756 | { |
662 | Prim.ForceRotationalVelocity = m_knownRotationalVelocity; | 757 | ControllingPrim.ForceRotationalVelocity = m_knownRotationalVelocity; |
663 | // Fake out Bullet by making it think the velocity is the same as last time. | 758 | // PhysicsScene.PE.SetInterpolationAngularVelocity(Prim.PhysBody, m_knownRotationalVelocity); |
664 | PhysicsScene.PE.SetInterpolationAngularVelocity(Prim.PhysBody, m_knownRotationalVelocity); | ||
665 | } | 759 | } |
666 | 760 | ||
761 | if ((m_knownChanged & m_knownChangedRotationalImpulse) != 0) | ||
762 | ControllingPrim.ApplyTorqueImpulse((Vector3)m_knownRotationalImpulse, true /*inTaintTime*/); | ||
763 | |||
667 | if ((m_knownChanged & m_knownChangedRotationalForce) != 0) | 764 | if ((m_knownChanged & m_knownChangedRotationalForce) != 0) |
668 | Prim.AddAngularForce((Vector3)m_knownRotationalForce, false, true); | 765 | { |
766 | ControllingPrim.AddAngularForce((Vector3)m_knownRotationalForce, false /*pushForce*/, true /*inTaintTime*/); | ||
767 | } | ||
669 | 768 | ||
670 | // If we set one of the values (ie, the physics engine didn't do it) we must force | 769 | // If we set one of the values (ie, the physics engine didn't do it) we must force |
671 | // an UpdateProperties event to send the changes up to the simulator. | 770 | // an UpdateProperties event to send the changes up to the simulator. |
672 | PhysicsScene.PE.PushUpdate(Prim.PhysBody); | 771 | m_physicsScene.PE.PushUpdate(ControllingPrim.PhysBody); |
673 | } | 772 | } |
674 | m_knownChanged = 0; | 773 | m_knownChanged = 0; |
675 | } | 774 | } |
676 | 775 | ||
677 | // Since the computation of terrain height can be a little involved, this routine | 776 | // Since the computation of terrain height can be a little involved, this routine |
678 | // is used to fetch the height only once for each vehicle simulation step. | 777 | // is used to fetch the height only once for each vehicle simulation step. |
778 | Vector3 lastRememberedHeightPos; | ||
679 | private float GetTerrainHeight(Vector3 pos) | 779 | private float GetTerrainHeight(Vector3 pos) |
680 | { | 780 | { |
681 | if ((m_knownHas & m_knownChangedTerrainHeight) == 0) | 781 | if ((m_knownHas & m_knownChangedTerrainHeight) == 0 || pos != lastRememberedHeightPos) |
682 | { | 782 | { |
683 | m_knownTerrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos); | 783 | lastRememberedHeightPos = pos; |
784 | m_knownTerrainHeight = ControllingPrim.PhysScene.TerrainManager.GetTerrainHeightAtXYZ(pos); | ||
684 | m_knownHas |= m_knownChangedTerrainHeight; | 785 | m_knownHas |= m_knownChangedTerrainHeight; |
685 | } | 786 | } |
686 | return m_knownTerrainHeight; | 787 | return m_knownTerrainHeight; |
@@ -692,7 +793,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
692 | { | 793 | { |
693 | if ((m_knownHas & m_knownChangedWaterLevel) == 0) | 794 | if ((m_knownHas & m_knownChangedWaterLevel) == 0) |
694 | { | 795 | { |
695 | m_knownWaterLevel = Prim.PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(pos); | 796 | m_knownWaterLevel = ControllingPrim.PhysScene.TerrainManager.GetWaterLevelAtXYZ(pos); |
696 | m_knownHas |= m_knownChangedWaterLevel; | 797 | m_knownHas |= m_knownChangedWaterLevel; |
697 | } | 798 | } |
698 | return (float)m_knownWaterLevel; | 799 | return (float)m_knownWaterLevel; |
@@ -704,7 +805,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
704 | { | 805 | { |
705 | if ((m_knownHas & m_knownChangedPosition) == 0) | 806 | if ((m_knownHas & m_knownChangedPosition) == 0) |
706 | { | 807 | { |
707 | m_knownPosition = Prim.ForcePosition; | 808 | m_knownPosition = ControllingPrim.ForcePosition; |
708 | m_knownHas |= m_knownChangedPosition; | 809 | m_knownHas |= m_knownChangedPosition; |
709 | } | 810 | } |
710 | return m_knownPosition; | 811 | return m_knownPosition; |
@@ -723,7 +824,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
723 | { | 824 | { |
724 | if ((m_knownHas & m_knownChangedOrientation) == 0) | 825 | if ((m_knownHas & m_knownChangedOrientation) == 0) |
725 | { | 826 | { |
726 | m_knownOrientation = Prim.ForceOrientation; | 827 | m_knownOrientation = ControllingPrim.ForceOrientation; |
727 | m_knownHas |= m_knownChangedOrientation; | 828 | m_knownHas |= m_knownChangedOrientation; |
728 | } | 829 | } |
729 | return m_knownOrientation; | 830 | return m_knownOrientation; |
@@ -742,10 +843,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
742 | { | 843 | { |
743 | if ((m_knownHas & m_knownChangedVelocity) == 0) | 844 | if ((m_knownHas & m_knownChangedVelocity) == 0) |
744 | { | 845 | { |
745 | m_knownVelocity = Prim.ForceVelocity; | 846 | m_knownVelocity = ControllingPrim.ForceVelocity; |
746 | m_knownHas |= m_knownChangedVelocity; | 847 | m_knownHas |= m_knownChangedVelocity; |
747 | } | 848 | } |
748 | return (Vector3)m_knownVelocity; | 849 | return m_knownVelocity; |
749 | } | 850 | } |
750 | set | 851 | set |
751 | { | 852 | { |
@@ -755,15 +856,26 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
755 | } | 856 | } |
756 | } | 857 | } |
757 | 858 | ||
758 | private void VehicleAddForce(Vector3 aForce) | 859 | private void VehicleAddForce(Vector3 pForce) |
759 | { | 860 | { |
760 | if ((m_knownHas & m_knownChangedForce) == 0) | 861 | if ((m_knownHas & m_knownChangedForce) == 0) |
761 | { | 862 | { |
762 | m_knownForce = Vector3.Zero; | 863 | m_knownForce = Vector3.Zero; |
864 | m_knownHas |= m_knownChangedForce; | ||
763 | } | 865 | } |
764 | m_knownForce += aForce; | 866 | m_knownForce += pForce; |
765 | m_knownChanged |= m_knownChangedForce; | 867 | m_knownChanged |= m_knownChangedForce; |
766 | m_knownHas |= m_knownChangedForce; | 868 | } |
869 | |||
870 | private void VehicleAddForceImpulse(Vector3 pImpulse) | ||
871 | { | ||
872 | if ((m_knownHas & m_knownChangedForceImpulse) == 0) | ||
873 | { | ||
874 | m_knownForceImpulse = Vector3.Zero; | ||
875 | m_knownHas |= m_knownChangedForceImpulse; | ||
876 | } | ||
877 | m_knownForceImpulse += pImpulse; | ||
878 | m_knownChanged |= m_knownChangedForceImpulse; | ||
767 | } | 879 | } |
768 | 880 | ||
769 | private Vector3 VehicleRotationalVelocity | 881 | private Vector3 VehicleRotationalVelocity |
@@ -772,7 +884,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
772 | { | 884 | { |
773 | if ((m_knownHas & m_knownChangedRotationalVelocity) == 0) | 885 | if ((m_knownHas & m_knownChangedRotationalVelocity) == 0) |
774 | { | 886 | { |
775 | m_knownRotationalVelocity = Prim.ForceRotationalVelocity; | 887 | m_knownRotationalVelocity = ControllingPrim.ForceRotationalVelocity; |
776 | m_knownHas |= m_knownChangedRotationalVelocity; | 888 | m_knownHas |= m_knownChangedRotationalVelocity; |
777 | } | 889 | } |
778 | return (Vector3)m_knownRotationalVelocity; | 890 | return (Vector3)m_knownRotationalVelocity; |
@@ -794,6 +906,17 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
794 | m_knownChanged |= m_knownChangedRotationalForce; | 906 | m_knownChanged |= m_knownChangedRotationalForce; |
795 | m_knownHas |= m_knownChangedRotationalForce; | 907 | m_knownHas |= m_knownChangedRotationalForce; |
796 | } | 908 | } |
909 | private void VehicleAddRotationalImpulse(Vector3 pImpulse) | ||
910 | { | ||
911 | if ((m_knownHas & m_knownChangedRotationalImpulse) == 0) | ||
912 | { | ||
913 | m_knownRotationalImpulse = Vector3.Zero; | ||
914 | m_knownHas |= m_knownChangedRotationalImpulse; | ||
915 | } | ||
916 | m_knownRotationalImpulse += pImpulse; | ||
917 | m_knownChanged |= m_knownChangedRotationalImpulse; | ||
918 | } | ||
919 | |||
797 | // Vehicle relative forward velocity | 920 | // Vehicle relative forward velocity |
798 | private Vector3 VehicleForwardVelocity | 921 | private Vector3 VehicleForwardVelocity |
799 | { | 922 | { |
@@ -822,9 +945,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
822 | { | 945 | { |
823 | if (!IsActive) return; | 946 | if (!IsActive) return; |
824 | 947 | ||
825 | if (PhysicsScene.VehiclePhysicalLoggingEnabled) | ||
826 | PhysicsScene.PE.DumpRigidBody(PhysicsScene.World, Prim.PhysBody); | ||
827 | |||
828 | ForgetKnownVehicleProperties(); | 948 | ForgetKnownVehicleProperties(); |
829 | 949 | ||
830 | MoveLinear(pTimestep); | 950 | MoveLinear(pTimestep); |
@@ -839,106 +959,116 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
839 | // for the physics engine to note the changes so an UpdateProperties event will happen. | 959 | // for the physics engine to note the changes so an UpdateProperties event will happen. |
840 | PushKnownChanged(); | 960 | PushKnownChanged(); |
841 | 961 | ||
842 | if (PhysicsScene.VehiclePhysicalLoggingEnabled) | 962 | if (m_physicsScene.VehiclePhysicalLoggingEnabled) |
843 | PhysicsScene.PE.DumpRigidBody(PhysicsScene.World, Prim.PhysBody); | 963 | m_physicsScene.PE.DumpRigidBody(m_physicsScene.World, ControllingPrim.PhysBody); |
844 | 964 | ||
845 | VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", | 965 | VDetailLog("{0},BSDynamics.Step,done,pos={1}, force={2},velocity={3},angvel={4}", |
846 | Prim.LocalID, VehiclePosition, Prim.Force, VehicleVelocity, VehicleRotationalVelocity); | 966 | ControllingPrim.LocalID, VehiclePosition, m_knownForce, VehicleVelocity, VehicleRotationalVelocity); |
847 | } | 967 | } |
848 | 968 | ||
849 | // Apply the effect of the linear motor and other linear motions (like hover and float). | 969 | // Called after the simulation step |
850 | private void MoveLinear(float pTimestep) | 970 | internal void PostStep(float pTimestep) |
851 | { | 971 | { |
852 | Vector3 linearMotorContribution = m_linearMotor.Step(pTimestep); | 972 | if (!IsActive) return; |
853 | 973 | ||
854 | // The movement computed in the linear motor is relative to the vehicle | 974 | if (m_physicsScene.VehiclePhysicalLoggingEnabled) |
855 | // coordinates. Rotate the movement to world coordinates. | 975 | m_physicsScene.PE.DumpRigidBody(m_physicsScene.World, ControllingPrim.PhysBody); |
856 | linearMotorContribution *= VehicleOrientation; | 976 | } |
857 | 977 | ||
858 | // ================================================================== | 978 | // Apply the effect of the linear motor and other linear motions (like hover and float). |
859 | // Buoyancy: force to overcome gravity. | 979 | private void MoveLinear(float pTimestep) |
860 | // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; | 980 | { |
861 | // So, if zero, don't change anything (let gravity happen). If one, negate the effect of gravity. | 981 | ComputeLinearVelocity(pTimestep); |
862 | Vector3 buoyancyContribution = Prim.PhysicsScene.DefaultGravity * m_VehicleBuoyancy; | ||
863 | 982 | ||
864 | Vector3 terrainHeightContribution = ComputeLinearTerrainHeightCorrection(pTimestep); | 983 | ComputeLinearTerrainHeightCorrection(pTimestep); |
865 | 984 | ||
866 | Vector3 hoverContribution = ComputeLinearHover(pTimestep); | 985 | ComputeLinearHover(pTimestep); |
867 | 986 | ||
868 | ComputeLinearBlockingEndPoint(pTimestep); | 987 | ComputeLinearBlockingEndPoint(pTimestep); |
869 | 988 | ||
870 | Vector3 limitMotorUpContribution = ComputeLinearMotorUp(pTimestep); | 989 | ComputeLinearMotorUp(pTimestep); |
871 | 990 | ||
872 | // ================================================================== | 991 | ApplyGravity(pTimestep); |
873 | Vector3 newVelocity = linearMotorContribution | ||
874 | + terrainHeightContribution | ||
875 | + hoverContribution | ||
876 | + limitMotorUpContribution; | ||
877 | |||
878 | Vector3 newForce = buoyancyContribution; | ||
879 | 992 | ||
880 | // If not changing some axis, reduce out velocity | 993 | // If not changing some axis, reduce out velocity |
881 | if ((m_flags & (VehicleFlag.NO_X)) != 0) | 994 | if ((m_flags & (VehicleFlag.NO_X | VehicleFlag.NO_Y | VehicleFlag.NO_Z)) != 0) |
882 | newVelocity.X = 0; | 995 | { |
883 | if ((m_flags & (VehicleFlag.NO_Y)) != 0) | 996 | Vector3 vel = VehicleVelocity; |
884 | newVelocity.Y = 0; | 997 | if ((m_flags & (VehicleFlag.NO_X)) != 0) |
885 | if ((m_flags & (VehicleFlag.NO_Z)) != 0) | 998 | vel.X = 0; |
886 | newVelocity.Z = 0; | 999 | if ((m_flags & (VehicleFlag.NO_Y)) != 0) |
1000 | vel.Y = 0; | ||
1001 | if ((m_flags & (VehicleFlag.NO_Z)) != 0) | ||
1002 | vel.Z = 0; | ||
1003 | VehicleVelocity = vel; | ||
1004 | } | ||
887 | 1005 | ||
888 | // ================================================================== | 1006 | // ================================================================== |
889 | // Clamp high or low velocities | 1007 | // Clamp high or low velocities |
890 | float newVelocityLengthSq = newVelocity.LengthSquared(); | 1008 | float newVelocityLengthSq = VehicleVelocity.LengthSquared(); |
891 | if (newVelocityLengthSq > 1000f) | 1009 | if (newVelocityLengthSq > BSParam.VehicleMaxLinearVelocitySquared) |
892 | { | 1010 | { |
893 | newVelocity /= newVelocity.Length(); | 1011 | Vector3 origVelW = VehicleVelocity; // DEBUG DEBUG |
894 | newVelocity *= 1000f; | 1012 | VehicleVelocity /= VehicleVelocity.Length(); |
1013 | VehicleVelocity *= BSParam.VehicleMaxLinearVelocity; | ||
1014 | VDetailLog("{0}, MoveLinear,clampMax,origVelW={1},lenSq={2},maxVelSq={3},,newVelW={4}", | ||
1015 | ControllingPrim.LocalID, origVelW, newVelocityLengthSq, BSParam.VehicleMaxLinearVelocitySquared, VehicleVelocity); | ||
895 | } | 1016 | } |
896 | else if (newVelocityLengthSq < 0.001f) | 1017 | else if (newVelocityLengthSq < 0.001f) |
897 | newVelocity = Vector3.Zero; | 1018 | VehicleVelocity = Vector3.Zero; |
898 | 1019 | ||
899 | // ================================================================== | 1020 | VDetailLog("{0}, MoveLinear,done,isColl={1},newVel={2}", ControllingPrim.LocalID, ControllingPrim.IsColliding, VehicleVelocity ); |
900 | // Stuff new linear velocity into the vehicle. | 1021 | |
901 | // Since the velocity is just being set, it is not scaled by pTimeStep. Bullet will do that for us. | 1022 | } // end MoveLinear() |
902 | VehicleVelocity = newVelocity; | 1023 | |
1024 | public void ComputeLinearVelocity(float pTimestep) | ||
1025 | { | ||
1026 | // Step the motor from the current value. Get the correction needed this step. | ||
1027 | Vector3 origVelW = VehicleVelocity; // DEBUG | ||
1028 | Vector3 currentVelV = VehicleVelocity * Quaternion.Inverse(VehicleOrientation); | ||
1029 | Vector3 linearMotorCorrectionV = m_linearMotor.Step(pTimestep, currentVelV); | ||
1030 | |||
1031 | // Friction reduces vehicle motion | ||
1032 | Vector3 frictionFactorW = ComputeFrictionFactor(m_linearFrictionTimescale, pTimestep); | ||
1033 | linearMotorCorrectionV -= (currentVelV * frictionFactorW); | ||
903 | 1034 | ||
904 | // Other linear forces are applied as forces. | 1035 | // Motor is vehicle coordinates. Rotate it to world coordinates |
905 | Vector3 totalDownForce = newForce * m_vehicleMass; | 1036 | Vector3 linearMotorVelocityW = linearMotorCorrectionV * VehicleOrientation; |
906 | if (!totalDownForce.ApproxEquals(Vector3.Zero, 0.01f)) | 1037 | |
1038 | // If we're a ground vehicle, don't add any upward Z movement | ||
1039 | if ((m_flags & VehicleFlag.LIMIT_MOTOR_UP) != 0) | ||
907 | { | 1040 | { |
908 | VehicleAddForce(totalDownForce); | 1041 | if (linearMotorVelocityW.Z > 0f) |
1042 | linearMotorVelocityW.Z = 0f; | ||
909 | } | 1043 | } |
910 | 1044 | ||
911 | VDetailLog("{0}, MoveLinear,done,newVel={1},totDown={2},IsColliding={3}", | 1045 | // Add this correction to the velocity to make it faster/slower. |
912 | Prim.LocalID, newVelocity, totalDownForce, Prim.IsColliding); | 1046 | VehicleVelocity += linearMotorVelocityW; |
913 | VDetailLog("{0}, MoveLinear,done,linContrib={1},terrContrib={2},hoverContrib={3},limitContrib={4},buoyContrib={5}", | ||
914 | Prim.LocalID, | ||
915 | linearMotorContribution, terrainHeightContribution, hoverContribution, | ||
916 | limitMotorUpContribution, buoyancyContribution | ||
917 | ); | ||
918 | 1047 | ||
919 | } // end MoveLinear() | ||
920 | 1048 | ||
921 | public Vector3 ComputeLinearTerrainHeightCorrection(float pTimestep) | 1049 | |
1050 | VDetailLog("{0}, MoveLinear,velocity,origVelW={1},velV={2},correctV={3},correctW={4},newVelW={5},fricFact={6}", | ||
1051 | ControllingPrim.LocalID, origVelW, currentVelV, linearMotorCorrectionV, | ||
1052 | linearMotorVelocityW, VehicleVelocity, frictionFactorW); | ||
1053 | } | ||
1054 | |||
1055 | public void ComputeLinearTerrainHeightCorrection(float pTimestep) | ||
922 | { | 1056 | { |
923 | Vector3 ret = Vector3.Zero; | ||
924 | // If below the terrain, move us above the ground a little. | 1057 | // If below the terrain, move us above the ground a little. |
925 | // TODO: Consider taking the rotated size of the object or possibly casting a ray. | 1058 | // TODO: Consider taking the rotated size of the object or possibly casting a ray. |
926 | if (VehiclePosition.Z < GetTerrainHeight(VehiclePosition)) | 1059 | if (VehiclePosition.Z < GetTerrainHeight(VehiclePosition)) |
927 | { | 1060 | { |
928 | // TODO: correct position by applying force rather than forcing position. | 1061 | // Force position because applying force won't get the vehicle through the terrain |
929 | Vector3 newPosition = VehiclePosition; | 1062 | Vector3 newPosition = VehiclePosition; |
930 | newPosition.Z = GetTerrainHeight(VehiclePosition) + 1f; | 1063 | newPosition.Z = GetTerrainHeight(VehiclePosition) + 1f; |
931 | VehiclePosition = newPosition; | 1064 | VehiclePosition = newPosition; |
932 | VDetailLog("{0}, MoveLinear,terrainHeight,terrainHeight={1},pos={2}", | 1065 | VDetailLog("{0}, MoveLinear,terrainHeight,terrainHeight={1},pos={2}", |
933 | Prim.LocalID, GetTerrainHeight(VehiclePosition), VehiclePosition); | 1066 | ControllingPrim.LocalID, GetTerrainHeight(VehiclePosition), VehiclePosition); |
934 | } | 1067 | } |
935 | return ret; | ||
936 | } | 1068 | } |
937 | 1069 | ||
938 | public Vector3 ComputeLinearHover(float pTimestep) | 1070 | public void ComputeLinearHover(float pTimestep) |
939 | { | 1071 | { |
940 | Vector3 ret = Vector3.Zero; | ||
941 | |||
942 | // m_VhoverEfficiency: 0=bouncy, 1=totally damped | 1072 | // m_VhoverEfficiency: 0=bouncy, 1=totally damped |
943 | // m_VhoverTimescale: time to achieve height | 1073 | // m_VhoverTimescale: time to achieve height |
944 | if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) | 1074 | if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) |
@@ -963,7 +1093,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
963 | if (VehiclePosition.Z > m_VhoverTargetHeight) | 1093 | if (VehiclePosition.Z > m_VhoverTargetHeight) |
964 | m_VhoverTargetHeight = VehiclePosition.Z; | 1094 | m_VhoverTargetHeight = VehiclePosition.Z; |
965 | } | 1095 | } |
966 | 1096 | ||
967 | if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) | 1097 | if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) |
968 | { | 1098 | { |
969 | if (Math.Abs(VehiclePosition.Z - m_VhoverTargetHeight) > 0.2f) | 1099 | if (Math.Abs(VehiclePosition.Z - m_VhoverTargetHeight) > 0.2f) |
@@ -971,26 +1101,42 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
971 | Vector3 pos = VehiclePosition; | 1101 | Vector3 pos = VehiclePosition; |
972 | pos.Z = m_VhoverTargetHeight; | 1102 | pos.Z = m_VhoverTargetHeight; |
973 | VehiclePosition = pos; | 1103 | VehiclePosition = pos; |
1104 | |||
1105 | VDetailLog("{0}, MoveLinear,hover,pos={1},lockHoverHeight", ControllingPrim.LocalID, pos); | ||
974 | } | 1106 | } |
975 | } | 1107 | } |
976 | else | 1108 | else |
977 | { | 1109 | { |
978 | // Error is positive if below the target and negative if above. | 1110 | // Error is positive if below the target and negative if above. |
979 | float verticalError = m_VhoverTargetHeight - VehiclePosition.Z; | 1111 | Vector3 hpos = VehiclePosition; |
1112 | float verticalError = m_VhoverTargetHeight - hpos.Z; | ||
1113 | float verticalCorrection = verticalError / m_VhoverTimescale; | ||
1114 | verticalCorrection *= m_VhoverEfficiency; | ||
1115 | |||
1116 | hpos.Z += verticalCorrection; | ||
1117 | VehiclePosition = hpos; | ||
1118 | |||
1119 | // Since we are hovering, we need to do the opposite of falling -- get rid of world Z | ||
1120 | Vector3 vel = VehicleVelocity; | ||
1121 | vel.Z = 0f; | ||
1122 | VehicleVelocity = vel; | ||
1123 | |||
1124 | /* | ||
980 | float verticalCorrectionVelocity = verticalError / m_VhoverTimescale; | 1125 | float verticalCorrectionVelocity = verticalError / m_VhoverTimescale; |
1126 | Vector3 verticalCorrection = new Vector3(0f, 0f, verticalCorrectionVelocity); | ||
1127 | verticalCorrection *= m_vehicleMass; | ||
981 | 1128 | ||
982 | // TODO: implement m_VhoverEfficiency correctly | 1129 | // TODO: implement m_VhoverEfficiency correctly |
983 | if (Math.Abs(verticalError) > m_VhoverEfficiency) | 1130 | VehicleAddForceImpulse(verticalCorrection); |
984 | { | 1131 | */ |
985 | ret = new Vector3(0f, 0f, verticalCorrectionVelocity); | 1132 | |
986 | } | 1133 | VDetailLog("{0}, MoveLinear,hover,pos={1},eff={2},hoverTS={3},height={4},target={5},err={6},corr={7}", |
1134 | ControllingPrim.LocalID, VehiclePosition, m_VhoverEfficiency, | ||
1135 | m_VhoverTimescale, m_VhoverHeight, m_VhoverTargetHeight, | ||
1136 | verticalError, verticalCorrection); | ||
987 | } | 1137 | } |
988 | 1138 | ||
989 | VDetailLog("{0}, MoveLinear,hover,pos={1},ret={2},hoverTS={3},height={4},target={5}", | ||
990 | Prim.LocalID, VehiclePosition, ret, m_VhoverTimescale, m_VhoverHeight, m_VhoverTargetHeight); | ||
991 | } | 1139 | } |
992 | |||
993 | return ret; | ||
994 | } | 1140 | } |
995 | 1141 | ||
996 | public bool ComputeLinearBlockingEndPoint(float pTimestep) | 1142 | public bool ComputeLinearBlockingEndPoint(float pTimestep) |
@@ -1030,7 +1176,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1030 | { | 1176 | { |
1031 | VehiclePosition = pos; | 1177 | VehiclePosition = pos; |
1032 | VDetailLog("{0}, MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", | 1178 | VDetailLog("{0}, MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", |
1033 | Prim.LocalID, m_BlockingEndPoint, posChange, pos); | 1179 | ControllingPrim.LocalID, m_BlockingEndPoint, posChange, pos); |
1034 | } | 1180 | } |
1035 | } | 1181 | } |
1036 | return changed; | 1182 | return changed; |
@@ -1041,34 +1187,75 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1041 | // used with conjunction with banking: the strength of the banking will decay when the | 1187 | // used with conjunction with banking: the strength of the banking will decay when the |
1042 | // vehicle no longer experiences collisions. The decay timescale is the same as | 1188 | // vehicle no longer experiences collisions. The decay timescale is the same as |
1043 | // VEHICLE_BANKING_TIMESCALE. This is to help prevent ground vehicles from steering | 1189 | // VEHICLE_BANKING_TIMESCALE. This is to help prevent ground vehicles from steering |
1044 | // when they are in mid jump. | 1190 | // when they are in mid jump. |
1045 | // TODO: this code is wrong. Also, what should it do for boats (height from water)? | 1191 | // TODO: this code is wrong. Also, what should it do for boats (height from water)? |
1046 | // This is just using the ground and a general collision check. Should really be using | 1192 | // This is just using the ground and a general collision check. Should really be using |
1047 | // a downward raycast to find what is below. | 1193 | // a downward raycast to find what is below. |
1048 | public Vector3 ComputeLinearMotorUp(float pTimestep) | 1194 | public void ComputeLinearMotorUp(float pTimestep) |
1049 | { | 1195 | { |
1050 | Vector3 ret = Vector3.Zero; | ||
1051 | float distanceAboveGround = 0f; | ||
1052 | |||
1053 | if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) | 1196 | if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) |
1054 | { | 1197 | { |
1198 | // This code tries to decide if the object is not on the ground and then pushing down | ||
1199 | /* | ||
1055 | float targetHeight = Type == Vehicle.TYPE_BOAT ? GetWaterLevel(VehiclePosition) : GetTerrainHeight(VehiclePosition); | 1200 | float targetHeight = Type == Vehicle.TYPE_BOAT ? GetWaterLevel(VehiclePosition) : GetTerrainHeight(VehiclePosition); |
1056 | distanceAboveGround = VehiclePosition.Z - targetHeight; | 1201 | distanceAboveGround = VehiclePosition.Z - targetHeight; |
1057 | // Not colliding if the vehicle is off the ground | 1202 | // Not colliding if the vehicle is off the ground |
1058 | if (!Prim.IsColliding) | 1203 | if (!Prim.IsColliding) |
1059 | { | 1204 | { |
1060 | // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale); | 1205 | // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale); |
1061 | ret = new Vector3(0, 0, -distanceAboveGround); | 1206 | VehicleVelocity += new Vector3(0, 0, -distanceAboveGround); |
1062 | } | 1207 | } |
1063 | // TODO: this calculation is wrong. From the description at | 1208 | // TODO: this calculation is wrong. From the description at |
1064 | // (http://wiki.secondlife.com/wiki/Category:LSL_Vehicle), the downForce | 1209 | // (http://wiki.secondlife.com/wiki/Category:LSL_Vehicle), the downForce |
1065 | // has a decay factor. This says this force should | 1210 | // has a decay factor. This says this force should |
1066 | // be computed with a motor. | 1211 | // be computed with a motor. |
1067 | // TODO: add interaction with banking. | 1212 | // TODO: add interaction with banking. |
1068 | } | 1213 | VDetailLog("{0}, MoveLinear,limitMotorUp,distAbove={1},colliding={2},ret={3}", |
1069 | VDetailLog("{0}, MoveLinear,limitMotorUp,distAbove={1},colliding={2},ret={3}", | ||
1070 | Prim.LocalID, distanceAboveGround, Prim.IsColliding, ret); | 1214 | Prim.LocalID, distanceAboveGround, Prim.IsColliding, ret); |
1071 | return ret; | 1215 | */ |
1216 | |||
1217 | // Another approach is to measure if we're going up. If going up and not colliding, | ||
1218 | // the vehicle is in the air. Fix that by pushing down. | ||
1219 | if (!ControllingPrim.IsColliding && VehicleVelocity.Z > 0.1) | ||
1220 | { | ||
1221 | // Get rid of any of the velocity vector that is pushing us up. | ||
1222 | float upVelocity = VehicleVelocity.Z; | ||
1223 | VehicleVelocity += new Vector3(0, 0, -upVelocity); | ||
1224 | |||
1225 | /* | ||
1226 | // If we're pointed up into the air, we should nose down | ||
1227 | Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation; | ||
1228 | // The rotation around the Y axis is pitch up or down | ||
1229 | if (pointingDirection.Y > 0.01f) | ||
1230 | { | ||
1231 | float angularCorrectionForce = -(float)Math.Asin(pointingDirection.Y); | ||
1232 | Vector3 angularCorrectionVector = new Vector3(0f, angularCorrectionForce, 0f); | ||
1233 | // Rotate into world coordinates and apply to vehicle | ||
1234 | angularCorrectionVector *= VehicleOrientation; | ||
1235 | VehicleAddAngularForce(angularCorrectionVector); | ||
1236 | VDetailLog("{0}, MoveLinear,limitMotorUp,newVel={1},pntDir={2},corrFrc={3},aCorr={4}", | ||
1237 | Prim.LocalID, VehicleVelocity, pointingDirection, angularCorrectionForce, angularCorrectionVector); | ||
1238 | } | ||
1239 | */ | ||
1240 | VDetailLog("{0}, MoveLinear,limitMotorUp,collide={1},upVel={2},newVel={3}", | ||
1241 | ControllingPrim.LocalID, ControllingPrim.IsColliding, upVelocity, VehicleVelocity); | ||
1242 | } | ||
1243 | } | ||
1244 | } | ||
1245 | |||
1246 | private void ApplyGravity(float pTimeStep) | ||
1247 | { | ||
1248 | Vector3 appliedGravity = m_VehicleGravity * m_vehicleMass; | ||
1249 | |||
1250 | // Hack to reduce downward force if the vehicle is probably sitting on the ground | ||
1251 | if (ControllingPrim.IsColliding && IsGroundVehicle) | ||
1252 | appliedGravity *= BSParam.VehicleGroundGravityFudge; | ||
1253 | |||
1254 | VehicleAddForce(appliedGravity); | ||
1255 | |||
1256 | VDetailLog("{0}, MoveLinear,applyGravity,vehGrav={1},collid={2},fudge={3},mass={4},appliedForce={3}", | ||
1257 | ControllingPrim.LocalID, m_VehicleGravity, | ||
1258 | ControllingPrim.IsColliding, BSParam.VehicleGroundGravityFudge, m_vehicleMass, appliedGravity); | ||
1072 | } | 1259 | } |
1073 | 1260 | ||
1074 | // ======================================================================= | 1261 | // ======================================================================= |
@@ -1079,55 +1266,24 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1079 | // set directly on the vehicle. | 1266 | // set directly on the vehicle. |
1080 | private void MoveAngular(float pTimestep) | 1267 | private void MoveAngular(float pTimestep) |
1081 | { | 1268 | { |
1082 | // The user wants this many radians per second angular change? | 1269 | ComputeAngularTurning(pTimestep); |
1083 | Vector3 angularMotorContribution = m_angularMotor.Step(pTimestep); | ||
1084 | 1270 | ||
1085 | // ================================================================== | 1271 | ComputeAngularVerticalAttraction(); |
1086 | // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags : | ||
1087 | // This flag prevents linear deflection parallel to world z-axis. This is useful | ||
1088 | // for preventing ground vehicles with large linear deflection, like bumper cars, | ||
1089 | // from climbing their linear deflection into the sky. | ||
1090 | // That is, NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement | ||
1091 | if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) | ||
1092 | { | ||
1093 | angularMotorContribution.X = 0f; | ||
1094 | angularMotorContribution.Y = 0f; | ||
1095 | VDetailLog("{0}, MoveAngular,noDeflectionUp,angularMotorContrib={1}", Prim.LocalID, angularMotorContribution); | ||
1096 | } | ||
1097 | |||
1098 | Vector3 verticalAttractionContribution = ComputeAngularVerticalAttraction(); | ||
1099 | 1272 | ||
1100 | Vector3 deflectionContribution = ComputeAngularDeflection(); | 1273 | ComputeAngularDeflection(); |
1101 | 1274 | ||
1102 | Vector3 bankingContribution = ComputeAngularBanking(); | 1275 | ComputeAngularBanking(); |
1103 | 1276 | ||
1104 | // ================================================================== | 1277 | // ================================================================== |
1105 | m_lastVertAttractor = verticalAttractionContribution; | 1278 | if (VehicleRotationalVelocity.ApproxEquals(Vector3.Zero, 0.0001f)) |
1106 | |||
1107 | m_lastAngularVelocity = angularMotorContribution | ||
1108 | + verticalAttractionContribution | ||
1109 | + deflectionContribution | ||
1110 | + bankingContribution; | ||
1111 | |||
1112 | // ================================================================== | ||
1113 | // Apply the correction velocity. | ||
1114 | // TODO: Should this be applied as an angular force (torque)? | ||
1115 | if (!m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) | ||
1116 | { | 1279 | { |
1117 | VehicleRotationalVelocity = m_lastAngularVelocity; | 1280 | // The vehicle is not adding anything angular wise. |
1118 | 1281 | VehicleRotationalVelocity = Vector3.Zero; | |
1119 | VDetailLog("{0}, MoveAngular,done,nonZero,angMotorContrib={1},vertAttrContrib={2},bankContrib={3},deflectContrib={4},totalContrib={5}", | 1282 | VDetailLog("{0}, MoveAngular,done,zero", ControllingPrim.LocalID); |
1120 | Prim.LocalID, | ||
1121 | angularMotorContribution, verticalAttractionContribution, | ||
1122 | bankingContribution, deflectionContribution, | ||
1123 | m_lastAngularVelocity | ||
1124 | ); | ||
1125 | } | 1283 | } |
1126 | else | 1284 | else |
1127 | { | 1285 | { |
1128 | // The vehicle is not adding anything angular wise. | 1286 | VDetailLog("{0}, MoveAngular,done,nonZero,angVel={1}", ControllingPrim.LocalID, VehicleRotationalVelocity); |
1129 | VehicleRotationalVelocity = Vector3.Zero; | ||
1130 | VDetailLog("{0}, MoveAngular,done,zero", Prim.LocalID); | ||
1131 | } | 1287 | } |
1132 | 1288 | ||
1133 | // ================================================================== | 1289 | // ================================================================== |
@@ -1158,10 +1314,42 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1158 | torqueFromOffset.Z = 0; | 1314 | torqueFromOffset.Z = 0; |
1159 | 1315 | ||
1160 | VehicleAddAngularForce(torqueFromOffset * m_vehicleMass); | 1316 | VehicleAddAngularForce(torqueFromOffset * m_vehicleMass); |
1161 | VDetailLog("{0}, BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", Prim.LocalID, torqueFromOffset); | 1317 | VDetailLog("{0}, BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", ControllingPrim.LocalID, torqueFromOffset); |
1162 | } | 1318 | } |
1163 | 1319 | ||
1164 | } | 1320 | } |
1321 | |||
1322 | private void ComputeAngularTurning(float pTimestep) | ||
1323 | { | ||
1324 | // The user wants this many radians per second angular change? | ||
1325 | Vector3 currentAngularV = VehicleRotationalVelocity * Quaternion.Inverse(VehicleOrientation); | ||
1326 | Vector3 angularMotorContributionV = m_angularMotor.Step(pTimestep, currentAngularV); | ||
1327 | |||
1328 | // ================================================================== | ||
1329 | // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags : | ||
1330 | // This flag prevents linear deflection parallel to world z-axis. This is useful | ||
1331 | // for preventing ground vehicles with large linear deflection, like bumper cars, | ||
1332 | // from climbing their linear deflection into the sky. | ||
1333 | // That is, NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement | ||
1334 | // TODO: This is here because this is where ODE put it but documentation says it | ||
1335 | // is a linear effect. Where should this check go? | ||
1336 | //if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) | ||
1337 | // { | ||
1338 | // angularMotorContributionV.X = 0f; | ||
1339 | // angularMotorContributionV.Y = 0f; | ||
1340 | // } | ||
1341 | |||
1342 | // Reduce any velocity by friction. | ||
1343 | Vector3 frictionFactorW = ComputeFrictionFactor(m_angularFrictionTimescale, pTimestep); | ||
1344 | angularMotorContributionV -= (currentAngularV * frictionFactorW); | ||
1345 | |||
1346 | VehicleRotationalVelocity += angularMotorContributionV * VehicleOrientation; | ||
1347 | |||
1348 | |||
1349 | |||
1350 | VDetailLog("{0}, MoveAngular,angularTurning,angContribV={1}", ControllingPrim.LocalID, angularMotorContributionV); | ||
1351 | } | ||
1352 | |||
1165 | // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial: | 1353 | // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial: |
1166 | // Some vehicles, like boats, should always keep their up-side up. This can be done by | 1354 | // Some vehicles, like boats, should always keep their up-side up. This can be done by |
1167 | // enabling the "vertical attractor" behavior that springs the vehicle's local z-axis to | 1355 | // enabling the "vertical attractor" behavior that springs the vehicle's local z-axis to |
@@ -1170,15 +1358,84 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1170 | // and then set the VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY to control the damping. An | 1358 | // and then set the VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY to control the damping. An |
1171 | // efficiency of 0.0 will cause the spring to wobble around its equilibrium, while an | 1359 | // efficiency of 0.0 will cause the spring to wobble around its equilibrium, while an |
1172 | // efficiency of 1.0 will cause the spring to reach its equilibrium with exponential decay. | 1360 | // efficiency of 1.0 will cause the spring to reach its equilibrium with exponential decay. |
1173 | public Vector3 ComputeAngularVerticalAttraction() | 1361 | public void ComputeAngularVerticalAttraction() |
1174 | { | 1362 | { |
1175 | Vector3 ret = Vector3.Zero; | ||
1176 | 1363 | ||
1177 | // If vertical attaction timescale is reasonable | 1364 | // If vertical attaction timescale is reasonable |
1178 | if (m_verticalAttractionTimescale < m_verticalAttractionCutoff) | 1365 | if (enableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff) |
1179 | { | 1366 | { |
1367 | //Another formula to try got from : | ||
1368 | //http://answers.unity3d.com/questions/10425/how-to-stabilize-angular-motion-alignment-of-hover.html | ||
1369 | |||
1370 | Vector3 VehicleUpAxis = Vector3.UnitZ * VehicleOrientation; | ||
1371 | |||
1372 | // Flipping what was originally a timescale into a speed variable and then multiplying it by 2 | ||
1373 | // since only computing half the distance between the angles. | ||
1374 | float VerticalAttractionSpeed = (1 / m_verticalAttractionTimescale) * 2.0f; | ||
1375 | |||
1376 | // Make a prediction of where the up axis will be when this is applied rather then where it is now as | ||
1377 | // this makes for a smoother adjustment and less fighting between the various forces. | ||
1378 | Vector3 predictedUp = VehicleUpAxis * Quaternion.CreateFromAxisAngle(VehicleRotationalVelocity, 0f); | ||
1379 | |||
1380 | // This is only half the distance to the target so it will take 2 seconds to complete the turn. | ||
1381 | Vector3 torqueVector = Vector3.Cross(predictedUp, Vector3.UnitZ); | ||
1382 | |||
1383 | // Scale vector by our timescale since it is an acceleration it is r/s^2 or radians a timescale squared | ||
1384 | Vector3 vertContributionV = torqueVector * VerticalAttractionSpeed * VerticalAttractionSpeed; | ||
1385 | |||
1386 | VehicleRotationalVelocity += vertContributionV; | ||
1387 | |||
1388 | VDetailLog("{0}, MoveAngular,verticalAttraction,UpAxis={1},PredictedUp={2},torqueVector={3},contrib={4}", | ||
1389 | ControllingPrim.LocalID, | ||
1390 | VehicleUpAxis, | ||
1391 | predictedUp, | ||
1392 | torqueVector, | ||
1393 | vertContributionV); | ||
1394 | //===================================================================== | ||
1395 | /* | ||
1396 | // Possible solution derived from a discussion at: | ||
1397 | // http://stackoverflow.com/questions/14939657/computing-vector-from-quaternion-works-computing-quaternion-from-vector-does-no | ||
1398 | |||
1399 | // Create a rotation that is only the vehicle's rotation around Z | ||
1400 | Vector3 currentEuler = Vector3.Zero; | ||
1401 | VehicleOrientation.GetEulerAngles(out currentEuler.X, out currentEuler.Y, out currentEuler.Z); | ||
1402 | Quaternion justZOrientation = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, currentEuler.Z); | ||
1403 | |||
1404 | // Create the axis that is perpendicular to the up vector and the rotated up vector. | ||
1405 | Vector3 differenceAxis = Vector3.Cross(Vector3.UnitZ * justZOrientation, Vector3.UnitZ * VehicleOrientation); | ||
1406 | // Compute the angle between those to vectors. | ||
1407 | double differenceAngle = Math.Acos((double)Vector3.Dot(Vector3.UnitZ, Vector3.Normalize(Vector3.UnitZ * VehicleOrientation))); | ||
1408 | // 'differenceAngle' is the angle to rotate and 'differenceAxis' is the plane to rotate in to get the vehicle vertical | ||
1409 | |||
1410 | // Reduce the change by the time period it is to change in. Timestep is handled when velocity is applied. | ||
1411 | // TODO: add 'efficiency'. | ||
1412 | differenceAngle /= m_verticalAttractionTimescale; | ||
1413 | |||
1414 | // Create the quaterian representing the correction angle | ||
1415 | Quaternion correctionRotation = Quaternion.CreateFromAxisAngle(differenceAxis, (float)differenceAngle); | ||
1416 | |||
1417 | // Turn that quaternion into Euler values to make it into velocities to apply. | ||
1418 | Vector3 vertContributionV = Vector3.Zero; | ||
1419 | correctionRotation.GetEulerAngles(out vertContributionV.X, out vertContributionV.Y, out vertContributionV.Z); | ||
1420 | vertContributionV *= -1f; | ||
1421 | |||
1422 | VehicleRotationalVelocity += vertContributionV; | ||
1423 | |||
1424 | VDetailLog("{0}, MoveAngular,verticalAttraction,diffAxis={1},diffAng={2},corrRot={3},contrib={4}", | ||
1425 | ControllingPrim.LocalID, | ||
1426 | differenceAxis, | ||
1427 | differenceAngle, | ||
1428 | correctionRotation, | ||
1429 | vertContributionV); | ||
1430 | */ | ||
1431 | |||
1432 | // =================================================================== | ||
1433 | /* | ||
1434 | Vector3 vertContributionV = Vector3.Zero; | ||
1435 | Vector3 origRotVelW = VehicleRotationalVelocity; // DEBUG DEBUG | ||
1436 | |||
1180 | // Take a vector pointing up and convert it from world to vehicle relative coords. | 1437 | // Take a vector pointing up and convert it from world to vehicle relative coords. |
1181 | Vector3 verticalError = Vector3.UnitZ * VehicleOrientation; | 1438 | Vector3 verticalError = Vector3.Normalize(Vector3.UnitZ * VehicleOrientation); |
1182 | 1439 | ||
1183 | // If vertical attraction correction is needed, the vector that was pointing up (UnitZ) | 1440 | // If vertical attraction correction is needed, the vector that was pointing up (UnitZ) |
1184 | // is now: | 1441 | // is now: |
@@ -1190,49 +1447,57 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1190 | 1447 | ||
1191 | // Y error means needed rotation around X axis and visa versa. | 1448 | // Y error means needed rotation around X axis and visa versa. |
1192 | // Since the error goes from zero to one, the asin is the corresponding angle. | 1449 | // Since the error goes from zero to one, the asin is the corresponding angle. |
1193 | ret.X = (float)Math.Asin(verticalError.Y); | 1450 | vertContributionV.X = (float)Math.Asin(verticalError.Y); |
1194 | // (Tilt forward (positive X) needs to tilt back (rotate negative) around Y axis.) | 1451 | // (Tilt forward (positive X) needs to tilt back (rotate negative) around Y axis.) |
1195 | ret.Y = -(float)Math.Asin(verticalError.X); | 1452 | vertContributionV.Y = -(float)Math.Asin(verticalError.X); |
1196 | 1453 | ||
1197 | // If verticalError.Z is negative, the vehicle is upside down. Add additional push. | 1454 | // If verticalError.Z is negative, the vehicle is upside down. Add additional push. |
1198 | if (verticalError.Z < 0f) | 1455 | if (verticalError.Z < 0f) |
1199 | { | 1456 | { |
1200 | ret.X += PIOverFour; | 1457 | vertContributionV.X += Math.Sign(vertContributionV.X) * PIOverFour; |
1201 | ret.Y += PIOverFour; | 1458 | // vertContribution.Y -= PIOverFour; |
1202 | } | 1459 | } |
1203 | 1460 | ||
1204 | // 'ret' is now the necessary velocity to correct tilt in one second. | 1461 | // 'vertContrbution' is now the necessary angular correction to correct tilt in one second. |
1205 | // Correction happens over a number of seconds. | 1462 | // Correction happens over a number of seconds. |
1206 | Vector3 unscaledContrib = ret; | 1463 | Vector3 unscaledContribVerticalErrorV = vertContributionV; // DEBUG DEBUG |
1207 | ret /= m_verticalAttractionTimescale; | 1464 | |
1465 | // The correction happens over the user's time period | ||
1466 | vertContributionV /= m_verticalAttractionTimescale; | ||
1208 | 1467 | ||
1209 | VDetailLog("{0}, MoveAngular,verticalAttraction,,verticalError={1},unscaled={2},eff={3},ts={4},vertAttr={5}", | 1468 | // Rotate the vehicle rotation to the world coordinates. |
1210 | Prim.LocalID, verticalError, unscaledContrib, m_verticalAttractionEfficiency, m_verticalAttractionTimescale, ret); | 1469 | VehicleRotationalVelocity += (vertContributionV * VehicleOrientation); |
1470 | |||
1471 | VDetailLog("{0}, MoveAngular,verticalAttraction,,origRotVW={1},vertError={2},unscaledV={3},eff={4},ts={5},vertContribV={6}", | ||
1472 | Prim.LocalID, origRotVelW, verticalError, unscaledContribVerticalErrorV, | ||
1473 | m_verticalAttractionEfficiency, m_verticalAttractionTimescale, vertContributionV); | ||
1474 | */ | ||
1211 | } | 1475 | } |
1212 | return ret; | ||
1213 | } | 1476 | } |
1214 | 1477 | ||
1215 | // Return the angular correction to correct the direction the vehicle is pointing to be | 1478 | // Angular correction to correct the direction the vehicle is pointing to be |
1216 | // the direction is should want to be pointing. | 1479 | // the direction is should want to be pointing. |
1217 | // The vehicle is moving in some direction and correct its orientation to it is pointing | 1480 | // The vehicle is moving in some direction and correct its orientation to it is pointing |
1218 | // in that direction. | 1481 | // in that direction. |
1219 | // TODO: implement reference frame. | 1482 | // TODO: implement reference frame. |
1220 | public Vector3 ComputeAngularDeflection() | 1483 | public void ComputeAngularDeflection() |
1221 | { | 1484 | { |
1222 | Vector3 ret = Vector3.Zero; | ||
1223 | return ret; // DEBUG DEBUG DEBUG | ||
1224 | // Disable angular deflection for the moment. | ||
1225 | // Since angularMotorUp and angularDeflection are computed independently, they will calculate | 1485 | // Since angularMotorUp and angularDeflection are computed independently, they will calculate |
1226 | // approximately the same X or Y correction. When added together (when contributions are combined) | 1486 | // approximately the same X or Y correction. When added together (when contributions are combined) |
1227 | // this creates an over-correction and then wabbling as the target is overshot. | 1487 | // this creates an over-correction and then wabbling as the target is overshot. |
1228 | // TODO: rethink how the different correction computations inter-relate. | 1488 | // TODO: rethink how the different correction computations inter-relate. |
1229 | 1489 | ||
1230 | if (m_angularDeflectionEfficiency != 0) | 1490 | if (enableAngularDeflection && m_angularDeflectionEfficiency != 0 && VehicleForwardSpeed > 0.2) |
1231 | { | 1491 | { |
1492 | Vector3 deflectContributionV = Vector3.Zero; | ||
1493 | |||
1232 | // The direction the vehicle is moving | 1494 | // The direction the vehicle is moving |
1233 | Vector3 movingDirection = VehicleVelocity; | 1495 | Vector3 movingDirection = VehicleVelocity; |
1234 | movingDirection.Normalize(); | 1496 | movingDirection.Normalize(); |
1235 | 1497 | ||
1498 | // If the vehicle is going backward, it is still pointing forward | ||
1499 | movingDirection *= Math.Sign(VehicleForwardSpeed); | ||
1500 | |||
1236 | // The direction the vehicle is pointing | 1501 | // The direction the vehicle is pointing |
1237 | Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation; | 1502 | Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation; |
1238 | pointingDirection.Normalize(); | 1503 | pointingDirection.Normalize(); |
@@ -1241,6 +1506,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1241 | Vector3 deflectionError = movingDirection - pointingDirection; | 1506 | Vector3 deflectionError = movingDirection - pointingDirection; |
1242 | 1507 | ||
1243 | // Don't try to correct very large errors (not our job) | 1508 | // Don't try to correct very large errors (not our job) |
1509 | // if (Math.Abs(deflectionError.X) > PIOverFour) deflectionError.X = PIOverTwo * Math.Sign(deflectionError.X); | ||
1510 | // if (Math.Abs(deflectionError.Y) > PIOverFour) deflectionError.Y = PIOverTwo * Math.Sign(deflectionError.Y); | ||
1511 | // if (Math.Abs(deflectionError.Z) > PIOverFour) deflectionError.Z = PIOverTwo * Math.Sign(deflectionError.Z); | ||
1244 | if (Math.Abs(deflectionError.X) > PIOverFour) deflectionError.X = 0f; | 1512 | if (Math.Abs(deflectionError.X) > PIOverFour) deflectionError.X = 0f; |
1245 | if (Math.Abs(deflectionError.Y) > PIOverFour) deflectionError.Y = 0f; | 1513 | if (Math.Abs(deflectionError.Y) > PIOverFour) deflectionError.Y = 0f; |
1246 | if (Math.Abs(deflectionError.Z) > PIOverFour) deflectionError.Z = 0f; | 1514 | if (Math.Abs(deflectionError.Z) > PIOverFour) deflectionError.Z = 0f; |
@@ -1248,18 +1516,19 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1248 | // ret = m_angularDeflectionCorrectionMotor(1f, deflectionError); | 1516 | // ret = m_angularDeflectionCorrectionMotor(1f, deflectionError); |
1249 | 1517 | ||
1250 | // Scale the correction by recovery timescale and efficiency | 1518 | // Scale the correction by recovery timescale and efficiency |
1251 | ret = (-deflectionError) * m_angularDeflectionEfficiency; | 1519 | deflectContributionV = (-deflectionError) * m_angularDeflectionEfficiency; |
1252 | ret /= m_angularDeflectionTimescale; | 1520 | deflectContributionV /= m_angularDeflectionTimescale; |
1521 | |||
1522 | VehicleRotationalVelocity += deflectContributionV * VehicleOrientation; | ||
1253 | 1523 | ||
1254 | VDetailLog("{0}, MoveAngular,Deflection,movingDir={1},pointingDir={2},deflectError={3},ret={4}", | 1524 | VDetailLog("{0}, MoveAngular,Deflection,movingDir={1},pointingDir={2},deflectError={3},ret={4}", |
1255 | Prim.LocalID, movingDirection, pointingDirection, deflectionError, ret); | 1525 | ControllingPrim.LocalID, movingDirection, pointingDirection, deflectionError, deflectContributionV); |
1256 | VDetailLog("{0}, MoveAngular,Deflection,fwdSpd={1},defEff={2},defTS={3}", | 1526 | VDetailLog("{0}, MoveAngular,Deflection,fwdSpd={1},defEff={2},defTS={3}", |
1257 | Prim.LocalID, VehicleForwardSpeed, m_angularDeflectionEfficiency, m_angularDeflectionTimescale); | 1527 | ControllingPrim.LocalID, VehicleForwardSpeed, m_angularDeflectionEfficiency, m_angularDeflectionTimescale); |
1258 | } | 1528 | } |
1259 | return ret; | ||
1260 | } | 1529 | } |
1261 | 1530 | ||
1262 | // Return an angular change to rotate the vehicle around the Z axis when the vehicle | 1531 | // Angular change to rotate the vehicle around the Z axis when the vehicle |
1263 | // is tipped around the X axis. | 1532 | // is tipped around the X axis. |
1264 | // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial: | 1533 | // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial: |
1265 | // The vertical attractor feature must be enabled in order for the banking behavior to | 1534 | // The vertical attractor feature must be enabled in order for the banking behavior to |
@@ -1267,13 +1536,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1267 | // produce a angular velocity around the yaw-axis, causing the vehicle to turn. The magnitude | 1536 | // produce a angular velocity around the yaw-axis, causing the vehicle to turn. The magnitude |
1268 | // of the yaw effect will be proportional to the | 1537 | // of the yaw effect will be proportional to the |
1269 | // VEHICLE_BANKING_EFFICIENCY, the angle of the roll rotation, and sometimes the vehicle's | 1538 | // VEHICLE_BANKING_EFFICIENCY, the angle of the roll rotation, and sometimes the vehicle's |
1270 | // velocity along its preferred axis of motion. | 1539 | // velocity along its preferred axis of motion. |
1271 | // The VEHICLE_BANKING_EFFICIENCY can vary between -1 and +1. When it is positive then any | 1540 | // The VEHICLE_BANKING_EFFICIENCY can vary between -1 and +1. When it is positive then any |
1272 | // positive rotation (by the right-hand rule) about the roll-axis will effect a | 1541 | // positive rotation (by the right-hand rule) about the roll-axis will effect a |
1273 | // (negative) torque around the yaw-axis, making it turn to the right--that is the | 1542 | // (negative) torque around the yaw-axis, making it turn to the right--that is the |
1274 | // vehicle will lean into the turn, which is how real airplanes and motorcycle's work. | 1543 | // vehicle will lean into the turn, which is how real airplanes and motorcycle's work. |
1275 | // Negating the banking coefficient will make it so that the vehicle leans to the | 1544 | // Negating the banking coefficient will make it so that the vehicle leans to the |
1276 | // outside of the turn (not very "physical" but might allow interesting vehicles so why not?). | 1545 | // outside of the turn (not very "physical" but might allow interesting vehicles so why not?). |
1277 | // The VEHICLE_BANKING_MIX is a fake (i.e. non-physical) parameter that is useful for making | 1546 | // The VEHICLE_BANKING_MIX is a fake (i.e. non-physical) parameter that is useful for making |
1278 | // banking vehicles do what you want rather than what the laws of physics allow. | 1547 | // banking vehicles do what you want rather than what the laws of physics allow. |
1279 | // For example, consider a real motorcycle...it must be moving forward in order for | 1548 | // For example, consider a real motorcycle...it must be moving forward in order for |
@@ -1285,46 +1554,44 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1285 | // totally static (0.0) and totally dynamic (1.0). By "static" we mean that the | 1554 | // totally static (0.0) and totally dynamic (1.0). By "static" we mean that the |
1286 | // banking effect depends only on the vehicle's rotation about its roll-axis compared | 1555 | // banking effect depends only on the vehicle's rotation about its roll-axis compared |
1287 | // to "dynamic" where the banking is also proportional to its velocity along its | 1556 | // to "dynamic" where the banking is also proportional to its velocity along its |
1288 | // roll-axis. Finding the best value of the "mixture" will probably require trial and error. | 1557 | // roll-axis. Finding the best value of the "mixture" will probably require trial and error. |
1289 | // The time it takes for the banking behavior to defeat a preexisting angular velocity about the | 1558 | // The time it takes for the banking behavior to defeat a preexisting angular velocity about the |
1290 | // world z-axis is determined by the VEHICLE_BANKING_TIMESCALE. So if you want the vehicle to | 1559 | // world z-axis is determined by the VEHICLE_BANKING_TIMESCALE. So if you want the vehicle to |
1291 | // bank quickly then give it a banking timescale of about a second or less, otherwise you can | 1560 | // bank quickly then give it a banking timescale of about a second or less, otherwise you can |
1292 | // make a sluggish vehicle by giving it a timescale of several seconds. | 1561 | // make a sluggish vehicle by giving it a timescale of several seconds. |
1293 | public Vector3 ComputeAngularBanking() | 1562 | public void ComputeAngularBanking() |
1294 | { | 1563 | { |
1295 | Vector3 ret = Vector3.Zero; | 1564 | if (enableAngularBanking && m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff) |
1296 | |||
1297 | if (m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff) | ||
1298 | { | 1565 | { |
1299 | // This works by rotating a unit vector to the orientation of the vehicle. The | 1566 | Vector3 bankingContributionV = Vector3.Zero; |
1300 | // roll (tilt) will be Y component of a tilting Z vector (zero for no tilt | 1567 | |
1301 | // up to one for full over). | 1568 | // Rotate a UnitZ vector (pointing up) to how the vehicle is oriented. |
1569 | // As the vehicle rolls to the right or left, the Y value will increase from | ||
1570 | // zero (straight up) to 1 or -1 (full tilt right or left) | ||
1302 | Vector3 rollComponents = Vector3.UnitZ * VehicleOrientation; | 1571 | Vector3 rollComponents = Vector3.UnitZ * VehicleOrientation; |
1303 | 1572 | ||
1304 | // Figure out the yaw value for this much roll. | 1573 | // Figure out the yaw value for this much roll. |
1305 | float turnComponent = rollComponents.Y * rollComponents.Y * m_bankingEfficiency; | 1574 | float yawAngle = m_angularMotorDirection.X * m_bankingEfficiency; |
1306 | // Keep the sign | ||
1307 | if (rollComponents.Y < 0f) | ||
1308 | turnComponent = -turnComponent; | ||
1309 | |||
1310 | // TODO: there must be a better computation of the banking force. | ||
1311 | float bankingTurnForce = turnComponent; | ||
1312 | |||
1313 | // actual error = static turn error + dynamic turn error | 1575 | // actual error = static turn error + dynamic turn error |
1314 | float mixedBankingError = bankingTurnForce * (1f - m_bankingMix) + bankingTurnForce * m_bankingMix * VehicleForwardSpeed; | 1576 | float mixedYawAngle =(yawAngle * (1f - m_bankingMix)) + ((yawAngle * m_bankingMix) * VehicleForwardSpeed); |
1577 | |||
1315 | // TODO: the banking effect should not go to infinity but what to limit it to? | 1578 | // TODO: the banking effect should not go to infinity but what to limit it to? |
1316 | mixedBankingError = ClampInRange(-20f, mixedBankingError, 20f); | 1579 | // And what should happen when this is being added to a user defined yaw that is already PI*4? |
1580 | mixedYawAngle = ClampInRange(-12, mixedYawAngle, 12); | ||
1317 | 1581 | ||
1318 | // Build the force vector to change rotation from what it is to what it should be | 1582 | // Build the force vector to change rotation from what it is to what it should be |
1319 | ret.Z = -mixedBankingError; | 1583 | bankingContributionV.Z = -mixedYawAngle; |
1584 | |||
1585 | // Don't do it all at once. Fudge because 1 second is too fast with most user defined roll as PI*4. | ||
1586 | bankingContributionV /= m_bankingTimescale * BSParam.VehicleAngularBankingTimescaleFudge; | ||
1320 | 1587 | ||
1321 | // Don't do it all at once. | 1588 | //VehicleRotationalVelocity += bankingContributionV * VehicleOrientation; |
1322 | ret /= m_bankingTimescale; | 1589 | VehicleRotationalVelocity += bankingContributionV; |
1323 | 1590 | ||
1324 | VDetailLog("{0}, MoveAngular,Banking,rollComp={1},speed={2},turnComp={3},bankErr={4},mixedBankErr={5},ret={6}", | 1591 | |
1325 | Prim.LocalID, rollComponents, VehicleForwardSpeed, turnComponent, bankingTurnForce, mixedBankingError, ret); | 1592 | VDetailLog("{0}, MoveAngular,Banking,rollComp={1},speed={2},rollComp={3},yAng={4},mYAng={5},ret={6}", |
1593 | ControllingPrim.LocalID, rollComponents, VehicleForwardSpeed, rollComponents, yawAngle, mixedYawAngle, bankingContributionV); | ||
1326 | } | 1594 | } |
1327 | return ret; | ||
1328 | } | 1595 | } |
1329 | 1596 | ||
1330 | // This is from previous instantiations of XXXDynamics.cs. | 1597 | // This is from previous instantiations of XXXDynamics.cs. |
@@ -1362,11 +1629,28 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1362 | if (rotq != m_rot) | 1629 | if (rotq != m_rot) |
1363 | { | 1630 | { |
1364 | VehicleOrientation = m_rot; | 1631 | VehicleOrientation = m_rot; |
1365 | VDetailLog("{0}, LimitRotation,done,orig={1},new={2}", Prim.LocalID, rotq, m_rot); | 1632 | VDetailLog("{0}, LimitRotation,done,orig={1},new={2}", ControllingPrim.LocalID, rotq, m_rot); |
1366 | } | 1633 | } |
1367 | 1634 | ||
1368 | } | 1635 | } |
1369 | 1636 | ||
1637 | // Given a friction vector (reduction in seconds) and a timestep, return the factor to reduce | ||
1638 | // some value by to apply this friction. | ||
1639 | private Vector3 ComputeFrictionFactor(Vector3 friction, float pTimestep) | ||
1640 | { | ||
1641 | Vector3 frictionFactor = Vector3.Zero; | ||
1642 | if (friction != BSMotor.InfiniteVector) | ||
1643 | { | ||
1644 | // frictionFactor = (Vector3.One / FrictionTimescale) * timeStep; | ||
1645 | // Individual friction components can be 'infinite' so compute each separately. | ||
1646 | frictionFactor.X = (friction.X == BSMotor.Infinite) ? 0f : (1f / friction.X); | ||
1647 | frictionFactor.Y = (friction.Y == BSMotor.Infinite) ? 0f : (1f / friction.Y); | ||
1648 | frictionFactor.Z = (friction.Z == BSMotor.Infinite) ? 0f : (1f / friction.Z); | ||
1649 | frictionFactor *= pTimestep; | ||
1650 | } | ||
1651 | return frictionFactor; | ||
1652 | } | ||
1653 | |||
1370 | private float ClampInRange(float low, float val, float high) | 1654 | private float ClampInRange(float low, float val, float high) |
1371 | { | 1655 | { |
1372 | return Math.Max(low, Math.Min(val, high)); | 1656 | return Math.Max(low, Math.Min(val, high)); |
@@ -1376,8 +1660,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
1376 | // Invoke the detailed logger and output something if it's enabled. | 1660 | // Invoke the detailed logger and output something if it's enabled. |
1377 | private void VDetailLog(string msg, params Object[] args) | 1661 | private void VDetailLog(string msg, params Object[] args) |
1378 | { | 1662 | { |
1379 | if (Prim.PhysicsScene.VehicleLoggingEnabled) | 1663 | if (ControllingPrim.PhysScene.VehicleLoggingEnabled) |
1380 | Prim.PhysicsScene.DetailLog(msg, args); | 1664 | ControllingPrim.PhysScene.DetailLog(msg, args); |
1381 | } | 1665 | } |
1382 | } | 1666 | } |
1383 | } | 1667 | } |