From 31d3952477b96b669d8a46d0941ea6d1bc1133b5 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 13 Dec 2012 16:23:51 -0800 Subject: [PATCH] BulletSim: fix problem with continuious rebuilding of physical linksets. This caused movement problems and large prim vehicles to take up a LOT of simulation time. --- .../Region/Physics/BulletSPlugin/BSLinkset.cs | 9 +- .../BulletSPlugin/BSLinksetCompound.cs | 161 +++++++++--------- .../BulletSPlugin/BSLinksetConstraints.cs | 3 +- 3 files changed, 91 insertions(+), 82 deletions(-) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 777c5cb33a..ce0fbe6c91 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -124,7 +124,7 @@ public abstract class BSLinkset get { return ComputeLinksetGeometricCenter(); } } - protected void Initialize(BSScene scene, BSPhysObject parent) + protected BSLinkset(BSScene scene, BSPhysObject parent) { // A simple linkset of one (no children) LinksetID = m_nextLinksetID++; @@ -135,6 +135,7 @@ public abstract class BSLinkset LinksetRoot = parent; m_children = new HashSet(); m_mass = parent.RawMass; + Rebuilding = false; } // Link to a linkset where the child knows the parent. @@ -227,7 +228,7 @@ public abstract class BSLinkset // I am the root of a linkset and a new child is being added // Called while LinkActivity is locked. protected abstract void AddChildToLinkset(BSPhysObject child); - + // I am the root of a linkset and one of my children is being removed. // Safe to call even if the child is not really in my linkset. protected abstract void RemoveChildFromLinkset(BSPhysObject child); @@ -237,6 +238,10 @@ public abstract class BSLinkset // May be called at runtime or taint-time. public abstract void Refresh(BSPhysObject requestor); + // Flag denoting the linkset is in the process of being rebuilt. + // Used to know not the schedule a rebuild in the middle of a rebuild. + protected bool Rebuilding { get; set; } + // 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 diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs index 6cabe3a3ec..2189468e17 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs @@ -61,9 +61,8 @@ public sealed class BSLinksetCompound : BSLinkset { private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]"; - public BSLinksetCompound(BSScene scene, BSPhysObject parent) + public BSLinksetCompound(BSScene scene, BSPhysObject parent) : base(scene, parent) { - base.Initialize(scene, parent); } // For compound implimented linksets, if there are children, use compound shape for the root. @@ -81,8 +80,6 @@ public sealed class BSLinksetCompound : BSLinkset // When physical properties are changed the linkset needs to recalculate // its internal properties. - // This is queued in the 'post taint' queue so the - // refresh will happen once after all the other taints are applied. public override void Refresh(BSPhysObject requestor) { // External request for Refresh (from BSPrim) doesn't need to do anything @@ -92,12 +89,18 @@ public sealed class BSLinksetCompound : BSLinkset // Schedule a refresh to happen after all the other taint processing. private void InternalRefresh(BSPhysObject requestor) { - DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,requestor={1}", LinksetRoot.LocalID, requestor.LocalID); - PhysicsScene.PostTaintObject("BSLinksetCompound.Refresh", requestor.LocalID, delegate() + DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,requestor={1},rebuilding={2}", + LinksetRoot.LocalID, requestor.LocalID, Rebuilding); + // When rebuilding, it is possible to set properties that would normally require a rebuild. + // If already rebuilding, don't request another rebuild. + if (!Rebuilding) { - if (IsRoot(requestor) && HasAnyChildren) - RecomputeLinksetCompound(); - }); + PhysicsScene.PostTaintObject("BSLinksetCompound.Refresh", requestor.LocalID, delegate() + { + if (IsRoot(requestor) && HasAnyChildren) + RecomputeLinksetCompound(); + }); + } } // The object is going dynamic (physical). Do any setup necessary @@ -115,11 +118,7 @@ public sealed class BSLinksetCompound : BSLinkset // The root is going dynamic. Make sure mass is properly set. m_mass = ComputeLinksetMass(); if (HasAnyChildren) - { - // Schedule a rebuilding as this will construct the complete compound shape - // and set all the properties correctly. InternalRefresh(LinksetRoot); - } } else { @@ -149,16 +148,13 @@ public sealed class BSLinksetCompound : BSLinkset if (IsRoot(child)) { if (HasAnyChildren) - { - // Schedule a rebuilding as this will construct the complete compound shape - // and set all the properties correctly. InternalRefresh(LinksetRoot); - } } else { // The non-physical children can come back to life. BulletSimAPI.RemoveFromCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); + child.PhysBody.collisionType = CollisionType.LinksetChild; // Don't force activation so setting of DISABLE_SIMULATION can stay if used. @@ -307,74 +303,83 @@ public sealed class BSLinksetCompound : BSLinkset // Called at taint time!! private void RecomputeLinksetCompound() { - // Cause the root shape to be rebuilt as a compound object with just the root in it - LinksetRoot.ForceBodyShapeRebuild(true); - - DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}", - LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren); - - // Add a shape for each of the other children in the linkset - ForEachMember(delegate(BSPhysObject cPrim) + try { - if (!IsRoot(cPrim)) + // Suppress rebuilding while rebuilding + Rebuilding = true; + + // Cause the root shape to be rebuilt as a compound object with just the root in it + LinksetRoot.ForceBodyShapeRebuild(true); + + DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}", + LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren); + + // Add a shape for each of the other children in the linkset + ForEachMember(delegate(BSPhysObject cPrim) { - // Compute the displacement of the child from the root of the linkset. - // This info is saved in the child prim so the relationship does not - // change over time and the new child position can be computed - // when the linkset is being disassembled (the linkset may have moved). - BSLinksetCompoundInfo lci = cPrim.LinksetInfo as BSLinksetCompoundInfo; - if (lci == null) + if (!IsRoot(cPrim)) { - // Each child position and rotation is given relative to the root. - OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation); - OMV.Vector3 displacementPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation; - OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation; - - // Save relative position for recomputing child's world position after moving linkset. - lci = new BSLinksetCompoundInfo(displacementPos, displacementRot); - cPrim.LinksetInfo = lci; - DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,creatingRelPos,lci={1}", cPrim.LocalID, lci); - } - - DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}", - LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, lci.OffsetPos, lci.OffsetRot); - - if (cPrim.PhysShape.isNativeShape) - { - // A native shape is turning into a hull collision shape because native - // shapes are not shared so we have to hullify it so it will be tracked - // and freed at the correct time. This also solves the scaling problem - // (native shapes scaled but hull/meshes are assumed to not be). - // TODO: decide of the native shape can just be used in the compound shape. - // Use call to CreateGeomNonSpecial(). - BulletShape saveShape = cPrim.PhysShape; - cPrim.PhysShape.Clear(); // Don't let the create free the child's shape - // PhysicsScene.Shapes.CreateGeomNonSpecial(true, cPrim, null); - PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null); - BulletShape newShape = cPrim.PhysShape; - cPrim.PhysShape = saveShape; - BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, newShape.ptr, lci.OffsetPos , lci.OffsetRot); - } - else - { - // For the shared shapes (meshes and hulls), just use the shape in the child. - // The reference count added here will be decremented when the compound shape - // is destroyed in BSShapeCollection (the child shapes are looped over and dereferenced). - if (PhysicsScene.Shapes.ReferenceShape(cPrim.PhysShape)) + // Compute the displacement of the child from the root of the linkset. + // This info is saved in the child prim so the relationship does not + // change over time and the new child position can be computed + // when the linkset is being disassembled (the linkset may have moved). + BSLinksetCompoundInfo lci = cPrim.LinksetInfo as BSLinksetCompoundInfo; + if (lci == null) { - PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}", - LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape); + // Each child position and rotation is given relative to the root. + OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation); + OMV.Vector3 displacementPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation; + OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation; + + // Save relative position for recomputing child's world position after moving linkset. + lci = new BSLinksetCompoundInfo(displacementPos, displacementRot); + cPrim.LinksetInfo = lci; + DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,creatingRelPos,lci={1}", cPrim.LocalID, lci); + } + + DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}", + LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, lci.OffsetPos, lci.OffsetRot); + + if (cPrim.PhysShape.isNativeShape) + { + // A native shape is turning into a hull collision shape because native + // shapes are not shared so we have to hullify it so it will be tracked + // and freed at the correct time. This also solves the scaling problem + // (native shapes scaled but hull/meshes are assumed to not be). + // TODO: decide of the native shape can just be used in the compound shape. + // Use call to CreateGeomNonSpecial(). + BulletShape saveShape = cPrim.PhysShape; + cPrim.PhysShape.Clear(); // Don't let the create free the child's shape + // PhysicsScene.Shapes.CreateGeomNonSpecial(true, cPrim, null); + PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null); + BulletShape newShape = cPrim.PhysShape; + cPrim.PhysShape = saveShape; + BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, newShape.ptr, lci.OffsetPos, lci.OffsetRot); + } + else + { + // For the shared shapes (meshes and hulls), just use the shape in the child. + // The reference count added here will be decremented when the compound shape + // is destroyed in BSShapeCollection (the child shapes are looped over and dereferenced). + if (PhysicsScene.Shapes.ReferenceShape(cPrim.PhysShape)) + { + PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}", + LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape); + } + BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, cPrim.PhysShape.ptr, lci.OffsetPos, lci.OffsetRot); } - BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, cPrim.PhysShape.ptr, lci.OffsetPos , lci.OffsetRot); } - } + return false; // 'false' says to move onto the next child in the list + }); - return false; // 'false' says to move onto the next child in the list - }); - - // With all of the linkset packed into the root prim, it has the mass of everyone. - float linksetMass = LinksetMass; - LinksetRoot.UpdatePhysicalMassProperties(linksetMass); + // With all of the linkset packed into the root prim, it has the mass of everyone. + float linksetMass = LinksetMass; + LinksetRoot.UpdatePhysicalMassProperties(linksetMass); + } + finally + { + Rebuilding = false; + } BulletSimAPI.RecalculateCompoundShapeLocalAabb2(LinksetRoot.PhysShape.ptr); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs index c855fda988..732c0848b7 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs @@ -36,9 +36,8 @@ public sealed class BSLinksetConstraints : BSLinkset { // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]"; - public BSLinksetConstraints(BSScene scene, BSPhysObject parent) + public BSLinksetConstraints(BSScene scene, BSPhysObject parent) : base(scene, parent) { - base.Initialize(scene, parent); } // When physical properties are changed the linkset needs to recalculate