From bd880f917812280eb90af51b3f1e74e3a6ba457b Mon Sep 17 00:00:00 2001
From: Teravus Ovares
Date: Thu, 14 Feb 2008 09:31:22 +0000
Subject: * Another ODE Stability update. This might fix the recent Linux
issues with the ODEPlugin.
---
OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 171 ++++++++++++++++++++------
OpenSim/Region/Physics/OdePlugin/OdePlugin.cs | 129 +++++++++++--------
2 files changed, 210 insertions(+), 90 deletions(-)
(limited to 'OpenSim/Region/Physics')
diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
index 12da6a7..4c041a1 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
@@ -28,6 +28,7 @@
using System;
using System.Collections.Generic;
+using System.Runtime.InteropServices;
using Axiom.Math;
using Ode.NET;
using OpenSim.Framework;
@@ -57,6 +58,7 @@ namespace OpenSim.Region.Physics.OdePlugin
public bool m_taintdisable = false;
public bool m_disabled = false;
public bool m_taintadd = false;
+ public GCHandle gc;
private CollisionLocker ode;
private bool m_taintforce = false;
@@ -67,6 +69,7 @@ namespace OpenSim.Region.Physics.OdePlugin
private OdeScene _parent_scene;
public IntPtr m_targetSpace = (IntPtr) 0;
public IntPtr prim_geom;
+ public IntPtr prev_geom;
public IntPtr _triMeshData;
private bool iscolliding = false;
@@ -95,6 +98,9 @@ namespace OpenSim.Region.Physics.OdePlugin
public OdePrim(String primName, OdeScene parent_scene, PhysicsVector pos, PhysicsVector size,
Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical, CollisionLocker dode)
{
+
+
+ gc = GCHandle.Alloc(prim_geom, GCHandleType.Pinned);
ode = dode;
_velocity = new PhysicsVector();
_position = pos;
@@ -116,6 +122,9 @@ namespace OpenSim.Region.Physics.OdePlugin
_position.Y = 0;
}
+ prim_geom = (IntPtr)0;
+ prev_geom = (IntPtr)0;
+
_size = size;
m_taintsize = _size;
_acceleration = new PhysicsVector();
@@ -173,6 +182,13 @@ namespace OpenSim.Region.Physics.OdePlugin
set { return; }
}
+ public void SetGeom(IntPtr geom)
+ {
+ prev_geom = prim_geom;
+ prim_geom = geom;
+ m_log.Warn("Setting Geom to: " + prim_geom);
+
+ }
public void enableBody()
{
@@ -337,9 +353,6 @@ namespace OpenSim.Region.Physics.OdePlugin
disableBody();
}
-
-
-
float[] vertexList = mesh.getVertexListAsFloatLocked(); // Note, that vertextList is pinned in memory
int[] indexList = mesh.getIndexListAsIntLocked(); // Also pinned, needs release after usage
int VertexCount = vertexList.GetLength(0)/3;
@@ -356,7 +369,10 @@ namespace OpenSim.Region.Physics.OdePlugin
try
{
- prim_geom = d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null);
+ if (prim_geom == (IntPtr)0)
+ {
+ SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null));
+ }
}
catch (System.AccessViolationException)
{
@@ -377,10 +393,12 @@ namespace OpenSim.Region.Physics.OdePlugin
public void ProcessTaints(float timestep)
{
-
+
if (m_taintadd)
+ {
changeadd(timestep);
+ }
if (m_taintposition != _position)
Move(timestep);
@@ -433,6 +451,11 @@ namespace OpenSim.Region.Physics.OdePlugin
}
public void changeadd(float timestep)
{
+ while (ode.lockquery())
+ {
+ }
+ ode.dlock(_parent_scene.world);
+
int[] iprimspaceArrItem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
IntPtr targetspace = _parent_scene.calculateSpaceForGeom(_position);
@@ -441,6 +464,11 @@ namespace OpenSim.Region.Physics.OdePlugin
m_targetSpace = targetspace;
+ if (m_targetSpace != (IntPtr)0)
+ {
+ m_log.Warn("[PHYSICS]: target: " + m_targetSpace.ToString());
+ }
+
if (_mesh != null)
{
}
@@ -473,11 +501,12 @@ namespace OpenSim.Region.Physics.OdePlugin
_parent_scene.waitForSpaceUnlock(m_targetSpace);
try
{
- prim_geom = d.CreateSphere(m_targetSpace, _size.X / 2);
+ SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2));
}
catch (System.AccessViolationException)
{
m_log.Warn("[PHYSICS]: Unable to create physics proxy for object");
+ ode.dunlock(_parent_scene.world);
return;
}
}
@@ -486,11 +515,12 @@ namespace OpenSim.Region.Physics.OdePlugin
_parent_scene.waitForSpaceUnlock(m_targetSpace);
try
{
- prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
+ SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
}
catch (System.AccessViolationException)
{
m_log.Warn("[PHYSICS]: Unable to create physics proxy for object");
+ ode.dunlock(_parent_scene.world);
return;
}
}
@@ -500,12 +530,13 @@ namespace OpenSim.Region.Physics.OdePlugin
_parent_scene.waitForSpaceUnlock(m_targetSpace);
try
{
- prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
+ SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
}
catch (System.AccessViolationException)
{
- return;
m_log.Warn("[PHYSICS]: Unable to create physics proxy for object");
+ ode.dunlock(_parent_scene.world);
+ return;
}
}
}
@@ -526,23 +557,26 @@ namespace OpenSim.Region.Physics.OdePlugin
_parent_scene.waitForSpaceUnlock(m_targetSpace);
try
{
- prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
+ SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
}
catch (System.AccessViolationException)
{
m_log.Warn("[PHYSICS]: Unable to create physics proxy for object");
+ ode.dunlock(_parent_scene.world);
return;
}
}
}
-
- d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
- d.Quaternion myrot = new d.Quaternion();
- myrot.W = _orientation.w;
- myrot.X = _orientation.x;
- myrot.Y = _orientation.y;
- myrot.Z = _orientation.z;
- d.GeomSetQuaternion(prim_geom, ref myrot);
+ if (prim_geom != (IntPtr) 0)
+ {
+ d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
+ d.Quaternion myrot = new d.Quaternion();
+ myrot.W = _orientation.w;
+ myrot.X = _orientation.x;
+ myrot.Y = _orientation.y;
+ myrot.Z = _orientation.z;
+ d.GeomSetQuaternion(prim_geom, ref myrot);
+ }
if (m_isphysical && Body == (IntPtr)0)
@@ -551,7 +585,8 @@ namespace OpenSim.Region.Physics.OdePlugin
}
- }
+ }
+ ode.dunlock(_parent_scene.world);
_parent_scene.geom_name_map[prim_geom] = this.m_primName;
_parent_scene.actor_name_map[prim_geom] = (PhysicsActor)this;
m_taintadd = false;
@@ -560,32 +595,55 @@ namespace OpenSim.Region.Physics.OdePlugin
}
public void Move(float timestep)
{
+ while (ode.lockquery())
+ {
+ }
+ ode.dlock(_parent_scene.world);
+
+
if (m_isphysical)
{
// This is a fallback.. May no longer be necessary.
if (Body == (IntPtr) 0)
enableBody();
//Prim auto disable after 20 frames,
- ///if you move it, re-enable the prim manually.
- d.BodyEnable(Body);
+ //if you move it, re-enable the prim manually.
+
d.BodySetPosition(Body, _position.X, _position.Y, _position.Z);
+ d.BodyEnable(Body);
+
}
else
{
string primScenAvatarIn = _parent_scene.whichspaceamIin(_position);
int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
- m_targetSpace = _parent_scene.recalculateSpaceForGeom(prim_geom, _position, m_targetSpace);
- d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
+ _parent_scene.waitForSpaceUnlock(m_targetSpace);
+
+ IntPtr tempspace = _parent_scene.recalculateSpaceForGeom(prim_geom, _position, m_targetSpace);
+ m_targetSpace = tempspace;
_parent_scene.waitForSpaceUnlock(m_targetSpace);
- d.SpaceAdd(m_targetSpace, prim_geom);
+ if (prim_geom != (IntPtr) 0)
+ {
+ d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
+
+ _parent_scene.waitForSpaceUnlock(m_targetSpace);
+ d.SpaceAdd(m_targetSpace, prim_geom);
+ }
}
+ ode.dunlock(_parent_scene.world);
+
resetCollisionAccounting();
m_taintposition = _position;
}
public void rotate(float timestep)
{
+ while (ode.lockquery())
+ {
+ }
+ ode.dlock(_parent_scene.world);
+
d.Quaternion myrot = new d.Quaternion();
myrot.W = _orientation.w;
myrot.X = _orientation.x;
@@ -596,6 +654,9 @@ namespace OpenSim.Region.Physics.OdePlugin
{
d.BodySetQuaternion(Body, ref myrot);
}
+
+ ode.dunlock(_parent_scene.world);
+
resetCollisionAccounting();
m_taintrot = _orientation;
}
@@ -608,11 +669,17 @@ namespace OpenSim.Region.Physics.OdePlugin
}
public void changedisable(float timestep)
- {
+ {
+ while (ode.lockquery())
+ {
+ }
+ ode.dlock(_parent_scene.world);
m_disabled = true;
if (Body != (IntPtr) 0)
d.BodyDisable(Body);
-
+
+ ode.dunlock(_parent_scene.world);
+
m_taintdisable = false;
}
@@ -638,6 +705,10 @@ namespace OpenSim.Region.Physics.OdePlugin
public void changesize(float timestamp)
{
+ while (ode.lockquery())
+ {
+ }
+ ode.dlock(_parent_scene.world);
//if (!_parent_scene.geom_name_map.ContainsKey(prim_geom))
//{
// m_taintsize = _size;
@@ -684,20 +755,20 @@ namespace OpenSim.Region.Physics.OdePlugin
if (((_size.X / 2f) > 0f) && ((_size.X / 2f) < 1000))
{
_parent_scene.waitForSpaceUnlock(m_targetSpace);
- prim_geom = d.CreateSphere(m_targetSpace, _size.X / 2);
+ SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2));
}
else
{
m_log.Info("[PHYSICS]: Failed to load a sphere bad size");
_parent_scene.waitForSpaceUnlock(m_targetSpace);
- prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
+ SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
}
}
else
{
_parent_scene.waitForSpaceUnlock(m_targetSpace);
- prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
+ SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
}
}
//else if (_pbs.ProfileShape == ProfileShape.Circle && _pbs.PathCurve == (byte)Extrusion.Straight)
@@ -715,7 +786,7 @@ namespace OpenSim.Region.Physics.OdePlugin
else
{
_parent_scene.waitForSpaceUnlock(m_targetSpace);
- prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
+ SetGeom(prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
}
//prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
@@ -734,12 +805,12 @@ namespace OpenSim.Region.Physics.OdePlugin
if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
{
_parent_scene.waitForSpaceUnlock(m_targetSpace);
- prim_geom = d.CreateSphere(m_targetSpace, _size.X / 2);
+ SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2));
}
else
{
_parent_scene.waitForSpaceUnlock(m_targetSpace);
- prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
+ SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
}
}
//else if (_pbs.ProfileShape == ProfileShape.Circle && _pbs.PathCurve == (byte)Extrusion.Straight)
@@ -757,7 +828,7 @@ namespace OpenSim.Region.Physics.OdePlugin
else
{
_parent_scene.waitForSpaceUnlock(m_targetSpace);
- prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
+ SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
}
d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
d.Quaternion myrot = new d.Quaternion();
@@ -779,12 +850,21 @@ namespace OpenSim.Region.Physics.OdePlugin
}
_parent_scene.geom_name_map[prim_geom] = oldname;
+
+ ode.dunlock(_parent_scene.world);
+
resetCollisionAccounting();
m_taintsize = _size;
}
public void changeshape(float timestamp)
{
+ while (ode.lockquery())
+ {
+ }
+ ode.dlock(_parent_scene.world);
+
+
string oldname = _parent_scene.geom_name_map[prim_geom];
// Cleanup of old prim geometry and Bodies
@@ -809,13 +889,13 @@ namespace OpenSim.Region.Physics.OdePlugin
else
{
_parent_scene.waitForSpaceUnlock(m_targetSpace);
- prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
+ SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
}
}
else
{
_parent_scene.waitForSpaceUnlock(m_targetSpace);
- prim_geom = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
+ SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z));
}
if (IsPhysical && Body == (IntPtr) 0)
{
@@ -833,12 +913,20 @@ namespace OpenSim.Region.Physics.OdePlugin
d.GeomSetQuaternion(prim_geom, ref myrot);
}
_parent_scene.geom_name_map[prim_geom] = oldname;
+
+ ode.dunlock(_parent_scene.world);
+
resetCollisionAccounting();
m_taintshape = false;
}
public void changeAddForce(float timestamp)
{
+ while (ode.lockquery())
+ {
+ }
+ ode.dlock(_parent_scene.world);
+
System.Threading.Thread.Sleep(2);
lock (m_forcelist)
{
@@ -855,6 +943,9 @@ namespace OpenSim.Region.Physics.OdePlugin
}
m_forcelist.Clear();
}
+
+ ode.dunlock(_parent_scene.world);
+
m_collisionscore = 0;
m_interpenetrationcount = 0;
m_taintforce = false;
@@ -862,6 +953,11 @@ namespace OpenSim.Region.Physics.OdePlugin
}
private void changevelocity(float timestep)
{
+ while (ode.lockquery())
+ {
+ }
+ ode.dlock(_parent_scene.world);
+
System.Threading.Thread.Sleep(20);
if (IsPhysical)
{
@@ -870,7 +966,10 @@ namespace OpenSim.Region.Physics.OdePlugin
d.BodySetLinearVel(Body, m_taintVelocity.X, m_taintVelocity.Y, m_taintVelocity.Z);
}
}
- resetCollisionAccounting();
+
+ ode.dunlock(_parent_scene.world);
+
+ //resetCollisionAccounting();
m_taintVelocity = PhysicsVector.Zero;
}
public override bool IsPhysical
diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
index f934341..9392192 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
@@ -596,7 +596,7 @@ namespace OpenSim.Region.Physics.OdePlugin
///
private void collision_optimized(float timeStep)
{
- starttiming();
+
foreach (OdeCharacter chr in _characters)
{
// Reset the collision values to false
@@ -626,7 +626,7 @@ namespace OpenSim.Region.Physics.OdePlugin
//forcedZ = true;
//}
}
- int avms = stoptiming();
+
// If the sim is running slow this frame,
// don't process collision for prim!
@@ -719,8 +719,9 @@ namespace OpenSim.Region.Physics.OdePlugin
{
OdePrim p = (OdePrim) prim;
- p.setPrimForRemoval();
- AddPhysicsActorTaint(prim);
+ //p.setPrimForRemoval();
+ //AddPhysicsActorTaint(prim);
+ RemovePrimThreadLocked(p);
}
}
}
@@ -736,10 +737,14 @@ namespace OpenSim.Region.Physics.OdePlugin
///
public void RemovePrimThreadLocked(OdePrim prim)
{
- prim.ResetTaints();
- lock (OdeLock)
+ while (ode.lockquery())
{
- System.Threading.Thread.Sleep(20);
+ }
+ ode.dlock(world);
+ //System.Threading.Thread.Sleep(20);
+ prim.ResetTaints();
+
+
if (prim.IsPhysical)
{
prim.disableBody();
@@ -748,27 +753,38 @@ namespace OpenSim.Region.Physics.OdePlugin
if (prim.m_targetSpace != space && prim.IsPhysical == false)
{
// If the geometry is in the targetspace, remove it from the target space
- if (d.SpaceQuery(prim.m_targetSpace, prim.prim_geom))
+ //m_log.Warn(prim.m_targetSpace);
+ if (prim.prim_geom == (IntPtr)0)
+ prim.prim_geom = prim.prev_geom;
+
+ if (prim.m_targetSpace != (IntPtr)0)
{
- if (!(prim.m_targetSpace.Equals(null)))
+ if (d.SpaceQuery(prim.m_targetSpace, prim.prim_geom))
{
if (d.GeomIsSpace(prim.m_targetSpace))
- {
+ {
waitForSpaceUnlock(prim.m_targetSpace);
d.SpaceRemove(prim.m_targetSpace, prim.prim_geom);
+ prim.m_targetSpace = space;
}
else
{
m_log.Info("[Physics]: Invalid Scene passed to 'removeprim from scene':" +
- ((OdePrim) prim).m_targetSpace.ToString());
+ ((OdePrim)prim).m_targetSpace.ToString());
}
+
}
}
+ m_log.Warn(prim.prim_geom);
try
{
-
- d.GeomDestroy(prim.prim_geom);
+ if (prim.prim_geom != (IntPtr)0)
+ {
+ d.GeomDestroy(prim.prim_geom);
+ prim.prim_geom = (IntPtr) 0;
+ }
+
}
catch (System.AccessViolationException)
{
@@ -777,30 +793,31 @@ namespace OpenSim.Region.Physics.OdePlugin
_prims.Remove(prim);
//If there are no more geometries in the sub-space, we don't need it in the main space anymore
- if (d.SpaceGetNumGeoms(prim.m_targetSpace) == 0)
- {
- if (!(prim.m_targetSpace.Equals(null)))
- {
- if (d.GeomIsSpace(prim.m_targetSpace))
- {
- waitForSpaceUnlock(prim.m_targetSpace);
- d.SpaceRemove(space, prim.m_targetSpace);
+ //if (d.SpaceGetNumGeoms(prim.m_targetSpace) == 0)
+ //{
+ //if (!(prim.m_targetSpace.Equals(null)))
+ //{
+ //if (d.GeomIsSpace(prim.m_targetSpace))
+ //{
+ //waitForSpaceUnlock(prim.m_targetSpace);
+ //d.SpaceRemove(space, prim.m_targetSpace);
// free up memory used by the space.
- d.SpaceDestroy(prim.m_targetSpace);
- int[] xyspace = calculateSpaceArrayItemFromPos(prim.Position);
- resetSpaceArrayItemToZero(xyspace[0], xyspace[1]);
- }
- else
- {
- m_log.Info("[Physics]: Invalid Scene passed to 'removeprim from scene':" +
- ((OdePrim) prim).m_targetSpace.ToString());
- }
- }
- }
+ //d.SpaceDestroy(prim.m_targetSpace);
+ //int[] xyspace = calculateSpaceArrayItemFromPos(prim.Position);
+ //resetSpaceArrayItemToZero(xyspace[0], xyspace[1]);
+ //}
+ //else
+ //{
+ //m_log.Info("[Physics]: Invalid Scene passed to 'removeprim from scene':" +
+ //((OdePrim) prim).m_targetSpace.ToString());
+ //}
+ //}
+ //}
}
-
- }
+
+
+ ode.dunlock(world);
}
///
/// Takes a space pointer and zeros out the array we're using to hold the spaces
@@ -905,9 +922,11 @@ namespace OpenSim.Region.Physics.OdePlugin
else
{
// this is a physical object that got disabled. ;.;
- if (d.SpaceQuery(currentspace, geom))
+ if (currentspace != (IntPtr)0 && geom != (IntPtr)0)
{
- if (currentspace != (IntPtr) 0)
+ if (d.SpaceQuery(currentspace, geom))
+ {
+
if (d.GeomIsSpace(currentspace))
{
waitForSpaceUnlock(currentspace);
@@ -918,23 +937,24 @@ namespace OpenSim.Region.Physics.OdePlugin
m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" +
currentspace.ToString() + " Geom:" + geom.ToString());
}
- }
- else
- {
- IntPtr sGeomIsIn = d.GeomGetSpace(geom);
- if (!(sGeomIsIn.Equals(null)))
+ }
+ else
{
- if (sGeomIsIn != (IntPtr) 0)
+ IntPtr sGeomIsIn = d.GeomGetSpace(geom);
+ if (!(sGeomIsIn.Equals(null)))
{
- if (d.GeomIsSpace(sGeomIsIn))
+ if (sGeomIsIn != (IntPtr)0)
{
- waitForSpaceUnlock(sGeomIsIn);
- d.SpaceRemove(sGeomIsIn, geom);
- }
- else
- {
- m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" +
- sGeomIsIn.ToString() + " Geom:" + geom.ToString());
+ if (d.GeomIsSpace(sGeomIsIn))
+ {
+ waitForSpaceUnlock(sGeomIsIn);
+ d.SpaceRemove(sGeomIsIn, geom);
+ }
+ else
+ {
+ m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" +
+ sGeomIsIn.ToString() + " Geom:" + geom.ToString());
+ }
}
}
}
@@ -1041,6 +1061,7 @@ namespace OpenSim.Region.Physics.OdePlugin
_prims.Add(newPrim);
}
+
return newPrim;
}
@@ -1268,10 +1289,10 @@ namespace OpenSim.Region.Physics.OdePlugin
bool processedtaints = false;
foreach (OdePrim prim in _taintedPrim)
{
- if (prim.m_taintremove)
- {
- RemovePrimThreadLocked(prim);
- }
+ //if (prim.m_taintremove)
+ //{
+ //RemovePrimThreadLocked(prim);
+ //}
prim.ProcessTaints(timeStep);
--
cgit v1.1