aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics')
-rw-r--r--OpenSim/Region/Physics/Manager/PhysicsActor.cs13
-rw-r--r--OpenSim/Region/Physics/Manager/PhysicsScene.cs10
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODECharacter.cs341
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODEPrim.cs20
-rw-r--r--OpenSim/Region/Physics/OdePlugin/OdeScene.cs680
5 files changed, 525 insertions, 539 deletions
diff --git a/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/OpenSim/Region/Physics/Manager/PhysicsActor.cs
index 798a0a4..c2acf97 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsActor.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsActor.cs
@@ -160,8 +160,19 @@ namespace OpenSim.Region.Physics.Manager
160 160
161 public abstract bool Selected { set; } 161 public abstract bool Selected { set; }
162 162
163 /// <summary>
164 /// Name of this actor.
165 /// </summary>
166 /// <remarks>
167 /// XXX: Bizarrely, this cannot be "Terrain" or "Water" right now unless it really is simulating terrain or
168 /// water. This is not a problem due to the formatting of names given by prims and avatars.
169 /// </remarks>
170 public string Name { get; protected set; }
171
172 /// <summary>
173 /// This is being used by ODE joint code.
174 /// </summary>
163 public string SOPName; 175 public string SOPName;
164 public string SOPDescription;
165 176
166 public abstract void CrossingFailure(); 177 public abstract void CrossingFailure();
167 178
diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
index acedf44..1f631ee 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
@@ -224,15 +224,9 @@ namespace OpenSim.Region.Physics.Manager
224 return false; 224 return false;
225 } 225 }
226 226
227 public virtual void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents) 227 public virtual void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents) {}
228 {
229 return;
230 }
231 228
232 public virtual void UnCombine(PhysicsScene pScene) 229 public virtual void UnCombine(PhysicsScene pScene) {}
233 {
234
235 }
236 230
237 /// <summary> 231 /// <summary>
238 /// Queue a raycast against the physics scene. 232 /// Queue a raycast against the physics scene.
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 ":""));
diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
index f07cf46..af05a15 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
@@ -184,7 +184,6 @@ namespace OpenSim.Region.Physics.OdePlugin
184 private bool m_lastUpdateSent; 184 private bool m_lastUpdateSent;
185 185
186 public IntPtr Body = IntPtr.Zero; 186 public IntPtr Body = IntPtr.Zero;
187 public String Name { get; private set; }
188 private Vector3 _target_velocity; 187 private Vector3 _target_velocity;
189 private d.Mass pMass; 188 private d.Mass pMass;
190 189
@@ -273,7 +272,6 @@ namespace OpenSim.Region.Physics.OdePlugin
273 272
274 m_taintadd = true; 273 m_taintadd = true;
275 _parent_scene.AddPhysicsActorTaint(this); 274 _parent_scene.AddPhysicsActorTaint(this);
276 // don't do .add() here; old geoms get recycled with the same hash
277 } 275 }
278 276
279 public override int PhysicsActorType 277 public override int PhysicsActorType
@@ -857,7 +855,7 @@ namespace OpenSim.Region.Physics.OdePlugin
857 m_MeshToTriMeshMap[mesh] = _triMeshData; 855 m_MeshToTriMeshMap[mesh] = _triMeshData;
858 } 856 }
859 857
860 _parent_scene.waitForSpaceUnlock(m_targetSpace); 858// _parent_scene.waitForSpaceUnlock(m_targetSpace);
861 try 859 try
862 { 860 {
863 if (prim_geom == IntPtr.Zero) 861 if (prim_geom == IntPtr.Zero)
@@ -1380,7 +1378,7 @@ Console.WriteLine("CreateGeom:");
1380 { 1378 {
1381 if (((_size.X / 2f) > 0f)) 1379 if (((_size.X / 2f) > 0f))
1382 { 1380 {
1383 _parent_scene.waitForSpaceUnlock(m_targetSpace); 1381// _parent_scene.waitForSpaceUnlock(m_targetSpace);
1384 try 1382 try
1385 { 1383 {
1386//Console.WriteLine(" CreateGeom 1"); 1384//Console.WriteLine(" CreateGeom 1");
@@ -1394,7 +1392,7 @@ Console.WriteLine("CreateGeom:");
1394 } 1392 }
1395 else 1393 else
1396 { 1394 {
1397 _parent_scene.waitForSpaceUnlock(m_targetSpace); 1395// _parent_scene.waitForSpaceUnlock(m_targetSpace);
1398 try 1396 try
1399 { 1397 {
1400//Console.WriteLine(" CreateGeom 2"); 1398//Console.WriteLine(" CreateGeom 2");
@@ -1409,7 +1407,7 @@ Console.WriteLine("CreateGeom:");
1409 } 1407 }
1410 else 1408 else
1411 { 1409 {
1412 _parent_scene.waitForSpaceUnlock(m_targetSpace); 1410// _parent_scene.waitForSpaceUnlock(m_targetSpace);
1413 try 1411 try
1414 { 1412 {
1415//Console.WriteLine(" CreateGeom 3"); 1413//Console.WriteLine(" CreateGeom 3");
@@ -1424,7 +1422,7 @@ Console.WriteLine("CreateGeom:");
1424 } 1422 }
1425 else 1423 else
1426 { 1424 {
1427 _parent_scene.waitForSpaceUnlock(m_targetSpace); 1425// _parent_scene.waitForSpaceUnlock(m_targetSpace);
1428 try 1426 try
1429 { 1427 {
1430//Console.WriteLine(" CreateGeom 4"); 1428//Console.WriteLine(" CreateGeom 4");
@@ -1577,17 +1575,17 @@ Console.WriteLine(" JointCreateFixed");
1577 { 1575 {
1578 // string primScenAvatarIn = _parent_scene.whichspaceamIin(_position); 1576 // string primScenAvatarIn = _parent_scene.whichspaceamIin(_position);
1579 // int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position); 1577 // int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
1580 _parent_scene.waitForSpaceUnlock(m_targetSpace); 1578// _parent_scene.waitForSpaceUnlock(m_targetSpace);
1581 1579
1582 IntPtr tempspace = _parent_scene.recalculateSpaceForGeom(prim_geom, _position, m_targetSpace); 1580 IntPtr tempspace = _parent_scene.recalculateSpaceForGeom(prim_geom, _position, m_targetSpace);
1583 m_targetSpace = tempspace; 1581 m_targetSpace = tempspace;
1584 1582
1585 _parent_scene.waitForSpaceUnlock(m_targetSpace); 1583// _parent_scene.waitForSpaceUnlock(m_targetSpace);
1586 if (prim_geom != IntPtr.Zero) 1584 if (prim_geom != IntPtr.Zero)
1587 { 1585 {
1588 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); 1586 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
1589 1587
1590 _parent_scene.waitForSpaceUnlock(m_targetSpace); 1588// _parent_scene.waitForSpaceUnlock(m_targetSpace);
1591 d.SpaceAdd(m_targetSpace, prim_geom); 1589 d.SpaceAdd(m_targetSpace, prim_geom);
1592 } 1590 }
1593 } 1591 }
@@ -1978,7 +1976,7 @@ Console.WriteLine(" JointCreateFixed");
1978 1976
1979 if (d.SpaceQuery(m_targetSpace, prim_geom)) 1977 if (d.SpaceQuery(m_targetSpace, prim_geom))
1980 { 1978 {
1981 _parent_scene.waitForSpaceUnlock(m_targetSpace); 1979// _parent_scene.waitForSpaceUnlock(m_targetSpace);
1982 d.SpaceRemove(m_targetSpace, prim_geom); 1980 d.SpaceRemove(m_targetSpace, prim_geom);
1983 } 1981 }
1984 1982
diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
index 43d852b..0456f56 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
@@ -188,8 +188,20 @@ namespace OpenSim.Region.Physics.OdePlugin
188 private d.NearCallback nearCallback; 188 private d.NearCallback nearCallback;
189 public d.TriCallback triCallback; 189 public d.TriCallback triCallback;
190 public d.TriArrayCallback triArrayCallback; 190 public d.TriArrayCallback triArrayCallback;
191
192 /// <summary>
193 /// Avatars in the physics scene.
194 /// </summary>
191 private readonly HashSet<OdeCharacter> _characters = new HashSet<OdeCharacter>(); 195 private readonly HashSet<OdeCharacter> _characters = new HashSet<OdeCharacter>();
196
197 /// <summary>
198 /// Prims in the physics scene.
199 /// </summary>
192 private readonly HashSet<OdePrim> _prims = new HashSet<OdePrim>(); 200 private readonly HashSet<OdePrim> _prims = new HashSet<OdePrim>();
201
202 /// <summary>
203 /// Prims in the physics scene that are subject to physics, not just collisions.
204 /// </summary>
193 private readonly HashSet<OdePrim> _activeprims = new HashSet<OdePrim>(); 205 private readonly HashSet<OdePrim> _activeprims = new HashSet<OdePrim>();
194 206
195 /// <summary> 207 /// <summary>
@@ -215,7 +227,14 @@ namespace OpenSim.Region.Physics.OdePlugin
215 /// </remarks> 227 /// </remarks>
216 private readonly HashSet<OdePrim> _taintedPrimH = new HashSet<OdePrim>(); 228 private readonly HashSet<OdePrim> _taintedPrimH = new HashSet<OdePrim>();
217 229
230 /// <summary>
231 /// Record a character that has taints to be processed.
232 /// </summary>
218 private readonly HashSet<OdeCharacter> _taintedActors = new HashSet<OdeCharacter>(); 233 private readonly HashSet<OdeCharacter> _taintedActors = new HashSet<OdeCharacter>();
234
235 /// <summary>
236 /// Keep record of contacts in the physics loop so that we can remove duplicates.
237 /// </summary>
219 private readonly List<d.ContactGeom> _perloopContact = new List<d.ContactGeom>(); 238 private readonly List<d.ContactGeom> _perloopContact = new List<d.ContactGeom>();
220 239
221 /// <summary> 240 /// <summary>
@@ -227,18 +246,58 @@ namespace OpenSim.Region.Physics.OdePlugin
227 /// A dictionary of collision event changes that are waiting to be processed. 246 /// A dictionary of collision event changes that are waiting to be processed.
228 /// </summary> 247 /// </summary>
229 private readonly Dictionary<uint, PhysicsActor> _collisionEventPrimChanges = new Dictionary<uint, PhysicsActor>(); 248 private readonly Dictionary<uint, PhysicsActor> _collisionEventPrimChanges = new Dictionary<uint, PhysicsActor>();
230 249
231 private readonly HashSet<OdeCharacter> _badCharacter = new HashSet<OdeCharacter>(); 250 /// <summary>
251 /// Maps a unique geometry id (a memory location) to a physics actor name.
252 /// </summary>
253 /// <remarks>
254 /// Only actors participating in collisions have geometries. This has to be maintained separately from
255 /// actor_name_map because terrain and water currently don't conceptually have a physics actor of their own
256 /// apart from the singleton PANull
257 /// </remarks>
232 public Dictionary<IntPtr, String> geom_name_map = new Dictionary<IntPtr, String>(); 258 public Dictionary<IntPtr, String> geom_name_map = new Dictionary<IntPtr, String>();
259
260 /// <summary>
261 /// Maps a unique geometry id (a memory location) to a physics actor.
262 /// </summary>
263 /// <remarks>
264 /// Only actors participating in collisions have geometries.
265 /// </remarks>
233 public Dictionary<IntPtr, PhysicsActor> actor_name_map = new Dictionary<IntPtr, PhysicsActor>(); 266 public Dictionary<IntPtr, PhysicsActor> actor_name_map = new Dictionary<IntPtr, PhysicsActor>();
267
268 /// <summary>
269 /// Defects list to remove characters that no longer have finite positions due to some other bug.
270 /// </summary>
271 /// <remarks>
272 /// Used repeatedly in Simulate() but initialized once here.
273 /// </remarks>
274 private readonly List<OdeCharacter> defects = new List<OdeCharacter>();
275
234 private bool m_NINJA_physics_joints_enabled = false; 276 private bool m_NINJA_physics_joints_enabled = false;
235 //private Dictionary<String, IntPtr> jointpart_name_map = new Dictionary<String,IntPtr>(); 277 //private Dictionary<String, IntPtr> jointpart_name_map = new Dictionary<String,IntPtr>();
236 private readonly Dictionary<String, List<PhysicsJoint>> joints_connecting_actor = new Dictionary<String, List<PhysicsJoint>>(); 278 private readonly Dictionary<String, List<PhysicsJoint>> joints_connecting_actor = new Dictionary<String, List<PhysicsJoint>>();
237 private d.ContactGeom[] contacts; 279 private d.ContactGeom[] contacts;
238 private readonly List<PhysicsJoint> requestedJointsToBeCreated = new List<PhysicsJoint>(); // lock only briefly. accessed by external code (to request new joints) and by OdeScene.Simulate() to move those joints into pending/active 280
239 private readonly List<PhysicsJoint> pendingJoints = new List<PhysicsJoint>(); // can lock for longer. accessed only by OdeScene. 281 /// <summary>
240 private readonly List<PhysicsJoint> activeJoints = new List<PhysicsJoint>(); // can lock for longer. accessed only by OdeScene. 282 /// Lock only briefly. accessed by external code (to request new joints) and by OdeScene.Simulate() to move those joints into pending/active
241 private readonly List<string> requestedJointsToBeDeleted = new List<string>(); // lock only briefly. accessed by external code (to request deletion of joints) and by OdeScene.Simulate() to move those joints out of pending/active 283 /// </summary>
284 private readonly List<PhysicsJoint> requestedJointsToBeCreated = new List<PhysicsJoint>();
285
286 /// <summary>
287 /// can lock for longer. accessed only by OdeScene.
288 /// </summary>
289 private readonly List<PhysicsJoint> pendingJoints = new List<PhysicsJoint>();
290
291 /// <summary>
292 /// can lock for longer. accessed only by OdeScene.
293 /// </summary>
294 private readonly List<PhysicsJoint> activeJoints = new List<PhysicsJoint>();
295
296 /// <summary>
297 /// lock only briefly. accessed by external code (to request deletion of joints) and by OdeScene.Simulate() to move those joints out of pending/active
298 /// </summary>
299 private readonly List<string> requestedJointsToBeDeleted = new List<string>();
300
242 private Object externalJointRequestsLock = new Object(); 301 private Object externalJointRequestsLock = new Object();
243 private readonly Dictionary<String, PhysicsJoint> SOPName_to_activeJoint = new Dictionary<String, PhysicsJoint>(); 302 private readonly Dictionary<String, PhysicsJoint> SOPName_to_activeJoint = new Dictionary<String, PhysicsJoint>();
244 private readonly Dictionary<String, PhysicsJoint> SOPName_to_pendingJoint = new Dictionary<String, PhysicsJoint>(); 303 private readonly Dictionary<String, PhysicsJoint> SOPName_to_pendingJoint = new Dictionary<String, PhysicsJoint>();
@@ -318,8 +377,7 @@ namespace OpenSim.Region.Physics.OdePlugin
318 /// <param value="name">Name of the scene. Useful in debug messages.</param> 377 /// <param value="name">Name of the scene. Useful in debug messages.</param>
319 public OdeScene(string name) 378 public OdeScene(string name)
320 { 379 {
321 m_log 380 m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.ToString() + "." + name);
322 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.ToString() + "." + name);
323 381
324 Name = name; 382 Name = name;
325 383
@@ -663,11 +721,11 @@ namespace OpenSim.Region.Physics.OdePlugin
663 } 721 }
664 } 722 }
665 723
666 internal void waitForSpaceUnlock(IntPtr space) 724// internal void waitForSpaceUnlock(IntPtr space)
667 { 725// {
668 //if (space != IntPtr.Zero) 726// //if (space != IntPtr.Zero)
669 //while (d.SpaceLockQuery(space)) { } // Wait and do nothing 727// //while (d.SpaceLockQuery(space)) { } // Wait and do nothing
670 } 728// }
671 729
672// /// <summary> 730// /// <summary>
673// /// Debug space message for printing the space that a prim/avatar is in. 731// /// Debug space message for printing the space that a prim/avatar is in.
@@ -710,7 +768,7 @@ namespace OpenSim.Region.Physics.OdePlugin
710 } 768 }
711 catch (AccessViolationException) 769 catch (AccessViolationException)
712 { 770 {
713 m_log.Warn("[PHYSICS]: Unable to collide test a space"); 771 m_log.Warn("[ODE SCENE]: Unable to collide test a space");
714 return; 772 return;
715 } 773 }
716 //Colliding a space or a geom with a space or a geom. so drill down 774 //Colliding a space or a geom with a space or a geom. so drill down
@@ -760,22 +818,19 @@ namespace OpenSim.Region.Physics.OdePlugin
760 if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact)) 818 if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
761 return; 819 return;
762 820
763 lock (contacts) 821 count = d.Collide(g1, g2, contacts.Length, contacts, d.ContactGeom.SizeOf);
764 { 822 if (count > contacts.Length)
765 count = d.Collide(g1, g2, contacts.Length, contacts, d.ContactGeom.SizeOf); 823 m_log.Error("[ODE SCENE]: Got " + count + " contacts when we asked for a maximum of " + contacts.Length);
766 if (count > contacts.Length)
767 m_log.Error("[PHYSICS]: Got " + count + " contacts when we asked for a maximum of " + contacts.Length);
768 }
769 } 824 }
770 catch (SEHException) 825 catch (SEHException)
771 { 826 {
772 m_log.Error( 827 m_log.Error(
773 "[PHYSICS]: The Operating system shut down ODE because of corrupt memory. This could be a result of really irregular terrain. If this repeats continuously, restart using Basic Physics and terrain fill your terrain. Restarting the sim."); 828 "[ODE SCENE]: The Operating system shut down ODE because of corrupt memory. This could be a result of really irregular terrain. If this repeats continuously, restart using Basic Physics and terrain fill your terrain. Restarting the sim.");
774 base.TriggerPhysicsBasedRestart(); 829 base.TriggerPhysicsBasedRestart();
775 } 830 }
776 catch (Exception e) 831 catch (Exception e)
777 { 832 {
778 m_log.WarnFormat("[PHYSICS]: Unable to collide test an object: {0}", e.Message); 833 m_log.WarnFormat("[ODE SCENE]: Unable to collide test an object: {0}", e.Message);
779 return; 834 return;
780 } 835 }
781 836
@@ -1029,6 +1084,8 @@ namespace OpenSim.Region.Physics.OdePlugin
1029 1084
1030 if (!skipThisContact) 1085 if (!skipThisContact)
1031 { 1086 {
1087 _perloopContact.Add(curContact);
1088
1032 // If we're colliding against terrain 1089 // If we're colliding against terrain
1033 if (name1 == "Terrain" || name2 == "Terrain") 1090 if (name1 == "Terrain" || name2 == "Terrain")
1034 { 1091 {
@@ -1038,7 +1095,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1038 { 1095 {
1039 // Use the movement terrain contact 1096 // Use the movement terrain contact
1040 AvatarMovementTerrainContact.geom = curContact; 1097 AvatarMovementTerrainContact.geom = curContact;
1041 _perloopContact.Add(curContact); 1098
1042 if (m_global_contactcount < maxContactsbeforedeath) 1099 if (m_global_contactcount < maxContactsbeforedeath)
1043 { 1100 {
1044 joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementTerrainContact); 1101 joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementTerrainContact);
@@ -1051,7 +1108,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1051 { 1108 {
1052 // Use the non moving terrain contact 1109 // Use the non moving terrain contact
1053 TerrainContact.geom = curContact; 1110 TerrainContact.geom = curContact;
1054 _perloopContact.Add(curContact); 1111
1055 if (m_global_contactcount < maxContactsbeforedeath) 1112 if (m_global_contactcount < maxContactsbeforedeath)
1056 { 1113 {
1057 joint = d.JointCreateContact(world, contactgroup, ref TerrainContact); 1114 joint = d.JointCreateContact(world, contactgroup, ref TerrainContact);
@@ -1077,7 +1134,6 @@ namespace OpenSim.Region.Physics.OdePlugin
1077 1134
1078 //m_log.DebugFormat("Material: {0}", material); 1135 //m_log.DebugFormat("Material: {0}", material);
1079 m_materialContacts[material, movintYN].geom = curContact; 1136 m_materialContacts[material, movintYN].geom = curContact;
1080 _perloopContact.Add(curContact);
1081 1137
1082 if (m_global_contactcount < maxContactsbeforedeath) 1138 if (m_global_contactcount < maxContactsbeforedeath)
1083 { 1139 {
@@ -1098,9 +1154,9 @@ namespace OpenSim.Region.Physics.OdePlugin
1098 1154
1099 if (p2 is OdePrim) 1155 if (p2 is OdePrim)
1100 material = ((OdePrim)p2).m_material; 1156 material = ((OdePrim)p2).m_material;
1157
1101 //m_log.DebugFormat("Material: {0}", material); 1158 //m_log.DebugFormat("Material: {0}", material);
1102 m_materialContacts[material, movintYN].geom = curContact; 1159 m_materialContacts[material, movintYN].geom = curContact;
1103 _perloopContact.Add(curContact);
1104 1160
1105 if (m_global_contactcount < maxContactsbeforedeath) 1161 if (m_global_contactcount < maxContactsbeforedeath)
1106 { 1162 {
@@ -1133,8 +1189,9 @@ namespace OpenSim.Region.Physics.OdePlugin
1133 //contact.normal = new d.Vector3(0, 0, 1); 1189 //contact.normal = new d.Vector3(0, 0, 1);
1134 //contact.pos = new d.Vector3(0, 0, contact.pos.Z - 5f); 1190 //contact.pos = new d.Vector3(0, 0, contact.pos.Z - 5f);
1135 } 1191 }
1192
1136 WaterContact.geom = curContact; 1193 WaterContact.geom = curContact;
1137 _perloopContact.Add(curContact); 1194
1138 if (m_global_contactcount < maxContactsbeforedeath) 1195 if (m_global_contactcount < maxContactsbeforedeath)
1139 { 1196 {
1140 joint = d.JointCreateContact(world, contactgroup, ref WaterContact); 1197 joint = d.JointCreateContact(world, contactgroup, ref WaterContact);
@@ -1152,7 +1209,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1152 { 1209 {
1153 // Use the Movement prim contact 1210 // Use the Movement prim contact
1154 AvatarMovementprimContact.geom = curContact; 1211 AvatarMovementprimContact.geom = curContact;
1155 _perloopContact.Add(curContact); 1212
1156 if (m_global_contactcount < maxContactsbeforedeath) 1213 if (m_global_contactcount < maxContactsbeforedeath)
1157 { 1214 {
1158 joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementprimContact); 1215 joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementprimContact);
@@ -1182,13 +1239,11 @@ namespace OpenSim.Region.Physics.OdePlugin
1182 1239
1183 //m_log.DebugFormat("Material: {0}", material); 1240 //m_log.DebugFormat("Material: {0}", material);
1184 m_materialContacts[material, 0].geom = curContact; 1241 m_materialContacts[material, 0].geom = curContact;
1185 _perloopContact.Add(curContact);
1186 1242
1187 if (m_global_contactcount < maxContactsbeforedeath) 1243 if (m_global_contactcount < maxContactsbeforedeath)
1188 { 1244 {
1189 joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, 0]); 1245 joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, 0]);
1190 m_global_contactcount++; 1246 m_global_contactcount++;
1191
1192 } 1247 }
1193 } 1248 }
1194 } 1249 }
@@ -1217,69 +1272,65 @@ namespace OpenSim.Region.Physics.OdePlugin
1217 1272
1218 private bool checkDupe(d.ContactGeom contactGeom, int atype) 1273 private bool checkDupe(d.ContactGeom contactGeom, int atype)
1219 { 1274 {
1220 bool result = false;
1221 //return result;
1222 if (!m_filterCollisions) 1275 if (!m_filterCollisions)
1223 return false; 1276 return false;
1224 1277
1278 bool result = false;
1279
1225 ActorTypes at = (ActorTypes)atype; 1280 ActorTypes at = (ActorTypes)atype;
1226 lock (_perloopContact) 1281
1282 foreach (d.ContactGeom contact in _perloopContact)
1227 { 1283 {
1228 foreach (d.ContactGeom contact in _perloopContact) 1284 //if ((contact.g1 == contactGeom.g1 && contact.g2 == contactGeom.g2))
1285 //{
1286 // || (contact.g2 == contactGeom.g1 && contact.g1 == contactGeom.g2)
1287 if (at == ActorTypes.Agent)
1229 { 1288 {
1230 //if ((contact.g1 == contactGeom.g1 && contact.g2 == contactGeom.g2)) 1289 if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f)
1231 //{ 1290 && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f)
1232 // || (contact.g2 == contactGeom.g1 && contact.g1 == contactGeom.g2) 1291 && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f))
1233 if (at == ActorTypes.Agent) 1292 && contactGeom.g1 != LandGeom && contactGeom.g2 != LandGeom)
1234 { 1293 {
1235 if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)) && contactGeom.g1 != LandGeom && contactGeom.g2 != LandGeom) 1294 if (Math.Abs(contact.depth - contactGeom.depth) < 0.052f)
1236 { 1295 {
1237 1296 //contactGeom.depth *= .00005f;
1238 if (Math.Abs(contact.depth - contactGeom.depth) < 0.052f) 1297 //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth));
1239 { 1298 // m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z));
1240 //contactGeom.depth *= .00005f; 1299 result = true;
1241 //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth)); 1300 break;
1242 // m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z)); 1301 }
1243 result = true; 1302// else
1244 break; 1303// {
1245 } 1304// //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth));
1246 else 1305// }
1247 { 1306 }
1248 //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth)); 1307// else
1249 } 1308// {
1250 } 1309// //m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z));
1251 else 1310// //int i = 0;
1252 { 1311// }
1253 //m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z)); 1312 }
1254 //int i = 0; 1313 else if (at == ActorTypes.Prim)
1255 } 1314 {
1256 } 1315 //d.AABB aabb1 = new d.AABB();
1257 else if (at == ActorTypes.Prim) 1316 //d.AABB aabb2 = new d.AABB();
1317
1318 //d.GeomGetAABB(contactGeom.g2, out aabb2);
1319 //d.GeomGetAABB(contactGeom.g1, out aabb1);
1320 //aabb1.
1321 if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)) && contactGeom.g1 != LandGeom && contactGeom.g2 != LandGeom)
1258 { 1322 {
1259 //d.AABB aabb1 = new d.AABB(); 1323 if (contactGeom.normal.X == contact.normal.X && contactGeom.normal.Y == contact.normal.Y && contactGeom.normal.Z == contact.normal.Z)
1260 //d.AABB aabb2 = new d.AABB(); 1324 {
1261 1325 if (Math.Abs(contact.depth - contactGeom.depth) < 0.272f)
1262 //d.GeomGetAABB(contactGeom.g2, out aabb2);
1263 //d.GeomGetAABB(contactGeom.g1, out aabb1);
1264 //aabb1.
1265 if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)) && contactGeom.g1 != LandGeom && contactGeom.g2 != LandGeom)
1266 { 1326 {
1267 if (contactGeom.normal.X == contact.normal.X && contactGeom.normal.Y == contact.normal.Y && contactGeom.normal.Z == contact.normal.Z) 1327 result = true;
1268 { 1328 break;
1269 if (Math.Abs(contact.depth - contactGeom.depth) < 0.272f)
1270 {
1271 result = true;
1272 break;
1273 }
1274 }
1275 //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth));
1276 //m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z));
1277 } 1329 }
1278 1330 }
1331 //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth));
1332 //m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z));
1279 } 1333 }
1280
1281 //}
1282
1283 } 1334 }
1284 } 1335 }
1285 1336
@@ -1482,90 +1533,77 @@ namespace OpenSim.Region.Physics.OdePlugin
1482 { 1533 {
1483 _perloopContact.Clear(); 1534 _perloopContact.Clear();
1484 1535
1485 lock (_characters) 1536 foreach (OdeCharacter chr in _characters)
1486 { 1537 {
1487 foreach (OdeCharacter chr in _characters) 1538 // Reset the collision values to false
1539 // since we don't know if we're colliding yet
1540 if (chr.Shell == IntPtr.Zero || chr.Body == IntPtr.Zero)
1541 continue;
1542
1543 chr.IsColliding = false;
1544 chr.CollidingGround = false;
1545 chr.CollidingObj = false;
1546
1547 // test the avatar's geometry for collision with the space
1548 // This will return near and the space that they are the closest to
1549 // And we'll run this again against the avatar and the space segment
1550 // This will return with a bunch of possible objects in the space segment
1551 // and we'll run it again on all of them.
1552 try
1488 { 1553 {
1489 // Reset the collision values to false 1554 d.SpaceCollide2(space, chr.Shell, IntPtr.Zero, nearCallback);
1490 // since we don't know if we're colliding yet
1491
1492 // For some reason this can happen. Don't ask...
1493 //
1494 if (chr == null)
1495 continue;
1496
1497 if (chr.Shell == IntPtr.Zero || chr.Body == IntPtr.Zero)
1498 continue;
1499
1500 chr.IsColliding = false;
1501 chr.CollidingGround = false;
1502 chr.CollidingObj = false;
1503
1504 // test the avatar's geometry for collision with the space
1505 // This will return near and the space that they are the closest to
1506 // And we'll run this again against the avatar and the space segment
1507 // This will return with a bunch of possible objects in the space segment
1508 // and we'll run it again on all of them.
1509 try
1510 {
1511 d.SpaceCollide2(space, chr.Shell, IntPtr.Zero, nearCallback);
1512 }
1513 catch (AccessViolationException)
1514 {
1515 m_log.Warn("[PHYSICS]: Unable to space collide");
1516 }
1517 //float terrainheight = GetTerrainHeightAtXY(chr.Position.X, chr.Position.Y);
1518 //if (chr.Position.Z + (chr.Velocity.Z * timeStep) < terrainheight + 10)
1519 //{
1520 //chr.Position.Z = terrainheight + 10.0f;
1521 //forcedZ = true;
1522 //}
1523 } 1555 }
1556 catch (AccessViolationException)
1557 {
1558 m_log.WarnFormat("[ODE SCENE]: Unable to space collide {0}", Name);
1559 }
1560
1561 //float terrainheight = GetTerrainHeightAtXY(chr.Position.X, chr.Position.Y);
1562 //if (chr.Position.Z + (chr.Velocity.Z * timeStep) < terrainheight + 10)
1563 //{
1564 //chr.Position.Z = terrainheight + 10.0f;
1565 //forcedZ = true;
1566 //}
1524 } 1567 }
1525 1568
1526 lock (_activeprims) 1569 List<OdePrim> removeprims = null;
1570 foreach (OdePrim chr in _activeprims)
1527 { 1571 {
1528 List<OdePrim> removeprims = null; 1572 if (chr.Body != IntPtr.Zero && d.BodyIsEnabled(chr.Body) && (!chr.m_disabled))
1529 foreach (OdePrim chr in _activeprims)
1530 { 1573 {
1531 if (chr.Body != IntPtr.Zero && d.BodyIsEnabled(chr.Body) && (!chr.m_disabled)) 1574 try
1532 { 1575 {
1533 try 1576 lock (chr)
1534 { 1577 {
1535 lock (chr) 1578 if (space != IntPtr.Zero && chr.prim_geom != IntPtr.Zero && chr.m_taintremove == false)
1536 { 1579 {
1537 if (space != IntPtr.Zero && chr.prim_geom != IntPtr.Zero && chr.m_taintremove == false) 1580 d.SpaceCollide2(space, chr.prim_geom, IntPtr.Zero, nearCallback);
1538 { 1581 }
1539 d.SpaceCollide2(space, chr.prim_geom, IntPtr.Zero, nearCallback); 1582 else
1540 } 1583 {
1541 else 1584 if (removeprims == null)
1542 { 1585 {
1543 if (removeprims == null) 1586 removeprims = new List<OdePrim>();
1544 {
1545 removeprims = new List<OdePrim>();
1546 }
1547 removeprims.Add(chr);
1548 m_log.Debug("[PHYSICS]: unable to collide test active prim against space. The space was zero, the geom was zero or it was in the process of being removed. Removed it from the active prim list. This needs to be fixed!");
1549 } 1587 }
1588 removeprims.Add(chr);
1589 m_log.Debug("[ODE SCENE]: unable to collide test active prim against space. The space was zero, the geom was zero or it was in the process of being removed. Removed it from the active prim list. This needs to be fixed!");
1550 } 1590 }
1551 } 1591 }
1552 catch (AccessViolationException)
1553 {
1554 m_log.Warn("[PHYSICS]: Unable to space collide");
1555 }
1556 } 1592 }
1557 } 1593 catch (AccessViolationException)
1558
1559 if (removeprims != null)
1560 {
1561 foreach (OdePrim chr in removeprims)
1562 { 1594 {
1563 _activeprims.Remove(chr); 1595 m_log.Warn("[ODE SCENE]: Unable to space collide");
1564 } 1596 }
1565 } 1597 }
1566 } 1598 }
1567 1599
1568 _perloopContact.Clear(); 1600 if (removeprims != null)
1601 {
1602 foreach (OdePrim chr in removeprims)
1603 {
1604 _activeprims.Remove(chr);
1605 }
1606 }
1569 } 1607 }
1570 1608
1571 #endregion 1609 #endregion
@@ -1685,35 +1723,29 @@ namespace OpenSim.Region.Physics.OdePlugin
1685 1723
1686 internal void AddCharacter(OdeCharacter chr) 1724 internal void AddCharacter(OdeCharacter chr)
1687 { 1725 {
1688 lock (_characters) 1726 if (!_characters.Contains(chr))
1689 { 1727 {
1690 if (!_characters.Contains(chr)) 1728 _characters.Add(chr);
1691 {
1692 _characters.Add(chr);
1693 if (chr.bad)
1694 m_log.DebugFormat("[PHYSICS] Added BAD actor {0} to characters list", chr.m_uuid);
1695 }
1696 }
1697 }
1698 1729
1699 internal void RemoveCharacter(OdeCharacter chr) 1730 if (chr.bad)
1700 { 1731 m_log.ErrorFormat("[ODE SCENE]: Added BAD actor {0} to characters list", chr.m_uuid);
1701 lock (_characters) 1732 }
1733 else
1702 { 1734 {
1703 if (_characters.Contains(chr)) 1735 m_log.ErrorFormat(
1704 { 1736 "[ODE SCENE]: Tried to add character {0} {1} but they are already in the set!",
1705 _characters.Remove(chr); 1737 chr.Name, chr.LocalID);
1706 }
1707 } 1738 }
1708 } 1739 }
1709 1740
1710 internal void BadCharacter(OdeCharacter chr) 1741 internal void RemoveCharacter(OdeCharacter chr)
1711 { 1742 {
1712 lock (_badCharacter) 1743 if (_characters.Contains(chr))
1713 { 1744 _characters.Remove(chr);
1714 if (!_badCharacter.Contains(chr)) 1745 else
1715 _badCharacter.Add(chr); 1746 m_log.ErrorFormat(
1716 } 1747 "[ODE SCENE]: Tried to remove character {0} {1} but they are not in the list!",
1748 chr.Name, chr.LocalID);
1717 } 1749 }
1718 1750
1719 private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation, 1751 private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation,
@@ -1742,13 +1774,10 @@ namespace OpenSim.Region.Physics.OdePlugin
1742 internal void ActivatePrim(OdePrim prim) 1774 internal void ActivatePrim(OdePrim prim)
1743 { 1775 {
1744 // adds active prim.. (ones that should be iterated over in collisions_optimized 1776 // adds active prim.. (ones that should be iterated over in collisions_optimized
1745 lock (_activeprims) 1777 if (!_activeprims.Contains(prim))
1746 { 1778 _activeprims.Add(prim);
1747 if (!_activeprims.Contains(prim)) 1779 //else
1748 _activeprims.Add(prim); 1780 // m_log.Warn("[PHYSICS]: Double Entry in _activeprims detected, potential crash immenent");
1749 //else
1750 // m_log.Warn("[PHYSICS]: Double Entry in _activeprims detected, potential crash immenent");
1751 }
1752 } 1781 }
1753 1782
1754 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, 1783 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
@@ -2027,7 +2056,6 @@ namespace OpenSim.Region.Physics.OdePlugin
2027 //m_log.Debug("RemoveAllJointsConnectedToActor: start"); 2056 //m_log.Debug("RemoveAllJointsConnectedToActor: start");
2028 if (actor.SOPName != null && joints_connecting_actor.ContainsKey(actor.SOPName) && joints_connecting_actor[actor.SOPName] != null) 2057 if (actor.SOPName != null && joints_connecting_actor.ContainsKey(actor.SOPName) && joints_connecting_actor[actor.SOPName] != null)
2029 { 2058 {
2030
2031 List<PhysicsJoint> jointsToRemove = new List<PhysicsJoint>(); 2059 List<PhysicsJoint> jointsToRemove = new List<PhysicsJoint>();
2032 //TODO: merge these 2 loops (originally it was needed to avoid altering a list being iterated over, but it is no longer needed due to the joint request queue mechanism) 2060 //TODO: merge these 2 loops (originally it was needed to avoid altering a list being iterated over, but it is no longer needed due to the joint request queue mechanism)
2033 foreach (PhysicsJoint j in joints_connecting_actor[actor.SOPName]) 2061 foreach (PhysicsJoint j in joints_connecting_actor[actor.SOPName])
@@ -2122,8 +2150,7 @@ namespace OpenSim.Region.Physics.OdePlugin
2122 /// <param name="prim"></param> 2150 /// <param name="prim"></param>
2123 internal void DeactivatePrim(OdePrim prim) 2151 internal void DeactivatePrim(OdePrim prim)
2124 { 2152 {
2125 lock (_activeprims) 2153 _activeprims.Remove(prim);
2126 _activeprims.Remove(prim);
2127 } 2154 }
2128 2155
2129 public override void RemovePrim(PhysicsActor prim) 2156 public override void RemovePrim(PhysicsActor prim)
@@ -2138,7 +2165,6 @@ namespace OpenSim.Region.Physics.OdePlugin
2138 2165
2139 p.setPrimForRemoval(); 2166 p.setPrimForRemoval();
2140 AddPhysicsActorTaint(prim); 2167 AddPhysicsActorTaint(prim);
2141 //RemovePrimThreadLocked(p);
2142 } 2168 }
2143 } 2169 }
2144 } 2170 }
@@ -2206,7 +2232,7 @@ namespace OpenSim.Region.Physics.OdePlugin
2206 //m_log.Warn(prim.prim_geom); 2232 //m_log.Warn(prim.prim_geom);
2207 2233
2208 if (!prim.RemoveGeom()) 2234 if (!prim.RemoveGeom())
2209 m_log.Warn("[PHYSICS]: Unable to remove prim from physics scene"); 2235 m_log.Warn("[ODE SCENE]: Unable to remove prim from physics scene");
2210 2236
2211 lock (_prims) 2237 lock (_prims)
2212 _prims.Remove(prim); 2238 _prims.Remove(prim);
@@ -2293,12 +2319,12 @@ namespace OpenSim.Region.Physics.OdePlugin
2293 { 2319 {
2294 if (d.GeomIsSpace(currentspace)) 2320 if (d.GeomIsSpace(currentspace))
2295 { 2321 {
2296 waitForSpaceUnlock(currentspace); 2322// waitForSpaceUnlock(currentspace);
2297 d.SpaceRemove(currentspace, geom); 2323 d.SpaceRemove(currentspace, geom);
2298 } 2324 }
2299 else 2325 else
2300 { 2326 {
2301 m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + currentspace + 2327 m_log.Info("[ODE SCENE]: Invalid Scene passed to 'recalculatespace':" + currentspace +
2302 " Geom:" + geom); 2328 " Geom:" + geom);
2303 } 2329 }
2304 } 2330 }
@@ -2309,12 +2335,12 @@ namespace OpenSim.Region.Physics.OdePlugin
2309 { 2335 {
2310 if (d.GeomIsSpace(currentspace)) 2336 if (d.GeomIsSpace(currentspace))
2311 { 2337 {
2312 waitForSpaceUnlock(sGeomIsIn); 2338// waitForSpaceUnlock(sGeomIsIn);
2313 d.SpaceRemove(sGeomIsIn, geom); 2339 d.SpaceRemove(sGeomIsIn, geom);
2314 } 2340 }
2315 else 2341 else
2316 { 2342 {
2317 m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + 2343 m_log.Info("[ODE SCENE]: Invalid Scene passed to 'recalculatespace':" +
2318 sGeomIsIn + " Geom:" + geom); 2344 sGeomIsIn + " Geom:" + geom);
2319 } 2345 }
2320 } 2346 }
@@ -2327,8 +2353,8 @@ namespace OpenSim.Region.Physics.OdePlugin
2327 { 2353 {
2328 if (d.GeomIsSpace(currentspace)) 2354 if (d.GeomIsSpace(currentspace))
2329 { 2355 {
2330 waitForSpaceUnlock(currentspace); 2356// waitForSpaceUnlock(currentspace);
2331 waitForSpaceUnlock(space); 2357// waitForSpaceUnlock(space);
2332 d.SpaceRemove(space, currentspace); 2358 d.SpaceRemove(space, currentspace);
2333 // free up memory used by the space. 2359 // free up memory used by the space.
2334 2360
@@ -2337,7 +2363,7 @@ namespace OpenSim.Region.Physics.OdePlugin
2337 } 2363 }
2338 else 2364 else
2339 { 2365 {
2340 m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + 2366 m_log.Info("[ODE SCENE]: Invalid Scene passed to 'recalculatespace':" +
2341 currentspace + " Geom:" + geom); 2367 currentspace + " Geom:" + geom);
2342 } 2368 }
2343 } 2369 }
@@ -2352,12 +2378,12 @@ namespace OpenSim.Region.Physics.OdePlugin
2352 { 2378 {
2353 if (d.GeomIsSpace(currentspace)) 2379 if (d.GeomIsSpace(currentspace))
2354 { 2380 {
2355 waitForSpaceUnlock(currentspace); 2381// waitForSpaceUnlock(currentspace);
2356 d.SpaceRemove(currentspace, geom); 2382 d.SpaceRemove(currentspace, geom);
2357 } 2383 }
2358 else 2384 else
2359 { 2385 {
2360 m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + 2386 m_log.Info("[ODE SCENE]: Invalid Scene passed to 'recalculatespace':" +
2361 currentspace + " Geom:" + geom); 2387 currentspace + " Geom:" + geom);
2362 } 2388 }
2363 } 2389 }
@@ -2368,12 +2394,12 @@ namespace OpenSim.Region.Physics.OdePlugin
2368 { 2394 {
2369 if (d.GeomIsSpace(sGeomIsIn)) 2395 if (d.GeomIsSpace(sGeomIsIn))
2370 { 2396 {
2371 waitForSpaceUnlock(sGeomIsIn); 2397// waitForSpaceUnlock(sGeomIsIn);
2372 d.SpaceRemove(sGeomIsIn, geom); 2398 d.SpaceRemove(sGeomIsIn, geom);
2373 } 2399 }
2374 else 2400 else
2375 { 2401 {
2376 m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + 2402 m_log.Info("[ODE SCENE]: Invalid Scene passed to 'recalculatespace':" +
2377 sGeomIsIn + " Geom:" + geom); 2403 sGeomIsIn + " Geom:" + geom);
2378 } 2404 }
2379 } 2405 }
@@ -2407,9 +2433,10 @@ namespace OpenSim.Region.Physics.OdePlugin
2407 // creating a new space for prim and inserting it into main space. 2433 // creating a new space for prim and inserting it into main space.
2408 staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY] = d.HashSpaceCreate(IntPtr.Zero); 2434 staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY] = d.HashSpaceCreate(IntPtr.Zero);
2409 d.GeomSetCategoryBits(staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY], (int)CollisionCategories.Space); 2435 d.GeomSetCategoryBits(staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY], (int)CollisionCategories.Space);
2410 waitForSpaceUnlock(space); 2436// waitForSpaceUnlock(space);
2411 d.SpaceSetSublevel(space, 1); 2437 d.SpaceSetSublevel(space, 1);
2412 d.SpaceAdd(space, staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY]); 2438 d.SpaceAdd(space, staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY]);
2439
2413 return staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY]; 2440 return staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY];
2414 } 2441 }
2415 2442
@@ -2584,15 +2611,17 @@ namespace OpenSim.Region.Physics.OdePlugin
2584 2611
2585 /// <summary> 2612 /// <summary>
2586 /// Called after our prim properties are set Scale, position etc. 2613 /// Called after our prim properties are set Scale, position etc.
2614 /// </summary>
2615 /// <remarks>
2587 /// We use this event queue like method to keep changes to the physical scene occuring in the threadlocked mutex 2616 /// We use this event queue like method to keep changes to the physical scene occuring in the threadlocked mutex
2588 /// This assures us that we have no race conditions 2617 /// This assures us that we have no race conditions
2589 /// </summary> 2618 /// </remarks>
2590 /// <param name="prim"></param> 2619 /// <param name="actor"></param>
2591 public override void AddPhysicsActorTaint(PhysicsActor prim) 2620 public override void AddPhysicsActorTaint(PhysicsActor actor)
2592 { 2621 {
2593 if (prim is OdePrim) 2622 if (actor is OdePrim)
2594 { 2623 {
2595 OdePrim taintedprim = ((OdePrim) prim); 2624 OdePrim taintedprim = ((OdePrim)actor);
2596 lock (_taintedPrimLock) 2625 lock (_taintedPrimLock)
2597 { 2626 {
2598 if (!(_taintedPrimH.Contains(taintedprim))) 2627 if (!(_taintedPrimH.Contains(taintedprim)))
@@ -2604,18 +2633,17 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
2604 _taintedPrimL.Add(taintedprim); // List for ordered readout 2633 _taintedPrimL.Add(taintedprim); // List for ordered readout
2605 } 2634 }
2606 } 2635 }
2607 return;
2608 } 2636 }
2609 else if (prim is OdeCharacter) 2637 else if (actor is OdeCharacter)
2610 { 2638 {
2611 OdeCharacter taintedchar = ((OdeCharacter)prim); 2639 OdeCharacter taintedchar = ((OdeCharacter)actor);
2612 lock (_taintedActors) 2640 lock (_taintedActors)
2613 { 2641 {
2614 if (!(_taintedActors.Contains(taintedchar))) 2642 if (!(_taintedActors.Contains(taintedchar)))
2615 { 2643 {
2616 _taintedActors.Add(taintedchar); 2644 _taintedActors.Add(taintedchar);
2617 if (taintedchar.bad) 2645 if (taintedchar.bad)
2618 m_log.DebugFormat("[PHYSICS]: Added BAD actor {0} to tainted actors", taintedchar.m_uuid); 2646 m_log.DebugFormat("[ODE SCENE]: Added BAD actor {0} to tainted actors", taintedchar.m_uuid);
2619 } 2647 }
2620 } 2648 }
2621 } 2649 }
@@ -2711,29 +2739,18 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
2711 { 2739 {
2712 try 2740 try
2713 { 2741 {
2714 // Insert, remove Characters
2715 bool processedtaints = false;
2716
2717 lock (_taintedActors) 2742 lock (_taintedActors)
2718 { 2743 {
2719 if (_taintedActors.Count > 0) 2744 if (_taintedActors.Count > 0)
2720 { 2745 {
2721 foreach (OdeCharacter character in _taintedActors) 2746 foreach (OdeCharacter character in _taintedActors)
2722 {
2723 character.ProcessTaints(); 2747 character.ProcessTaints();
2724 2748
2725 processedtaints = true; 2749 if (_taintedActors.Count > 0)
2726 //character.m_collisionscore = 0;
2727 }
2728
2729 if (processedtaints)
2730 _taintedActors.Clear(); 2750 _taintedActors.Clear();
2731 } 2751 }
2732 } 2752 }
2733 2753
2734 // Modify other objects in the scene.
2735 processedtaints = false;
2736
2737 lock (_taintedPrimLock) 2754 lock (_taintedPrimLock)
2738 { 2755 {
2739 foreach (OdePrim prim in _taintedPrimL) 2756 foreach (OdePrim prim in _taintedPrimL)
@@ -2749,7 +2766,6 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
2749 prim.ProcessTaints(); 2766 prim.ProcessTaints();
2750 } 2767 }
2751 2768
2752 processedtaints = true;
2753 prim.m_collisionscore = 0; 2769 prim.m_collisionscore = 0;
2754 2770
2755 // This loop can block up the Heartbeat for a very long time on large regions. 2771 // This loop can block up the Heartbeat for a very long time on large regions.
@@ -2762,7 +2778,7 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
2762 if (SupportsNINJAJoints) 2778 if (SupportsNINJAJoints)
2763 SimulatePendingNINJAJoints(); 2779 SimulatePendingNINJAJoints();
2764 2780
2765 if (processedtaints) 2781 if (_taintedPrimL.Count > 0)
2766 { 2782 {
2767//Console.WriteLine("Simulate calls Clear of _taintedPrim list"); 2783//Console.WriteLine("Simulate calls Clear of _taintedPrim list");
2768 _taintedPrimH.Clear(); 2784 _taintedPrimH.Clear();
@@ -2771,31 +2787,25 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
2771 } 2787 }
2772 2788
2773 // Move characters 2789 // Move characters
2774 lock (_characters) 2790 foreach (OdeCharacter actor in _characters)
2791 actor.Move(defects);
2792
2793 if (defects.Count != 0)
2775 { 2794 {
2776 List<OdeCharacter> defects = new List<OdeCharacter>(); 2795 foreach (OdeCharacter actor in defects)
2777 foreach (OdeCharacter actor in _characters)
2778 {
2779 if (actor != null)
2780 actor.Move(defects);
2781 }
2782 if (0 != defects.Count)
2783 { 2796 {
2784 foreach (OdeCharacter defect in defects) 2797 RemoveCharacter(actor);
2785 { 2798 actor.DestroyOdeStructures();
2786 RemoveCharacter(defect);
2787 }
2788 } 2799 }
2800
2801 defects.Clear();
2789 } 2802 }
2790 2803
2791 // Move other active objects 2804 // Move other active objects
2792 lock (_activeprims) 2805 foreach (OdePrim prim in _activeprims)
2793 { 2806 {
2794 foreach (OdePrim prim in _activeprims) 2807 prim.m_collisionscore = 0;
2795 { 2808 prim.Move(timeStep);
2796 prim.m_collisionscore = 0;
2797 prim.Move(timeStep);
2798 }
2799 } 2809 }
2800 2810
2801 //if ((framecount % m_randomizeWater) == 0) 2811 //if ((framecount % m_randomizeWater) == 0)
@@ -2836,53 +2846,41 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
2836 } 2846 }
2837 catch (Exception e) 2847 catch (Exception e)
2838 { 2848 {
2839 m_log.ErrorFormat("[PHYSICS]: {0}, {1}, {2}", e.Message, e.TargetSite, e); 2849 m_log.ErrorFormat("[ODE SCENE]: {0}, {1}, {2}", e.Message, e.TargetSite, e);
2840 } 2850 }
2841 2851
2842 timeLeft -= ODE_STEPSIZE; 2852 timeLeft -= ODE_STEPSIZE;
2843 } 2853 }
2844 2854
2845 lock (_characters) 2855 foreach (OdeCharacter actor in _characters)
2846 { 2856 {
2847 foreach (OdeCharacter actor in _characters) 2857 if (actor.bad)
2848 { 2858 m_log.WarnFormat("[ODE SCENE]: BAD Actor {0} in _characters list was not removed?", actor.m_uuid);
2849 if (actor != null)
2850 {
2851 if (actor.bad)
2852 m_log.WarnFormat("[PHYSICS]: BAD Actor {0} in _characters list was not removed?", actor.m_uuid);
2853 2859
2854 actor.UpdatePositionAndVelocity(); 2860 actor.UpdatePositionAndVelocity(defects);
2855 }
2856 }
2857 } 2861 }
2858 2862
2859 lock (_badCharacter) 2863 if (defects.Count != 0)
2860 { 2864 {
2861 if (_badCharacter.Count > 0) 2865 foreach (OdeCharacter actor in defects)
2862 { 2866 {
2863 foreach (OdeCharacter chr in _badCharacter) 2867 RemoveCharacter(actor);
2864 { 2868 actor.DestroyOdeStructures();
2865 RemoveCharacter(chr);
2866 }
2867
2868 _badCharacter.Clear();
2869 } 2869 }
2870
2871 defects.Clear();
2870 } 2872 }
2871 2873
2872 lock (_activeprims) 2874 //if (timeStep < 0.2f)
2875
2876 foreach (OdePrim prim in _activeprims)
2873 { 2877 {
2874 //if (timeStep < 0.2f) 2878 if (prim.IsPhysical && (d.BodyIsEnabled(prim.Body) || !prim._zeroFlag))
2875 { 2879 {
2876 foreach (OdePrim prim in _activeprims) 2880 prim.UpdatePositionAndVelocity();
2877 {
2878 if (prim.IsPhysical && (d.BodyIsEnabled(prim.Body) || !prim._zeroFlag))
2879 {
2880 prim.UpdatePositionAndVelocity();
2881 2881
2882 if (SupportsNINJAJoints) 2882 if (SupportsNINJAJoints)
2883 SimulateActorPendingJoints(prim); 2883 SimulateActorPendingJoints(prim);
2884 }
2885 }
2886 } 2884 }
2887 } 2885 }
2888 2886
@@ -3417,7 +3415,7 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
3417 { 3415 {
3418 if (Single.IsNaN(resultarr2[y, x]) || Single.IsInfinity(resultarr2[y, x])) 3416 if (Single.IsNaN(resultarr2[y, x]) || Single.IsInfinity(resultarr2[y, x]))
3419 { 3417 {
3420 m_log.Warn("[PHYSICS]: Non finite heightfield element detected. Setting it to 0"); 3418 m_log.Warn("[ODE SCENE]: Non finite heightfield element detected. Setting it to 0");
3421 resultarr2[y, x] = 0; 3419 resultarr2[y, x] = 0;
3422 } 3420 }
3423 returnarr[i] = resultarr2[y, x]; 3421 returnarr[i] = resultarr2[y, x];
@@ -3448,7 +3446,7 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
3448 private void SetTerrain(float[] heightMap, Vector3 pOffset) 3446 private void SetTerrain(float[] heightMap, Vector3 pOffset)
3449 { 3447 {
3450 int startTime = Util.EnvironmentTickCount(); 3448 int startTime = Util.EnvironmentTickCount();
3451 m_log.DebugFormat("[PHYSICS]: Setting terrain for {0}", Name); 3449 m_log.DebugFormat("[ODE SCENE]: Setting terrain for {0}", Name);
3452 3450
3453 // this._heightmap[i] = (double)heightMap[i]; 3451 // this._heightmap[i] = (double)heightMap[i];
3454 // dbm (danx0r) -- creating a buffer zone of one extra sample all around 3452 // dbm (danx0r) -- creating a buffer zone of one extra sample all around
@@ -3573,7 +3571,7 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
3573 } 3571 }
3574 3572
3575 m_log.DebugFormat( 3573 m_log.DebugFormat(
3576 "[PHYSICS]: Setting terrain for {0} took {1}ms", Name, Util.EnvironmentTickCountSubtract(startTime)); 3574 "[ODE SCENE]: Setting terrain for {0} took {1}ms", Name, Util.EnvironmentTickCountSubtract(startTime));
3577 } 3575 }
3578 3576
3579 public override void DeleteTerrain() 3577 public override void DeleteTerrain()
@@ -3590,64 +3588,64 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
3590 return true; 3588 return true;
3591 } 3589 }
3592 3590
3593 public override void UnCombine(PhysicsScene pScene) 3591// public override void UnCombine(PhysicsScene pScene)
3594 { 3592// {
3595 IntPtr localGround = IntPtr.Zero; 3593// IntPtr localGround = IntPtr.Zero;
3596// float[] localHeightfield; 3594//// float[] localHeightfield;
3597 bool proceed = false; 3595// bool proceed = false;
3598 List<IntPtr> geomDestroyList = new List<IntPtr>(); 3596// List<IntPtr> geomDestroyList = new List<IntPtr>();
3599 3597//
3600 lock (OdeLock) 3598// lock (OdeLock)
3601 { 3599// {
3602 if (RegionTerrain.TryGetValue(Vector3.Zero, out localGround)) 3600// if (RegionTerrain.TryGetValue(Vector3.Zero, out localGround))
3603 { 3601// {
3604 foreach (IntPtr geom in TerrainHeightFieldHeights.Keys) 3602// foreach (IntPtr geom in TerrainHeightFieldHeights.Keys)
3605 { 3603// {
3606 if (geom == localGround) 3604// if (geom == localGround)
3607 { 3605// {
3608// localHeightfield = TerrainHeightFieldHeights[geom]; 3606//// localHeightfield = TerrainHeightFieldHeights[geom];
3609 proceed = true; 3607// proceed = true;
3610 } 3608// }
3611 else 3609// else
3612 { 3610// {
3613 geomDestroyList.Add(geom); 3611// geomDestroyList.Add(geom);
3614 } 3612// }
3615 } 3613// }
3616 3614//
3617 if (proceed) 3615// if (proceed)
3618 { 3616// {
3619 m_worldOffset = Vector3.Zero; 3617// m_worldOffset = Vector3.Zero;
3620 WorldExtents = new Vector2((int)Constants.RegionSize, (int)Constants.RegionSize); 3618// WorldExtents = new Vector2((int)Constants.RegionSize, (int)Constants.RegionSize);
3621 m_parentScene = null; 3619// m_parentScene = null;
3622 3620//
3623 foreach (IntPtr g in geomDestroyList) 3621// foreach (IntPtr g in geomDestroyList)
3624 { 3622// {
3625 // removingHeightField needs to be done or the garbage collector will 3623// // removingHeightField needs to be done or the garbage collector will
3626 // collect the terrain data before we tell ODE to destroy it causing 3624// // collect the terrain data before we tell ODE to destroy it causing
3627 // memory corruption 3625// // memory corruption
3628 if (TerrainHeightFieldHeights.ContainsKey(g)) 3626// if (TerrainHeightFieldHeights.ContainsKey(g))
3629 { 3627// {
3630// float[] removingHeightField = TerrainHeightFieldHeights[g]; 3628//// float[] removingHeightField = TerrainHeightFieldHeights[g];
3631 TerrainHeightFieldHeights.Remove(g); 3629// TerrainHeightFieldHeights.Remove(g);
3632 3630//
3633 if (RegionTerrain.ContainsKey(g)) 3631// if (RegionTerrain.ContainsKey(g))
3634 { 3632// {
3635 RegionTerrain.Remove(g); 3633// RegionTerrain.Remove(g);
3636 } 3634// }
3637 3635//
3638 d.GeomDestroy(g); 3636// d.GeomDestroy(g);
3639 //removingHeightField = new float[0]; 3637// //removingHeightField = new float[0];
3640 } 3638// }
3641 } 3639// }
3642 3640//
3643 } 3641// }
3644 else 3642// else
3645 { 3643// {
3646 m_log.Warn("[PHYSICS]: Couldn't proceed with UnCombine. Region has inconsistant data."); 3644// m_log.Warn("[PHYSICS]: Couldn't proceed with UnCombine. Region has inconsistant data.");
3647 } 3645// }
3648 } 3646// }
3649 } 3647// }
3650 } 3648// }
3651 3649
3652 public override void SetWaterLevel(float baseheight) 3650 public override void SetWaterLevel(float baseheight)
3653 { 3651 {
@@ -3894,30 +3892,28 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
3894 } 3892 }
3895 } 3893 }
3896 ds.SetColor(1.0f, 0.0f, 0.0f); 3894 ds.SetColor(1.0f, 0.0f, 0.0f);
3897 lock (_characters) 3895
3896 foreach (OdeCharacter chr in _characters)
3898 { 3897 {
3899 foreach (OdeCharacter chr in _characters) 3898 if (chr.Shell != IntPtr.Zero)
3900 { 3899 {
3901 if (chr.Shell != IntPtr.Zero) 3900 IntPtr body = d.GeomGetBody(chr.Shell);
3902 {
3903 IntPtr body = d.GeomGetBody(chr.Shell);
3904 3901
3905 d.Vector3 pos; 3902 d.Vector3 pos;
3906 d.GeomCopyPosition(chr.Shell, out pos); 3903 d.GeomCopyPosition(chr.Shell, out pos);
3907 //d.BodyCopyPosition(body, out pos); 3904 //d.BodyCopyPosition(body, out pos);
3908 3905
3909 d.Matrix3 R; 3906 d.Matrix3 R;
3910 d.GeomCopyRotation(chr.Shell, out R); 3907 d.GeomCopyRotation(chr.Shell, out R);
3911 //d.BodyCopyRotation(body, out R); 3908 //d.BodyCopyRotation(body, out R);
3912 3909
3913 ds.DrawCapsule(ref pos, ref R, chr.Size.Z, 0.35f); 3910 ds.DrawCapsule(ref pos, ref R, chr.Size.Z, 0.35f);
3914 d.Vector3 sides = new d.Vector3(); 3911 d.Vector3 sides = new d.Vector3();
3915 sides.X = 0.5f; 3912 sides.X = 0.5f;
3916 sides.Y = 0.5f; 3913 sides.Y = 0.5f;
3917 sides.Z = 0.5f; 3914 sides.Z = 0.5f;
3918 3915
3919 ds.DrawBox(ref pos, ref R, ref sides); 3916 ds.DrawBox(ref pos, ref R, ref sides);
3920 }
3921 } 3917 }
3922 } 3918 }
3923 } 3919 }