BulletSim: make avatar animations update properly.

It seems that ODE calls the avatar collision handling routine even
if there are no collisions. This causes the animation to be updated.
So, for instance, going from HOVER to FLY is caused by the physics engine
calling the collision routine each frame with 0 collisions.
0.7.4.1
Robert Adams 2012-03-26 17:36:33 -07:00
parent 84c9bd52d3
commit 872d513daa
3 changed files with 48 additions and 9 deletions

View File

@ -426,6 +426,8 @@ public class BSCharacter : PhysicsActor
}
}
// Called by the scene when a collision with this object is reported
CollisionEventUpdate collisionCollection = null;
public void Collide(uint collidingWith, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth)
{
// m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith);
@ -443,10 +445,24 @@ public class BSCharacter : PhysicsActor
if (nowTime < (_lastCollisionTime + _subscribedEventsMs)) return;
_lastCollisionTime = nowTime;
Dictionary<uint, ContactPoint> contactPoints = new Dictionary<uint, ContactPoint>();
contactPoints.Add(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
CollisionEventUpdate args = new CollisionEventUpdate(contactPoints);
base.SendCollisionUpdate(args);
if (collisionCollection == null)
collisionCollection = new CollisionEventUpdate();
collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
}
public void SendCollisions()
{
// if (collisionCollection != null)
// {
// base.SendCollisionUpdate(collisionCollection);
// collisionCollection = null;
// }
// Kludge to make a collision call even if there are no collisions.
// This causes the avatar animation to get updated.
if (collisionCollection == null)
collisionCollection = new CollisionEventUpdate();
base.SendCollisionUpdate(collisionCollection);
collisionCollection = null;
}
}

View File

@ -1326,6 +1326,7 @@ public sealed class BSPrim : PhysicsActor
}
// I've collided with something
CollisionEventUpdate collisionCollection = null;
public void Collide(uint collidingWith, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
{
// m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith);
@ -1343,11 +1344,18 @@ public sealed class BSPrim : PhysicsActor
if (nowTime < (_lastCollisionTime + _subscribedEventsMs)) return;
_lastCollisionTime = nowTime;
// create the event for the collision
Dictionary<uint, ContactPoint> contactPoints = new Dictionary<uint, ContactPoint>();
contactPoints.Add(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
CollisionEventUpdate args = new CollisionEventUpdate(contactPoints);
base.SendCollisionUpdate(args);
if (collisionCollection == null)
collisionCollection = new CollisionEventUpdate();
collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
}
public void SendCollisions()
{
if (collisionCollection != null)
{
base.SendCollisionUpdate(collisionCollection);
collisionCollection = null;
}
}
}
}

View File

@ -78,6 +78,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
private Dictionary<uint, BSCharacter> m_avatars = new Dictionary<uint, BSCharacter>();
private Dictionary<uint, BSPrim> m_prims = new Dictionary<uint, BSPrim>();
private HashSet<BSCharacter> m_avatarsWithCollisions = new HashSet<BSCharacter>();
private HashSet<BSPrim> m_primsWithCollisions = new HashSet<BSPrim>();
private List<BSPrim> m_vehicles = new List<BSPrim>();
private float[] m_heightMap;
private float m_waterLevel;
@ -435,6 +437,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters
}
}
// The SendCollision's batch up the collisions on the objects. Now push the collisions into the simulator.
foreach (BSPrim bsp in m_primsWithCollisions)
bsp.SendCollisions();
m_primsWithCollisions.Clear();
// foreach (BSCharacter bsc in m_avatarsWithCollisions)
// bsc.SendCollisions();
// This is a kludge to get avatar movement updated. ODE sends collisions even if there isn't any
foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars)
kvp.Value.SendCollisions();
m_avatarsWithCollisions.Clear();
// If any of the objects had updated properties, tell the object it has been changed by the physics engine
if (updatedEntityCount > 0)
{
@ -485,11 +498,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters
BSPrim prim;
if (m_prims.TryGetValue(localID, out prim)) {
prim.Collide(collidingWith, type, collidePoint, collideNormal, penitration);
m_primsWithCollisions.Add(prim);
return;
}
BSCharacter actor;
if (m_avatars.TryGetValue(localID, out actor)) {
actor.Collide(collidingWith, type, collidePoint, collideNormal, penitration);
m_avatarsWithCollisions.Add(actor);
return;
}
return;