BulletSim: remove code in ShapeCollection that hinted at shape sharing.

Add new function to ParameterDefn for calling BulletSimAPI to set values.
Tweaking to BSCharacter parameter setting to try and have avatars stand.
connector_plugin
Robert Adams 2012-10-15 12:11:00 -07:00
parent eaccfa6d99
commit fc33afddd3
5 changed files with 136 additions and 159 deletions

View File

@ -117,14 +117,6 @@ public class BSCharacter : BSPhysObject
PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, shapeData, null, null, null);
SetPhysicalProperties();
// Set the buoyancy for flying. This will be refactored when all the settings happen in C#.
// If not set at creation, the avatar will stop flying when created after crossing a region boundry.
ForceBuoyancy = _buoyancy;
// This works here because CreateObject has already put the character into the physical world.
BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr,
(uint)CollisionFilterGroups.AvatarFilter, (uint)CollisionFilterGroups.AvatarMask);
});
return;
}
@ -149,24 +141,29 @@ public class BSCharacter : BSPhysObject
OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw);
BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia);
ForcePosition = _position;
// Set the velocity and compute the proper friction
ForceVelocity = _velocity;
BulletSimAPI.SetFriction2(BSBody.ptr, _currentFriction);
BulletSimAPI.SetRestitution2(BSBody.ptr, PhysicsScene.Params.avatarRestitution);
BulletSimAPI.SetLocalScaling2(BSShape.ptr, Scale);
BulletSimAPI.SetContactProcessingThreshold2(BSBody.ptr, PhysicsScene.Params.contactProcessingThreshold);
if (PhysicsScene.Params.ccdMotionThreshold > 0f)
{
BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold);
BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius);
}
BulletSimAPI.SetActivationState2(BSBody.ptr, (int)ActivationState.DISABLE_DEACTIVATION);
BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_CHARACTER_OBJECT);
BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, BSBody.ptr);
BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_DEACTIVATION);
BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, BSBody.ptr);
// Do this after the object has been added to the world
BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr,
(uint)CollisionFilterGroups.AvatarFilter,
(uint)CollisionFilterGroups.AvatarMask);
}
public override void RequestPhysicsterseUpdate()
@ -174,9 +171,7 @@ public class BSCharacter : BSPhysObject
base.RequestPhysicsterseUpdate();
}
// No one calls this method so I don't know what it could possibly mean
public override bool Stopped {
get { return false; }
}
public override bool Stopped { get { return false; } }
public override OMV.Vector3 Size {
get
{
@ -185,18 +180,14 @@ public class BSCharacter : BSPhysObject
}
set {
// When an avatar's size is set, only the height is changed
// and that really only depends on the radius.
// When an avatar's size is set, only the height is changed.
_size = value;
ComputeAvatarScale(_size);
// TODO: something has to be done with the avatar's vertical position
ComputeAvatarVolumeAndMass();
PhysicsScene.TaintedObject("BSCharacter.setSize", delegate()
{
BulletSimAPI.SetLocalScaling2(BSBody.ptr, Scale);
BulletSimAPI.SetLocalScaling2(BSShape.ptr, Scale);
OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSBody.ptr, MassRaw);
BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia);
});
@ -300,7 +291,7 @@ public class BSCharacter : BSPhysObject
// A version of the sanity check that also makes sure a new position value is
// pushed back to the physics engine. This routine would be used by anyone
// who is not already pushing the value.
private bool PositionSanityCheck2(bool inTaintTime)
private bool PositionSanityCheck(bool inTaintTime)
{
bool ret = false;
if (PositionSanityCheck())
@ -378,14 +369,16 @@ public class BSCharacter : BSPhysObject
}
else
{
if (_currentFriction == 999f)
if (_currentFriction != PhysicsScene.Params.avatarFriction)
{
_currentFriction = PhysicsScene.Params.avatarFriction;
BulletSimAPI.SetFriction2(BSBody.ptr, _currentFriction);
}
}
_velocity = value;
// Remember the set velocity so we can suppress the reduction by friction, ...
_appliedVelocity = value;
BulletSimAPI.SetLinearVelocity2(BSBody.ptr, _velocity);
BulletSimAPI.Activate2(BSBody.ptr, true);
}
@ -590,7 +583,8 @@ public class BSCharacter : BSPhysObject
// The 1.15 came from ODE but it seems to cause the avatar to float off the ground
// Scale.Z = (_size.Z * 1.15f) - (Scale.X + Scale.Y);
newScale.Z = (_size.Z) - (Scale.X + Scale.Y);
// From the total height, remove the capsule half spheres that are at each end
newScale.Z = (size.Z) - (Math.Min(newScale.X, newScale.Y) * 2f);
Scale = newScale;
}
@ -621,7 +615,7 @@ public class BSCharacter : BSPhysObject
_acceleration = entprop.Acceleration;
_rotationalVelocity = entprop.RotationalVelocity;
// Do some sanity checking for the avatar. Make sure it's above ground and inbounds.
PositionSanityCheck2(true);
PositionSanityCheck(true);
// remember the current and last set values
LastEntityProperties = CurrentEntityProperties;

