From 7480f2fd0e5482d366890b34d4aca72c887e02c3 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 21 Nov 2011 21:04:24 +0000 Subject: Restore defects list. In hindsight, the reason for this is becuase we can't remove the character whilst iterating over the list. This commit also removes locking on OdeScene._characters since code is single threaded --- OpenSim/Region/Physics/OdePlugin/ODECharacter.cs | 27 ++-- OpenSim/Region/Physics/OdePlugin/OdeScene.cs | 177 +++++++++++++---------- 2 files changed, 112 insertions(+), 92 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs index 5a7626e..cfe64f2 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs @@ -862,11 +862,10 @@ namespace OpenSim.Region.Physics.OdePlugin /// Called from Simulate /// This is the avatar's movement control + PID Controller /// - /// - /// This routine will remove the character from the physics scene if it detects something wrong (non-finite + /// The character will be added to this list if there is something wrong (non-finite /// position or velocity). - /// - internal void Move() + /// + internal void Move(List defects) { // no lock; for now it's only called from within Simulate() @@ -891,8 +890,7 @@ namespace OpenSim.Region.Physics.OdePlugin "[ODE CHARACTER]: Avatar position of {0} for {1} is non-finite! Removing from physics scene.", localPos, Name); - _parent_scene.RemoveCharacter(this); - DestroyOdeStructures(); + defects.Add(this); return; } @@ -1031,15 +1029,19 @@ namespace OpenSim.Region.Physics.OdePlugin "[ODE CHARACTER]: Got a NaN force vector {0} in Move() for {1}. Removing character from physics scene.", vec, Name); - _parent_scene.RemoveCharacter(this); - DestroyOdeStructures(); + defects.Add(this); + + return; } } /// /// Updates the reported position and velocity. This essentially sends the data up to ScenePresence. /// - internal void UpdatePositionAndVelocity() + /// The character will be added to this list if there is something wrong (non-finite + /// position or velocity). + /// + internal void UpdatePositionAndVelocity(List defects) { // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit! d.Vector3 newPos; @@ -1050,11 +1052,12 @@ namespace OpenSim.Region.Physics.OdePlugin catch (NullReferenceException) { bad = true; - _parent_scene.RemoveCharacter(this); - DestroyOdeStructures(); + defects.Add(this); newPos = new d.Vector3(_position.X, _position.Y, _position.Z); base.RaiseOutOfBounds(_position); // Tells ScenePresence that there's a problem! m_log.WarnFormat("[ODE CHARACTER]: Avatar Null reference for Avatar {0}, physical actor {1}", Name, m_uuid); + + return; } // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!) @@ -1134,7 +1137,7 @@ namespace OpenSim.Region.Physics.OdePlugin /// /// Used internally to destroy the ODE structures associated with this character. /// - private void DestroyOdeStructures() + internal void DestroyOdeStructures() { // destroy avatar capsule and related ODE data if (Amotor != IntPtr.Zero) diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs index 7db188f..89568b6 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs @@ -189,7 +189,11 @@ namespace OpenSim.Region.Physics.OdePlugin public d.TriCallback triCallback; public d.TriArrayCallback triArrayCallback; + /// + /// Avatars in the physics scene. + /// private readonly HashSet _characters = new HashSet(); + private readonly HashSet _prims = new HashSet(); private readonly HashSet _activeprims = new HashSet(); @@ -254,6 +258,14 @@ namespace OpenSim.Region.Physics.OdePlugin /// public Dictionary actor_name_map = new Dictionary(); + /// + /// Defects list to remove characters that no longer have finite positions due to some other bug. + /// + /// + /// Used repeatedly in Simulate() but initialized once here. + /// + private readonly List defects = new List(); + private bool m_NINJA_physics_joints_enabled = false; //private Dictionary jointpart_name_map = new Dictionary(); private readonly Dictionary> joints_connecting_actor = new Dictionary>(); @@ -1515,45 +1527,42 @@ namespace OpenSim.Region.Physics.OdePlugin { _perloopContact.Clear(); - lock (_characters) + foreach (OdeCharacter chr in _characters) { - foreach (OdeCharacter chr in _characters) + // Reset the collision values to false + // since we don't know if we're colliding yet + + // For some reason this can happen. Don't ask... + // + if (chr == null) + continue; + + if (chr.Shell == IntPtr.Zero || chr.Body == IntPtr.Zero) + continue; + + chr.IsColliding = false; + chr.CollidingGround = false; + chr.CollidingObj = false; + + // test the avatar's geometry for collision with the space + // This will return near and the space that they are the closest to + // And we'll run this again against the avatar and the space segment + // This will return with a bunch of possible objects in the space segment + // and we'll run it again on all of them. + try { - // Reset the collision values to false - // since we don't know if we're colliding yet - - // For some reason this can happen. Don't ask... - // - if (chr == null) - continue; - - if (chr.Shell == IntPtr.Zero || chr.Body == IntPtr.Zero) - continue; - - chr.IsColliding = false; - chr.CollidingGround = false; - chr.CollidingObj = false; - - // test the avatar's geometry for collision with the space - // This will return near and the space that they are the closest to - // And we'll run this again against the avatar and the space segment - // This will return with a bunch of possible objects in the space segment - // and we'll run it again on all of them. - try - { - d.SpaceCollide2(space, chr.Shell, IntPtr.Zero, nearCallback); - } - catch (AccessViolationException) - { - m_log.Warn("[PHYSICS]: Unable to space collide"); - } - //float terrainheight = GetTerrainHeightAtXY(chr.Position.X, chr.Position.Y); - //if (chr.Position.Z + (chr.Velocity.Z * timeStep) < terrainheight + 10) - //{ - //chr.Position.Z = terrainheight + 10.0f; - //forcedZ = true; - //} + d.SpaceCollide2(space, chr.Shell, IntPtr.Zero, nearCallback); + } + catch (AccessViolationException) + { + m_log.Warn("[PHYSICS]: Unable to space collide"); } + //float terrainheight = GetTerrainHeightAtXY(chr.Position.X, chr.Position.Y); + //if (chr.Position.Z + (chr.Velocity.Z * timeStep) < terrainheight + 10) + //{ + //chr.Position.Z = terrainheight + 10.0f; + //forcedZ = true; + //} } lock (_activeprims) @@ -1716,28 +1725,22 @@ namespace OpenSim.Region.Physics.OdePlugin internal void AddCharacter(OdeCharacter chr) { - lock (_characters) + if (!_characters.Contains(chr)) { - if (!_characters.Contains(chr)) - { - _characters.Add(chr); + _characters.Add(chr); - if (chr.bad) - m_log.ErrorFormat("[PHYSICS] Added BAD actor {0} to characters list", chr.m_uuid); - } + if (chr.bad) + m_log.ErrorFormat("[PHYSICS] Added BAD actor {0} to characters list", chr.m_uuid); } } internal void RemoveCharacter(OdeCharacter chr) { - lock (_characters) + if (_characters.Contains(chr)) { - if (_characters.Contains(chr)) - { - _characters.Remove(chr); - geom_name_map.Remove(chr.Shell); - actor_name_map.Remove(chr.Shell); - } + _characters.Remove(chr); + geom_name_map.Remove(chr.Shell); + actor_name_map.Remove(chr.Shell); } } @@ -2797,13 +2800,21 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name); } // Move characters - lock (_characters) + foreach (OdeCharacter actor in _characters) { - foreach (OdeCharacter actor in _characters) + if (actor != null) + actor.Move(defects); + } + + if (defects.Count != 0) + { + foreach (OdeCharacter actor in defects) { - if (actor != null) - actor.Move(); + RemoveCharacter(actor); + actor.DestroyOdeStructures(); } + + defects.Clear(); } // Move other active objects @@ -2860,18 +2871,26 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name); timeLeft -= ODE_STEPSIZE; } - lock (_characters) + foreach (OdeCharacter actor in _characters) { - foreach (OdeCharacter actor in _characters) + if (actor != null) { - if (actor != null) - { - if (actor.bad) - m_log.WarnFormat("[PHYSICS]: BAD Actor {0} in _characters list was not removed?", actor.m_uuid); + if (actor.bad) + m_log.WarnFormat("[PHYSICS]: BAD Actor {0} in _characters list was not removed?", actor.m_uuid); - actor.UpdatePositionAndVelocity(); - } + actor.UpdatePositionAndVelocity(defects); + } + } + + if (defects.Count != 0) + { + foreach (OdeCharacter actor in defects) + { + RemoveCharacter(actor); + actor.DestroyOdeStructures(); } + + defects.Clear(); } lock (_activeprims) @@ -3899,30 +3918,28 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name); } } ds.SetColor(1.0f, 0.0f, 0.0f); - lock (_characters) + + foreach (OdeCharacter chr in _characters) { - foreach (OdeCharacter chr in _characters) + if (chr.Shell != IntPtr.Zero) { - if (chr.Shell != IntPtr.Zero) - { - IntPtr body = d.GeomGetBody(chr.Shell); + IntPtr body = d.GeomGetBody(chr.Shell); - d.Vector3 pos; - d.GeomCopyPosition(chr.Shell, out pos); - //d.BodyCopyPosition(body, out pos); + d.Vector3 pos; + d.GeomCopyPosition(chr.Shell, out pos); + //d.BodyCopyPosition(body, out pos); - d.Matrix3 R; - d.GeomCopyRotation(chr.Shell, out R); - //d.BodyCopyRotation(body, out R); + d.Matrix3 R; + d.GeomCopyRotation(chr.Shell, out R); + //d.BodyCopyRotation(body, out R); - ds.DrawCapsule(ref pos, ref R, chr.Size.Z, 0.35f); - d.Vector3 sides = new d.Vector3(); - sides.X = 0.5f; - sides.Y = 0.5f; - sides.Z = 0.5f; + ds.DrawCapsule(ref pos, ref R, chr.Size.Z, 0.35f); + d.Vector3 sides = new d.Vector3(); + sides.X = 0.5f; + sides.Y = 0.5f; + sides.Z = 0.5f; - ds.DrawBox(ref pos, ref R, ref sides); - } + ds.DrawBox(ref pos, ref R, ref sides); } } } -- cgit v1.1