44 using System.Collections.Generic;
45 using System.Reflection;
46 using System.Runtime.InteropServices;
50 using OpenSim.Framework;
51 using OpenSim.Region.PhysicsModules.SharedBase;
53 namespace OpenSim.
Region.PhysicsModule.ubOde
59 get {
return m_type; }
69 private Quaternion m_referenceFrame = Quaternion.Identity;
70 private Quaternion m_RollreferenceFrame = Quaternion.Identity;
72 private Vehicle m_type = Vehicle.TYPE_NONE;
82 private Vector3 m_BlockingEndPoint = Vector3.Zero;
85 private Vector3 m_linearMotorDirection = Vector3.Zero;
86 private Vector3 m_linearFrictionTimescale =
new Vector3(1000, 1000, 1000);
87 private float m_linearMotorDecayTimescale = 120;
88 private float m_linearMotorTimescale = 1000;
89 private Vector3 m_linearMotorOffset = Vector3.Zero;
92 private Vector3 m_angularMotorDirection = Vector3.Zero;
93 private float m_angularMotorTimescale = 1000;
94 private float m_angularMotorDecayTimescale = 120;
95 private Vector3 m_angularFrictionTimescale =
new Vector3(1000, 1000, 1000);
98 private float m_angularDeflectionEfficiency = 0;
99 private float m_angularDeflectionTimescale = 1000;
100 private float m_linearDeflectionEfficiency = 0;
101 private float m_linearDeflectionTimescale = 1000;
104 private float m_bankingEfficiency = 0;
105 private float m_bankingMix = 0;
106 private float m_bankingTimescale = 1000;
109 private float m_VhoverHeight = 0f;
110 private float m_VhoverEfficiency = 0f;
111 private float m_VhoverTimescale = 1000f;
112 private float m_VehicleBuoyancy = 0f;
118 private float m_verticalAttractionEfficiency = 1.0f;
119 private float m_verticalAttractionTimescale = 1000f;
123 private float m_lmEfect = 0f;
124 private float m_lmDecay = 0f;
126 private float m_amEfect = 0;
127 private float m_amDecay = 0f;
129 private float m_ffactor = 1.0f;
131 private float m_timestep = 0.02f;
132 private float m_invtimestep = 50;
142 public float FrictionFactor
162 _pParentScene = rootPrim._parent_scene;
163 m_timestep = _pParentScene.ODE_STEPSIZE;
164 m_invtimestep = 1.0f / m_timestep;
165 m_gravmod = rootPrim.GravModifier;
171 m_flags = vd.m_flags;
175 m_linearMotorDirection = vd.m_linearMotorDirection;
177 m_linearFrictionTimescale = vd.m_linearFrictionTimescale;
178 if (m_linearFrictionTimescale.X < m_timestep) m_linearFrictionTimescale.X = m_timestep;
179 if (m_linearFrictionTimescale.Y < m_timestep) m_linearFrictionTimescale.Y = m_timestep;
180 if (m_linearFrictionTimescale.Z < m_timestep) m_linearFrictionTimescale.Z = m_timestep;
182 m_linearMotorDecayTimescale = vd.m_linearMotorDecayTimescale;
183 if (m_linearMotorDecayTimescale < m_timestep) m_linearMotorDecayTimescale = m_timestep;
184 m_linearMotorDecayTimescale += 0.2f;
185 m_linearMotorDecayTimescale *= m_invtimestep;
187 m_linearMotorTimescale = vd.m_linearMotorTimescale;
188 if (m_linearMotorTimescale < m_timestep) m_linearMotorTimescale = m_timestep;
190 m_linearMotorOffset = vd.m_linearMotorOffset;
193 m_angularMotorDirection = vd.m_angularMotorDirection;
194 m_angularMotorTimescale = vd.m_angularMotorTimescale;
195 if (m_angularMotorTimescale < m_timestep) m_angularMotorTimescale = m_timestep;
197 m_angularMotorDecayTimescale = vd.m_angularMotorDecayTimescale;
198 if (m_angularMotorDecayTimescale < m_timestep) m_angularMotorDecayTimescale = m_timestep;
199 m_angularMotorDecayTimescale *= m_invtimestep;
201 m_angularFrictionTimescale = vd.m_angularFrictionTimescale;
202 if (m_angularFrictionTimescale.X < m_timestep) m_angularFrictionTimescale.X = m_timestep;
203 if (m_angularFrictionTimescale.Y < m_timestep) m_angularFrictionTimescale.Y = m_timestep;
204 if (m_angularFrictionTimescale.Z < m_timestep) m_angularFrictionTimescale.Z = m_timestep;
207 m_angularDeflectionEfficiency = vd.m_angularDeflectionEfficiency;
208 m_angularDeflectionTimescale = vd.m_angularDeflectionTimescale;
209 if (m_angularDeflectionTimescale < m_timestep) m_angularDeflectionTimescale = m_timestep;
211 m_linearDeflectionEfficiency = vd.m_linearDeflectionEfficiency;
212 m_linearDeflectionTimescale = vd.m_linearDeflectionTimescale;
213 if (m_linearDeflectionTimescale < m_timestep) m_linearDeflectionTimescale = m_timestep;
216 m_bankingEfficiency = vd.m_bankingEfficiency;
217 m_bankingMix = vd.m_bankingMix;
218 m_bankingTimescale = vd.m_bankingTimescale;
219 if (m_bankingTimescale < m_timestep) m_bankingTimescale = m_timestep;
222 m_VhoverHeight = vd.m_VhoverHeight;
223 m_VhoverEfficiency = vd.m_VhoverEfficiency;
224 m_VhoverTimescale = vd.m_VhoverTimescale;
225 if (m_VhoverTimescale < m_timestep) m_VhoverTimescale = m_timestep;
227 m_VehicleBuoyancy = vd.m_VehicleBuoyancy;
230 m_verticalAttractionEfficiency = vd.m_verticalAttractionEfficiency;
231 m_verticalAttractionTimescale = vd.m_verticalAttractionTimescale;
232 if (m_verticalAttractionTimescale < m_timestep) m_verticalAttractionTimescale = m_timestep;
235 m_referenceFrame = vd.m_referenceFrame;
238 m_lmDecay = (1.0f - 1.0f / m_linearMotorDecayTimescale);
243 internal void ProcessFloatVehicleParam(
Vehicle pParam,
float pValue)
249 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
250 if (pValue < 0f) pValue = 0f;
251 if (pValue > 1f) pValue = 1f;
252 m_angularDeflectionEfficiency = pValue;
254 case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
255 if (pValue < m_timestep) pValue = m_timestep;
256 m_angularDeflectionTimescale = pValue;
258 case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
259 if (pValue < m_timestep) pValue = m_timestep;
260 else if (pValue > 120) pValue = 120;
261 m_angularMotorDecayTimescale = pValue * m_invtimestep;
262 m_amDecay = 1.0f - 1.0f / m_angularMotorDecayTimescale;
264 case Vehicle.ANGULAR_MOTOR_TIMESCALE:
265 if (pValue < m_timestep) pValue = m_timestep;
266 m_angularMotorTimescale = pValue;
268 case Vehicle.BANKING_EFFICIENCY:
269 if (pValue < -1f) pValue = -1f;
270 if (pValue > 1f) pValue = 1f;
271 m_bankingEfficiency = pValue;
273 case Vehicle.BANKING_MIX:
274 if (pValue < 0f) pValue = 0f;
275 if (pValue > 1f) pValue = 1f;
276 m_bankingMix = pValue;
278 case Vehicle.BANKING_TIMESCALE:
279 if (pValue < m_timestep) pValue = m_timestep;
280 m_bankingTimescale = pValue;
282 case Vehicle.BUOYANCY:
283 if (pValue < -1f) pValue = -1f;
284 if (pValue > 1f) pValue = 1f;
285 m_VehicleBuoyancy = pValue;
287 case Vehicle.HOVER_EFFICIENCY:
288 if (pValue < 0f) pValue = 0f;
289 if (pValue > 1f) pValue = 1f;
290 m_VhoverEfficiency = pValue;
292 case Vehicle.HOVER_HEIGHT:
293 m_VhoverHeight = pValue;
295 case Vehicle.HOVER_TIMESCALE:
296 if (pValue < m_timestep) pValue = m_timestep;
297 m_VhoverTimescale = pValue;
299 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
300 if (pValue < 0f) pValue = 0f;
301 if (pValue > 1f) pValue = 1f;
302 m_linearDeflectionEfficiency = pValue;
304 case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
305 if (pValue < m_timestep) pValue = m_timestep;
306 m_linearDeflectionTimescale = pValue;
308 case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
309 if (pValue < m_timestep) pValue = m_timestep;
310 else if (pValue > 120) pValue = 120;
311 m_linearMotorDecayTimescale = (0.2f +pValue) * m_invtimestep;
312 m_lmDecay = (1.0f - 1.0f / m_linearMotorDecayTimescale);
314 case Vehicle.LINEAR_MOTOR_TIMESCALE:
315 if (pValue < m_timestep) pValue = m_timestep;
316 m_linearMotorTimescale = pValue;
318 case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
319 if (pValue < 0f) pValue = 0f;
320 if (pValue > 1f) pValue = 1f;
321 m_verticalAttractionEfficiency = pValue;
323 case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
324 if (pValue < m_timestep) pValue = m_timestep;
325 m_verticalAttractionTimescale = pValue;
330 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
331 if (pValue < m_timestep) pValue = m_timestep;
332 m_angularFrictionTimescale =
new Vector3(pValue, pValue, pValue);
334 case Vehicle.ANGULAR_MOTOR_DIRECTION:
335 m_angularMotorDirection =
new Vector3(pValue, pValue, pValue);
336 len = m_angularMotorDirection.Length();
338 m_angularMotorDirection *= (12.566f / len);
341 m_amDecay = 1.0f - 1.0f / m_angularMotorDecayTimescale;
343 if (rootPrim.Body != IntPtr.Zero && !d.BodyIsEnabled(rootPrim.Body)
344 && !rootPrim.m_isSelected && !rootPrim.m_disabled)
345 d.BodyEnable(rootPrim.Body);
347 case Vehicle.LINEAR_FRICTION_TIMESCALE:
348 if (pValue < m_timestep) pValue = m_timestep;
349 m_linearFrictionTimescale =
new Vector3(pValue, pValue, pValue);
351 case Vehicle.LINEAR_MOTOR_DIRECTION:
352 m_linearMotorDirection =
new Vector3(pValue, pValue, pValue);
353 len = m_linearMotorDirection.Length();
355 m_linearMotorDirection *= (100.0f / len);
357 m_lmDecay = 1.0f - 1.0f / m_linearMotorDecayTimescale;
361 if (rootPrim.Body != IntPtr.Zero && !d.BodyIsEnabled(rootPrim.Body)
362 && !rootPrim.m_isSelected && !rootPrim.m_disabled)
363 d.BodyEnable(rootPrim.Body);
365 case Vehicle.LINEAR_MOTOR_OFFSET:
366 m_linearMotorOffset =
new Vector3(pValue, pValue, pValue);
367 len = m_linearMotorOffset.Length();
369 m_linearMotorOffset *= (100.0f / len);
374 internal void ProcessVectorVehicleParam(
Vehicle pParam, Vector3 pValue)
380 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
381 if (pValue.X < m_timestep) pValue.X = m_timestep;
382 if (pValue.Y < m_timestep) pValue.Y = m_timestep;
383 if (pValue.Z < m_timestep) pValue.Z = m_timestep;
385 m_angularFrictionTimescale =
new Vector3(pValue.X, pValue.Y, pValue.Z);
387 case Vehicle.ANGULAR_MOTOR_DIRECTION:
388 m_angularMotorDirection =
new Vector3(pValue.X, pValue.Y, pValue.Z);
390 len = m_angularMotorDirection.Length();
392 m_angularMotorDirection *= (12.566f / len);
395 m_amDecay = 1.0f - 1.0f / m_angularMotorDecayTimescale;
397 if (rootPrim.Body != IntPtr.Zero && !d.BodyIsEnabled(rootPrim.Body)
398 && !rootPrim.m_isSelected && !rootPrim.m_disabled)
399 d.BodyEnable(rootPrim.Body);
401 case Vehicle.LINEAR_FRICTION_TIMESCALE:
402 if (pValue.X < m_timestep) pValue.X = m_timestep;
403 if (pValue.Y < m_timestep) pValue.Y = m_timestep;
404 if (pValue.Z < m_timestep) pValue.Z = m_timestep;
405 m_linearFrictionTimescale =
new Vector3(pValue.X, pValue.Y, pValue.Z);
407 case Vehicle.LINEAR_MOTOR_DIRECTION:
408 m_linearMotorDirection =
new Vector3(pValue.X, pValue.Y, pValue.Z);
409 len = m_linearMotorDirection.Length();
411 m_linearMotorDirection *= (100.0f / len);
414 m_lmDecay = 1.0f - 1.0f / m_linearMotorDecayTimescale;
417 if (rootPrim.Body != IntPtr.Zero && !d.BodyIsEnabled(rootPrim.Body)
418 && !rootPrim.m_isSelected && !rootPrim.m_disabled)
419 d.BodyEnable(rootPrim.Body);
421 case Vehicle.LINEAR_MOTOR_OFFSET:
422 m_linearMotorOffset =
new Vector3(pValue.X, pValue.Y, pValue.Z);
423 len = m_linearMotorOffset.Length();
425 m_linearMotorOffset *= (100.0f / len);
427 case Vehicle.BLOCK_EXIT:
428 m_BlockingEndPoint =
new Vector3(pValue.X, pValue.Y, pValue.Z);
433 internal void ProcessRotationVehicleParam(
Vehicle pParam, Quaternion pValue)
437 case Vehicle.REFERENCE_FRAME:
439 m_referenceFrame = pValue;
441 case Vehicle.ROLL_FRAME:
442 m_RollreferenceFrame = pValue;
447 internal void ProcessVehicleFlags(
int pParam,
bool remove)
459 internal void ProcessTypeChange(
Vehicle pType)
466 m_linearMotorDirection = Vector3.Zero;
467 m_angularMotorDirection = Vector3.Zero;
469 m_BlockingEndPoint = Vector3.Zero;
470 m_RollreferenceFrame = Quaternion.Identity;
471 m_linearMotorOffset = Vector3.Zero;
473 m_referenceFrame = Quaternion.Identity;
479 case Vehicle.TYPE_NONE:
480 m_linearFrictionTimescale =
new Vector3(1000, 1000, 1000);
481 m_angularFrictionTimescale =
new Vector3(1000, 1000, 1000);
482 m_linearMotorTimescale = 1000;
483 m_linearMotorDecayTimescale = 120 * m_invtimestep;
484 m_angularMotorTimescale = 1000;
485 m_angularMotorDecayTimescale = 1000 * m_invtimestep;
487 m_VhoverEfficiency = 1;
488 m_VhoverTimescale = 1000;
489 m_VehicleBuoyancy = 0;
490 m_linearDeflectionEfficiency = 0;
491 m_linearDeflectionTimescale = 1000;
492 m_angularDeflectionEfficiency = 0;
493 m_angularDeflectionTimescale = 1000;
494 m_bankingEfficiency = 0;
496 m_bankingTimescale = 1000;
497 m_verticalAttractionEfficiency = 0;
498 m_verticalAttractionTimescale = 1000;
503 case Vehicle.TYPE_SLED:
504 m_linearFrictionTimescale =
new Vector3(30, 1, 1000);
505 m_angularFrictionTimescale =
new Vector3(1000, 1000, 1000);
506 m_linearMotorTimescale = 1000;
507 m_linearMotorDecayTimescale = 120 * m_invtimestep;
508 m_angularMotorTimescale = 1000;
509 m_angularMotorDecayTimescale = 120 * m_invtimestep;
511 m_VhoverEfficiency = 1;
512 m_VhoverTimescale = 10;
513 m_VehicleBuoyancy = 0;
514 m_linearDeflectionEfficiency = 1;
515 m_linearDeflectionTimescale = 1;
516 m_angularDeflectionEfficiency = 0;
517 m_angularDeflectionTimescale = 10;
518 m_verticalAttractionEfficiency = 1;
519 m_verticalAttractionTimescale = 1000;
520 m_bankingEfficiency = 0;
522 m_bankingTimescale = 10;
524 ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
525 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
526 m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
527 VehicleFlag.LIMIT_ROLL_ONLY |
528 VehicleFlag.LIMIT_MOTOR_UP);
531 case Vehicle.TYPE_CAR:
532 m_linearFrictionTimescale =
new Vector3(100, 2, 1000);
533 m_angularFrictionTimescale =
new Vector3(1000, 1000, 1000);
534 m_linearMotorTimescale = 1;
535 m_linearMotorDecayTimescale = 60 * m_invtimestep;
536 m_angularMotorTimescale = 1;
537 m_angularMotorDecayTimescale = 0.8f * m_invtimestep;
539 m_VhoverEfficiency = 0;
540 m_VhoverTimescale = 1000;
541 m_VehicleBuoyancy = 0;
542 m_linearDeflectionEfficiency = 1;
543 m_linearDeflectionTimescale = 2;
544 m_angularDeflectionEfficiency = 0;
545 m_angularDeflectionTimescale = 10;
546 m_verticalAttractionEfficiency = 1f;
547 m_verticalAttractionTimescale = 10f;
548 m_bankingEfficiency = -0.2f;
550 m_bankingTimescale = 1;
551 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
552 VehicleFlag.HOVER_TERRAIN_ONLY |
553 VehicleFlag.HOVER_GLOBAL_HEIGHT);
554 m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
555 VehicleFlag.LIMIT_ROLL_ONLY |
556 VehicleFlag.LIMIT_MOTOR_UP |
557 VehicleFlag.HOVER_UP_ONLY);
559 case Vehicle.TYPE_BOAT:
560 m_linearFrictionTimescale =
new Vector3(10, 3, 2);
561 m_angularFrictionTimescale =
new Vector3(10, 10, 10);
562 m_linearMotorTimescale = 5;
563 m_linearMotorDecayTimescale = 60 * m_invtimestep;
564 m_angularMotorTimescale = 4;
565 m_angularMotorDecayTimescale = 4 * m_invtimestep;
567 m_VhoverEfficiency = 0.5f;
568 m_VhoverTimescale = 2;
569 m_VehicleBuoyancy = 1;
570 m_linearDeflectionEfficiency = 0.5f;
571 m_linearDeflectionTimescale = 3;
572 m_angularDeflectionEfficiency = 0.5f;
573 m_angularDeflectionTimescale = 5;
574 m_verticalAttractionEfficiency = 0.5f;
575 m_verticalAttractionTimescale = 5f;
576 m_bankingEfficiency = -0.3f;
578 m_bankingTimescale = 1;
579 m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY |
580 VehicleFlag.HOVER_GLOBAL_HEIGHT |
581 VehicleFlag.HOVER_UP_ONLY);
583 m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
584 VehicleFlag.LIMIT_MOTOR_UP |
585 VehicleFlag.HOVER_UP_ONLY |
586 VehicleFlag.HOVER_WATER_ONLY);
589 case Vehicle.TYPE_AIRPLANE:
590 m_linearFrictionTimescale =
new Vector3(200, 10, 5);
591 m_angularFrictionTimescale =
new Vector3(20, 20, 20);
592 m_linearMotorTimescale = 2;
593 m_linearMotorDecayTimescale = 60 * m_invtimestep;
594 m_angularMotorTimescale = 4;
595 m_angularMotorDecayTimescale = 8 * m_invtimestep;
597 m_VhoverEfficiency = 0.5f;
598 m_VhoverTimescale = 1000;
599 m_VehicleBuoyancy = 0;
600 m_linearDeflectionEfficiency = 0.5f;
601 m_linearDeflectionTimescale = 0.5f;
602 m_angularDeflectionEfficiency = 1;
603 m_angularDeflectionTimescale = 2;
604 m_verticalAttractionEfficiency = 0.9f;
605 m_verticalAttractionTimescale = 2f;
606 m_bankingEfficiency = 1;
608 m_bankingTimescale = 2;
609 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
610 VehicleFlag.HOVER_TERRAIN_ONLY |
611 VehicleFlag.HOVER_GLOBAL_HEIGHT |
612 VehicleFlag.HOVER_UP_ONLY |
613 VehicleFlag.NO_DEFLECTION_UP |
614 VehicleFlag.LIMIT_MOTOR_UP);
615 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
618 case Vehicle.TYPE_BALLOON:
619 m_linearFrictionTimescale =
new Vector3(5, 5, 5);
620 m_angularFrictionTimescale =
new Vector3(10, 10, 10);
621 m_linearMotorTimescale = 5;
622 m_linearMotorDecayTimescale = 60 * m_invtimestep;
623 m_angularMotorTimescale = 6;
624 m_angularMotorDecayTimescale = 10 * m_invtimestep;
626 m_VhoverEfficiency = 0.8f;
627 m_VhoverTimescale = 10;
628 m_VehicleBuoyancy = 1;
629 m_linearDeflectionEfficiency = 0;
630 m_linearDeflectionTimescale = 5 * m_invtimestep;
631 m_angularDeflectionEfficiency = 0;
632 m_angularDeflectionTimescale = 5;
633 m_verticalAttractionEfficiency = 1f;
634 m_verticalAttractionTimescale = 1000f;
635 m_bankingEfficiency = 0;
637 m_bankingTimescale = 5;
638 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
639 VehicleFlag.HOVER_TERRAIN_ONLY |
640 VehicleFlag.HOVER_UP_ONLY |
641 VehicleFlag.NO_DEFLECTION_UP |
642 VehicleFlag.LIMIT_MOTOR_UP |
643 VehicleFlag.LIMIT_ROLL_ONLY |
644 VehicleFlag.HOVER_GLOBAL_HEIGHT);
652 m_lmDecay = (1.0f - 1.0f / m_linearMotorDecayTimescale);
653 m_amDecay = 1.0f - 1.0f / m_angularMotorDecayTimescale;
666 public static Vector3
Xrot(Quaternion rot)
670 vec.X = 2 * (rot.X * rot.X + rot.W * rot.W) - 1;
671 vec.Y = 2 * (rot.X * rot.Y + rot.Z * rot.W);
672 vec.Z = 2 * (rot.X * rot.Z - rot.Y * rot.W);
676 public static Vector3
Zrot(Quaternion rot)
680 vec.X = 2 * (rot.X * rot.Z + rot.Y * rot.W);
681 vec.Y = 2 * (rot.Y * rot.Z - rot.X * rot.W);
682 vec.Z = 2 * (rot.Z * rot.Z + rot.W * rot.W) - 1;
687 private const float pi = (float)Math.PI;
688 private const float halfpi = 0.5f * (
float)Math.PI;
689 private const float twopi = 2.0f * pi;
701 float zX = rot.X * rot.Z + rot.Y * rot.W;
707 vec.Z = (float)(-2d * Math.Atan(rot.X / rot.W));
709 else if (zX > 0.49999f)
713 vec.Z = (float)(2d * Math.Atan(rot.X / rot.W));
717 vec.Y = (float)Math.Asin(2 * zX);
719 float sqw = rot.W * rot.W;
721 float minuszY = rot.X * rot.W - rot.Y * rot.Z;
722 float zZ = rot.Z * rot.Z + sqw - 0.5f;
724 vec.X = (float)Math.Atan2(minuszY, zZ);
726 float yX = rot.Z * rot.W - rot.X * rot.Y;
727 float yY = rot.X * rot.X + sqw - 0.5f;
728 vec.Z = (float)Math.Atan2(yX, yY);
733 public static void GetRollPitch(Quaternion rot, out
float roll, out
float pitch)
738 float zX = rot.X * rot.Z + rot.Y * rot.W;
745 else if (zX > 0.49999f)
752 pitch = (float)Math.Asin(2 * zX);
754 float minuszY = rot.X * rot.W - rot.Y * rot.Z;
755 float zZ = rot.Z * rot.Z + rot.W * rot.W - 0.5f;
757 roll = (float)Math.Atan2(minuszY, zZ);
764 IntPtr Body = rootPrim.Body;
767 d.BodyGetMass(Body, out dmass);
770 Quaternion objrotq =
new Quaternion(rot.X, rot.Y, rot.Z, rot.W);
771 Quaternion rotq = objrotq;
772 rotq *= m_referenceFrame;
773 Quaternion irotq = Quaternion.Inverse(rotq);
779 Vector3 force = Vector3.Zero;
780 Vector3 torque = Vector3.Zero;
783 dvtmp = d.BodyGetLinearVel(Body);
787 Vector3 curLocalVel = curVel * irotq;
789 dvtmp = d.BodyGetAngularVel(Body);
790 curAngVel.X = dvtmp.X;
791 curAngVel.Y = dvtmp.Y;
792 curAngVel.Z = dvtmp.Z;
793 Vector3 curLocalAngVel = curAngVel * irotq;
798 if (m_lmEfect > 0.01 && m_linearMotorTimescale < 1000)
800 tmpV = m_linearMotorDirection - curLocalVel;
801 tmpV *= m_lmEfect / m_linearMotorTimescale;
807 if (m_linearMotorOffset.X != 0 || m_linearMotorOffset.Y != 0 || m_linearMotorOffset.Z != 0)
811 d.BodyAddForceAtRelPos(Body, tmpV.X, tmpV.Y, tmpV.Z, m_linearMotorOffset.X, m_linearMotorOffset.Y, m_linearMotorOffset.Z);
820 m_lmEfect *= m_lmDecay;
831 if (m_VhoverTimescale < 300 && rootPrim.prim_geom != IntPtr.Zero)
834 d.Vector3 pos = d.GeomGetPosition(rootPrim.prim_geom);
837 float t = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y);
841 perr = m_VhoverHeight - pos.Z;
843 if ((m_flags &
VehicleFlag.HOVER_GLOBAL_HEIGHT) == 0)
847 perr += _pParentScene.GetWaterLevel();
849 else if ((m_flags &
VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
855 float w = _pParentScene.GetWaterLevel();
862 else if (t > m_VhoverHeight)
865 if ((m_flags &
VehicleFlag.HOVER_UP_ONLY) == 0 || perr > -0.1)
867 ldampZ = m_VhoverEfficiency * m_invtimestep;
869 perr *= (1.0f + ldampZ) / m_VhoverTimescale;
875 force.Z += _pParentScene.gravityz * m_gravmod * (1f - m_VehicleBuoyancy);
878 force.Z += _pParentScene.gravityz;
883 force.Z += _pParentScene.gravityz * m_gravmod * (1f - m_VehicleBuoyancy);
887 if (m_linearDeflectionEfficiency > 0)
889 float len = curVel.Length();
898 len = atAxis.LengthSquared();
901 float lens = tmpV.LengthSquared();
903 if (len > 0.01 || lens > 0.01)
908 tmpV *= (m_linearDeflectionEfficiency / m_linearDeflectionTimescale);
918 if (curLocalVel.X != 0 || curLocalVel.Y != 0 || curLocalVel.Z != 0)
920 tmpV.X = -curLocalVel.X / m_linearFrictionTimescale.X;
921 tmpV.Y = -curLocalVel.Y / m_linearFrictionTimescale.Y;
922 tmpV.Z = -curLocalVel.Z / m_linearFrictionTimescale.Z;
925 if(ldampZ != 0 && Math.Abs(ldampZ) > Math.Abs(tmpV.Z))
933 if (m_verticalAttractionTimescale < 300)
940 float ftmp = m_invtimestep / m_verticalAttractionTimescale / m_verticalAttractionTimescale;
943 ftmp2 = 0.5f * m_verticalAttractionEfficiency * m_invtimestep;
946 m_ampwr = 1.0f - 0.8f * m_verticalAttractionEfficiency;
948 GetRollPitch(irotq, out roll, out pitch);
952 else if (roll < -halfpi)
955 float effroll = pitch / halfpi;
957 effroll = 1 - effroll;
961 torque.X += effroll * ftmp;
965 float effpitch = roll / halfpi;
966 effpitch *= effpitch;
967 effpitch = 1 - effpitch;
970 torque.Y += effpitch * ftmp;
973 if (m_bankingEfficiency != 0 && Math.Abs(effroll) > 0.01)
976 float broll = effroll;
983 broll *= m_bankingEfficiency;
984 if (m_bankingMix != 0)
986 float vfact = Math.Abs(curLocalVel.X) / 10.0f;
987 if (vfact > 1.0f) vfact = 1.0f;
989 if (curLocalVel.X >= 0)
990 broll *= (1 + (vfact - 1) * m_bankingMix);
992 broll *= -(1 + (vfact - 1) * m_bankingMix);
996 broll = broll / m_bankingTimescale;
1006 m_amdampZ = Math.Abs(m_bankingEfficiency) / m_bankingTimescale;
1007 m_amdampY = m_amdampZ;
1012 m_amdampZ = 1 / m_angularFrictionTimescale.Z;
1013 m_amdampY = m_amdampX;
1019 m_amdampX = 1 / m_angularFrictionTimescale.X;
1020 m_amdampY = 1 / m_angularFrictionTimescale.Y;
1021 m_amdampZ = 1 / m_angularFrictionTimescale.Z;
1025 if (m_amEfect > 0.01 && m_angularMotorTimescale < 1000)
1027 tmpV = m_angularMotorDirection - curLocalAngVel;
1028 tmpV *= m_amEfect / m_angularMotorTimescale;
1029 torque.X += tmpV.X * m_ampwr;
1030 torque.Y += tmpV.Y * m_ampwr;
1033 m_amEfect *= m_amDecay;
1039 if (m_angularDeflectionEfficiency > 0)
1043 if (curLocalVel.X > 0.01f)
1045 else if (curLocalVel.X < -0.01f)
1047 dirv = -curLocalVel;
1052 dirv.Y = curLocalVel.Y;
1053 dirv.Z = curLocalVel.Z;
1056 float ftmp = m_angularDeflectionEfficiency / m_angularDeflectionTimescale;
1058 if (Math.Abs(dirv.Z) > 0.01)
1060 torque.Y += - (float)Math.Atan2(dirv.Z, dirv.X) * ftmp;
1063 if (Math.Abs(dirv.Y) > 0.01)
1065 torque.Z += (float)Math.Atan2(dirv.Y, dirv.X) * ftmp;
1070 if (curLocalAngVel.X != 0 || curLocalAngVel.Y != 0 || curLocalAngVel.Z != 0)
1072 torque.X -= curLocalAngVel.X * m_amdampX;
1073 torque.Y -= curLocalAngVel.Y * m_amdampY;
1074 torque.Z -= curLocalAngVel.Z * m_amdampZ;
1078 if (force.X != 0 || force.Y != 0 || force.Z != 0)
1080 force *= dmass.mass;
1081 d.BodyAddForce(Body, force.X, force.Y, force.Z);
1084 if (torque.X != 0 || torque.Y != 0 || torque.Z != 0)
1086 torque *= m_referenceFrame;
1087 dtorque.X = torque.X ;
1088 dtorque.Y = torque.Y;
1089 dtorque.Z = torque.Z;
1091 d.MultiplyM3V3(out dvtmp, ref dmass.I, ref dtorque);
1092 d.BodyAddRelTorque(Body, dvtmp.X, dvtmp.Y, dvtmp.Z);
ODEDynamics(OdePrim rootp)
static Vector3 Xrot(Quaternion rot)
static Vector3 Zrot(Quaternion rot)
static Vector3 ubRot2Euler(Quaternion rot)
void DoSetVehicle(VehicleData vd)
static void GetRollPitch(Quaternion rot, out float roll, out float pitch)