// Called to update/change the body and shape for an object. // 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, BulletWorld sim, BSPhysObject prim, ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback) { PhysicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape"); bool ret = false; // This lock could probably be pushed down lower but building shouldn't take long lock (m_collectionActivityLock) { // Do we have the correct geometry for this type of object? // Updates prim.BSShape with information/pointers to shape. // Returns 'true' of BSShape is changed to a new shape. bool newGeom = CreateGeom(forceRebuild, prim, shapeCallback); // If we had to select a new shape geometry for the object, // rebuild the body around it. // Updates prim.BSBody with information/pointers to requested body // Returns 'true' if BSBody was changed. bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, prim.PhysShape, bodyCallback); ret = newGeom || newBody; } DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}", prim.LocalID, forceRebuild, ret, prim.PhysBody, prim.PhysShape); return(ret); }
// Create a body object in Bullet. // Updates prim.BSBody with the information about the new body if one is created. // Returns 'true' if an object was actually created. // Called at taint-time. private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletWorld sim, BulletShape shape, BodyDestructionCallback bodyCallback) { bool ret = false; // the mesh, hull or native shape must have already been created in Bullet bool mustRebuild = !prim.PhysBody.HasPhysicalBody; // If there is an existing body, verify it's of an acceptable type. // If not a solid object, body is a GhostObject. Otherwise a RigidBody. if (!mustRebuild) { CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(prim.PhysBody.ptr); if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT) { // If the collisionObject is not the correct type for solidness, rebuild what's there mustRebuild = true; } } if (mustRebuild || forceRebuild) { // Free any old body DereferenceBody(prim.PhysBody, true, bodyCallback); BulletBody aBody; Object bodyPtr = null; if (prim.IsSolid) { bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr, prim.LocalID, prim.RawPosition, prim.RawOrientation); if (DDetail) { DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString()); } } else { bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr, prim.LocalID, prim.RawPosition, prim.RawOrientation); if (DDetail) { DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString()); } } aBody = new BulletBody(prim.LocalID, bodyPtr); ReferenceBody(aBody, true); prim.PhysBody = aBody; ret = true; } return(ret); }
// Release the usage of a body. // Called when releasing use of a BSBody. BSShape is handled separately. public void DereferenceBody(BulletBody body, bool inTaintTime, BodyDestructionCallback bodyCallback) { if (body.ptr == IntPtr.Zero) { return; } lock (m_collectionActivityLock) { BodyDesc bodyDesc; if (Bodies.TryGetValue(body.ID, out bodyDesc)) { bodyDesc.referenceCount--; bodyDesc.lastReferenced = System.DateTime.Now; Bodies[body.ID] = bodyDesc; DetailLog("{0},BSShapeCollection.DereferenceBody,ref={1}", body.ID, bodyDesc.referenceCount); // If body is no longer being used, free it -- bodies are never shared. if (bodyDesc.referenceCount == 0) { Bodies.Remove(body.ID); BSScene.TaintCallback removeOperation = delegate() { DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}", body.ID, body.ptr.ToString("X")); // If the caller needs to know, pass the event up. if (bodyCallback != null) { bodyCallback(body); } // 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); // It may have already been removed from the world in which case the next is a NOOP. BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr); 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); } } } else { DetailLog("{0},BSShapeCollection.DereferenceBody,DID NOT FIND BODY", body.ID, bodyDesc.referenceCount); } } }
// Create a body object in Bullet. // Updates prim.BSBody with the information about the new body if one is created. // Returns 'true' if an object was actually created. // Called at taint-time. private bool CreateBody(bool forceRebuild, BSPrim prim, BulletSim sim, BulletShape shape, ShapeData shapeData, BodyDestructionCallback bodyCallback) { bool ret = false; // the mesh, hull or native shape must have already been created in Bullet bool mustRebuild = (prim.BSBody.ptr == IntPtr.Zero); // If there is an existing body, verify it's of an acceptable type. // If not a solid object, body is a GhostObject. Otherwise a RigidBody. if (!mustRebuild) { CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(prim.BSBody.ptr); if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT) { // If the collisionObject is not the correct type for solidness, rebuild what's there mustRebuild = true; } } if (mustRebuild || forceRebuild) { DereferenceBody(prim.BSBody, true, bodyCallback); BulletBody aBody; IntPtr bodyPtr = IntPtr.Zero; if (prim.IsSolid) { bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr, shapeData.ID, shapeData.Position, shapeData.Rotation); // DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); } else { bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr, shapeData.ID, shapeData.Position, shapeData.Rotation); // DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); } aBody = new BulletBody(shapeData.ID, bodyPtr); ReferenceBody(aBody, true); prim.BSBody = aBody; ret = true; } return(ret); }
// Called to update/change the body and shape for an object. // 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. // Called at taint-time!! public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback) { bool ret = false; // This lock could probably be pushed down lower but building shouldn't take long lock (m_collectionActivityLock) { // Do we have the correct geometry for this type of object? // Updates prim.BSShape with information/pointers to requested 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. // Updates prim.BSBody with information/pointers to requested body bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, prim.BSShape, shapeData, bodyCallback); ret = newGeom || newBody; } DetailLog("{0},BSShapeCollection.GetBodyAndShape,force={1},ret={2},body={3},shape={4}", prim.LocalID, forceRebuild, ret, prim.BSBody, prim.BSShape); return(ret); }
// Release the usage of a body. // Called when releasing use of a BSBody. BSShape is handled separately. public void DereferenceBody(BulletBody body, bool inTaintTime, BodyDestructionCallback bodyCallback) { if (!body.HasPhysicalBody) { return; } lock (m_collectionActivityLock) { PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceBody", delegate() { if (DDetail) { DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1},inTaintTime={2}", body.ID, body, inTaintTime); } // If the caller needs to know the old body is going away, pass the event up. if (bodyCallback != null) { bodyCallback(body); } if (BulletSimAPI.IsInWorld2(PhysicsScene.World.ptr, body.ptr)) { BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr); if (DDetail) { DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body); } } // Zero any reference to the shape so it is not freed when the body is deleted. BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, null); BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr); }); } }
// Create a body object in Bullet. // Updates prim.BSBody with the information about the new body if one is created. // Returns 'true' if an object was actually created. // Called at taint-time. private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletWorld sim, BodyDestructionCallback bodyCallback) { bool ret = false; // the mesh, hull or native shape must have already been created in Bullet bool mustRebuild = !prim.PhysBody.HasPhysicalBody; // If there is an existing body, verify it's of an acceptable type. // If not a solid object, body is a GhostObject. Otherwise a RigidBody. if (!mustRebuild) { CollisionObjectTypes bodyType = (CollisionObjectTypes)PhysicsScene.PE.GetBodyType(prim.PhysBody); if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT) { // If the collisionObject is not the correct type for solidness, rebuild what's there mustRebuild = true; if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,forceRebuildBecauseChangingBodyType,bodyType={1}", prim.LocalID, bodyType); } } if (mustRebuild || forceRebuild) { // Free any old body DereferenceBody(prim.PhysBody, bodyCallback); BulletBody aBody; if (prim.IsSolid) { aBody = PhysicsScene.PE.CreateBodyFromShape(sim, prim.PhysShape, prim.LocalID, prim.RawPosition, prim.RawOrientation); if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,mesh,body={1}", prim.LocalID, aBody); } else { aBody = PhysicsScene.PE.CreateGhostFromShape(sim, prim.PhysShape, prim.LocalID, prim.RawPosition, prim.RawOrientation); if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,ghost,body={1}", prim.LocalID, aBody); } ReferenceBody(aBody); prim.PhysBody = aBody; ret = true; } return ret; }
// Release the usage of a body. // Called when releasing use of a BSBody. BSShape is handled separately. // Called in taint time. public void DereferenceBody(BulletBody body, BodyDestructionCallback bodyCallback ) { if (!body.HasPhysicalBody) return; PhysicsScene.AssertInTaintTime("BSShapeCollection.DereferenceBody"); lock (m_collectionActivityLock) { if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1}", body.ID, body); // If the caller needs to know the old body is going away, pass the event up. if (bodyCallback != null) bodyCallback(body); if (PhysicsScene.PE.IsInWorld(PhysicsScene.World, body)) { PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, body); if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body); } // Zero any reference to the shape so it is not freed when the body is deleted. PhysicsScene.PE.SetCollisionShape(PhysicsScene.World, body, null); PhysicsScene.PE.DestroyObject(PhysicsScene.World, body); } }
// Called to update/change the body and shape for an object. // 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, BulletWorld sim, BSPhysObject prim, ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback) { PhysicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape"); bool ret = false; // This lock could probably be pushed down lower but building shouldn't take long lock (m_collectionActivityLock) { // Do we have the correct geometry for this type of object? // Updates prim.BSShape with information/pointers to shape. // Returns 'true' of BSShape is changed to a new shape. bool newGeom = CreateGeom(forceRebuild, prim, shapeCallback); // If we had to select a new shape geometry for the object, // rebuild the body around it. // Updates prim.BSBody with information/pointers to requested body // Returns 'true' if BSBody was changed. bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, bodyCallback); ret = newGeom || newBody; } DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}", prim.LocalID, forceRebuild, ret, prim.PhysBody, prim.PhysShape); return ret; }
// Called to update/change the body and shape for an object. // 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. // Called at taint-time!! public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback) { bool ret = false; // This lock could probably be pushed down lower but building shouldn't take long lock (m_collectionActivityLock) { // Do we have the correct geometry for this type of object? // Updates prim.BSShape with information/pointers to requested 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. // Updates prim.BSBody with information/pointers to requested body bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, prim.BSShape, shapeData, bodyCallback); ret = newGeom || newBody; } DetailLog("{0},BSShapeCollection.GetBodyAndShape,force={1},ret={2},body={3},shape={4}", prim.LocalID, forceRebuild, ret, prim.BSBody, prim.BSShape); return ret; }
// Create a body object in Bullet. // Updates prim.BSBody with the information about the new body if one is created. // Returns 'true' if an object was actually created. // Called at taint-time. private bool CreateBody(bool forceRebuild, BSPrim prim, BulletSim sim, BulletShape shape, ShapeData shapeData, BodyDestructionCallback bodyCallback) { bool ret = false; // the mesh, hull or native shape must have already been created in Bullet bool mustRebuild = (prim.BSBody.ptr == IntPtr.Zero); // If there is an existing body, verify it's of an acceptable type. // If not a solid object, body is a GhostObject. Otherwise a RigidBody. if (!mustRebuild) { CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(prim.BSBody.ptr); if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT) { // If the collisionObject is not the correct type for solidness, rebuild what's there mustRebuild = true; } } if (mustRebuild || forceRebuild) { DereferenceBody(prim.BSBody, true, bodyCallback); BulletBody aBody; IntPtr bodyPtr = IntPtr.Zero; if (prim.IsSolid) { bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr, shapeData.ID, shapeData.Position, shapeData.Rotation); // DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); } else { bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr, shapeData.ID, shapeData.Position, shapeData.Rotation); // DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); } aBody = new BulletBody(shapeData.ID, bodyPtr); ReferenceBody(aBody, true); prim.BSBody = aBody; ret = true; } return ret; }
// Release the usage of a body. // Called when releasing use of a BSBody. BSShape is handled separately. public void DereferenceBody(BulletBody body, bool inTaintTime, BodyDestructionCallback bodyCallback ) { if (body.ptr == IntPtr.Zero) return; lock (m_collectionActivityLock) { BodyDesc bodyDesc; if (Bodies.TryGetValue(body.ID, out bodyDesc)) { bodyDesc.referenceCount--; bodyDesc.lastReferenced = System.DateTime.Now; Bodies[body.ID] = bodyDesc; DetailLog("{0},BSShapeCollection.DereferenceBody,ref={1}", body.ID, bodyDesc.referenceCount); // If body is no longer being used, free it -- bodies are never shared. if (bodyDesc.referenceCount == 0) { Bodies.Remove(body.ID); BSScene.TaintCallback removeOperation = delegate() { DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}", body.ID, body.ptr.ToString("X")); // If the caller needs to know the old body is going away, pass the event up. if (bodyCallback != null) bodyCallback(body); // 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); // It may have already been removed from the world in which case the next is a NOOP. BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr); 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); } } else { DetailLog("{0},BSShapeCollection.DereferenceBody,DID NOT FIND BODY", body.ID, bodyDesc.referenceCount); } } }
// Release the usage of a body. // Called when releasing use of a BSBody. BSShape is handled separately. public void DereferenceBody(BulletBody body, bool inTaintTime, BodyDestructionCallback bodyCallback ) { if (body.ptr == IntPtr.Zero) return; lock (m_collectionActivityLock) { 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); // 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); } }
// Release the usage of a body. // Called when releasing use of a BSBody. BSShape is handled separately. public void DereferenceBody(BulletBody body, bool inTaintTime, BodyDestructionCallback bodyCallback ) { if (!body.HasPhysicalBody) return; lock (m_collectionActivityLock) { PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceBody", delegate() { if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1},inTaintTime={2}", body.ID, body, inTaintTime); // If the caller needs to know the old body is going away, pass the event up. if (bodyCallback != null) bodyCallback(body); if (BulletSimAPI.IsInWorld2(PhysicsScene.World.ptr, body.ptr)) { BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr); if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body); } // Zero any reference to the shape so it is not freed when the body is deleted. BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, null); BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr); }); } }