View File

@ -796,6 +796,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val);
delegate float ParamGet(BSScene scene);
delegate void ParamSet(BSScene scene, string paramName, uint localID, float val);
delegate void SetOnObject(BSScene scene, BSPhysObject obj, float val);
private struct ParameterDefn
{
@ -805,6 +806,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
public ParamUser userParam; // get the value from the configuration file
public ParamGet getter; // return the current value stored for this parameter
public ParamSet setter; // set the current value for this parameter
public SetOnObject onObject; // set the value on an object in the physical domain
public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s)
{
name = n;
@ -813,6 +815,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters
userParam = u;
getter = g;
setter = s;
onObject = null;
}
public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s, SetOnObject o)
{
name = n;
desc = d;
defaultValue = v;
userParam = u;
getter = g;
setter = s;
onObject = o;
}
}
@ -834,6 +847,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
//
// The single letter parameters for the delegates are:
// s = BSScene
// o = BSPhysObject
// p = string parameter name
// l = localID of referenced object
// v = float value
@ -943,65 +957,74 @@ public class BSScene : PhysicsScene, IPhysicsParameters
-9.80665f,
(s,cf,p,v) => { s.m_params[0].gravity = cf.GetFloat(p, v); },
(s) => { return s.m_params[0].gravity; },
(s,p,l,v) => { s.m_params[0].gravity = v; s.TaintedUpdateParameter(p,l,v); } ),
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].gravity, p, PhysParameterEntry.APPLY_TO_NONE, v); },
(s,o,v) => { BulletSimAPI.SetGravity2(s.World.ptr, new Vector3(0f,0f,v)); } ),
new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)",
0f,
(s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); },
(s) => { return s.m_params[0].linearDamping; },
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearDamping, p, l, v); } ),
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearDamping, p, l, v); },
(s,o,v) => { BulletSimAPI.SetDamping2(o.BSBody.ptr, v, v); } ),
new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)",
0f,
(s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); },
(s) => { return s.m_params[0].angularDamping; },
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularDamping, p, l, v); } ),
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularDamping, p, l, v); },
(s,o,v) => { BulletSimAPI.SetDamping2(o.BSBody.ptr, v, v); } ),
new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static",
0.2f,
(s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); },
(s) => { return s.m_params[0].deactivationTime; },
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].deactivationTime, p, l, v); } ),
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].deactivationTime, p, l, v); },
(s,o,v) => { BulletSimAPI.SetDeactivationTime2(o.BSBody.ptr, v); } ),
new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static",
0.8f,
(s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); },
(s) => { return s.m_params[0].linearSleepingThreshold; },
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearSleepingThreshold, p, l, v); } ),
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearSleepingThreshold, p, l, v); },
(s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.BSBody.ptr, v, v); } ),
new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static",
1.0f,
(s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); },
(s) => { return s.m_params[0].angularSleepingThreshold; },
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularSleepingThreshold, p, l, v); } ),
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularSleepingThreshold, p, l, v); },
(s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.BSBody.ptr, v, v); } ),
new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ,
0f, // set to zero to disable
(s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); },
(s) => { return s.m_params[0].ccdMotionThreshold; },
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdMotionThreshold, p, l, v); } ),
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdMotionThreshold, p, l, v); },
(s,o,v) => { BulletSimAPI.SetCcdMotionThreshold2(o.BSBody.ptr, v); } ),
new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" ,
0f,
(s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); },
(s) => { return s.m_params[0].ccdSweptSphereRadius; },
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); } ),
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); },
(s,o,v) => { BulletSimAPI.SetCcdSweepSphereRadius2(o.BSBody.ptr, v); } ),
new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" ,
0.1f,
(s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); },
(s) => { return s.m_params[0].contactProcessingThreshold; },
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); } ),
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); },
(s,o,v) => { BulletSimAPI.SetContactProcessingThreshold2(o.BSBody.ptr, v); } ),
new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" ,
0.5f,
(s,cf,p,v) => { s.m_params[0].terrainFriction = cf.GetFloat(p, v); },
(s) => { return s.m_params[0].terrainFriction; },
(s,p,l,v) => { s.m_params[0].terrainFriction = v; s.TaintedUpdateParameter(p,l,v); } ),
(s,p,l,v) => { s.m_params[0].terrainFriction = v; /* TODO: set on real terrain */} ),
new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" ,
0.8f,
(s,cf,p,v) => { s.m_params[0].terrainHitFraction = cf.GetFloat(p, v); },
(s) => { return s.m_params[0].terrainHitFraction; },
(s,p,l,v) => { s.m_params[0].terrainHitFraction = v; s.TaintedUpdateParameter(p,l,v); } ),
(s,p,l,v) => { s.m_params[0].terrainHitFraction = v; /* TODO: set on real terrain */ } ),
new ParameterDefn("TerrainRestitution", "Bouncyness" ,
0f,
(s,cf,p,v) => { s.m_params[0].terrainRestitution = cf.GetFloat(p, v); },
(s) => { return s.m_params[0].terrainRestitution; },
(s,p,l,v) => { s.m_params[0].terrainRestitution = v; s.TaintedUpdateParameter(p,l,v); } ),
(s,p,l,v) => { s.m_params[0].terrainRestitution = v; /* TODO: set on real terrain */ } ),
new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
0.2f,
(s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); },
@ -1228,58 +1251,55 @@ public class BSScene : PhysicsScene, IPhysicsParameters
return ret;
}
// check to see if we are updating a parameter for a particular or all of the prims
protected void UpdateParameterObject(ref float loc, string parm, uint localID, float val)
{
List<uint> operateOn;
lock (PhysObjects) operateOn = new List<uint>(PhysObjects.Keys);
UpdateParameterSet(operateOn, ref loc, parm, localID, val);
}
// update all the localIDs specified
// If the local ID is APPLY_TO_NONE, just change the default value
// If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs
// If the localID is a specific object, apply the parameter change to only that object
protected void UpdateParameterSet(List<uint> lIDs, ref float defaultLoc, string parm, uint localID, float val)
protected void UpdateParameterObject(ref float defaultLoc, string parm, uint localID, float val)
{
List<uint> objectIDs = new List<uint>();
switch (localID)
{
case PhysParameterEntry.APPLY_TO_NONE:
defaultLoc = val; // setting only the default value
// This will cause a call into the physical world if some operation is specified (SetOnObject).
objectIDs.Add(TERRAIN_ID);
TaintedUpdateParameter(parm, objectIDs, val);
break;
case PhysParameterEntry.APPLY_TO_ALL:
defaultLoc = val; // setting ALL also sets the default value
/*
List<uint> objectIDs = lIDs;
string xparm = parm.ToLower();
float xval = val;
TaintedObject("BSScene.UpdateParameterSet", delegate() {
foreach (uint lID in objectIDs)
{
BulletSimAPI.UpdateParameter(WorldID, lID, xparm, xval);
}
});
*/
lock (PhysObjects) objectIDs = new List<uint>(PhysObjects.Keys);
TaintedUpdateParameter(parm, objectIDs, val);
break;
default:
// setting only one localID
TaintedUpdateParameter(parm, localID, val);
objectIDs.Add(localID);
TaintedUpdateParameter(parm, objectIDs, val);
break;
}
}
// schedule the actual updating of the paramter to when the phys engine is not busy
protected void TaintedUpdateParameter(string parm, uint localID, float val)
protected void TaintedUpdateParameter(string parm, List<uint> lIDs, float val)
{
/* Settings in the C++ code are not working at the moment. TODO: fix the settings.
m_log.ErrorFormat("{0} Cannot change parameters of base objects. Someday it will be added.", LogHeader);
uint xlocalID = localID;
string xparm = parm.ToLower();
float xval = val;
TaintedObject("BSScene.TaintedUpdateParameter", delegate() {
BulletSimAPI.UpdateParameter(WorldID, xlocalID, xparm, xval);
List<uint> xlIDs = lIDs;
string xparm = parm;
TaintedObject("BSScene.UpdateParameterSet", delegate() {
ParameterDefn thisParam;
if (TryGetParameter(xparm, out thisParam))
{
if (thisParam.onObject != null)
{
foreach (uint lID in xlIDs)
{
BSPhysObject theObject = null;
PhysObjects.TryGetValue(lID, out theObject);
thisParam.onObject(this, theObject, xval);
}
}
}
});
*/
}
// Get parameter.

