From 7f80eff06732969f0d7f89e8774fc212123557e6 Mon Sep 17 00:00:00 2001
From: Teravus Ovares
Date: Wed, 10 Dec 2008 23:46:20 +0000
Subject: * Committing a slightly distilled version of nlin's ODECharacter race
condition eliminator. * The modifications that I made were only so that it
didn't require changes to the public physics api.
---
OpenSim/Region/Physics/OdePlugin/ODECharacter.cs | 134 ++++++++++++++++-------
OpenSim/Region/Physics/OdePlugin/OdePlugin.cs | 50 +++++++--
2 files changed, 139 insertions(+), 45 deletions(-)
(limited to 'OpenSim')
diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
index 6957cca..666fa86 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
@@ -26,10 +26,12 @@
*/
using System;
+using System.Reflection;
using OpenMetaverse;
using Ode.NET;
using OpenSim.Framework;
using OpenSim.Region.Physics.Manager;
+using log4net;
namespace OpenSim.Region.Physics.OdePlugin
{
@@ -55,7 +57,7 @@ namespace OpenSim.Region.Physics.OdePlugin
}
public class OdeCharacter : PhysicsActor
{
- //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
+ private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private PhysicsVector _position;
private d.Vector3 _zeroPosition;
@@ -89,6 +91,10 @@ namespace OpenSim.Region.Physics.OdePlugin
private bool m_hackSentFly = false;
public uint m_localID = 0;
public bool m_returnCollisions = false;
+ // taints and their non-tainted counterparts
+ public bool m_isPhysical = false; // the current physical status
+ public bool m_tainted_isPhysical = false; // set when the physical status is tainted (false=not existing in physics engine, true=existing)
+ private float m_tainted_CAPSULE_LENGTH; // set when the capsule length changes.
private float m_buoyancy = 0f;
@@ -108,10 +114,10 @@ namespace OpenSim.Region.Physics.OdePlugin
| CollisionCategories.Body
| CollisionCategories.Character
| CollisionCategories.Land);
- public IntPtr Body;
+ public IntPtr Body = IntPtr.Zero;
private OdeScene _parent_scene;
- public IntPtr Shell;
- public IntPtr Amotor;
+ public IntPtr Shell = IntPtr.Zero;
+ public IntPtr Amotor = IntPtr.Zero;
public d.Mass ShellMass;
public bool collidelock = false;
@@ -147,14 +153,16 @@ namespace OpenSim.Region.Physics.OdePlugin
}
CAPSULE_LENGTH = (size.Z * 1.15f) - CAPSULE_RADIUS * 2.0f;
//m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString());
+ m_tainted_CAPSULE_LENGTH = CAPSULE_LENGTH;
+
+ m_isPhysical = false; // current status: no ODE information exists
+ m_tainted_isPhysical = true; // new tainted status: need to create ODE information
lock (_parent_scene.OdeLock)
{
- AvatarGeomAndBodyCreation(pos.X, pos.Y, pos.Z, m_tensor);
+ _parent_scene.AddPhysicsActorTaint(this);
}
m_name = avName;
- parent_scene.geom_name_map[Shell] = avName;
- parent_scene.actor_name_map[Shell] = (PhysicsActor) this;
}
public override int PhysicsActorType
@@ -389,27 +397,13 @@ namespace OpenSim.Region.Physics.OdePlugin
m_pidControllerActive = true;
lock (_parent_scene.OdeLock)
{
- d.JointDestroy(Amotor);
-
PhysicsVector SetSize = value;
- float prevCapsule = CAPSULE_LENGTH;
- // float capsuleradius = CAPSULE_RADIUS;
- //capsuleradius = 0.2f;
-
- CAPSULE_LENGTH = (SetSize.Z * 1.15f) - CAPSULE_RADIUS * 2.0f;
+ m_tainted_CAPSULE_LENGTH = (SetSize.Z * 1.15f) - CAPSULE_RADIUS * 2.0f;
//m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString());
- d.BodyDestroy(Body);
-
- _parent_scene.waitForSpaceUnlock(_parent_scene.space);
- d.GeomDestroy(Shell);
- AvatarGeomAndBodyCreation(_position.X, _position.Y,
- _position.Z + (Math.Abs(CAPSULE_LENGTH - prevCapsule) * 2), m_tensor);
Velocity = new PhysicsVector(0f, 0f, 0f);
-
}
- _parent_scene.geom_name_map[Shell] = m_name;
- _parent_scene.actor_name_map[Shell] = (PhysicsActor) this;
+ _parent_scene.AddPhysicsActorTaint(this);
}
}
@@ -419,9 +413,12 @@ namespace OpenSim.Region.Physics.OdePlugin
///
///
///
+
+ // WARNING: This MUST NOT be called outside of ProcessTaints, else we can have unsynchronized access
+ // to ODE internals. ProcessTaints is called from within thread-locked Simulate(), so it is the only
+ // place that is safe to call this routine AvatarGeomAndBodyCreation.
private void AvatarGeomAndBodyCreation(float npositionX, float npositionY, float npositionZ, float tensor)
{
-
int dAMotorEuler = 1;
_parent_scene.waitForSpaceUnlock(_parent_scene.space);
Shell = d.CreateCapsule(_parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH);
@@ -477,9 +474,6 @@ namespace OpenSim.Region.Physics.OdePlugin
//
//m_log.Info("[PHYSICSAV]: Rotation: " + bodyrotation.M00 + " : " + bodyrotation.M01 + " : " + bodyrotation.M02 + " : " + bodyrotation.M10 + " : " + bodyrotation.M11 + " : " + bodyrotation.M12 + " : " + bodyrotation.M20 + " : " + bodyrotation.M21 + " : " + bodyrotation.M22);
//standupStraight();
-
-
-
}
//
@@ -872,17 +866,8 @@ namespace OpenSim.Region.Physics.OdePlugin
{
lock (_parent_scene.OdeLock)
{
- // Kill the Amotor
- d.JointDestroy(Amotor);
-
- //kill the Geometry
- _parent_scene.waitForSpaceUnlock(_parent_scene.space);
-
- d.GeomDestroy(Shell);
- _parent_scene.geom_name_map.Remove(Shell);
-
- //kill the body
- d.BodyDestroy(Body);
+ m_tainted_isPhysical = false;
+ _parent_scene.AddPhysicsActorTaint(this);
}
}
@@ -922,5 +907,78 @@ namespace OpenSim.Region.Physics.OdePlugin
return true;
return false;
}
+
+ public void ProcessTaints(float timestep)
+ {
+
+ if (m_tainted_isPhysical != m_isPhysical)
+ {
+ if (m_tainted_isPhysical)
+ {
+ // Create avatar capsule and related ODE data
+ if (!(Shell == IntPtr.Zero && Body == IntPtr.Zero && Amotor == IntPtr.Zero))
+ {
+ m_log.Warn("[PHYSICS]: re-creating the following avatar ODE data, even though it already exists - "
+ + (Shell!=IntPtr.Zero ? "Shell ":"")
+ + (Body!=IntPtr.Zero ? "Body ":"")
+ + (Amotor!=IntPtr.Zero ? "Amotor ":"") );
+ }
+ AvatarGeomAndBodyCreation(_position.X, _position.Y, _position.Z, m_tensor);
+
+ _parent_scene.geom_name_map[Shell] = m_name;
+ _parent_scene.actor_name_map[Shell] = (PhysicsActor)this;
+ }
+ else
+ {
+ // destroy avatar capsule and related ODE data
+
+ // Kill the Amotor
+ d.JointDestroy(Amotor);
+ Amotor = IntPtr.Zero;
+
+ //kill the Geometry
+ _parent_scene.waitForSpaceUnlock(_parent_scene.space);
+
+ d.GeomDestroy(Shell);
+ _parent_scene.geom_name_map.Remove(Shell);
+ Shell = IntPtr.Zero;
+
+ //kill the body
+ d.BodyDestroy(Body);
+ Body=IntPtr.Zero;
+ }
+
+ m_isPhysical = m_tainted_isPhysical;
+ }
+
+ if (m_tainted_CAPSULE_LENGTH != CAPSULE_LENGTH)
+ {
+ if (Shell != IntPtr.Zero && Body != IntPtr.Zero && Amotor != IntPtr.Zero)
+ {
+
+ m_pidControllerActive = true;
+ // no lock needed on _parent_scene.OdeLock because we are called from within the thread lock in OdePlugin's simulate()
+ d.JointDestroy(Amotor);
+ float prevCapsule = CAPSULE_LENGTH;
+ CAPSULE_LENGTH = m_tainted_CAPSULE_LENGTH;
+ //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString());
+ d.BodyDestroy(Body);
+ d.GeomDestroy(Shell);
+ AvatarGeomAndBodyCreation(_position.X, _position.Y,
+ _position.Z + (Math.Abs(CAPSULE_LENGTH - prevCapsule) * 2), m_tensor);
+ Velocity = new PhysicsVector(0f, 0f, 0f);
+
+ _parent_scene.geom_name_map[Shell] = m_name;
+ _parent_scene.actor_name_map[Shell] = (PhysicsActor)this;
+ }
+ else
+ {
+ m_log.Warn("[PHYSICS]: trying to change capsule size, but the following ODE data is missing - "
+ + (Shell==IntPtr.Zero ? "Shell ":"")
+ + (Body==IntPtr.Zero ? "Body ":"")
+ + (Amotor==IntPtr.Zero ? "Amotor ":"") );
+ }
+ }
+ }
}
}
diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
index a875d84..b066d0c 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
@@ -213,6 +213,7 @@ namespace OpenSim.Region.Physics.OdePlugin
private List _prims = new List();
private List _activeprims = new List();
private List _taintedPrim = new List();
+ private List _taintedActors = new List();
private List _perloopContact = new List();
private List _collisionEventPrim = new List();
public Dictionary geom_name_map = new Dictionary();
@@ -1793,6 +1794,7 @@ namespace OpenSim.Region.Physics.OdePlugin
///
public override void AddPhysicsActorTaint(PhysicsActor prim)
{
+
if (prim is OdePrim)
{
OdePrim taintedprim = ((OdePrim) prim);
@@ -1801,6 +1803,16 @@ namespace OpenSim.Region.Physics.OdePlugin
if (!(_taintedPrim.Contains(taintedprim)))
_taintedPrim.Add(taintedprim);
}
+ return;
+ }
+ else if (prim is OdeCharacter)
+ {
+ OdeCharacter taintedchar = ((OdeCharacter)prim);
+ lock (_taintedActors)
+ {
+ if (!(_taintedActors.Contains(taintedchar)))
+ _taintedActors.Add(taintedchar);
+ }
}
}
@@ -1869,17 +1881,30 @@ namespace OpenSim.Region.Physics.OdePlugin
//{
// ode.dlock(world);
try
- {
- lock (_characters)
+ {
+ // Insert, remove Characters
+ bool processedtaints = false;
+
+ lock (_taintedActors)
{
- foreach (OdeCharacter actor in _characters)
+ if (_taintedActors.Count > 0)
{
- if (actor != null)
- actor.Move(timeStep);
+ foreach (OdeCharacter character in _taintedActors)
+ {
+
+ character.ProcessTaints(timeStep);
+
+ processedtaints = true;
+ //character.m_collisionscore = 0;
+ }
+
+ if (processedtaints)
+ _taintedActors.Clear();
}
}
- bool processedtaints = false;
+ // Modify other objects in the scene.
+ processedtaints = false;
lock (_taintedPrim)
{
@@ -1898,9 +1923,20 @@ namespace OpenSim.Region.Physics.OdePlugin
}
if (processedtaints)
- _taintedPrim = new List();
+ _taintedPrim.Clear();
+ }
+
+ // Move characters
+ lock (_characters)
+ {
+ foreach (OdeCharacter actor in _characters)
+ {
+ if (actor != null)
+ actor.Move(timeStep);
+ }
}
+ // Move other active objects
lock (_activeprims)
{
foreach (OdePrim prim in _activeprims)
--
cgit v1.1