aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/OdePlugin/ODECharacter.cs')
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODECharacter.cs341
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 ":""));