diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/PhysicsModules/BulletS/BSDynamics.cs (renamed from OpenSim/Region/Physics/BulletSNPlugin/BSDynamics.cs) | 1099 |
1 files changed, 761 insertions, 338 deletions
diff --git a/OpenSim/Region/Physics/BulletSNPlugin/BSDynamics.cs b/OpenSim/Region/PhysicsModules/BulletS/BSDynamics.cs index 415ad4f..0fc5577 100644 --- a/OpenSim/Region/Physics/BulletSNPlugin/BSDynamics.cs +++ b/OpenSim/Region/PhysicsModules/BulletS/BSDynamics.cs | |||
@@ -35,17 +35,21 @@ 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.Region.Physics.Manager; | 38 | using OpenSim.Framework; |
39 | using OpenSim.Region.PhysicsModules.SharedBase; | ||
39 | 40 | ||
40 | namespace OpenSim.Region.Physics.BulletSNPlugin | 41 | namespace OpenSim.Region.PhysicsModule.BulletS |
41 | { | 42 | { |
42 | public sealed class BSDynamics | 43 | public sealed class BSDynamics : BSActor |
43 | { | 44 | { |
45 | #pragma warning disable 414 | ||
44 | private static string LogHeader = "[BULLETSIM VEHICLE]"; | 46 | private static string LogHeader = "[BULLETSIM VEHICLE]"; |
47 | #pragma warning restore 414 | ||
45 | 48 | ||
46 | private BSScene PhysicsScene { get; set; } | ||
47 | // the prim this dynamic controller belongs to | 49 | // the prim this dynamic controller belongs to |
48 | private BSPrim Prim { get; set; } | 50 | private BSPrimLinkable ControllingPrim { get; set; } |
51 | |||
52 | private bool m_haveRegisteredForSceneEvents; | ||
49 | 53 | ||
50 | // mass of the vehicle fetched each time we're calles | 54 | // mass of the vehicle fetched each time we're calles |
51 | private float m_vehicleMass; | 55 | private float m_vehicleMass; |
@@ -72,8 +76,8 @@ namespace OpenSim.Region.Physics.BulletSNPlugin | |||
72 | private Vector3 m_linearMotorOffset = Vector3.Zero; // the point of force can be offset from the center | 76 | private Vector3 m_linearMotorOffset = Vector3.Zero; // the point of force can be offset from the center |
73 | private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL | 77 | private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL |
74 | private Vector3 m_linearFrictionTimescale = Vector3.Zero; | 78 | private Vector3 m_linearFrictionTimescale = Vector3.Zero; |
75 | private float m_linearMotorDecayTimescale = 0; | 79 | private float m_linearMotorDecayTimescale = 1; |
76 | private float m_linearMotorTimescale = 0; | 80 | private float m_linearMotorTimescale = 1; |
77 | private Vector3 m_lastLinearVelocityVector = Vector3.Zero; | 81 | private Vector3 m_lastLinearVelocityVector = Vector3.Zero; |
78 | private Vector3 m_lastPositionVector = Vector3.Zero; | 82 | private Vector3 m_lastPositionVector = Vector3.Zero; |
79 | // private bool m_LinearMotorSetLastFrame = false; | 83 | // private bool m_LinearMotorSetLastFrame = false; |
@@ -84,8 +88,8 @@ namespace OpenSim.Region.Physics.BulletSNPlugin | |||
84 | private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor | 88 | private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor |
85 | // private int m_angularMotorApply = 0; // application frame counter | 89 | // private int m_angularMotorApply = 0; // application frame counter |
86 | private Vector3 m_angularMotorVelocity = Vector3.Zero; // current angular motor velocity | 90 | private Vector3 m_angularMotorVelocity = Vector3.Zero; // current angular motor velocity |
87 | private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate | 91 | private float m_angularMotorTimescale = 1; // motor angular velocity ramp up rate |
88 | private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate | 92 | private float m_angularMotorDecayTimescale = 1; // motor angular velocity decay rate |
89 | private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate | 93 | private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate |
90 | private Vector3 m_lastAngularVelocity = Vector3.Zero; | 94 | private Vector3 m_lastAngularVelocity = Vector3.Zero; |
91 | private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body | 95 | private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body |
@@ -99,7 +103,7 @@ namespace OpenSim.Region.Physics.BulletSNPlugin | |||
99 | 103 | ||
100 | //Banking properties | 104 | //Banking properties |
101 | private float m_bankingEfficiency = 0; | 105 | private float m_bankingEfficiency = 0; |
102 | private float m_bankingMix = 0; | 106 | private float m_bankingMix = 1; |
103 | private float m_bankingTimescale = 0; | 107 | private float m_bankingTimescale = 0; |
104 | 108 | ||
105 | //Hover and Buoyancy properties | 109 | //Hover and Buoyancy properties |
@@ -108,10 +112,9 @@ namespace OpenSim.Region.Physics.BulletSNPlugin | |||
108 | private float m_VhoverEfficiency = 0f; | 112 | private float m_VhoverEfficiency = 0f; |
109 | private float m_VhoverTimescale = 0f; | 113 | private float m_VhoverTimescale = 0f; |
110 | private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height | 114 | 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. | 115 | // 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) | 116 | private float m_VehicleBuoyancy = 0f; |
113 | // KF: So far I have found no good method to combine a script-requested .Z velocity and gravity. | 117 | 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 | 118 | ||
116 | //Attractor properties | 119 | //Attractor properties |
117 | private BSVMotor m_verticalAttractionMotor = new BSVMotor("VerticalAttraction"); | 120 | private BSVMotor m_verticalAttractionMotor = new BSVMotor("VerticalAttraction"); |
@@ -121,74 +124,95 @@ namespace OpenSim.Region.Physics.BulletSNPlugin | |||
121 | private float m_verticalAttractionTimescale = 510f; | 124 | private float m_verticalAttractionTimescale = 510f; |
122 | 125 | ||
123 | // Just some recomputed constants: | 126 | // Just some recomputed constants: |
127 | #pragma warning disable 414 | ||
128 | static readonly float TwoPI = ((float)Math.PI) * 2f; | ||
129 | static readonly float FourPI = ((float)Math.PI) * 4f; | ||
124 | static readonly float PIOverFour = ((float)Math.PI) / 4f; | 130 | static readonly float PIOverFour = ((float)Math.PI) / 4f; |
125 | static readonly float PIOverTwo = ((float)Math.PI) / 2f; | 131 | static readonly float PIOverTwo = ((float)Math.PI) / 2f; |
132 | #pragma warning restore 414 | ||
126 | 133 | ||
127 | public BSDynamics(BSScene myScene, BSPrim myPrim) | 134 | public BSDynamics(BSScene myScene, BSPrim myPrim, string actorName) |
135 | : base(myScene, myPrim, actorName) | ||
128 | { | 136 | { |
129 | PhysicsScene = myScene; | ||
130 | Prim = myPrim; | ||
131 | Type = Vehicle.TYPE_NONE; | 137 | Type = Vehicle.TYPE_NONE; |
138 | m_haveRegisteredForSceneEvents = false; | ||
139 | |||
140 | ControllingPrim = myPrim as BSPrimLinkable; | ||
141 | if (ControllingPrim == null) | ||
142 | { | ||
143 | // THIS CANNOT HAPPEN!! | ||
144 | } | ||
145 | VDetailLog("{0},Creation", ControllingPrim.LocalID); | ||
132 | } | 146 | } |
133 | 147 | ||
134 | // Return 'true' if this vehicle is doing vehicle things | 148 | // Return 'true' if this vehicle is doing vehicle things |
135 | public bool IsActive | 149 | public bool IsActive |
136 | { | 150 | { |
137 | get { return Type != Vehicle.TYPE_NONE && Prim.IsPhysical; } | 151 | get { return (Type != Vehicle.TYPE_NONE && ControllingPrim.IsPhysicallyActive); } |
152 | } | ||
153 | |||
154 | // Return 'true' if this a vehicle that should be sitting on the ground | ||
155 | public bool IsGroundVehicle | ||
156 | { | ||
157 | get { return (Type == Vehicle.TYPE_CAR || Type == Vehicle.TYPE_SLED); } | ||
138 | } | 158 | } |
139 | 159 | ||
140 | internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue) | 160 | #region Vehicle parameter setting |
161 | public void ProcessFloatVehicleParam(Vehicle pParam, float pValue) | ||
141 | { | 162 | { |
142 | VDetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue); | 163 | VDetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", ControllingPrim.LocalID, pParam, pValue); |
164 | float clampTemp; | ||
165 | |||
143 | switch (pParam) | 166 | switch (pParam) |
144 | { | 167 | { |
145 | case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: | 168 | case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: |
146 | m_angularDeflectionEfficiency = Math.Max(pValue, 0.01f); | 169 | m_angularDeflectionEfficiency = ClampInRange(0f, pValue, 1f); |
147 | break; | 170 | break; |
148 | case Vehicle.ANGULAR_DEFLECTION_TIMESCALE: | 171 | case Vehicle.ANGULAR_DEFLECTION_TIMESCALE: |
149 | m_angularDeflectionTimescale = Math.Max(pValue, 0.01f); | 172 | m_angularDeflectionTimescale = ClampInRange(0.25f, pValue, 120); |
150 | break; | 173 | break; |
151 | case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE: | 174 | case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE: |
152 | m_angularMotorDecayTimescale = ClampInRange(0.01f, pValue, 120); | 175 | m_angularMotorDecayTimescale = ClampInRange(0.25f, pValue, 120); |
153 | m_angularMotor.TargetValueDecayTimeScale = m_angularMotorDecayTimescale; | 176 | m_angularMotor.TargetValueDecayTimeScale = m_angularMotorDecayTimescale; |
154 | break; | 177 | break; |
155 | case Vehicle.ANGULAR_MOTOR_TIMESCALE: | 178 | case Vehicle.ANGULAR_MOTOR_TIMESCALE: |
156 | m_angularMotorTimescale = Math.Max(pValue, 0.01f); | 179 | m_angularMotorTimescale = ClampInRange(0.25f, pValue, 120); |
157 | m_angularMotor.TimeScale = m_angularMotorTimescale; | 180 | m_angularMotor.TimeScale = m_angularMotorTimescale; |
158 | break; | 181 | break; |
159 | case Vehicle.BANKING_EFFICIENCY: | 182 | case Vehicle.BANKING_EFFICIENCY: |
160 | m_bankingEfficiency = ClampInRange(-1f, pValue, 1f); | 183 | m_bankingEfficiency = ClampInRange(-1f, pValue, 1f); |
161 | break; | 184 | break; |
162 | case Vehicle.BANKING_MIX: | 185 | case Vehicle.BANKING_MIX: |
163 | m_bankingMix = Math.Max(pValue, 0.01f); | 186 | m_bankingMix = ClampInRange(0.01f, pValue, 1); |
164 | break; | 187 | break; |
165 | case Vehicle.BANKING_TIMESCALE: | 188 | case Vehicle.BANKING_TIMESCALE: |
166 | m_bankingTimescale = Math.Max(pValue, 0.01f); | 189 | m_bankingTimescale = ClampInRange(0.25f, pValue, 120); |
167 | break; | 190 | break; |
168 | case Vehicle.BUOYANCY: | 191 | case Vehicle.BUOYANCY: |
169 | m_VehicleBuoyancy = ClampInRange(-1f, pValue, 1f); | 192 | m_VehicleBuoyancy = ClampInRange(-1f, pValue, 1f); |
193 | m_VehicleGravity = ControllingPrim.ComputeGravity(m_VehicleBuoyancy); | ||
170 | break; | 194 | break; |
171 | case Vehicle.HOVER_EFFICIENCY: | 195 | case Vehicle.HOVER_EFFICIENCY: |
172 | m_VhoverEfficiency = ClampInRange(0f, pValue, 1f); | 196 | m_VhoverEfficiency = ClampInRange(0.01f, pValue, 1f); |
173 | break; | 197 | break; |
174 | case Vehicle.HOVER_HEIGHT: | 198 | case Vehicle.HOVER_HEIGHT: |
175 | m_VhoverHeight = pValue; | 199 | m_VhoverHeight = ClampInRange(0f, pValue, 1000000f); |
176 | break; | 200 | break; |
177 | case Vehicle.HOVER_TIMESCALE: | 201 | case Vehicle.HOVER_TIMESCALE: |
178 | m_VhoverTimescale = Math.Max(pValue, 0.01f); | 202 | m_VhoverTimescale = ClampInRange(0.01f, pValue, 120); |
179 | break; | 203 | break; |
180 | case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: | 204 | case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: |
181 | m_linearDeflectionEfficiency = Math.Max(pValue, 0.01f); | 205 | m_linearDeflectionEfficiency = ClampInRange(0f, pValue, 1f); |
182 | break; | 206 | break; |
183 | case Vehicle.LINEAR_DEFLECTION_TIMESCALE: | 207 | case Vehicle.LINEAR_DEFLECTION_TIMESCALE: |
184 | m_linearDeflectionTimescale = Math.Max(pValue, 0.01f); | 208 | m_linearDeflectionTimescale = ClampInRange(0.01f, pValue, 120); |
185 | break; | 209 | break; |
186 | case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE: | 210 | case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE: |
187 | m_linearMotorDecayTimescale = ClampInRange(0.01f, pValue, 120); | 211 | m_linearMotorDecayTimescale = ClampInRange(0.01f, pValue, 120); |
188 | m_linearMotor.TargetValueDecayTimeScale = m_linearMotorDecayTimescale; | 212 | m_linearMotor.TargetValueDecayTimeScale = m_linearMotorDecayTimescale; |
189 | break; | 213 | break; |
190 | case Vehicle.LINEAR_MOTOR_TIMESCALE: | 214 | case Vehicle.LINEAR_MOTOR_TIMESCALE: |
191 | m_linearMotorTimescale = Math.Max(pValue, 0.01f); | 215 | m_linearMotorTimescale = ClampInRange(0.01f, pValue, 120); |
192 | m_linearMotor.TimeScale = m_linearMotorTimescale; | 216 | m_linearMotor.TimeScale = m_linearMotorTimescale; |
193 | break; | 217 | break; |
194 | case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY: | 218 | case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY: |
@@ -196,31 +220,35 @@ namespace OpenSim.Region.Physics.BulletSNPlugin | |||
196 | m_verticalAttractionMotor.Efficiency = m_verticalAttractionEfficiency; | 220 | m_verticalAttractionMotor.Efficiency = m_verticalAttractionEfficiency; |
197 | break; | 221 | break; |
198 | case Vehicle.VERTICAL_ATTRACTION_TIMESCALE: | 222 | case Vehicle.VERTICAL_ATTRACTION_TIMESCALE: |
199 | m_verticalAttractionTimescale = Math.Max(pValue, 0.01f); | 223 | m_verticalAttractionTimescale = ClampInRange(0.01f, pValue, 120); |
200 | m_verticalAttractionMotor.TimeScale = m_verticalAttractionTimescale; | 224 | m_verticalAttractionMotor.TimeScale = m_verticalAttractionTimescale; |
201 | break; | 225 | break; |
202 | 226 | ||
203 | // These are vector properties but the engine lets you use a single float value to | 227 | // These are vector properties but the engine lets you use a single float value to |
204 | // set all of the components to the same value | 228 | // set all of the components to the same value |
205 | case Vehicle.ANGULAR_FRICTION_TIMESCALE: | 229 | case Vehicle.ANGULAR_FRICTION_TIMESCALE: |
206 | m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue); | 230 | clampTemp = ClampInRange(0.01f, pValue, 120); |
207 | m_angularMotor.FrictionTimescale = m_angularFrictionTimescale; | 231 | m_angularFrictionTimescale = new Vector3(clampTemp, clampTemp, clampTemp); |
208 | break; | 232 | break; |
209 | case Vehicle.ANGULAR_MOTOR_DIRECTION: | 233 | case Vehicle.ANGULAR_MOTOR_DIRECTION: |
210 | m_angularMotorDirection = new Vector3(pValue, pValue, pValue); | 234 | clampTemp = ClampInRange(-TwoPI, pValue, TwoPI); |
235 | m_angularMotorDirection = new Vector3(clampTemp, clampTemp, clampTemp); | ||
236 | m_angularMotor.Zero(); | ||
211 | m_angularMotor.SetTarget(m_angularMotorDirection); | 237 | m_angularMotor.SetTarget(m_angularMotorDirection); |
212 | break; | 238 | break; |
213 | case Vehicle.LINEAR_FRICTION_TIMESCALE: | 239 | case Vehicle.LINEAR_FRICTION_TIMESCALE: |
214 | m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); | 240 | clampTemp = ClampInRange(0.01f, pValue, 120); |
215 | m_linearMotor.FrictionTimescale = m_linearFrictionTimescale; | 241 | m_linearFrictionTimescale = new Vector3(clampTemp, clampTemp, clampTemp); |
216 | break; | 242 | break; |
217 | case Vehicle.LINEAR_MOTOR_DIRECTION: | 243 | case Vehicle.LINEAR_MOTOR_DIRECTION: |
218 | m_linearMotorDirection = new Vector3(pValue, pValue, pValue); | 244 | clampTemp = ClampInRange(-BSParam.MaxLinearVelocity, pValue, BSParam.MaxLinearVelocity); |
219 | m_linearMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue); | 245 | m_linearMotorDirection = new Vector3(clampTemp, clampTemp, clampTemp); |
246 | m_linearMotorDirectionLASTSET = new Vector3(clampTemp, clampTemp, clampTemp); | ||
220 | m_linearMotor.SetTarget(m_linearMotorDirection); | 247 | m_linearMotor.SetTarget(m_linearMotorDirection); |
221 | break; | 248 | break; |
222 | case Vehicle.LINEAR_MOTOR_OFFSET: | 249 | case Vehicle.LINEAR_MOTOR_OFFSET: |
223 | m_linearMotorOffset = new Vector3(pValue, pValue, pValue); | 250 | clampTemp = ClampInRange(-1000, pValue, 1000); |
251 | m_linearMotorOffset = new Vector3(clampTemp, clampTemp, clampTemp); | ||
224 | break; | 252 | break; |
225 | 253 | ||
226 | } | 254 | } |
@@ -228,34 +256,50 @@ namespace OpenSim.Region.Physics.BulletSNPlugin | |||
228 | 256 | ||
229 | internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue) | 257 | internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue) |
230 | { | 258 | { |
231 | VDetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue); | 259 | VDetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", ControllingPrim.LocalID, pParam, pValue); |
232 | switch (pParam) | 260 | switch (pParam) |
233 | { | 261 | { |
234 | case Vehicle.ANGULAR_FRICTION_TIMESCALE: | 262 | case Vehicle.ANGULAR_FRICTION_TIMESCALE: |
263 | pValue.X = ClampInRange(0.25f, pValue.X, 120); | ||
264 | pValue.Y = ClampInRange(0.25f, pValue.Y, 120); | ||
265 | pValue.Z = ClampInRange(0.25f, pValue.Z, 120); | ||
235 | m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); | 266 | m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); |
236 | m_angularMotor.FrictionTimescale = m_angularFrictionTimescale; | ||
237 | break; | 267 | break; |
238 | case Vehicle.ANGULAR_MOTOR_DIRECTION: | 268 | case Vehicle.ANGULAR_MOTOR_DIRECTION: |
239 | // Limit requested angular speed to 2 rps= 4 pi rads/sec | 269 | // Limit requested angular speed to 2 rps= 4 pi rads/sec |
240 | pValue.X = ClampInRange(-12.56f, pValue.X, 12.56f); | 270 | pValue.X = ClampInRange(-FourPI, pValue.X, FourPI); |
241 | pValue.Y = ClampInRange(-12.56f, pValue.Y, 12.56f); | 271 | pValue.Y = ClampInRange(-FourPI, pValue.Y, FourPI); |
242 | pValue.Z = ClampInRange(-12.56f, pValue.Z, 12.56f); | 272 | pValue.Z = ClampInRange(-FourPI, pValue.Z, FourPI); |
243 | m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); | 273 | m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); |
274 | m_angularMotor.Zero(); | ||
244 | m_angularMotor.SetTarget(m_angularMotorDirection); | 275 | m_angularMotor.SetTarget(m_angularMotorDirection); |
245 | break; | 276 | break; |
246 | case Vehicle.LINEAR_FRICTION_TIMESCALE: | 277 | case Vehicle.LINEAR_FRICTION_TIMESCALE: |
278 | pValue.X = ClampInRange(0.25f, pValue.X, 120); | ||
279 | pValue.Y = ClampInRange(0.25f, pValue.Y, 120); | ||
280 | pValue.Z = ClampInRange(0.25f, pValue.Z, 120); | ||
247 | m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); | 281 | m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); |
248 | m_linearMotor.FrictionTimescale = m_linearFrictionTimescale; | ||
249 | break; | 282 | break; |
250 | case Vehicle.LINEAR_MOTOR_DIRECTION: | 283 | case Vehicle.LINEAR_MOTOR_DIRECTION: |
284 | pValue.X = ClampInRange(-BSParam.MaxLinearVelocity, pValue.X, BSParam.MaxLinearVelocity); | ||
285 | pValue.Y = ClampInRange(-BSParam.MaxLinearVelocity, pValue.Y, BSParam.MaxLinearVelocity); | ||
286 | pValue.Z = ClampInRange(-BSParam.MaxLinearVelocity, pValue.Z, BSParam.MaxLinearVelocity); | ||
251 | m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); | 287 | m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); |
252 | m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z); | 288 | m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z); |
253 | m_linearMotor.SetTarget(m_linearMotorDirection); | 289 | m_linearMotor.SetTarget(m_linearMotorDirection); |
254 | break; | 290 | break; |
255 | case Vehicle.LINEAR_MOTOR_OFFSET: | 291 | case Vehicle.LINEAR_MOTOR_OFFSET: |
292 | // Not sure the correct range to limit this variable | ||
293 | pValue.X = ClampInRange(-1000, pValue.X, 1000); | ||
294 | pValue.Y = ClampInRange(-1000, pValue.Y, 1000); | ||
295 | pValue.Z = ClampInRange(-1000, pValue.Z, 1000); | ||
256 | m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z); | 296 | m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z); |
257 | break; | 297 | break; |
258 | case Vehicle.BLOCK_EXIT: | 298 | case Vehicle.BLOCK_EXIT: |
299 | // Not sure the correct range to limit this variable | ||
300 | pValue.X = ClampInRange(-10000, pValue.X, 10000); | ||
301 | pValue.Y = ClampInRange(-10000, pValue.Y, 10000); | ||
302 | pValue.Z = ClampInRange(-10000, pValue.Z, 10000); | ||
259 | m_BlockingEndPoint = new Vector3(pValue.X, pValue.Y, pValue.Z); | 303 | m_BlockingEndPoint = new Vector3(pValue.X, pValue.Y, pValue.Z); |
260 | break; | 304 | break; |
261 | } | 305 | } |
@@ -263,7 +307,7 @@ namespace OpenSim.Region.Physics.BulletSNPlugin | |||
263 | 307 | ||
264 | internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) | 308 | internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) |
265 | { | 309 | { |
266 | VDetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue); | 310 | VDetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", ControllingPrim.LocalID, pParam, pValue); |
267 | switch (pParam) | 311 | switch (pParam) |
268 | { | 312 | { |
269 | case Vehicle.REFERENCE_FRAME: | 313 | case Vehicle.REFERENCE_FRAME: |
@@ -277,7 +321,7 @@ namespace OpenSim.Region.Physics.BulletSNPlugin | |||
277 | 321 | ||
278 | internal void ProcessVehicleFlags(int pParam, bool remove) | 322 | internal void ProcessVehicleFlags(int pParam, bool remove) |
279 | { | 323 | { |
280 | VDetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", Prim.LocalID, pParam, remove); | 324 | VDetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", ControllingPrim.LocalID, pParam, remove); |
281 | VehicleFlag parm = (VehicleFlag)pParam; | 325 | VehicleFlag parm = (VehicleFlag)pParam; |
282 | if (pParam == -1) | 326 | if (pParam == -1) |
283 | m_flags = (VehicleFlag)0; | 327 | m_flags = (VehicleFlag)0; |
@@ -290,9 +334,9 @@ namespace OpenSim.Region.Physics.BulletSNPlugin | |||
290 | } | 334 | } |
291 | } | 335 | } |
292 | 336 | ||
293 | internal void ProcessTypeChange(Vehicle pType) | 337 | public void ProcessTypeChange(Vehicle pType) |
294 | { | 338 | { |
295 | VDetailLog("{0},ProcessTypeChange,type={1}", Prim.LocalID, pType); | 339 | VDetailLog("{0},ProcessTypeChange,type={1}", ControllingPrim.LocalID, pType); |
296 | // Set Defaults For Type | 340 | // Set Defaults For Type |
297 | Type = pType; | 341 | Type = pType; |
298 | switch (pType) | 342 | switch (pType) |
@@ -526,81 +570,144 @@ namespace OpenSim.Region.Physics.BulletSNPlugin | |||
526 | break; | 570 | break; |
527 | } | 571 | } |
528 | 572 | ||
529 | // Update any physical parameters based on this type. | 573 | m_linearMotor = new BSVMotor("LinearMotor", m_linearMotorTimescale, m_linearMotorDecayTimescale, 1f); |
530 | Refresh(); | 574 | // 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 | 575 | ||
537 | m_angularMotor = new BSVMotor("AngularMotor", m_angularMotorTimescale, | 576 | m_angularMotor = new BSVMotor("AngularMotor", m_angularMotorTimescale, m_angularMotorDecayTimescale, 1f); |
538 | m_angularMotorDecayTimescale, m_angularFrictionTimescale, | 577 | // 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 | 578 | ||
579 | /* Not implemented | ||
542 | m_verticalAttractionMotor = new BSVMotor("VerticalAttraction", m_verticalAttractionTimescale, | 580 | m_verticalAttractionMotor = new BSVMotor("VerticalAttraction", m_verticalAttractionTimescale, |
543 | BSMotor.Infinite, BSMotor.InfiniteVector, | 581 | BSMotor.Infinite, BSMotor.InfiniteVector, |
544 | m_verticalAttractionEfficiency); | 582 | m_verticalAttractionEfficiency); |
545 | // Z goes away and we keep X and Y | 583 | // 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) | 584 | m_verticalAttractionMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging) |
585 | */ | ||
586 | |||
587 | if (this.Type == Vehicle.TYPE_NONE) | ||
588 | { | ||
589 | UnregisterForSceneEvents(); | ||
590 | } | ||
591 | else | ||
592 | { | ||
593 | RegisterForSceneEvents(); | ||
594 | } | ||
595 | |||
596 | // Update any physical parameters based on this type. | ||
597 | Refresh(); | ||
598 | } | ||
599 | #endregion // Vehicle parameter setting | ||
600 | |||
601 | // BSActor.Refresh() | ||
602 | public override void Refresh() | ||
603 | { | ||
604 | // If asking for a refresh, reset the physical parameters before the next simulation step. | ||
605 | // Called whether active or not since the active state may be updated before the next step. | ||
606 | m_physicsScene.PostTaintObject("BSDynamics.Refresh", ControllingPrim.LocalID, delegate() | ||
607 | { | ||
608 | SetPhysicalParameters(); | ||
609 | }); | ||
548 | } | 610 | } |
549 | 611 | ||
550 | // Some of the properties of this prim may have changed. | 612 | // Some of the properties of this prim may have changed. |
551 | // Do any updating needed for a vehicle | 613 | // Do any updating needed for a vehicle |
552 | public void Refresh() | 614 | private void SetPhysicalParameters() |
553 | { | 615 | { |
554 | if (IsActive) | 616 | if (IsActive) |
555 | { | 617 | { |
556 | // Remember the mass so we don't have to fetch it every step | 618 | // Remember the mass so we don't have to fetch it every step |
557 | m_vehicleMass = Prim.Linkset.LinksetMass; | 619 | m_vehicleMass = ControllingPrim.TotalMass; |
558 | 620 | ||
559 | // Friction affects are handled by this vehicle code | 621 | // Friction affects are handled by this vehicle code |
560 | float friction = 0f; | 622 | // m_physicsScene.PE.SetFriction(ControllingPrim.PhysBody, BSParam.VehicleFriction); |
561 | BulletSimAPI.SetFriction2(Prim.PhysBody.ptr, friction); | 623 | // m_physicsScene.PE.SetRestitution(ControllingPrim.PhysBody, BSParam.VehicleRestitution); |
624 | ControllingPrim.Linkset.SetPhysicalFriction(BSParam.VehicleFriction); | ||
625 | ControllingPrim.Linkset.SetPhysicalRestitution(BSParam.VehicleRestitution); | ||
562 | 626 | ||
563 | // Moderate angular movement introduced by Bullet. | 627 | // Moderate angular movement introduced by Bullet. |
564 | // TODO: possibly set AngularFactor and LinearFactor for the type of vehicle. | 628 | // TODO: possibly set AngularFactor and LinearFactor for the type of vehicle. |
565 | // Maybe compute linear and angular factor and damping from params. | 629 | // Maybe compute linear and angular factor and damping from params. |
566 | float angularDamping = BSParam.VehicleAngularDamping; | 630 | m_physicsScene.PE.SetAngularDamping(ControllingPrim.PhysBody, BSParam.VehicleAngularDamping); |
567 | BulletSimAPI.SetAngularDamping2(Prim.PhysBody.ptr, angularDamping); | 631 | m_physicsScene.PE.SetLinearFactor(ControllingPrim.PhysBody, BSParam.VehicleLinearFactor); |
632 | m_physicsScene.PE.SetAngularFactorV(ControllingPrim.PhysBody, BSParam.VehicleAngularFactor); | ||
568 | 633 | ||
569 | // Vehicles report collision events so we know when it's on the ground | 634 | // Vehicles report collision events so we know when it's on the ground |
570 | BulletSimAPI.AddToCollisionFlags2(Prim.PhysBody.ptr, CollisionFlags.BS_VEHICLE_COLLISIONS); | 635 | // m_physicsScene.PE.AddToCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); |
636 | ControllingPrim.Linkset.AddToPhysicalCollisionFlags(CollisionFlags.BS_VEHICLE_COLLISIONS); | ||
637 | |||
638 | // Vector3 inertia = m_physicsScene.PE.CalculateLocalInertia(ControllingPrim.PhysShape.physShapeInfo, m_vehicleMass); | ||
639 | // ControllingPrim.Inertia = inertia * BSParam.VehicleInertiaFactor; | ||
640 | // m_physicsScene.PE.SetMassProps(ControllingPrim.PhysBody, m_vehicleMass, ControllingPrim.Inertia); | ||
641 | // m_physicsScene.PE.UpdateInertiaTensor(ControllingPrim.PhysBody); | ||
642 | ControllingPrim.Linkset.ComputeAndSetLocalInertia(BSParam.VehicleInertiaFactor, m_vehicleMass); | ||
643 | |||
644 | // Set the gravity for the vehicle depending on the buoyancy | ||
645 | // TODO: what should be done if prim and vehicle buoyancy differ? | ||
646 | m_VehicleGravity = ControllingPrim.ComputeGravity(m_VehicleBuoyancy); | ||
647 | // The actual vehicle gravity is set to zero in Bullet so we can do all the application of same. | ||
648 | // m_physicsScene.PE.SetGravity(ControllingPrim.PhysBody, Vector3.Zero); | ||
649 | ControllingPrim.Linkset.SetPhysicalGravity(Vector3.Zero); | ||
650 | |||
651 | VDetailLog("{0},BSDynamics.SetPhysicalParameters,mass={1},inert={2},vehGrav={3},aDamp={4},frict={5},rest={6},lFact={7},aFact={8}", | ||
652 | ControllingPrim.LocalID, m_vehicleMass, ControllingPrim.Inertia, m_VehicleGravity, | ||
653 | BSParam.VehicleAngularDamping, BSParam.VehicleFriction, BSParam.VehicleRestitution, | ||
654 | BSParam.VehicleLinearFactor, BSParam.VehicleAngularFactor | ||
655 | ); | ||
656 | } | ||
657 | else | ||
658 | { | ||
659 | if (ControllingPrim.PhysBody.HasPhysicalBody) | ||
660 | m_physicsScene.PE.RemoveFromCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); | ||
661 | // ControllingPrim.Linkset.RemoveFromPhysicalCollisionFlags(CollisionFlags.BS_VEHICLE_COLLISIONS); | ||
662 | } | ||
663 | } | ||
571 | 664 | ||
572 | Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(Prim.PhysShape.ptr, m_vehicleMass); | 665 | // BSActor.RemoveBodyDependencies |
573 | BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia); | 666 | public override void RemoveDependencies() |
574 | BulletSimAPI.UpdateInertiaTensor2(Prim.PhysBody.ptr); | 667 | { |
668 | Refresh(); | ||
669 | } | ||
575 | 670 | ||
576 | Vector3 grav = PhysicsScene.DefaultGravity * (1f - Prim.Buoyancy); | 671 | // BSActor.Release() |
577 | BulletSimAPI.SetGravity2(Prim.PhysBody.ptr, grav); | 672 | public override void Dispose() |
673 | { | ||
674 | VDetailLog("{0},Dispose", ControllingPrim.LocalID); | ||
675 | UnregisterForSceneEvents(); | ||
676 | Type = Vehicle.TYPE_NONE; | ||
677 | Enabled = false; | ||
678 | return; | ||
679 | } | ||
578 | 680 | ||
579 | VDetailLog("{0},BSDynamics.Refresh,mass={1},frict={2},inert={3},aDamp={4}", | 681 | private void RegisterForSceneEvents() |
580 | Prim.LocalID, m_vehicleMass, friction, localInertia, angularDamping); | 682 | { |
581 | } | 683 | if (!m_haveRegisteredForSceneEvents) |
582 | else | ||
583 | { | 684 | { |
584 | BulletSimAPI.RemoveFromCollisionFlags2(Prim.PhysBody.ptr, CollisionFlags.BS_VEHICLE_COLLISIONS); | 685 | m_physicsScene.BeforeStep += this.Step; |
686 | m_physicsScene.AfterStep += this.PostStep; | ||
687 | ControllingPrim.OnPreUpdateProperty += this.PreUpdateProperty; | ||
688 | m_haveRegisteredForSceneEvents = true; | ||
585 | } | 689 | } |
586 | } | 690 | } |
587 | 691 | ||
588 | public bool RemoveBodyDependencies(BSPhysObject prim) | 692 | private void UnregisterForSceneEvents() |
589 | { | 693 | { |
590 | // If active, we need to add our properties back when the body is rebuilt. | 694 | if (m_haveRegisteredForSceneEvents) |
591 | return IsActive; | 695 | { |
696 | m_physicsScene.BeforeStep -= this.Step; | ||
697 | m_physicsScene.AfterStep -= this.PostStep; | ||
698 | ControllingPrim.OnPreUpdateProperty -= this.PreUpdateProperty; | ||
699 | m_haveRegisteredForSceneEvents = false; | ||
700 | } | ||
592 | } | 701 | } |
593 | 702 | ||
594 | public void RestoreBodyDependencies(BSPhysObject prim) | 703 | private void PreUpdateProperty(ref EntityProperties entprop) |
595 | { | 704 | { |
596 | if (Prim.LocalID != prim.LocalID) | 705 | // A temporary kludge to suppress the rotational effects introduced on vehicles by Bullet |
706 | // TODO: handle physics introduced by Bullet with computed vehicle physics. | ||
707 | if (IsActive) | ||
597 | { | 708 | { |
598 | // The call should be on us by our prim. Error if not. | 709 | 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 | } | 710 | } |
603 | Refresh(); | ||
604 | } | 711 | } |
605 | 712 | ||
606 | #region Known vehicle value functions | 713 | #region Known vehicle value functions |
@@ -617,70 +724,85 @@ namespace OpenSim.Region.Physics.BulletSNPlugin | |||
617 | private Vector3 m_knownPosition; | 724 | private Vector3 m_knownPosition; |
618 | private Vector3 m_knownVelocity; | 725 | private Vector3 m_knownVelocity; |
619 | private Vector3 m_knownForce; | 726 | private Vector3 m_knownForce; |
727 | private Vector3 m_knownForceImpulse; | ||
620 | private Quaternion m_knownOrientation; | 728 | private Quaternion m_knownOrientation; |
621 | private Vector3 m_knownRotationalVelocity; | 729 | private Vector3 m_knownRotationalVelocity; |
622 | private Vector3 m_knownRotationalForce; | 730 | private Vector3 m_knownRotationalForce; |
623 | private Vector3 m_knownForwardVelocity; // vehicle relative forward speed | 731 | private Vector3 m_knownRotationalImpulse; |
624 | 732 | ||
625 | private const int m_knownChangedPosition = 1 << 0; | 733 | private const int m_knownChangedPosition = 1 << 0; |
626 | private const int m_knownChangedVelocity = 1 << 1; | 734 | private const int m_knownChangedVelocity = 1 << 1; |
627 | private const int m_knownChangedForce = 1 << 2; | 735 | private const int m_knownChangedForce = 1 << 2; |
628 | private const int m_knownChangedOrientation = 1 << 3; | 736 | private const int m_knownChangedForceImpulse = 1 << 3; |
629 | private const int m_knownChangedRotationalVelocity = 1 << 4; | 737 | private const int m_knownChangedOrientation = 1 << 4; |
630 | private const int m_knownChangedRotationalForce = 1 << 5; | 738 | private const int m_knownChangedRotationalVelocity = 1 << 5; |
631 | private const int m_knownChangedTerrainHeight = 1 << 6; | 739 | private const int m_knownChangedRotationalForce = 1 << 6; |
632 | private const int m_knownChangedWaterLevel = 1 << 7; | 740 | private const int m_knownChangedRotationalImpulse = 1 << 7; |
633 | private const int m_knownChangedForwardVelocity = 1 << 8; | 741 | private const int m_knownChangedTerrainHeight = 1 << 8; |
634 | 742 | private const int m_knownChangedWaterLevel = 1 << 9; | |
635 | private void ForgetKnownVehicleProperties() | 743 | |
744 | public void ForgetKnownVehicleProperties() | ||
636 | { | 745 | { |
637 | m_knownHas = 0; | 746 | m_knownHas = 0; |
638 | m_knownChanged = 0; | 747 | m_knownChanged = 0; |
639 | } | 748 | } |
640 | // Push all the changed values back into the physics engine | 749 | // Push all the changed values back into the physics engine |
641 | private void PushKnownChanged() | 750 | public void PushKnownChanged() |
642 | { | 751 | { |
643 | if (m_knownChanged != 0) | 752 | if (m_knownChanged != 0) |
644 | { | 753 | { |
645 | if ((m_knownChanged & m_knownChangedPosition) != 0) | 754 | if ((m_knownChanged & m_knownChangedPosition) != 0) |
646 | Prim.ForcePosition = m_knownPosition; | 755 | ControllingPrim.ForcePosition = m_knownPosition; |
647 | 756 | ||
648 | if ((m_knownChanged & m_knownChangedOrientation) != 0) | 757 | if ((m_knownChanged & m_knownChangedOrientation) != 0) |
649 | Prim.ForceOrientation = m_knownOrientation; | 758 | ControllingPrim.ForceOrientation = m_knownOrientation; |
650 | 759 | ||
651 | if ((m_knownChanged & m_knownChangedVelocity) != 0) | 760 | if ((m_knownChanged & m_knownChangedVelocity) != 0) |
652 | { | 761 | { |
653 | Prim.ForceVelocity = m_knownVelocity; | 762 | ControllingPrim.ForceVelocity = m_knownVelocity; |
654 | BulletSimAPI.SetInterpolationLinearVelocity2(Prim.PhysBody.ptr, VehicleVelocity); | 763 | // Fake out Bullet by making it think the velocity is the same as last time. |
764 | // Bullet does a bunch of smoothing for changing parameters. | ||
765 | // Since the vehicle is demanding this setting, we override Bullet's smoothing | ||
766 | // by telling Bullet the value was the same last time. | ||
767 | // PhysicsScene.PE.SetInterpolationLinearVelocity(Prim.PhysBody, m_knownVelocity); | ||
655 | } | 768 | } |
656 | 769 | ||
657 | if ((m_knownChanged & m_knownChangedForce) != 0) | 770 | if ((m_knownChanged & m_knownChangedForce) != 0) |
658 | Prim.AddForce((Vector3)m_knownForce, false, true); | 771 | ControllingPrim.AddForce((Vector3)m_knownForce, false /*pushForce*/, true /*inTaintTime*/); |
772 | |||
773 | if ((m_knownChanged & m_knownChangedForceImpulse) != 0) | ||
774 | ControllingPrim.AddForceImpulse((Vector3)m_knownForceImpulse, false /*pushforce*/, true /*inTaintTime*/); | ||
659 | 775 | ||
660 | if ((m_knownChanged & m_knownChangedRotationalVelocity) != 0) | 776 | if ((m_knownChanged & m_knownChangedRotationalVelocity) != 0) |
661 | { | 777 | { |
662 | Prim.ForceRotationalVelocity = m_knownRotationalVelocity; | 778 | ControllingPrim.ForceRotationalVelocity = m_knownRotationalVelocity; |
663 | // Fake out Bullet by making it think the velocity is the same as last time. | 779 | // PhysicsScene.PE.SetInterpolationAngularVelocity(Prim.PhysBody, m_knownRotationalVelocity); |
664 | BulletSimAPI.SetInterpolationAngularVelocity2(Prim.PhysBody.ptr, m_knownRotationalVelocity); | ||
665 | } | 780 | } |
666 | 781 | ||
782 | if ((m_knownChanged & m_knownChangedRotationalImpulse) != 0) | ||
783 | ControllingPrim.ApplyTorqueImpulse((Vector3)m_knownRotationalImpulse, true /*inTaintTime*/); | ||
784 | |||
667 | if ((m_knownChanged & m_knownChangedRotationalForce) != 0) | 785 | if ((m_knownChanged & m_knownChangedRotationalForce) != 0) |
668 | Prim.AddAngularForce((Vector3)m_knownRotationalForce, false, true); | 786 | { |
787 | ControllingPrim.AddAngularForce((Vector3)m_knownRotationalForce, false /*pushForce*/, true /*inTaintTime*/); | ||
788 | } | ||
669 | 789 | ||
670 | // If we set one of the values (ie, the physics engine didn't do it) we must force | 790 | // 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. | 791 | // an UpdateProperties event to send the changes up to the simulator. |
672 | BulletSimAPI.PushUpdate2(Prim.PhysBody.ptr); | 792 | m_physicsScene.PE.PushUpdate(ControllingPrim.PhysBody); |
673 | } | 793 | } |
674 | m_knownChanged = 0; | 794 | m_knownChanged = 0; |
675 | } | 795 | } |
676 | 796 | ||
677 | // Since the computation of terrain height can be a little involved, this routine | 797 | // 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. | 798 | // is used to fetch the height only once for each vehicle simulation step. |
799 | Vector3 lastRememberedHeightPos = new Vector3(-1, -1, -1); | ||
679 | private float GetTerrainHeight(Vector3 pos) | 800 | private float GetTerrainHeight(Vector3 pos) |
680 | { | 801 | { |
681 | if ((m_knownHas & m_knownChangedTerrainHeight) == 0) | 802 | if ((m_knownHas & m_knownChangedTerrainHeight) == 0 || pos != lastRememberedHeightPos) |
682 | { | 803 | { |
683 | m_knownTerrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos); | 804 | lastRememberedHeightPos = pos; |
805 | m_knownTerrainHeight = ControllingPrim.PhysScene.TerrainManager.GetTerrainHeightAtXYZ(pos); | ||
684 | m_knownHas |= m_knownChangedTerrainHeight; | 806 | m_knownHas |= m_knownChangedTerrainHeight; |
685 | } | 807 | } |
686 | return m_knownTerrainHeight; | 808 | return m_knownTerrainHeight; |
@@ -688,14 +810,16 @@ namespace OpenSim.Region.Physics.BulletSNPlugin | |||
688 | 810 | ||
689 | // Since the computation of water level can be a little involved, this routine | 811 | // Since the computation of water level can be a little involved, this routine |
690 | // is used ot fetch the level only once for each vehicle simulation step. | 812 | // is used ot fetch the level only once for each vehicle simulation step. |
813 | Vector3 lastRememberedWaterHeightPos = new Vector3(-1, -1, -1); | ||
691 | private float GetWaterLevel(Vector3 pos) | 814 | private float GetWaterLevel(Vector3 pos) |
692 | { | 815 | { |
693 | if ((m_knownHas & m_knownChangedWaterLevel) == 0) | 816 | if ((m_knownHas & m_knownChangedWaterLevel) == 0 || pos != lastRememberedWaterHeightPos) |
694 | { | 817 | { |
695 | m_knownWaterLevel = Prim.PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(pos); | 818 | lastRememberedWaterHeightPos = pos; |
819 | m_knownWaterLevel = ControllingPrim.PhysScene.TerrainManager.GetWaterLevelAtXYZ(pos); | ||
696 | m_knownHas |= m_knownChangedWaterLevel; | 820 | m_knownHas |= m_knownChangedWaterLevel; |
697 | } | 821 | } |
698 | return (float)m_knownWaterLevel; | 822 | return m_knownWaterLevel; |
699 | } | 823 | } |
700 | 824 | ||
701 | private Vector3 VehiclePosition | 825 | private Vector3 VehiclePosition |
@@ -704,7 +828,7 @@ namespace OpenSim.Region.Physics.BulletSNPlugin | |||
704 | { | 828 | { |
705 | if ((m_knownHas & m_knownChangedPosition) == 0) | 829 | if ((m_knownHas & m_knownChangedPosition) == 0) |
706 | { | 830 | { |
707 | m_knownPosition = Prim.ForcePosition; | 831 | m_knownPosition = ControllingPrim.ForcePosition; |
708 | m_knownHas |= m_knownChangedPosition; | 832 | m_knownHas |= m_knownChangedPosition; |
709 | } | 833 | } |
710 | return m_knownPosition; | 834 | return m_knownPosition; |
@@ -723,7 +847,7 @@ namespace OpenSim.Region.Physics.BulletSNPlugin | |||
723 | { | 847 | { |
724 | if ((m_knownHas & m_knownChangedOrientation) == 0) | 848 | if ((m_knownHas & m_knownChangedOrientation) == 0) |
725 | { | 849 | { |
726 | m_knownOrientation = Prim.ForceOrientation; | 850 | m_knownOrientation = ControllingPrim.ForceOrientation; |
727 | m_knownHas |= m_knownChangedOrientation; | 851 | m_knownHas |= m_knownChangedOrientation; |
728 | } | 852 | } |
729 | return m_knownOrientation; | 853 | return m_knownOrientation; |
@@ -742,10 +866,10 @@ namespace OpenSim.Region.Physics.BulletSNPlugin | |||
742 | { | 866 | { |
743 | if ((m_knownHas & m_knownChangedVelocity) == 0) | 867 | if ((m_knownHas & m_knownChangedVelocity) == 0) |
744 | { | 868 | { |
745 | m_knownVelocity = Prim.ForceVelocity; | 869 | m_knownVelocity = ControllingPrim.ForceVelocity; |
746 | m_knownHas |= m_knownChangedVelocity; | 870 | m_knownHas |= m_knownChangedVelocity; |
747 | } | 871 | } |
748 | return (Vector3)m_knownVelocity; | 872 | return m_knownVelocity; |
749 | } | 873 | } |
750 | set | 874 | set |
751 | { | 875 | { |
@@ -755,15 +879,26 @@ namespace OpenSim.Region.Physics.BulletSNPlugin | |||
755 | } | 879 | } |
756 | } | 880 | } |
757 | 881 | ||
758 | private void VehicleAddForce(Vector3 aForce) | 882 | private void VehicleAddForce(Vector3 pForce) |
759 | { | 883 | { |
760 | if ((m_knownHas & m_knownChangedForce) == 0) | 884 | if ((m_knownHas & m_knownChangedForce) == 0) |
761 | { | 885 | { |
762 | m_knownForce = Vector3.Zero; | 886 | m_knownForce = Vector3.Zero; |
887 | m_knownHas |= m_knownChangedForce; | ||
763 | } | 888 | } |
764 | m_knownForce += aForce; | 889 | m_knownForce += pForce; |
765 | m_knownChanged |= m_knownChangedForce; | 890 | m_knownChanged |= m_knownChangedForce; |
766 | m_knownHas |= m_knownChangedForce; | 891 | } |
892 | |||
893 | private void VehicleAddForceImpulse(Vector3 pImpulse) | ||
894 | { | ||
895 | if ((m_knownHas & m_knownChangedForceImpulse) == 0) | ||
896 | { | ||
897 | m_knownForceImpulse = Vector3.Zero; | ||
898 | m_knownHas |= m_knownChangedForceImpulse; | ||
899 | } | ||
900 | m_knownForceImpulse += pImpulse; | ||
901 | m_knownChanged |= m_knownChangedForceImpulse; | ||
767 | } | 902 | } |
768 | 903 | ||
769 | private Vector3 VehicleRotationalVelocity | 904 | private Vector3 VehicleRotationalVelocity |
@@ -772,7 +907,7 @@ namespace OpenSim.Region.Physics.BulletSNPlugin | |||
772 | { | 907 | { |
773 | if ((m_knownHas & m_knownChangedRotationalVelocity) == 0) | 908 | if ((m_knownHas & m_knownChangedRotationalVelocity) == 0) |
774 | { | 909 | { |
775 | m_knownRotationalVelocity = Prim.ForceRotationalVelocity; | 910 | m_knownRotationalVelocity = ControllingPrim.ForceRotationalVelocity; |
776 | m_knownHas |= m_knownChangedRotationalVelocity; | 911 | m_knownHas |= m_knownChangedRotationalVelocity; |
777 | } | 912 | } |
778 | return (Vector3)m_knownRotationalVelocity; | 913 | return (Vector3)m_knownRotationalVelocity; |
@@ -794,19 +929,26 @@ namespace OpenSim.Region.Physics.BulletSNPlugin | |||
794 | m_knownChanged |= m_knownChangedRotationalForce; | 929 | m_knownChanged |= m_knownChangedRotationalForce; |
795 | m_knownHas |= m_knownChangedRotationalForce; | 930 | m_knownHas |= m_knownChangedRotationalForce; |
796 | } | 931 | } |
932 | private void VehicleAddRotationalImpulse(Vector3 pImpulse) | ||
933 | { | ||
934 | if ((m_knownHas & m_knownChangedRotationalImpulse) == 0) | ||
935 | { | ||
936 | m_knownRotationalImpulse = Vector3.Zero; | ||
937 | m_knownHas |= m_knownChangedRotationalImpulse; | ||
938 | } | ||
939 | m_knownRotationalImpulse += pImpulse; | ||
940 | m_knownChanged |= m_knownChangedRotationalImpulse; | ||
941 | } | ||
942 | |||
797 | // Vehicle relative forward velocity | 943 | // Vehicle relative forward velocity |
798 | private Vector3 VehicleForwardVelocity | 944 | private Vector3 VehicleForwardVelocity |
799 | { | 945 | { |
800 | get | 946 | get |
801 | { | 947 | { |
802 | if ((m_knownHas & m_knownChangedForwardVelocity) == 0) | 948 | return VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleFrameOrientation)); |
803 | { | ||
804 | m_knownForwardVelocity = VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleOrientation)); | ||
805 | m_knownHas |= m_knownChangedForwardVelocity; | ||
806 | } | ||
807 | return m_knownForwardVelocity; | ||
808 | } | 949 | } |
809 | } | 950 | } |
951 | |||
810 | private float VehicleForwardSpeed | 952 | private float VehicleForwardSpeed |
811 | { | 953 | { |
812 | get | 954 | get |
@@ -814,6 +956,13 @@ namespace OpenSim.Region.Physics.BulletSNPlugin | |||
814 | return VehicleForwardVelocity.X; | 956 | return VehicleForwardVelocity.X; |
815 | } | 957 | } |
816 | } | 958 | } |
959 | private Quaternion VehicleFrameOrientation | ||
960 | { | ||
961 | get | ||
962 | { | ||
963 | return VehicleOrientation * m_referenceFrame; | ||
964 | } | ||
965 | } | ||
817 | 966 | ||
818 | #endregion // Known vehicle value functions | 967 | #endregion // Known vehicle value functions |
819 | 968 | ||
@@ -836,106 +985,170 @@ namespace OpenSim.Region.Physics.BulletSNPlugin | |||
836 | // for the physics engine to note the changes so an UpdateProperties event will happen. | 985 | // for the physics engine to note the changes so an UpdateProperties event will happen. |
837 | PushKnownChanged(); | 986 | PushKnownChanged(); |
838 | 987 | ||
839 | VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", | 988 | if (m_physicsScene.VehiclePhysicalLoggingEnabled) |
840 | Prim.LocalID, VehiclePosition, Prim.Force, VehicleVelocity, VehicleRotationalVelocity); | 989 | m_physicsScene.PE.DumpRigidBody(m_physicsScene.World, ControllingPrim.PhysBody); |
990 | |||
991 | VDetailLog("{0},BSDynamics.Step,done,pos={1}, force={2},velocity={3},angvel={4}", | ||
992 | ControllingPrim.LocalID, VehiclePosition, m_knownForce, VehicleVelocity, VehicleRotationalVelocity); | ||
993 | } | ||
994 | |||
995 | // Called after the simulation step | ||
996 | internal void PostStep(float pTimestep) | ||
997 | { | ||
998 | if (!IsActive) return; | ||
999 | |||
1000 | if (m_physicsScene.VehiclePhysicalLoggingEnabled) | ||
1001 | m_physicsScene.PE.DumpRigidBody(m_physicsScene.World, ControllingPrim.PhysBody); | ||
841 | } | 1002 | } |
842 | 1003 | ||
843 | // Apply the effect of the linear motor and other linear motions (like hover and float). | 1004 | // Apply the effect of the linear motor and other linear motions (like hover and float). |
844 | private void MoveLinear(float pTimestep) | 1005 | private void MoveLinear(float pTimestep) |
845 | { | 1006 | { |
846 | Vector3 linearMotorContribution = m_linearMotor.Step(pTimestep); | 1007 | ComputeLinearVelocity(pTimestep); |
847 | 1008 | ||
848 | // The movement computed in the linear motor is relative to the vehicle | 1009 | ComputeLinearDeflection(pTimestep); |
849 | // coordinates. Rotate the movement to world coordinates. | ||
850 | linearMotorContribution *= VehicleOrientation; | ||
851 | 1010 | ||
852 | // ================================================================== | 1011 | ComputeLinearTerrainHeightCorrection(pTimestep); |
853 | // Buoyancy: force to overcome gravity. | ||
854 | // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; | ||
855 | // So, if zero, don't change anything (let gravity happen). If one, negate the effect of gravity. | ||
856 | Vector3 buoyancyContribution = Prim.PhysicsScene.DefaultGravity * m_VehicleBuoyancy; | ||
857 | |||
858 | Vector3 terrainHeightContribution = ComputeLinearTerrainHeightCorrection(pTimestep); | ||
859 | 1012 | ||
860 | Vector3 hoverContribution = ComputeLinearHover(pTimestep); | 1013 | ComputeLinearHover(pTimestep); |
861 | 1014 | ||
862 | ComputeLinearBlockingEndPoint(pTimestep); | 1015 | ComputeLinearBlockingEndPoint(pTimestep); |
863 | 1016 | ||
864 | Vector3 limitMotorUpContribution = ComputeLinearMotorUp(pTimestep); | 1017 | ComputeLinearMotorUp(pTimestep); |
865 | |||
866 | // ================================================================== | ||
867 | Vector3 newVelocity = linearMotorContribution | ||
868 | + terrainHeightContribution | ||
869 | + hoverContribution | ||
870 | + limitMotorUpContribution; | ||
871 | 1018 | ||
872 | Vector3 newForce = buoyancyContribution; | 1019 | ApplyGravity(pTimestep); |
873 | 1020 | ||
874 | // If not changing some axis, reduce out velocity | 1021 | // If not changing some axis, reduce out velocity |
875 | if ((m_flags & (VehicleFlag.NO_X)) != 0) | 1022 | if ((m_flags & (VehicleFlag.NO_X | VehicleFlag.NO_Y | VehicleFlag.NO_Z)) != 0) |
876 | newVelocity.X = 0; | 1023 | { |
877 | if ((m_flags & (VehicleFlag.NO_Y)) != 0) | 1024 | Vector3 vel = VehicleVelocity; |
878 | newVelocity.Y = 0; | 1025 | if ((m_flags & (VehicleFlag.NO_X)) != 0) |
879 | if ((m_flags & (VehicleFlag.NO_Z)) != 0) | 1026 | { |
880 | newVelocity.Z = 0; | 1027 | vel.X = 0; |
1028 | } | ||
1029 | if ((m_flags & (VehicleFlag.NO_Y)) != 0) | ||
1030 | { | ||
1031 | vel.Y = 0; | ||
1032 | } | ||
1033 | if ((m_flags & (VehicleFlag.NO_Z)) != 0) | ||
1034 | { | ||
1035 | vel.Z = 0; | ||
1036 | } | ||
1037 | VehicleVelocity = vel; | ||
1038 | } | ||
881 | 1039 | ||
882 | // ================================================================== | 1040 | // ================================================================== |
883 | // Clamp high or low velocities | 1041 | // Clamp high or low velocities |
884 | float newVelocityLengthSq = newVelocity.LengthSquared(); | 1042 | float newVelocityLengthSq = VehicleVelocity.LengthSquared(); |
885 | if (newVelocityLengthSq > 1000f) | 1043 | if (newVelocityLengthSq > BSParam.VehicleMaxLinearVelocitySquared) |
886 | { | 1044 | { |
887 | newVelocity /= newVelocity.Length(); | 1045 | Vector3 origVelW = VehicleVelocity; // DEBUG DEBUG |
888 | newVelocity *= 1000f; | 1046 | VehicleVelocity /= VehicleVelocity.Length(); |
1047 | VehicleVelocity *= BSParam.VehicleMaxLinearVelocity; | ||
1048 | VDetailLog("{0}, MoveLinear,clampMax,origVelW={1},lenSq={2},maxVelSq={3},,newVelW={4}", | ||
1049 | ControllingPrim.LocalID, origVelW, newVelocityLengthSq, BSParam.VehicleMaxLinearVelocitySquared, VehicleVelocity); | ||
1050 | } | ||
1051 | else if (newVelocityLengthSq < BSParam.VehicleMinLinearVelocitySquared) | ||
1052 | { | ||
1053 | Vector3 origVelW = VehicleVelocity; // DEBUG DEBUG | ||
1054 | VDetailLog("{0}, MoveLinear,clampMin,origVelW={1},lenSq={2}", | ||
1055 | ControllingPrim.LocalID, origVelW, newVelocityLengthSq); | ||
1056 | VehicleVelocity = Vector3.Zero; | ||
889 | } | 1057 | } |
890 | else if (newVelocityLengthSq < 0.001f) | ||
891 | newVelocity = Vector3.Zero; | ||
892 | 1058 | ||
893 | // ================================================================== | 1059 | VDetailLog("{0}, MoveLinear,done,isColl={1},newVel={2}", ControllingPrim.LocalID, ControllingPrim.HasSomeCollision, VehicleVelocity ); |
894 | // Stuff new linear velocity into the vehicle. | 1060 | |
895 | // Since the velocity is just being set, it is not scaled by pTimeStep. Bullet will do that for us. | 1061 | } // end MoveLinear() |
896 | VehicleVelocity = newVelocity; | 1062 | |
1063 | public void ComputeLinearVelocity(float pTimestep) | ||
1064 | { | ||
1065 | // Step the motor from the current value. Get the correction needed this step. | ||
1066 | Vector3 origVelW = VehicleVelocity; // DEBUG | ||
1067 | Vector3 currentVelV = VehicleForwardVelocity; | ||
1068 | Vector3 linearMotorCorrectionV = m_linearMotor.Step(pTimestep, currentVelV); | ||
1069 | |||
1070 | // Friction reduces vehicle motion based on absolute speed. Slow vehicle down by friction. | ||
1071 | Vector3 frictionFactorV = ComputeFrictionFactor(m_linearFrictionTimescale, pTimestep); | ||
1072 | linearMotorCorrectionV -= (currentVelV * frictionFactorV); | ||
1073 | |||
1074 | // Motor is vehicle coordinates. Rotate it to world coordinates | ||
1075 | Vector3 linearMotorVelocityW = linearMotorCorrectionV * VehicleFrameOrientation; | ||
897 | 1076 | ||
898 | // Other linear forces are applied as forces. | 1077 | // If we're a ground vehicle, don't add any upward Z movement |
899 | Vector3 totalDownForce = newForce * m_vehicleMass; | 1078 | if ((m_flags & VehicleFlag.LIMIT_MOTOR_UP) != 0) |
900 | if (!totalDownForce.ApproxEquals(Vector3.Zero, 0.01f)) | ||
901 | { | 1079 | { |
902 | VehicleAddForce(totalDownForce); | 1080 | if (linearMotorVelocityW.Z > 0f) |
1081 | linearMotorVelocityW.Z = 0f; | ||
903 | } | 1082 | } |
904 | 1083 | ||
905 | VDetailLog("{0}, MoveLinear,done,newVel={1},totDown={2},IsColliding={3}", | 1084 | // Add this correction to the velocity to make it faster/slower. |
906 | Prim.LocalID, newVelocity, totalDownForce, Prim.IsColliding); | 1085 | VehicleVelocity += linearMotorVelocityW; |
907 | VDetailLog("{0}, MoveLinear,done,linContrib={1},terrContrib={2},hoverContrib={3},limitContrib={4},buoyContrib={5}", | ||
908 | Prim.LocalID, | ||
909 | linearMotorContribution, terrainHeightContribution, hoverContribution, | ||
910 | limitMotorUpContribution, buoyancyContribution | ||
911 | ); | ||
912 | 1086 | ||
913 | } // end MoveLinear() | 1087 | VDetailLog("{0}, MoveLinear,velocity,origVelW={1},velV={2},tgt={3},correctV={4},correctW={5},newVelW={6},fricFact={7}", |
1088 | ControllingPrim.LocalID, origVelW, currentVelV, m_linearMotor.TargetValue, linearMotorCorrectionV, | ||
1089 | linearMotorVelocityW, VehicleVelocity, frictionFactorV); | ||
1090 | } | ||
1091 | |||
1092 | //Given a Deflection Effiency and a Velocity, Returns a Velocity that is Partially Deflected onto the X Axis | ||
1093 | //Clamped so that a DeflectionTimescale of less then 1 does not increase force over original velocity | ||
1094 | private void ComputeLinearDeflection(float pTimestep) | ||
1095 | { | ||
1096 | Vector3 linearDeflectionV = Vector3.Zero; | ||
1097 | Vector3 velocityV = VehicleForwardVelocity; | ||
1098 | |||
1099 | if (BSParam.VehicleEnableLinearDeflection) | ||
1100 | { | ||
1101 | // Velocity in Y and Z dimensions is movement to the side or turning. | ||
1102 | // Compute deflection factor from the to the side and rotational velocity | ||
1103 | linearDeflectionV.Y = SortedClampInRange(0, (velocityV.Y * m_linearDeflectionEfficiency) / m_linearDeflectionTimescale, velocityV.Y); | ||
1104 | linearDeflectionV.Z = SortedClampInRange(0, (velocityV.Z * m_linearDeflectionEfficiency) / m_linearDeflectionTimescale, velocityV.Z); | ||
1105 | |||
1106 | // Velocity to the side and around is corrected and moved into the forward direction | ||
1107 | linearDeflectionV.X += Math.Abs(linearDeflectionV.Y); | ||
1108 | linearDeflectionV.X += Math.Abs(linearDeflectionV.Z); | ||
1109 | |||
1110 | // Scale the deflection to the fractional simulation time | ||
1111 | linearDeflectionV *= pTimestep; | ||
1112 | |||
1113 | // Subtract the sideways and rotational velocity deflection factors while adding the correction forward | ||
1114 | linearDeflectionV *= new Vector3(1, -1, -1); | ||
1115 | |||
1116 | // Correction is vehicle relative. Convert to world coordinates. | ||
1117 | Vector3 linearDeflectionW = linearDeflectionV * VehicleFrameOrientation; | ||
1118 | |||
1119 | // Optionally, if not colliding, don't effect world downward velocity. Let falling things fall. | ||
1120 | if (BSParam.VehicleLinearDeflectionNotCollidingNoZ && !m_controllingPrim.HasSomeCollision) | ||
1121 | { | ||
1122 | linearDeflectionW.Z = 0f; | ||
1123 | } | ||
1124 | |||
1125 | VehicleVelocity += linearDeflectionW; | ||
1126 | |||
1127 | VDetailLog("{0}, MoveLinear,LinearDeflection,linDefEff={1},linDefTS={2},linDeflectionV={3}", | ||
1128 | ControllingPrim.LocalID, m_linearDeflectionEfficiency, m_linearDeflectionTimescale, linearDeflectionV); | ||
1129 | } | ||
1130 | } | ||
914 | 1131 | ||
915 | public Vector3 ComputeLinearTerrainHeightCorrection(float pTimestep) | 1132 | public void ComputeLinearTerrainHeightCorrection(float pTimestep) |
916 | { | 1133 | { |
917 | Vector3 ret = Vector3.Zero; | ||
918 | // If below the terrain, move us above the ground a little. | 1134 | // If below the terrain, move us above the ground a little. |
919 | // TODO: Consider taking the rotated size of the object or possibly casting a ray. | 1135 | // TODO: Consider taking the rotated size of the object or possibly casting a ray. |
920 | if (VehiclePosition.Z < GetTerrainHeight(VehiclePosition)) | 1136 | if (VehiclePosition.Z < GetTerrainHeight(VehiclePosition)) |
921 | { | 1137 | { |
922 | // TODO: correct position by applying force rather than forcing position. | 1138 | // Force position because applying force won't get the vehicle through the terrain |
923 | Vector3 newPosition = VehiclePosition; | 1139 | Vector3 newPosition = VehiclePosition; |
924 | newPosition.Z = GetTerrainHeight(VehiclePosition) + 1f; | 1140 | newPosition.Z = GetTerrainHeight(VehiclePosition) + 1f; |
925 | VehiclePosition = newPosition; | 1141 | VehiclePosition = newPosition; |
926 | VDetailLog("{0}, MoveLinear,terrainHeight,terrainHeight={1},pos={2}", | 1142 | VDetailLog("{0}, MoveLinear,terrainHeight,terrainHeight={1},pos={2}", |
927 | Prim.LocalID, GetTerrainHeight(VehiclePosition), VehiclePosition); | 1143 | ControllingPrim.LocalID, GetTerrainHeight(VehiclePosition), VehiclePosition); |
928 | } | 1144 | } |
929 | return ret; | ||
930 | } | 1145 | } |
931 | 1146 | ||
932 | public Vector3 ComputeLinearHover(float pTimestep) | 1147 | public void ComputeLinearHover(float pTimestep) |
933 | { | 1148 | { |
934 | Vector3 ret = Vector3.Zero; | ||
935 | |||
936 | // m_VhoverEfficiency: 0=bouncy, 1=totally damped | 1149 | // m_VhoverEfficiency: 0=bouncy, 1=totally damped |
937 | // m_VhoverTimescale: time to achieve height | 1150 | // m_VhoverTimescale: time to achieve height |
938 | if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) | 1151 | if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0 && (m_VhoverHeight > 0) && (m_VhoverTimescale < 300)) |
939 | { | 1152 | { |
940 | // We should hover, get the target height | 1153 | // We should hover, get the target height |
941 | if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0) | 1154 | if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0) |
@@ -950,14 +1163,25 @@ namespace OpenSim.Region.Physics.BulletSNPlugin | |||
950 | { | 1163 | { |
951 | m_VhoverTargetHeight = m_VhoverHeight; | 1164 | m_VhoverTargetHeight = m_VhoverHeight; |
952 | } | 1165 | } |
953 | |||
954 | if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0) | 1166 | if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0) |
955 | { | 1167 | { |
956 | // If body is already heigher, use its height as target height | 1168 | // If body is already heigher, use its height as target height |
957 | if (VehiclePosition.Z > m_VhoverTargetHeight) | 1169 | if (VehiclePosition.Z > m_VhoverTargetHeight) |
1170 | { | ||
958 | m_VhoverTargetHeight = VehiclePosition.Z; | 1171 | m_VhoverTargetHeight = VehiclePosition.Z; |
1172 | |||
1173 | // A 'misfeature' of this flag is that if the vehicle is above it's hover height, | ||
1174 | // the vehicle's buoyancy goes away. This is an SL bug that got used by so many | ||
1175 | // scripts that it could not be changed. | ||
1176 | // So, if above the height, reapply gravity if buoyancy had it turned off. | ||
1177 | if (m_VehicleBuoyancy != 0) | ||
1178 | { | ||
1179 | Vector3 appliedGravity = ControllingPrim.ComputeGravity(ControllingPrim.Buoyancy) * m_vehicleMass; | ||
1180 | VehicleAddForce(appliedGravity); | ||
1181 | } | ||
1182 | } | ||
959 | } | 1183 | } |
960 | 1184 | ||
961 | if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) | 1185 | if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) |
962 | { | 1186 | { |
963 | if (Math.Abs(VehiclePosition.Z - m_VhoverTargetHeight) > 0.2f) | 1187 | if (Math.Abs(VehiclePosition.Z - m_VhoverTargetHeight) > 0.2f) |
@@ -965,26 +1189,41 @@ namespace OpenSim.Region.Physics.BulletSNPlugin | |||
965 | Vector3 pos = VehiclePosition; | 1189 | Vector3 pos = VehiclePosition; |
966 | pos.Z = m_VhoverTargetHeight; | 1190 | pos.Z = m_VhoverTargetHeight; |
967 | VehiclePosition = pos; | 1191 | VehiclePosition = pos; |
1192 | |||
1193 | VDetailLog("{0}, MoveLinear,hover,pos={1},lockHoverHeight", ControllingPrim.LocalID, pos); | ||
968 | } | 1194 | } |
969 | } | 1195 | } |
970 | else | 1196 | else |
971 | { | 1197 | { |
972 | // Error is positive if below the target and negative if above. | 1198 | // Error is positive if below the target and negative if above. |
973 | float verticalError = m_VhoverTargetHeight - VehiclePosition.Z; | 1199 | Vector3 hpos = VehiclePosition; |
1200 | float verticalError = m_VhoverTargetHeight - hpos.Z; | ||
1201 | float verticalCorrection = verticalError / m_VhoverTimescale; | ||
1202 | verticalCorrection *= m_VhoverEfficiency; | ||
1203 | |||
1204 | hpos.Z += verticalCorrection; | ||
1205 | VehiclePosition = hpos; | ||
1206 | |||
1207 | // Since we are hovering, we need to do the opposite of falling -- get rid of world Z | ||
1208 | Vector3 vel = VehicleVelocity; | ||
1209 | vel.Z = 0f; | ||
1210 | VehicleVelocity = vel; | ||
1211 | |||
1212 | /* | ||
974 | float verticalCorrectionVelocity = verticalError / m_VhoverTimescale; | 1213 | float verticalCorrectionVelocity = verticalError / m_VhoverTimescale; |
1214 | Vector3 verticalCorrection = new Vector3(0f, 0f, verticalCorrectionVelocity); | ||
1215 | verticalCorrection *= m_vehicleMass; | ||
975 | 1216 | ||
976 | // TODO: implement m_VhoverEfficiency correctly | 1217 | // TODO: implement m_VhoverEfficiency correctly |
977 | if (Math.Abs(verticalError) > m_VhoverEfficiency) | 1218 | VehicleAddForceImpulse(verticalCorrection); |
978 | { | 1219 | */ |
979 | ret = new Vector3(0f, 0f, verticalCorrectionVelocity); | ||
980 | } | ||
981 | } | ||
982 | 1220 | ||
983 | VDetailLog("{0}, MoveLinear,hover,pos={1},ret={2},hoverTS={3},height={4},target={5}", | 1221 | VDetailLog("{0}, MoveLinear,hover,pos={1},eff={2},hoverTS={3},height={4},target={5},err={6},corr={7}", |
984 | Prim.LocalID, VehiclePosition, ret, m_VhoverTimescale, m_VhoverHeight, m_VhoverTargetHeight); | 1222 | ControllingPrim.LocalID, VehiclePosition, m_VhoverEfficiency, |
1223 | m_VhoverTimescale, m_VhoverHeight, m_VhoverTargetHeight, | ||
1224 | verticalError, verticalCorrection); | ||
1225 | } | ||
985 | } | 1226 | } |
986 | |||
987 | return ret; | ||
988 | } | 1227 | } |
989 | 1228 | ||
990 | public bool ComputeLinearBlockingEndPoint(float pTimestep) | 1229 | public bool ComputeLinearBlockingEndPoint(float pTimestep) |
@@ -1024,7 +1263,7 @@ namespace OpenSim.Region.Physics.BulletSNPlugin | |||
1024 | { | 1263 | { |
1025 | VehiclePosition = pos; | 1264 | VehiclePosition = pos; |
1026 | VDetailLog("{0}, MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", | 1265 | VDetailLog("{0}, MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", |
1027 | Prim.LocalID, m_BlockingEndPoint, posChange, pos); | 1266 | ControllingPrim.LocalID, m_BlockingEndPoint, posChange, pos); |
1028 | } | 1267 | } |
1029 | } | 1268 | } |
1030 | return changed; | 1269 | return changed; |
@@ -1035,34 +1274,75 @@ namespace OpenSim.Region.Physics.BulletSNPlugin | |||
1035 | // used with conjunction with banking: the strength of the banking will decay when the | 1274 | // used with conjunction with banking: the strength of the banking will decay when the |
1036 | // vehicle no longer experiences collisions. The decay timescale is the same as | 1275 | // vehicle no longer experiences collisions. The decay timescale is the same as |
1037 | // VEHICLE_BANKING_TIMESCALE. This is to help prevent ground vehicles from steering | 1276 | // VEHICLE_BANKING_TIMESCALE. This is to help prevent ground vehicles from steering |
1038 | // when they are in mid jump. | 1277 | // when they are in mid jump. |
1039 | // TODO: this code is wrong. Also, what should it do for boats (height from water)? | 1278 | // TODO: this code is wrong. Also, what should it do for boats (height from water)? |
1040 | // This is just using the ground and a general collision check. Should really be using | 1279 | // This is just using the ground and a general collision check. Should really be using |
1041 | // a downward raycast to find what is below. | 1280 | // a downward raycast to find what is below. |
1042 | public Vector3 ComputeLinearMotorUp(float pTimestep) | 1281 | public void ComputeLinearMotorUp(float pTimestep) |
1043 | { | 1282 | { |
1044 | Vector3 ret = Vector3.Zero; | ||
1045 | float distanceAboveGround = 0f; | ||
1046 | |||
1047 | if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) | 1283 | if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) |
1048 | { | 1284 | { |
1285 | // This code tries to decide if the object is not on the ground and then pushing down | ||
1286 | /* | ||
1049 | float targetHeight = Type == Vehicle.TYPE_BOAT ? GetWaterLevel(VehiclePosition) : GetTerrainHeight(VehiclePosition); | 1287 | float targetHeight = Type == Vehicle.TYPE_BOAT ? GetWaterLevel(VehiclePosition) : GetTerrainHeight(VehiclePosition); |
1050 | distanceAboveGround = VehiclePosition.Z - targetHeight; | 1288 | distanceAboveGround = VehiclePosition.Z - targetHeight; |
1051 | // Not colliding if the vehicle is off the ground | 1289 | // Not colliding if the vehicle is off the ground |
1052 | if (!Prim.IsColliding) | 1290 | if (!Prim.HasSomeCollision) |
1053 | { | 1291 | { |
1054 | // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale); | 1292 | // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale); |
1055 | ret = new Vector3(0, 0, -distanceAboveGround); | 1293 | VehicleVelocity += new Vector3(0, 0, -distanceAboveGround); |
1056 | } | 1294 | } |
1057 | // TODO: this calculation is wrong. From the description at | 1295 | // TODO: this calculation is wrong. From the description at |
1058 | // (http://wiki.secondlife.com/wiki/Category:LSL_Vehicle), the downForce | 1296 | // (http://wiki.secondlife.com/wiki/Category:LSL_Vehicle), the downForce |
1059 | // has a decay factor. This says this force should | 1297 | // has a decay factor. This says this force should |
1060 | // be computed with a motor. | 1298 | // be computed with a motor. |
1061 | // TODO: add interaction with banking. | 1299 | // TODO: add interaction with banking. |
1300 | VDetailLog("{0}, MoveLinear,limitMotorUp,distAbove={1},colliding={2},ret={3}", | ||
1301 | Prim.LocalID, distanceAboveGround, Prim.HasSomeCollision, ret); | ||
1302 | */ | ||
1303 | |||
1304 | // Another approach is to measure if we're going up. If going up and not colliding, | ||
1305 | // the vehicle is in the air. Fix that by pushing down. | ||
1306 | if (!ControllingPrim.HasSomeCollision && VehicleVelocity.Z > 0.1) | ||
1307 | { | ||
1308 | // Get rid of any of the velocity vector that is pushing us up. | ||
1309 | float upVelocity = VehicleVelocity.Z; | ||
1310 | VehicleVelocity += new Vector3(0, 0, -upVelocity); | ||
1311 | |||
1312 | /* | ||
1313 | // If we're pointed up into the air, we should nose down | ||
1314 | Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation; | ||
1315 | // The rotation around the Y axis is pitch up or down | ||
1316 | if (pointingDirection.Y > 0.01f) | ||
1317 | { | ||
1318 | float angularCorrectionForce = -(float)Math.Asin(pointingDirection.Y); | ||
1319 | Vector3 angularCorrectionVector = new Vector3(0f, angularCorrectionForce, 0f); | ||
1320 | // Rotate into world coordinates and apply to vehicle | ||
1321 | angularCorrectionVector *= VehicleOrientation; | ||
1322 | VehicleAddAngularForce(angularCorrectionVector); | ||
1323 | VDetailLog("{0}, MoveLinear,limitMotorUp,newVel={1},pntDir={2},corrFrc={3},aCorr={4}", | ||
1324 | Prim.LocalID, VehicleVelocity, pointingDirection, angularCorrectionForce, angularCorrectionVector); | ||
1325 | } | ||
1326 | */ | ||
1327 | VDetailLog("{0}, MoveLinear,limitMotorUp,collide={1},upVel={2},newVel={3}", | ||
1328 | ControllingPrim.LocalID, ControllingPrim.HasSomeCollision, upVelocity, VehicleVelocity); | ||
1329 | } | ||
1062 | } | 1330 | } |
1063 | VDetailLog("{0}, MoveLinear,limitMotorUp,distAbove={1},colliding={2},ret={3}", | 1331 | } |
1064 | Prim.LocalID, distanceAboveGround, Prim.IsColliding, ret); | 1332 | |
1065 | return ret; | 1333 | private void ApplyGravity(float pTimeStep) |
1334 | { | ||
1335 | Vector3 appliedGravity = m_VehicleGravity * m_vehicleMass; | ||
1336 | |||
1337 | // Hack to reduce downward force if the vehicle is probably sitting on the ground | ||
1338 | if (ControllingPrim.HasSomeCollision && IsGroundVehicle) | ||
1339 | appliedGravity *= BSParam.VehicleGroundGravityFudge; | ||
1340 | |||
1341 | VehicleAddForce(appliedGravity); | ||
1342 | |||
1343 | VDetailLog("{0}, MoveLinear,applyGravity,vehGrav={1},collid={2},fudge={3},mass={4},appliedForce={5}", | ||
1344 | ControllingPrim.LocalID, m_VehicleGravity, | ||
1345 | ControllingPrim.HasSomeCollision, BSParam.VehicleGroundGravityFudge, m_vehicleMass, appliedGravity); | ||
1066 | } | 1346 | } |
1067 | 1347 | ||
1068 | // ======================================================================= | 1348 | // ======================================================================= |
@@ -1073,55 +1353,24 @@ namespace OpenSim.Region.Physics.BulletSNPlugin | |||
1073 | // set directly on the vehicle. | 1353 | // set directly on the vehicle. |
1074 | private void MoveAngular(float pTimestep) | 1354 | private void MoveAngular(float pTimestep) |
1075 | { | 1355 | { |
1076 | // The user wants this many radians per second angular change? | 1356 | ComputeAngularTurning(pTimestep); |
1077 | Vector3 angularMotorContribution = m_angularMotor.Step(pTimestep); | ||
1078 | |||
1079 | // ================================================================== | ||
1080 | // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags : | ||
1081 | // This flag prevents linear deflection parallel to world z-axis. This is useful | ||
1082 | // for preventing ground vehicles with large linear deflection, like bumper cars, | ||
1083 | // from climbing their linear deflection into the sky. | ||
1084 | // That is, NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement | ||
1085 | if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) | ||
1086 | { | ||
1087 | angularMotorContribution.X = 0f; | ||
1088 | angularMotorContribution.Y = 0f; | ||
1089 | VDetailLog("{0}, MoveAngular,noDeflectionUp,angularMotorContrib={1}", Prim.LocalID, angularMotorContribution); | ||
1090 | } | ||
1091 | |||
1092 | Vector3 verticalAttractionContribution = ComputeAngularVerticalAttraction(); | ||
1093 | 1357 | ||
1094 | Vector3 deflectionContribution = ComputeAngularDeflection(); | 1358 | ComputeAngularVerticalAttraction(); |
1095 | 1359 | ||
1096 | Vector3 bankingContribution = ComputeAngularBanking(); | 1360 | ComputeAngularDeflection(); |
1097 | 1361 | ||
1098 | // ================================================================== | 1362 | ComputeAngularBanking(); |
1099 | m_lastVertAttractor = verticalAttractionContribution; | ||
1100 | |||
1101 | m_lastAngularVelocity = angularMotorContribution | ||
1102 | + verticalAttractionContribution | ||
1103 | + deflectionContribution | ||
1104 | + bankingContribution; | ||
1105 | 1363 | ||
1106 | // ================================================================== | 1364 | // ================================================================== |
1107 | // Apply the correction velocity. | 1365 | if (VehicleRotationalVelocity.ApproxEquals(Vector3.Zero, 0.0001f)) |
1108 | // TODO: Should this be applied as an angular force (torque)? | ||
1109 | if (!m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) | ||
1110 | { | 1366 | { |
1111 | VehicleRotationalVelocity = m_lastAngularVelocity; | 1367 | // The vehicle is not adding anything angular wise. |
1112 | 1368 | VehicleRotationalVelocity = Vector3.Zero; | |
1113 | VDetailLog("{0}, MoveAngular,done,nonZero,angMotorContrib={1},vertAttrContrib={2},bankContrib={3},deflectContrib={4},totalContrib={5}", | 1369 | VDetailLog("{0}, MoveAngular,done,zero", ControllingPrim.LocalID); |
1114 | Prim.LocalID, | ||
1115 | angularMotorContribution, verticalAttractionContribution, | ||
1116 | bankingContribution, deflectionContribution, | ||
1117 | m_lastAngularVelocity | ||
1118 | ); | ||
1119 | } | 1370 | } |
1120 | else | 1371 | else |
1121 | { | 1372 | { |
1122 | // The vehicle is not adding anything angular wise. | 1373 | VDetailLog("{0}, MoveAngular,done,nonZero,angVel={1}", ControllingPrim.LocalID, VehicleRotationalVelocity); |
1123 | VehicleRotationalVelocity = Vector3.Zero; | ||
1124 | VDetailLog("{0}, MoveAngular,done,zero", Prim.LocalID); | ||
1125 | } | 1374 | } |
1126 | 1375 | ||
1127 | // ================================================================== | 1376 | // ================================================================== |
@@ -1152,10 +1401,43 @@ namespace OpenSim.Region.Physics.BulletSNPlugin | |||
1152 | torqueFromOffset.Z = 0; | 1401 | torqueFromOffset.Z = 0; |
1153 | 1402 | ||
1154 | VehicleAddAngularForce(torqueFromOffset * m_vehicleMass); | 1403 | VehicleAddAngularForce(torqueFromOffset * m_vehicleMass); |
1155 | VDetailLog("{0}, BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", Prim.LocalID, torqueFromOffset); | 1404 | VDetailLog("{0}, BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", ControllingPrim.LocalID, torqueFromOffset); |
1156 | } | 1405 | } |
1157 | 1406 | ||
1158 | } | 1407 | } |
1408 | |||
1409 | private void ComputeAngularTurning(float pTimestep) | ||
1410 | { | ||
1411 | // The user wants this many radians per second angular change? | ||
1412 | Vector3 origVehicleRotationalVelocity = VehicleRotationalVelocity; // DEBUG DEBUG | ||
1413 | Vector3 currentAngularV = VehicleRotationalVelocity * Quaternion.Inverse(VehicleFrameOrientation); | ||
1414 | Vector3 angularMotorContributionV = m_angularMotor.Step(pTimestep, currentAngularV); | ||
1415 | |||
1416 | // ================================================================== | ||
1417 | // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags : | ||
1418 | // This flag prevents linear deflection parallel to world z-axis. This is useful | ||
1419 | // for preventing ground vehicles with large linear deflection, like bumper cars, | ||
1420 | // from climbing their linear deflection into the sky. | ||
1421 | // That is, NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement | ||
1422 | // TODO: This is here because this is where ODE put it but documentation says it | ||
1423 | // is a linear effect. Where should this check go? | ||
1424 | //if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) | ||
1425 | // { | ||
1426 | // angularMotorContributionV.X = 0f; | ||
1427 | // angularMotorContributionV.Y = 0f; | ||
1428 | // } | ||
1429 | |||
1430 | // Reduce any velocity by friction. | ||
1431 | Vector3 frictionFactorW = ComputeFrictionFactor(m_angularFrictionTimescale, pTimestep); | ||
1432 | angularMotorContributionV -= (currentAngularV * frictionFactorW); | ||
1433 | |||
1434 | Vector3 angularMotorContributionW = angularMotorContributionV * VehicleFrameOrientation; | ||
1435 | VehicleRotationalVelocity += angularMotorContributionW; | ||
1436 | |||
1437 | VDetailLog("{0}, MoveAngular,angularTurning,curAngVelV={1},origVehRotVel={2},vehRotVel={3},frictFact={4}, angContribV={5},angContribW={6}", | ||
1438 | ControllingPrim.LocalID, currentAngularV, origVehicleRotationalVelocity, VehicleRotationalVelocity, frictionFactorW, angularMotorContributionV, angularMotorContributionW); | ||
1439 | } | ||
1440 | |||
1159 | // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial: | 1441 | // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial: |
1160 | // Some vehicles, like boats, should always keep their up-side up. This can be done by | 1442 | // Some vehicles, like boats, should always keep their up-side up. This can be done by |
1161 | // enabling the "vertical attractor" behavior that springs the vehicle's local z-axis to | 1443 | // enabling the "vertical attractor" behavior that springs the vehicle's local z-axis to |
@@ -1164,77 +1446,183 @@ namespace OpenSim.Region.Physics.BulletSNPlugin | |||
1164 | // and then set the VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY to control the damping. An | 1446 | // and then set the VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY to control the damping. An |
1165 | // efficiency of 0.0 will cause the spring to wobble around its equilibrium, while an | 1447 | // efficiency of 0.0 will cause the spring to wobble around its equilibrium, while an |
1166 | // efficiency of 1.0 will cause the spring to reach its equilibrium with exponential decay. | 1448 | // efficiency of 1.0 will cause the spring to reach its equilibrium with exponential decay. |
1167 | public Vector3 ComputeAngularVerticalAttraction() | 1449 | public void ComputeAngularVerticalAttraction() |
1168 | { | 1450 | { |
1169 | Vector3 ret = Vector3.Zero; | ||
1170 | 1451 | ||
1171 | // If vertical attaction timescale is reasonable | 1452 | // If vertical attaction timescale is reasonable |
1172 | if (m_verticalAttractionTimescale < m_verticalAttractionCutoff) | 1453 | if (BSParam.VehicleEnableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff) |
1173 | { | 1454 | { |
1174 | // Take a vector pointing up and convert it from world to vehicle relative coords. | 1455 | Vector3 vehicleUpAxis = Vector3.UnitZ * VehicleFrameOrientation; |
1175 | Vector3 verticalError = Vector3.UnitZ * VehicleOrientation; | 1456 | switch (BSParam.VehicleAngularVerticalAttractionAlgorithm) |
1176 | |||
1177 | // If vertical attraction correction is needed, the vector that was pointing up (UnitZ) | ||
1178 | // is now: | ||
1179 | // leaning to one side: rotated around the X axis with the Y value going | ||
1180 | // from zero (nearly straight up) to one (completely to the side)) or | ||
1181 | // leaning front-to-back: rotated around the Y axis with the value of X being between | ||
1182 | // zero and one. | ||
1183 | // The value of Z is how far the rotation is off with 1 meaning none and 0 being 90 degrees. | ||
1184 | |||
1185 | // Y error means needed rotation around X axis and visa versa. | ||
1186 | // Since the error goes from zero to one, the asin is the corresponding angle. | ||
1187 | ret.X = (float)Math.Asin(verticalError.Y); | ||
1188 | // (Tilt forward (positive X) needs to tilt back (rotate negative) around Y axis.) | ||
1189 | ret.Y = -(float)Math.Asin(verticalError.X); | ||
1190 | |||
1191 | // If verticalError.Z is negative, the vehicle is upside down. Add additional push. | ||
1192 | if (verticalError.Z < 0f) | ||
1193 | { | 1457 | { |
1194 | ret.X += PIOverFour; | 1458 | case 0: |
1195 | ret.Y += PIOverFour; | 1459 | { |
1460 | //Another formula to try got from : | ||
1461 | //http://answers.unity3d.com/questions/10425/how-to-stabilize-angular-motion-alignment-of-hover.html | ||
1462 | |||
1463 | // Flipping what was originally a timescale into a speed variable and then multiplying it by 2 | ||
1464 | // since only computing half the distance between the angles. | ||
1465 | float verticalAttractionSpeed = (1 / m_verticalAttractionTimescale) * 2.0f; | ||
1466 | |||
1467 | // Make a prediction of where the up axis will be when this is applied rather then where it is now as | ||
1468 | // this makes for a smoother adjustment and less fighting between the various forces. | ||
1469 | Vector3 predictedUp = vehicleUpAxis * Quaternion.CreateFromAxisAngle(VehicleRotationalVelocity, 0f); | ||
1470 | |||
1471 | // This is only half the distance to the target so it will take 2 seconds to complete the turn. | ||
1472 | Vector3 torqueVector = Vector3.Cross(predictedUp, Vector3.UnitZ); | ||
1473 | |||
1474 | if ((m_flags & VehicleFlag.LIMIT_ROLL_ONLY) != 0) | ||
1475 | { | ||
1476 | Vector3 vehicleForwardAxis = Vector3.UnitX * VehicleFrameOrientation; | ||
1477 | torqueVector = ProjectVector(torqueVector, vehicleForwardAxis); | ||
1478 | } | ||
1479 | |||
1480 | // Scale vector by our timescale since it is an acceleration it is r/s^2 or radians a timescale squared | ||
1481 | Vector3 vertContributionV = torqueVector * verticalAttractionSpeed * verticalAttractionSpeed; | ||
1482 | |||
1483 | VehicleRotationalVelocity += vertContributionV; | ||
1484 | |||
1485 | VDetailLog("{0}, MoveAngular,verticalAttraction,vertAttrSpeed={1},upAxis={2},PredictedUp={3},torqueVector={4},contrib={5}", | ||
1486 | ControllingPrim.LocalID, | ||
1487 | verticalAttractionSpeed, | ||
1488 | vehicleUpAxis, | ||
1489 | predictedUp, | ||
1490 | torqueVector, | ||
1491 | vertContributionV); | ||
1492 | break; | ||
1493 | } | ||
1494 | case 1: | ||
1495 | { | ||
1496 | // Possible solution derived from a discussion at: | ||
1497 | // http://stackoverflow.com/questions/14939657/computing-vector-from-quaternion-works-computing-quaternion-from-vector-does-no | ||
1498 | |||
1499 | // Create a rotation that is only the vehicle's rotation around Z | ||
1500 | Vector3 currentEulerW = Vector3.Zero; | ||
1501 | VehicleFrameOrientation.GetEulerAngles(out currentEulerW.X, out currentEulerW.Y, out currentEulerW.Z); | ||
1502 | Quaternion justZOrientation = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, currentEulerW.Z); | ||
1503 | |||
1504 | // Create the axis that is perpendicular to the up vector and the rotated up vector. | ||
1505 | Vector3 differenceAxisW = Vector3.Cross(Vector3.UnitZ * justZOrientation, Vector3.UnitZ * VehicleFrameOrientation); | ||
1506 | // Compute the angle between those to vectors. | ||
1507 | double differenceAngle = Math.Acos((double)Vector3.Dot(Vector3.UnitZ, Vector3.Normalize(Vector3.UnitZ * VehicleFrameOrientation))); | ||
1508 | // 'differenceAngle' is the angle to rotate and 'differenceAxis' is the plane to rotate in to get the vehicle vertical | ||
1509 | |||
1510 | // Reduce the change by the time period it is to change in. Timestep is handled when velocity is applied. | ||
1511 | // TODO: add 'efficiency'. | ||
1512 | // differenceAngle /= m_verticalAttractionTimescale; | ||
1513 | |||
1514 | // Create the quaterian representing the correction angle | ||
1515 | Quaternion correctionRotationW = Quaternion.CreateFromAxisAngle(differenceAxisW, (float)differenceAngle); | ||
1516 | |||
1517 | // Turn that quaternion into Euler values to make it into velocities to apply. | ||
1518 | Vector3 vertContributionW = Vector3.Zero; | ||
1519 | correctionRotationW.GetEulerAngles(out vertContributionW.X, out vertContributionW.Y, out vertContributionW.Z); | ||
1520 | vertContributionW *= -1f; | ||
1521 | vertContributionW /= m_verticalAttractionTimescale; | ||
1522 | |||
1523 | VehicleRotationalVelocity += vertContributionW; | ||
1524 | |||
1525 | VDetailLog("{0}, MoveAngular,verticalAttraction,upAxis={1},diffAxis={2},diffAng={3},corrRot={4},contrib={5}", | ||
1526 | ControllingPrim.LocalID, | ||
1527 | vehicleUpAxis, | ||
1528 | differenceAxisW, | ||
1529 | differenceAngle, | ||
1530 | correctionRotationW, | ||
1531 | vertContributionW); | ||
1532 | break; | ||
1533 | } | ||
1534 | case 2: | ||
1535 | { | ||
1536 | Vector3 vertContributionV = Vector3.Zero; | ||
1537 | Vector3 origRotVelW = VehicleRotationalVelocity; // DEBUG DEBUG | ||
1538 | |||
1539 | // Take a vector pointing up and convert it from world to vehicle relative coords. | ||
1540 | Vector3 verticalError = Vector3.Normalize(Vector3.UnitZ * VehicleFrameOrientation); | ||
1541 | |||
1542 | // If vertical attraction correction is needed, the vector that was pointing up (UnitZ) | ||
1543 | // is now: | ||
1544 | // leaning to one side: rotated around the X axis with the Y value going | ||
1545 | // from zero (nearly straight up) to one (completely to the side)) or | ||
1546 | // leaning front-to-back: rotated around the Y axis with the value of X being between | ||
1547 | // zero and one. | ||
1548 | // The value of Z is how far the rotation is off with 1 meaning none and 0 being 90 degrees. | ||
1549 | |||
1550 | // Y error means needed rotation around X axis and visa versa. | ||
1551 | // Since the error goes from zero to one, the asin is the corresponding angle. | ||
1552 | vertContributionV.X = (float)Math.Asin(verticalError.Y); | ||
1553 | // (Tilt forward (positive X) needs to tilt back (rotate negative) around Y axis.) | ||
1554 | vertContributionV.Y = -(float)Math.Asin(verticalError.X); | ||
1555 | |||
1556 | // If verticalError.Z is negative, the vehicle is upside down. Add additional push. | ||
1557 | if (verticalError.Z < 0f) | ||
1558 | { | ||
1559 | vertContributionV.X += Math.Sign(vertContributionV.X) * PIOverFour; | ||
1560 | // vertContribution.Y -= PIOverFour; | ||
1561 | } | ||
1562 | |||
1563 | // 'vertContrbution' is now the necessary angular correction to correct tilt in one second. | ||
1564 | // Correction happens over a number of seconds. | ||
1565 | Vector3 unscaledContribVerticalErrorV = vertContributionV; // DEBUG DEBUG | ||
1566 | |||
1567 | // The correction happens over the user's time period | ||
1568 | vertContributionV /= m_verticalAttractionTimescale; | ||
1569 | |||
1570 | // Rotate the vehicle rotation to the world coordinates. | ||
1571 | VehicleRotationalVelocity += (vertContributionV * VehicleFrameOrientation); | ||
1572 | |||
1573 | VDetailLog("{0}, MoveAngular,verticalAttraction,,upAxis={1},origRotVW={2},vertError={3},unscaledV={4},eff={5},ts={6},vertContribV={7}", | ||
1574 | ControllingPrim.LocalID, | ||
1575 | vehicleUpAxis, | ||
1576 | origRotVelW, | ||
1577 | verticalError, | ||
1578 | unscaledContribVerticalErrorV, | ||
1579 | m_verticalAttractionEfficiency, | ||
1580 | m_verticalAttractionTimescale, | ||
1581 | vertContributionV); | ||
1582 | break; | ||
1583 | } | ||
1584 | default: | ||
1585 | { | ||
1586 | break; | ||
1587 | } | ||
1196 | } | 1588 | } |
1197 | |||
1198 | // 'ret' is now the necessary velocity to correct tilt in one second. | ||
1199 | // Correction happens over a number of seconds. | ||
1200 | Vector3 unscaledContrib = ret; | ||
1201 | ret /= m_verticalAttractionTimescale; | ||
1202 | |||
1203 | VDetailLog("{0}, MoveAngular,verticalAttraction,,verticalError={1},unscaled={2},eff={3},ts={4},vertAttr={5}", | ||
1204 | Prim.LocalID, verticalError, unscaledContrib, m_verticalAttractionEfficiency, m_verticalAttractionTimescale, ret); | ||
1205 | } | 1589 | } |
1206 | return ret; | ||
1207 | } | 1590 | } |
1208 | 1591 | ||
1209 | // Return the angular correction to correct the direction the vehicle is pointing to be | 1592 | // Angular correction to correct the direction the vehicle is pointing to be |
1210 | // the direction is should want to be pointing. | 1593 | // the direction is should want to be pointing. |
1211 | // The vehicle is moving in some direction and correct its orientation to it is pointing | 1594 | // The vehicle is moving in some direction and correct its orientation to it is pointing |
1212 | // in that direction. | 1595 | // in that direction. |
1213 | // TODO: implement reference frame. | 1596 | // TODO: implement reference frame. |
1214 | public Vector3 ComputeAngularDeflection() | 1597 | public void ComputeAngularDeflection() |
1215 | { | 1598 | { |
1216 | Vector3 ret = Vector3.Zero; | 1599 | |
1217 | return ret; // DEBUG DEBUG DEBUG | 1600 | if (BSParam.VehicleEnableAngularDeflection && m_angularDeflectionEfficiency != 0 && VehicleForwardSpeed > 0.2) |
1218 | // Disable angular deflection for the moment. | ||
1219 | // Since angularMotorUp and angularDeflection are computed independently, they will calculate | ||
1220 | // approximately the same X or Y correction. When added together (when contributions are combined) | ||
1221 | // this creates an over-correction and then wabbling as the target is overshot. | ||
1222 | // TODO: rethink how the different correction computations inter-relate. | ||
1223 | |||
1224 | if (m_angularDeflectionEfficiency != 0) | ||
1225 | { | 1601 | { |
1602 | Vector3 deflectContributionV = Vector3.Zero; | ||
1603 | |||
1226 | // The direction the vehicle is moving | 1604 | // The direction the vehicle is moving |
1227 | Vector3 movingDirection = VehicleVelocity; | 1605 | Vector3 movingDirection = VehicleVelocity; |
1228 | movingDirection.Normalize(); | 1606 | movingDirection.Normalize(); |
1229 | 1607 | ||
1608 | // If the vehicle is going backward, it is still pointing forward | ||
1609 | movingDirection *= Math.Sign(VehicleForwardSpeed); | ||
1610 | |||
1230 | // The direction the vehicle is pointing | 1611 | // The direction the vehicle is pointing |
1231 | Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation; | 1612 | Vector3 pointingDirection = Vector3.UnitX * VehicleFrameOrientation; |
1232 | pointingDirection.Normalize(); | 1613 | //Predict where the Vehicle will be pointing after AngularVelocity change is applied. This will keep |
1614 | // from overshooting and allow this correction to merge with the Vertical Attraction peacefully. | ||
1615 | Vector3 predictedPointingDirection = pointingDirection * Quaternion.CreateFromAxisAngle(VehicleRotationalVelocity, 0f); | ||
1616 | predictedPointingDirection.Normalize(); | ||
1233 | 1617 | ||
1234 | // The difference between what is and what should be. | 1618 | // The difference between what is and what should be. |
1235 | Vector3 deflectionError = movingDirection - pointingDirection; | 1619 | // Vector3 deflectionError = movingDirection - predictedPointingDirection; |
1620 | Vector3 deflectionError = Vector3.Cross(movingDirection, predictedPointingDirection); | ||
1236 | 1621 | ||
1237 | // Don't try to correct very large errors (not our job) | 1622 | // Don't try to correct very large errors (not our job) |
1623 | // if (Math.Abs(deflectionError.X) > PIOverFour) deflectionError.X = PIOverTwo * Math.Sign(deflectionError.X); | ||
1624 | // if (Math.Abs(deflectionError.Y) > PIOverFour) deflectionError.Y = PIOverTwo * Math.Sign(deflectionError.Y); | ||
1625 | // if (Math.Abs(deflectionError.Z) > PIOverFour) deflectionError.Z = PIOverTwo * Math.Sign(deflectionError.Z); | ||
1238 | if (Math.Abs(deflectionError.X) > PIOverFour) deflectionError.X = 0f; | 1626 | if (Math.Abs(deflectionError.X) > PIOverFour) deflectionError.X = 0f; |
1239 | if (Math.Abs(deflectionError.Y) > PIOverFour) deflectionError.Y = 0f; | 1627 | if (Math.Abs(deflectionError.Y) > PIOverFour) deflectionError.Y = 0f; |
1240 | if (Math.Abs(deflectionError.Z) > PIOverFour) deflectionError.Z = 0f; | 1628 | if (Math.Abs(deflectionError.Z) > PIOverFour) deflectionError.Z = 0f; |
@@ -1242,18 +1630,19 @@ namespace OpenSim.Region.Physics.BulletSNPlugin | |||
1242 | // ret = m_angularDeflectionCorrectionMotor(1f, deflectionError); | 1630 | // ret = m_angularDeflectionCorrectionMotor(1f, deflectionError); |
1243 | 1631 | ||
1244 | // Scale the correction by recovery timescale and efficiency | 1632 | // Scale the correction by recovery timescale and efficiency |
1245 | ret = (-deflectionError) * m_angularDeflectionEfficiency; | 1633 | // Not modeling a spring so clamp the scale to no more then the arc |
1246 | ret /= m_angularDeflectionTimescale; | 1634 | deflectContributionV = (-deflectionError) * ClampInRange(0, m_angularDeflectionEfficiency/m_angularDeflectionTimescale,1f); |
1635 | //deflectContributionV /= m_angularDeflectionTimescale; | ||
1247 | 1636 | ||
1637 | VehicleRotationalVelocity += deflectContributionV; | ||
1248 | VDetailLog("{0}, MoveAngular,Deflection,movingDir={1},pointingDir={2},deflectError={3},ret={4}", | 1638 | VDetailLog("{0}, MoveAngular,Deflection,movingDir={1},pointingDir={2},deflectError={3},ret={4}", |
1249 | Prim.LocalID, movingDirection, pointingDirection, deflectionError, ret); | 1639 | ControllingPrim.LocalID, movingDirection, pointingDirection, deflectionError, deflectContributionV); |
1250 | VDetailLog("{0}, MoveAngular,Deflection,fwdSpd={1},defEff={2},defTS={3}", | 1640 | VDetailLog("{0}, MoveAngular,Deflection,fwdSpd={1},defEff={2},defTS={3},PredictedPointingDir={4}", |
1251 | Prim.LocalID, VehicleForwardSpeed, m_angularDeflectionEfficiency, m_angularDeflectionTimescale); | 1641 | ControllingPrim.LocalID, VehicleForwardSpeed, m_angularDeflectionEfficiency, m_angularDeflectionTimescale, predictedPointingDirection); |
1252 | } | 1642 | } |
1253 | return ret; | ||
1254 | } | 1643 | } |
1255 | 1644 | ||
1256 | // Return an angular change to rotate the vehicle around the Z axis when the vehicle | 1645 | // Angular change to rotate the vehicle around the Z axis when the vehicle |
1257 | // is tipped around the X axis. | 1646 | // is tipped around the X axis. |
1258 | // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial: | 1647 | // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial: |
1259 | // The vertical attractor feature must be enabled in order for the banking behavior to | 1648 | // The vertical attractor feature must be enabled in order for the banking behavior to |
@@ -1261,13 +1650,13 @@ namespace OpenSim.Region.Physics.BulletSNPlugin | |||
1261 | // produce a angular velocity around the yaw-axis, causing the vehicle to turn. The magnitude | 1650 | // produce a angular velocity around the yaw-axis, causing the vehicle to turn. The magnitude |
1262 | // of the yaw effect will be proportional to the | 1651 | // of the yaw effect will be proportional to the |
1263 | // VEHICLE_BANKING_EFFICIENCY, the angle of the roll rotation, and sometimes the vehicle's | 1652 | // VEHICLE_BANKING_EFFICIENCY, the angle of the roll rotation, and sometimes the vehicle's |
1264 | // velocity along its preferred axis of motion. | 1653 | // velocity along its preferred axis of motion. |
1265 | // The VEHICLE_BANKING_EFFICIENCY can vary between -1 and +1. When it is positive then any | 1654 | // The VEHICLE_BANKING_EFFICIENCY can vary between -1 and +1. When it is positive then any |
1266 | // positive rotation (by the right-hand rule) about the roll-axis will effect a | 1655 | // positive rotation (by the right-hand rule) about the roll-axis will effect a |
1267 | // (negative) torque around the yaw-axis, making it turn to the right--that is the | 1656 | // (negative) torque around the yaw-axis, making it turn to the right--that is the |
1268 | // vehicle will lean into the turn, which is how real airplanes and motorcycle's work. | 1657 | // vehicle will lean into the turn, which is how real airplanes and motorcycle's work. |
1269 | // Negating the banking coefficient will make it so that the vehicle leans to the | 1658 | // Negating the banking coefficient will make it so that the vehicle leans to the |
1270 | // outside of the turn (not very "physical" but might allow interesting vehicles so why not?). | 1659 | // outside of the turn (not very "physical" but might allow interesting vehicles so why not?). |
1271 | // The VEHICLE_BANKING_MIX is a fake (i.e. non-physical) parameter that is useful for making | 1660 | // The VEHICLE_BANKING_MIX is a fake (i.e. non-physical) parameter that is useful for making |
1272 | // banking vehicles do what you want rather than what the laws of physics allow. | 1661 | // banking vehicles do what you want rather than what the laws of physics allow. |
1273 | // For example, consider a real motorcycle...it must be moving forward in order for | 1662 | // For example, consider a real motorcycle...it must be moving forward in order for |
@@ -1279,46 +1668,43 @@ namespace OpenSim.Region.Physics.BulletSNPlugin | |||
1279 | // totally static (0.0) and totally dynamic (1.0). By "static" we mean that the | 1668 | // totally static (0.0) and totally dynamic (1.0). By "static" we mean that the |
1280 | // banking effect depends only on the vehicle's rotation about its roll-axis compared | 1669 | // banking effect depends only on the vehicle's rotation about its roll-axis compared |
1281 | // to "dynamic" where the banking is also proportional to its velocity along its | 1670 | // to "dynamic" where the banking is also proportional to its velocity along its |
1282 | // roll-axis. Finding the best value of the "mixture" will probably require trial and error. | 1671 | // roll-axis. Finding the best value of the "mixture" will probably require trial and error. |
1283 | // The time it takes for the banking behavior to defeat a preexisting angular velocity about the | 1672 | // The time it takes for the banking behavior to defeat a preexisting angular velocity about the |
1284 | // world z-axis is determined by the VEHICLE_BANKING_TIMESCALE. So if you want the vehicle to | 1673 | // world z-axis is determined by the VEHICLE_BANKING_TIMESCALE. So if you want the vehicle to |
1285 | // bank quickly then give it a banking timescale of about a second or less, otherwise you can | 1674 | // bank quickly then give it a banking timescale of about a second or less, otherwise you can |
1286 | // make a sluggish vehicle by giving it a timescale of several seconds. | 1675 | // make a sluggish vehicle by giving it a timescale of several seconds. |
1287 | public Vector3 ComputeAngularBanking() | 1676 | public void ComputeAngularBanking() |
1288 | { | 1677 | { |
1289 | Vector3 ret = Vector3.Zero; | 1678 | if (BSParam.VehicleEnableAngularBanking && m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff) |
1290 | |||
1291 | if (m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff) | ||
1292 | { | 1679 | { |
1293 | // This works by rotating a unit vector to the orientation of the vehicle. The | 1680 | Vector3 bankingContributionV = Vector3.Zero; |
1294 | // roll (tilt) will be Y component of a tilting Z vector (zero for no tilt | ||
1295 | // up to one for full over). | ||
1296 | Vector3 rollComponents = Vector3.UnitZ * VehicleOrientation; | ||
1297 | 1681 | ||
1298 | // Figure out the yaw value for this much roll. | 1682 | // Rotate a UnitZ vector (pointing up) to how the vehicle is oriented. |
1299 | float turnComponent = rollComponents.Y * rollComponents.Y * m_bankingEfficiency; | 1683 | // As the vehicle rolls to the right or left, the Y value will increase from |
1300 | // Keep the sign | 1684 | // zero (straight up) to 1 or -1 (full tilt right or left) |
1301 | if (rollComponents.Y < 0f) | 1685 | Vector3 rollComponents = Vector3.UnitZ * VehicleFrameOrientation; |
1302 | turnComponent = -turnComponent; | ||
1303 | |||
1304 | // TODO: there must be a better computation of the banking force. | ||
1305 | float bankingTurnForce = turnComponent; | ||
1306 | 1686 | ||
1687 | // Figure out the yaw value for this much roll. | ||
1688 | float yawAngle = m_angularMotorDirection.X * m_bankingEfficiency; | ||
1307 | // actual error = static turn error + dynamic turn error | 1689 | // actual error = static turn error + dynamic turn error |
1308 | float mixedBankingError = bankingTurnForce * (1f - m_bankingMix) + bankingTurnForce * m_bankingMix * VehicleForwardSpeed; | 1690 | float mixedYawAngle =(yawAngle * (1f - m_bankingMix)) + ((yawAngle * m_bankingMix) * VehicleForwardSpeed); |
1691 | |||
1309 | // TODO: the banking effect should not go to infinity but what to limit it to? | 1692 | // TODO: the banking effect should not go to infinity but what to limit it to? |
1310 | mixedBankingError = ClampInRange(-20f, mixedBankingError, 20f); | 1693 | // And what should happen when this is being added to a user defined yaw that is already PI*4? |
1694 | mixedYawAngle = ClampInRange(-FourPI, mixedYawAngle, FourPI); | ||
1311 | 1695 | ||
1312 | // Build the force vector to change rotation from what it is to what it should be | 1696 | // Build the force vector to change rotation from what it is to what it should be |
1313 | ret.Z = -mixedBankingError; | 1697 | bankingContributionV.Z = -mixedYawAngle; |
1698 | |||
1699 | // Don't do it all at once. Fudge because 1 second is too fast with most user defined roll as PI*4. | ||
1700 | bankingContributionV /= m_bankingTimescale * BSParam.VehicleAngularBankingTimescaleFudge; | ||
1701 | |||
1702 | VehicleRotationalVelocity += bankingContributionV; | ||
1314 | 1703 | ||
1315 | // Don't do it all at once. | ||
1316 | ret /= m_bankingTimescale; | ||
1317 | 1704 | ||
1318 | VDetailLog("{0}, MoveAngular,Banking,rollComp={1},speed={2},turnComp={3},bankErr={4},mixedBankErr={5},ret={6}", | 1705 | VDetailLog("{0}, MoveAngular,Banking,rollComp={1},speed={2},rollComp={3},yAng={4},mYAng={5},ret={6}", |
1319 | Prim.LocalID, rollComponents, VehicleForwardSpeed, turnComponent, bankingTurnForce, mixedBankingError, ret); | 1706 | ControllingPrim.LocalID, rollComponents, VehicleForwardSpeed, rollComponents, yawAngle, mixedYawAngle, bankingContributionV); |
1320 | } | 1707 | } |
1321 | return ret; | ||
1322 | } | 1708 | } |
1323 | 1709 | ||
1324 | // This is from previous instantiations of XXXDynamics.cs. | 1710 | // This is from previous instantiations of XXXDynamics.cs. |
@@ -1356,8 +1742,45 @@ namespace OpenSim.Region.Physics.BulletSNPlugin | |||
1356 | if (rotq != m_rot) | 1742 | if (rotq != m_rot) |
1357 | { | 1743 | { |
1358 | VehicleOrientation = m_rot; | 1744 | VehicleOrientation = m_rot; |
1359 | VDetailLog("{0}, LimitRotation,done,orig={1},new={2}", Prim.LocalID, rotq, m_rot); | 1745 | VDetailLog("{0}, LimitRotation,done,orig={1},new={2}", ControllingPrim.LocalID, rotq, m_rot); |
1746 | } | ||
1747 | |||
1748 | } | ||
1749 | |||
1750 | // Given a friction vector (reduction in seconds) and a timestep, return the factor to reduce | ||
1751 | // some value by to apply this friction. | ||
1752 | private Vector3 ComputeFrictionFactor(Vector3 friction, float pTimestep) | ||
1753 | { | ||
1754 | Vector3 frictionFactor = Vector3.Zero; | ||
1755 | if (friction != BSMotor.InfiniteVector) | ||
1756 | { | ||
1757 | // frictionFactor = (Vector3.One / FrictionTimescale) * timeStep; | ||
1758 | // Individual friction components can be 'infinite' so compute each separately. | ||
1759 | frictionFactor.X = (friction.X == BSMotor.Infinite) ? 0f : (1f / friction.X); | ||
1760 | frictionFactor.Y = (friction.Y == BSMotor.Infinite) ? 0f : (1f / friction.Y); | ||
1761 | frictionFactor.Z = (friction.Z == BSMotor.Infinite) ? 0f : (1f / friction.Z); | ||
1762 | frictionFactor *= pTimestep; | ||
1763 | } | ||
1764 | return frictionFactor; | ||
1765 | } | ||
1766 | |||
1767 | private float SortedClampInRange(float clampa, float val, float clampb) | ||
1768 | { | ||
1769 | if (clampa > clampb) | ||
1770 | { | ||
1771 | float temp = clampa; | ||
1772 | clampa = clampb; | ||
1773 | clampb = temp; | ||
1360 | } | 1774 | } |
1775 | return ClampInRange(clampa, val, clampb); | ||
1776 | |||
1777 | } | ||
1778 | |||
1779 | //Given a Vector and a unit vector will return the amount of the vector is on the same axis as the unit. | ||
1780 | private Vector3 ProjectVector(Vector3 vector, Vector3 onNormal) | ||
1781 | { | ||
1782 | float vectorDot = Vector3.Dot(vector, onNormal); | ||
1783 | return onNormal * vectorDot; | ||
1361 | 1784 | ||
1362 | } | 1785 | } |
1363 | 1786 | ||
@@ -1370,8 +1793,8 @@ namespace OpenSim.Region.Physics.BulletSNPlugin | |||
1370 | // Invoke the detailed logger and output something if it's enabled. | 1793 | // Invoke the detailed logger and output something if it's enabled. |
1371 | private void VDetailLog(string msg, params Object[] args) | 1794 | private void VDetailLog(string msg, params Object[] args) |
1372 | { | 1795 | { |
1373 | if (Prim.PhysicsScene.VehicleLoggingEnabled) | 1796 | if (ControllingPrim.PhysScene.VehicleLoggingEnabled) |
1374 | Prim.PhysicsScene.DetailLog(msg, args); | 1797 | ControllingPrim.PhysScene.DetailLog(msg, args); |
1375 | } | 1798 | } |
1376 | } | 1799 | } |
1377 | } | 1800 | } |