View File

@ -51,7 +51,7 @@ public class BSShapeCollection : IDisposable
}
// Description of a hull.
// Meshes and hulls have the same shape hash key but we only need hulls for efficient physical objects
// Meshes and hulls have the same shape hash key but we only need hulls for efficient collision calculations.
private struct HullDesc
{
public IntPtr ptr;
@ -59,17 +59,9 @@ public class BSShapeCollection : IDisposable
public DateTime lastReferenced;
}
private struct BodyDesc
{
public IntPtr ptr;
// Bodies are only used once so reference count is always either one or zero
public int referenceCount;
public DateTime lastReferenced;
}
// The sharable set of meshes and hulls. Indexed by their shape hash.
private Dictionary<System.UInt64, MeshDesc> Meshes = new Dictionary<System.UInt64, MeshDesc>();
private Dictionary<System.UInt64, HullDesc> Hulls = new Dictionary<System.UInt64, HullDesc>();
private Dictionary<uint, BodyDesc> Bodies = new Dictionary<uint, BodyDesc>();
public BSShapeCollection(BSScene physScene)
{
@ -92,6 +84,10 @@ public class BSShapeCollection : IDisposable
// First checks the shape and updates that if necessary then makes
// sure the body is of the right type.
// Return 'true' if either the body or the shape changed.
// 'shapeCallback' and 'bodyCallback' are, if non-null, functions called just before
// the current shape or body is destroyed. This allows the caller to remove any
// higher level dependencies on the shape or body. Mostly used for LinkSets to
// remove the physical constraints before the body is destroyed.
// Called at taint-time!!
public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPhysObject prim,
ShapeData shapeData, PrimitiveBaseShape pbs,
@ -103,7 +99,8 @@ public class BSShapeCollection : IDisposable
lock (m_collectionActivityLock)
{
// Do we have the correct geometry for this type of object?
// Updates prim.BSShape with information/pointers to requested shape
// Updates prim.BSShape with information/pointers to shape.
// CreateGeom returns 'true' of BSShape as changed to a new shape.
bool newGeom = CreateGeom(forceRebuild, prim, shapeData, pbs, shapeCallback);
// If we had to select a new shape geometry for the object,
// rebuild the body around it.
@ -125,35 +122,19 @@ public class BSShapeCollection : IDisposable
{
lock (m_collectionActivityLock)
{
BodyDesc bodyDesc;
if (Bodies.TryGetValue(body.ID, out bodyDesc))
DetailLog("{0},BSShapeCollection.ReferenceBody,newBody", body.ID, body);
BSScene.TaintCallback createOperation = delegate()
{
bodyDesc.referenceCount++;
DetailLog("{0},BSShapeCollection.ReferenceBody,existingBody,body={1},ref={2}", body.ID, body, bodyDesc.referenceCount);
}
else
{
// New entry
bodyDesc.ptr = body.ptr;
bodyDesc.referenceCount = 1;
DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,ref={2}",
body.ID, body, bodyDesc.referenceCount);
BSScene.TaintCallback createOperation = delegate()
if (!BulletSimAPI.IsInWorld2(body.ptr))
{
if (!BulletSimAPI.IsInWorld2(body.ptr))
{
BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr);
DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}",
body.ID, body);
}
};
if (inTaintTime)
createOperation();
else
PhysicsScene.TaintedObject("BSShapeCollection.ReferenceBody", createOperation);
}
bodyDesc.lastReferenced = System.DateTime.Now;
Bodies[body.ID] = bodyDesc;
BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr);
DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body);
}
};
if (inTaintTime)
createOperation();
else
PhysicsScene.TaintedObject("BSShapeCollection.ReferenceBody", createOperation);
}
}
@ -166,43 +147,25 @@ public class BSShapeCollection : IDisposable
lock (m_collectionActivityLock)
{
BodyDesc bodyDesc;
if (Bodies.TryGetValue(body.ID, out bodyDesc))
BSScene.TaintCallback removeOperation = delegate()
{
bodyDesc.referenceCount--;
bodyDesc.lastReferenced = System.DateTime.Now;
Bodies[body.ID] = bodyDesc;
DetailLog("{0},BSShapeCollection.DereferenceBody,ref={1}", body.ID, bodyDesc.referenceCount);
DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}, inTaintTime={2}",
body.ID, body.ptr.ToString("X"), inTaintTime);
// If the caller needs to know the old body is going away, pass the event up.
if (bodyCallback != null) bodyCallback(body);
// If body is no longer being used, free it -- bodies can never be shared.
if (bodyDesc.referenceCount == 0)
{
Bodies.Remove(body.ID);
BSScene.TaintCallback removeOperation = delegate()
{
DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}, inTaintTime={2}",
body.ID, body.ptr.ToString("X"), inTaintTime);
// If the caller needs to know the old body is going away, pass the event up.
if (bodyCallback != null) bodyCallback(body);
// It may have already been removed from the world in which case the next is a NOOP.
BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr);
// It may have already been removed from the world in which case the next is a NOOP.
BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr);
// Zero any reference to the shape so it is not freed when the body is deleted.
BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero);
BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr);
};
// If already in taint-time, do the operations now. Otherwise queue for later.
if (inTaintTime)
removeOperation();
else
PhysicsScene.TaintedObject("BSShapeCollection.DereferenceBody", removeOperation);
}
}
// Zero any reference to the shape so it is not freed when the body is deleted.
BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero);
BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr);
};
// If already in taint-time, do the operations now. Otherwise queue for later.
if (inTaintTime)
removeOperation();
else
{
DetailLog("{0},BSShapeCollection.DereferenceBody,DID NOT FIND BODY", body.ID, bodyDesc.referenceCount);
}
PhysicsScene.TaintedObject("BSShapeCollection.DereferenceBody", removeOperation);
}
}
@ -271,7 +234,6 @@ public class BSShapeCollection : IDisposable
}
// Release the usage of a shape.
// The collisionObject is released since it is a copy of the real collision shape.
public void DereferenceShape(BulletShape shape, bool inTaintTime, ShapeDestructionCallback shapeCallback)
{
if (shape.ptr == IntPtr.Zero)

View File

@ -334,7 +334,8 @@ public class BSTerrainManager
// Make sure the new shape is processed.
// BulletSimAPI.Activate2(mapInfo.terrainBody.ptr, true);
BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION);
BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.ISLAND_SLEEPING);
// BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION);
m_terrainModified = true;
};