BulletSim: rearrange code and add different locking to eliminate chances

of race conditions and, especially, race conditions when an object is
removed and quickly re-added to a scene.

This hopefully reduces the occurance of problems when avatars TP within
a region -- the main problem being the loss of collisions.
0.8.2-post-fixes
Robert Adams 2015-08-09 15:36:50 -07:00
parent fe86df0ec9
commit fe37cb9990
3 changed files with 40 additions and 43 deletions

View File

@ -459,7 +459,7 @@ public sealed class BSCharacter : BSPhysObject
RawVelocity = value;
OMV.Vector3 vel = RawVelocity;
DetailLog("{0}: set Velocity = {1}", LogHeader, value);
DetailLog("{0}: set Velocity = {1}", LocalID, value);
PhysScene.TaintedObject(LocalID, "BSCharacter.setVelocity", delegate()
{
@ -477,7 +477,7 @@ public sealed class BSCharacter : BSPhysObject
set {
PhysScene.AssertInTaintTime("BSCharacter.ForceVelocity");
// Util.PrintCallStack();
DetailLog("{0}: set ForceVelocity = {1}", LogHeader, value);
DetailLog("{0}: set ForceVelocity = {1}", LocalID, value);
RawVelocity = value;
PhysScene.PE.SetLinearVelocity(PhysBody, RawVelocity);

View File

@ -80,12 +80,13 @@ public abstract class BSPhysObject : PhysicsActor
Name = name; // PhysicsActor also has the name of the object. Someday consolidate.
TypeName = typeName;
// The collection of things that push me around
PhysicalActors = new BSActorCollection(PhysScene);
// We don't have any physical representation yet.
// Oddity if object is destroyed and recreated very quickly it could still have the old body.
if (!PhysBody.HasPhysicalBody)
PhysBody = new BulletBody(localID);
PhysShape = new BSShapeNull();
// Clean out anything that might be in the physical actor list.
// Again, a workaround for destroying and recreating an object very quickly.
PhysicalActors.Dispose();
UserSetCenterOfMassDisplacement = null;
@ -100,9 +101,6 @@ public abstract class BSPhysObject : PhysicsActor
// Default material type. Also sets Friction, Restitution and Density.
SetMaterial((int)MaterialAttributes.Material.Wood);
CollisionCollection = new CollisionEventUpdate();
CollisionsLastReported = CollisionCollection;
CollisionsLastTick = new CollisionEventUpdate();
CollisionsLastTickStep = -1;
SubscribedEventsMs = 0;
@ -158,9 +156,9 @@ public abstract class BSPhysObject : PhysicsActor
public OMV.Vector3 Inertia { get; set; }
// Reference to the physical body (btCollisionObject) of this object
public BulletBody PhysBody;
public BulletBody PhysBody = new BulletBody(0);
// Reference to the physical shape (btCollisionShape) of this object
public BSShape PhysShape;
public BSShape PhysShape = new BSShapeNull();
// The physical representation of the prim might require an asset fetch.
// The asset state is first 'Unknown' then 'Waiting' then either 'Failed' or 'Fetched'.
@ -445,12 +443,12 @@ public abstract class BSPhysObject : PhysicsActor
}
// The collisions that have been collected for the next collision reporting (throttled by subscription)
protected CollisionEventUpdate CollisionCollection;
protected CollisionEventUpdate CollisionCollection = new CollisionEventUpdate();
// This is the collision collection last reported to the Simulator.
public CollisionEventUpdate CollisionsLastReported;
public CollisionEventUpdate CollisionsLastReported = new CollisionEventUpdate();
// Remember the collisions recorded in the last tick for fancy collision checking
// (like a BSCharacter walking up stairs).
public CollisionEventUpdate CollisionsLastTick;
public CollisionEventUpdate CollisionsLastTick = new CollisionEventUpdate();
private long CollisionsLastTickStep = -1;
// The simulation step is telling this object about a collision.
@ -495,7 +493,7 @@ public abstract class BSPhysObject : PhysicsActor
{
CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
}
DetailLog("{0},{1}.Collison.AddCollider,call,with={2},point={3},normal={4},depth={5},colliderMoving={6}",
DetailLog("{0},{1}.Collision.AddCollider,call,with={2},point={3},normal={4},depth={5},colliderMoving={6}",
LocalID, TypeName, collidingWith, contactPoint, contactNormal, pentrationDepth, ColliderIsMoving);
ret = true;
@ -596,7 +594,7 @@ public abstract class BSPhysObject : PhysicsActor
#region Per Simulation Step actions
public BSActorCollection PhysicalActors;
public BSActorCollection PhysicalActors = new BSActorCollection();
// When an update to the physical properties happens, this event is fired to let
// different actors to modify the update before it is passed around

View File

@ -76,7 +76,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
// Keep track of all the avatars so we can send them a collision event
// every tick so OpenSim will update its animation.
private HashSet<BSPhysObject> m_avatars = new HashSet<BSPhysObject>();
private HashSet<BSPhysObject> AvatarsInScene = new HashSet<BSPhysObject>();
private Object AvatarsInSceneLock = new Object();
// let my minuions use my logger
public ILog Logger { get { return m_log; } }
@ -425,11 +426,14 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
// make sure no stepping happens while we're deleting stuff
m_initialized = false;
lock (PhysObjects)
{
foreach (KeyValuePair<uint, BSPhysObject> kvp in PhysObjects)
{
kvp.Value.Destroy();
}
PhysObjects.Clear();
}
// Now that the prims are all cleaned up, there should be no constraints left
if (Constraints != null)
@ -480,15 +484,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
// TODO: Remove kludge someday.
// We must generate a collision for avatars whether they collide or not.
// This is required by OpenSim to update avatar animations, etc.
lock (m_avatars)
{
// The funky copy is because this list has few and infrequent changes but is
// read zillions of times. This allows the reader/iterator to use the
// list and this creates a new list with any updates.
HashSet<BSPhysObject> avatarTemp = new HashSet<BSPhysObject>(m_avatars);
avatarTemp.Add(actor);
m_avatars = avatarTemp;
}
lock (AvatarsInSceneLock)
AvatarsInScene.Add(actor);
return actor;
}
@ -507,12 +504,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
lock (PhysObjects)
PhysObjects.Remove(bsactor.LocalID);
// Remove kludge someday
lock (m_avatars)
{
HashSet<BSPhysObject> avatarTemp = new HashSet<BSPhysObject>(m_avatars);
avatarTemp.Remove(bsactor);
m_avatars = avatarTemp;
}
lock (AvatarsInSceneLock)
AvatarsInScene.Remove(bsactor);
}
catch (Exception e)
{
@ -757,13 +750,18 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
// The simulator expects collisions for avatars even if there are have been no collisions.
// The event updates avatar animations and stuff.
// If you fix avatar animation updates, remove this overhead and let normal collision processing happen.
// Note that we copy the root of the list to search. Any updates will create a new list
// thus freeing this code from having to do an extra lock for every collision.
HashSet<BSPhysObject> avatarTemp = m_avatars;
foreach (BSPhysObject bsp in avatarTemp)
if (!ObjectsWithCollisions.Contains(bsp)) // don't call avatars twice
bsp.SendCollisions();
avatarTemp = null;
// Note that we get a copy of the list to search because SendCollision() can take a while.
HashSet<BSPhysObject> tempAvatarsInScene;
lock (AvatarsInSceneLock)
{
tempAvatarsInScene = new HashSet<BSPhysObject>(AvatarsInScene);
}
foreach (BSPhysObject actor in tempAvatarsInScene)
{
if (!ObjectsWithCollisions.Contains(actor)) // don't call avatars twice
actor.SendCollisions();
}
tempAvatarsInScene = null;
// Objects that are done colliding are removed from the ObjectsWithCollisions list.
// Not done above because it is inside an iteration of ObjectWithCollisions.
@ -813,6 +811,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
}
BSPhysObject collider;
// NOTE that PhysObjects was locked before the call to SendCollision().
if (!PhysObjects.TryGetValue(localID, out collider))
{
// If the object that is colliding cannot be found, just ignore the collision.