BulletSim: add parameter to UpdateProperties call into the linkset so changes from the physics engine can be differentiated from changes made by the user. This eliminates a linkset rebuild loop. Also add logic to not rebuild or freak out when the object/linkset crosses a terrain boundry.
parent
3f2aaffd4d
commit
2b8efa24dd
|
@ -252,8 +252,9 @@ public abstract class BSLinkset
|
||||||
|
|
||||||
// Called when a parameter update comes from the physics engine for any object
|
// Called when a parameter update comes from the physics engine for any object
|
||||||
// of the linkset is received.
|
// of the linkset is received.
|
||||||
|
// Passed flag is update came from physics engine (true) or the user (false).
|
||||||
// Called at taint-time!!
|
// Called at taint-time!!
|
||||||
public abstract void UpdateProperties(BSPhysObject physObject);
|
public abstract void UpdateProperties(BSPhysObject physObject, bool physicalUpdate);
|
||||||
|
|
||||||
// Routine used when rebuilding the body of the root of the linkset
|
// Routine used when rebuilding the body of the root of the linkset
|
||||||
// Destroy all the constraints have have been made to root.
|
// Destroy all the constraints have have been made to root.
|
||||||
|
|
|
@ -28,6 +28,8 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
|
using OpenSim.Framework;
|
||||||
|
|
||||||
using OMV = OpenMetaverse;
|
using OMV = OpenMetaverse;
|
||||||
|
|
||||||
namespace OpenSim.Region.Physics.BulletSPlugin
|
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
|
@ -87,25 +89,22 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
// its internal properties.
|
// its internal properties.
|
||||||
public override void Refresh(BSPhysObject requestor)
|
public override void Refresh(BSPhysObject requestor)
|
||||||
{
|
{
|
||||||
if (!IsRoot(requestor))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
// Something changed so do the rebuilding thing
|
// Something changed so do the rebuilding thing
|
||||||
InternalRefresh(requestor);
|
// ScheduleRebuild();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Schedule a refresh to happen after all the other taint processing.
|
// Schedule a refresh to happen after all the other taint processing.
|
||||||
private void InternalRefresh(BSPhysObject requestor)
|
private void ScheduleRebuild()
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,requestor={1},rebuilding={2}",
|
DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,rebuilding={1}",
|
||||||
LinksetRoot.LocalID, requestor.LocalID, Rebuilding);
|
LinksetRoot.LocalID, Rebuilding);
|
||||||
// When rebuilding, it is possible to set properties that would normally require a rebuild.
|
// When rebuilding, it is possible to set properties that would normally require a rebuild.
|
||||||
// If already rebuilding, don't request another rebuild.
|
// If already rebuilding, don't request another rebuild.
|
||||||
if (!Rebuilding)
|
if (!Rebuilding)
|
||||||
{
|
{
|
||||||
PhysicsScene.PostTaintObject("BSLinksetCompound.Refresh", requestor.LocalID, delegate()
|
PhysicsScene.PostTaintObject("BSLinksetCompound.Refresh", LinksetRoot.LocalID, delegate()
|
||||||
{
|
{
|
||||||
if (IsRoot(requestor) && HasAnyChildren)
|
if (HasAnyChildren)
|
||||||
RecomputeLinksetCompound();
|
RecomputeLinksetCompound();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -125,8 +124,7 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
{
|
{
|
||||||
// The root is going dynamic. Make sure mass is properly set.
|
// The root is going dynamic. Make sure mass is properly set.
|
||||||
m_mass = ComputeLinksetMass();
|
m_mass = ComputeLinksetMass();
|
||||||
if (HasAnyChildren)
|
ScheduleRebuild();
|
||||||
InternalRefresh(LinksetRoot);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -155,8 +153,7 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
DetailLog("{0},BSLinksetCompound.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child));
|
DetailLog("{0},BSLinksetCompound.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child));
|
||||||
if (IsRoot(child))
|
if (IsRoot(child))
|
||||||
{
|
{
|
||||||
if (HasAnyChildren)
|
ScheduleRebuild();
|
||||||
InternalRefresh(LinksetRoot);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -172,10 +169,21 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called at taint-time!!
|
public override void UpdateProperties(BSPhysObject updated, bool physicalUpdate)
|
||||||
public override void UpdateProperties(BSPhysObject updated)
|
|
||||||
{
|
{
|
||||||
// Nothing to do for compound linksets on property updates
|
// The user moving a child around requires the rebuilding of the linkset compound shape
|
||||||
|
// One problem is this happens when a border is crossed -- the simulator implementation
|
||||||
|
// is to store the position into the group which causes the move of the object
|
||||||
|
// but it also means all the child positions get updated.
|
||||||
|
// What would cause an unnecessary rebuild so we make sure the linkset is in a
|
||||||
|
// region before bothering to do a rebuild.
|
||||||
|
if (!IsRoot(updated)
|
||||||
|
&& !physicalUpdate
|
||||||
|
&& PhysicsScene.TerrainManager.IsWithinKnownTerrain(LinksetRoot.RawPosition))
|
||||||
|
{
|
||||||
|
updated.LinksetInfo = null;
|
||||||
|
ScheduleRebuild();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Routine called when rebuilding the body of some member of the linkset.
|
// Routine called when rebuilding the body of some member of the linkset.
|
||||||
|
@ -257,8 +265,8 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
|
|
||||||
DetailLog("{0},BSLinksetCompound.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID);
|
DetailLog("{0},BSLinksetCompound.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID);
|
||||||
|
|
||||||
// Cause constraints and assorted properties to be recomputed before the next simulation step.
|
// Rebuild the compound shape with the new child shape included
|
||||||
InternalRefresh(LinksetRoot);
|
ScheduleRebuild();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -285,8 +293,8 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Schedule a rebuild of the linkset before the next simulation tick.
|
// Rebuild the compound shape with the child removed
|
||||||
InternalRefresh(LinksetRoot);
|
ScheduleRebuild();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -78,7 +78,7 @@ public sealed class BSLinksetConstraints : BSLinkset
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called at taint-time!!
|
// Called at taint-time!!
|
||||||
public override void UpdateProperties(BSPhysObject updated)
|
public override void UpdateProperties(BSPhysObject updated, bool inTaintTime)
|
||||||
{
|
{
|
||||||
// Nothing to do for constraints on property updates
|
// Nothing to do for constraints on property updates
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,7 +214,7 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
{
|
{
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
// If the 'no collision' call, force it to happen right now so quick collision_end
|
// If the 'no collision' call, force it to happen right now so quick collision_end
|
||||||
bool force = CollisionCollection.Count == 0;
|
bool force = (CollisionCollection.Count == 0);
|
||||||
|
|
||||||
// throttle the collisions to the number of milliseconds specified in the subscription
|
// throttle the collisions to the number of milliseconds specified in the subscription
|
||||||
if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime))
|
if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime))
|
||||||
|
@ -232,8 +232,10 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
// DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count);
|
// DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count);
|
||||||
base.SendCollisionUpdate(CollisionCollection);
|
base.SendCollisionUpdate(CollisionCollection);
|
||||||
|
|
||||||
// The collisionCollection structure is passed around in the simulator.
|
// The CollisionCollection instance is passed around in the simulator.
|
||||||
// Make sure we don't have a handle to that one and that a new one is used for next time.
|
// Make sure we don't have a handle to that one and that a new one is used for next time.
|
||||||
|
// This fixes an interesting 'gotcha'. If we call CollisionCollection.Clear() here,
|
||||||
|
// a race condition is created for the other users of this instance.
|
||||||
CollisionCollection = new CollisionEventUpdate();
|
CollisionCollection = new CollisionEventUpdate();
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -251,6 +253,7 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
|
|
||||||
PhysicsScene.TaintedObject(TypeName+".SubscribeEvents", delegate()
|
PhysicsScene.TaintedObject(TypeName+".SubscribeEvents", delegate()
|
||||||
{
|
{
|
||||||
|
if (PhysBody.HasPhysicalBody)
|
||||||
CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
|
CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -300,6 +300,10 @@ public sealed class BSPrim : BSPhysObject
|
||||||
}
|
}
|
||||||
_position = value;
|
_position = value;
|
||||||
PositionSanityCheck(false);
|
PositionSanityCheck(false);
|
||||||
|
|
||||||
|
// A linkset might need to know if a component information changed.
|
||||||
|
Linkset.UpdateProperties(this, false);
|
||||||
|
|
||||||
PhysicsScene.TaintedObject("BSPrim.setPosition", delegate()
|
PhysicsScene.TaintedObject("BSPrim.setPosition", delegate()
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
||||||
|
@ -329,6 +333,14 @@ public sealed class BSPrim : BSPhysObject
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
|
||||||
|
if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(_position))
|
||||||
|
{
|
||||||
|
// The physical object is out of the known/simulated area.
|
||||||
|
// Upper levels of code will handle the transition to other areas so, for
|
||||||
|
// the time, we just ignore the position.
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position);
|
float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position);
|
||||||
OMV.Vector3 upForce = OMV.Vector3.Zero;
|
OMV.Vector3 upForce = OMV.Vector3.Zero;
|
||||||
if (RawPosition.Z < terrainHeight)
|
if (RawPosition.Z < terrainHeight)
|
||||||
|
@ -352,8 +364,6 @@ public sealed class BSPrim : BSPhysObject
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: check for out of bounds
|
|
||||||
|
|
||||||
// The above code computes a force to apply to correct any out-of-bounds problems. Apply same.
|
// The above code computes a force to apply to correct any out-of-bounds problems. Apply same.
|
||||||
// TODO: This should be intergrated with a geneal physics action mechanism.
|
// TODO: This should be intergrated with a geneal physics action mechanism.
|
||||||
// TODO: This should be moderated with PID'ness.
|
// TODO: This should be moderated with PID'ness.
|
||||||
|
@ -567,7 +577,10 @@ public sealed class BSPrim : BSPhysObject
|
||||||
if (_orientation == value)
|
if (_orientation == value)
|
||||||
return;
|
return;
|
||||||
_orientation = value;
|
_orientation = value;
|
||||||
// TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint?
|
|
||||||
|
// A linkset might need to know if a component information changed.
|
||||||
|
Linkset.UpdateProperties(this, false);
|
||||||
|
|
||||||
PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate()
|
PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate()
|
||||||
{
|
{
|
||||||
if (PhysBody.HasPhysicalBody)
|
if (PhysBody.HasPhysicalBody)
|
||||||
|
@ -1432,14 +1445,14 @@ public sealed class BSPrim : BSPhysObject
|
||||||
entprop.Velocity = _velocity;
|
entprop.Velocity = _velocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
// remember the current and last set values
|
|
||||||
LastEntityProperties = CurrentEntityProperties;
|
|
||||||
CurrentEntityProperties = entprop;
|
|
||||||
|
|
||||||
OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; // DEBUG DEBUG DEBUG
|
OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; // DEBUG DEBUG DEBUG
|
||||||
DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}",
|
DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}",
|
||||||
LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity);
|
LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity);
|
||||||
|
|
||||||
|
// remember the current and last set values
|
||||||
|
LastEntityProperties = CurrentEntityProperties;
|
||||||
|
CurrentEntityProperties = entprop;
|
||||||
|
|
||||||
base.RequestPhysicsterseUpdate();
|
base.RequestPhysicsterseUpdate();
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -1453,7 +1466,7 @@ public sealed class BSPrim : BSPhysObject
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// The linkset implimentation might want to know about this.
|
// The linkset implimentation might want to know about this.
|
||||||
Linkset.UpdateProperties(this);
|
Linkset.UpdateProperties(this, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -517,8 +517,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr);
|
out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr);
|
||||||
|
|
||||||
if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime);
|
if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime);
|
||||||
DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}",
|
DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}, objWColl={7}",
|
||||||
DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount);
|
DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps,
|
||||||
|
updatedEntityCount, collidersCount, ObjectsWithCollisions.Count);
|
||||||
if (VehiclePhysicalLoggingEnabled) DumpVehicles(); // DEBUG
|
if (VehiclePhysicalLoggingEnabled) DumpVehicles(); // DEBUG
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
@ -573,6 +574,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
|
|
||||||
// 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.
|
||||||
|
// This complex collision processing is required to create an empty collision
|
||||||
|
// event call after all collisions have happened on an object. This enables
|
||||||
|
// the simulator to generate the 'collision end' event.
|
||||||
if (ObjectsWithNoMoreCollisions.Count > 0)
|
if (ObjectsWithNoMoreCollisions.Count > 0)
|
||||||
{
|
{
|
||||||
foreach (BSPhysObject po in ObjectsWithNoMoreCollisions)
|
foreach (BSPhysObject po in ObjectsWithNoMoreCollisions)
|
||||||
|
@ -597,7 +601,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
|
|
||||||
ProcessPostStepTaints();
|
ProcessPostStepTaints();
|
||||||
|
|
||||||
// This causes the unmanaged code to output ALL the values found in ALL the objects in the world.
|
// The following causes the unmanaged code to output ALL the values found in ALL the objects in the world.
|
||||||
// Only enable this in a limited test world with few objects.
|
// Only enable this in a limited test world with few objects.
|
||||||
// BulletSimAPI.DumpAllInfo2(World.ptr); // DEBUG DEBUG DEBUG
|
// BulletSimAPI.DumpAllInfo2(World.ptr); // DEBUG DEBUG DEBUG
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue