From 74dea4cfd52be75b4dd6277260c3ada80b939fbb Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 27 Sep 2012 19:57:35 -0700 Subject: BulletSim: rename some constraint variables to be consistant with other name use. Added callbacks for shape and body changes in GetBodyAndShape() so the linkset constraints can be picked up and restored. A better design might be to have a "prim shape changed" event. Think about that. Added constraint types to general constraint class. --- .../Physics/BulletSPlugin/BS6DofConstraint.cs | 42 +++-- .../Region/Physics/BulletSPlugin/BSConstraint.cs | 21 ++- .../Physics/BulletSPlugin/BSHingeConstraint.cs | 2 + OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 182 +++++++++++++-------- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 14 +- .../Physics/BulletSPlugin/BSShapeCollection.cs | 65 +++++--- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 21 ++- 7 files changed, 231 insertions(+), 116 deletions(-) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs index 39a3421..3306a97 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs @@ -34,6 +34,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin public class BS6DofConstraint : BSConstraint { + private static string LogHeader = "[BULLETSIM 6DOF CONSTRAINT]"; + + public override ConstraintType Type { get { return ConstraintType.D6_CONSTRAINT_TYPE; } } + // Create a btGeneric6DofConstraint public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, Vector3 frame1, Quaternion frame1rot, @@ -49,6 +53,9 @@ public class BS6DofConstraint : BSConstraint frame2, frame2rot, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); m_enabled = true; + world.physicsScene.DetailLog("{0},BS6DofConstraint,createFrame,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", + BSScene.DetailLogZero, world.worldID, + obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); } public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, @@ -60,12 +67,13 @@ public class BS6DofConstraint : BSConstraint m_body2 = obj2; if (obj1.ptr == IntPtr.Zero || obj2.ptr == IntPtr.Zero) { - world.scene.DetailLog("{0},BS6DOFConstraint,badBodyPtr,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", - "[BULLETSIM 6DOF CONSTRAINT]", world.worldID, + world.physicsScene.DetailLog("{0},BS6DOFConstraint,badBodyPtr,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", + BSScene.DetailLogZero, world.worldID, obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); - world.scene.Logger.ErrorFormat("{0} Attempt to build 6DOF constraint with missing bodies: wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", + world.physicsScene.Logger.ErrorFormat("{0} Attempt to build 6DOF constraint with missing bodies: wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", "[BULLETSIM 6DOF CONSTRAINT]", world.worldID, obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); + m_enabled = false; } else { @@ -73,8 +81,20 @@ public class BS6DofConstraint : BSConstraint BulletSimAPI.Create6DofConstraintToPoint2(m_world.ptr, m_body1.ptr, m_body2.ptr, joinPoint, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); + world.physicsScene.DetailLog("{0},BS6DofConstraint,createMidPoint,wID={1}, csrt={2}, rID={3}, rBody={4}, cID={5}, cBody={6}", + BSScene.DetailLogZero, world.worldID, m_constraint.ptr.ToString("X"), + obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); + if (m_constraint.ptr == IntPtr.Zero) + { + world.physicsScene.Logger.ErrorFormat("{0} Failed creation of 6Dof constraint. rootID={1}, childID={2}", + LogHeader, obj1.ID, obj2.ID); + m_enabled = false; + } + else + { + m_enabled = true; + } } - m_enabled = true; } public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot) @@ -82,7 +102,7 @@ public class BS6DofConstraint : BSConstraint bool ret = false; if (m_enabled) { - BulletSimAPI.SetFrames2(m_constraint.Ptr, frameA, frameArot, frameB, frameBrot); + BulletSimAPI.SetFrames2(m_constraint.ptr, frameA, frameArot, frameB, frameBrot); ret = true; } return ret; @@ -93,9 +113,9 @@ public class BS6DofConstraint : BSConstraint bool ret = false; if (m_enabled) { - BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL); - BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL); - BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL); + BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL); + BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL); + BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL); ret = true; } return ret; @@ -106,7 +126,7 @@ public class BS6DofConstraint : BSConstraint bool ret = false; float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; if (m_enabled) - ret = BulletSimAPI.UseFrameOffset2(m_constraint.Ptr, onOff); + ret = BulletSimAPI.UseFrameOffset2(m_constraint.ptr, onOff); return ret; } @@ -115,7 +135,7 @@ public class BS6DofConstraint : BSConstraint bool ret = false; float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; if (m_enabled) - ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce); + ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.ptr, onOff, targetVelocity, maxMotorForce); return ret; } @@ -123,7 +143,7 @@ public class BS6DofConstraint : BSConstraint { bool ret = false; if (m_enabled) - ret = BulletSimAPI.SetBreakingImpulseThreshold2(m_constraint.Ptr, threshold); + ret = BulletSimAPI.SetBreakingImpulseThreshold2(m_constraint.ptr, threshold); return ret; } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs index c21252b..63a4127 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs @@ -49,20 +49,23 @@ public abstract class BSConstraint : IDisposable if (m_enabled) { m_enabled = false; - bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.Ptr); - m_world.scene.DetailLog("{0},BSConstraint.Dispose,taint,body1={1},body2={2},success={3}", BSScene.DetailLogZero, m_body1.ID, m_body2.ID, success); - m_constraint.Ptr = System.IntPtr.Zero; + bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.ptr); + m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,body1={1},body2={2},success={3}", BSScene.DetailLogZero, m_body1.ID, m_body2.ID, success); + m_constraint.ptr = System.IntPtr.Zero; } } public BulletBody Body1 { get { return m_body1; } } public BulletBody Body2 { get { return m_body2; } } + public BulletConstraint Constraint { get { return m_constraint; } } + public abstract ConstraintType Type { get; } + public virtual bool SetLinearLimits(Vector3 low, Vector3 high) { bool ret = false; if (m_enabled) - ret = BulletSimAPI.SetLinearLimits2(m_constraint.Ptr, low, high); + ret = BulletSimAPI.SetLinearLimits2(m_constraint.ptr, low, high); return ret; } @@ -70,7 +73,7 @@ public abstract class BSConstraint : IDisposable { bool ret = false; if (m_enabled) - ret = BulletSimAPI.SetAngularLimits2(m_constraint.Ptr, low, high); + ret = BulletSimAPI.SetAngularLimits2(m_constraint.ptr, low, high); return ret; } @@ -79,7 +82,7 @@ public abstract class BSConstraint : IDisposable bool ret = false; if (m_enabled) { - BulletSimAPI.SetConstraintNumSolverIterations2(m_constraint.Ptr, cnt); + BulletSimAPI.SetConstraintNumSolverIterations2(m_constraint.ptr, cnt); ret = true; } return ret; @@ -91,7 +94,7 @@ public abstract class BSConstraint : IDisposable if (m_enabled) { // Recompute the internal transforms - BulletSimAPI.CalculateTransforms2(m_constraint.Ptr); + BulletSimAPI.CalculateTransforms2(m_constraint.ptr); ret = true; } return ret; @@ -110,11 +113,11 @@ public abstract class BSConstraint : IDisposable // Setting an object's mass to zero (making it static like when it's selected) // automatically disables the constraints. // If the link is enabled, be sure to set the constraint itself to enabled. - BulletSimAPI.SetConstraintEnable2(m_constraint.Ptr, m_world.scene.NumericBool(true)); + BulletSimAPI.SetConstraintEnable2(m_constraint.ptr, m_world.physicsScene.NumericBool(true)); } else { - m_world.scene.Logger.ErrorFormat("[BULLETSIM CONSTRAINT] CalculateTransforms failed. A={0}, B={1}", Body1.ID, Body2.ID); + m_world.physicsScene.Logger.ErrorFormat("[BULLETSIM CONSTRAINT] CalculateTransforms failed. A={0}, B={1}", Body1.ID, Body2.ID); } } return ret; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs index a6e4235..7c8a215 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs @@ -34,6 +34,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin class BSHingeConstraint : BSConstraint { + public override ConstraintType Type { get { return ConstraintType.HINGE_CONSTRAINT_TYPE; } } + public BSHingeConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, Vector3 pivotInA, Vector3 pivotInB, Vector3 axisInA, Vector3 axisInB, diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index b0cc63c..dff71af 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -88,6 +88,7 @@ public class BSLinkset // Link to a linkset where the child knows the parent. // Parent changing should not happen so do some sanity checking. // We return the parent's linkset so the child can track its membership. + // Called at runtime. public BSLinkset AddMeToLinkset(BSPhysObject child) { lock (m_linksetActivityLock) @@ -102,6 +103,7 @@ public class BSLinkset // Remove a child from a linkset. // Returns a new linkset for the child which is a linkset of one (just the // orphened child). + // Called at runtime. public BSLinkset RemoveMeFromLinkset(BSPhysObject child) { lock (m_linksetActivityLock) @@ -113,27 +115,6 @@ public class BSLinkset } RemoveChildFromLinkset(child); - - /* Alternate implementation that destroys the linkset of the root is removed. - * This fails because items are added and removed from linksets to build shapes. - * Code left for reference. - if (IsRoot(child)) - { - // if root of linkset, take the linkset apart - while (m_children.Count > 0) - { - // Note that we don't do a foreach because the remove routine - // takes it out of the list. - RemoveChildFromOtherLinkset(m_children[0]); - } - m_children.Clear(); // just to make sure - } - else - { - // Just removing a child from an existing linkset - RemoveChildFromLinkset(child); - } - */ } // The child is down to a linkset of just itself @@ -169,6 +150,106 @@ public class BSLinkset return ret; } + // The object is going dynamic (physical). Do any setup necessary + // for a dynamic linkset. + // Only the state of the passed object can be modified. The rest of the linkset + // has not yet been fully constructed. + // Return 'true' if any properties updated on the passed object. + // Called at taint-time! + public bool MakeDynamic(BSPhysObject child) + { + // What is done for each object in BSPrim is what we want. + return false; + } + + // The object is going static (non-physical). Do any setup necessary + // for a static linkset. + // Return 'true' if any properties updated on the passed object. + // Called at taint-time! + public bool MakeStatic(BSPhysObject child) + { + // What is done for each object in BSPrim is what we want. + return false; + } + + // When physical properties are changed the linkset needs to recalculate + // its internal properties. + // Called at runtime. + public void Refresh(BSPhysObject requestor) + { + // If there are no children, there can't be any constraints to recompute + if (!HasAnyChildren) + return; + + // Only the root does the recomputation + if (IsRoot(requestor)) + { + PhysicsScene.TaintedObject("BSLinkSet.Refresh", delegate() + { + RecomputeLinksetConstraintVariables(); + }); + } + } + + // Routine used when rebuilding the body of the root of the linkset + // Destroy all the constraints have have been made to root. + // This is called when the root body is changing. + // Called at taint-time!! + public void RemoveBodyDependencies(BSPrim child) + { + lock (m_linksetActivityLock) + { + if (IsRoot(child)) + { + // If the one with the dependency is root, must undo all children + DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeChildrenForRoot,rID={1},numChild={2}", + LinksetRoot.LocalID, m_children.Count); + foreach (BSPhysObject bpo in m_children) + { + PhysicallyUnlinkAChildFromRoot(LinksetRoot, LinksetRoot.BSBody, bpo, bpo.BSBody); + } + } + else + { + DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeSingleChild,rID={1},rBody={2},cID={3},cBody={4}", + LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), + child.LocalID, child.BSBody.ptr.ToString("X")); + // Remove the dependency on the body of this one + PhysicallyUnlinkAChildFromRoot(LinksetRoot, LinksetRoot.BSBody, child, child.BSBody); + } + } + } + + // Routine used when rebuilding the body of the root of the linkset + // This is called after RemoveAllLinksToRoot() to restore all the constraints. + // This is called when the root body has been changed. + // Called at taint-time!! + public void RestoreBodyDependencies(BSPrim child) + { + lock (m_linksetActivityLock) + { + if (IsRoot(child)) + { + DetailLog("{0},BSLinkset.RestoreBodyDependencies,restoreChildrenForRoot,rID={1},numChild={2}", + LinksetRoot.LocalID, m_children.Count); + foreach (BSPhysObject bpo in m_children) + { + PhysicallyLinkAChildToRoot(LinksetRoot, LinksetRoot.BSBody, bpo, bpo.BSBody); + } + } + else + { + DetailLog("{0},BSLinkset.RestoreBodyDependencies,restoreSingleChild,rID={1},rBody={2},cID={3},cBody={4}", + LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), + child.LocalID, child.BSBody.ptr.ToString("X")); + PhysicallyLinkAChildToRoot(LinksetRoot, LinksetRoot.BSBody, child, child.BSBody); + } + } + } + + // ================================================================ + // Below this point is internal magic + private float ComputeLinksetMass() { float mass; @@ -220,46 +301,6 @@ public class BSLinkset return com; } - // The object is going dynamic (physical). Do any setup necessary - // for a dynamic linkset. - // Only the state of the passed object can be modified. The rest of the linkset - // has not yet been fully constructed. - // Return 'true' if any properties updated on the passed object. - // Called at taint-time! - public bool MakeDynamic(BSPhysObject child) - { - // What is done for each object in BSPrim is what we want. - return false; - } - - // The object is going static (non-physical). Do any setup necessary - // for a static linkset. - // Return 'true' if any properties updated on the passed object. - // Called at taint-time! - public bool MakeStatic(BSPhysObject child) - { - // What is done for each object in BSPrim is what we want. - return false; - } - - // When physical properties are changed the linkset needs to recalculate - // its internal properties. - public void Refresh(BSPhysObject requestor) - { - // If there are no children, there can't be any constraints to recompute - if (!HasAnyChildren) - return; - - // Only the root does the recomputation - if (IsRoot(requestor)) - { - PhysicsScene.TaintedObject("BSLinkSet.Refresh", delegate() - { - RecomputeLinksetConstraintVariables(); - }); - } - } - // Call each of the constraints that make up this linkset and recompute the // various transforms and variables. Used when objects are added or removed // from a linkset to make sure the constraints know about the new mass and @@ -327,6 +368,11 @@ public class BSLinkset BSPhysObject childx = child; BulletBody childBodyx = child.BSBody; + DetailLog("{0},AddChildToLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", + rootx.LocalID, + rootx.LocalID, rootBodyx.ptr.ToString("X"), + childx.LocalID, childBodyx.ptr.ToString("X")); + PhysicsScene.TaintedObject("AddChildToLinkset", delegate() { DetailLog("{0},AddChildToLinkset,taint,child={1}", LinksetRoot.LocalID, child.LocalID); @@ -358,10 +404,14 @@ public class BSLinkset BulletBody rootBodyx = LinksetRoot.BSBody; BSPhysObject childx = child; BulletBody childBodyx = child.BSBody; + + DetailLog("{0},RemoveChildFromLinkset,call,child={1}", + rootx.LocalID, + rootx.LocalID, rootBodyx.ptr.ToString("X"), + childx.LocalID, childBodyx.ptr.ToString("X")); + PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate() { - DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", LinksetRoot.LocalID, child.LocalID); - PhysicallyUnlinkAChildFromRoot(rootx, rootBodyx, childx, childBodyx); RecomputeLinksetConstraintVariables(); }); @@ -390,14 +440,15 @@ public class BSLinkset // real world coordinate of midpoint between the two objects OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); - // create a constraint that allows no freedom of movement between the two objects - // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", rootPrim.LocalID, rootPrim.LocalID, rootBody.ptr.ToString("X"), childPrim.LocalID, childBody.ptr.ToString("X"), rootPrim.Position, childPrim.Position, midPoint); + // create a constraint that allows no freedom of movement between the two objects + // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 + // There is great subtlty in these paramters. Notice the check for a ptr of zero. // We pass the BulletBody structure into the taint in order to capture the pointer // of the body at the time of constraint creation. This doesn't work for the very first @@ -416,6 +467,7 @@ public class BSLinkset true, true ); + /* NOTE: below is an attempt to build constraint with full frame computation, etc. * Using the midpoint is easier since it lets the Bullet code manipulate the transforms * of the objects. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 8688485..c879143 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -1111,13 +1111,21 @@ public sealed class BSPrim : BSPhysObject // Undo me from any possible linkset so, if body is rebuilt, the link will get restored. // NOTE that the new linkset is not set. This saves the handle to the linkset // so we can add ourselves back when shape mangling is complete. - Linkset.RemoveMeFromLinkset(this); + bool needToRestoreLinkset = false; // Create the correct physical representation for this type of object. // Updates BSBody and BSShape with the new information. - PhysicsScene.Shapes.GetBodyAndShape(forceRebuild, PhysicsScene.World, this, shapeData, _pbs); + PhysicsScene.Shapes.GetBodyAndShape(forceRebuild, PhysicsScene.World, this, shapeData, _pbs, + null, delegate(BulletBody dBody) + { + // Called if the current prim body is about to be destroyed. + // The problem is the constraints for Linksets which need to be updated for the new body. + Linkset.RemoveBodyDependencies(this); + needToRestoreLinkset = true; + }); - Linkset = Linkset.AddMeToLinkset(this); + if (needToRestoreLinkset) + Linkset.RestoreBodyDependencies(this); // Make sure the properties are set on the new object UpdatePhysicalParameters(); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index b428ba3..2618971 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -81,12 +81,21 @@ public class BSShapeCollection : IDisposable // TODO!!!!!!!!! } + // Callbacks called just before either the body or shape is destroyed. + // Mostly used for changing bodies out from under Linksets. + // Useful for other cases where parameters need saving. + // Passing 'null' says no callback. + public delegate void ShapeDestructionCallback(BulletShape shape); + public delegate void BodyDestructionCallback(BulletBody 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. // Called at taint-time!! - public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs) + public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPrim prim, + ShapeData shapeData, PrimitiveBaseShape pbs, + ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback) { bool ret = false; @@ -95,11 +104,11 @@ public class BSShapeCollection : IDisposable { // 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); + 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); + 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}", @@ -135,7 +144,7 @@ public class BSShapeCollection : IDisposable // Release the usage of a body. // Called when releasing use of a BSBody. BSShape is handled separately. - public void DereferenceBody(BulletBody shape, bool inTaintTime) + public void DereferenceBody(BulletBody shape, bool inTaintTime, BodyDestructionCallback bodyCallback ) { if (shape.ptr == IntPtr.Zero) return; @@ -244,7 +253,7 @@ public class BSShapeCollection : IDisposable // Release the usage of a shape. // The collisionObject is released since it is a copy of the real collision shape. - private void DereferenceShape(BulletShape shape, bool atTaintTime) + private void DereferenceShape(BulletShape shape, bool atTaintTime, ShapeDestructionCallback shapeCallback) { if (shape.ptr == IntPtr.Zero) return; @@ -254,10 +263,10 @@ public class BSShapeCollection : IDisposable switch (shape.type) { case ShapeData.PhysicsShapeType.SHAPE_HULL: - DereferenceHull(shape); + DereferenceHull(shape, shapeCallback); break; case ShapeData.PhysicsShapeType.SHAPE_MESH: - DereferenceMesh(shape); + DereferenceMesh(shape, shapeCallback); break; case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN: break; @@ -267,6 +276,7 @@ public class BSShapeCollection : IDisposable { DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}", BSScene.DetailLogZero, shape.ptr.ToString("X"), atTaintTime); + if (shapeCallback != null) shapeCallback(shape); BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); } break; @@ -287,13 +297,14 @@ public class BSShapeCollection : IDisposable // Count down the reference count for a mesh shape // Called at taint-time. - private void DereferenceMesh(BulletShape shape) + private void DereferenceMesh(BulletShape shape, ShapeDestructionCallback shapeCallback) { MeshDesc meshDesc; if (Meshes.TryGetValue(shape.shapeKey, out meshDesc)) { meshDesc.referenceCount--; // TODO: release the Bullet storage + if (shapeCallback != null) shapeCallback(shape); meshDesc.lastReferenced = System.DateTime.Now; Meshes[shape.shapeKey] = meshDesc; DetailLog("{0},BSShapeCollection.DereferenceMesh,key={1},refCnt={2}", @@ -304,13 +315,14 @@ public class BSShapeCollection : IDisposable // Count down the reference count for a hull shape // Called at taint-time. - private void DereferenceHull(BulletShape shape) + private void DereferenceHull(BulletShape shape, ShapeDestructionCallback shapeCallback) { HullDesc hullDesc; if (Hulls.TryGetValue(shape.shapeKey, out hullDesc)) { hullDesc.referenceCount--; // TODO: release the Bullet storage (aging old entries?) + if (shapeCallback != null) shapeCallback(shape); hullDesc.lastReferenced = System.DateTime.Now; Hulls[shape.shapeKey] = hullDesc; DetailLog("{0},BSShapeCollection.DereferenceHull,key={1},refCnt={2}", @@ -324,7 +336,8 @@ public class BSShapeCollection : IDisposable // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used. // Returns 'true' if the geometry was rebuilt. // Called at taint-time! - private bool CreateGeom(bool forceRebuild, BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs) + private bool CreateGeom(bool forceRebuild, BSPrim prim, ShapeData shapeData, + PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback) { bool ret = false; bool haveShape = false; @@ -349,8 +362,8 @@ public class BSShapeCollection : IDisposable || prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE ) { - ret = GetReferenceToNativeShape(prim, shapeData, - ShapeData.PhysicsShapeType.SHAPE_SPHERE, ShapeData.FixedShapeKey.KEY_SPHERE); + ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_SPHERE, + ShapeData.FixedShapeKey.KEY_SPHERE, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}", prim.LocalID, forceRebuild, prim.BSShape); } @@ -363,8 +376,8 @@ public class BSShapeCollection : IDisposable || prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX ) { - ret = GetReferenceToNativeShape( - prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_BOX, ShapeData.FixedShapeKey.KEY_BOX); + ret = GetReferenceToNativeShape( prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_BOX, + ShapeData.FixedShapeKey.KEY_BOX, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}", prim.LocalID, forceRebuild, prim.BSShape); } @@ -378,13 +391,13 @@ public class BSShapeCollection : IDisposable if (prim.IsPhysical) { // Update prim.BSShape to reference a hull of this shape. - ret = GetReferenceToHull(prim, shapeData, pbs); + ret = GetReferenceToHull(prim, shapeData, pbs, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}", shapeData.ID, prim.BSShape, prim.BSShape.shapeKey.ToString("X")); } else { - ret = GetReferenceToMesh(prim, shapeData, pbs); + ret = GetReferenceToMesh(prim, shapeData, pbs, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}", shapeData.ID, prim.BSShape, prim.BSShape.shapeKey.ToString("X")); } @@ -394,7 +407,8 @@ public class BSShapeCollection : IDisposable // Creates a native shape and assignes it to prim.BSShape private bool GetReferenceToNativeShape( BSPrim prim, ShapeData shapeData, - ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey) + ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey, + ShapeDestructionCallback shapeCallback) { BulletShape newShape; @@ -404,7 +418,7 @@ public class BSShapeCollection : IDisposable shapeData.Scale = shapeData.Size; // release any previous shape - DereferenceShape(prim.BSShape, true); + DereferenceShape(prim.BSShape, true, shapeCallback); // Native shapes are always built independently. newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType); @@ -422,7 +436,8 @@ public class BSShapeCollection : IDisposable // Dereferences previous shape in BSShape and adds a reference for this new shape. // Returns 'true' of a mesh was actually built. Otherwise . // Called at taint-time! - private bool GetReferenceToMesh(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs) + private bool GetReferenceToMesh(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs, + ShapeDestructionCallback shapeCallback) { BulletShape newShape = new BulletShape(IntPtr.Zero); @@ -436,7 +451,7 @@ public class BSShapeCollection : IDisposable prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newMeshKey.ToString("X")); // Since we're recreating new, get rid of the reference to the previous shape - DereferenceShape(prim.BSShape, true); + DereferenceShape(prim.BSShape, true, shapeCallback); newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, pbs, shapeData.Size, lod); @@ -490,7 +505,8 @@ public class BSShapeCollection : IDisposable // See that hull shape exists in the physical world and update prim.BSShape. // We could be creating the hull because scale changed or whatever. - private bool GetReferenceToHull(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs) + private bool GetReferenceToHull(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs, + ShapeDestructionCallback shapeCallback) { BulletShape newShape; @@ -505,7 +521,7 @@ public class BSShapeCollection : IDisposable prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newHullKey.ToString("X")); // Remove usage of the previous shape. Also removes reference to underlying mesh if it is a hull. - DereferenceShape(prim.BSShape, true); + DereferenceShape(prim.BSShape, true, shapeCallback); newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, pbs, shapeData.Size, lod); @@ -656,7 +672,8 @@ public class BSShapeCollection : IDisposable // 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) + private bool CreateBody(bool forceRebuild, BSPrim prim, BulletSim sim, BulletShape shape, + ShapeData shapeData, BodyDestructionCallback bodyCallback) { bool ret = false; @@ -679,7 +696,7 @@ public class BSShapeCollection : IDisposable if (mustRebuild || forceRebuild) { - DereferenceBody(prim.BSBody, true); + DereferenceBody(prim.BSBody, true, bodyCallback); BulletBody aBody; IntPtr bodyPtr = IntPtr.Zero; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 544c53d..1125d7e 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -42,12 +42,12 @@ public struct BulletSim { ptr = xx; worldID = worldId; - scene = bss; + physicsScene = bss; } public IntPtr ptr; public uint worldID; // The scene is only in here so very low level routines have a handle to print debug/error messages - public BSScene scene; + public BSScene physicsScene; } // An allocated Bullet btRigidBody @@ -120,14 +120,27 @@ public struct BulletShape } } + // Constraint type values as defined by Bullet +public enum ConstraintType : int +{ + POINT2POINT_CONSTRAINT_TYPE = 3, + HINGE_CONSTRAINT_TYPE, + CONETWIST_CONSTRAINT_TYPE, + D6_CONSTRAINT_TYPE, + SLIDER_CONSTRAINT_TYPE, + CONTACT_CONSTRAINT_TYPE, + D6_SPRING_CONSTRAINT_TYPE, + MAX_CONSTRAINT_TYPE +} + // An allocated Bullet btConstraint public struct BulletConstraint { public BulletConstraint(IntPtr xx) { - Ptr = xx; + ptr = xx; } - public IntPtr Ptr; + public IntPtr ptr; } // An allocated HeightMapThing which holds various heightmap info. -- cgit v1.1