diff options
Diffstat (limited to 'OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs')
-rw-r--r-- | OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs | 440 |
1 files changed, 216 insertions, 224 deletions
diff --git a/OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs b/OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs index 39cdc0f..008070b 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs | |||
@@ -32,11 +32,11 @@ | |||
32 | * ODEDynamics.cs contains methods dealing with Prim Physical motion | 32 | * ODEDynamics.cs contains methods dealing with Prim Physical motion |
33 | * (dynamics) and the associated settings. Old Linear and angular | 33 | * (dynamics) and the associated settings. Old Linear and angular |
34 | * motors for dynamic motion have been replace with MoveLinear() | 34 | * motors for dynamic motion have been replace with MoveLinear() |
35 | * and MoveAngular(); 'Physical' is used only to switch ODE dynamic | 35 | * and MoveAngular(); 'Physical' is used only to switch ODE dynamic |
36 | * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_<other> is to | 36 | * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_<other> is to |
37 | * switch between 'VEHICLE' parameter use and general dynamics | 37 | * switch between 'VEHICLE' parameter use and general dynamics |
38 | * settings use. | 38 | * settings use. |
39 | */ | 39 | */ |
40 | 40 | ||
41 | using System; | 41 | using System; |
42 | using System.Collections.Generic; | 42 | using System.Collections.Generic; |
@@ -53,7 +53,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
53 | public class ODEDynamics | 53 | public class ODEDynamics |
54 | { | 54 | { |
55 | public Vehicle Type | 55 | public Vehicle Type |
56 | { | 56 | { |
57 | get { return m_type; } | 57 | get { return m_type; } |
58 | } | 58 | } |
59 | 59 | ||
@@ -62,14 +62,14 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
62 | get { return m_body; } | 62 | get { return m_body; } |
63 | } | 63 | } |
64 | 64 | ||
65 | private int frcount = 0; // Used to limit dynamics debug output to | 65 | private int frcount = 0; // Used to limit dynamics debug output to |
66 | // every 100th frame | 66 | // every 100th frame |
67 | 67 | ||
68 | // private OdeScene m_parentScene = null; | 68 | // private OdeScene m_parentScene = null; |
69 | private IntPtr m_body = IntPtr.Zero; | 69 | private IntPtr m_body = IntPtr.Zero; |
70 | // private IntPtr m_jointGroup = IntPtr.Zero; | 70 | // private IntPtr m_jointGroup = IntPtr.Zero; |
71 | // private IntPtr m_aMotor = IntPtr.Zero; | 71 | // private IntPtr m_aMotor = IntPtr.Zero; |
72 | 72 | ||
73 | 73 | ||
74 | // Vehicle properties | 74 | // Vehicle properties |
75 | private Vehicle m_type = Vehicle.TYPE_NONE; // If a 'VEHICLE', and what kind | 75 | private Vehicle m_type = Vehicle.TYPE_NONE; // If a 'VEHICLE', and what kind |
@@ -82,7 +82,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
82 | // HOVER_UP_ONLY | 82 | // HOVER_UP_ONLY |
83 | // LIMIT_MOTOR_UP | 83 | // LIMIT_MOTOR_UP |
84 | // LIMIT_ROLL_ONLY | 84 | // LIMIT_ROLL_ONLY |
85 | 85 | ||
86 | // Linear properties | 86 | // Linear properties |
87 | private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time | 87 | private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time |
88 | private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL | 88 | private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL |
@@ -91,47 +91,43 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
91 | private float m_linearMotorDecayTimescale = 0; | 91 | private float m_linearMotorDecayTimescale = 0; |
92 | private float m_linearMotorTimescale = 0; | 92 | private float m_linearMotorTimescale = 0; |
93 | private Vector3 m_lastLinearVelocityVector = Vector3.Zero; | 93 | private Vector3 m_lastLinearVelocityVector = Vector3.Zero; |
94 | // private bool m_LinearMotorSetLastFrame = false; | 94 | // private bool m_LinearMotorSetLastFrame = false; |
95 | // private Vector3 m_linearMotorOffset = Vector3.Zero; | 95 | // private Vector3 m_linearMotorOffset = Vector3.Zero; |
96 | 96 | ||
97 | //Angular properties | 97 | //Angular properties |
98 | private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor | 98 | private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor |
99 | private int m_angularMotorApply = 0; // application frame counter | 99 | private int m_angularMotorApply = 0; // application frame counter |
100 | private Vector3 m_angularMotorVelocity = Vector3.Zero; // current angular motor velocity | 100 | private Vector3 m_angularMotorVelocity = Vector3.Zero; // current angular motor velocity |
101 | private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate | 101 | private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate |
102 | private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate | 102 | private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate |
103 | private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate | 103 | private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate |
104 | private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body | 104 | private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body |
105 | // private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body | 105 | // private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body |
106 | 106 | ||
107 | //Deflection properties | 107 | //Deflection properties |
108 | // private float m_angularDeflectionEfficiency = 0; | 108 | // private float m_angularDeflectionEfficiency = 0; |
109 | // private float m_angularDeflectionTimescale = 0; | 109 | // private float m_angularDeflectionTimescale = 0; |
110 | // private float m_linearDeflectionEfficiency = 0; | 110 | // private float m_linearDeflectionEfficiency = 0; |
111 | // private float m_linearDeflectionTimescale = 0; | 111 | // private float m_linearDeflectionTimescale = 0; |
112 | 112 | ||
113 | //Banking properties | 113 | //Banking properties |
114 | // private float m_bankingEfficiency = 0; | 114 | // private float m_bankingEfficiency = 0; |
115 | // private float m_bankingMix = 0; | 115 | // private float m_bankingMix = 0; |
116 | // private float m_bankingTimescale = 0; | 116 | // private float m_bankingTimescale = 0; |
117 | 117 | ||
118 | //Hover and Buoyancy properties | 118 | //Hover and Buoyancy properties |
119 | private float m_VhoverHeight = 0f; | 119 | private float m_VhoverHeight = 0f; |
120 | // private float m_VhoverEfficiency = 0f; | 120 | // private float m_VhoverEfficiency = 0f; |
121 | private float m_VhoverTimescale = 0f; | 121 | private float m_VhoverTimescale = 0f; |
122 | private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height | 122 | private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height |
123 | private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle. | 123 | private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle. |
124 | // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity) | 124 | // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity) |
125 | // KF: So far I have found no good method to combine a script-requested .Z velocity and gravity. | 125 | // KF: So far I have found no good method to combine a script-requested .Z velocity and gravity. |
126 | // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity. | 126 | // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity. |
127 | 127 | ||
128 | //Attractor properties | 128 | //Attractor properties |
129 | private float m_verticalAttractionEfficiency = 1.0f; // damped | 129 | private float m_verticalAttractionEfficiency = 1.0f; // damped |
130 | private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor. | 130 | private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor. |
131 | |||
132 | |||
133 | |||
134 | |||
135 | 131 | ||
136 | internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue) | 132 | internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue) |
137 | { | 133 | { |
@@ -166,13 +162,13 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
166 | // m_bankingTimescale = pValue; | 162 | // m_bankingTimescale = pValue; |
167 | break; | 163 | break; |
168 | case Vehicle.BUOYANCY: | 164 | case Vehicle.BUOYANCY: |
169 | if (pValue < -1f) pValue = -1f; | 165 | if (pValue < -1f) pValue = -1f; |
170 | if (pValue > 1f) pValue = 1f; | 166 | if (pValue > 1f) pValue = 1f; |
171 | m_VehicleBuoyancy = pValue; | 167 | m_VehicleBuoyancy = pValue; |
172 | break; | 168 | break; |
173 | // case Vehicle.HOVER_EFFICIENCY: | 169 | // case Vehicle.HOVER_EFFICIENCY: |
174 | // if (pValue < 0f) pValue = 0f; | 170 | // if (pValue < 0f) pValue = 0f; |
175 | // if (pValue > 1f) pValue = 1f; | 171 | // if (pValue > 1f) pValue = 1f; |
176 | // m_VhoverEfficiency = pValue; | 172 | // m_VhoverEfficiency = pValue; |
177 | // break; | 173 | // break; |
178 | case Vehicle.HOVER_HEIGHT: | 174 | case Vehicle.HOVER_HEIGHT: |
@@ -199,7 +195,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
199 | m_linearMotorTimescale = pValue; | 195 | m_linearMotorTimescale = pValue; |
200 | break; | 196 | break; |
201 | case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY: | 197 | case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY: |
202 | if (pValue < 0.1f) pValue = 0.1f; // Less goes unstable | 198 | if (pValue < 0.1f) pValue = 0.1f; // Less goes unstable |
203 | if (pValue > 1.0f) pValue = 1.0f; | 199 | if (pValue > 1.0f) pValue = 1.0f; |
204 | m_verticalAttractionEfficiency = pValue; | 200 | m_verticalAttractionEfficiency = pValue; |
205 | break; | 201 | break; |
@@ -207,8 +203,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
207 | if (pValue < 0.01f) pValue = 0.01f; | 203 | if (pValue < 0.01f) pValue = 0.01f; |
208 | m_verticalAttractionTimescale = pValue; | 204 | m_verticalAttractionTimescale = pValue; |
209 | break; | 205 | break; |
210 | 206 | ||
211 | // These are vector properties but the engine lets you use a single float value to | 207 | // These are vector properties but the engine lets you use a single float value to |
212 | // set all of the components to the same value | 208 | // set all of the components to the same value |
213 | case Vehicle.ANGULAR_FRICTION_TIMESCALE: | 209 | case Vehicle.ANGULAR_FRICTION_TIMESCALE: |
214 | m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue); | 210 | m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue); |
@@ -229,7 +225,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
229 | break; | 225 | break; |
230 | 226 | ||
231 | } | 227 | } |
232 | |||
233 | }//end ProcessFloatVehicleParam | 228 | }//end ProcessFloatVehicleParam |
234 | 229 | ||
235 | internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue) | 230 | internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue) |
@@ -242,12 +237,12 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
242 | case Vehicle.ANGULAR_MOTOR_DIRECTION: | 237 | case Vehicle.ANGULAR_MOTOR_DIRECTION: |
243 | m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); | 238 | m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); |
244 | // Limit requested angular speed to 2 rps= 4 pi rads/sec | 239 | // Limit requested angular speed to 2 rps= 4 pi rads/sec |
245 | if(m_angularMotorDirection.X > 12.56f) m_angularMotorDirection.X = 12.56f; | 240 | if (m_angularMotorDirection.X > 12.56f) m_angularMotorDirection.X = 12.56f; |
246 | if(m_angularMotorDirection.X < - 12.56f) m_angularMotorDirection.X = - 12.56f; | 241 | if (m_angularMotorDirection.X < - 12.56f) m_angularMotorDirection.X = - 12.56f; |
247 | if(m_angularMotorDirection.Y > 12.56f) m_angularMotorDirection.Y = 12.56f; | 242 | if (m_angularMotorDirection.Y > 12.56f) m_angularMotorDirection.Y = 12.56f; |
248 | if(m_angularMotorDirection.Y < - 12.56f) m_angularMotorDirection.Y = - 12.56f; | 243 | if (m_angularMotorDirection.Y < - 12.56f) m_angularMotorDirection.Y = - 12.56f; |
249 | if(m_angularMotorDirection.Z > 12.56f) m_angularMotorDirection.Z = 12.56f; | 244 | if (m_angularMotorDirection.Z > 12.56f) m_angularMotorDirection.Z = 12.56f; |
250 | if(m_angularMotorDirection.Z < - 12.56f) m_angularMotorDirection.Z = - 12.56f; | 245 | if (m_angularMotorDirection.Z < - 12.56f) m_angularMotorDirection.Z = - 12.56f; |
251 | m_angularMotorApply = 10; | 246 | m_angularMotorApply = 10; |
252 | break; | 247 | break; |
253 | case Vehicle.LINEAR_FRICTION_TIMESCALE: | 248 | case Vehicle.LINEAR_FRICTION_TIMESCALE: |
@@ -261,7 +256,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
261 | // m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z); | 256 | // m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z); |
262 | break; | 257 | break; |
263 | } | 258 | } |
264 | |||
265 | }//end ProcessVectorVehicleParam | 259 | }//end ProcessVectorVehicleParam |
266 | 260 | ||
267 | internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) | 261 | internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) |
@@ -272,12 +266,11 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
272 | // m_referenceFrame = pValue; | 266 | // m_referenceFrame = pValue; |
273 | break; | 267 | break; |
274 | } | 268 | } |
275 | |||
276 | }//end ProcessRotationVehicleParam | 269 | }//end ProcessRotationVehicleParam |
277 | 270 | ||
278 | internal void ProcessTypeChange(Vehicle pType) | 271 | internal void ProcessTypeChange(Vehicle pType) |
279 | { | 272 | { |
280 | // Set Defaults For Type | 273 | // Set Defaults For Type |
281 | m_type = pType; | 274 | m_type = pType; |
282 | switch (pType) | 275 | switch (pType) |
283 | { | 276 | { |
@@ -357,8 +350,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
357 | // m_bankingMix = 0.8f; | 350 | // m_bankingMix = 0.8f; |
358 | // m_bankingTimescale = 1; | 351 | // m_bankingTimescale = 1; |
359 | // m_referenceFrame = Quaternion.Identity; | 352 | // m_referenceFrame = Quaternion.Identity; |
360 | m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.LIMIT_ROLL_ONLY | | 353 | m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.LIMIT_ROLL_ONLY | |
361 | VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); | 354 | VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); |
362 | m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | | 355 | m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | |
363 | VehicleFlag.LIMIT_MOTOR_UP); | 356 | VehicleFlag.LIMIT_MOTOR_UP); |
364 | break; | 357 | break; |
@@ -432,24 +425,25 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
432 | { | 425 | { |
433 | if (m_body == IntPtr.Zero || m_type == Vehicle.TYPE_NONE) | 426 | if (m_body == IntPtr.Zero || m_type == Vehicle.TYPE_NONE) |
434 | return; | 427 | return; |
435 | frcount++; // used to limit debug comment output | 428 | frcount++; // used to limit debug comment output |
436 | if (frcount > 100) | 429 | if (frcount > 100) |
437 | frcount = 0; | 430 | frcount = 0; |
438 | 431 | ||
439 | MoveLinear(pTimestep, pParentScene); | 432 | MoveLinear(pTimestep, pParentScene); |
440 | MoveAngular(pTimestep); | 433 | MoveAngular(pTimestep); |
441 | }// end Step | 434 | }// end Step |
442 | 435 | ||
443 | private void MoveLinear(float pTimestep, OdeScene _pParentScene) | 436 | private void MoveLinear(float pTimestep, OdeScene _pParentScene) |
444 | { | 437 | { |
445 | if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) // requested m_linearMotorDirection is significant | 438 | if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) // requested m_linearMotorDirection is significant |
446 | { | 439 | { |
447 | if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); | 440 | if (!d.BodyIsEnabled(Body)) |
441 | d.BodyEnable(Body); | ||
448 | 442 | ||
449 | // add drive to body | 443 | // add drive to body |
450 | Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep); | 444 | Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep); |
451 | m_lastLinearVelocityVector += (addAmount*10); // lastLinearVelocityVector is the current body velocity vector? | 445 | m_lastLinearVelocityVector += (addAmount*10); // lastLinearVelocityVector is the current body velocity vector? |
452 | 446 | ||
453 | // This will work temporarily, but we really need to compare speed on an axis | 447 | // This will work temporarily, but we really need to compare speed on an axis |
454 | // KF: Limit body velocity to applied velocity? | 448 | // KF: Limit body velocity to applied velocity? |
455 | if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X)) | 449 | if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X)) |
@@ -458,7 +452,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
458 | m_lastLinearVelocityVector.Y = m_linearMotorDirectionLASTSET.Y; | 452 | m_lastLinearVelocityVector.Y = m_linearMotorDirectionLASTSET.Y; |
459 | if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z)) | 453 | if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z)) |
460 | m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z; | 454 | m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z; |
461 | 455 | ||
462 | // decay applied velocity | 456 | // decay applied velocity |
463 | Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep))); | 457 | Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep))); |
464 | //Console.WriteLine("decay: " + decayfraction); | 458 | //Console.WriteLine("decay: " + decayfraction); |
@@ -466,194 +460,192 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
466 | //Console.WriteLine("actual: " + m_linearMotorDirection); | 460 | //Console.WriteLine("actual: " + m_linearMotorDirection); |
467 | } | 461 | } |
468 | else | 462 | else |
469 | { // requested is not significant | 463 | { // requested is not significant |
470 | // if what remains of applied is small, zero it. | 464 | // if what remains of applied is small, zero it. |
471 | if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f)) | 465 | if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f)) |
472 | m_lastLinearVelocityVector = Vector3.Zero; | 466 | m_lastLinearVelocityVector = Vector3.Zero; |
473 | } | 467 | } |
474 | 468 | ||
475 | 469 | // convert requested object velocity to world-referenced vector | |
476 | // convert requested object velocity to world-referenced vector | ||
477 | m_dir = m_lastLinearVelocityVector; | 470 | m_dir = m_lastLinearVelocityVector; |
478 | d.Quaternion rot = d.BodyGetQuaternion(Body); | 471 | d.Quaternion rot = d.BodyGetQuaternion(Body); |
479 | Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object | 472 | Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object |
480 | m_dir *= rotq; // apply obj rotation to velocity vector | 473 | m_dir *= rotq; // apply obj rotation to velocity vector |
481 | 474 | ||
482 | // add Gravity andBuoyancy | 475 | // add Gravity andBuoyancy |
483 | // KF: So far I have found no good method to combine a script-requested | 476 | // KF: So far I have found no good method to combine a script-requested |
484 | // .Z velocity and gravity. Therefore only 0g will used script-requested | 477 | // .Z velocity and gravity. Therefore only 0g will used script-requested |
485 | // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only. | 478 | // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only. |
486 | Vector3 grav = Vector3.Zero; | 479 | Vector3 grav = Vector3.Zero; |
487 | if(m_VehicleBuoyancy < 1.0f) | 480 | if (m_VehicleBuoyancy < 1.0f) |
488 | { | 481 | { |
489 | // There is some gravity, make a gravity force vector | 482 | // There is some gravity, make a gravity force vector |
490 | // that is applied after object velocity. | 483 | // that is applied after object velocity. |
491 | d.Mass objMass; | 484 | d.Mass objMass; |
492 | d.BodyGetMass(Body, out objMass); | 485 | d.BodyGetMass(Body, out objMass); |
493 | // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; | 486 | // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; |
494 | grav.Z = _pParentScene.gravityz * objMass.mass * (1f - m_VehicleBuoyancy); | 487 | grav.Z = _pParentScene.gravityz * objMass.mass * (1f - m_VehicleBuoyancy); |
495 | // Preserve the current Z velocity | 488 | // Preserve the current Z velocity |
496 | d.Vector3 vel_now = d.BodyGetLinearVel(Body); | 489 | d.Vector3 vel_now = d.BodyGetLinearVel(Body); |
497 | m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity | 490 | m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity |
498 | } // else its 1.0, no gravity. | 491 | } // else its 1.0, no gravity. |
499 | 492 | ||
500 | // Check if hovering | 493 | // Check if hovering |
501 | if( (m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) | 494 | if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) |
502 | { | 495 | { |
503 | // We should hover, get the target height | 496 | // We should hover, get the target height |
504 | d.Vector3 pos = d.BodyGetPosition(Body); | 497 | d.Vector3 pos = d.BodyGetPosition(Body); |
505 | if((m_flags & VehicleFlag.HOVER_WATER_ONLY) == VehicleFlag.HOVER_WATER_ONLY) | 498 | if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) == VehicleFlag.HOVER_WATER_ONLY) |
506 | { | 499 | { |
507 | m_VhoverTargetHeight = _pParentScene.GetWaterLevel() + m_VhoverHeight; | 500 | m_VhoverTargetHeight = _pParentScene.GetWaterLevel() + m_VhoverHeight; |
508 | } | 501 | } |
509 | else if((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) == VehicleFlag.HOVER_TERRAIN_ONLY) | 502 | else if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) == VehicleFlag.HOVER_TERRAIN_ONLY) |
510 | { | 503 | { |
511 | m_VhoverTargetHeight = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight; | 504 | m_VhoverTargetHeight = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight; |
512 | } | 505 | } |
513 | else if((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) == VehicleFlag.HOVER_GLOBAL_HEIGHT) | 506 | else if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) == VehicleFlag.HOVER_GLOBAL_HEIGHT) |
514 | { | 507 | { |
515 | m_VhoverTargetHeight = m_VhoverHeight; | 508 | m_VhoverTargetHeight = m_VhoverHeight; |
516 | } | 509 | } |
517 | 510 | ||
518 | if((m_flags & VehicleFlag.HOVER_UP_ONLY) == VehicleFlag.HOVER_UP_ONLY) | 511 | if ((m_flags & VehicleFlag.HOVER_UP_ONLY) == VehicleFlag.HOVER_UP_ONLY) |
519 | { | 512 | { |
520 | // If body is aready heigher, use its height as target height | 513 | // If body is aready heigher, use its height as target height |
521 | if(pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z; | 514 | if (pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z; |
522 | } | 515 | } |
523 | 516 | ||
524 | // m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped | 517 | // m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped |
525 | // m_VhoverTimescale = 0f; // time to acheive height | 518 | // m_VhoverTimescale = 0f; // time to acheive height |
526 | // pTimestep is time since last frame,in secs | 519 | // pTimestep is time since last frame,in secs |
527 | float herr0 = pos.Z - m_VhoverTargetHeight; | 520 | float herr0 = pos.Z - m_VhoverTargetHeight; |
528 | // Replace Vertical speed with correction figure if significant | 521 | // Replace Vertical speed with correction figure if significant |
529 | if(Math.Abs(herr0) > 0.01f ) | 522 | if (Math.Abs(herr0) > 0.01f) |
530 | { | 523 | { |
531 | d.Mass objMass; | 524 | d.Mass objMass; |
532 | d.BodyGetMass(Body, out objMass); | 525 | d.BodyGetMass(Body, out objMass); |
533 | m_dir.Z = - ( (herr0 * pTimestep * 50.0f) / m_VhoverTimescale); | 526 | m_dir.Z = - ((herr0 * pTimestep * 50.0f) / m_VhoverTimescale); |
534 | //KF: m_VhoverEfficiency is not yet implemented | 527 | //KF: m_VhoverEfficiency is not yet implemented |
535 | } | 528 | } |
536 | else | 529 | else |
537 | { | 530 | { |
538 | m_dir.Z = 0f; | 531 | m_dir.Z = 0f; |
539 | } | 532 | } |
540 | } | 533 | } |
541 | 534 | ||
542 | // Apply velocity | 535 | // Apply velocity |
543 | d.BodySetLinearVel(Body, m_dir.X, m_dir.Y, m_dir.Z); | 536 | d.BodySetLinearVel(Body, m_dir.X, m_dir.Y, m_dir.Z); |
544 | // apply gravity force | 537 | // apply gravity force |
545 | d.BodyAddForce(Body, grav.X, grav.Y, grav.Z); | 538 | d.BodyAddForce(Body, grav.X, grav.Y, grav.Z); |
546 | 539 | ||
547 | 540 | ||
548 | // apply friction | 541 | // apply friction |
549 | Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep); | 542 | Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep); |
550 | m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount; | 543 | m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount; |
551 | } // end MoveLinear() | 544 | } // end MoveLinear() |
552 | 545 | ||
553 | private void MoveAngular(float pTimestep) | 546 | private void MoveAngular(float pTimestep) |
554 | { | 547 | { |
555 | /* | 548 | /* |
556 | private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor | 549 | private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor |
557 | private int m_angularMotorApply = 0; // application frame counter | 550 | private int m_angularMotorApply = 0; // application frame counter |
558 | private float m_angularMotorVelocity = 0; // current angular motor velocity (ramps up and down) | 551 | private float m_angularMotorVelocity = 0; // current angular motor velocity (ramps up and down) |
559 | private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate | 552 | private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate |
560 | private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate | 553 | private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate |
561 | private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate | 554 | private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate |
562 | private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body | 555 | private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body |
563 | */ | 556 | */ |
564 | 557 | ||
565 | // Get what the body is doing, this includes 'external' influences | 558 | // Get what the body is doing, this includes 'external' influences |
566 | d.Vector3 angularVelocity = d.BodyGetAngularVel(Body); | 559 | d.Vector3 angularVelocity = d.BodyGetAngularVel(Body); |
567 | // Vector3 angularVelocity = Vector3.Zero; | 560 | // Vector3 angularVelocity = Vector3.Zero; |
568 | 561 | ||
569 | if (m_angularMotorApply > 0) | 562 | if (m_angularMotorApply > 0) |
570 | { | 563 | { |
571 | // ramp up to new value | 564 | // ramp up to new value |
572 | // current velocity += error / ( time to get there / step interval ) | 565 | // current velocity += error / (time to get there / step interval) |
573 | // requested speed - last motor speed | 566 | // requested speed - last motor speed |
574 | m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep); | 567 | m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep); |
575 | m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep); | 568 | m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep); |
576 | m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep); | 569 | m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep); |
577 | 570 | ||
578 | m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected | 571 | m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected |
579 | // velocity may still be acheived. | 572 | // velocity may still be acheived. |
580 | } | 573 | } |
581 | else | 574 | else |
582 | { | 575 | { |
583 | // no motor recently applied, keep the body velocity | 576 | // no motor recently applied, keep the body velocity |
584 | /* m_angularMotorVelocity.X = angularVelocity.X; | 577 | /* m_angularMotorVelocity.X = angularVelocity.X; |
585 | m_angularMotorVelocity.Y = angularVelocity.Y; | 578 | m_angularMotorVelocity.Y = angularVelocity.Y; |
586 | m_angularMotorVelocity.Z = angularVelocity.Z; */ | 579 | m_angularMotorVelocity.Z = angularVelocity.Z; */ |
587 | 580 | ||
588 | // and decay the velocity | 581 | // and decay the velocity |
589 | m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep); | 582 | m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep); |
590 | } // end motor section | 583 | } // end motor section |
591 | |||
592 | 584 | ||
593 | // Vertical attractor section | 585 | // Vertical attractor section |
594 | Vector3 vertattr = Vector3.Zero; | 586 | Vector3 vertattr = Vector3.Zero; |
595 | 587 | ||
596 | if(m_verticalAttractionTimescale < 300) | 588 | if (m_verticalAttractionTimescale < 300) |
597 | { | ||
598 | float VAservo = 0.2f / (m_verticalAttractionTimescale * pTimestep); | ||
599 | // get present body rotation | ||
600 | d.Quaternion rot = d.BodyGetQuaternion(Body); | ||
601 | Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); | ||
602 | // make a vector pointing up | ||
603 | Vector3 verterr = Vector3.Zero; | ||
604 | verterr.Z = 1.0f; | ||
605 | // rotate it to Body Angle | ||
606 | verterr = verterr * rotq; | ||
607 | // verterr.X and .Y are the World error ammounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1. | ||
608 | // As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go | ||
609 | // negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body. | ||
610 | if (verterr.Z < 0.0f) | ||
611 | { | ||
612 | verterr.X = 2.0f - verterr.X; | ||
613 | verterr.Y = 2.0f - verterr.Y; | ||
614 | } | ||
615 | // Error is 0 (no error) to +/- 2 (max error) | ||
616 | // scale it by VAservo | ||
617 | verterr = verterr * VAservo; | ||
618 | //if(frcount == 0) Console.WriteLine("VAerr=" + verterr); | ||
619 | |||
620 | // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so | ||
621 | // Change Body angular velocity X based on Y, and Y based on X. Z is not changed. | ||
622 | vertattr.X = verterr.Y; | ||
623 | vertattr.Y = - verterr.X; | ||
624 | vertattr.Z = 0f; | ||
625 | |||
626 | // scaling appears better usingsquare-law | ||
627 | float bounce = 1.0f - (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); | ||
628 | vertattr.X += bounce * angularVelocity.X; | ||
629 | vertattr.Y += bounce * angularVelocity.Y; | ||
630 | |||
631 | } // else vertical attractor is off | ||
632 | |||
633 | // m_lastVertAttractor = vertattr; | ||
634 | |||
635 | // Bank section tba | ||
636 | // Deflection section tba | ||
637 | |||
638 | // Sum velocities | ||
639 | m_lastAngularVelocity = m_angularMotorVelocity + vertattr; // + bank + deflection | ||
640 | |||
641 | if (!m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) | ||
642 | { | 589 | { |
643 | if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); | 590 | float VAservo = 0.2f / (m_verticalAttractionTimescale * pTimestep); |
644 | } | 591 | // get present body rotation |
645 | else | 592 | d.Quaternion rot = d.BodyGetQuaternion(Body); |
646 | { | 593 | Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); |
647 | m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. | 594 | // make a vector pointing up |
648 | } | 595 | Vector3 verterr = Vector3.Zero; |
649 | 596 | verterr.Z = 1.0f; | |
650 | // apply friction | 597 | // rotate it to Body Angle |
598 | verterr = verterr * rotq; | ||
599 | // verterr.X and .Y are the World error ammounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1. | ||
600 | // As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go | ||
601 | // negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body. | ||
602 | if (verterr.Z < 0.0f) | ||
603 | { | ||
604 | verterr.X = 2.0f - verterr.X; | ||
605 | verterr.Y = 2.0f - verterr.Y; | ||
606 | } | ||
607 | // Error is 0 (no error) to +/- 2 (max error) | ||
608 | // scale it by VAservo | ||
609 | verterr = verterr * VAservo; | ||
610 | //if (frcount == 0) Console.WriteLine("VAerr=" + verterr); | ||
611 | |||
612 | // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so | ||
613 | // Change Body angular velocity X based on Y, and Y based on X. Z is not changed. | ||
614 | vertattr.X = verterr.Y; | ||
615 | vertattr.Y = - verterr.X; | ||
616 | vertattr.Z = 0f; | ||
617 | |||
618 | // scaling appears better usingsquare-law | ||
619 | float bounce = 1.0f - (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); | ||
620 | vertattr.X += bounce * angularVelocity.X; | ||
621 | vertattr.Y += bounce * angularVelocity.Y; | ||
622 | |||
623 | } // else vertical attractor is off | ||
624 | |||
625 | // m_lastVertAttractor = vertattr; | ||
626 | |||
627 | // Bank section tba | ||
628 | // Deflection section tba | ||
629 | |||
630 | // Sum velocities | ||
631 | m_lastAngularVelocity = m_angularMotorVelocity + vertattr; // + bank + deflection | ||
632 | |||
633 | if (!m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) | ||
634 | { | ||
635 | if (!d.BodyIsEnabled (Body)) d.BodyEnable (Body); | ||
636 | } | ||
637 | else | ||
638 | { | ||
639 | m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. | ||
640 | } | ||
641 | |||
642 | // apply friction | ||
651 | Vector3 decayamount = Vector3.One / (m_angularFrictionTimescale / pTimestep); | 643 | Vector3 decayamount = Vector3.One / (m_angularFrictionTimescale / pTimestep); |
652 | m_lastAngularVelocity -= m_lastAngularVelocity * decayamount; | 644 | m_lastAngularVelocity -= m_lastAngularVelocity * decayamount; |
653 | 645 | ||
654 | // Apply to the body | 646 | // Apply to the body |
655 | d.BodySetAngularVel (Body, m_lastAngularVelocity.X, m_lastAngularVelocity.Y, m_lastAngularVelocity.Z); | 647 | d.BodySetAngularVel (Body, m_lastAngularVelocity.X, m_lastAngularVelocity.Y, m_lastAngularVelocity.Z); |
656 | 648 | ||
657 | } //end MoveAngular | 649 | } //end MoveAngular |
658 | } | 650 | } |
659 | } | 651 | } |