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')
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