diff options
Diffstat (limited to 'OpenSim/Region/Physics/OdePlugin/ODECharacter.cs')
-rw-r--r-- | OpenSim/Region/Physics/OdePlugin/ODECharacter.cs | 341 |
1 files changed, 164 insertions, 177 deletions
diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs index c37d588..489a23a 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs | |||
@@ -70,7 +70,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
70 | 70 | ||
71 | private Vector3 _position; | 71 | private Vector3 _position; |
72 | private d.Vector3 _zeroPosition; | 72 | private d.Vector3 _zeroPosition; |
73 | // private d.Matrix3 m_StandUpRotation; | ||
74 | private bool _zeroFlag = false; | 73 | private bool _zeroFlag = false; |
75 | private bool m_lastUpdateSent = false; | 74 | private bool m_lastUpdateSent = false; |
76 | private Vector3 _velocity; | 75 | private Vector3 _velocity; |
@@ -123,9 +122,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
123 | private float m_buoyancy = 0f; | 122 | private float m_buoyancy = 0f; |
124 | 123 | ||
125 | // private CollisionLocker ode; | 124 | // private CollisionLocker ode; |
126 | |||
127 | private string m_name = String.Empty; | ||
128 | |||
129 | private bool[] m_colliderarr = new bool[11]; | 125 | private bool[] m_colliderarr = new bool[11]; |
130 | private bool[] m_colliderGroundarr = new bool[11]; | 126 | private bool[] m_colliderGroundarr = new bool[11]; |
131 | 127 | ||
@@ -181,7 +177,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
181 | parent_scene.GetTerrainHeightAtXY(128f, 128f) + 10f); | 177 | parent_scene.GetTerrainHeightAtXY(128f, 128f) + 10f); |
182 | m_taintPosition = _position; | 178 | m_taintPosition = _position; |
183 | 179 | ||
184 | m_log.Warn("[PHYSICS]: Got NaN Position on Character Create"); | 180 | m_log.WarnFormat("[ODE CHARACTER]: Got NaN Position on Character Create for {0}", avName); |
185 | } | 181 | } |
186 | 182 | ||
187 | _parent_scene = parent_scene; | 183 | _parent_scene = parent_scene; |
@@ -204,7 +200,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
204 | m_colliderarr[i] = false; | 200 | m_colliderarr[i] = false; |
205 | } | 201 | } |
206 | CAPSULE_LENGTH = (size.Z * 1.15f) - CAPSULE_RADIUS * 2.0f; | 202 | CAPSULE_LENGTH = (size.Z * 1.15f) - CAPSULE_RADIUS * 2.0f; |
207 | //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString()); | 203 | //m_log.Info("[ODE CHARACTER]: " + CAPSULE_LENGTH.ToString()); |
208 | m_tainted_CAPSULE_LENGTH = CAPSULE_LENGTH; | 204 | m_tainted_CAPSULE_LENGTH = CAPSULE_LENGTH; |
209 | 205 | ||
210 | m_isPhysical = false; // current status: no ODE information exists | 206 | m_isPhysical = false; // current status: no ODE information exists |
@@ -212,7 +208,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
212 | 208 | ||
213 | _parent_scene.AddPhysicsActorTaint(this); | 209 | _parent_scene.AddPhysicsActorTaint(this); |
214 | 210 | ||
215 | m_name = avName; | 211 | Name = avName; |
216 | } | 212 | } |
217 | 213 | ||
218 | public override int PhysicsActorType | 214 | public override int PhysicsActorType |
@@ -269,7 +265,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
269 | set | 265 | set |
270 | { | 266 | { |
271 | flying = value; | 267 | flying = value; |
272 | // m_log.DebugFormat("[PHYSICS]: Set OdeCharacter Flying to {0}", flying); | 268 | // m_log.DebugFormat("[ODE CHARACTER]: Set OdeCharacter Flying to {0}", flying); |
273 | } | 269 | } |
274 | } | 270 | } |
275 | 271 | ||
@@ -440,7 +436,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
440 | } | 436 | } |
441 | else | 437 | else |
442 | { | 438 | { |
443 | m_log.Warn("[PHYSICS]: Got a NaN Position from Scene on a Character"); | 439 | m_log.WarnFormat("[ODE CHARACTER]: Got a NaN Position from Scene on character {0}", Name); |
444 | } | 440 | } |
445 | } | 441 | } |
446 | } | 442 | } |
@@ -467,7 +463,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
467 | 463 | ||
468 | Vector3 SetSize = value; | 464 | Vector3 SetSize = value; |
469 | m_tainted_CAPSULE_LENGTH = (SetSize.Z * 1.15f) - CAPSULE_RADIUS * 2.0f; | 465 | m_tainted_CAPSULE_LENGTH = (SetSize.Z * 1.15f) - CAPSULE_RADIUS * 2.0f; |
470 | // m_log.Info("[SIZE]: " + CAPSULE_LENGTH); | 466 | // m_log.Info("[ODE CHARACTER]: " + CAPSULE_LENGTH); |
471 | 467 | ||
472 | // If we reset velocity here, then an avatar stalls when it crosses a border for the first time | 468 | // If we reset velocity here, then an avatar stalls when it crosses a border for the first time |
473 | // (as the height of the new root agent is set). | 469 | // (as the height of the new root agent is set). |
@@ -477,7 +473,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
477 | } | 473 | } |
478 | else | 474 | else |
479 | { | 475 | { |
480 | m_log.Warn("[PHYSICS]: Got a NaN Size from Scene on a Character"); | 476 | m_log.WarnFormat("[ODE CHARACTER]: Got a NaN Size from Scene on {0}", Name); |
481 | } | 477 | } |
482 | } | 478 | } |
483 | } | 479 | } |
@@ -529,7 +525,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
529 | } | 525 | } |
530 | } | 526 | } |
531 | 527 | ||
532 | |||
533 | // movementVector.Z is zero | 528 | // movementVector.Z is zero |
534 | 529 | ||
535 | // calculate tilt components based on desired amount of tilt and current (snapped) heading. | 530 | // calculate tilt components based on desired amount of tilt and current (snapped) heading. |
@@ -537,7 +532,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
537 | float xTiltComponent = -movementVector.X * m_tiltMagnitudeWhenProjectedOnXYPlane; | 532 | float xTiltComponent = -movementVector.X * m_tiltMagnitudeWhenProjectedOnXYPlane; |
538 | float yTiltComponent = -movementVector.Y * m_tiltMagnitudeWhenProjectedOnXYPlane; | 533 | float yTiltComponent = -movementVector.Y * m_tiltMagnitudeWhenProjectedOnXYPlane; |
539 | 534 | ||
540 | //m_log.Debug("[PHYSICS] changing avatar tilt"); | 535 | //m_log.Debug("[ODE CHARACTER]: changing avatar tilt"); |
541 | d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, xTiltComponent); | 536 | d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, xTiltComponent); |
542 | d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, xTiltComponent); // must be same as lowstop, else a different, spurious tilt is introduced | 537 | d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, xTiltComponent); // must be same as lowstop, else a different, spurious tilt is introduced |
543 | d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, yTiltComponent); | 538 | d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, yTiltComponent); |
@@ -547,124 +542,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
547 | } | 542 | } |
548 | 543 | ||
549 | /// <summary> | 544 | /// <summary> |
550 | /// This creates the Avatar's physical Surrogate at the position supplied | ||
551 | /// </summary> | ||
552 | /// <param name="npositionX"></param> | ||
553 | /// <param name="npositionY"></param> | ||
554 | /// <param name="npositionZ"></param> | ||
555 | |||
556 | // WARNING: This MUST NOT be called outside of ProcessTaints, else we can have unsynchronized access | ||
557 | // to ODE internals. ProcessTaints is called from within thread-locked Simulate(), so it is the only | ||
558 | // place that is safe to call this routine AvatarGeomAndBodyCreation. | ||
559 | private void AvatarGeomAndBodyCreation(float npositionX, float npositionY, float npositionZ, float tensor) | ||
560 | { | ||
561 | //CAPSULE_LENGTH = -5; | ||
562 | //CAPSULE_RADIUS = -5; | ||
563 | int dAMotorEuler = 1; | ||
564 | _parent_scene.waitForSpaceUnlock(_parent_scene.space); | ||
565 | if (CAPSULE_LENGTH <= 0) | ||
566 | { | ||
567 | m_log.Warn("[PHYSICS]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!"); | ||
568 | CAPSULE_LENGTH = 0.01f; | ||
569 | |||
570 | } | ||
571 | |||
572 | if (CAPSULE_RADIUS <= 0) | ||
573 | { | ||
574 | m_log.Warn("[PHYSICS]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!"); | ||
575 | CAPSULE_RADIUS = 0.01f; | ||
576 | |||
577 | } | ||
578 | Shell = d.CreateCapsule(_parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH); | ||
579 | |||
580 | d.GeomSetCategoryBits(Shell, (int)m_collisionCategories); | ||
581 | d.GeomSetCollideBits(Shell, (int)m_collisionFlags); | ||
582 | |||
583 | d.MassSetCapsuleTotal(out ShellMass, m_mass, 2, CAPSULE_RADIUS, CAPSULE_LENGTH); | ||
584 | Body = d.BodyCreate(_parent_scene.world); | ||
585 | d.BodySetPosition(Body, npositionX, npositionY, npositionZ); | ||
586 | |||
587 | _position.X = npositionX; | ||
588 | _position.Y = npositionY; | ||
589 | _position.Z = npositionZ; | ||
590 | |||
591 | m_taintPosition = _position; | ||
592 | |||
593 | d.BodySetMass(Body, ref ShellMass); | ||
594 | d.Matrix3 m_caprot; | ||
595 | // 90 Stand up on the cap of the capped cyllinder | ||
596 | if (_parent_scene.IsAvCapsuleTilted) | ||
597 | { | ||
598 | d.RFromAxisAndAngle(out m_caprot, 1, 0, 1, (float)(Math.PI / 2)); | ||
599 | } | ||
600 | else | ||
601 | { | ||
602 | d.RFromAxisAndAngle(out m_caprot, 0, 0, 1, (float)(Math.PI / 2)); | ||
603 | } | ||
604 | |||
605 | |||
606 | d.GeomSetRotation(Shell, ref m_caprot); | ||
607 | d.BodySetRotation(Body, ref m_caprot); | ||
608 | |||
609 | d.GeomSetBody(Shell, Body); | ||
610 | |||
611 | |||
612 | // The purpose of the AMotor here is to keep the avatar's physical | ||
613 | // surrogate from rotating while moving | ||
614 | Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero); | ||
615 | d.JointAttach(Amotor, Body, IntPtr.Zero); | ||
616 | d.JointSetAMotorMode(Amotor, dAMotorEuler); | ||
617 | d.JointSetAMotorNumAxes(Amotor, 3); | ||
618 | d.JointSetAMotorAxis(Amotor, 0, 0, 1, 0, 0); | ||
619 | d.JointSetAMotorAxis(Amotor, 1, 0, 0, 1, 0); | ||
620 | d.JointSetAMotorAxis(Amotor, 2, 0, 0, 0, 1); | ||
621 | d.JointSetAMotorAngle(Amotor, 0, 0); | ||
622 | d.JointSetAMotorAngle(Amotor, 1, 0); | ||
623 | d.JointSetAMotorAngle(Amotor, 2, 0); | ||
624 | |||
625 | // These lowstops and high stops are effectively (no wiggle room) | ||
626 | if (_parent_scene.IsAvCapsuleTilted) | ||
627 | { | ||
628 | d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, -0.000000000001f); | ||
629 | d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -0.000000000001f); | ||
630 | d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, -0.000000000001f); | ||
631 | d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0.000000000001f); | ||
632 | d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0.000000000001f); | ||
633 | d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0.000000000001f); | ||
634 | } | ||
635 | else | ||
636 | { | ||
637 | #region Documentation of capsule motor LowStop and HighStop parameters | ||
638 | // Intentionally introduce some tilt into the capsule by setting | ||
639 | // the motor stops to small epsilon values. This small tilt prevents | ||
640 | // the capsule from falling into the terrain; a straight-up capsule | ||
641 | // (with -0..0 motor stops) falls into the terrain for reasons yet | ||
642 | // to be comprehended in their entirety. | ||
643 | #endregion | ||
644 | AlignAvatarTiltWithCurrentDirectionOfMovement(Vector3.Zero); | ||
645 | d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, 0.08f); | ||
646 | d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -0f); | ||
647 | d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, 0.08f); | ||
648 | d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0.08f); // must be same as lowstop, else a different, spurious tilt is introduced | ||
649 | d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0f); // same as lowstop | ||
650 | d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0.08f); // same as lowstop | ||
651 | } | ||
652 | |||
653 | // Fudge factor is 1f by default, we're setting it to 0. We don't want it to Fudge or the | ||
654 | // capped cyllinder will fall over | ||
655 | d.JointSetAMotorParam(Amotor, (int)dParam.FudgeFactor, 0f); | ||
656 | d.JointSetAMotorParam(Amotor, (int)dParam.FMax, tensor); | ||
657 | |||
658 | //d.Matrix3 bodyrotation = d.BodyGetRotation(Body); | ||
659 | //d.QfromR( | ||
660 | //d.Matrix3 checkrotation = new d.Matrix3(0.7071068,0.5, -0.7071068, | ||
661 | // | ||
662 | //m_log.Info("[PHYSICSAV]: Rotation: " + bodyrotation.M00 + " : " + bodyrotation.M01 + " : " + bodyrotation.M02 + " : " + bodyrotation.M10 + " : " + bodyrotation.M11 + " : " + bodyrotation.M12 + " : " + bodyrotation.M20 + " : " + bodyrotation.M21 + " : " + bodyrotation.M22); | ||
663 | //standupStraight(); | ||
664 | } | ||
665 | |||
666 | // | ||
667 | /// <summary> | ||
668 | /// Uses the capped cyllinder volume formula to calculate the avatar's mass. | 545 | /// Uses the capped cyllinder volume formula to calculate the avatar's mass. |
669 | /// This may be used in calculations in the scene/scenepresence | 546 | /// This may be used in calculations in the scene/scenepresence |
670 | /// </summary> | 547 | /// </summary> |
@@ -774,7 +651,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
774 | } | 651 | } |
775 | else | 652 | else |
776 | { | 653 | { |
777 | m_log.Warn("[PHYSICS]: Got a NaN velocity from Scene in a Character"); | 654 | m_log.WarnFormat("[ODE CHARACTER]: Got a NaN velocity from Scene for {0}", Name); |
778 | } | 655 | } |
779 | 656 | ||
780 | // m_log.DebugFormat("[PHYSICS]: Set target velocity of {0}", m_taintTargetVelocity); | 657 | // m_log.DebugFormat("[PHYSICS]: Set target velocity of {0}", m_taintTargetVelocity); |
@@ -836,7 +713,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
836 | m_taintForce += force; | 713 | m_taintForce += force; |
837 | _parent_scene.AddPhysicsActorTaint(this); | 714 | _parent_scene.AddPhysicsActorTaint(this); |
838 | 715 | ||
839 | //doForce(force); | ||
840 | // If uncommented, things get pushed off world | 716 | // If uncommented, things get pushed off world |
841 | // | 717 | // |
842 | // m_log.Debug("Push!"); | 718 | // m_log.Debug("Push!"); |
@@ -852,7 +728,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
852 | } | 728 | } |
853 | else | 729 | else |
854 | { | 730 | { |
855 | m_log.Warn("[PHYSICS]: Got a NaN force applied to a Character"); | 731 | m_log.WarnFormat("[ODE CHARACTER]: Got a NaN force applied to {0}", Name); |
856 | } | 732 | } |
857 | //m_lastUpdateSent = false; | 733 | //m_lastUpdateSent = false; |
858 | } | 734 | } |
@@ -861,15 +737,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
861 | { | 737 | { |
862 | } | 738 | } |
863 | 739 | ||
864 | /// <summary> | ||
865 | /// After all of the forces add up with 'add force' we apply them with doForce | ||
866 | /// </summary> | ||
867 | /// <param name="force"></param> | ||
868 | public void doForce(Vector3 force) | ||
869 | { | ||
870 | d.BodyAddForce(Body, force.X, force.Y, force.Z); | ||
871 | } | ||
872 | |||
873 | public override void SetMomentum(Vector3 momentum) | 740 | public override void SetMomentum(Vector3 momentum) |
874 | { | 741 | { |
875 | } | 742 | } |
@@ -878,9 +745,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
878 | /// Called from Simulate | 745 | /// Called from Simulate |
879 | /// This is the avatar's movement control + PID Controller | 746 | /// This is the avatar's movement control + PID Controller |
880 | /// </summary> | 747 | /// </summary> |
881 | /// <param name="defects"> | 748 | /// <param name="defects">The character will be added to this list if there is something wrong (non-finite |
882 | /// If there is something wrong with the character (e.g. its position is non-finite) | 749 | /// position or velocity). |
883 | /// then it is added to this list. The ODE structures associated with it are also destroyed. | ||
884 | /// </param> | 750 | /// </param> |
885 | internal void Move(List<OdeCharacter> defects) | 751 | internal void Move(List<OdeCharacter> defects) |
886 | { | 752 | { |
@@ -903,12 +769,11 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
903 | 769 | ||
904 | if (!localPos.IsFinite()) | 770 | if (!localPos.IsFinite()) |
905 | { | 771 | { |
906 | m_log.Warn("[PHYSICS]: Avatar Position is non-finite!"); | 772 | m_log.WarnFormat( |
773 | "[ODE CHARACTER]: Avatar position of {0} for {1} is non-finite! Removing from physics scene.", | ||
774 | localPos, Name); | ||
907 | 775 | ||
908 | defects.Add(this); | 776 | defects.Add(this); |
909 | // _parent_scene.RemoveCharacter(this); | ||
910 | |||
911 | DestroyOdeStructures(); | ||
912 | 777 | ||
913 | return; | 778 | return; |
914 | } | 779 | } |
@@ -1035,26 +900,31 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1035 | 900 | ||
1036 | if (vec.IsFinite()) | 901 | if (vec.IsFinite()) |
1037 | { | 902 | { |
1038 | doForce(vec); | 903 | // Apply the total force acting on this avatar |
904 | d.BodyAddForce(Body, vec.X, vec.Y, vec.Z); | ||
1039 | 905 | ||
1040 | if (!_zeroFlag) | 906 | if (!_zeroFlag) |
1041 | AlignAvatarTiltWithCurrentDirectionOfMovement(vec); | 907 | AlignAvatarTiltWithCurrentDirectionOfMovement(vec); |
1042 | } | 908 | } |
1043 | else | 909 | else |
1044 | { | 910 | { |
1045 | m_log.Warn("[PHYSICS]: Got a NaN force vector in Move()"); | 911 | m_log.WarnFormat( |
1046 | m_log.Warn("[PHYSICS]: Avatar Position is non-finite!"); | 912 | "[ODE CHARACTER]: Got a NaN force vector {0} in Move() for {1}. Removing character from physics scene.", |
913 | vec, Name); | ||
914 | |||
1047 | defects.Add(this); | 915 | defects.Add(this); |
1048 | // _parent_scene.RemoveCharacter(this); | ||
1049 | 916 | ||
1050 | DestroyOdeStructures(); | 917 | return; |
1051 | } | 918 | } |
1052 | } | 919 | } |
1053 | 920 | ||
1054 | /// <summary> | 921 | /// <summary> |
1055 | /// Updates the reported position and velocity. This essentially sends the data up to ScenePresence. | 922 | /// Updates the reported position and velocity. This essentially sends the data up to ScenePresence. |
1056 | /// </summary> | 923 | /// </summary> |
1057 | internal void UpdatePositionAndVelocity() | 924 | /// <param name="defects">The character will be added to this list if there is something wrong (non-finite |
925 | /// position or velocity). | ||
926 | /// </param> | ||
927 | internal void UpdatePositionAndVelocity(List<OdeCharacter> defects) | ||
1058 | { | 928 | { |
1059 | // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit! | 929 | // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit! |
1060 | d.Vector3 newPos; | 930 | d.Vector3 newPos; |
@@ -1065,10 +935,12 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1065 | catch (NullReferenceException) | 935 | catch (NullReferenceException) |
1066 | { | 936 | { |
1067 | bad = true; | 937 | bad = true; |
1068 | _parent_scene.BadCharacter(this); | 938 | defects.Add(this); |
1069 | newPos = new d.Vector3(_position.X, _position.Y, _position.Z); | 939 | newPos = new d.Vector3(_position.X, _position.Y, _position.Z); |
1070 | base.RaiseOutOfBounds(_position); // Tells ScenePresence that there's a problem! | 940 | base.RaiseOutOfBounds(_position); // Tells ScenePresence that there's a problem! |
1071 | m_log.WarnFormat("[ODEPLUGIN]: Avatar Null reference for Avatar {0}, physical actor {1}", m_name, m_uuid); | 941 | m_log.WarnFormat("[ODE CHARACTER]: Avatar Null reference for Avatar {0}, physical actor {1}", Name, m_uuid); |
942 | |||
943 | return; | ||
1072 | } | 944 | } |
1073 | 945 | ||
1074 | // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!) | 946 | // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!) |
@@ -1137,6 +1009,123 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1137 | } | 1009 | } |
1138 | 1010 | ||
1139 | /// <summary> | 1011 | /// <summary> |
1012 | /// This creates the Avatar's physical Surrogate in ODE at the position supplied | ||
1013 | /// </summary> | ||
1014 | /// <remarks> | ||
1015 | /// WARNING: This MUST NOT be called outside of ProcessTaints, else we can have unsynchronized access | ||
1016 | /// to ODE internals. ProcessTaints is called from within thread-locked Simulate(), so it is the only | ||
1017 | /// place that is safe to call this routine AvatarGeomAndBodyCreation. | ||
1018 | /// </remarks> | ||
1019 | /// <param name="npositionX"></param> | ||
1020 | /// <param name="npositionY"></param> | ||
1021 | /// <param name="npositionZ"></param> | ||
1022 | /// <param name="tensor"></param> | ||
1023 | private void CreateOdeStructures(float npositionX, float npositionY, float npositionZ, float tensor) | ||
1024 | { | ||
1025 | int dAMotorEuler = 1; | ||
1026 | // _parent_scene.waitForSpaceUnlock(_parent_scene.space); | ||
1027 | if (CAPSULE_LENGTH <= 0) | ||
1028 | { | ||
1029 | m_log.Warn("[ODE CHARACTER]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!"); | ||
1030 | CAPSULE_LENGTH = 0.01f; | ||
1031 | } | ||
1032 | |||
1033 | if (CAPSULE_RADIUS <= 0) | ||
1034 | { | ||
1035 | m_log.Warn("[ODE CHARACTER]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!"); | ||
1036 | CAPSULE_RADIUS = 0.01f; | ||
1037 | } | ||
1038 | |||
1039 | Shell = d.CreateCapsule(_parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH); | ||
1040 | |||
1041 | d.GeomSetCategoryBits(Shell, (int)m_collisionCategories); | ||
1042 | d.GeomSetCollideBits(Shell, (int)m_collisionFlags); | ||
1043 | |||
1044 | d.MassSetCapsuleTotal(out ShellMass, m_mass, 2, CAPSULE_RADIUS, CAPSULE_LENGTH); | ||
1045 | Body = d.BodyCreate(_parent_scene.world); | ||
1046 | d.BodySetPosition(Body, npositionX, npositionY, npositionZ); | ||
1047 | |||
1048 | _position.X = npositionX; | ||
1049 | _position.Y = npositionY; | ||
1050 | _position.Z = npositionZ; | ||
1051 | |||
1052 | m_taintPosition = _position; | ||
1053 | |||
1054 | d.BodySetMass(Body, ref ShellMass); | ||
1055 | d.Matrix3 m_caprot; | ||
1056 | // 90 Stand up on the cap of the capped cyllinder | ||
1057 | if (_parent_scene.IsAvCapsuleTilted) | ||
1058 | { | ||
1059 | d.RFromAxisAndAngle(out m_caprot, 1, 0, 1, (float)(Math.PI / 2)); | ||
1060 | } | ||
1061 | else | ||
1062 | { | ||
1063 | d.RFromAxisAndAngle(out m_caprot, 0, 0, 1, (float)(Math.PI / 2)); | ||
1064 | } | ||
1065 | |||
1066 | d.GeomSetRotation(Shell, ref m_caprot); | ||
1067 | d.BodySetRotation(Body, ref m_caprot); | ||
1068 | |||
1069 | d.GeomSetBody(Shell, Body); | ||
1070 | |||
1071 | // The purpose of the AMotor here is to keep the avatar's physical | ||
1072 | // surrogate from rotating while moving | ||
1073 | Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero); | ||
1074 | d.JointAttach(Amotor, Body, IntPtr.Zero); | ||
1075 | d.JointSetAMotorMode(Amotor, dAMotorEuler); | ||
1076 | d.JointSetAMotorNumAxes(Amotor, 3); | ||
1077 | d.JointSetAMotorAxis(Amotor, 0, 0, 1, 0, 0); | ||
1078 | d.JointSetAMotorAxis(Amotor, 1, 0, 0, 1, 0); | ||
1079 | d.JointSetAMotorAxis(Amotor, 2, 0, 0, 0, 1); | ||
1080 | d.JointSetAMotorAngle(Amotor, 0, 0); | ||
1081 | d.JointSetAMotorAngle(Amotor, 1, 0); | ||
1082 | d.JointSetAMotorAngle(Amotor, 2, 0); | ||
1083 | |||
1084 | // These lowstops and high stops are effectively (no wiggle room) | ||
1085 | if (_parent_scene.IsAvCapsuleTilted) | ||
1086 | { | ||
1087 | d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, -0.000000000001f); | ||
1088 | d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -0.000000000001f); | ||
1089 | d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, -0.000000000001f); | ||
1090 | d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0.000000000001f); | ||
1091 | d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0.000000000001f); | ||
1092 | d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0.000000000001f); | ||
1093 | } | ||
1094 | else | ||
1095 | { | ||
1096 | #region Documentation of capsule motor LowStop and HighStop parameters | ||
1097 | // Intentionally introduce some tilt into the capsule by setting | ||
1098 | // the motor stops to small epsilon values. This small tilt prevents | ||
1099 | // the capsule from falling into the terrain; a straight-up capsule | ||
1100 | // (with -0..0 motor stops) falls into the terrain for reasons yet | ||
1101 | // to be comprehended in their entirety. | ||
1102 | #endregion | ||
1103 | AlignAvatarTiltWithCurrentDirectionOfMovement(Vector3.Zero); | ||
1104 | d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, 0.08f); | ||
1105 | d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -0f); | ||
1106 | d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, 0.08f); | ||
1107 | d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0.08f); // must be same as lowstop, else a different, spurious tilt is introduced | ||
1108 | d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0f); // same as lowstop | ||
1109 | d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0.08f); // same as lowstop | ||
1110 | } | ||
1111 | |||
1112 | // Fudge factor is 1f by default, we're setting it to 0. We don't want it to Fudge or the | ||
1113 | // capped cyllinder will fall over | ||
1114 | d.JointSetAMotorParam(Amotor, (int)dParam.FudgeFactor, 0f); | ||
1115 | d.JointSetAMotorParam(Amotor, (int)dParam.FMax, tensor); | ||
1116 | |||
1117 | //d.Matrix3 bodyrotation = d.BodyGetRotation(Body); | ||
1118 | //d.QfromR( | ||
1119 | //d.Matrix3 checkrotation = new d.Matrix3(0.7071068,0.5, -0.7071068, | ||
1120 | // | ||
1121 | //m_log.Info("[PHYSICSAV]: Rotation: " + bodyrotation.M00 + " : " + bodyrotation.M01 + " : " + bodyrotation.M02 + " : " + bodyrotation.M10 + " : " + bodyrotation.M11 + " : " + bodyrotation.M12 + " : " + bodyrotation.M20 + " : " + bodyrotation.M21 + " : " + bodyrotation.M22); | ||
1122 | //standupStraight(); | ||
1123 | |||
1124 | _parent_scene.geom_name_map[Shell] = Name; | ||
1125 | _parent_scene.actor_name_map[Shell] = this; | ||
1126 | } | ||
1127 | |||
1128 | /// <summary> | ||
1140 | /// Cleanup the things we use in the scene. | 1129 | /// Cleanup the things we use in the scene. |
1141 | /// </summary> | 1130 | /// </summary> |
1142 | internal void Destroy() | 1131 | internal void Destroy() |
@@ -1148,7 +1137,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1148 | /// <summary> | 1137 | /// <summary> |
1149 | /// Used internally to destroy the ODE structures associated with this character. | 1138 | /// Used internally to destroy the ODE structures associated with this character. |
1150 | /// </summary> | 1139 | /// </summary> |
1151 | private void DestroyOdeStructures() | 1140 | internal void DestroyOdeStructures() |
1152 | { | 1141 | { |
1153 | // destroy avatar capsule and related ODE data | 1142 | // destroy avatar capsule and related ODE data |
1154 | if (Amotor != IntPtr.Zero) | 1143 | if (Amotor != IntPtr.Zero) |
@@ -1159,13 +1148,12 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1159 | } | 1148 | } |
1160 | 1149 | ||
1161 | //kill the Geometry | 1150 | //kill the Geometry |
1162 | _parent_scene.waitForSpaceUnlock(_parent_scene.space); | 1151 | // _parent_scene.waitForSpaceUnlock(_parent_scene.space); |
1163 | 1152 | ||
1164 | if (Body != IntPtr.Zero) | 1153 | if (Body != IntPtr.Zero) |
1165 | { | 1154 | { |
1166 | //kill the body | 1155 | //kill the body |
1167 | d.BodyDestroy(Body); | 1156 | d.BodyDestroy(Body); |
1168 | |||
1169 | Body = IntPtr.Zero; | 1157 | Body = IntPtr.Zero; |
1170 | } | 1158 | } |
1171 | 1159 | ||
@@ -1173,6 +1161,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1173 | { | 1161 | { |
1174 | d.GeomDestroy(Shell); | 1162 | d.GeomDestroy(Shell); |
1175 | _parent_scene.geom_name_map.Remove(Shell); | 1163 | _parent_scene.geom_name_map.Remove(Shell); |
1164 | _parent_scene.actor_name_map.Remove(Shell); | ||
1165 | |||
1176 | Shell = IntPtr.Zero; | 1166 | Shell = IntPtr.Zero; |
1177 | } | 1167 | } |
1178 | } | 1168 | } |
@@ -1261,7 +1251,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1261 | // FIXME: This is not a good solution since it's subject to a race condition if a force is another | 1251 | // FIXME: This is not a good solution since it's subject to a race condition if a force is another |
1262 | // thread sets a new force while we're in this loop (since it could be obliterated by | 1252 | // thread sets a new force while we're in this loop (since it could be obliterated by |
1263 | // m_taintForce = Vector3.Zero. Need to lock ProcessTaints() when we set a new tainted force. | 1253 | // m_taintForce = Vector3.Zero. Need to lock ProcessTaints() when we set a new tainted force. |
1264 | doForce(m_taintForce); | 1254 | d.BodyAddForce(Body, m_taintForce.X, m_taintForce.Y, m_taintForce.Z); |
1265 | } | 1255 | } |
1266 | 1256 | ||
1267 | m_taintForce = Vector3.Zero; | 1257 | m_taintForce = Vector3.Zero; |
@@ -1277,15 +1267,13 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1277 | // Create avatar capsule and related ODE data | 1267 | // Create avatar capsule and related ODE data |
1278 | if (!(Shell == IntPtr.Zero && Body == IntPtr.Zero && Amotor == IntPtr.Zero)) | 1268 | if (!(Shell == IntPtr.Zero && Body == IntPtr.Zero && Amotor == IntPtr.Zero)) |
1279 | { | 1269 | { |
1280 | m_log.Warn("[PHYSICS]: re-creating the following avatar ODE data, even though it already exists - " | 1270 | m_log.Warn("[ODE CHARACTER]: re-creating the following avatar ODE data for " + Name + ", even though it already exists - " |
1281 | + (Shell!=IntPtr.Zero ? "Shell ":"") | 1271 | + (Shell!=IntPtr.Zero ? "Shell ":"") |
1282 | + (Body!=IntPtr.Zero ? "Body ":"") | 1272 | + (Body!=IntPtr.Zero ? "Body ":"") |
1283 | + (Amotor!=IntPtr.Zero ? "Amotor ":"")); | 1273 | + (Amotor!=IntPtr.Zero ? "Amotor ":"")); |
1284 | } | 1274 | } |
1285 | AvatarGeomAndBodyCreation(_position.X, _position.Y, _position.Z, m_tensor); | 1275 | |
1286 | 1276 | CreateOdeStructures(_position.X, _position.Y, _position.Z, m_tensor); | |
1287 | _parent_scene.geom_name_map[Shell] = m_name; | ||
1288 | _parent_scene.actor_name_map[Shell] = (PhysicsActor)this; | ||
1289 | _parent_scene.AddCharacter(this); | 1277 | _parent_scene.AddCharacter(this); |
1290 | } | 1278 | } |
1291 | else | 1279 | else |
@@ -1301,17 +1289,19 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1301 | { | 1289 | { |
1302 | if (Shell != IntPtr.Zero && Body != IntPtr.Zero && Amotor != IntPtr.Zero) | 1290 | if (Shell != IntPtr.Zero && Body != IntPtr.Zero && Amotor != IntPtr.Zero) |
1303 | { | 1291 | { |
1304 | // m_log.DebugFormat("[PHYSICS]: Changing capsule size"); | 1292 | // m_log.DebugFormat( |
1293 | // "[ODE CHARACTER]: Changing capsule size from {0} to {1} for {2}", | ||
1294 | // CAPSULE_LENGTH, m_tainted_CAPSULE_LENGTH, Name); | ||
1305 | 1295 | ||
1306 | m_pidControllerActive = true; | 1296 | m_pidControllerActive = true; |
1297 | |||
1307 | // no lock needed on _parent_scene.OdeLock because we are called from within the thread lock in OdePlugin's simulate() | 1298 | // no lock needed on _parent_scene.OdeLock because we are called from within the thread lock in OdePlugin's simulate() |
1308 | d.JointDestroy(Amotor); | 1299 | DestroyOdeStructures(); |
1300 | |||
1309 | float prevCapsule = CAPSULE_LENGTH; | 1301 | float prevCapsule = CAPSULE_LENGTH; |
1310 | CAPSULE_LENGTH = m_tainted_CAPSULE_LENGTH; | 1302 | CAPSULE_LENGTH = m_tainted_CAPSULE_LENGTH; |
1311 | //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString()); | 1303 | |
1312 | d.BodyDestroy(Body); | 1304 | CreateOdeStructures( |
1313 | d.GeomDestroy(Shell); | ||
1314 | AvatarGeomAndBodyCreation( | ||
1315 | _position.X, | 1305 | _position.X, |
1316 | _position.Y, | 1306 | _position.Y, |
1317 | _position.Z + (Math.Abs(CAPSULE_LENGTH - prevCapsule) * 2), m_tensor); | 1307 | _position.Z + (Math.Abs(CAPSULE_LENGTH - prevCapsule) * 2), m_tensor); |
@@ -1319,13 +1309,10 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1319 | // As with Size, we reset velocity. However, this isn't strictly necessary since it doesn't | 1309 | // As with Size, we reset velocity. However, this isn't strictly necessary since it doesn't |
1320 | // appear to stall initial region crossings when done here. Being done for consistency. | 1310 | // appear to stall initial region crossings when done here. Being done for consistency. |
1321 | // Velocity = Vector3.Zero; | 1311 | // Velocity = Vector3.Zero; |
1322 | |||
1323 | _parent_scene.geom_name_map[Shell] = m_name; | ||
1324 | _parent_scene.actor_name_map[Shell] = (PhysicsActor)this; | ||
1325 | } | 1312 | } |
1326 | else | 1313 | else |
1327 | { | 1314 | { |
1328 | m_log.Warn("[PHYSICS]: trying to change capsule size, but the following ODE data is missing - " | 1315 | m_log.Warn("[ODE CHARACTER]: trying to change capsule size for " + Name + ", but the following ODE data is missing - " |
1329 | + (Shell==IntPtr.Zero ? "Shell ":"") | 1316 | + (Shell==IntPtr.Zero ? "Shell ":"") |
1330 | + (Body==IntPtr.Zero ? "Body ":"") | 1317 | + (Body==IntPtr.Zero ? "Body ":"") |
1331 | + (Amotor==IntPtr.Zero ? "Amotor ":"")); | 1318 | + (Amotor==IntPtr.Zero ? "Amotor ":"")); |