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
parent
fe86df0ec9
commit
fe37cb9990
|
@ -459,7 +459,7 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
RawVelocity = value;
|
RawVelocity = value;
|
||||||
OMV.Vector3 vel = RawVelocity;
|
OMV.Vector3 vel = RawVelocity;
|
||||||
|
|
||||||
DetailLog("{0}: set Velocity = {1}", LogHeader, value);
|
DetailLog("{0}: set Velocity = {1}", LocalID, value);
|
||||||
|
|
||||||
PhysScene.TaintedObject(LocalID, "BSCharacter.setVelocity", delegate()
|
PhysScene.TaintedObject(LocalID, "BSCharacter.setVelocity", delegate()
|
||||||
{
|
{
|
||||||
|
@ -477,7 +477,7 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
set {
|
set {
|
||||||
PhysScene.AssertInTaintTime("BSCharacter.ForceVelocity");
|
PhysScene.AssertInTaintTime("BSCharacter.ForceVelocity");
|
||||||
// Util.PrintCallStack();
|
// Util.PrintCallStack();
|
||||||
DetailLog("{0}: set ForceVelocity = {1}", LogHeader, value);
|
DetailLog("{0}: set ForceVelocity = {1}", LocalID, value);
|
||||||
|
|
||||||
RawVelocity = value;
|
RawVelocity = value;
|
||||||
PhysScene.PE.SetLinearVelocity(PhysBody, RawVelocity);
|
PhysScene.PE.SetLinearVelocity(PhysBody, RawVelocity);
|
||||||
|
|
|
@ -80,12 +80,13 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
Name = name; // PhysicsActor also has the name of the object. Someday consolidate.
|
Name = name; // PhysicsActor also has the name of the object. Someday consolidate.
|
||||||
TypeName = typeName;
|
TypeName = typeName;
|
||||||
|
|
||||||
// The collection of things that push me around
|
// Oddity if object is destroyed and recreated very quickly it could still have the old body.
|
||||||
PhysicalActors = new BSActorCollection(PhysScene);
|
if (!PhysBody.HasPhysicalBody)
|
||||||
|
|
||||||
// We don't have any physical representation yet.
|
|
||||||
PhysBody = new BulletBody(localID);
|
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;
|
UserSetCenterOfMassDisplacement = null;
|
||||||
|
|
||||||
|
@ -100,9 +101,6 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
// Default material type. Also sets Friction, Restitution and Density.
|
// Default material type. Also sets Friction, Restitution and Density.
|
||||||
SetMaterial((int)MaterialAttributes.Material.Wood);
|
SetMaterial((int)MaterialAttributes.Material.Wood);
|
||||||
|
|
||||||
CollisionCollection = new CollisionEventUpdate();
|
|
||||||
CollisionsLastReported = CollisionCollection;
|
|
||||||
CollisionsLastTick = new CollisionEventUpdate();
|
|
||||||
CollisionsLastTickStep = -1;
|
CollisionsLastTickStep = -1;
|
||||||
|
|
||||||
SubscribedEventsMs = 0;
|
SubscribedEventsMs = 0;
|
||||||
|
@ -158,9 +156,9 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
public OMV.Vector3 Inertia { get; set; }
|
public OMV.Vector3 Inertia { get; set; }
|
||||||
|
|
||||||
// Reference to the physical body (btCollisionObject) of this object
|
// 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
|
// 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 physical representation of the prim might require an asset fetch.
|
||||||
// The asset state is first 'Unknown' then 'Waiting' then either 'Failed' or 'Fetched'.
|
// 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)
|
// 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.
|
// 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
|
// Remember the collisions recorded in the last tick for fancy collision checking
|
||||||
// (like a BSCharacter walking up stairs).
|
// (like a BSCharacter walking up stairs).
|
||||||
public CollisionEventUpdate CollisionsLastTick;
|
public CollisionEventUpdate CollisionsLastTick = new CollisionEventUpdate();
|
||||||
private long CollisionsLastTickStep = -1;
|
private long CollisionsLastTickStep = -1;
|
||||||
|
|
||||||
// The simulation step is telling this object about a collision.
|
// 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));
|
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);
|
LocalID, TypeName, collidingWith, contactPoint, contactNormal, pentrationDepth, ColliderIsMoving);
|
||||||
|
|
||||||
ret = true;
|
ret = true;
|
||||||
|
@ -596,7 +594,7 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
|
|
||||||
#region Per Simulation Step actions
|
#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
|
// 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
|
// different actors to modify the update before it is passed around
|
||||||
|
|
|
@ -76,7 +76,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
|
|
||||||
// Keep track of all the avatars so we can send them a collision event
|
// Keep track of all the avatars so we can send them a collision event
|
||||||
// every tick so OpenSim will update its animation.
|
// 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
|
// let my minuions use my logger
|
||||||
public ILog Logger { get { return m_log; } }
|
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
|
// make sure no stepping happens while we're deleting stuff
|
||||||
m_initialized = false;
|
m_initialized = false;
|
||||||
|
|
||||||
|
lock (PhysObjects)
|
||||||
|
{
|
||||||
foreach (KeyValuePair<uint, BSPhysObject> kvp in PhysObjects)
|
foreach (KeyValuePair<uint, BSPhysObject> kvp in PhysObjects)
|
||||||
{
|
{
|
||||||
kvp.Value.Destroy();
|
kvp.Value.Destroy();
|
||||||
}
|
}
|
||||||
PhysObjects.Clear();
|
PhysObjects.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
// Now that the prims are all cleaned up, there should be no constraints left
|
// Now that the prims are all cleaned up, there should be no constraints left
|
||||||
if (Constraints != null)
|
if (Constraints != null)
|
||||||
|
@ -480,15 +484,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
// TODO: Remove kludge someday.
|
// TODO: Remove kludge someday.
|
||||||
// We must generate a collision for avatars whether they collide or not.
|
// We must generate a collision for avatars whether they collide or not.
|
||||||
// This is required by OpenSim to update avatar animations, etc.
|
// This is required by OpenSim to update avatar animations, etc.
|
||||||
lock (m_avatars)
|
lock (AvatarsInSceneLock)
|
||||||
{
|
AvatarsInScene.Add(actor);
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
return actor;
|
return actor;
|
||||||
}
|
}
|
||||||
|
@ -507,12 +504,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
lock (PhysObjects)
|
lock (PhysObjects)
|
||||||
PhysObjects.Remove(bsactor.LocalID);
|
PhysObjects.Remove(bsactor.LocalID);
|
||||||
// Remove kludge someday
|
// Remove kludge someday
|
||||||
lock (m_avatars)
|
lock (AvatarsInSceneLock)
|
||||||
{
|
AvatarsInScene.Remove(bsactor);
|
||||||
HashSet<BSPhysObject> avatarTemp = new HashSet<BSPhysObject>(m_avatars);
|
|
||||||
avatarTemp.Remove(bsactor);
|
|
||||||
m_avatars = avatarTemp;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
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 simulator expects collisions for avatars even if there are have been no collisions.
|
||||||
// The event updates avatar animations and stuff.
|
// The event updates avatar animations and stuff.
|
||||||
// If you fix avatar animation updates, remove this overhead and let normal collision processing happen.
|
// 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
|
// Note that we get a copy of the list to search because SendCollision() can take a while.
|
||||||
// thus freeing this code from having to do an extra lock for every collision.
|
HashSet<BSPhysObject> tempAvatarsInScene;
|
||||||
HashSet<BSPhysObject> avatarTemp = m_avatars;
|
lock (AvatarsInSceneLock)
|
||||||
foreach (BSPhysObject bsp in avatarTemp)
|
{
|
||||||
if (!ObjectsWithCollisions.Contains(bsp)) // don't call avatars twice
|
tempAvatarsInScene = new HashSet<BSPhysObject>(AvatarsInScene);
|
||||||
bsp.SendCollisions();
|
}
|
||||||
avatarTemp = null;
|
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.
|
// Objects that are done colliding are removed from the ObjectsWithCollisions list.
|
||||||
// Not done above because it is inside an iteration of ObjectWithCollisions.
|
// Not done above because it is inside an iteration of ObjectWithCollisions.
|
||||||
|
@ -813,6 +811,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
}
|
}
|
||||||
|
|
||||||
BSPhysObject collider;
|
BSPhysObject collider;
|
||||||
|
// NOTE that PhysObjects was locked before the call to SendCollision().
|
||||||
if (!PhysObjects.TryGetValue(localID, out collider))
|
if (!PhysObjects.TryGetValue(localID, out collider))
|
||||||
{
|
{
|
||||||
// If the object that is colliding cannot be found, just ignore the collision.
|
// If the object that is colliding cannot be found, just ignore the collision.
|
||||||
|
|
Loading…
Reference in New Issue