From 652bcf91d50898181638a2668c9e2dcacfa33005 Mon Sep 17 00:00:00 2001
From: Dr Scofield
Date: Thu, 25 Jun 2009 07:39:48 +0000
Subject: - fixes a "collection out of sync" exception in the ODE physics
engine, caused by an "avatar infinite position" occurring under heavy load.
- fixes "value too small" exception in ChatModule
---
OpenSim/Region/Physics/OdePlugin/ODECharacter.cs | 12 +++-
OpenSim/Region/Physics/OdePlugin/OdePlugin.cs | 77 ++++++++++++++----------
2 files changed, 53 insertions(+), 36 deletions(-)
(limited to 'OpenSim/Region/Physics/OdePlugin')
diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
index 3f0d6c1..e5e7d07 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
@@ -26,6 +26,7 @@
*/
using System;
+using System.Collections.Generic;
using System.Reflection;
using OpenMetaverse;
using Ode.NET;
@@ -785,7 +786,7 @@ namespace OpenSim.Region.Physics.OdePlugin
/// This is the avatar's movement control + PID Controller
///
///
- public void Move(float timeStep)
+ public void Move(float timeStep, List defects)
{
// no lock; for now it's only called from within Simulate()
@@ -803,11 +804,14 @@ namespace OpenSim.Region.Physics.OdePlugin
d.Vector3 localpos = d.BodyGetPosition(Body);
PhysicsVector localPos = new PhysicsVector(localpos.X, localpos.Y, localpos.Z);
+
if (!PhysicsVector.isFinite(localPos))
{
m_log.Warn("[PHYSICS]: Avatar Position is non-finite!");
- _parent_scene.RemoveCharacter(this);
+ defects.Add(this);
+ // _parent_scene.RemoveCharacter(this);
+
// destroy avatar capsule and related ODE data
if (Amotor != IntPtr.Zero)
{
@@ -815,6 +819,7 @@ namespace OpenSim.Region.Physics.OdePlugin
d.JointDestroy(Amotor);
Amotor = IntPtr.Zero;
}
+
//kill the Geometry
_parent_scene.waitForSpaceUnlock(_parent_scene.space);
@@ -958,7 +963,8 @@ namespace OpenSim.Region.Physics.OdePlugin
{
m_log.Warn("[PHYSICS]: Got a NaN force vector in Move()");
m_log.Warn("[PHYSICS]: Avatar Position is non-finite!");
- _parent_scene.RemoveCharacter(this);
+ defects.Add(this);
+ // _parent_scene.RemoveCharacter(this);
// destroy avatar capsule and related ODE data
if (Amotor != IntPtr.Zero)
{
diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
index 46689eb..0f92358 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
@@ -1434,42 +1434,45 @@ namespace OpenSim.Region.Physics.OdePlugin
{
_perloopContact.Clear();
- foreach (OdeCharacter chr in _characters)
+ lock (_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
- {
- d.SpaceCollide2(space, chr.Shell, IntPtr.Zero, nearCallback);
- }
- catch (AccessViolationException)
+ foreach (OdeCharacter chr in _characters)
{
- 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)
- //{
+ // 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;
- //}
+ //}
+ }
}
lock (_activeprims)
@@ -2799,10 +2802,18 @@ namespace OpenSim.Region.Physics.OdePlugin
// Move characters
lock (_characters)
{
+ List defects = new List();
foreach (OdeCharacter actor in _characters)
{
if (actor != null)
- actor.Move(timeStep);
+ actor.Move(timeStep, defects);
+ }
+ if (0 != defects.Count)
+ {
+ foreach (OdeCharacter defect in defects)
+ {
+ RemoveCharacter(defect);
+ }
}
}
--
cgit v1.1