From a61f20ac74836049cbd24397670c2dcd75fb22da Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sun, 21 Oct 2012 16:12:06 -0700 Subject: BulletSim: Create LinkSet abstract class and sparate constraint based linksets into own subclass. Will eventually add manual movement linkset subclass. --- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 355 ++---------------- .../Physics/BulletSPlugin/BSLinksetConstraints.cs | 396 +++++++++++++++++++++ .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 2 +- 3 files changed, 434 insertions(+), 319 deletions(-) create mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 43b1262..2e6b104 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -32,10 +32,27 @@ using OMV = OpenMetaverse; namespace OpenSim.Region.Physics.BulletSPlugin { -public class BSLinkset +public abstract class BSLinkset { // private static string LogHeader = "[BULLETSIM LINKSET]"; + // Create the correct type of linkset for this child + public static BSLinkset Factory(BSScene physScene, BSPhysObject parent) + { + BSLinkset ret = null; + /* + if (parent.IsPhysical) + ret = new BSLinksetConstraints(physScene, parent); + else + ret = new BSLinksetManual(physScene, parent); + */ + + // at the moment, there is only one + ret = new BSLinksetConstraints(physScene, parent); + + return ret; + } + public BSPhysObject LinksetRoot { get; protected set; } public BSScene PhysicsScene { get; private set; } @@ -52,16 +69,16 @@ public class BSLinkset // the physical 'taint' children separately. // After taint processing and before the simulation step, these // two lists must be the same. - private HashSet m_children; - private HashSet m_taintChildren; + protected HashSet m_children; + protected HashSet m_taintChildren; // We lock the diddling of linkset classes to prevent any badness. // This locks the modification of the instances of this class. Changes // to the physical representation is done via the tainting mechenism. - private object m_linksetActivityLock = new Object(); + protected object m_linksetActivityLock = new Object(); // We keep the prim's mass in the linkset structure since it could be dependent on other prims - private float m_mass; + protected float m_mass; public float LinksetMass { get @@ -81,7 +98,7 @@ public class BSLinkset get { return ComputeLinksetGeometricCenter(); } } - public BSLinkset(BSScene scene, BSPhysObject parent) + protected void Initialize(BSScene scene, BSPhysObject parent) { // A simple linkset of one (no children) LinksetID = m_nextLinksetID++; @@ -128,7 +145,7 @@ public class BSLinkset } // The child is down to a linkset of just itself - return new BSLinkset(PhysicsScene, child); + return BSLinkset.Factory(PhysicsScene, child); } // Return 'true' if the passed object is the root object of this linkset @@ -163,24 +180,7 @@ public class BSLinkset // When physical properties are changed the linkset needs to recalculate // its internal properties. // May be called at runtime or taint-time (just pass the appropriate flag). - public void Refresh(BSPhysObject requestor, bool inTaintTime) - { - // If there are no children, not physical or not root, I am not the one that recomputes the constraints - // (For the moment, static linksets do create constraints so remove the test for physical.) - if (!HasAnyChildren || /*!requestor.IsPhysical ||*/ !IsRoot(requestor)) - return; - - BSScene.TaintCallback refreshOperation = delegate() - { - RecomputeLinksetConstraintVariables(); - DetailLog("{0},BSLinkset.Refresh,complete,rBody={1}", - LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); - }; - if (inTaintTime) - refreshOperation(); - else - PhysicsScene.TaintedObject("BSLinkSet.Refresh", refreshOperation); - } + public abstract void Refresh(BSPhysObject requestor, bool inTaintTime); // The object is going dynamic (physical). Do any setup necessary // for a dynamic linkset. @@ -188,102 +188,36 @@ public class BSLinkset // 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; - } + public abstract bool MakeDynamic(BSPhysObject child); // 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; - } + public abstract bool MakeStatic(BSPhysObject child); // If the software is handling the movement of all the objects in a linkset // (like if one doesn't use constraints for static linksets), this is called // when an update for the root of the linkset is received. // Called at taint-time!! - public void UpdateProperties(BSPhysObject physObject) - { - // The root local properties have been updated. Apply to the children if appropriate. - if (IsRoot(physObject) && HasAnyChildren) - { - if (!physObject.IsPhysical) - { - // TODO: implement software linkset update for static object linksets - } - } - } + public abstract void UpdateProperties(BSPhysObject physObject); // 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. // Returns 'true' of something eas actually removed and would need restoring // Called at taint-time!! - public bool RemoveBodyDependencies(BSPrim child) - { - bool ret = false; - - 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},rBody={2}", - child.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); - - ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot); - } - else - { - DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeSingleChild,rID={1},rBody={2},cID={3},cBody={4}", - child.LocalID, - LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), - child.LocalID, child.BSBody.ptr.ToString("X")); - // ret = PhysicallyUnlinkAChildFromRoot(LinksetRoot, child); - // Despite the function name, this removes any link to the specified object. - ret = PhysicallyUnlinkAllChildrenFromRoot(child); - } - } - return ret; - } + public abstract bool RemoveBodyDependencies(BSPrim child); // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', // this routine will restore the removed constraints. // Called at taint-time!! - public void RestoreBodyDependencies(BSPrim child) - { - lock (m_linksetActivityLock) - { - if (IsRoot(child)) - { - DetailLog("{0},BSLinkset.RestoreBodyDependencies,restoreChildrenForRoot,rID={1},numChild={2}", - child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count); - foreach (BSPhysObject bpo in m_taintChildren) - { - PhysicallyLinkAChildToRoot(LinksetRoot, bpo); - } - } - else - { - DetailLog("{0},BSLinkset.RestoreBodyDependencies,restoreSingleChild,rID={1},rBody={2},cID={3},cBody={4}", - LinksetRoot.LocalID, - LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), - child.LocalID, child.BSBody.ptr.ToString("X")); - PhysicallyLinkAChildToRoot(LinksetRoot, child); - } - } - } + public abstract void RestoreBodyDependencies(BSPrim child); // ================================================================ // Below this point is internal magic - private float ComputeLinksetMass() + protected virtual float ComputeLinksetMass() { float mass; lock (m_linksetActivityLock) @@ -297,7 +231,7 @@ public class BSLinkset return mass; } - private OMV.Vector3 ComputeLinksetCenterOfMass() + protected virtual OMV.Vector3 ComputeLinksetCenterOfMass() { OMV.Vector3 com; lock (m_linksetActivityLock) @@ -317,7 +251,7 @@ public class BSLinkset return com; } - private OMV.Vector3 ComputeLinksetGeometricCenter() + protected virtual OMV.Vector3 ComputeLinksetGeometricCenter() { OMV.Vector3 com; lock (m_linksetActivityLock) @@ -336,236 +270,21 @@ public class BSLinkset // I am the root of a linkset and a new child is being added // Called while LinkActivity is locked. - private void AddChildToLinkset(BSPhysObject child) - { - if (!HasChild(child)) - { - m_children.Add(child); - - BSPhysObject rootx = LinksetRoot; // capture the root as of now - BSPhysObject childx = child; - - DetailLog("{0},AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); - - PhysicsScene.TaintedObject("AddChildToLinkset", delegate() - { - DetailLog("{0},AddChildToLinkset,taint,rID={1},rBody={2},cID={3},cBody={4}", - rootx.LocalID, - rootx.LocalID, rootx.BSBody.ptr.ToString("X"), - childx.LocalID, childx.BSBody.ptr.ToString("X")); - // Since this is taint-time, the body and shape could have changed for the child - rootx.ForcePosition = rootx.Position; // DEBUG - childx.ForcePosition = childx.Position; // DEBUG - PhysicallyLinkAChildToRoot(rootx, childx); - m_taintChildren.Add(child); - }); - } - return; - } + protected abstract void AddChildToLinkset(BSPhysObject child); // Forcefully removing a child from a linkset. // This is not being called by the child so we have to make sure the child doesn't think // it's still connected to the linkset. // Normal OpenSimulator operation will never do this because other SceneObjectPart information // also has to be updated (like pointer to prim's parent). - private void RemoveChildFromOtherLinkset(BSPhysObject pchild) - { - pchild.Linkset = new BSLinkset(PhysicsScene, pchild); - RemoveChildFromLinkset(pchild); - } + protected abstract void RemoveChildFromOtherLinkset(BSPhysObject pchild); // 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. - private void RemoveChildFromLinkset(BSPhysObject child) - { - if (m_children.Remove(child)) - { - BSPhysObject rootx = LinksetRoot; // capture the root and body as of now - BSPhysObject childx = child; - - DetailLog("{0},RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", - childx.LocalID, - rootx.LocalID, rootx.BSBody.ptr.ToString("X"), - childx.LocalID, childx.BSBody.ptr.ToString("X")); - - PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate() - { - m_taintChildren.Remove(child); - PhysicallyUnlinkAChildFromRoot(rootx, childx); - RecomputeLinksetConstraintVariables(); - }); - - } - else - { - // This will happen if we remove the root of the linkset first. Non-fatal occurance. - // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader); - } - return; - } - - // Create a constraint between me (root of linkset) and the passed prim (the child). - // Called at taint time! - private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim) - { - // Zero motion for children so they don't interpolate - childPrim.ZeroMotion(); - - // Relative position normalized to the root prim - // Essentually a vector pointing from center of rootPrim to center of childPrim - OMV.Vector3 childRelativePosition = childPrim.Position - rootPrim.Position; - - // real world coordinate of midpoint between the two objects - OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); - - DetailLog("{0},BSLinkset.PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", - rootPrim.LocalID, - rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"), - childPrim.LocalID, childPrim.BSBody.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 - - BS6DofConstraint constrain = new BS6DofConstraint( - PhysicsScene.World, rootPrim.BSBody, childPrim.BSBody, midPoint, 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. - * Code left as a warning to future programmers. - // ================================================================================== - // relative position normalized to the root prim - OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation); - OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation; - - // relative rotation of the child to the parent - OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation; - OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation); - - // create a constraint that allows no freedom of movement between the two objects - // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 - DetailLog("{0},BSLinkset.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); - BS6DofConstraint constrain = new BS6DofConstraint( - PhysicsScene.World, rootPrim.Body, childPrim.Body, - OMV.Vector3.Zero, - OMV.Quaternion.Inverse(rootPrim.Orientation), - OMV.Vector3.Zero, - OMV.Quaternion.Inverse(childPrim.Orientation), - // A point half way between the parent and child - // childRelativePosition/2, - // childRelativeRotation, - // childRelativePosition/2, - // inverseChildRelativeRotation, - true, - true - ); - // ================================================================================== - */ - - PhysicsScene.Constraints.AddConstraint(constrain); - - // zero linear and angular limits makes the objects unable to move in relation to each other - constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); - constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); - - // tweek the constraint to increase stability - constrain.UseFrameOffset(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintUseFrameOffset)); - constrain.TranslationalLimitMotor(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintEnableTransMotor), - PhysicsScene.Params.linkConstraintTransMotorMaxVel, - PhysicsScene.Params.linkConstraintTransMotorMaxForce); - constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP); - if (PhysicsScene.Params.linkConstraintSolverIterations != 0f) - { - constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations); - } - } - - // Remove linkage between myself and a particular child - // The root and child bodies are passed in because we need to remove the constraint between - // the bodies that were at unlink time. - // Called at taint time! - private bool PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim) - { - bool ret = false; - DetailLog("{0},BSLinkset.PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}", - rootPrim.LocalID, - rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"), - childPrim.LocalID, childPrim.BSBody.ptr.ToString("X")); - - // Find the constraint for this link and get rid of it from the overall collection and from my list - if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody, childPrim.BSBody)) - { - // Make the child refresh its location - BulletSimAPI.PushUpdate2(childPrim.BSBody.ptr); - ret = true; - } - - return ret; - } - - // Remove linkage between myself and any possible children I might have. - // Called at taint time! - private bool PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim) - { - DetailLog("{0},BSLinkset.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); - bool ret = false; - - if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody)) - { - ret = true; - } - return ret; - } - - // 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 - // geometry. - // Must only be called at taint time!! - private void RecomputeLinksetConstraintVariables() - { - float linksetMass = LinksetMass; - foreach (BSPhysObject child in m_taintChildren) - { - BSConstraint constrain; - if (PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.BSBody, child.BSBody, out constrain)) - { - // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}", - // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID); - constrain.RecomputeConstraintVariables(linksetMass); - } - else - { - // Non-fatal error that happens when children are being added to the linkset but - // their constraints have not been created yet. - break; - } - } - - // If the whole linkset is not here, doesn't make sense to recompute linkset wide values - if (m_children.Count == m_taintChildren.Count) - { - // If this is a multiple object linkset, set everybody's center of mass to the set's center of mass - OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); - BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, - centerOfMass, OMV.Quaternion.Identity); - DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,setCenterOfMass,COM={1},rBody={2}", - LinksetRoot.LocalID, centerOfMass, LinksetRoot.BSBody.ptr.ToString("X")); - foreach (BSPhysObject child in m_taintChildren) - { - BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, - centerOfMass, OMV.Quaternion.Identity); - } - - // BulletSimAPI.DumpAllInfo2(PhysicsScene.World.ptr); // DEBUG DEBUG DEBUG - } - return; - } - + protected abstract void RemoveChildFromLinkset(BSPhysObject child); // Invoke the detailed logger and output something if it's enabled. - private void DetailLog(string msg, params Object[] args) + protected void DetailLog(string msg, params Object[] args) { if (PhysicsScene.PhysicsLogging.Enabled) PhysicsScene.DetailLog(msg, args); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs new file mode 100755 index 0000000..ee53d92 --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs @@ -0,0 +1,396 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyrightD + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections.Generic; +using System.Text; + +using OMV = OpenMetaverse; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ +public class BSLinksetConstraints : BSLinkset +{ + // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]"; + + public BSLinksetConstraints(BSScene scene, BSPhysObject parent) + { + base.Initialize(scene, parent); + } + + // When physical properties are changed the linkset needs to recalculate + // its internal properties. + // May be called at runtime or taint-time (just pass the appropriate flag). + public override void Refresh(BSPhysObject requestor, bool inTaintTime) + { + // If there are no children, not physical or not root, I am not the one that recomputes the constraints + // (For the moment, static linksets do create constraints so remove the test for physical.) + if (!HasAnyChildren || /*!requestor.IsPhysical ||*/ !IsRoot(requestor)) + return; + + BSScene.TaintCallback refreshOperation = delegate() + { + RecomputeLinksetConstraintVariables(); + DetailLog("{0},BSLinkset.Refresh,complete,rBody={1}", + LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); + }; + if (inTaintTime) + refreshOperation(); + else + PhysicsScene.TaintedObject("BSLinkSet.Refresh", refreshOperation); + } + + // 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 override 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 override bool MakeStatic(BSPhysObject child) + { + // What is done for each object in BSPrim is what we want. + return false; + } + + // If the software is handling the movement of all the objects in a linkset + // (like if one doesn't use constraints for static linksets), this is called + // when an update for the root of the linkset is received. + // Called at taint-time!! + public override void UpdateProperties(BSPhysObject physObject) + { + // The root local properties have been updated. Apply to the children if appropriate. + if (IsRoot(physObject) && HasAnyChildren) + { + if (!physObject.IsPhysical) + { + // TODO: implement software linkset update for static object linksets + } + } + } + + // 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. + // Returns 'true' of something eas actually removed and would need restoring + // Called at taint-time!! + public override bool RemoveBodyDependencies(BSPrim child) + { + bool ret = false; + + 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},rBody={2}", + child.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); + + ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot); + } + else + { + DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeSingleChild,rID={1},rBody={2},cID={3},cBody={4}", + child.LocalID, + LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), + child.LocalID, child.BSBody.ptr.ToString("X")); + // ret = PhysicallyUnlinkAChildFromRoot(LinksetRoot, child); + // Despite the function name, this removes any link to the specified object. + ret = PhysicallyUnlinkAllChildrenFromRoot(child); + } + } + return ret; + } + + // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', + // this routine will restore the removed constraints. + // Called at taint-time!! + public override void RestoreBodyDependencies(BSPrim child) + { + lock (m_linksetActivityLock) + { + if (IsRoot(child)) + { + DetailLog("{0},BSLinkset.RestoreBodyDependencies,restoreChildrenForRoot,rID={1},numChild={2}", + child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count); + foreach (BSPhysObject bpo in m_taintChildren) + { + PhysicallyLinkAChildToRoot(LinksetRoot, bpo); + } + } + else + { + DetailLog("{0},BSLinkset.RestoreBodyDependencies,restoreSingleChild,rID={1},rBody={2},cID={3},cBody={4}", + LinksetRoot.LocalID, + LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), + child.LocalID, child.BSBody.ptr.ToString("X")); + PhysicallyLinkAChildToRoot(LinksetRoot, child); + } + } + } + + // ================================================================ + // Below this point is internal magic + + // I am the root of a linkset and a new child is being added + // Called while LinkActivity is locked. + protected override void AddChildToLinkset(BSPhysObject child) + { + if (!HasChild(child)) + { + m_children.Add(child); + + BSPhysObject rootx = LinksetRoot; // capture the root as of now + BSPhysObject childx = child; + + DetailLog("{0},AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); + + PhysicsScene.TaintedObject("AddChildToLinkset", delegate() + { + DetailLog("{0},AddChildToLinkset,taint,rID={1},rBody={2},cID={3},cBody={4}", + rootx.LocalID, + rootx.LocalID, rootx.BSBody.ptr.ToString("X"), + childx.LocalID, childx.BSBody.ptr.ToString("X")); + // Since this is taint-time, the body and shape could have changed for the child + rootx.ForcePosition = rootx.Position; // DEBUG + childx.ForcePosition = childx.Position; // DEBUG + PhysicallyLinkAChildToRoot(rootx, childx); + m_taintChildren.Add(child); + }); + } + return; + } + + // Forcefully removing a child from a linkset. + // This is not being called by the child so we have to make sure the child doesn't think + // it's still connected to the linkset. + // Normal OpenSimulator operation will never do this because other SceneObjectPart information + // also has to be updated (like pointer to prim's parent). + protected override void RemoveChildFromOtherLinkset(BSPhysObject pchild) + { + pchild.Linkset = BSLinkset.Factory(PhysicsScene, pchild); + RemoveChildFromLinkset(pchild); + } + + // 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 override void RemoveChildFromLinkset(BSPhysObject child) + { + if (m_children.Remove(child)) + { + BSPhysObject rootx = LinksetRoot; // capture the root and body as of now + BSPhysObject childx = child; + + DetailLog("{0},RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", + childx.LocalID, + rootx.LocalID, rootx.BSBody.ptr.ToString("X"), + childx.LocalID, childx.BSBody.ptr.ToString("X")); + + PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate() + { + m_taintChildren.Remove(child); + PhysicallyUnlinkAChildFromRoot(rootx, childx); + RecomputeLinksetConstraintVariables(); + }); + + } + else + { + // This will happen if we remove the root of the linkset first. Non-fatal occurance. + // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader); + } + return; + } + + // Create a constraint between me (root of linkset) and the passed prim (the child). + // Called at taint time! + private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim) + { + // Zero motion for children so they don't interpolate + childPrim.ZeroMotion(); + + // Relative position normalized to the root prim + // Essentually a vector pointing from center of rootPrim to center of childPrim + OMV.Vector3 childRelativePosition = childPrim.Position - rootPrim.Position; + + // real world coordinate of midpoint between the two objects + OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); + + DetailLog("{0},BSLinkset.PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", + rootPrim.LocalID, + rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"), + childPrim.LocalID, childPrim.BSBody.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 + + BS6DofConstraint constrain = new BS6DofConstraint( + PhysicsScene.World, rootPrim.BSBody, childPrim.BSBody, midPoint, 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. + * Code left as a warning to future programmers. + // ================================================================================== + // relative position normalized to the root prim + OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation); + OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation; + + // relative rotation of the child to the parent + OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation; + OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation); + + // create a constraint that allows no freedom of movement between the two objects + // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 + DetailLog("{0},BSLinkset.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); + BS6DofConstraint constrain = new BS6DofConstraint( + PhysicsScene.World, rootPrim.Body, childPrim.Body, + OMV.Vector3.Zero, + OMV.Quaternion.Inverse(rootPrim.Orientation), + OMV.Vector3.Zero, + OMV.Quaternion.Inverse(childPrim.Orientation), + // A point half way between the parent and child + // childRelativePosition/2, + // childRelativeRotation, + // childRelativePosition/2, + // inverseChildRelativeRotation, + true, + true + ); + // ================================================================================== + */ + + PhysicsScene.Constraints.AddConstraint(constrain); + + // zero linear and angular limits makes the objects unable to move in relation to each other + constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); + constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); + + // tweek the constraint to increase stability + constrain.UseFrameOffset(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintUseFrameOffset)); + constrain.TranslationalLimitMotor(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintEnableTransMotor), + PhysicsScene.Params.linkConstraintTransMotorMaxVel, + PhysicsScene.Params.linkConstraintTransMotorMaxForce); + constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP); + if (PhysicsScene.Params.linkConstraintSolverIterations != 0f) + { + constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations); + } + } + + // Remove linkage between myself and a particular child + // The root and child bodies are passed in because we need to remove the constraint between + // the bodies that were at unlink time. + // Called at taint time! + private bool PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim) + { + bool ret = false; + DetailLog("{0},BSLinkset.PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}", + rootPrim.LocalID, + rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"), + childPrim.LocalID, childPrim.BSBody.ptr.ToString("X")); + + // Find the constraint for this link and get rid of it from the overall collection and from my list + if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody, childPrim.BSBody)) + { + // Make the child refresh its location + BulletSimAPI.PushUpdate2(childPrim.BSBody.ptr); + ret = true; + } + + return ret; + } + + // Remove linkage between myself and any possible children I might have. + // Called at taint time! + private bool PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim) + { + DetailLog("{0},BSLinkset.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); + bool ret = false; + + if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody)) + { + ret = true; + } + return ret; + } + + // 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 + // geometry. + // Must only be called at taint time!! + private void RecomputeLinksetConstraintVariables() + { + float linksetMass = LinksetMass; + foreach (BSPhysObject child in m_taintChildren) + { + BSConstraint constrain; + if (PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.BSBody, child.BSBody, out constrain)) + { + // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}", + // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID); + constrain.RecomputeConstraintVariables(linksetMass); + } + else + { + // Non-fatal error that happens when children are being added to the linkset but + // their constraints have not been created yet. + break; + } + } + + // If the whole linkset is not here, doesn't make sense to recompute linkset wide values + if (m_children.Count == m_taintChildren.Count) + { + // If this is a multiple object linkset, set everybody's center of mass to the set's center of mass + OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); + BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, + centerOfMass, OMV.Quaternion.Identity); + DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,setCenterOfMass,COM={1},rBody={2}", + LinksetRoot.LocalID, centerOfMass, LinksetRoot.BSBody.ptr.ToString("X")); + foreach (BSPhysObject child in m_taintChildren) + { + BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, + centerOfMass, OMV.Quaternion.Identity); + } + + // BulletSimAPI.DumpAllInfo2(PhysicsScene.World.ptr); // DEBUG DEBUG DEBUG + } + return; + } +} +} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index ead6a08..51b9196 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -46,7 +46,7 @@ public abstract class BSPhysObject : PhysicsActor PhysObjectName = name; TypeName = typeName; - Linkset = new BSLinkset(PhysicsScene, this); + Linkset = BSLinkset.Factory(PhysicsScene, this); LastAssetBuildFailed = false; CollisionCollection = new CollisionEventUpdate(); -- cgit v1.1 From c245178eeee530e2be90ef9395ee885e0a79b7df Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sun, 21 Oct 2012 16:13:22 -0700 Subject: BulletSim: encorporate UBit's suggestion to save a copy of mesh raw data. --- OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index d3ba273..7b808eb 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -724,8 +724,7 @@ public class BSShapeCollection : IDisposable if (yprim.BaseShape.SculptTexture.ToString() != asset.ID) return; - yprim.BaseShape.SculptData = new byte[asset.Data.Length]; - asset.Data.CopyTo(yprim.BaseShape.SculptData, 0); + yprim.BaseShape.SculptData = asset.Data; // This will cause the prim to see that the filler shape is not the right // one and try again to build the object. yprim.ForceBodyShapeRebuild(false); -- cgit v1.1 From 65c131c4a362bed347a6240184ce40b9ddeaaae1 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 22 Oct 2012 08:23:21 -0700 Subject: BulletSim: remove trailing spaces to make git happy. --- OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | 10 +++++----- OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs | 2 +- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 10 +++++----- .../Physics/BulletSPlugin/BSLinksetConstraints.cs | 10 +++++----- OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs | 6 +++--- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 10 +++++----- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 4 ++-- .../Physics/BulletSPlugin/BSShapeCollection.cs | 20 ++++++++++---------- 8 files changed, 36 insertions(+), 36 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 623ac8f..07dd613 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -165,7 +165,7 @@ public class BSCharacter : BSPhysObject // Do this after the object has been added to the world BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr, - (uint)CollisionFilterGroups.AvatarFilter, + (uint)CollisionFilterGroups.AvatarFilter, (uint)CollisionFilterGroups.AvatarMask); } @@ -269,7 +269,7 @@ public class BSCharacter : BSPhysObject private bool PositionSanityCheck() { bool ret = false; - + // If below the ground, move the avatar up float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); if (Position.Z < terrainHeight) @@ -413,7 +413,7 @@ public class BSCharacter : BSPhysObject }); } } - // Go directly to Bullet to get/set the value. + // Go directly to Bullet to get/set the value. public override OMV.Quaternion ForceOrientation { get @@ -478,7 +478,7 @@ public class BSCharacter : BSPhysObject set { _collidingObj = value; } } public override bool FloatOnWater { - set { + set { _floatOnWater = value; PhysicsScene.TaintedObject("BSCharacter.setFloatOnWater", delegate() { @@ -588,7 +588,7 @@ public class BSCharacter : BSPhysObject newScale.X = PhysicsScene.Params.avatarCapsuleRadius; newScale.Y = PhysicsScene.Params.avatarCapsuleRadius; - // From the total height, remote the capsule half spheres that are at each end + // From the total height, remote the capsule half spheres that are at each end newScale.Z = (size.Z * 2f) - Math.Min(newScale.X, newScale.Y); // newScale.Z = (size.Z * 2f); Scale = newScale; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs index a20be3a..b58745a 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs @@ -53,7 +53,7 @@ public abstract class BSConstraint : IDisposable { bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.ptr); m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,id1={1},body1={2},id2={3},body2={4},success={5}", - BSScene.DetailLogZero, + BSScene.DetailLogZero, m_body1.ID, m_body1.ptr.ToString("X"), m_body2.ID, m_body2.ptr.ToString("X"), success); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 56342b8..f71f3b0 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -23,7 +23,7 @@ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ + * /* RA: June 14, 2011. Copied from ODEDynamics.cs and converted to * call the BulletSim system. @@ -352,7 +352,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin // m_bankingMix = 1; // m_bankingTimescale = 1; // m_referenceFrame = Quaternion.Identity; - m_flags |= (VehicleFlag.NO_DEFLECTION_UP + m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP); m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT); @@ -382,7 +382,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin // m_bankingTimescale = 1; // m_referenceFrame = Quaternion.Identity; m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY - | VehicleFlag.HOVER_GLOBAL_HEIGHT + | VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.HOVER_UP_ONLY); m_flags |= (VehicleFlag.NO_DEFLECTION_UP @@ -458,7 +458,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin // Do any updating needed for a vehicle public void Refresh() { - if (!IsActive) + if (!IsActive) return; // Set the prim's inertia to zero. The vehicle code handles that and this @@ -791,7 +791,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin // Sum velocities m_lastAngularVelocity = m_angularMotorVelocity + vertattr; // + bank + deflection - + if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) { m_lastAngularVelocity.X = 0; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs index ee53d92..8eeeb73 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs @@ -54,7 +54,7 @@ public class BSLinksetConstraints : BSLinkset BSScene.TaintCallback refreshOperation = delegate() { RecomputeLinksetConstraintVariables(); - DetailLog("{0},BSLinkset.Refresh,complete,rBody={1}", + DetailLog("{0},BSLinkset.Refresh,complete,rBody={1}", LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); }; if (inTaintTime) @@ -179,7 +179,7 @@ public class BSLinksetConstraints : BSLinkset PhysicsScene.TaintedObject("AddChildToLinkset", delegate() { - DetailLog("{0},AddChildToLinkset,taint,rID={1},rBody={2},cID={3},cBody={4}", + DetailLog("{0},AddChildToLinkset,taint,rID={1},rBody={2},cID={3},cBody={4}", rootx.LocalID, rootx.LocalID, rootx.BSBody.ptr.ToString("X"), childx.LocalID, childx.BSBody.ptr.ToString("X")); @@ -213,7 +213,7 @@ public class BSLinksetConstraints : BSLinkset BSPhysObject rootx = LinksetRoot; // capture the root and body as of now BSPhysObject childx = child; - DetailLog("{0},RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", + DetailLog("{0},RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", childx.LocalID, rootx.LocalID, rootx.BSBody.ptr.ToString("X"), childx.LocalID, childx.BSBody.ptr.ToString("X")); @@ -378,13 +378,13 @@ public class BSLinksetConstraints : BSLinkset { // If this is a multiple object linkset, set everybody's center of mass to the set's center of mass OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); - BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, + BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,setCenterOfMass,COM={1},rBody={2}", LinksetRoot.LocalID, centerOfMass, LinksetRoot.BSBody.ptr.ToString("X")); foreach (BSPhysObject child in m_taintChildren) { - BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, + BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 51b9196..538f905 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -78,7 +78,7 @@ public abstract class BSPhysObject : PhysicsActor public PrimitiveBaseShape BaseShape { get; protected set; } // When the physical properties are updated, an EntityProperty holds the update values. - // Keep the current and last EntityProperties to enable computation of differences + // Keep the current and last EntityProperties to enable computation of differences // between the current update and the previous values. public EntityProperties CurrentEntityProperties { get; set; } public EntityProperties LastEntityProperties { get; set; } @@ -213,7 +213,7 @@ public abstract class BSPhysObject : PhysicsActor UnSubscribeEvents(); } } - public override void UnSubscribeEvents() { + public override void UnSubscribeEvents() { // DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName); SubscribedEventsMs = 0; PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate() @@ -222,7 +222,7 @@ public abstract class BSPhysObject : PhysicsActor }); } // Return 'true' if the simulator wants collision events - public override bool SubscribedEvents() { + public override bool SubscribedEvents() { return (SubscribedEventsMs > 0); } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index aeeb4dd..7b211fa 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -295,7 +295,7 @@ public sealed class BSPrim : BSPhysObject private bool PositionSanityCheck() { bool ret = false; - + // If totally below the ground, move the prim up // TODO: figure out the right solution for this... only for dynamic objects? /* @@ -510,7 +510,7 @@ public sealed class BSPrim : BSPhysObject }); } } - // Go directly to Bullet to get/set the value. + // Go directly to Bullet to get/set the value. public override OMV.Quaternion ForceOrientation { get @@ -768,7 +768,7 @@ public sealed class BSPrim : BSPhysObject } } public override bool FloatOnWater { - set { + set { _floatOnWater = value; PhysicsScene.TaintedObject("BSPrim.setFloatOnWater", delegate() { @@ -971,7 +971,7 @@ public sealed class BSPrim : BSPhysObject if (hollowAmount > 0.0) { hollowVolume *= hollowAmount; - + switch (BaseShape.HollowShape) { case HollowShape.Square: @@ -1251,7 +1251,7 @@ public sealed class BSPrim : BSPhysObject // Create the correct physical representation for this type of object. // Updates BSBody and BSShape with the new information. // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. - PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, shapeData, BaseShape, + PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, shapeData, BaseShape, null, delegate(BulletBody dBody) { // Called if the current prim body is about to be destroyed. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 6621d39..233f1ca 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -320,7 +320,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters { m_log.Debug("[BULLETS UNMANAGED]:" + msg); } - + // Called directly from unmanaged code so don't do much private void BulletLoggerPhysLog(string msg) { @@ -545,7 +545,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters } // This is a kludge to get avatar movement updates. - // The simulator expects collisions for avatars even if there are have been no collisions. + // The simulator expects collisions for avatars even if there are have been no collisions. // The event updates avatar animations and stuff. // If you fix avatar animation updates, remove this overhead and let normal collision processing happen. foreach (BSPhysObject bsp in m_avatars) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 7b808eb..86bbf46 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -89,7 +89,7 @@ public class BSShapeCollection : IDisposable // 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, + public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback) { @@ -105,7 +105,7 @@ public class BSShapeCollection : IDisposable // 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, + bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, prim.BSShape, shapeData, bodyCallback); ret = newGeom || newBody; } @@ -325,7 +325,7 @@ public class BSShapeCollection : IDisposable // Info in prim.BSShape is updated to the new shape. // Returns 'true' if the geometry was rebuilt. // Called at taint-time! - private bool CreateGeom(bool forceRebuild, BSPhysObject prim, ShapeData shapeData, + private bool CreateGeom(bool forceRebuild, BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback) { bool ret = false; @@ -335,7 +335,7 @@ public class BSShapeCollection : IDisposable if (shapeData.Type == ShapeData.PhysicsShapeType.SHAPE_AVATAR) { // an avatar capsule is close to a native shape (it is not shared) - ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_AVATAR, + ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_AVATAR, ShapeData.FixedShapeKey.KEY_CAPSULE, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.BSShape); haveShape = true; @@ -362,7 +362,7 @@ public class BSShapeCollection : IDisposable || prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE ) { - ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_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); @@ -376,7 +376,7 @@ public class BSShapeCollection : IDisposable || prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX ) { - ret = GetReferenceToNativeShape( prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_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); @@ -423,14 +423,14 @@ public class BSShapeCollection : IDisposable BulletShape newShape = BuildPhysicalNativeShape(shapeType, shapeData, shapeKey); // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. - DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}", + DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}", shapeData.ID, newShape, shapeData.Scale); prim.BSShape = newShape; return true; } - private BulletShape BuildPhysicalNativeShape(ShapeData.PhysicsShapeType shapeType, + private BulletShape BuildPhysicalNativeShape(ShapeData.PhysicsShapeType shapeType, ShapeData shapeData, ShapeData.FixedShapeKey shapeKey) { BulletShape newShape; @@ -438,7 +438,7 @@ public class BSShapeCollection : IDisposable if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) { newShape = new BulletShape( - BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1.0f, 1.0f, shapeData.Scale), + BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1.0f, 1.0f, shapeData.Scale), shapeType); } else @@ -745,7 +745,7 @@ 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, BSPhysObject prim, BulletSim sim, BulletShape shape, + private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletSim sim, BulletShape shape, ShapeData shapeData, BodyDestructionCallback bodyCallback) { bool ret = false; -- cgit v1.1 From 7272a4cae835f2d3d2a696241c6e6eb5f4b5af54 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 22 Oct 2012 09:12:06 -0700 Subject: BulletSim: fix problem of not rebuilding shape by clearing last rebuild failed flag in BSPrim.ForceBodyShapeRebuild() --- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 1 + OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 7b211fa..3c5e6e5 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -173,6 +173,7 @@ public sealed class BSPrim : BSPhysObject } public override bool ForceBodyShapeRebuild(bool inTaintTime) { + LastAssetBuildFailed = false; BSScene.TaintCallback rebuildOperation = delegate() { _mass = CalculateMass(); // changing the shape changes the mass diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 86bbf46..89d0d3e 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -698,14 +698,19 @@ public class BSShapeCollection : IDisposable return ComputeShapeKey(shapeData, pbs, out lod); } + // The creation of a mesh or hull can fail if an underlying asset is not available. + // There are two cases: 1) the asset is not in the cache and it needs to be fetched; + // and 2) the asset cannot be converted (like decompressing JPEG2000s). + // The first case causes the asset to be fetched. The second case just requires + // us to not loop forever. + // Called after creating a physical mesh or hull. If the physical shape was created, + // just return. private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs) { // If the shape was successfully created, nothing more to do if (newShape.ptr != IntPtr.Zero) return newShape; - // The most common reason for failure is that an underlying asset is not available - // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset if (pbs.SculptEntry && !prim.LastAssetBuildFailed && pbs.SculptTexture != OMV.UUID.Zero) { -- cgit v1.1 From 14eeb8b31b865f7b1927703028b03b6f61693cb6 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 22 Oct 2012 16:33:21 -0700 Subject: BulletSim: fix bug that caused error (and a crash on 32 bit Linux) when mesh assets weren't already in the cache. Comment cleanups. --- .../Region/Physics/BulletSPlugin/BSConstraint.cs | 4 ++- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 5 ++-- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 13 +++++---- .../Physics/BulletSPlugin/BSLinksetConstraints.cs | 19 +++---------- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 9 ++++--- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 1 + .../Physics/BulletSPlugin/BSShapeCollection.cs | 31 ++++++++++++++++++---- .../Physics/BulletSPlugin/BSTerrainManager.cs | 4 +-- 8 files changed, 51 insertions(+), 35 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs index b58745a..f017cdd 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs @@ -34,6 +34,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin public abstract class BSConstraint : IDisposable { + private static string LogHeader = "[BULLETSIM CONSTRAINT]"; + protected BulletSim m_world; protected BulletBody m_body1; protected BulletBody m_body2; @@ -124,7 +126,7 @@ public abstract class BSConstraint : IDisposable } else { - m_world.physicsScene.Logger.ErrorFormat("[BULLETSIM CONSTRAINT] CalculateTransforms failed. A={0}, B={1}", Body1.ID, Body2.ID); + m_world.physicsScene.Logger.ErrorFormat("{0} CalculateTransforms failed. A={1}, B={2}", LogHeader, Body1.ID, Body2.ID); } } return ret; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index f71f3b0..117c878 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -464,8 +464,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin // Set the prim's inertia to zero. The vehicle code handles that and this // removes the motion and torque actions introduced by Bullet. Vector3 inertia = Vector3.Zero; - BulletSimAPI.SetMassProps2(Prim.BSBody.ptr, Prim.MassRaw, inertia); - BulletSimAPI.UpdateInertiaTensor2(Prim.BSBody.ptr); + // comment out for DEBUG test + // BulletSimAPI.SetMassProps2(Prim.BSBody.ptr, Prim.MassRaw, inertia); + // BulletSimAPI.UpdateInertiaTensor2(Prim.BSBody.ptr); } // One step of the vehicle properties for the next 'pTimestep' seconds. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 2e6b104..c984824 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -165,6 +165,9 @@ public abstract class BSLinkset bool ret = false; lock (m_linksetActivityLock) { + if (m_children.Contains(child)) + ret = true; + /* foreach (BSPhysObject bp in m_children) { if (child.LocalID == bp.LocalID) @@ -173,6 +176,7 @@ public abstract class BSLinkset break; } } + */ } return ret; } @@ -196,21 +200,20 @@ public abstract class BSLinkset // Called at taint-time! public abstract bool MakeStatic(BSPhysObject child); - // If the software is handling the movement of all the objects in a linkset - // (like if one doesn't use constraints for static linksets), this is called - // when an update for the root of the linkset is received. + // Called when a parameter update comes from the physics engine for any object + // of the linkset is received. // Called at taint-time!! public abstract void UpdateProperties(BSPhysObject physObject); // 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. - // Returns 'true' of something eas actually removed and would need restoring + // Returns 'true' of something was actually removed and would need restoring // Called at taint-time!! public abstract bool RemoveBodyDependencies(BSPrim child); // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', - // this routine will restore the removed constraints. + // this routine will restore the removed constraints. // Called at taint-time!! public abstract void RestoreBodyDependencies(BSPrim child); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs index 8eeeb73..8a750b5 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs @@ -46,9 +46,8 @@ public class BSLinksetConstraints : BSLinkset // May be called at runtime or taint-time (just pass the appropriate flag). public override void Refresh(BSPhysObject requestor, bool inTaintTime) { - // If there are no children, not physical or not root, I am not the one that recomputes the constraints - // (For the moment, static linksets do create constraints so remove the test for physical.) - if (!HasAnyChildren || /*!requestor.IsPhysical ||*/ !IsRoot(requestor)) + // If there are no children or not root, I am not the one that recomputes the constraints + if (!HasAnyChildren || !IsRoot(requestor)) return; BSScene.TaintCallback refreshOperation = delegate() @@ -85,20 +84,10 @@ public class BSLinksetConstraints : BSLinkset return false; } - // If the software is handling the movement of all the objects in a linkset - // (like if one doesn't use constraints for static linksets), this is called - // when an update for the root of the linkset is received. // Called at taint-time!! - public override void UpdateProperties(BSPhysObject physObject) + public override void UpdateProperties(BSPhysObject updated) { - // The root local properties have been updated. Apply to the children if appropriate. - if (IsRoot(physObject) && HasAnyChildren) - { - if (!physObject.IsPhysical) - { - // TODO: implement software linkset update for static object linksets - } - } + // Nothing to do for constraints on property updates } // Routine used when rebuilding the body of the root of the linkset diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 3c5e6e5..8401c69 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -399,7 +399,7 @@ public sealed class BSPrim : BSPhysObject { // Done at taint time so we're sure the physics engine is not using the variables // Vehicle code changes the parameters for this vehicle type. - this._vehicle.ProcessTypeChange(type); + _vehicle.ProcessTypeChange(type); }); } } @@ -1246,12 +1246,13 @@ public sealed class BSPrim : BSPhysObject FillShapeInfo(out shapeData); // If this prim is part of a linkset, we must remove and restore the physical - // links of the body is rebuilt. + // links if the body is rebuilt. bool needToRestoreLinkset = false; // Create the correct physical representation for this type of object. // Updates BSBody and BSShape with the new information. // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. + // Returns 'true' if either the body or the shape was changed. PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, shapeData, BaseShape, null, delegate(BulletBody dBody) { @@ -1355,7 +1356,7 @@ public sealed class BSPrim : BSPhysObject DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); - // BulletSimAPI.DumpRigidBody2(Scene.World.Ptr, BSBody.Ptr); + BulletSimAPI.DumpRigidBody2(PhysicsScene.World.ptr, BSBody.ptr); // DEBUG DEBUG DEBUG base.RequestPhysicsterseUpdate(); } @@ -1368,8 +1369,8 @@ public sealed class BSPrim : BSPhysObject entprop.Acceleration, entprop.RotationalVelocity); } */ - // The linkset implimentation might want to know about this. + // The linkset implimentation might want to know about this. Linkset.UpdateProperties(this); } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 233f1ca..48ee6f6 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -716,6 +716,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters } catch (Exception e) { + DetailLog("{0},BSScene.ProcessTaints,doTaintException,id={1}", DetailLogZero, oneCallback.ident); // DEBUG DEBUG DEBUG m_log.ErrorFormat("{0}: ProcessTaints: {1}: Exception: {2}", LogHeader, oneCallback.ident, e); } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 89d0d3e..b1833c5 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -36,7 +36,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin { public class BSShapeCollection : IDisposable { - // private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]"; + private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]"; protected BSScene PhysicsScene { get; set; } @@ -434,16 +434,26 @@ public class BSShapeCollection : IDisposable ShapeData shapeData, ShapeData.FixedShapeKey shapeKey) { BulletShape newShape; + // Need to make sure the passed shape information is for the native type. + ShapeData nativeShapeData = shapeData; + nativeShapeData.Type = shapeType; + nativeShapeData.MeshKey = (ulong)shapeKey; + nativeShapeData.HullKey = (ulong)shapeKey; if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) { newShape = new BulletShape( - BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1.0f, 1.0f, shapeData.Scale), - shapeType); + BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1.0f, 1.0f, nativeShapeData.Scale), shapeType); + DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", nativeShapeData.ID, nativeShapeData.Scale); } else { - newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType); + newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, nativeShapeData), shapeType); + } + if (newShape.ptr == IntPtr.Zero) + { + PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", + LogHeader, nativeShapeData.ID, nativeShapeData.Type); } newShape.shapeKey = (System.UInt64)shapeKey; newShape.isNativeShape = true; @@ -716,6 +726,8 @@ public class BSShapeCollection : IDisposable { prim.LastAssetBuildFailed = true; BSPhysObject xprim = prim; + DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset,lID={1},lastFailed={2}", + LogHeader, shapeData.ID.ToString("X"), prim.LastAssetBuildFailed); Util.FireAndForget(delegate { RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod; @@ -732,16 +744,25 @@ public class BSShapeCollection : IDisposable yprim.BaseShape.SculptData = asset.Data; // This will cause the prim to see that the filler shape is not the right // one and try again to build the object. + // No race condition with the native sphere setting since the rebuild is at taint time. yprim.ForceBodyShapeRebuild(false); }); } }); } + else + { + if (prim.LastAssetBuildFailed) + { + PhysicsScene.Logger.ErrorFormat("{0} Mesh failed to fetch asset. lID={1}, texture={2}", + LogHeader, shapeData.ID, pbs.SculptTexture); + } + } // While we figure out the real problem, stick a simple native shape on the object. BulletShape fillinShape = - BuildPhysicalNativeShape(ShapeData.PhysicsShapeType.SHAPE_SPHERE, shapeData, ShapeData.FixedShapeKey.KEY_SPHERE); + BuildPhysicalNativeShape(ShapeData.PhysicsShapeType.SHAPE_BOX, shapeData, ShapeData.FixedShapeKey.KEY_BOX); return fillinShape; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index 4106534..ae267e3 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -201,9 +201,7 @@ public class BSTerrainManager // If called with a mapInfo in m_heightMaps and there is an existing terrain body, a new // terrain shape is created and added to the body. // This call is most often used to update the heightMap and parameters of the terrain. - // The 'doNow' boolean says whether to do all the unmanaged activities right now (like when - // calling this routine from initialization or taint-time routines) or whether to delay - // all the unmanaged activities to taint-time. + // (The above does suggest that some simplification/refactoring is in order.) private void UpdateOrCreateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords, bool inTaintTime) { DetailLog("{0},BSTerrainManager.UpdateOrCreateTerrain,call,minC={1},maxC={2},inTaintTime={3}", -- cgit v1.1 From 36bfd3667c44f7cd4e66e880c45c34903ed34842 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 22 Oct 2012 22:22:48 -0700 Subject: BulletSim: remove chatty debug message. --- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 2 +- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 8401c69..38ab3de 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -1356,7 +1356,7 @@ public sealed class BSPrim : BSPhysObject DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); - BulletSimAPI.DumpRigidBody2(PhysicsScene.World.ptr, BSBody.ptr); // DEBUG DEBUG DEBUG + // BulletSimAPI.DumpRigidBody2(PhysicsScene.World.ptr, BSBody.ptr); // DEBUG DEBUG DEBUG base.RequestPhysicsterseUpdate(); } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 48ee6f6..e686f2f 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -1334,7 +1334,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters // Add the Flush() if debugging crashes to get all the messages written out. // PhysicsLogging.Flush(); } - // used to fill in the LocalID when there isn't one + // Used to fill in the LocalID when there isn't one. It's the correct number of characters. public const string DetailLogZero = "0000000000"; } -- cgit v1.1 From b49f8a377b9ac542096a0bc8ad30b11942c27413 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 23 Oct 2012 08:02:26 -0700 Subject: BulletSim: minor change to insure avatar body recreation when shape changes. --- OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index b1833c5..d9427e1 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -338,6 +338,7 @@ public class BSShapeCollection : IDisposable ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_AVATAR, ShapeData.FixedShapeKey.KEY_CAPSULE, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.BSShape); + ret = true; haveShape = true; } // If the prim attributes are simple, this could be a simple Bullet native shape @@ -411,15 +412,14 @@ public class BSShapeCollection : IDisposable ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey, ShapeDestructionCallback shapeCallback) { + // release any previous shape + DereferenceShape(prim.BSShape, true, shapeCallback); shapeData.Type = shapeType; // Bullet native objects are scaled by the Bullet engine so pass the size in prim.Scale = shapeData.Size; shapeData.Scale = shapeData.Size; - // release any previous shape - DereferenceShape(prim.BSShape, true, shapeCallback); - BulletShape newShape = BuildPhysicalNativeShape(shapeType, shapeData, shapeKey); // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. -- cgit v1.1 From b6fc5bad000e7e7af992e7f29eeb2de9f716fcc4 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 23 Oct 2012 17:30:43 -0700 Subject: BulletSim: fix problem with avatars sinking into the ground. Change terrain activation state to DISABLE_SIMULATION for better performance. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 27 ++++++++++++++-------- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 3 +-- .../Physics/BulletSPlugin/BSShapeCollection.cs | 4 ++-- .../Physics/BulletSPlugin/BSTerrainManager.cs | 4 ++-- 4 files changed, 23 insertions(+), 15 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 07dd613..a041ba8 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -105,7 +105,7 @@ public class BSCharacter : BSPhysObject shapeData.Position = _position; shapeData.Rotation = _orientation; shapeData.Velocity = _velocity; - shapeData.Size = Scale; + shapeData.Size = Scale; // capsule is a native shape but scale is not just <1,1,1> shapeData.Scale = Scale; shapeData.Mass = _mass; shapeData.Buoyancy = _buoyancy; @@ -144,7 +144,9 @@ public class BSCharacter : BSPhysObject ForcePosition = _position; // Set the velocity and compute the proper friction ForceVelocity = _velocity; + BulletSimAPI.SetRestitution2(BSBody.ptr, PhysicsScene.Params.avatarRestitution); + BulletSimAPI.SetMargin2(BSShape.ptr, PhysicsScene.Params.collisionMargin); BulletSimAPI.SetLocalScaling2(BSShape.ptr, Scale); BulletSimAPI.SetContactProcessingThreshold2(BSBody.ptr, PhysicsScene.Params.contactProcessingThreshold); if (PhysicsScene.Params.ccdMotionThreshold > 0f) @@ -156,11 +158,15 @@ public class BSCharacter : BSPhysObject OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw); BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); + // Make so capsule does not fall over + BulletSimAPI.SetAngularFactorV2(BSBody.ptr, OMV.Vector3.Zero); + BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_CHARACTER_OBJECT); BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, BSBody.ptr); - BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ACTIVE_TAG); + // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ACTIVE_TAG); + 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 @@ -175,11 +181,13 @@ public class BSCharacter : BSPhysObject } // No one calls this method so I don't know what it could possibly mean public override bool Stopped { get { return false; } } + public override OMV.Vector3 Size { get { // Avatar capsule size is kept in the scale parameter. - return _size; + // return _size; + return new OMV.Vector3(Scale.X * 2f, Scale.Y * 2f, Scale.Z); } set { @@ -199,7 +207,9 @@ public class BSCharacter : BSPhysObject } } + public override OMV.Vector3 Scale { get; set; } + public override PrimitiveBaseShape Shape { set { BaseShape = value; } @@ -264,7 +274,7 @@ public class BSCharacter : BSPhysObject // Check that the current position is sane and, if not, modify the position to make it so. - // Check for being below terrain and being out of bounds. + // Check for being below terrain or on water. // Returns 'true' of the position was made sane by some action. private bool PositionSanityCheck() { @@ -335,7 +345,7 @@ public class BSCharacter : BSPhysObject } // Avatars don't do vehicles - public override int VehicleType { get { return 0; } set { return; } } + public override int VehicleType { get { return (int)Vehicle.TYPE_NONE; } set { return; } } public override void VehicleFloatParam(int param, float value) { } public override void VehicleVectorParam(int param, OMV.Vector3 value) {} public override void VehicleRotationParam(int param, OMV.Quaternion rotation) { } @@ -588,9 +598,8 @@ public class BSCharacter : BSPhysObject newScale.X = PhysicsScene.Params.avatarCapsuleRadius; newScale.Y = PhysicsScene.Params.avatarCapsuleRadius; - // From the total height, remote the capsule half spheres that are at each end - newScale.Z = (size.Z * 2f) - Math.Min(newScale.X, newScale.Y); - // newScale.Z = (size.Z * 2f); + // From the total height, remove the capsule half spheres that are at each end + newScale.Z = size.Z- (newScale.X + newScale.Y); Scale = newScale; } @@ -636,7 +645,7 @@ public class BSCharacter : BSPhysObject BulletSimAPI.SetLinearVelocity2(BSBody.ptr, avVel); } - // Tell the linkset about this + // Tell the linkset about value changes Linkset.UpdateProperties(this); // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index e686f2f..db0c99e 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -692,7 +692,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters { if (_taintedObjects.Count > 0) // save allocating new list if there is nothing to process { - // swizzle a new list into the list location so we can process what's there int taintCount = m_taintsToProcessPerStep; TaintCallbackEntry oneCallback = new TaintCallbackEntry(); while (_taintedObjects.Count > 0 && taintCount-- > 0) @@ -711,7 +710,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters { try { - DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, oneCallback.ident); // DEBUG DEBUG DEBUG + DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, oneCallback.ident); oneCallback.callback(); } catch (Exception e) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index d9427e1..30fa50a 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -443,7 +443,8 @@ public class BSShapeCollection : IDisposable if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) { newShape = new BulletShape( - BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1.0f, 1.0f, nativeShapeData.Scale), shapeType); + BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, nativeShapeData.Scale) + , shapeType); DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", nativeShapeData.ID, nativeShapeData.Scale); } else @@ -790,7 +791,6 @@ public class BSShapeCollection : IDisposable // If the collisionObject is not the correct type for solidness, rebuild what's there mustRebuild = true; } - } if (mustRebuild || forceRebuild) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index ae267e3..880859a 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -333,8 +333,8 @@ public class BSTerrainManager // Make sure the new shape is processed. // BulletSimAPI.Activate2(mapInfo.terrainBody.ptr, true); - BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.ISLAND_SLEEPING); - // 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; }; -- cgit v1.1 From 804b332d45c3989958f5ec08e1509ba373fb84b1 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 25 Oct 2012 08:04:20 -0700 Subject: BulletSim: Add banking and other new code to vechile dynamics. Add third party license and contributor in for for Aurora-Sim project for physics code. --- .../Physics/BulletSPlugin/BS6DofConstraint.cs | 2 +- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 2 +- .../BulletSPlugin/BSConstraintCollection.cs | 2 +- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 489 +++++++++++++-------- .../Physics/BulletSPlugin/BSHingeConstraint.cs | 2 +- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 2 + .../Physics/BulletSPlugin/BSLinksetConstraints.cs | 2 +- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 4 +- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 2 +- .../Physics/BulletSPlugin/BSShapeCollection.cs | 2 +- .../Physics/BulletSPlugin/BSTerrainManager.cs | 2 +- 11 files changed, 323 insertions(+), 188 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs index 3306a97..310df3d 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs @@ -32,7 +32,7 @@ using OpenMetaverse; namespace OpenSim.Region.Physics.BulletSPlugin { -public class BS6DofConstraint : BSConstraint +public sealed class BS6DofConstraint : BSConstraint { private static string LogHeader = "[BULLETSIM 6DOF CONSTRAINT]"; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index a041ba8..9fea9b8 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -34,7 +34,7 @@ using OpenSim.Region.Physics.Manager; namespace OpenSim.Region.Physics.BulletSPlugin { -public class BSCharacter : BSPhysObject +public sealed class BSCharacter : BSPhysObject { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly string LogHeader = "[BULLETS CHAR]"; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs index 22ea367..b9add06 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs @@ -33,7 +33,7 @@ using OpenMetaverse; namespace OpenSim.Region.Physics.BulletSPlugin { -public class BSConstraintCollection : IDisposable +public sealed class BSConstraintCollection : IDisposable { // private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); // private static readonly string LogHeader = "[CONSTRAINT COLLECTION]"; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 117c878..9b59bef 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -52,7 +52,7 @@ using OpenSim.Region.Physics.Manager; namespace OpenSim.Region.Physics.BulletSPlugin { - public class BSDynamics + public sealed class BSDynamics { private BSScene PhysicsScene { get; set; } // the prim this dynamic controller belongs to @@ -72,8 +72,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin // LIMIT_ROLL_ONLY private Vector3 m_BlockingEndPoint = Vector3.Zero; private Quaternion m_RollreferenceFrame = Quaternion.Identity; + private Quaternion m_referenceFrame = Quaternion.Identity; + // Linear properties private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time + private Vector3 m_linearMotorOffset = Vector3.Zero; // the point of force can be offset from the center private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL private Vector3 m_newVelocity = Vector3.Zero; // velocity computed to be applied to body private Vector3 m_linearFrictionTimescale = Vector3.Zero; @@ -95,19 +98,19 @@ namespace OpenSim.Region.Physics.BulletSPlugin private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body //Deflection properties - // private float m_angularDeflectionEfficiency = 0; - // private float m_angularDeflectionTimescale = 0; - // private float m_linearDeflectionEfficiency = 0; - // private float m_linearDeflectionTimescale = 0; + private float m_angularDeflectionEfficiency = 0; + private float m_angularDeflectionTimescale = 0; + private float m_linearDeflectionEfficiency = 0; + private float m_linearDeflectionTimescale = 0; //Banking properties - // private float m_bankingEfficiency = 0; - // private float m_bankingMix = 0; - // private float m_bankingTimescale = 0; + private float m_bankingEfficiency = 0; + private float m_bankingMix = 0; + private float m_bankingTimescale = 0; //Hover and Buoyancy properties private float m_VhoverHeight = 0f; -// private float m_VhoverEfficiency = 0f; + private float m_VhoverEfficiency = 0f; private float m_VhoverTimescale = 0f; private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle. @@ -138,10 +141,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin switch (pParam) { case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: - // m_angularDeflectionEfficiency = Math.Max(pValue, 0.01f); + m_angularDeflectionEfficiency = Math.Max(pValue, 0.01f); break; case Vehicle.ANGULAR_DEFLECTION_TIMESCALE: - // m_angularDeflectionTimescale = Math.Max(pValue, 0.01f); + m_angularDeflectionTimescale = Math.Max(pValue, 0.01f); break; case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE: m_angularMotorDecayTimescale = Math.Max(pValue, 0.01f); @@ -150,20 +153,20 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_angularMotorTimescale = Math.Max(pValue, 0.01f); break; case Vehicle.BANKING_EFFICIENCY: - // m_bankingEfficiency = Math.Max(pValue, 0.01f); + m_bankingEfficiency = Math.Max(-1f, Math.Min(pValue, 1f)); break; case Vehicle.BANKING_MIX: - // m_bankingMix = Math.Max(pValue, 0.01f); + m_bankingMix = Math.Max(pValue, 0.01f); break; case Vehicle.BANKING_TIMESCALE: - // m_bankingTimescale = Math.Max(pValue, 0.01f); + m_bankingTimescale = Math.Max(pValue, 0.01f); break; case Vehicle.BUOYANCY: m_VehicleBuoyancy = Math.Max(-1f, Math.Min(pValue, 1f)); break; -// case Vehicle.HOVER_EFFICIENCY: -// m_VhoverEfficiency = Math.Max(0f, Math.Min(pValue, 1f)); -// break; + case Vehicle.HOVER_EFFICIENCY: + m_VhoverEfficiency = Math.Max(0f, Math.Min(pValue, 1f)); + break; case Vehicle.HOVER_HEIGHT: m_VhoverHeight = pValue; break; @@ -171,10 +174,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_VhoverTimescale = Math.Max(pValue, 0.01f); break; case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: - // m_linearDeflectionEfficiency = Math.Max(pValue, 0.01f); + m_linearDeflectionEfficiency = Math.Max(pValue, 0.01f); break; case Vehicle.LINEAR_DEFLECTION_TIMESCALE: - // m_linearDeflectionTimescale = Math.Max(pValue, 0.01f); + m_linearDeflectionTimescale = Math.Max(pValue, 0.01f); break; case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE: m_linearMotorDecayTimescale = Math.Max(pValue, 0.01f); @@ -196,7 +199,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin break; case Vehicle.ANGULAR_MOTOR_DIRECTION: m_angularMotorDirection = new Vector3(pValue, pValue, pValue); - m_angularMotorApply = 10; + m_angularMotorApply = 100; break; case Vehicle.LINEAR_FRICTION_TIMESCALE: m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); @@ -206,7 +209,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_linearMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue); break; case Vehicle.LINEAR_MOTOR_OFFSET: - // m_linearMotorOffset = new Vector3(pValue, pValue, pValue); + m_linearMotorOffset = new Vector3(pValue, pValue, pValue); break; } @@ -221,15 +224,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); break; case Vehicle.ANGULAR_MOTOR_DIRECTION: - m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); // Limit requested angular speed to 2 rps= 4 pi rads/sec - if (m_angularMotorDirection.X > 12.56f) m_angularMotorDirection.X = 12.56f; - if (m_angularMotorDirection.X < - 12.56f) m_angularMotorDirection.X = - 12.56f; - if (m_angularMotorDirection.Y > 12.56f) m_angularMotorDirection.Y = 12.56f; - if (m_angularMotorDirection.Y < - 12.56f) m_angularMotorDirection.Y = - 12.56f; - if (m_angularMotorDirection.Z > 12.56f) m_angularMotorDirection.Z = 12.56f; - if (m_angularMotorDirection.Z < - 12.56f) m_angularMotorDirection.Z = - 12.56f; - m_angularMotorApply = 10; + pValue.X = Math.Max(-12.56f, Math.Min(pValue.X, 12.56f)); + pValue.Y = Math.Max(-12.56f, Math.Min(pValue.Y, 12.56f)); + pValue.Z = Math.Max(-12.56f, Math.Min(pValue.Z, 12.56f)); + m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); + m_angularMotorApply = 100; break; case Vehicle.LINEAR_FRICTION_TIMESCALE: m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); @@ -239,7 +239,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z); break; case Vehicle.LINEAR_MOTOR_OFFSET: - // m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z); + m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z); break; case Vehicle.BLOCK_EXIT: m_BlockingEndPoint = new Vector3(pValue.X, pValue.Y, pValue.Z); @@ -253,7 +253,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin switch (pParam) { case Vehicle.REFERENCE_FRAME: - // m_referenceFrame = pValue; + m_referenceFrame = pValue; break; case Vehicle.ROLL_FRAME: m_RollreferenceFrame = pValue; @@ -265,21 +265,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin { VDetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", Prim.LocalID, pParam, remove); VehicleFlag parm = (VehicleFlag)pParam; - if (remove) + if (pParam == -1) + m_flags = (VehicleFlag)0; + else { - if (pParam == -1) - { - m_flags = (VehicleFlag)0; - } - else - { + if (remove) m_flags &= ~parm; - } - } - else { - m_flags |= parm; + else + m_flags |= parm; } - }//end ProcessVehicleFlags + } internal void ProcessTypeChange(Vehicle pType) { @@ -288,99 +283,142 @@ namespace OpenSim.Region.Physics.BulletSPlugin Type = pType; switch (pType) { - case Vehicle.TYPE_NONE: - m_linearFrictionTimescale = new Vector3(0, 0, 0); - m_angularFrictionTimescale = new Vector3(0, 0, 0); + case Vehicle.TYPE_NONE: m_linearMotorDirection = Vector3.Zero; m_linearMotorTimescale = 0; m_linearMotorDecayTimescale = 0; + m_linearFrictionTimescale = new Vector3(0, 0, 0); + m_angularMotorDirection = Vector3.Zero; - m_angularMotorTimescale = 0; m_angularMotorDecayTimescale = 0; + m_angularMotorTimescale = 0; + m_angularFrictionTimescale = new Vector3(0, 0, 0); + m_VhoverHeight = 0; + m_VhoverEfficiency = 0; m_VhoverTimescale = 0; m_VehicleBuoyancy = 0; + + m_linearDeflectionEfficiency = 1; + m_linearDeflectionTimescale = 1; + + m_angularDeflectionEfficiency = 0; + m_angularDeflectionTimescale = 1000; + + m_verticalAttractionEfficiency = 0; + m_verticalAttractionTimescale = 0; + + m_bankingEfficiency = 0; + m_bankingTimescale = 1000; + m_bankingMix = 1; + + m_referenceFrame = Quaternion.Identity; m_flags = (VehicleFlag)0; break; case Vehicle.TYPE_SLED: - m_linearFrictionTimescale = new Vector3(30, 1, 1000); - m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); m_linearMotorDirection = Vector3.Zero; m_linearMotorTimescale = 1000; m_linearMotorDecayTimescale = 120; + m_linearFrictionTimescale = new Vector3(30, 1, 1000); + m_angularMotorDirection = Vector3.Zero; m_angularMotorTimescale = 1000; m_angularMotorDecayTimescale = 120; + m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); + m_VhoverHeight = 0; -// m_VhoverEfficiency = 1; + m_VhoverEfficiency = 10; // TODO: this looks wrong!! m_VhoverTimescale = 10; m_VehicleBuoyancy = 0; - // m_linearDeflectionEfficiency = 1; - // m_linearDeflectionTimescale = 1; - // m_angularDeflectionEfficiency = 1; - // m_angularDeflectionTimescale = 1000; - // m_bankingEfficiency = 0; - // m_bankingMix = 1; - // m_bankingTimescale = 10; - // m_referenceFrame = Quaternion.Identity; + + m_linearDeflectionEfficiency = 1; + m_linearDeflectionTimescale = 1; + + m_angularDeflectionEfficiency = 1; + m_angularDeflectionTimescale = 1000; + + m_verticalAttractionEfficiency = 0; + m_verticalAttractionTimescale = 0; + + m_bankingEfficiency = 0; + m_bankingTimescale = 10; + m_bankingMix = 1; + + m_referenceFrame = Quaternion.Identity; m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP); m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); break; case Vehicle.TYPE_CAR: - m_linearFrictionTimescale = new Vector3(100, 2, 1000); - m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); m_linearMotorDirection = Vector3.Zero; m_linearMotorTimescale = 1; m_linearMotorDecayTimescale = 60; + m_linearFrictionTimescale = new Vector3(100, 2, 1000); + m_angularMotorDirection = Vector3.Zero; m_angularMotorTimescale = 1; m_angularMotorDecayTimescale = 0.8f; + m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); + m_VhoverHeight = 0; -// m_VhoverEfficiency = 0; + m_VhoverEfficiency = 0; m_VhoverTimescale = 1000; m_VehicleBuoyancy = 0; - // // m_linearDeflectionEfficiency = 1; - // // m_linearDeflectionTimescale = 2; - // // m_angularDeflectionEfficiency = 0; - // m_angularDeflectionTimescale = 10; + + m_linearDeflectionEfficiency = 1; + m_linearDeflectionTimescale = 2; + + m_angularDeflectionEfficiency = 0; + m_angularDeflectionTimescale = 10; + m_verticalAttractionEfficiency = 1f; m_verticalAttractionTimescale = 10f; - // m_bankingEfficiency = -0.2f; - // m_bankingMix = 1; - // m_bankingTimescale = 1; - // m_referenceFrame = Quaternion.Identity; + + m_bankingEfficiency = -0.2f; + m_bankingMix = 1; + m_bankingTimescale = 1; + + m_referenceFrame = Quaternion.Identity; + m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY + | VehicleFlag.HOVER_TERRAIN_ONLY + | VehicleFlag.HOVER_GLOBAL_HEIGHT); m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY - | VehicleFlag.LIMIT_MOTOR_UP); - m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT); - m_flags |= (VehicleFlag.HOVER_UP_ONLY); + | VehicleFlag.LIMIT_MOTOR_UP + | VehicleFlag.HOVER_UP_ONLY); break; case Vehicle.TYPE_BOAT: - m_linearFrictionTimescale = new Vector3(10, 3, 2); - m_angularFrictionTimescale = new Vector3(10,10,10); m_linearMotorDirection = Vector3.Zero; m_linearMotorTimescale = 5; m_linearMotorDecayTimescale = 60; + m_linearFrictionTimescale = new Vector3(10, 3, 2); + m_angularMotorDirection = Vector3.Zero; m_angularMotorTimescale = 4; m_angularMotorDecayTimescale = 4; + m_angularFrictionTimescale = new Vector3(10,10,10); + m_VhoverHeight = 0; -// m_VhoverEfficiency = 0.5f; + m_VhoverEfficiency = 0.5f; m_VhoverTimescale = 2; m_VehicleBuoyancy = 1; - // m_linearDeflectionEfficiency = 0.5f; - // m_linearDeflectionTimescale = 3; - // m_angularDeflectionEfficiency = 0.5f; - // m_angularDeflectionTimescale = 5; + + m_linearDeflectionEfficiency = 0.5f; + m_linearDeflectionTimescale = 3; + + m_angularDeflectionEfficiency = 0.5f; + m_angularDeflectionTimescale = 5; + m_verticalAttractionEfficiency = 0.5f; m_verticalAttractionTimescale = 5f; - // m_bankingEfficiency = -0.3f; - // m_bankingMix = 0.8f; - // m_bankingTimescale = 1; - // m_referenceFrame = Quaternion.Identity; + + m_bankingEfficiency = -0.3f; + m_bankingMix = 0.8f; + m_bankingTimescale = 1; + + m_referenceFrame = Quaternion.Identity; m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.LIMIT_ROLL_ONLY @@ -390,28 +428,35 @@ namespace OpenSim.Region.Physics.BulletSPlugin | VehicleFlag.HOVER_WATER_ONLY); break; case Vehicle.TYPE_AIRPLANE: - m_linearFrictionTimescale = new Vector3(200, 10, 5); - m_angularFrictionTimescale = new Vector3(20, 20, 20); m_linearMotorDirection = Vector3.Zero; m_linearMotorTimescale = 2; m_linearMotorDecayTimescale = 60; + m_linearFrictionTimescale = new Vector3(200, 10, 5); + m_angularMotorDirection = Vector3.Zero; m_angularMotorTimescale = 4; m_angularMotorDecayTimescale = 4; + m_angularFrictionTimescale = new Vector3(20, 20, 20); + m_VhoverHeight = 0; -// m_VhoverEfficiency = 0.5f; + m_VhoverEfficiency = 0.5f; m_VhoverTimescale = 1000; m_VehicleBuoyancy = 0; - // m_linearDeflectionEfficiency = 0.5f; - // m_linearDeflectionTimescale = 3; - // m_angularDeflectionEfficiency = 1; - // m_angularDeflectionTimescale = 2; + + m_linearDeflectionEfficiency = 0.5f; + m_linearDeflectionTimescale = 3; + + m_angularDeflectionEfficiency = 1; + m_angularDeflectionTimescale = 2; + m_verticalAttractionEfficiency = 0.9f; m_verticalAttractionTimescale = 2f; - // m_bankingEfficiency = 1; - // m_bankingMix = 0.7f; - // m_bankingTimescale = 2; - // m_referenceFrame = Quaternion.Identity; + + m_bankingEfficiency = 1; + m_bankingMix = 0.7f; + m_bankingTimescale = 2; + + m_referenceFrame = Quaternion.Identity; m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT @@ -421,28 +466,36 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); break; case Vehicle.TYPE_BALLOON: - m_linearFrictionTimescale = new Vector3(5, 5, 5); - m_angularFrictionTimescale = new Vector3(10, 10, 10); m_linearMotorDirection = Vector3.Zero; m_linearMotorTimescale = 5; + m_linearFrictionTimescale = new Vector3(5, 5, 5); m_linearMotorDecayTimescale = 60; + m_angularMotorDirection = Vector3.Zero; m_angularMotorTimescale = 6; + m_angularFrictionTimescale = new Vector3(10, 10, 10); m_angularMotorDecayTimescale = 10; + m_VhoverHeight = 5; -// m_VhoverEfficiency = 0.8f; + m_VhoverEfficiency = 0.8f; m_VhoverTimescale = 10; m_VehicleBuoyancy = 1; - // m_linearDeflectionEfficiency = 0; - // m_linearDeflectionTimescale = 5; - // m_angularDeflectionEfficiency = 0; - // m_angularDeflectionTimescale = 5; + + m_linearDeflectionEfficiency = 0; + m_linearDeflectionTimescale = 5; + + m_angularDeflectionEfficiency = 0; + m_angularDeflectionTimescale = 5; + m_verticalAttractionEfficiency = 1f; m_verticalAttractionTimescale = 100f; - // m_bankingEfficiency = 0; - // m_bankingMix = 0.7f; - // m_bankingTimescale = 5; - // m_referenceFrame = Quaternion.Identity; + + m_bankingEfficiency = 0; + m_bankingMix = 0.7f; + m_bankingTimescale = 5; + m_referenceFrame = Quaternion.Identity; + + m_referenceFrame = Quaternion.Identity; m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_UP_ONLY @@ -452,21 +505,27 @@ namespace OpenSim.Region.Physics.BulletSPlugin | VehicleFlag.HOVER_GLOBAL_HEIGHT); break; } - }//end SetDefaultsForType + } // Some of the properties of this prim may have changed. // Do any updating needed for a vehicle public void Refresh() { - if (!IsActive) - return; - - // Set the prim's inertia to zero. The vehicle code handles that and this - // removes the motion and torque actions introduced by Bullet. - Vector3 inertia = Vector3.Zero; - // comment out for DEBUG test - // BulletSimAPI.SetMassProps2(Prim.BSBody.ptr, Prim.MassRaw, inertia); - // BulletSimAPI.UpdateInertiaTensor2(Prim.BSBody.ptr); + /* + * Doesnt work unless BSDynamics senses and corrects for all collisions + if (IsActive) + BulletSimAPI.AddToCollisionFlags2(Prim.BSBody.ptr, CollisionFlags.CF_KINEMATIC_OBJECT); + else + BulletSimAPI.RemoveFromCollisionFlags2(Prim.BSBody.ptr, CollisionFlags.CF_KINEMATIC_OBJECT); + */ + /* + * Doesn't work because with zero inertia, Bullet will not apply any forces to the object. + if (IsActive) + { + BulletSimAPI.SetMassProps2(Prim.BSBody.ptr, Prim.MassRaw, Vector3.Zero); + BulletSimAPI.UpdateInertiaTensor2(Prim.BSBody.ptr); + } + */ } // One step of the vehicle properties for the next 'pTimestep' seconds. @@ -478,6 +537,22 @@ namespace OpenSim.Region.Physics.BulletSPlugin MoveAngular(pTimestep); LimitRotation(pTimestep); + /* Experimental + // Wonder if Bullet could handle collision penetration while this applies the forces. + // Apply the computed forces on the vehicle + Prim.ForcePosition += Prim.ForceVelocity * Prim.MassRaw * pTimestep; + + if (Prim.ForceRotationalVelocity != Vector3.Zero) + { + Quaternion newOrientation = Prim.ForceOrientation; + newOrientation.Normalize(); + Quaternion appliedRotation = new Quaternion((Prim.ForceRotationalVelocity * pTimestep), 0f); + newOrientation += (appliedRotation * newOrientation) * 0.5f; + newOrientation.Normalize(); + Prim.ForceOrientation = newOrientation; + } + */ + // remember the position so next step we can limit absolute movement effects m_lastPositionVector = Prim.ForcePosition; @@ -489,59 +564,46 @@ namespace OpenSim.Region.Physics.BulletSPlugin // Also does hover and float. private void MoveLinear(float pTimestep) { - // m_linearMotorDirection is the direction we are moving relative to the vehicle coordinates - // m_lastLinearVelocityVector is the speed we are moving in that direction + // m_linearMotorDirection is the target direction we are moving relative to the vehicle coordinates + // m_lastLinearVelocityVector is the current speed we are moving in that direction if (m_linearMotorDirection.LengthSquared() > 0.001f) { Vector3 origDir = m_linearMotorDirection; Vector3 origVel = m_lastLinearVelocityVector; // add drive to body - // Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale / pTimestep); Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/(m_linearMotorTimescale / pTimestep); // lastLinearVelocityVector is the current body velocity vector - // RA: Not sure what the *10 is for. A correction for pTimestep? - // m_lastLinearVelocityVector += (addAmount*10); m_lastLinearVelocityVector += addAmount; - // Limit the velocity vector to less than the last set linear motor direction - if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X)) - m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X; - if (Math.Abs(m_lastLinearVelocityVector.Y) > Math.Abs(m_linearMotorDirectionLASTSET.Y)) - m_lastLinearVelocityVector.Y = m_linearMotorDirectionLASTSET.Y; - if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z)) - m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z; - - /* - // decay applied velocity - Vector3 decayfraction = Vector3.One/(m_linearMotorDecayTimescale / pTimestep); - // (RA: do not know where the 0.5f comes from) - m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f; - */ float keepfraction = 1.0f - (1.0f / (m_linearMotorDecayTimescale / pTimestep)); m_linearMotorDirection *= keepfraction; VDetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},notDecay={4},dir={5},vel={6}", Prim.LocalID, origDir, origVel, addAmount, keepfraction, m_linearMotorDirection, m_lastLinearVelocityVector); + + // convert requested object velocity to object relative vector + m_newVelocity = m_lastLinearVelocityVector * Prim.ForceOrientation; } else { // if what remains of direction is very small, zero it. m_linearMotorDirection = Vector3.Zero; m_lastLinearVelocityVector = Vector3.Zero; + m_newVelocity = Vector3.Zero; + VDetailLog("{0},MoveLinear,zeroed", Prim.LocalID); } - // convert requested object velocity to object relative vector - Quaternion rotq = Prim.ForceOrientation; - m_newVelocity = m_lastLinearVelocityVector * rotq; + // m_newVelocity is velocity computed from linear motor // Add the various forces into m_dir which will be our new direction vector (velocity) // add Gravity and Buoyancy // There is some gravity, make a gravity force vector that is applied after object velocity. // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; - Vector3 grav = Prim.PhysicsScene.DefaultGravity * (Prim.Linkset.LinksetMass * (1f - m_VehicleBuoyancy)); + // Vector3 grav = Prim.PhysicsScene.DefaultGravity * (Prim.Linkset.LinksetMass * (1f - m_VehicleBuoyancy)); + Vector3 grav = Prim.PhysicsScene.DefaultGravity * (1f - m_VehicleBuoyancy); /* * RA: Not sure why one would do this @@ -567,6 +629,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin } // Check if hovering + // m_VhoverEfficiency: 0=bouncy, 1=totally damped + // m_VhoverTimescale: time to achieve height if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) { // We should hover, get the target height @@ -597,13 +661,19 @@ namespace OpenSim.Region.Physics.BulletSPlugin } else { - float herr0 = pos.Z - m_VhoverTargetHeight; + float horizontalError = pos.Z - m_VhoverTargetHeight; + // RA: where does the 50 come from> + float horizontalCorrectionVelocity = ((horizontalError * 50.0f) / (m_VhoverTimescale / pTimestep)); // Replace Vertical speed with correction figure if significant - if (Math.Abs(herr0) > 0.01f) + if (Math.Abs(horizontalError) > 0.01f) { - m_newVelocity.Z = -((herr0 * pTimestep * 50.0f) / m_VhoverTimescale); + m_newVelocity.Z += horizontalCorrectionVelocity; //KF: m_VhoverEfficiency is not yet implemented } + else if (horizontalError < -0.01) + { + m_newVelocity.Z -= horizontalCorrectionVelocity; + } else { m_newVelocity.Z = 0f; @@ -678,16 +748,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin if ((m_flags & (VehicleFlag.NO_Z)) != 0) m_newVelocity.Z = 0; - // Apply velocity - Prim.ForceVelocity = m_newVelocity; - // apply gravity force - // Why is this set here? The physics engine already does gravity. - Prim.AddForce(grav, false, true); - // Apply friction Vector3 keepFraction = Vector3.One - (Vector3.One / (m_linearFrictionTimescale / pTimestep)); m_lastLinearVelocityVector *= keepFraction; + // Apply velocity + // Prim.ForceVelocity = m_newVelocity; + Prim.AddForce(m_newVelocity, false); + VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},grav={4},1Mdecay={5}", Prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity, grav, keepFraction); @@ -717,11 +785,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin Vector3 origDir = m_angularMotorDirection; // ramp up to new value - // new velocity += error / ( time to get there / step interval) - // requested speed - last motor speed - m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep); - m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep); - m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep); + // new velocity += error / ( time to get there / step interval) + // requested speed - last motor speed + m_angularMotorVelocity += (m_angularMotorDirection - m_angularMotorVelocity) / (m_angularMotorTimescale / pTimestep); VDetailLog("{0},MoveAngular,angularMotorApply,apply={1},angTScale={2},timeStep={3},origvel={4},origDir={5},vel={6}", Prim.LocalID, m_angularMotorApply, m_angularMotorTimescale, pTimestep, origVel, origDir, m_angularMotorVelocity); @@ -732,46 +798,50 @@ namespace OpenSim.Region.Physics.BulletSPlugin { // No motor recently applied, keep the body velocity // and decay the velocity - m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep); - if (m_angularMotorVelocity.LengthSquared() < 0.00001) + if (m_angularMotorVelocity.LengthSquared() < 0.0001) m_angularMotorVelocity = Vector3.Zero; + else + m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep); } // end motor section - // Vertical attractor section + #region Vertical attactor + Vector3 vertattr = Vector3.Zero; Vector3 deflection = Vector3.Zero; Vector3 banking = Vector3.Zero; if (m_verticalAttractionTimescale < 300 && m_lastAngularVelocity != Vector3.Zero) { - float VAservo = 0.2f / (m_verticalAttractionTimescale / pTimestep); + float VAservo = 0.2f; + if (Prim.Linkset.LinksetIsColliding) + VAservo = 0.05f / (m_verticalAttractionTimescale / pTimestep); + VAservo *= (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); // get present body rotation Quaternion rotq = Prim.ForceOrientation; // vector pointing up - Vector3 verterr = Vector3.Zero; - verterr.Z = 1.0f; + Vector3 verticalError = Vector3.UnitZ; // rotate it to Body Angle - verterr = verterr * rotq; - // verterr.X and .Y are the World error amounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1. + verticalError = verticalError * rotq; + // verticalError.X and .Y are the World error amounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1. // As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go // negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body. // Error is 0 (no error) to +/- 2 (max error) - if (verterr.Z < 0.0f) + if (verticalError.Z < 0.0f) { - verterr.X = 2.0f - verterr.X; - verterr.Y = 2.0f - verterr.Y; + verticalError.X = 2.0f - verticalError.X; + verticalError.Y = 2.0f - verticalError.Y; } // scale it by VAservo - verterr = verterr * VAservo; + verticalError = verticalError * VAservo; - // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so + // As the body rotates around the X axis, then verticalError.Y increases; Rotated around Y then .X increases, so // Change Body angular velocity X based on Y, and Y based on X. Z is not changed. - vertattr.X = verterr.Y; - vertattr.Y = - verterr.X; + vertattr.X = verticalError.Y; + vertattr.Y = - verticalError.X; vertattr.Z = 0f; // scaling appears better usingsquare-law @@ -779,10 +849,77 @@ namespace OpenSim.Region.Physics.BulletSPlugin vertattr.X += bounce * angularVelocity.X; vertattr.Y += bounce * angularVelocity.Y; - VDetailLog("{0},MoveAngular,verticalAttraction,verterr={1},bounce={2},vertattr={3}", - Prim.LocalID, verterr, bounce, vertattr); + VDetailLog("{0},MoveAngular,verticalAttraction,verticalError={1},bounce={2},vertattr={3}", + Prim.LocalID, verticalError, bounce, vertattr); + + } + #endregion // Vertical attactor + + #region Deflection + + //Forward is the prefered direction, but if the reference frame has changed, we need to take this into account as well + Vector3 PreferredAxisOfMotion = + new Vector3((10*(m_angularDeflectionEfficiency/m_angularDeflectionTimescale)), 0, 0); + PreferredAxisOfMotion *= Quaternion.Add(Prim.ForceOrientation, m_referenceFrame); + + //Multiply it so that it scales linearly + //deflection = PreferredAxisOfMotion; + + //deflection = ((PreferredAxisOfMotion * m_angularDeflectionEfficiency) / (m_angularDeflectionTimescale / pTimestep)); + + #endregion - } // else vertical attractor is off + #region Banking + + if (m_bankingEfficiency != 0) + { + Vector3 dir = Vector3.One * Prim.ForceOrientation; + float mult = (m_bankingMix*m_bankingMix)*-1*(m_bankingMix < 0 ? -1 : 1); + //Changes which way it banks in and out of turns + + //Use the square of the efficiency, as it looks much more how SL banking works + float effSquared = (m_bankingEfficiency*m_bankingEfficiency); + if (m_bankingEfficiency < 0) + effSquared *= -1; //Keep the negative! + + float mix = Math.Abs(m_bankingMix); + if (m_angularMotorVelocity.X == 0) + { + /*if (!parent.Orientation.ApproxEquals(this.m_referenceFrame, 0.25f)) + { + Vector3 axisAngle; + float angle; + parent.Orientation.GetAxisAngle(out axisAngle, out angle); + Vector3 rotatedVel = parent.Velocity * parent.Orientation; + if ((rotatedVel.X < 0 && axisAngle.Y > 0) || (rotatedVel.X > 0 && axisAngle.Y < 0)) + m_angularMotorVelocity.X += (effSquared * (mult * mix)) * (1f) * 10; + else + m_angularMotorVelocity.X += (effSquared * (mult * mix)) * (-1f) * 10; + }*/ + } + else + banking.Z += (effSquared*(mult*mix))*(m_angularMotorVelocity.X) * 4; + if (!Prim.Linkset.LinksetIsColliding && Math.Abs(m_angularMotorVelocity.X) > mix) + //If they are colliding, we probably shouldn't shove the prim around... probably + { + float angVelZ = m_angularMotorVelocity.X*-1; + /*if(angVelZ > mix) + angVelZ = mix; + else if(angVelZ < -mix) + angVelZ = -mix;*/ + //This controls how fast and how far the banking occurs + Vector3 bankingRot = new Vector3(angVelZ*(effSquared*mult), 0, 0); + if (bankingRot.X > 3) + bankingRot.X = 3; + else if (bankingRot.X < -3) + bankingRot.X = -3; + bankingRot *= Prim.ForceOrientation; + banking += bankingRot; + } + m_angularMotorVelocity.X *= m_bankingEfficiency == 1 ? 0.0f : 1 - m_bankingEfficiency; + } + + #endregion m_lastVertAttractor = vertattr; @@ -811,7 +948,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_lastAngularVelocity -= m_lastAngularVelocity * decayamount; // Apply to the body - Prim.ForceRotationalVelocity = m_lastAngularVelocity; + // Prim.ForceRotationalVelocity = m_lastAngularVelocity; + Prim.AddAngularForce(m_lastAngularVelocity, false); VDetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", Prim.LocalID, decayamount, m_lastAngularVelocity); } //end MoveAngular @@ -820,38 +958,31 @@ namespace OpenSim.Region.Physics.BulletSPlugin { Quaternion rotq = Prim.ForceOrientation; Quaternion m_rot = rotq; - bool changed = false; if (m_RollreferenceFrame != Quaternion.Identity) { if (rotq.X >= m_RollreferenceFrame.X) { m_rot.X = rotq.X - (m_RollreferenceFrame.X / 2); - changed = true; } if (rotq.Y >= m_RollreferenceFrame.Y) { m_rot.Y = rotq.Y - (m_RollreferenceFrame.Y / 2); - changed = true; } if (rotq.X <= -m_RollreferenceFrame.X) { m_rot.X = rotq.X + (m_RollreferenceFrame.X / 2); - changed = true; } if (rotq.Y <= -m_RollreferenceFrame.Y) { m_rot.Y = rotq.Y + (m_RollreferenceFrame.Y / 2); - changed = true; } - changed = true; } if ((m_flags & VehicleFlag.LOCK_ROTATION) != 0) { m_rot.X = 0; m_rot.Y = 0; - changed = true; } - if (changed) + if (rotq != m_rot) { Prim.ForceOrientation = m_rot; VDetailLog("{0},LimitRotation,done,orig={1},new={2}", Prim.LocalID, rotq, m_rot); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs index 7c8a215..76bd930 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs @@ -32,7 +32,7 @@ using OpenMetaverse; namespace OpenSim.Region.Physics.BulletSPlugin { -class BSHingeConstraint : BSConstraint +public sealed class BSHingeConstraint : BSConstraint { public override ConstraintType Type { get { return ConstraintType.HINGE_CONSTRAINT_TYPE; } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index c984824..24fe6b9 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -88,6 +88,8 @@ public abstract class BSLinkset } } + public virtual bool LinksetIsColliding { get { return false; } } + public OMV.Vector3 CenterOfMass { get { return ComputeLinksetCenterOfMass(); } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs index 8a750b5..003c294 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs @@ -32,7 +32,7 @@ using OMV = OpenMetaverse; namespace OpenSim.Region.Physics.BulletSPlugin { -public class BSLinksetConstraints : BSLinkset +public sealed class BSLinksetConstraints : BSLinkset { // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]"; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 38ab3de..39d20dc 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -311,6 +311,7 @@ public sealed class BSPrim : BSPhysObject if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) { float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position); + // TODO: a floating motor so object will bob in the water if (Position.Z < waterHeight) { _position.Z = waterHeight; @@ -902,7 +903,8 @@ public sealed class BSPrim : BSPhysObject } // DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, fSum); // For unknown reasons, "ApplyCentralForce" adds this force to the total force on the object. - BulletSimAPI.ApplyCentralForce2(BSBody.ptr, fSum); + if (fSum != OMV.Vector3.Zero) + BulletSimAPI.ApplyCentralForce2(BSBody.ptr, fSum); }; if (inTaintTime) addForceOperation(); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index db0c99e..9e95ce5 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -62,7 +62,7 @@ using OpenMetaverse; // namespace OpenSim.Region.Physics.BulletSPlugin { -public class BSScene : PhysicsScene, IPhysicsParameters +public sealed class BSScene : PhysicsScene, IPhysicsParameters { private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); private static readonly string LogHeader = "[BULLETS SCENE]"; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 30fa50a..1c0e6f5 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -34,7 +34,7 @@ using OpenSim.Region.Physics.ConvexDecompositionDotNet; namespace OpenSim.Region.Physics.BulletSPlugin { -public class BSShapeCollection : IDisposable +public sealed class BSShapeCollection : IDisposable { private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]"; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index 880859a..11298fe 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -40,7 +40,7 @@ using OpenMetaverse; namespace OpenSim.Region.Physics.BulletSPlugin { -public class BSTerrainManager +public sealed class BSTerrainManager { static string LogHeader = "[BULLETSIM TERRAIN MANAGER]"; -- cgit v1.1 From b83449ae9ad3073abaa06167a99c47943c3199c2 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 26 Oct 2012 13:47:28 -0700 Subject: BulletSim: correct spelling of Bullet call. It's 'swept' not 'sweep'. --- OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs | 4 ++++ OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | 2 +- OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs | 4 ++-- 3 files changed, 7 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs index 310df3d..ecb3ec8 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs @@ -135,7 +135,11 @@ public sealed 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); + m_world.physicsScene.DetailLog("{0},BS6DOFConstraint,TransLimitMotor,enable={1},vel={2},maxForce={3}", + BSScene.DetailLogZero, enable, targetVelocity, maxMotorForce); + } return ret; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 9fea9b8..8bb4b21 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -152,7 +152,7 @@ public sealed class BSCharacter : BSPhysObject if (PhysicsScene.Params.ccdMotionThreshold > 0f) { BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold); - BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); + BulletSimAPI.SetCcdSweptSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); } OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 5ffd591..be3a5ad 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -881,10 +881,10 @@ public static extern float GetCcdMotionThreshold2(IntPtr obj); public static extern void SetCcdMotionThreshold2(IntPtr obj, float val); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetCcdSweepSphereRadius2(IntPtr obj); +public static extern float GetCcdSweptSphereRadius2(IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetCcdSweepSphereRadius2(IntPtr obj, float val); +public static extern void SetCcdSweptSphereRadius2(IntPtr obj, float val); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr GetUserPointer2(IntPtr obj); -- cgit v1.1 From 8fa83cf43045401ee02321e0fb1191402db5bb05 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 26 Oct 2012 13:49:57 -0700 Subject: BulletSim: Add activations after vehicle properties change. Problem was the vehicle was going to sleep while waiting for commands. Make AddAngularForce work the same way as AddForce -- accumulates values and pushes them once into Bullet. --- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 74 +++++++++++++++++++++----- 1 file changed, 62 insertions(+), 12 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 39d20dc..44937df 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -242,8 +242,8 @@ public sealed class BSPrim : BSPhysObject _acceleration = OMV.Vector3.Zero; _rotationalVelocity = OMV.Vector3.Zero; - // Zero some other properties directly into the physics engine - BulletSimAPI.ClearForces2(BSBody.ptr); + // Zero some other properties in the physics engine + BulletSimAPI.ClearAllForces2(BSBody.ptr); } public override void LockAngularMotion(OMV.Vector3 axis) @@ -275,6 +275,7 @@ public sealed class BSPrim : BSPhysObject { // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); + ActivateIfPhysical(false); }); } } @@ -287,6 +288,7 @@ public sealed class BSPrim : BSPhysObject _position = value; PositionSanityCheck(); BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); + ActivateIfPhysical(false); } } @@ -401,6 +403,7 @@ public sealed class BSPrim : BSPhysObject // Done at taint time so we're sure the physics engine is not using the variables // Vehicle code changes the parameters for this vehicle type. _vehicle.ProcessTypeChange(type); + ActivateIfPhysical(false); }); } } @@ -409,6 +412,7 @@ public sealed class BSPrim : BSPhysObject PhysicsScene.TaintedObject("BSPrim.VehicleFloatParam", delegate() { _vehicle.ProcessFloatVehicleParam((Vehicle)param, value); + ActivateIfPhysical(false); }); } public override void VehicleVectorParam(int param, OMV.Vector3 value) @@ -416,6 +420,7 @@ public sealed class BSPrim : BSPhysObject PhysicsScene.TaintedObject("BSPrim.VehicleVectorParam", delegate() { _vehicle.ProcessVectorVehicleParam((Vehicle)param, value); + ActivateIfPhysical(false); }); } public override void VehicleRotationParam(int param, OMV.Quaternion rotation) @@ -423,6 +428,7 @@ public sealed class BSPrim : BSPhysObject PhysicsScene.TaintedObject("BSPrim.VehicleRotationParam", delegate() { _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); + ActivateIfPhysical(false); }); } public override void VehicleFlags(int param, bool remove) @@ -540,6 +546,8 @@ public sealed class BSPrim : BSPhysObject { // DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical); SetObjectDynamic(true); + // whether phys-to-static or static-to-phys, the object is not moving. + ZeroMotion(); }); } } @@ -623,7 +631,7 @@ public sealed class BSPrim : BSPhysObject // Become a Bullet 'static' object type CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_STATIC_OBJECT); // Stop all movement - BulletSimAPI.ClearAllForces2(BSBody.ptr); + ZeroMotion(); // Center of mass is at the center of the object BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.BSBody.ptr, _position, _orientation); // Mass is zero which disables a bunch of physics stuff in Bullet @@ -634,7 +642,7 @@ public sealed class BSPrim : BSPhysObject if (PhysicsScene.Params.ccdMotionThreshold > 0f) { BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold); - BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); + BulletSimAPI.SetCcdSweptSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); } // There can be special things needed for implementing linksets Linkset.MakeStatic(this); @@ -656,14 +664,14 @@ public sealed class BSPrim : BSPhysObject BulletSimAPI.SetRestitution2(BSBody.ptr, PhysicsScene.Params.defaultRestitution); // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 - BulletSimAPI.ClearAllForces2(BSBody.ptr); + // Since this can be called multiple times, only zero forces when becoming physical + // BulletSimAPI.ClearAllForces2(BSBody.ptr); // For good measure, make sure the transform is set through to the motion state BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); // A dynamic object has mass - IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.ptr); - OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, Mass); + OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, Mass); BulletSimAPI.SetMassProps2(BSBody.ptr, _mass, inertia); BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); @@ -671,7 +679,7 @@ public sealed class BSPrim : BSPhysObject if (PhysicsScene.Params.ccdMotionThreshold > 0f) { BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold); - BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); + BulletSimAPI.SetCcdSweptSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); } // Various values for simulation limits @@ -721,6 +729,15 @@ public sealed class BSPrim : BSPhysObject } } + // Enable physical actions. Bullet will keep sleeping non-moving physical objects so + // they need waking up when parameters are changed. + // Called in taint-time!! + private void ActivateIfPhysical(bool forceIt) + { + if (IsPhysical) + BulletSimAPI.Activate2(BSBody.ptr, forceIt); + } + // Turn on or off the flag controlling whether collision events are returned to the simulator. private void EnableCollisions(bool wantsCollisionEvents) { @@ -901,8 +918,7 @@ public sealed class BSPrim : BSPhysObject } m_accumulatedForces.Clear(); } - // DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, fSum); - // For unknown reasons, "ApplyCentralForce" adds this force to the total force on the object. + DetailLog("{0},BSPrim.AddForce,taint,force={1}", LocalID, fSum); if (fSum != OMV.Vector3.Zero) BulletSimAPI.ApplyCentralForce2(BSBody.ptr, fSum); }; @@ -912,9 +928,43 @@ public sealed class BSPrim : BSPhysObject PhysicsScene.TaintedObject("BSPrim.AddForce", addForceOperation); } + private List m_accumulatedAngularForces = new List(); public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { - // DetailLog("{0},BSPrim.AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce); - // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce); + AddAngularForce(force, pushforce, false); + } + public void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) + { + if (force.IsFinite()) + { + // _force += force; + lock (m_accumulatedAngularForces) + m_accumulatedAngularForces.Add(new OMV.Vector3(force)); + } + else + { + m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); + return; + } + BSScene.TaintCallback addAngularForceOperation = delegate() + { + OMV.Vector3 fSum = OMV.Vector3.Zero; + lock (m_accumulatedAngularForces) + { + // Sum the accumulated additional forces for one big force to apply once. + foreach (OMV.Vector3 v in m_accumulatedAngularForces) + { + fSum += v; + } + m_accumulatedAngularForces.Clear(); + } + // DetailLog("{0},BSPrim.AddAngularForce,taint,aForce={1}", LocalID, fSum); + if (fSum != OMV.Vector3.Zero) + BulletSimAPI.ApplyTorque2(BSBody.ptr, fSum); + }; + if (inTaintTime) + addAngularForceOperation(); + else + PhysicsScene.TaintedObject("BSPrim.AddForce", addAngularForceOperation); } public override void SetMomentum(OMV.Vector3 momentum) { // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); -- cgit v1.1 From 2b75035aefceeae44e35364036a0748dfd5fb786 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 26 Oct 2012 13:54:54 -0700 Subject: BulletSim: add ForEachMember(action) call for linkset. --- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 36 ++++++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 24fe6b9..d0e514b 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -167,9 +167,8 @@ public abstract class BSLinkset bool ret = false; lock (m_linksetActivityLock) { - if (m_children.Contains(child)) - ret = true; - /* + ret = m_children.Contains(child); + /* Safer version but the above should work foreach (BSPhysObject bp in m_children) { if (child.LocalID == bp.LocalID) @@ -183,6 +182,25 @@ public abstract class BSLinkset return ret; } + // Perform an action on each member of the linkset including root prim. + // The action is performed only on the objects that are physically in the linkset. + // Depends on the action on whether this should be done at taint time. + public delegate bool ForEachMemberAction(BSPhysObject obj); + public virtual bool ForEachMember(ForEachMemberAction action) + { + bool ret = false; + lock (m_linksetActivityLock) + { + action(LinksetRoot); + foreach (BSPhysObject po in m_taintChildren) + { + if (action(po)) + break; + } + } + return ret; + } + // When physical properties are changed the linkset needs to recalculate // its internal properties. // May be called at runtime or taint-time (just pass the appropriate flag). @@ -224,13 +242,15 @@ public abstract class BSLinkset protected virtual float ComputeLinksetMass() { - float mass; - lock (m_linksetActivityLock) + float mass = LinksetRoot.MassRaw; + if (HasAnyChildren) { - mass = LinksetRoot.MassRaw; - foreach (BSPhysObject bp in m_taintChildren) + lock (m_linksetActivityLock) { - mass += bp.MassRaw; + foreach (BSPhysObject bp in m_children) + { + mass += bp.MassRaw; + } } } return mass; -- cgit v1.1 From 92d3c611e57fc320bf20b6b500c275eaebf912aa Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 26 Oct 2012 13:55:20 -0700 Subject: BulletSim: many small changes for vehicles simulation. --- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 71 ++++++++++++---------- 1 file changed, 40 insertions(+), 31 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 9b59bef..8bd8117 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -526,6 +526,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin BulletSimAPI.UpdateInertiaTensor2(Prim.BSBody.ptr); } */ + if (IsActive) + { + // Friction effects are handled by this vehicle code + BulletSimAPI.SetFriction2(Prim.BSBody.ptr, 0f); + BulletSimAPI.SetHitFraction2(Prim.BSBody.ptr, 0f); + } } // One step of the vehicle properties for the next 'pTimestep' seconds. @@ -552,6 +558,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin Prim.ForceOrientation = newOrientation; } */ + BulletSimAPI.SetInterpolationVelocity2(Prim.BSBody.ptr, m_newVelocity, m_lastAngularVelocity); // remember the position so next step we can limit absolute movement effects m_lastPositionVector = Prim.ForcePosition; @@ -570,17 +577,21 @@ namespace OpenSim.Region.Physics.BulletSPlugin { Vector3 origDir = m_linearMotorDirection; Vector3 origVel = m_lastLinearVelocityVector; + Vector3 vehicleVelocity = Prim.ForceVelocity * Quaternion.Inverse(Prim.ForceOrientation); // DEBUG // add drive to body Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/(m_linearMotorTimescale / pTimestep); // lastLinearVelocityVector is the current body velocity vector m_lastLinearVelocityVector += addAmount; - float keepfraction = 1.0f - (1.0f / (m_linearMotorDecayTimescale / pTimestep)); - m_linearMotorDirection *= keepfraction; + float decayFactor = (1.0f / m_linearMotorDecayTimescale) * pTimestep; + m_linearMotorDirection *= (1f - decayFactor); - VDetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},notDecay={4},dir={5},vel={6}", - Prim.LocalID, origDir, origVel, addAmount, keepfraction, m_linearMotorDirection, m_lastLinearVelocityVector); + Vector3 frictionFactor = (Vector3.One / m_linearFrictionTimescale) * pTimestep; + m_lastLinearVelocityVector *= (Vector3.One - frictionFactor); + + VDetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},vehVel={3},add={4},decay={5},lmDir={6},lmVel={7}", + Prim.LocalID, origDir, origVel, vehicleVelocity, addAmount, decayFactor, m_linearMotorDirection, m_lastLinearVelocityVector); // convert requested object velocity to object relative vector m_newVelocity = m_lastLinearVelocityVector * Prim.ForceOrientation; @@ -661,18 +672,18 @@ namespace OpenSim.Region.Physics.BulletSPlugin } else { - float horizontalError = pos.Z - m_VhoverTargetHeight; + float verticalError = pos.Z - m_VhoverTargetHeight; // RA: where does the 50 come from> - float horizontalCorrectionVelocity = ((horizontalError * 50.0f) / (m_VhoverTimescale / pTimestep)); + float verticalCorrectionVelocity = pTimestep * ((verticalError * 50.0f) / m_VhoverTimescale); // Replace Vertical speed with correction figure if significant - if (Math.Abs(horizontalError) > 0.01f) + if (Math.Abs(verticalError) > 0.01f) { - m_newVelocity.Z += horizontalCorrectionVelocity; + m_newVelocity.Z += verticalCorrectionVelocity; //KF: m_VhoverEfficiency is not yet implemented } - else if (horizontalError < -0.01) + else if (verticalError < -0.01) { - m_newVelocity.Z -= horizontalCorrectionVelocity; + m_newVelocity.Z -= verticalCorrectionVelocity; } else { @@ -748,16 +759,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin if ((m_flags & (VehicleFlag.NO_Z)) != 0) m_newVelocity.Z = 0; - // Apply friction - Vector3 keepFraction = Vector3.One - (Vector3.One / (m_linearFrictionTimescale / pTimestep)); - m_lastLinearVelocityVector *= keepFraction; - // Apply velocity - // Prim.ForceVelocity = m_newVelocity; - Prim.AddForce(m_newVelocity, false); + Prim.ForceVelocity = m_newVelocity; + // Prim.AddForce(m_newVelocity * Prim.Linkset.LinksetMass, false); + // Prim.AddForce(grav * Prim.Linkset.LinksetMass, false); - VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},grav={4},1Mdecay={5}", - Prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity, grav, keepFraction); + VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},grav={4}", + Prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity, grav); } // end MoveLinear() @@ -858,14 +866,17 @@ namespace OpenSim.Region.Physics.BulletSPlugin #region Deflection //Forward is the prefered direction, but if the reference frame has changed, we need to take this into account as well - Vector3 PreferredAxisOfMotion = - new Vector3((10*(m_angularDeflectionEfficiency/m_angularDeflectionTimescale)), 0, 0); - PreferredAxisOfMotion *= Quaternion.Add(Prim.ForceOrientation, m_referenceFrame); + if (m_angularDeflectionEfficiency != 0) + { + Vector3 preferredAxisOfMotion = + new Vector3((pTimestep * 10 * (m_angularDeflectionEfficiency / m_angularDeflectionTimescale)), 0, 0); + preferredAxisOfMotion *= Quaternion.Add(Prim.ForceOrientation, m_referenceFrame); - //Multiply it so that it scales linearly - //deflection = PreferredAxisOfMotion; + deflection = (preferredAxisOfMotion * (m_angularDeflectionEfficiency) / m_angularDeflectionTimescale) * pTimestep; - //deflection = ((PreferredAxisOfMotion * m_angularDeflectionEfficiency) / (m_angularDeflectionTimescale / pTimestep)); + VDetailLog("{0},MoveAngular,Deflection,perfAxis={1},deflection={2}", + Prim.LocalID, preferredAxisOfMotion, deflection); + } #endregion @@ -917,18 +928,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin banking += bankingRot; } m_angularMotorVelocity.X *= m_bankingEfficiency == 1 ? 0.0f : 1 - m_bankingEfficiency; + VDetailLog("{0},MoveAngular,Banking,bEff={1},angMotVel={2},banking={3}", + Prim.LocalID, m_bankingEfficiency, m_angularMotorVelocity, banking); } #endregion m_lastVertAttractor = vertattr; - // Bank section tba - - // Deflection section tba - // Sum velocities - m_lastAngularVelocity = m_angularMotorVelocity + vertattr; // + bank + deflection + m_lastAngularVelocity = m_angularMotorVelocity + vertattr + banking + deflection; if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) { @@ -948,8 +957,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_lastAngularVelocity -= m_lastAngularVelocity * decayamount; // Apply to the body - // Prim.ForceRotationalVelocity = m_lastAngularVelocity; - Prim.AddAngularForce(m_lastAngularVelocity, false); + // The above calculates the absolute angular velocity needed + Prim.ForceRotationalVelocity = m_lastAngularVelocity; VDetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", Prim.LocalID, decayamount, m_lastAngularVelocity); } //end MoveAngular -- cgit v1.1 From 7af28724acf12245977fc44576c36ec0de320a8a Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 26 Oct 2012 16:09:08 -0700 Subject: BulletSim: rename constraint classes so they show up together alphabetically. --- .../Physics/BulletSPlugin/BS6DofConstraint.cs | 154 --------------------- .../Physics/BulletSPlugin/BSConstraint6Dof.cs | 154 +++++++++++++++++++++ .../Physics/BulletSPlugin/BSConstraintHinge.cs | 57 ++++++++ .../Physics/BulletSPlugin/BSHingeConstraint.cs | 57 -------- .../Physics/BulletSPlugin/BSLinksetConstraints.cs | 2 +- 5 files changed, 212 insertions(+), 212 deletions(-) delete mode 100755 OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs create mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs create mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs delete mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs deleted file mode 100755 index ecb3ec8..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; -using OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ - -public sealed 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, - Vector3 frame2, Quaternion frame2rot, - bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) - { - m_world = world; - m_body1 = obj1; - m_body2 = obj2; - m_constraint = new BulletConstraint( - BulletSimAPI.Create6DofConstraint2(m_world.ptr, m_body1.ptr, m_body2.ptr, - frame1, frame1rot, - 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, - Vector3 joinPoint, - bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) - { - m_world = world; - m_body1 = obj1; - m_body2 = obj2; - if (obj1.ptr == IntPtr.Zero || obj2.ptr == IntPtr.Zero) - { - 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.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 - { - m_constraint = new BulletConstraint( - 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; - } - } - } - - public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot) - { - bool ret = false; - if (m_enabled) - { - BulletSimAPI.SetFrames2(m_constraint.ptr, frameA, frameArot, frameB, frameBrot); - ret = true; - } - return ret; - } - - public bool SetCFMAndERP(float cfm, float erp) - { - 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); - ret = true; - } - return ret; - } - - public bool UseFrameOffset(bool useOffset) - { - bool ret = false; - float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; - if (m_enabled) - ret = BulletSimAPI.UseFrameOffset2(m_constraint.ptr, onOff); - return ret; - } - - public bool TranslationalLimitMotor(bool enable, float targetVelocity, float maxMotorForce) - { - bool ret = false; - float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; - if (m_enabled) - { - ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.ptr, onOff, targetVelocity, maxMotorForce); - m_world.physicsScene.DetailLog("{0},BS6DOFConstraint,TransLimitMotor,enable={1},vel={2},maxForce={3}", - BSScene.DetailLogZero, enable, targetVelocity, maxMotorForce); - } - return ret; - } - - public bool SetBreakingImpulseThreshold(float threshold) - { - bool ret = false; - if (m_enabled) - ret = BulletSimAPI.SetBreakingImpulseThreshold2(m_constraint.ptr, threshold); - return ret; - } -} -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs new file mode 100755 index 0000000..3c37d76 --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs @@ -0,0 +1,154 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyrightD + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections.Generic; +using System.Text; +using OpenMetaverse; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ + +public sealed class BSConstraint6Dof : BSConstraint +{ + private static string LogHeader = "[BULLETSIM 6DOF CONSTRAINT]"; + + public override ConstraintType Type { get { return ConstraintType.D6_CONSTRAINT_TYPE; } } + + // Create a btGeneric6DofConstraint + public BSConstraint6Dof(BulletSim world, BulletBody obj1, BulletBody obj2, + Vector3 frame1, Quaternion frame1rot, + Vector3 frame2, Quaternion frame2rot, + bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) + { + m_world = world; + m_body1 = obj1; + m_body2 = obj2; + m_constraint = new BulletConstraint( + BulletSimAPI.Create6DofConstraint2(m_world.ptr, m_body1.ptr, m_body2.ptr, + frame1, frame1rot, + 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 BSConstraint6Dof(BulletSim world, BulletBody obj1, BulletBody obj2, + Vector3 joinPoint, + bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) + { + m_world = world; + m_body1 = obj1; + m_body2 = obj2; + if (obj1.ptr == IntPtr.Zero || obj2.ptr == IntPtr.Zero) + { + 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.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 + { + m_constraint = new BulletConstraint( + 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; + } + } + } + + public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot) + { + bool ret = false; + if (m_enabled) + { + BulletSimAPI.SetFrames2(m_constraint.ptr, frameA, frameArot, frameB, frameBrot); + ret = true; + } + return ret; + } + + public bool SetCFMAndERP(float cfm, float erp) + { + 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); + ret = true; + } + return ret; + } + + public bool UseFrameOffset(bool useOffset) + { + bool ret = false; + float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; + if (m_enabled) + ret = BulletSimAPI.UseFrameOffset2(m_constraint.ptr, onOff); + return ret; + } + + public bool TranslationalLimitMotor(bool enable, float targetVelocity, float maxMotorForce) + { + bool ret = false; + float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; + if (m_enabled) + { + ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.ptr, onOff, targetVelocity, maxMotorForce); + m_world.physicsScene.DetailLog("{0},BS6DOFConstraint,TransLimitMotor,enable={1},vel={2},maxForce={3}", + BSScene.DetailLogZero, enable, targetVelocity, maxMotorForce); + } + return ret; + } + + public bool SetBreakingImpulseThreshold(float threshold) + { + bool ret = false; + if (m_enabled) + ret = BulletSimAPI.SetBreakingImpulseThreshold2(m_constraint.ptr, threshold); + return ret; + } +} +} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs new file mode 100755 index 0000000..ed3ffa7 --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs @@ -0,0 +1,57 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyrightD + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections.Generic; +using System.Text; +using OpenMetaverse; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ + +public sealed class BSConstraintHinge : BSConstraint +{ + public override ConstraintType Type { get { return ConstraintType.HINGE_CONSTRAINT_TYPE; } } + + public BSConstraintHinge(BulletSim world, BulletBody obj1, BulletBody obj2, + Vector3 pivotInA, Vector3 pivotInB, + Vector3 axisInA, Vector3 axisInB, + bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) + { + m_world = world; + m_body1 = obj1; + m_body2 = obj2; + m_constraint = new BulletConstraint( + BulletSimAPI.CreateHingeConstraint2(m_world.ptr, m_body1.ptr, m_body2.ptr, + pivotInA, pivotInB, + axisInA, axisInB, + useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); + m_enabled = true; + } + +} + +} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs deleted file mode 100755 index 76bd930..0000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; -using OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ - -public sealed 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, - bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) - { - m_world = world; - m_body1 = obj1; - m_body2 = obj2; - m_constraint = new BulletConstraint( - BulletSimAPI.CreateHingeConstraint2(m_world.ptr, m_body1.ptr, m_body2.ptr, - pivotInA, pivotInB, - axisInA, axisInB, - useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); - m_enabled = true; - } - -} - -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs index 003c294..67979b3 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs @@ -246,7 +246,7 @@ public sealed class BSLinksetConstraints : BSLinkset // create a constraint that allows no freedom of movement between the two objects // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 - BS6DofConstraint constrain = new BS6DofConstraint( + BSConstraint6Dof constrain = new BSConstraint6Dof( PhysicsScene.World, rootPrim.BSBody, childPrim.BSBody, midPoint, true, true ); /* NOTE: below is an attempt to build constraint with full frame computation, etc. -- cgit v1.1 From e20bad12cc0584c6368e46e0f326e6b616133e8f Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 29 Oct 2012 11:30:47 -0700 Subject: BulletSim: centralize mass/inertia computation with UpdatePhysicalMassProperties() function. Didn't add setMassRaw because assignment with side effect is dirty. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 15 ++++++--- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 2 ++ OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 39 ++++++++++++++-------- 3 files changed, 38 insertions(+), 18 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 8bb4b21..b9013ab 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -155,8 +155,7 @@ public sealed class BSCharacter : BSPhysObject BulletSimAPI.SetCcdSweptSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); } - OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw); - BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); + UpdatePhysicalMassProperties(MassRaw); // Make so capsule does not fall over BulletSimAPI.SetAngularFactorV2(BSBody.ptr, OMV.Vector3.Zero); @@ -201,8 +200,7 @@ public sealed class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() { BulletSimAPI.SetLocalScaling2(BSShape.ptr, Scale); - OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw); - BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia); + UpdatePhysicalMassProperties(MassRaw); }); } @@ -329,7 +327,14 @@ public sealed class BSCharacter : BSPhysObject public override float Mass { get { return _mass; } } // used when we only want this prim's mass and not the linkset thing - public override float MassRaw { get {return _mass; } } + public override float MassRaw { + get {return _mass; } + } + public override void UpdatePhysicalMassProperties(float physMass) + { + OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, physMass); + BulletSimAPI.SetMassProps2(BSBody.ptr, physMass, localInertia); + } public override OMV.Vector3 Force { get { return _force; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 538f905..be8d64b 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -64,6 +64,8 @@ public abstract class BSPhysObject : PhysicsActor // Return the object mass without calculating it or having side effects public abstract float MassRaw { get; } + // Set the raw mass but also update physical mass properties (inertia, ...) + public abstract void UpdatePhysicalMassProperties(float mass); // Reference to the physical body (btCollisionObject) of this object public BulletBody BSBody; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 44937df..ad09a61 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -356,13 +356,32 @@ public sealed class BSPrim : BSPhysObject { get { - // return Linkset.LinksetMass; - return _mass; + return Linkset.LinksetMass; + // return _mass; } } // used when we only want this prim's mass and not the linkset thing - public override float MassRaw { get { return _mass; } } + public override float MassRaw { + get { return _mass; } + } + // Set the physical mass to the passed mass. + // Note that this does not change _mass! + public override void UpdatePhysicalMassProperties(float physMass) + { + if (IsStatic) + { + BulletSimAPI.SetMassProps2(BSBody.ptr, 0f, OMV.Vector3.Zero); + BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); + } + else + { + OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, physMass); + BulletSimAPI.SetMassProps2(BSBody.ptr, physMass, localInertia); + BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); + DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2}", LocalID, physMass, localInertia); + } + } // Is this used? public override OMV.Vector3 CenterOfMass @@ -613,7 +632,7 @@ public sealed class BSPrim : BSPhysObject // Recompute any linkset parameters. // When going from non-physical to physical, this re-enables the constraints that // had been automatically disabled when the mass was set to zero. - Linkset.Refresh(this, true); + Linkset.Refresh(this); DetailLog("{0},BSPrim.UpdatePhysicalParameters,exit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}", LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags, BSBody, BSShape); @@ -635,9 +654,7 @@ public sealed class BSPrim : BSPhysObject // Center of mass is at the center of the object BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.BSBody.ptr, _position, _orientation); // Mass is zero which disables a bunch of physics stuff in Bullet - BulletSimAPI.SetMassProps2(BSBody.ptr, 0f, OMV.Vector3.Zero); - // There is no inertia in a static object - BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); + UpdatePhysicalMassProperties(0f); // Set collision detection parameters if (PhysicsScene.Params.ccdMotionThreshold > 0f) { @@ -671,9 +688,7 @@ public sealed class BSPrim : BSPhysObject BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); // A dynamic object has mass - OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, Mass); - BulletSimAPI.SetMassProps2(BSBody.ptr, _mass, inertia); - BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); + UpdatePhysicalMassProperties(MassRaw); // Set collision detection parameters if (PhysicsScene.Params.ccdMotionThreshold > 0f) @@ -1247,9 +1262,7 @@ public sealed class BSPrim : BSPhysObject returnMass = _density * volume; - /* - * This change means each object keeps its own mass and the Mass property - * will return the sum if we're part of a linkset. + /* Comment out code that computes the mass of the linkset. That is done in the Linkset class. if (IsRootOfLinkset) { foreach (BSPrim prim in _childrenPrims) -- cgit v1.1 From 2f25f70316ff712d338bbff3f6d02650480a340b Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 29 Oct 2012 11:31:50 -0700 Subject: BulletSim: remove unneeded parameter from Refresh(). --- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index d0e514b..569d2e7 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -204,7 +204,7 @@ public abstract class BSLinkset // When physical properties are changed the linkset needs to recalculate // its internal properties. // May be called at runtime or taint-time (just pass the appropriate flag). - public abstract void Refresh(BSPhysObject requestor, bool inTaintTime); + public abstract void Refresh(BSPhysObject requestor); // The object is going dynamic (physical). Do any setup necessary // for a dynamic linkset. -- cgit v1.1 From 9568f24c2628312f366c99ce6beb5c193aace33c Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 29 Oct 2012 11:38:01 -0700 Subject: BulletSim: add post taint taints and post step taints. The post taints operation is most useful and is used by linksets to build and rebuild only once before the simulation step. --- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 138 +++++++++++++++++++++--- 1 file changed, 122 insertions(+), 16 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 9e95ce5..cb52937 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -171,7 +171,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters } } private Object _taintLock = new Object(); // lock for using the next object - private List _taintedObjects; + private List _taintOperations; + private Dictionary _postTaintOperations; + private List _postStepOperations; // A pointer to an instance if this structure is passed to the C++ code // Used to pass basic configuration values to the unmanaged code. @@ -203,7 +205,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters public override void Initialise(IMesher meshmerizer, IConfigSource config) { mesher = meshmerizer; - _taintedObjects = new List(); + _taintOperations = new List(); + _postTaintOperations = new Dictionary(); + _postStepOperations = new List(); PhysObjects = new Dictionary(); Shapes = new BSShapeCollection(this); @@ -475,23 +479,21 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters if (!m_initialized) return 5.0f; // update the prim states while we know the physics engine is not busy - int numTaints = _taintedObjects.Count; + int numTaints = _taintOperations.Count; ProcessTaints(); // Some of the prims operate with special vehicle properties ProcessVehicles(timeStep); - numTaints += _taintedObjects.Count; + numTaints += _taintOperations.Count; ProcessTaints(); // the vehicles might have added taints // step the physical world one interval m_simulationStep++; int numSubSteps = 0; - // DEBUG - // DetailLog("{0},BSScene.Simulate,beforeStep,ntaimts={1},step={2}", DetailLogZero, numTaints, m_simulationStep); - try { + // DumpVehicles(); // DEBUG if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount(); numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep, @@ -500,6 +502,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime); DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}", DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount); + // DumpVehicles(); // DEBUG } catch (Exception e) { @@ -579,6 +582,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters // Only enable this in a limited test world with few objects. // BulletSimAPI.DumpAllInfo2(World.ptr); // DEBUG DEBUG DEBUG + ProcessPostStepTaints(); + // The physics engine returns the number of milliseconds it simulated this call. // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. // We multiply by 55 to give a recognizable running rate (55 or less). @@ -670,6 +675,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters public override bool IsThreaded { get { return false; } } + #region Taints + // Calls to the PhysicsActors can't directly call into the physics engine // because it might be busy. We delay changes to a known time. // We rely on C#'s closure to save and restore the context for the delegate. @@ -679,7 +686,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters lock (_taintLock) { - _taintedObjects.Add(new TaintCallbackEntry(ident, callback)); + _taintOperations.Add(new TaintCallbackEntry(ident, callback)); } return; @@ -690,19 +697,25 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters // here just before the physics engine is called to step the simulation. public void ProcessTaints() { - if (_taintedObjects.Count > 0) // save allocating new list if there is nothing to process + ProcessRegularTaints(); + ProcessPostTaintTaints(); + } + + private void ProcessRegularTaints() + { + if (_taintOperations.Count > 0) // save allocating new list if there is nothing to process { int taintCount = m_taintsToProcessPerStep; TaintCallbackEntry oneCallback = new TaintCallbackEntry(); - while (_taintedObjects.Count > 0 && taintCount-- > 0) + while (_taintOperations.Count > 0 && taintCount-- > 0) { bool gotOne = false; lock (_taintLock) { - if (_taintedObjects.Count > 0) + if (_taintOperations.Count > 0) { - oneCallback = _taintedObjects[0]; - _taintedObjects.RemoveAt(0); + oneCallback = _taintOperations[0]; + _taintOperations.RemoveAt(0); gotOne = true; } } @@ -746,6 +759,89 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters } } + // Schedule an update to happen after all the regular taints are processed. + // Note that new requests for the same operation ("ident") for the same object ("ID") + // will replace any previous operation by the same object. + public void PostTaintObject(String ident, uint ID, TaintCallback callback) + { + if (!m_initialized) return; + + lock (_taintLock) + { + _postTaintOperations[ident] = new TaintCallbackEntry(ident + "-" + ID.ToString(), callback); + } + + return; + } + + private void ProcessPostTaintTaints() + { + if (_postTaintOperations.Count > 0) + { + Dictionary oldList; + lock (_taintLock) + { + oldList = _postTaintOperations; + _postTaintOperations = new Dictionary(); + } + + foreach (KeyValuePair kvp in oldList) + { + try + { + DetailLog("{0},BSScene.ProcessPostTaintTaints,doTaint,id={1}", DetailLogZero, kvp.Key); // DEBUG DEBUG DEBUG + kvp.Value.callback(); + } + catch (Exception e) + { + m_log.ErrorFormat("{0}: ProcessPostTaintTaints: {1}: Exception: {2}", LogHeader, kvp.Key, e); + } + } + oldList.Clear(); + } + } + + public void PostStepTaintObject(String ident, TaintCallback callback) + { + if (!m_initialized) return; + + lock (_taintLock) + { + _postStepOperations.Add(new TaintCallbackEntry(ident, callback)); + } + + return; + } + + private void ProcessPostStepTaints() + { + if (_postStepOperations.Count > 0) + { + List oldList; + lock (_taintLock) + { + oldList = _postStepOperations; + _postStepOperations = new List(); + } + + foreach (TaintCallbackEntry tcbe in oldList) + { + try + { + DetailLog("{0},BSScene.ProcessPostStepTaints,doTaint,id={1}", DetailLogZero, tcbe.ident); // DEBUG DEBUG DEBUG + tcbe.callback(); + } + catch (Exception e) + { + m_log.ErrorFormat("{0}: ProcessPostStepTaints: {1}: Exception: {2}", LogHeader, tcbe.ident, e); + } + } + oldList.Clear(); + } + } + + #endregion // Taints + #region Vehicles public void VehicleInSceneTypeChanged(BSPrim vehic, Vehicle newType) @@ -1006,7 +1102,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters (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,o,v) => { BulletSimAPI.SetCcdSweepSphereRadius2(o.BSBody.ptr, v); } ), + (s,o,v) => { BulletSimAPI.SetCcdSweptSphereRadius2(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); }, @@ -1128,12 +1224,12 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; }, (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ), new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1", - 0.001f, + 0.1f, (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].linkConstraintCFM; }, (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ), new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2", - 0.8f, + 0.1f, (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].linkConstraintERP; }, (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ), @@ -1326,6 +1422,16 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters #endregion Runtime settable parameters + // Debugging routine for dumping detailed physical information for vehicle prims + private void DumpVehicles() + { + foreach (BSPrim prim in m_vehicles) + { + BulletSimAPI.DumpRigidBody2(World.ptr, prim.BSBody.ptr); + BulletSimAPI.DumpCollisionShape2(World.ptr, prim.BSShape.ptr); + } + } + // Invoke the detailed logger and output something if it's enabled. public void DetailLog(string msg, params Object[] args) { -- cgit v1.1 From 8c9e4c1f7bdde47c9f29a9dfcf917421b943bb32 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 29 Oct 2012 11:41:25 -0700 Subject: BulletSim: Use Refresh/PostTaints to cause recomputing of constraint variables before the simulation step. Update logging and messages to properly name LinksetConstraints. Use UpdatePhysicalMassProperties to put the whole linkset mass into all the physical linkset members so they have the inertia to move the whole linkset. --- .../Physics/BulletSPlugin/BSLinksetConstraints.cs | 65 ++++++++++++---------- 1 file changed, 36 insertions(+), 29 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs index 67979b3..086aa12 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs @@ -43,23 +43,20 @@ public sealed class BSLinksetConstraints : BSLinkset // When physical properties are changed the linkset needs to recalculate // its internal properties. - // May be called at runtime or taint-time (just pass the appropriate flag). - public override void Refresh(BSPhysObject requestor, bool inTaintTime) + // This is queued in such a way that the + // refresh will only happen once after all the other taints are applied. + public override void Refresh(BSPhysObject requestor) { - // If there are no children or not root, I am not the one that recomputes the constraints - if (!HasAnyChildren || !IsRoot(requestor)) + // If there are no children, there are no constraints to recompute. + if (!HasAnyChildren) return; - BSScene.TaintCallback refreshOperation = delegate() + // Queue to happen after all the other taint processing + PhysicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate() { RecomputeLinksetConstraintVariables(); - DetailLog("{0},BSLinkset.Refresh,complete,rBody={1}", - LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); - }; - if (inTaintTime) - refreshOperation(); - else - PhysicsScene.TaintedObject("BSLinkSet.Refresh", refreshOperation); + }); + } // The object is going dynamic (physical). Do any setup necessary @@ -104,14 +101,14 @@ public sealed class BSLinksetConstraints : BSLinkset if (IsRoot(child)) { // If the one with the dependency is root, must undo all children - DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", + DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", child.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot); } else { - DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeSingleChild,rID={1},rBody={2},cID={3},cBody={4}", + DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeSingleChild,rID={1},rBody={2},cID={3},cBody={4}", child.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), child.LocalID, child.BSBody.ptr.ToString("X")); @@ -132,7 +129,7 @@ public sealed class BSLinksetConstraints : BSLinkset { if (IsRoot(child)) { - DetailLog("{0},BSLinkset.RestoreBodyDependencies,restoreChildrenForRoot,rID={1},numChild={2}", + DetailLog("{0},BSLinksetConstraint.RestoreBodyDependencies,restoreChildrenForRoot,rID={1},numChild={2}", child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count); foreach (BSPhysObject bpo in m_taintChildren) { @@ -141,7 +138,7 @@ public sealed class BSLinksetConstraints : BSLinkset } else { - DetailLog("{0},BSLinkset.RestoreBodyDependencies,restoreSingleChild,rID={1},rBody={2},cID={3},cBody={4}", + DetailLog("{0},BSLinksetConstraint.RestoreBodyDependencies,restoreSingleChild,rID={1},rBody={2},cID={3},cBody={4}", LinksetRoot.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), child.LocalID, child.BSBody.ptr.ToString("X")); @@ -178,6 +175,7 @@ public sealed class BSLinksetConstraints : BSLinkset PhysicallyLinkAChildToRoot(rootx, childx); m_taintChildren.Add(child); }); + Refresh(LinksetRoot); } return; } @@ -211,9 +209,9 @@ public sealed class BSLinksetConstraints : BSLinkset { m_taintChildren.Remove(child); PhysicallyUnlinkAChildFromRoot(rootx, childx); - RecomputeLinksetConstraintVariables(); }); - + // See that the linkset parameters are recomputed at the end of the taint time. + Refresh(LinksetRoot); } else { @@ -237,7 +235,7 @@ public sealed class BSLinksetConstraints : BSLinkset // real world coordinate of midpoint between the two objects OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); - DetailLog("{0},BSLinkset.PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", + DetailLog("{0},BSLinksetConstraint.PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", rootPrim.LocalID, rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"), childPrim.LocalID, childPrim.BSBody.ptr.ToString("X"), @@ -248,6 +246,7 @@ public sealed class BSLinksetConstraints : BSLinkset BSConstraint6Dof constrain = new BSConstraint6Dof( PhysicsScene.World, rootPrim.BSBody, childPrim.BSBody, midPoint, true, true ); + // PhysicsScene.World, childPrim.BSBody, rootPrim.BSBody, midPoint, 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 @@ -264,7 +263,7 @@ public sealed class BSLinksetConstraints : BSLinkset // create a constraint that allows no freedom of movement between the two objects // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 - DetailLog("{0},BSLinkset.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); + DetailLog("{0},BSLinksetConstraint.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); BS6DofConstraint constrain = new BS6DofConstraint( PhysicsScene.World, rootPrim.Body, childPrim.Body, OMV.Vector3.Zero, @@ -307,7 +306,7 @@ public sealed class BSLinksetConstraints : BSLinkset private bool PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim) { bool ret = false; - DetailLog("{0},BSLinkset.PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}", + DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}", rootPrim.LocalID, rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"), childPrim.LocalID, childPrim.BSBody.ptr.ToString("X")); @@ -327,7 +326,7 @@ public sealed class BSLinksetConstraints : BSLinkset // Called at taint time! private bool PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim) { - DetailLog("{0},BSLinkset.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); + DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); bool ret = false; if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody)) @@ -350,7 +349,7 @@ public sealed class BSLinksetConstraints : BSLinkset BSConstraint constrain; if (PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.BSBody, child.BSBody, out constrain)) { - // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}", + // DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}", // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID); constrain.RecomputeConstraintVariables(linksetMass); } @@ -367,15 +366,23 @@ public sealed class BSLinksetConstraints : BSLinkset { // If this is a multiple object linkset, set everybody's center of mass to the set's center of mass OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); - BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, - centerOfMass, OMV.Quaternion.Identity); - DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,setCenterOfMass,COM={1},rBody={2}", - LinksetRoot.LocalID, centerOfMass, LinksetRoot.BSBody.ptr.ToString("X")); + BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); + // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, + // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); + DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraintVariables,setCenterOfMass,COM={1},rBody={2},linksetMass={3}", + LinksetRoot.LocalID, centerOfMass, LinksetRoot.BSBody.ptr.ToString("X"), linksetMass); foreach (BSPhysObject child in m_taintChildren) { - BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, - centerOfMass, OMV.Quaternion.Identity); + BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); + // A child in the linkset physically shows the mass of the whole linkset. + // This allows Bullet to apply enough force on the child to move the whole linkset. + child.UpdatePhysicalMassProperties(linksetMass); + // DEBUG: see of inter-linkset collisions are causing problems + // BulletSimAPI.SetCollisionFilterMask2(child.BSBody.ptr, + // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); } + // Also update the root's physical mass to the whole linkset + LinksetRoot.UpdatePhysicalMassProperties(linksetMass); // BulletSimAPI.DumpAllInfo2(PhysicsScene.World.ptr); // DEBUG DEBUG DEBUG } -- cgit v1.1 From bc43c7007d3d8ffc2f497a6d37004eb3d3544e00 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 29 Oct 2012 14:27:48 -0700 Subject: BulletSim: code rearrangement --- OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs | 12 ++++++------ .../Region/Physics/BulletSPlugin/BSConstraintCollection.cs | 2 -- 2 files changed, 6 insertions(+), 8 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs index f017cdd..65fac00 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs @@ -42,6 +42,12 @@ public abstract class BSConstraint : IDisposable protected BulletConstraint m_constraint; protected bool m_enabled = false; + 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 bool IsEnabled { get { return m_enabled; } } + public BSConstraint() { } @@ -64,12 +70,6 @@ public abstract class BSConstraint : IDisposable } } - 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; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs index b9add06..a9fd826 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs @@ -143,8 +143,6 @@ public sealed class BSConstraintCollection : IDisposable // Return 'true' if any constraints were destroyed. public bool RemoveAndDestroyConstraint(BulletBody body1) { - // return BulletSimAPI.RemoveConstraintByID(m_world.ID, obj.ID); - List toRemove = new List(); uint lookingID = body1.ID; lock (m_constraints) -- cgit v1.1 From 4cfa3be4efbca49e4670b92ec2c110f65f658b8e Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 29 Oct 2012 14:28:24 -0700 Subject: BulletSim: add definitions for linkset collision mask --- OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index be3a5ad..9b7ba03 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -378,6 +378,7 @@ public enum CollisionFilterGroups : uint BTerrainFilter = 1 << 11, BRaycastFilter = 1 << 12, BSolidFilter = 1 << 13, + BLinksetFilter = 1 << 14, // The collsion filters and masked are defined in one place -- don't want them scattered AvatarFilter = BCharacterFilter, @@ -386,6 +387,8 @@ public enum CollisionFilterGroups : uint ObjectMask = BAllFilter, StaticObjectFilter = BStaticFilter, StaticObjectMask = BAllFilter, + LinksetFilter = BLinksetFilter, + LinksetMask = BAllFilter & ~BLinksetFilter, VolumeDetectFilter = BSensorTrigger, VolumeDetectMask = ~BSensorTrigger, TerrainFilter = BTerrainFilter, -- cgit v1.1 From dae038a117c3110970d6fe0b743e20f342df2269 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 29 Oct 2012 14:30:16 -0700 Subject: BulletSim: fix problem with multiple linksets stepping on each other if they are built at the same time. --- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index cb52937..c27b5f0 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -578,12 +578,12 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters } } + ProcessPostStepTaints(); + // This 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. // BulletSimAPI.DumpAllInfo2(World.ptr); // DEBUG DEBUG DEBUG - ProcessPostStepTaints(); - // The physics engine returns the number of milliseconds it simulated this call. // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. // We multiply by 55 to give a recognizable running rate (55 or less). @@ -766,9 +766,10 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters { if (!m_initialized) return; + string uniqueIdent = ident + "-" + ID.ToString(); lock (_taintLock) { - _postTaintOperations[ident] = new TaintCallbackEntry(ident + "-" + ID.ToString(), callback); + _postTaintOperations[uniqueIdent] = new TaintCallbackEntry(uniqueIdent, callback); } return; -- cgit v1.1 From 42d65840c843f2cac6f02fc1b6012140c9cb240e Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 29 Oct 2012 14:32:07 -0700 Subject: BulletSim: Add gravity force to vehicle. Some debugging additions. --- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 8bd8117..4981007 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -539,6 +539,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin { if (!IsActive) return; + m_lastAngularVelocity = Prim.ForceRotationalVelocity; // DEBUG: account for what Bullet did last time + MoveLinear(pTimestep); MoveAngular(pTimestep); LimitRotation(pTimestep); @@ -558,7 +560,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin Prim.ForceOrientation = newOrientation; } */ - BulletSimAPI.SetInterpolationVelocity2(Prim.BSBody.ptr, m_newVelocity, m_lastAngularVelocity); + // DEBUG: Trying to figure out why Bullet goes crazy when the root prim is moved. + BulletSimAPI.SetInterpolationVelocity2(Prim.BSBody.ptr, m_newVelocity, m_lastAngularVelocity); // DEBUG DEBUG DEBUG // remember the position so next step we can limit absolute movement effects m_lastPositionVector = Prim.ForcePosition; @@ -762,13 +765,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin // Apply velocity Prim.ForceVelocity = m_newVelocity; // Prim.AddForce(m_newVelocity * Prim.Linkset.LinksetMass, false); - // Prim.AddForce(grav * Prim.Linkset.LinksetMass, false); + Prim.AddForce(grav * Prim.Linkset.LinksetMass, false); VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},grav={4}", Prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity, grav); } // end MoveLinear() + // ======================================================================= // Apply the effect of the angular motor. private void MoveAngular(float pTimestep) { -- cgit v1.1 From 93fe384cce42e91337f446fd658ef29ca3d9f733 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Mon, 29 Oct 2012 14:33:31 -0700 Subject: BulletSim: Use the PostTaints operation to build the linkset once before the next simulation step. This eliminates the management of children vs taintChildren and simplifies the constratin creation code. --- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 52 +++----- .../Physics/BulletSPlugin/BSLinksetConstraints.cs | 140 +++++++-------------- 2 files changed, 68 insertions(+), 124 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 569d2e7..187951e 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -61,16 +61,7 @@ public abstract class BSLinkset public int LinksetID { get; private set; } // The children under the root in this linkset. - // There are two lists of children: the current children at runtime - // and the children at taint-time. For instance, if you delink a - // child from the linkset, the child is removed from m_children - // but the constraint won't be removed until taint time. - // Two lists lets this track the 'current' children and - // the physical 'taint' children separately. - // After taint processing and before the simulation step, these - // two lists must be the same. protected HashSet m_children; - protected HashSet m_taintChildren; // We lock the diddling of linkset classes to prevent any badness. // This locks the modification of the instances of this class. Changes @@ -110,7 +101,6 @@ public abstract class BSLinkset PhysicsScene = scene; LinksetRoot = parent; m_children = new HashSet(); - m_taintChildren = new HashSet(); m_mass = parent.MassRaw; } @@ -192,7 +182,7 @@ public abstract class BSLinkset lock (m_linksetActivityLock) { action(LinksetRoot); - foreach (BSPhysObject po in m_taintChildren) + foreach (BSPhysObject po in m_children) { if (action(po)) break; @@ -201,9 +191,24 @@ public abstract class BSLinkset return ret; } + // 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); + + // Forcefully removing a child from a linkset. + // This is not being called by the child so we have to make sure the child doesn't think + // it's still connected to the linkset. + // Normal OpenSimulator operation will never do this because other SceneObjectPart information + // also has to be updated (like pointer to prim's parent). + protected abstract void RemoveChildFromOtherLinkset(BSPhysObject pchild); + + // 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); + // When physical properties are changed the linkset needs to recalculate // its internal properties. - // May be called at runtime or taint-time (just pass the appropriate flag). + // May be called at runtime or taint-time. public abstract void Refresh(BSPhysObject requestor); // The object is going dynamic (physical). Do any setup necessary @@ -238,8 +243,6 @@ public abstract class BSLinkset public abstract void RestoreBodyDependencies(BSPrim child); // ================================================================ - // Below this point is internal magic - protected virtual float ComputeLinksetMass() { float mass = LinksetRoot.MassRaw; @@ -264,7 +267,7 @@ public abstract class BSLinkset com = LinksetRoot.Position * LinksetRoot.MassRaw; float totalMass = LinksetRoot.MassRaw; - foreach (BSPhysObject bp in m_taintChildren) + foreach (BSPhysObject bp in m_children) { com += bp.Position * bp.MassRaw; totalMass += bp.MassRaw; @@ -283,31 +286,16 @@ public abstract class BSLinkset { com = LinksetRoot.Position; - foreach (BSPhysObject bp in m_taintChildren) + foreach (BSPhysObject bp in m_children) { com += bp.Position * bp.MassRaw; } - com /= (m_taintChildren.Count + 1); + com /= (m_children.Count + 1); } return com; } - // 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); - - // Forcefully removing a child from a linkset. - // This is not being called by the child so we have to make sure the child doesn't think - // it's still connected to the linkset. - // Normal OpenSimulator operation will never do this because other SceneObjectPart information - // also has to be updated (like pointer to prim's parent). - protected abstract void RemoveChildFromOtherLinkset(BSPhysObject pchild); - - // 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); - // Invoke the detailed logger and output something if it's enabled. protected void DetailLog(string msg, params Object[] args) { diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs index 086aa12..6c1fa2a 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs @@ -54,7 +54,7 @@ public sealed class BSLinksetConstraints : BSLinkset // Queue to happen after all the other taint processing PhysicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate() { - RecomputeLinksetConstraintVariables(); + RecomputeLinksetConstraints(); }); } @@ -98,24 +98,13 @@ public sealed class BSLinksetConstraints : BSLinkset lock (m_linksetActivityLock) { - if (IsRoot(child)) - { - // If the one with the dependency is root, must undo all children - DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", - child.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); + // Just undo all the constraints for this linkset. Rebuild at the end of the step. + DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", + child.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); - ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot); - } - else - { - DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeSingleChild,rID={1},rBody={2},cID={3},cBody={4}", - child.LocalID, - LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), - child.LocalID, child.BSBody.ptr.ToString("X")); - // ret = PhysicallyUnlinkAChildFromRoot(LinksetRoot, child); - // Despite the function name, this removes any link to the specified object. - ret = PhysicallyUnlinkAllChildrenFromRoot(child); - } + ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot); + // Cause the constraints, et al to be rebuilt before the next simulation step. + Refresh(LinksetRoot); } return ret; } @@ -125,26 +114,7 @@ public sealed class BSLinksetConstraints : BSLinkset // Called at taint-time!! public override void RestoreBodyDependencies(BSPrim child) { - lock (m_linksetActivityLock) - { - if (IsRoot(child)) - { - DetailLog("{0},BSLinksetConstraint.RestoreBodyDependencies,restoreChildrenForRoot,rID={1},numChild={2}", - child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count); - foreach (BSPhysObject bpo in m_taintChildren) - { - PhysicallyLinkAChildToRoot(LinksetRoot, bpo); - } - } - else - { - DetailLog("{0},BSLinksetConstraint.RestoreBodyDependencies,restoreSingleChild,rID={1},rBody={2},cID={3},cBody={4}", - LinksetRoot.LocalID, - LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), - child.LocalID, child.BSBody.ptr.ToString("X")); - PhysicallyLinkAChildToRoot(LinksetRoot, child); - } - } + // The Refresh operation will build any missing constraints. } // ================================================================ @@ -163,18 +133,7 @@ public sealed class BSLinksetConstraints : BSLinkset DetailLog("{0},AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); - PhysicsScene.TaintedObject("AddChildToLinkset", delegate() - { - DetailLog("{0},AddChildToLinkset,taint,rID={1},rBody={2},cID={3},cBody={4}", - rootx.LocalID, - rootx.LocalID, rootx.BSBody.ptr.ToString("X"), - childx.LocalID, childx.BSBody.ptr.ToString("X")); - // Since this is taint-time, the body and shape could have changed for the child - rootx.ForcePosition = rootx.Position; // DEBUG - childx.ForcePosition = childx.Position; // DEBUG - PhysicallyLinkAChildToRoot(rootx, childx); - m_taintChildren.Add(child); - }); + // Cause constraints and assorted properties to be recomputed before the next simulation step. Refresh(LinksetRoot); } return; @@ -207,7 +166,6 @@ public sealed class BSLinksetConstraints : BSLinkset PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate() { - m_taintChildren.Remove(child); PhysicallyUnlinkAChildFromRoot(rootx, childx); }); // See that the linkset parameters are recomputed at the end of the taint time. @@ -225,6 +183,12 @@ public sealed class BSLinksetConstraints : BSLinkset // Called at taint time! private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim) { + // Don't build the constraint when asked. Put it off until just before the simulation step. + Refresh(rootPrim); + } + + private BSConstraint BuildConstraint(BSPhysObject rootPrim, BSPhysObject childPrim) + { // Zero motion for children so they don't interpolate childPrim.ZeroMotion(); @@ -235,7 +199,7 @@ public sealed class BSLinksetConstraints : BSLinkset // real world coordinate of midpoint between the two objects OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); - DetailLog("{0},BSLinksetConstraint.PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", + DetailLog("{0},BSLinksetConstraint.BuildConstraint,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", rootPrim.LocalID, rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"), childPrim.LocalID, childPrim.BSBody.ptr.ToString("X"), @@ -297,6 +261,7 @@ public sealed class BSLinksetConstraints : BSLinkset { constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations); } + return constrain; } // Remove linkage between myself and a particular child @@ -337,56 +302,47 @@ public sealed class BSLinksetConstraints : BSLinkset } // 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 - // geometry. + // various transforms and variables. Create constraints of not created yet. + // Called before the simulation step to make sure the constraint based linkset + // is all initialized. // Must only be called at taint time!! - private void RecomputeLinksetConstraintVariables() + private void RecomputeLinksetConstraints() { float linksetMass = LinksetMass; - foreach (BSPhysObject child in m_taintChildren) + LinksetRoot.UpdatePhysicalMassProperties(linksetMass); + + // For a multiple object linkset, set everybody's center of mass to the set's center of mass + OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); + BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); + + // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, + // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); + DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraints,setCenterOfMass,COM={1},rBody={2},linksetMass={3}", + LinksetRoot.LocalID, centerOfMass, LinksetRoot.BSBody.ptr.ToString("X"), linksetMass); + + foreach (BSPhysObject child in m_children) { + // A child in the linkset physically shows the mass of the whole linkset. + // This allows Bullet to apply enough force on the child to move the whole linkset. + // (Also do the mass stuff before recomputing the constraint so mass is not zero.) + BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); + child.UpdatePhysicalMassProperties(linksetMass); + BSConstraint constrain; - if (PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.BSBody, child.BSBody, out constrain)) - { - // DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}", - // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID); - constrain.RecomputeConstraintVariables(linksetMass); - } - else + if (!PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.BSBody, child.BSBody, out constrain)) { - // Non-fatal error that happens when children are being added to the linkset but - // their constraints have not been created yet. - break; + // If constraint doesn't exist yet, create it. + constrain = BuildConstraint(LinksetRoot, child); } - } + constrain.RecomputeConstraintVariables(linksetMass); - // If the whole linkset is not here, doesn't make sense to recompute linkset wide values - if (m_children.Count == m_taintChildren.Count) - { - // If this is a multiple object linkset, set everybody's center of mass to the set's center of mass - OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); - BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); - // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, - // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); - DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraintVariables,setCenterOfMass,COM={1},rBody={2},linksetMass={3}", - LinksetRoot.LocalID, centerOfMass, LinksetRoot.BSBody.ptr.ToString("X"), linksetMass); - foreach (BSPhysObject child in m_taintChildren) - { - BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); - // A child in the linkset physically shows the mass of the whole linkset. - // This allows Bullet to apply enough force on the child to move the whole linkset. - child.UpdatePhysicalMassProperties(linksetMass); - // DEBUG: see of inter-linkset collisions are causing problems - // BulletSimAPI.SetCollisionFilterMask2(child.BSBody.ptr, - // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); - } - // Also update the root's physical mass to the whole linkset - LinksetRoot.UpdatePhysicalMassProperties(linksetMass); + // DEBUG: see of inter-linkset collisions are causing problems + // BulletSimAPI.SetCollisionFilterMask2(child.BSBody.ptr, + // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); - // BulletSimAPI.DumpAllInfo2(PhysicsScene.World.ptr); // DEBUG DEBUG DEBUG + // BulletSimAPI.DumpConstraint2(PhysicsScene.World.ptr, constrain.Constraint.ptr); // DEBUG DEBUG } - return; + } } } -- cgit v1.1 From 52be581f71b3c8da6113e4f4b193694683e6f8cc Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 30 Oct 2012 09:12:07 -0700 Subject: BulletSim: remove center-of-mass setting for linksets because it causes the constraint calculation to pull the objects together. --- .../Physics/BulletSPlugin/BSConstraint6Dof.cs | 3 +- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 1 - .../Physics/BulletSPlugin/BSLinksetConstraints.cs | 79 ++++++++-------------- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 2 +- .../Physics/BulletSPlugin/BSShapeCollection.cs | 2 +- 5 files changed, 33 insertions(+), 54 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs index 3c37d76..23ef052 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs @@ -71,8 +71,7 @@ public sealed class BSConstraint6Dof : BSConstraint BSScene.DetailLogZero, world.worldID, obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); 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")); + LogHeader, world.worldID, obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); m_enabled = false; } else diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 187951e..6d84fcc 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -132,7 +132,6 @@ public abstract class BSLinkset // Cannot remove the root from a linkset. return this; } - RemoveChildFromLinkset(child); } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs index 6c1fa2a..ecb6ad4 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs @@ -43,20 +43,16 @@ public sealed class BSLinksetConstraints : BSLinkset // When physical properties are changed the linkset needs to recalculate // its internal properties. - // This is queued in such a way that the - // refresh will only happen once after all the other taints are applied. + // 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) { - // If there are no children, there are no constraints to recompute. - if (!HasAnyChildren) - return; - // Queue to happen after all the other taint processing PhysicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate() { - RecomputeLinksetConstraints(); + if (HasAnyChildren && IsRoot(requestor)) + RecomputeLinksetConstraints(); }); - } // The object is going dynamic (physical). Do any setup necessary @@ -71,9 +67,10 @@ public sealed class BSLinksetConstraints : BSLinkset return false; } - // The object is going static (non-physical). Do any setup necessary - // for a static linkset. + // 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. + // This doesn't normally happen -- OpenSim removes the objects from the physical + // world if it is a static linkset. // Called at taint-time! public override bool MakeStatic(BSPhysObject child) { @@ -87,21 +84,21 @@ public sealed class BSLinksetConstraints : BSLinkset // Nothing to do for constraints on property updates } - // 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. - // Returns 'true' of something eas actually removed and would need restoring + // Routine called when rebuilding the body of some member of the linkset. + // Destroy all the constraints have have been made to root and set + // up to rebuild the constraints before the next simulation step. + // Returns 'true' of something was actually removed and would need restoring // Called at taint-time!! public override bool RemoveBodyDependencies(BSPrim child) { bool ret = false; + DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", + child.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); + lock (m_linksetActivityLock) { // Just undo all the constraints for this linkset. Rebuild at the end of the step. - DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", - child.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); - ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot); // Cause the constraints, et al to be rebuilt before the next simulation step. Refresh(LinksetRoot); @@ -114,13 +111,12 @@ public sealed class BSLinksetConstraints : BSLinkset // Called at taint-time!! public override void RestoreBodyDependencies(BSPrim child) { - // The Refresh operation will build any missing constraints. + // The Refresh operation queued by RemoveBodyDependencies() will build any missing constraints. } // ================================================================ - // Below this point is internal magic - // I am the root of a linkset and a new child is being added + // Add a new child to the linkset. // Called while LinkActivity is locked. protected override void AddChildToLinkset(BSPhysObject child) { @@ -131,7 +127,7 @@ public sealed class BSLinksetConstraints : BSLinkset BSPhysObject rootx = LinksetRoot; // capture the root as of now BSPhysObject childx = child; - DetailLog("{0},AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); + DetailLog("{0},BSLinksetConstraints.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); // Cause constraints and assorted properties to be recomputed before the next simulation step. Refresh(LinksetRoot); @@ -150,7 +146,7 @@ public sealed class BSLinksetConstraints : BSLinkset RemoveChildFromLinkset(pchild); } - // I am the root of a linkset and one of my children is being removed. + // Remove the specified child from the linkset. // Safe to call even if the child is not really in my linkset. protected override void RemoveChildFromLinkset(BSPhysObject child) { @@ -159,12 +155,12 @@ public sealed class BSLinksetConstraints : BSLinkset BSPhysObject rootx = LinksetRoot; // capture the root and body as of now BSPhysObject childx = child; - DetailLog("{0},RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", + DetailLog("{0},BSLinksetConstraints.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", childx.LocalID, rootx.LocalID, rootx.BSBody.ptr.ToString("X"), childx.LocalID, childx.BSBody.ptr.ToString("X")); - PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate() + PhysicsScene.TaintedObject("BSLinksetConstraints.RemoveChildFromLinkset", delegate() { PhysicallyUnlinkAChildFromRoot(rootx, childx); }); @@ -173,7 +169,7 @@ public sealed class BSLinksetConstraints : BSLinkset } else { - // This will happen if we remove the root of the linkset first. Non-fatal occurance. + // Non-fatal occurance. // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader); } return; @@ -215,7 +211,7 @@ public sealed class BSLinksetConstraints : BSLinkset /* 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. - * Code left as a warning to future programmers. + * Code left for future programmers. // ================================================================================== // relative position normalized to the root prim OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation); @@ -225,8 +221,6 @@ public sealed class BSLinksetConstraints : BSLinkset OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation; OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation); - // create a constraint that allows no freedom of movement between the two objects - // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 DetailLog("{0},BSLinksetConstraint.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); BS6DofConstraint constrain = new BS6DofConstraint( PhysicsScene.World, rootPrim.Body, childPrim.Body, @@ -234,11 +228,6 @@ public sealed class BSLinksetConstraints : BSLinkset OMV.Quaternion.Inverse(rootPrim.Orientation), OMV.Vector3.Zero, OMV.Quaternion.Inverse(childPrim.Orientation), - // A point half way between the parent and child - // childRelativePosition/2, - // childRelativeRotation, - // childRelativePosition/2, - // inverseChildRelativeRotation, true, true ); @@ -264,9 +253,9 @@ public sealed class BSLinksetConstraints : BSLinkset return constrain; } - // Remove linkage between myself and a particular child + // Remove linkage between the linkset root and a particular child // The root and child bodies are passed in because we need to remove the constraint between - // the bodies that were at unlink time. + // the bodies that were present at unlink time. // Called at taint time! private bool PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim) { @@ -288,44 +277,36 @@ public sealed class BSLinksetConstraints : BSLinkset } // Remove linkage between myself and any possible children I might have. + // Returns 'true' of any constraints were destroyed. // Called at taint time! private bool PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim) { DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); - bool ret = false; - if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody)) - { - ret = true; - } - return ret; + return PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody); } // Call each of the constraints that make up this linkset and recompute the // various transforms and variables. Create constraints of not created yet. // Called before the simulation step to make sure the constraint based linkset // is all initialized. - // Must only be called at taint time!! + // Called at taint time!! private void RecomputeLinksetConstraints() { float linksetMass = LinksetMass; LinksetRoot.UpdatePhysicalMassProperties(linksetMass); - // For a multiple object linkset, set everybody's center of mass to the set's center of mass - OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass(); - BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); - + // DEBUG: see of inter-linkset collisions are causing problems // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); - DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraints,setCenterOfMass,COM={1},rBody={2},linksetMass={3}", - LinksetRoot.LocalID, centerOfMass, LinksetRoot.BSBody.ptr.ToString("X"), linksetMass); + DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraints,setCenterOfMass,rBody={1},linksetMass={2}", + LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), linksetMass); foreach (BSPhysObject child in m_children) { // A child in the linkset physically shows the mass of the whole linkset. // This allows Bullet to apply enough force on the child to move the whole linkset. // (Also do the mass stuff before recomputing the constraint so mass is not zero.) - BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr, centerOfMass, OMV.Quaternion.Identity); child.UpdatePhysicalMassProperties(linksetMass); BSConstraint constrain; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index ad09a61..7851a40 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -634,7 +634,7 @@ public sealed class BSPrim : BSPhysObject // had been automatically disabled when the mass was set to zero. Linkset.Refresh(this); - DetailLog("{0},BSPrim.UpdatePhysicalParameters,exit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}", + DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}", LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags, BSBody, BSShape); } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 1c0e6f5..1219fc0 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -109,7 +109,7 @@ public sealed class BSShapeCollection : IDisposable prim.BSShape, shapeData, bodyCallback); ret = newGeom || newBody; } - DetailLog("{0},BSShapeCollection.GetBodyAndShape,force={1},ret={2},body={3},shape={4}", + DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}", prim.LocalID, forceRebuild, ret, prim.BSBody, prim.BSShape); return ret; -- cgit v1.1 From 28e2cd3fa21835b124552dec024745f5784f6b3a Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 31 Oct 2012 09:26:58 -0700 Subject: BulletSim: vehicle tweeking. Add AddTorque() method to BSPrim. Remove some manual motor actions in computing angular force (will eventually be replaced with motor class). Remove some experimental changes. --- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 136 ++++++++------------- .../Physics/BulletSPlugin/BSLinksetConstraints.cs | 2 +- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 45 +++++-- 3 files changed, 90 insertions(+), 93 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 4981007..5c61774 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -511,21 +511,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin // Do any updating needed for a vehicle public void Refresh() { - /* - * Doesnt work unless BSDynamics senses and corrects for all collisions - if (IsActive) - BulletSimAPI.AddToCollisionFlags2(Prim.BSBody.ptr, CollisionFlags.CF_KINEMATIC_OBJECT); - else - BulletSimAPI.RemoveFromCollisionFlags2(Prim.BSBody.ptr, CollisionFlags.CF_KINEMATIC_OBJECT); - */ - /* - * Doesn't work because with zero inertia, Bullet will not apply any forces to the object. - if (IsActive) - { - BulletSimAPI.SetMassProps2(Prim.BSBody.ptr, Prim.MassRaw, Vector3.Zero); - BulletSimAPI.UpdateInertiaTensor2(Prim.BSBody.ptr); - } - */ if (IsActive) { // Friction effects are handled by this vehicle code @@ -539,29 +524,21 @@ namespace OpenSim.Region.Physics.BulletSPlugin { if (!IsActive) return; - m_lastAngularVelocity = Prim.ForceRotationalVelocity; // DEBUG: account for what Bullet did last time + // DEBUG + // Because Bullet does apply forces to the vehicle, our last computed + // linear and angular velocities are not what is happening now. + // Vector3 externalAngularVelocity = Prim.ForceRotationalVelocity - m_lastAngularVelocity; + // m_lastAngularVelocity += (externalAngularVelocity * 0.5f) * pTimestep; + // m_lastAngularVelocity = Prim.ForceRotationalVelocity; // DEBUG: account for what Bullet did last time + // m_lastLinearVelocityVector = Prim.ForceVelocity * Quaternion.Inverse(Prim.ForceOrientation); // DEBUG: + // END DEBUG MoveLinear(pTimestep); MoveAngular(pTimestep); LimitRotation(pTimestep); - /* Experimental - // Wonder if Bullet could handle collision penetration while this applies the forces. - // Apply the computed forces on the vehicle - Prim.ForcePosition += Prim.ForceVelocity * Prim.MassRaw * pTimestep; - - if (Prim.ForceRotationalVelocity != Vector3.Zero) - { - Quaternion newOrientation = Prim.ForceOrientation; - newOrientation.Normalize(); - Quaternion appliedRotation = new Quaternion((Prim.ForceRotationalVelocity * pTimestep), 0f); - newOrientation += (appliedRotation * newOrientation) * 0.5f; - newOrientation.Normalize(); - Prim.ForceOrientation = newOrientation; - } - */ // DEBUG: Trying to figure out why Bullet goes crazy when the root prim is moved. - BulletSimAPI.SetInterpolationVelocity2(Prim.BSBody.ptr, m_newVelocity, m_lastAngularVelocity); // DEBUG DEBUG DEBUG + // BulletSimAPI.SetInterpolationVelocity2(Prim.BSBody.ptr, m_newVelocity, m_lastAngularVelocity); // DEBUG DEBUG DEBUG // remember the position so next step we can limit absolute movement effects m_lastPositionVector = Prim.ForcePosition; @@ -583,7 +560,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin Vector3 vehicleVelocity = Prim.ForceVelocity * Quaternion.Inverse(Prim.ForceOrientation); // DEBUG // add drive to body - Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/(m_linearMotorTimescale / pTimestep); + Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/(m_linearMotorTimescale) * pTimestep; // lastLinearVelocityVector is the current body velocity vector m_lastLinearVelocityVector += addAmount; @@ -593,11 +570,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin Vector3 frictionFactor = (Vector3.One / m_linearFrictionTimescale) * pTimestep; m_lastLinearVelocityVector *= (Vector3.One - frictionFactor); - VDetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},vehVel={3},add={4},decay={5},lmDir={6},lmVel={7}", - Prim.LocalID, origDir, origVel, vehicleVelocity, addAmount, decayFactor, m_linearMotorDirection, m_lastLinearVelocityVector); - - // convert requested object velocity to object relative vector + // Rotate new object velocity from vehicle relative to world coordinates m_newVelocity = m_lastLinearVelocityVector * Prim.ForceOrientation; + + VDetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},vehVel={3},add={4},decay={5},frict={6},lmDir={7},lmVel={8},newVel={9}", + Prim.LocalID, origDir, origVel, vehicleVelocity, addAmount, decayFactor, frictionFactor, + m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity); } else { @@ -609,18 +587,15 @@ namespace OpenSim.Region.Physics.BulletSPlugin VDetailLog("{0},MoveLinear,zeroed", Prim.LocalID); } - // m_newVelocity is velocity computed from linear motor + // m_newVelocity is velocity computed from linear motor in world coordinates - // Add the various forces into m_dir which will be our new direction vector (velocity) - - // add Gravity and Buoyancy + // Gravity and Buoyancy // There is some gravity, make a gravity force vector that is applied after object velocity. // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; - // Vector3 grav = Prim.PhysicsScene.DefaultGravity * (Prim.Linkset.LinksetMass * (1f - m_VehicleBuoyancy)); Vector3 grav = Prim.PhysicsScene.DefaultGravity * (1f - m_VehicleBuoyancy); /* - * RA: Not sure why one would do this + * RA: Not sure why one would do this unless we are hoping external forces are doing gravity, ... // Preserve the current Z velocity Vector3 vel_now = m_prim.Velocity; m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity @@ -676,7 +651,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin else { float verticalError = pos.Z - m_VhoverTargetHeight; - // RA: where does the 50 come from> + // RA: where does the 50 come from? float verticalCorrectionVelocity = pTimestep * ((verticalError * 50.0f) / m_VhoverTimescale); // Replace Vertical speed with correction figure if significant if (Math.Abs(verticalError) > 0.01f) @@ -784,37 +759,24 @@ namespace OpenSim.Region.Physics.BulletSPlugin // m_angularFrictionTimescale // body angular velocity decay rate // m_lastAngularVelocity // what was last applied to body - // Get what the body is doing, this includes 'external' influences - Vector3 angularVelocity = Prim.ForceRotationalVelocity; - - if (m_angularMotorApply > 0) + if (m_angularMotorDirection.LengthSquared() > 0.0001) { - // Rather than snapping the angular motor velocity from the old value to - // a newly set velocity, this routine steps the value from the previous - // value (m_angularMotorVelocity) to the requested value (m_angularMotorDirection). - // There are m_angularMotorApply steps. Vector3 origVel = m_angularMotorVelocity; Vector3 origDir = m_angularMotorDirection; - // ramp up to new value // new velocity += error / ( time to get there / step interval) // requested speed - last motor speed m_angularMotorVelocity += (m_angularMotorDirection - m_angularMotorVelocity) / (m_angularMotorTimescale / pTimestep); + // decay requested direction + m_angularMotorDirection *= (1.0f - (pTimestep * 1.0f/m_angularMotorDecayTimescale)); - VDetailLog("{0},MoveAngular,angularMotorApply,apply={1},angTScale={2},timeStep={3},origvel={4},origDir={5},vel={6}", - Prim.LocalID, m_angularMotorApply, m_angularMotorTimescale, pTimestep, origVel, origDir, m_angularMotorVelocity); - - m_angularMotorApply--; + VDetailLog("{0},MoveAngular,angularMotorApply,angTScale={1},timeStep={2},origvel={3},origDir={4},vel={5}", + Prim.LocalID, m_angularMotorTimescale, pTimestep, origVel, origDir, m_angularMotorVelocity); } else { - // No motor recently applied, keep the body velocity - // and decay the velocity - if (m_angularMotorVelocity.LengthSquared() < 0.0001) - m_angularMotorVelocity = Vector3.Zero; - else - m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep); - } // end motor section + m_angularMotorVelocity = Vector3.Zero; + } #region Vertical attactor @@ -824,22 +786,19 @@ namespace OpenSim.Region.Physics.BulletSPlugin if (m_verticalAttractionTimescale < 300 && m_lastAngularVelocity != Vector3.Zero) { - float VAservo = 0.2f; + float VAservo = pTimestep * 0.2f / m_verticalAttractionTimescale; if (Prim.Linkset.LinksetIsColliding) - VAservo = 0.05f / (m_verticalAttractionTimescale / pTimestep); + VAservo = pTimestep * 0.05f / (m_verticalAttractionTimescale); VAservo *= (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); - // get present body rotation - Quaternion rotq = Prim.ForceOrientation; - // vector pointing up - Vector3 verticalError = Vector3.UnitZ; - - // rotate it to Body Angle - verticalError = verticalError * rotq; - // verticalError.X and .Y are the World error amounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1. - // As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go - // negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body. + // Create a vector of the vehicle "up" in world coordinates + Vector3 verticalError = Vector3.UnitZ * Prim.ForceOrientation; + // verticalError.X and .Y are the World error amounts. They are 0 when there is no + // error (Vehicle Body is 'vertical'), and .Z will be 1. As the body leans to its + // side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall + // and .Z will go // negative. Similar for tilt and |.Y|. .X and .Y must be + // modulated to prevent a stable inverted body. // Error is 0 (no error) to +/- 2 (max error) if (verticalError.Z < 0.0f) @@ -850,13 +809,15 @@ namespace OpenSim.Region.Physics.BulletSPlugin // scale it by VAservo verticalError = verticalError * VAservo; - // As the body rotates around the X axis, then verticalError.Y increases; Rotated around Y then .X increases, so - // Change Body angular velocity X based on Y, and Y based on X. Z is not changed. + // As the body rotates around the X axis, then verticalError.Y increases; Rotated around Y + // then .X increases, so change Body angular velocity X based on Y, and Y based on X. + // Z is not changed. vertattr.X = verticalError.Y; vertattr.Y = - verticalError.X; vertattr.Z = 0f; // scaling appears better usingsquare-law + Vector3 angularVelocity = Prim.ForceRotationalVelocity; float bounce = 1.0f - (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); vertattr.X += bounce * angularVelocity.X; vertattr.Y += bounce * angularVelocity.Y; @@ -956,15 +917,22 @@ namespace OpenSim.Region.Physics.BulletSPlugin VDetailLog("{0},MoveAngular,zeroSmallValues,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity); } - // apply friction - Vector3 decayamount = Vector3.One / (m_angularFrictionTimescale / pTimestep); - m_lastAngularVelocity -= m_lastAngularVelocity * decayamount; - // Apply to the body // The above calculates the absolute angular velocity needed - Prim.ForceRotationalVelocity = m_lastAngularVelocity; + // Prim.ForceRotationalVelocity = m_lastAngularVelocity; + + // Apply a force to overcome current angular velocity + Vector3 applyAngularForce = (m_lastAngularVelocity - Prim.ForceRotationalVelocity) * Prim.Linkset.LinksetMass; + // Vector3 applyAngularForce = (m_lastAngularVelocity - Prim.ForceRotationalVelocity); + // Prim.AddAngularForce(applyAngularForce, false); + Prim.ApplyTorqueImpulse(applyAngularForce, false); + + // Apply friction for next time + Vector3 decayamount = (Vector3.One / m_angularFrictionTimescale) * pTimestep; + m_lastAngularVelocity *= Vector3.One - decayamount; - VDetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", Prim.LocalID, decayamount, m_lastAngularVelocity); + VDetailLog("{0},MoveAngular,done,applyAForce={1},decay={2},lastAngular={3}", + Prim.LocalID, applyAngularForce, decayamount, m_lastAngularVelocity); } //end MoveAngular internal void LimitRotation(float timestep) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs index ecb6ad4..8cdbd9b 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs @@ -299,7 +299,7 @@ public sealed class BSLinksetConstraints : BSLinkset // DEBUG: see of inter-linkset collisions are causing problems // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); - DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraints,setCenterOfMass,rBody={1},linksetMass={2}", + DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraints,set,rBody={1},linksetMass={2}", LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), linksetMass); foreach (BSPhysObject child in m_children) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 7851a40..9ced61fa 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -378,7 +378,9 @@ public sealed class BSPrim : BSPhysObject { OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, physMass); BulletSimAPI.SetMassProps2(BSBody.ptr, physMass, localInertia); - BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); + // center of mass is at the zero of the object + BulletSimAPI.SetCenterOfMassByPosRot2(BSBody.ptr, ForcePosition, ForceOrientation); + // BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2}", LocalID, physMass, localInertia); } } @@ -462,9 +464,16 @@ public sealed class BSPrim : BSPhysObject // Called from Scene when doing simulation step so we're in taint processing time. public override void StepVehicle(float timeStep) { - if (IsPhysical) + if (IsPhysical && _vehicle.IsActive) { _vehicle.Step(timeStep); + /* // TEST TEST DEBUG DEBUG -- trying to reduce the extra action of Bullet simulation step + PhysicsScene.PostTaintObject("BSPrim.StepVehicles", LocalID, delegate() + { + // This resets the interpolation values and recomputes the tensor variables + BulletSimAPI.SetCenterOfMassByPosRot2(BSBody.ptr, ForcePosition, ForceOrientation); + }); + */ } } @@ -502,7 +511,9 @@ public sealed class BSPrim : BSPhysObject } public override OMV.Vector3 Torque { get { return _torque; } - set { _torque = value; + set { + _torque = value; + AddAngularForce(_torque, false, false); // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); } } @@ -831,7 +842,7 @@ public sealed class BSPrim : BSPhysObject // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate() { - // DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); + DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); BulletSimAPI.SetAngularVelocity2(BSBody.ptr, _rotationalVelocity); }); } @@ -972,14 +983,31 @@ public sealed class BSPrim : BSPhysObject } m_accumulatedAngularForces.Clear(); } - // DetailLog("{0},BSPrim.AddAngularForce,taint,aForce={1}", LocalID, fSum); + DetailLog("{0},BSPrim.AddAngularForce,taint,aForce={1}", LocalID, fSum); if (fSum != OMV.Vector3.Zero) + { BulletSimAPI.ApplyTorque2(BSBody.ptr, fSum); + _torque = fSum; + } }; if (inTaintTime) addAngularForceOperation(); else - PhysicsScene.TaintedObject("BSPrim.AddForce", addAngularForceOperation); + PhysicsScene.TaintedObject("BSPrim.AddAngularForce", addAngularForceOperation); + } + // A torque impulse. + public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime) + { + OMV.Vector3 applyImpulse = impulse; + BSScene.TaintCallback applyTorqueImpulseOperation = delegate() + { + DetailLog("{0},BSPrim.ApplyTorqueImpulse,taint,tImpulse={1}", LocalID, applyImpulse); + BulletSimAPI.ApplyTorqueImpulse2(BSBody.ptr, applyImpulse); + }; + if (inTaintTime) + applyTorqueImpulseOperation(); + else + PhysicsScene.TaintedObject("BSPrim.ApplyTorqueImpulse", applyTorqueImpulseOperation); } public override void SetMomentum(OMV.Vector3 momentum) { // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); @@ -1418,8 +1446,9 @@ public sealed class BSPrim : BSPhysObject PositionSanityCheck(true); - DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", - LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); + OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; + DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}", + LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity); // BulletSimAPI.DumpRigidBody2(PhysicsScene.World.ptr, BSBody.ptr); // DEBUG DEBUG DEBUG -- cgit v1.1 From 364a7c308804a3e331199ca60c6dfafa406b5d0d Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 31 Oct 2012 14:49:28 -0700 Subject: BulletSim: rename BSBody and BSShape to PhysBody and PhysShape. Add skeleton of BSLinksetCompound. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 78 +++++----- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 4 +- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 7 - .../Physics/BulletSPlugin/BSLinksetCompound.cs | 173 +++++++++++++++++++++ .../Physics/BulletSPlugin/BSLinksetConstraints.cs | 40 ++--- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 8 +- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 128 +++++++-------- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 20 +-- .../Physics/BulletSPlugin/BSShapeCollection.cs | 46 +++--- 9 files changed, 328 insertions(+), 176 deletions(-) create mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index b9013ab..8c7061d 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -131,45 +131,45 @@ public sealed class BSCharacter : BSPhysObject DetailLog("{0},BSCharacter.Destroy", LocalID); PhysicsScene.TaintedObject("BSCharacter.destroy", delegate() { - PhysicsScene.Shapes.DereferenceBody(BSBody, true, null); - PhysicsScene.Shapes.DereferenceShape(BSShape, true, null); + PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null); + PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null); }); } private void SetPhysicalProperties() { - BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, BSBody.ptr); + BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, PhysBody.ptr); ZeroMotion(); ForcePosition = _position; // Set the velocity and compute the proper friction ForceVelocity = _velocity; - BulletSimAPI.SetRestitution2(BSBody.ptr, PhysicsScene.Params.avatarRestitution); - BulletSimAPI.SetMargin2(BSShape.ptr, PhysicsScene.Params.collisionMargin); - BulletSimAPI.SetLocalScaling2(BSShape.ptr, Scale); - BulletSimAPI.SetContactProcessingThreshold2(BSBody.ptr, PhysicsScene.Params.contactProcessingThreshold); + BulletSimAPI.SetRestitution2(PhysBody.ptr, PhysicsScene.Params.avatarRestitution); + BulletSimAPI.SetMargin2(PhysShape.ptr, PhysicsScene.Params.collisionMargin); + BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale); + BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, PhysicsScene.Params.contactProcessingThreshold); if (PhysicsScene.Params.ccdMotionThreshold > 0f) { - BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold); - BulletSimAPI.SetCcdSweptSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); + BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold); + BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); } UpdatePhysicalMassProperties(MassRaw); // Make so capsule does not fall over - BulletSimAPI.SetAngularFactorV2(BSBody.ptr, OMV.Vector3.Zero); + BulletSimAPI.SetAngularFactorV2(PhysBody.ptr, OMV.Vector3.Zero); - BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_CHARACTER_OBJECT); + BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_CHARACTER_OBJECT); - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, BSBody.ptr); + BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, PhysBody.ptr); // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ACTIVE_TAG); - BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_DEACTIVATION); - BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, BSBody.ptr); + BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.DISABLE_DEACTIVATION); + BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr); // Do this after the object has been added to the world - BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr, + BulletSimAPI.SetCollisionFilterMask2(PhysBody.ptr, (uint)CollisionFilterGroups.AvatarFilter, (uint)CollisionFilterGroups.AvatarMask); } @@ -199,7 +199,7 @@ public sealed class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() { - BulletSimAPI.SetLocalScaling2(BSShape.ptr, Scale); + BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale); UpdatePhysicalMassProperties(MassRaw); }); @@ -234,10 +234,10 @@ public sealed class BSCharacter : BSPhysObject _rotationalVelocity = OMV.Vector3.Zero; // Zero some other properties directly into the physics engine - BulletSimAPI.SetLinearVelocity2(BSBody.ptr, OMV.Vector3.Zero); - BulletSimAPI.SetAngularVelocity2(BSBody.ptr, OMV.Vector3.Zero); - BulletSimAPI.SetInterpolationVelocity2(BSBody.ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); - BulletSimAPI.ClearForces2(BSBody.ptr); + BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, OMV.Vector3.Zero); + BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero); + BulletSimAPI.SetInterpolationVelocity2(PhysBody.ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); + BulletSimAPI.ClearForces2(PhysBody.ptr); } public override void LockAngularMotion(OMV.Vector3 axis) { return; } @@ -254,19 +254,19 @@ public sealed class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate() { DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); + BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); }); } } public override OMV.Vector3 ForcePosition { get { - _position = BulletSimAPI.GetPosition2(BSBody.ptr); + _position = BulletSimAPI.GetPosition2(PhysBody.ptr); return _position; } set { _position = value; PositionSanityCheck(); - BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); + BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); } } @@ -313,7 +313,7 @@ public sealed class BSCharacter : BSPhysObject BSScene.TaintCallback sanityOperation = delegate() { DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); + BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); }; if (inTaintTime) sanityOperation(); @@ -332,8 +332,8 @@ public sealed class BSCharacter : BSPhysObject } public override void UpdatePhysicalMassProperties(float physMass) { - OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, physMass); - BulletSimAPI.SetMassProps2(BSBody.ptr, physMass, localInertia); + OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass); + BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, localInertia); } public override OMV.Vector3 Force { @@ -344,7 +344,7 @@ public sealed class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate() { DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force); - BulletSimAPI.SetObjectForce2(BSBody.ptr, _force); + BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); }); } } @@ -383,7 +383,7 @@ public sealed class BSCharacter : BSPhysObject if (_currentFriction != PhysicsScene.Params.avatarStandingFriction) { _currentFriction = PhysicsScene.Params.avatarStandingFriction; - BulletSimAPI.SetFriction2(BSBody.ptr, _currentFriction); + BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction); } } else @@ -391,15 +391,15 @@ public sealed class BSCharacter : BSPhysObject if (_currentFriction != PhysicsScene.Params.avatarFriction) { _currentFriction = PhysicsScene.Params.avatarFriction; - BulletSimAPI.SetFriction2(BSBody.ptr, _currentFriction); + BulletSimAPI.SetFriction2(PhysBody.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); + BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity); + BulletSimAPI.Activate2(PhysBody.ptr, true); } } public override OMV.Vector3 Torque { @@ -424,7 +424,7 @@ public sealed class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate() { // _position = BulletSimAPI.GetPosition2(BSBody.ptr); - BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); + BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); }); } } @@ -433,13 +433,13 @@ public sealed class BSCharacter : BSPhysObject { get { - _orientation = BulletSimAPI.GetOrientation2(BSBody.ptr); + _orientation = BulletSimAPI.GetOrientation2(PhysBody.ptr); return _orientation; } set { _orientation = value; - BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); + BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); } } public override int PhysicsActorType { @@ -498,9 +498,9 @@ public sealed class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.setFloatOnWater", delegate() { if (_floatOnWater) - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); + CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); else - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); + CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); }); } } @@ -533,7 +533,7 @@ public sealed class BSCharacter : BSPhysObject DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); // Buoyancy is faked by changing the gravity applied to the object float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); - BulletSimAPI.SetGravity2(BSBody.ptr, new OMV.Vector3(0f, 0f, grav)); + BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav)); } } @@ -579,7 +579,7 @@ public sealed class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.AddForce", delegate() { DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force); - BulletSimAPI.SetObjectForce2(BSBody.ptr, _force); + BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); }); } else @@ -647,7 +647,7 @@ public sealed class BSCharacter : BSPhysObject // That's just the way they are defined. OMV.Vector3 avVel = new OMV.Vector3(_appliedVelocity.X, _appliedVelocity.Y, entprop.Velocity.Z); _velocity = avVel; - BulletSimAPI.SetLinearVelocity2(BSBody.ptr, avVel); + BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, avVel); } // Tell the linkset about value changes diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 5c61774..38609e3 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -514,8 +514,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin if (IsActive) { // Friction effects are handled by this vehicle code - BulletSimAPI.SetFriction2(Prim.BSBody.ptr, 0f); - BulletSimAPI.SetHitFraction2(Prim.BSBody.ptr, 0f); + BulletSimAPI.SetFriction2(Prim.PhysBody.ptr, 0f); + BulletSimAPI.SetHitFraction2(Prim.PhysBody.ptr, 0f); } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 6d84fcc..525ec28 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -194,13 +194,6 @@ public abstract class BSLinkset // Called while LinkActivity is locked. protected abstract void AddChildToLinkset(BSPhysObject child); - // Forcefully removing a child from a linkset. - // This is not being called by the child so we have to make sure the child doesn't think - // it's still connected to the linkset. - // Normal OpenSimulator operation will never do this because other SceneObjectPart information - // also has to be updated (like pointer to prim's parent). - protected abstract void RemoveChildFromOtherLinkset(BSPhysObject pchild); - // 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); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs new file mode 100755 index 0000000..1c569b5 --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs @@ -0,0 +1,173 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyrightD + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections.Generic; +using System.Text; + +using OMV = OpenMetaverse; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ +public sealed class BSLinksetCompound : BSLinkset +{ + // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]"; + + public BSLinksetCompound(BSScene scene, BSPhysObject parent) + { + base.Initialize(scene, parent); + } + + // 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) + { + // Queue to happen after all the other taint processing + PhysicsScene.PostTaintObject("BSLinksetcompound.Refresh", requestor.LocalID, delegate() + { + if (HasAnyChildren && IsRoot(requestor)) + RecomputeLinksetCompound(); + }); + } + + // 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 override 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. + // This doesn't normally happen -- OpenSim removes the objects from the physical + // world if it is a static linkset. + // Called at taint-time! + public override bool MakeStatic(BSPhysObject child) + { + // What is done for each object in BSPrim is what we want. + return false; + } + + // Called at taint-time!! + public override void UpdateProperties(BSPhysObject updated) + { + // Nothing to do for constraints on property updates + } + + // Routine called when rebuilding the body of some member of the linkset. + // Destroy all the constraints have have been made to root and set + // up to rebuild the constraints before the next simulation step. + // Returns 'true' of something was actually removed and would need restoring + // Called at taint-time!! + public override bool RemoveBodyDependencies(BSPrim child) + { + bool ret = false; + + DetailLog("{0},BSLinksetcompound.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", + child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X")); + + // Cause the current shape to be freed and the new one to be built. + Refresh(LinksetRoot); + + return ret; + } + + // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', + // this routine will restore the removed constraints. + // Called at taint-time!! + public override void RestoreBodyDependencies(BSPrim child) + { + // The Refresh operation queued by RemoveBodyDependencies() will build any missing constraints. + } + + // ================================================================ + + // Add a new child to the linkset. + // Called while LinkActivity is locked. + protected override void AddChildToLinkset(BSPhysObject child) + { + if (!HasChild(child)) + { + m_children.Add(child); + + DetailLog("{0},BSLinksetCompound.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); + + // Cause constraints and assorted properties to be recomputed before the next simulation step. + Refresh(LinksetRoot); + } + return; + } + + // Remove the specified child from the linkset. + // Safe to call even if the child is not really in my linkset. + protected override void RemoveChildFromLinkset(BSPhysObject child) + { + if (m_children.Remove(child)) + { + DetailLog("{0},BSLinksetCompound.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", + child.LocalID, + LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), + child.LocalID, child.PhysBody.ptr.ToString("X")); + + // See that the linkset parameters are recomputed at the end of the taint time. + Refresh(LinksetRoot); + } + else + { + // Non-fatal occurance. + // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader); + } + return; + } + + + // Call each of the constraints that make up this linkset and recompute the + // various transforms and variables. Create constraints of not created yet. + // Called before the simulation step to make sure the constraint based linkset + // is all initialized. + // Called at taint time!! + private void RecomputeLinksetCompound() + { + float linksetMass = LinksetMass; + LinksetRoot.UpdatePhysicalMassProperties(linksetMass); + + // DEBUG: see of inter-linkset collisions are causing problems + // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, + // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); + DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,set,rBody={1},linksetMass={2}", + LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), linksetMass); + + + } +} +} \ No newline at end of file diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs index 8cdbd9b..65aed77 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs @@ -94,7 +94,7 @@ public sealed class BSLinksetConstraints : BSLinkset bool ret = false; DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", - child.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X")); + child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X")); lock (m_linksetActivityLock) { @@ -124,9 +124,6 @@ public sealed class BSLinksetConstraints : BSLinkset { m_children.Add(child); - BSPhysObject rootx = LinksetRoot; // capture the root as of now - BSPhysObject childx = child; - DetailLog("{0},BSLinksetConstraints.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); // Cause constraints and assorted properties to be recomputed before the next simulation step. @@ -135,17 +132,6 @@ public sealed class BSLinksetConstraints : BSLinkset return; } - // Forcefully removing a child from a linkset. - // This is not being called by the child so we have to make sure the child doesn't think - // it's still connected to the linkset. - // Normal OpenSimulator operation will never do this because other SceneObjectPart information - // also has to be updated (like pointer to prim's parent). - protected override void RemoveChildFromOtherLinkset(BSPhysObject pchild) - { - pchild.Linkset = BSLinkset.Factory(PhysicsScene, pchild); - RemoveChildFromLinkset(pchild); - } - // Remove the specified child from the linkset. // Safe to call even if the child is not really in my linkset. protected override void RemoveChildFromLinkset(BSPhysObject child) @@ -157,8 +143,8 @@ public sealed class BSLinksetConstraints : BSLinkset DetailLog("{0},BSLinksetConstraints.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", childx.LocalID, - rootx.LocalID, rootx.BSBody.ptr.ToString("X"), - childx.LocalID, childx.BSBody.ptr.ToString("X")); + rootx.LocalID, rootx.PhysBody.ptr.ToString("X"), + childx.LocalID, childx.PhysBody.ptr.ToString("X")); PhysicsScene.TaintedObject("BSLinksetConstraints.RemoveChildFromLinkset", delegate() { @@ -197,15 +183,15 @@ public sealed class BSLinksetConstraints : BSLinkset DetailLog("{0},BSLinksetConstraint.BuildConstraint,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", rootPrim.LocalID, - rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"), - childPrim.LocalID, childPrim.BSBody.ptr.ToString("X"), + rootPrim.LocalID, rootPrim.PhysBody.ptr.ToString("X"), + childPrim.LocalID, childPrim.PhysBody.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 BSConstraint6Dof constrain = new BSConstraint6Dof( - PhysicsScene.World, rootPrim.BSBody, childPrim.BSBody, midPoint, true, true ); + PhysicsScene.World, rootPrim.PhysBody, childPrim.PhysBody, midPoint, true, true ); // PhysicsScene.World, childPrim.BSBody, rootPrim.BSBody, midPoint, true, true ); /* NOTE: below is an attempt to build constraint with full frame computation, etc. @@ -262,14 +248,14 @@ public sealed class BSLinksetConstraints : BSLinkset bool ret = false; DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}", rootPrim.LocalID, - rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"), - childPrim.LocalID, childPrim.BSBody.ptr.ToString("X")); + rootPrim.LocalID, rootPrim.PhysBody.ptr.ToString("X"), + childPrim.LocalID, childPrim.PhysBody.ptr.ToString("X")); // Find the constraint for this link and get rid of it from the overall collection and from my list - if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody, childPrim.BSBody)) + if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody, childPrim.PhysBody)) { // Make the child refresh its location - BulletSimAPI.PushUpdate2(childPrim.BSBody.ptr); + BulletSimAPI.PushUpdate2(childPrim.PhysBody.ptr); ret = true; } @@ -283,7 +269,7 @@ public sealed class BSLinksetConstraints : BSLinkset { DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); - return PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody); + return PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody); } // Call each of the constraints that make up this linkset and recompute the @@ -300,7 +286,7 @@ public sealed class BSLinksetConstraints : BSLinkset // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraints,set,rBody={1},linksetMass={2}", - LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"), linksetMass); + LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), linksetMass); foreach (BSPhysObject child in m_children) { @@ -310,7 +296,7 @@ public sealed class BSLinksetConstraints : BSLinkset child.UpdatePhysicalMassProperties(linksetMass); BSConstraint constrain; - if (!PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.BSBody, child.BSBody, out constrain)) + if (!PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.PhysBody, child.PhysBody, out constrain)) { // If constraint doesn't exist yet, create it. constrain = BuildConstraint(LinksetRoot, child); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index be8d64b..6220b21 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -68,9 +68,9 @@ public abstract class BSPhysObject : PhysicsActor public abstract void UpdatePhysicalMassProperties(float mass); // Reference to the physical body (btCollisionObject) of this object - public BulletBody BSBody; + public BulletBody PhysBody; // Reference to the physical shape (btCollisionShape) of this object - public BulletShape BSShape; + public BulletShape PhysShape; // 'true' if the mesh's underlying asset failed to build. // This will keep us from looping after the first time the build failed. @@ -206,7 +206,7 @@ public abstract class BSPhysObject : PhysicsActor PhysicsScene.TaintedObject(TypeName+".SubscribeEvents", delegate() { - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); }); } else @@ -220,7 +220,7 @@ public abstract class BSPhysObject : PhysicsActor SubscribedEventsMs = 0; PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate() { - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); }); } // Return 'true' if the simulator wants collision events diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 9ced61fa..8dd48ca 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -111,8 +111,8 @@ public sealed class BSPrim : BSPhysObject _mass = CalculateMass(); // No body or shape yet - BSBody = new BulletBody(LocalID, IntPtr.Zero); - BSShape = new BulletShape(IntPtr.Zero); + PhysBody = new BulletBody(LocalID, IntPtr.Zero); + PhysShape = new BulletShape(IntPtr.Zero); DetailLog("{0},BSPrim.constructor,call", LocalID); // do the actual object creation at taint time @@ -120,7 +120,7 @@ public sealed class BSPrim : BSPhysObject { CreateGeomAndObject(true); - CurrentCollisionFlags = BulletSimAPI.GetCollisionFlags2(BSBody.ptr); + CurrentCollisionFlags = BulletSimAPI.GetCollisionFlags2(PhysBody.ptr); }); } @@ -145,8 +145,8 @@ public sealed class BSPrim : BSPhysObject { DetailLog("{0},BSPrim.Destroy,taint,", LocalID); // If there are physical body and shape, release my use of same. - PhysicsScene.Shapes.DereferenceBody(BSBody, true, null); - PhysicsScene.Shapes.DereferenceShape(BSShape, true, null); + PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null); + PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null); }); } @@ -243,7 +243,7 @@ public sealed class BSPrim : BSPhysObject _rotationalVelocity = OMV.Vector3.Zero; // Zero some other properties in the physics engine - BulletSimAPI.ClearAllForces2(BSBody.ptr); + BulletSimAPI.ClearAllForces2(PhysBody.ptr); } public override void LockAngularMotion(OMV.Vector3 axis) @@ -256,7 +256,7 @@ public sealed class BSPrim : BSPhysObject get { if (!Linkset.IsRoot(this)) // child prims move around based on their parent. Need to get the latest location - _position = BulletSimAPI.GetPosition2(BSBody.ptr); + _position = BulletSimAPI.GetPosition2(PhysBody.ptr); // don't do the GetObjectPosition for root elements because this function is called a zillion times // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); @@ -274,20 +274,20 @@ public sealed class BSPrim : BSPhysObject PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() { // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); + BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); ActivateIfPhysical(false); }); } } public override OMV.Vector3 ForcePosition { get { - _position = BulletSimAPI.GetPosition2(BSBody.ptr); + _position = BulletSimAPI.GetPosition2(PhysBody.ptr); return _position; } set { _position = value; PositionSanityCheck(); - BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); + BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); ActivateIfPhysical(false); } } @@ -371,15 +371,15 @@ public sealed class BSPrim : BSPhysObject { if (IsStatic) { - BulletSimAPI.SetMassProps2(BSBody.ptr, 0f, OMV.Vector3.Zero); - BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); + BulletSimAPI.SetMassProps2(PhysBody.ptr, 0f, OMV.Vector3.Zero); + BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr); } else { - OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, physMass); - BulletSimAPI.SetMassProps2(BSBody.ptr, physMass, localInertia); + OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass); + BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, localInertia); // center of mass is at the zero of the object - BulletSimAPI.SetCenterOfMassByPosRot2(BSBody.ptr, ForcePosition, ForceOrientation); + BulletSimAPI.SetCenterOfMassByPosRot2(PhysBody.ptr, ForcePosition, ForceOrientation); // BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2}", LocalID, physMass, localInertia); } @@ -404,7 +404,7 @@ public sealed class BSPrim : BSPhysObject PhysicsScene.TaintedObject("BSPrim.setForce", delegate() { // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); - BulletSimAPI.SetObjectForce2(BSBody.ptr, _force); + BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); }); } } @@ -498,7 +498,7 @@ public sealed class BSPrim : BSPhysObject PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate() { // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); - BulletSimAPI.SetLinearVelocity2(BSBody.ptr, _velocity); + BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity); }); } } @@ -506,7 +506,7 @@ public sealed class BSPrim : BSPhysObject get { return _velocity; } set { _velocity = value; - BulletSimAPI.SetLinearVelocity2(BSBody.ptr, _velocity); + BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity); } } public override OMV.Vector3 Torque { @@ -531,7 +531,7 @@ public sealed class BSPrim : BSPhysObject if (!Linkset.IsRoot(this)) { // Children move around because tied to parent. Get a fresh value. - _orientation = BulletSimAPI.GetOrientation2(BSBody.ptr); + _orientation = BulletSimAPI.GetOrientation2(PhysBody.ptr); } return _orientation; } @@ -544,7 +544,7 @@ public sealed class BSPrim : BSPhysObject { // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); + BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); }); } } @@ -553,13 +553,13 @@ public sealed class BSPrim : BSPhysObject { get { - _orientation = BulletSimAPI.GetOrientation2(BSBody.ptr); + _orientation = BulletSimAPI.GetOrientation2(PhysBody.ptr); return _orientation; } set { _orientation = value; - BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); + BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); } } public override int PhysicsActorType { @@ -615,7 +615,7 @@ public sealed class BSPrim : BSPhysObject // Mangling all the physical properties requires the object not be in the physical world. // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found). - BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, BSBody.ptr); + BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, PhysBody.ptr); // Set up the object physicalness (does gravity and collisions move this object) MakeDynamic(IsStatic); @@ -629,15 +629,15 @@ public sealed class BSPrim : BSPhysObject // Make solid or not (do things bounce off or pass through this object). MakeSolid(IsSolid); - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, BSBody.ptr); + BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, PhysBody.ptr); // Rebuild its shape - BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, BSBody.ptr); + BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr); // Collision filter can be set only when the object is in the world - if (BSBody.collisionFilter != 0 || BSBody.collisionMask != 0) + if (PhysBody.collisionFilter != 0 || PhysBody.collisionMask != 0) { - BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr, (uint)BSBody.collisionFilter, (uint)BSBody.collisionMask); + BulletSimAPI.SetCollisionFilterMask2(PhysBody.ptr, (uint)PhysBody.collisionFilter, (uint)PhysBody.collisionMask); } // Recompute any linkset parameters. @@ -646,7 +646,7 @@ public sealed class BSPrim : BSPhysObject Linkset.Refresh(this); DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}", - LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags, BSBody, BSShape); + LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags, PhysBody, PhysShape); } // "Making dynamic" means changing to and from static. @@ -659,44 +659,44 @@ public sealed class BSPrim : BSPhysObject if (makeStatic) { // Become a Bullet 'static' object type - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_STATIC_OBJECT); + CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_STATIC_OBJECT); // Stop all movement ZeroMotion(); // Center of mass is at the center of the object - BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.BSBody.ptr, _position, _orientation); + BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation); // Mass is zero which disables a bunch of physics stuff in Bullet UpdatePhysicalMassProperties(0f); // Set collision detection parameters if (PhysicsScene.Params.ccdMotionThreshold > 0f) { - BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold); - BulletSimAPI.SetCcdSweptSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); + BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold); + BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); } // There can be special things needed for implementing linksets Linkset.MakeStatic(this); // The activation state is 'disabled' so Bullet will not try to act on it. - BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_SIMULATION); + BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.DISABLE_SIMULATION); // Start it out sleeping and physical actions could wake it up. // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING); - BSBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter; - BSBody.collisionMask = CollisionFilterGroups.StaticObjectMask; + PhysBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter; + PhysBody.collisionMask = CollisionFilterGroups.StaticObjectMask; } else { // Not a Bullet static object - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.CF_STATIC_OBJECT); + CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_STATIC_OBJECT); // Set various physical properties so internal dynamic properties will get computed correctly as they are set - BulletSimAPI.SetFriction2(BSBody.ptr, PhysicsScene.Params.defaultFriction); - BulletSimAPI.SetRestitution2(BSBody.ptr, PhysicsScene.Params.defaultRestitution); + BulletSimAPI.SetFriction2(PhysBody.ptr, PhysicsScene.Params.defaultFriction); + BulletSimAPI.SetRestitution2(PhysBody.ptr, PhysicsScene.Params.defaultRestitution); // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 // Since this can be called multiple times, only zero forces when becoming physical // BulletSimAPI.ClearAllForces2(BSBody.ptr); // For good measure, make sure the transform is set through to the motion state - BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); + BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); // A dynamic object has mass UpdatePhysicalMassProperties(MassRaw); @@ -704,26 +704,26 @@ public sealed class BSPrim : BSPhysObject // Set collision detection parameters if (PhysicsScene.Params.ccdMotionThreshold > 0f) { - BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold); - BulletSimAPI.SetCcdSweptSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); + BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold); + BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); } // Various values for simulation limits - BulletSimAPI.SetDamping2(BSBody.ptr, PhysicsScene.Params.linearDamping, PhysicsScene.Params.angularDamping); - BulletSimAPI.SetDeactivationTime2(BSBody.ptr, PhysicsScene.Params.deactivationTime); - BulletSimAPI.SetSleepingThresholds2(BSBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold); - BulletSimAPI.SetContactProcessingThreshold2(BSBody.ptr, PhysicsScene.Params.contactProcessingThreshold); + BulletSimAPI.SetDamping2(PhysBody.ptr, PhysicsScene.Params.linearDamping, PhysicsScene.Params.angularDamping); + BulletSimAPI.SetDeactivationTime2(PhysBody.ptr, PhysicsScene.Params.deactivationTime); + BulletSimAPI.SetSleepingThresholds2(PhysBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold); + BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, PhysicsScene.Params.contactProcessingThreshold); // There might be special things needed for implementing linksets. Linkset.MakeDynamic(this); // Force activation of the object so Bullet will act on it. // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects. - BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ACTIVE_TAG); + BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ACTIVE_TAG); // BulletSimAPI.Activate2(BSBody.ptr, true); - BSBody.collisionFilter = CollisionFilterGroups.ObjectFilter; - BSBody.collisionMask = CollisionFilterGroups.ObjectMask; + PhysBody.collisionFilter = CollisionFilterGroups.ObjectFilter; + PhysBody.collisionMask = CollisionFilterGroups.ObjectMask; } } @@ -733,7 +733,7 @@ public sealed class BSPrim : BSPhysObject // the functions after this one set up the state of a possibly newly created collision body. private void MakeSolid(bool makeSolid) { - CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(BSBody.ptr); + CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(PhysBody.ptr); if (makeSolid) { // Verify the previous code created the correct shape for this type of thing. @@ -741,7 +741,7 @@ public sealed class BSPrim : BSPhysObject { m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for solidity. id={1}, type={2}", LogHeader, LocalID, bodyType); } - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); + CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); } else { @@ -749,9 +749,9 @@ public sealed class BSPrim : BSPhysObject { m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType); } - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); - BSBody.collisionFilter = CollisionFilterGroups.VolumeDetectFilter; - BSBody.collisionMask = CollisionFilterGroups.VolumeDetectMask; + CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); + PhysBody.collisionFilter = CollisionFilterGroups.VolumeDetectFilter; + PhysBody.collisionMask = CollisionFilterGroups.VolumeDetectMask; } } @@ -761,7 +761,7 @@ public sealed class BSPrim : BSPhysObject private void ActivateIfPhysical(bool forceIt) { if (IsPhysical) - BulletSimAPI.Activate2(BSBody.ptr, forceIt); + BulletSimAPI.Activate2(PhysBody.ptr, forceIt); } // Turn on or off the flag controlling whether collision events are returned to the simulator. @@ -769,11 +769,11 @@ public sealed class BSPrim : BSPhysObject { if (wantsCollisionEvents) { - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); } else { - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); } } @@ -818,9 +818,9 @@ public sealed class BSPrim : BSPhysObject PhysicsScene.TaintedObject("BSPrim.setFloatOnWater", delegate() { if (_floatOnWater) - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); + CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); else - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); + CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); }); } } @@ -843,7 +843,7 @@ public sealed class BSPrim : BSPhysObject PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate() { DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); - BulletSimAPI.SetAngularVelocity2(BSBody.ptr, _rotationalVelocity); + BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity); }); } } @@ -853,7 +853,7 @@ public sealed class BSPrim : BSPhysObject } set { _rotationalVelocity = value; - BulletSimAPI.SetAngularVelocity2(BSBody.ptr, _rotationalVelocity); + BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity); } } public override bool Kinematic { @@ -879,7 +879,7 @@ public sealed class BSPrim : BSPhysObject // DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); // Buoyancy is faked by changing the gravity applied to the object float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); - BulletSimAPI.SetGravity2(BSBody.ptr, new OMV.Vector3(0f, 0f, grav)); + BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav)); } } @@ -946,7 +946,7 @@ public sealed class BSPrim : BSPhysObject } DetailLog("{0},BSPrim.AddForce,taint,force={1}", LocalID, fSum); if (fSum != OMV.Vector3.Zero) - BulletSimAPI.ApplyCentralForce2(BSBody.ptr, fSum); + BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, fSum); }; if (inTaintTime) addForceOperation(); @@ -986,7 +986,7 @@ public sealed class BSPrim : BSPhysObject DetailLog("{0},BSPrim.AddAngularForce,taint,aForce={1}", LocalID, fSum); if (fSum != OMV.Vector3.Zero) { - BulletSimAPI.ApplyTorque2(BSBody.ptr, fSum); + BulletSimAPI.ApplyTorque2(PhysBody.ptr, fSum); _torque = fSum; } }; @@ -1002,7 +1002,7 @@ public sealed class BSPrim : BSPhysObject BSScene.TaintCallback applyTorqueImpulseOperation = delegate() { DetailLog("{0},BSPrim.ApplyTorqueImpulse,taint,tImpulse={1}", LocalID, applyImpulse); - BulletSimAPI.ApplyTorqueImpulse2(BSBody.ptr, applyImpulse); + BulletSimAPI.ApplyTorqueImpulse2(PhysBody.ptr, applyImpulse); }; if (inTaintTime) applyTorqueImpulseOperation(); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index c27b5f0..cc5dbb2 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -1067,49 +1067,49 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters (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,o,v) => { BulletSimAPI.SetDamping2(o.BSBody.ptr, v, v); } ), + (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.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,o,v) => { BulletSimAPI.SetDamping2(o.BSBody.ptr, v, v); } ), + (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.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,o,v) => { BulletSimAPI.SetDeactivationTime2(o.BSBody.ptr, v); } ), + (s,o,v) => { BulletSimAPI.SetDeactivationTime2(o.PhysBody.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,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.BSBody.ptr, v, v); } ), + (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.PhysBody.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,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.BSBody.ptr, v, v); } ), + (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.PhysBody.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,o,v) => { BulletSimAPI.SetCcdMotionThreshold2(o.BSBody.ptr, v); } ), + (s,o,v) => { BulletSimAPI.SetCcdMotionThreshold2(o.PhysBody.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,o,v) => { BulletSimAPI.SetCcdSweptSphereRadius2(o.BSBody.ptr, v); } ), + (s,o,v) => { BulletSimAPI.SetCcdSweptSphereRadius2(o.PhysBody.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,o,v) => { BulletSimAPI.SetContactProcessingThreshold2(o.BSBody.ptr, v); } ), + (s,o,v) => { BulletSimAPI.SetContactProcessingThreshold2(o.PhysBody.ptr, v); } ), new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" , 0.5f, @@ -1428,8 +1428,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters { foreach (BSPrim prim in m_vehicles) { - BulletSimAPI.DumpRigidBody2(World.ptr, prim.BSBody.ptr); - BulletSimAPI.DumpCollisionShape2(World.ptr, prim.BSShape.ptr); + BulletSimAPI.DumpRigidBody2(World.ptr, prim.PhysBody.ptr); + BulletSimAPI.DumpCollisionShape2(World.ptr, prim.PhysShape.ptr); } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 1219fc0..a38e650 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -106,11 +106,11 @@ public sealed class BSShapeCollection : IDisposable // 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); + prim.PhysShape, shapeData, bodyCallback); ret = newGeom || newBody; } DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}", - prim.LocalID, forceRebuild, ret, prim.BSBody, prim.BSShape); + prim.LocalID, forceRebuild, ret, prim.PhysBody, prim.PhysShape); return ret; } @@ -337,7 +337,7 @@ public sealed class BSShapeCollection : IDisposable // an avatar capsule is close to a native shape (it is not shared) ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_AVATAR, ShapeData.FixedShapeKey.KEY_CAPSULE, shapeCallback); - DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.BSShape); + DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape); ret = true; haveShape = true; } @@ -360,13 +360,13 @@ public sealed class BSShapeCollection : IDisposable haveShape = true; if (forceRebuild || prim.Scale != shapeData.Size - || prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE + || prim.PhysShape.type != ShapeData.PhysicsShapeType.SHAPE_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); + prim.LocalID, forceRebuild, prim.PhysShape); } } if (pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) @@ -374,13 +374,13 @@ public sealed class BSShapeCollection : IDisposable haveShape = true; if (forceRebuild || prim.Scale != shapeData.Size - || prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX + || prim.PhysShape.type != ShapeData.PhysicsShapeType.SHAPE_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); + prim.LocalID, forceRebuild, prim.PhysShape); } } } @@ -394,13 +394,13 @@ public sealed class BSShapeCollection : IDisposable // Update prim.BSShape to reference a hull of this shape. ret = GetReferenceToHull(prim, shapeData, pbs, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}", - shapeData.ID, prim.BSShape, prim.BSShape.shapeKey.ToString("X")); + shapeData.ID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); } else { ret = GetReferenceToMesh(prim, shapeData, pbs, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}", - shapeData.ID, prim.BSShape, prim.BSShape.shapeKey.ToString("X")); + shapeData.ID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); } } return ret; @@ -413,7 +413,7 @@ public sealed class BSShapeCollection : IDisposable ShapeDestructionCallback shapeCallback) { // release any previous shape - DereferenceShape(prim.BSShape, true, shapeCallback); + DereferenceShape(prim.PhysShape, true, shapeCallback); shapeData.Type = shapeType; // Bullet native objects are scaled by the Bullet engine so pass the size in @@ -426,7 +426,7 @@ public sealed class BSShapeCollection : IDisposable DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}", shapeData.ID, newShape, shapeData.Scale); - prim.BSShape = newShape; + prim.PhysShape = newShape; return true; } @@ -475,14 +475,14 @@ public sealed class BSShapeCollection : IDisposable System.UInt64 newMeshKey = ComputeShapeKey(shapeData, pbs, out lod); // if this new shape is the same as last time, don't recreate the mesh - if (newMeshKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH) + if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH) return false; DetailLog("{0},BSShapeCollection.CreateGeomMesh,create,oldKey={1},newKey={2}", - prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newMeshKey.ToString("X")); + prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X")); // Since we're recreating new, get rid of the reference to the previous shape - DereferenceShape(prim.BSShape, true, shapeCallback); + DereferenceShape(prim.PhysShape, true, shapeCallback); newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, pbs, shapeData.Size, lod); // Take evasive action if the mesh was not constructed. @@ -492,7 +492,7 @@ public sealed class BSShapeCollection : IDisposable // meshes are already scaled by the meshmerizer prim.Scale = new OMV.Vector3(1f, 1f, 1f); - prim.BSShape = newShape; + prim.PhysShape = newShape; return true; // 'true' means a new shape has been added to this prim } @@ -550,14 +550,14 @@ public sealed class BSShapeCollection : IDisposable System.UInt64 newHullKey = ComputeShapeKey(shapeData, pbs, out lod); // if the hull hasn't changed, don't rebuild it - if (newHullKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL) + if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL) return false; DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}", - prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newHullKey.ToString("X")); + prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X")); // Remove usage of the previous shape. - DereferenceShape(prim.BSShape, true, shapeCallback); + DereferenceShape(prim.PhysShape, true, shapeCallback); newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, pbs, shapeData.Size, lod); newShape = VerifyMeshCreated(newShape, prim, shapeData, pbs); @@ -566,7 +566,7 @@ public sealed class BSShapeCollection : IDisposable // hulls are already scaled by the meshmerizer prim.Scale = new OMV.Vector3(1f, 1f, 1f); - prim.BSShape = newShape; + prim.PhysShape = newShape; return true; // 'true' means a new shape has been added to this prim } @@ -778,13 +778,13 @@ public sealed class BSShapeCollection : IDisposable bool ret = false; // the mesh, hull or native shape must have already been created in Bullet - bool mustRebuild = (prim.BSBody.ptr == IntPtr.Zero); + bool mustRebuild = (prim.PhysBody.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); + CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(prim.PhysBody.ptr); if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT) { @@ -796,7 +796,7 @@ public sealed class BSShapeCollection : IDisposable if (mustRebuild || forceRebuild) { // Free any old body - DereferenceBody(prim.BSBody, true, bodyCallback); + DereferenceBody(prim.PhysBody, true, bodyCallback); BulletBody aBody; IntPtr bodyPtr = IntPtr.Zero; @@ -816,7 +816,7 @@ public sealed class BSShapeCollection : IDisposable ReferenceBody(aBody, true); - prim.BSBody = aBody; + prim.PhysBody = aBody; ret = true; } -- cgit v1.1 From 39c02dcc8c537d5989238ec97c876e033895a8a9 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 1 Nov 2012 10:23:37 -0700 Subject: BulletSim: Remove use of shapeData in ShapeCollection and rely on the available BSPhysObject varaiables. Fix line endings in BSLinksetCompound. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 19 +- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 5 + .../Physics/BulletSPlugin/BSLinksetCompound.cs | 347 +++++++++++---------- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 4 + OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 30 +- .../Physics/BulletSPlugin/BSShapeCollection.cs | 116 +++---- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 1 + 7 files changed, 256 insertions(+), 266 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 8c7061d..2a634b9 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -99,26 +99,12 @@ public sealed class BSCharacter : BSPhysObject DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}", LocalID, _size, Scale, _avatarDensity, _avatarVolume, MassRaw); - ShapeData shapeData = new ShapeData(); - shapeData.ID = LocalID; - shapeData.Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR; - shapeData.Position = _position; - shapeData.Rotation = _orientation; - shapeData.Velocity = _velocity; - shapeData.Size = Scale; // capsule is a native shape but scale is not just <1,1,1> - shapeData.Scale = Scale; - shapeData.Mass = _mass; - shapeData.Buoyancy = _buoyancy; - shapeData.Static = ShapeData.numericFalse; - shapeData.Friction = PhysicsScene.Params.avatarStandingFriction; - shapeData.Restitution = PhysicsScene.Params.avatarRestitution; - // do actual create at taint time PhysicsScene.TaintedObject("BSCharacter.create", delegate() { DetailLog("{0},BSCharacter.create,taint", LocalID); // New body and shape into BSBody and BSShape - PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, shapeData, null, null, null); + PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, null, null); SetPhysicalProperties(); }); @@ -212,6 +198,9 @@ public sealed class BSCharacter : BSPhysObject { set { BaseShape = value; } } + // I want the physics engine to make an avatar capsule + public override ShapeData.PhysicsShapeType PreferredPhysicalShape + { get { return ShapeData.PhysicsShapeType.SHAPE_AVATAR; } } public override bool Grabbed { set { _grabbed = value; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 525ec28..f56851f 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -68,6 +68,11 @@ public abstract class BSLinkset // to the physical representation is done via the tainting mechenism. protected object m_linksetActivityLock = new Object(); + // Some linksets have a preferred physical shape. + // Returns SHAPE_UNKNOWN if there is no preference. + public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape + { get { return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; } } + // We keep the prim's mass in the linkset structure since it could be dependent on other prims protected float m_mass; public float LinksetMass diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs index 1c569b5..638fae1 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs @@ -1,173 +1,176 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; - -using OMV = OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ -public sealed class BSLinksetCompound : BSLinkset -{ - // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]"; - - public BSLinksetCompound(BSScene scene, BSPhysObject parent) - { - base.Initialize(scene, parent); - } - - // 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) - { - // Queue to happen after all the other taint processing - PhysicsScene.PostTaintObject("BSLinksetcompound.Refresh", requestor.LocalID, delegate() - { - if (HasAnyChildren && IsRoot(requestor)) - RecomputeLinksetCompound(); - }); - } - - // 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 override 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. - // This doesn't normally happen -- OpenSim removes the objects from the physical - // world if it is a static linkset. - // Called at taint-time! - public override bool MakeStatic(BSPhysObject child) - { - // What is done for each object in BSPrim is what we want. - return false; - } - - // Called at taint-time!! - public override void UpdateProperties(BSPhysObject updated) - { - // Nothing to do for constraints on property updates - } - - // Routine called when rebuilding the body of some member of the linkset. - // Destroy all the constraints have have been made to root and set - // up to rebuild the constraints before the next simulation step. - // Returns 'true' of something was actually removed and would need restoring - // Called at taint-time!! - public override bool RemoveBodyDependencies(BSPrim child) - { - bool ret = false; - - DetailLog("{0},BSLinksetcompound.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", - child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X")); - - // Cause the current shape to be freed and the new one to be built. - Refresh(LinksetRoot); - - return ret; - } - - // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', - // this routine will restore the removed constraints. - // Called at taint-time!! - public override void RestoreBodyDependencies(BSPrim child) - { - // The Refresh operation queued by RemoveBodyDependencies() will build any missing constraints. - } - - // ================================================================ - - // Add a new child to the linkset. - // Called while LinkActivity is locked. - protected override void AddChildToLinkset(BSPhysObject child) - { - if (!HasChild(child)) - { - m_children.Add(child); - - DetailLog("{0},BSLinksetCompound.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); - - // Cause constraints and assorted properties to be recomputed before the next simulation step. - Refresh(LinksetRoot); - } - return; - } - - // Remove the specified child from the linkset. - // Safe to call even if the child is not really in my linkset. - protected override void RemoveChildFromLinkset(BSPhysObject child) - { - if (m_children.Remove(child)) - { - DetailLog("{0},BSLinksetCompound.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", - child.LocalID, - LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), - child.LocalID, child.PhysBody.ptr.ToString("X")); - - // See that the linkset parameters are recomputed at the end of the taint time. - Refresh(LinksetRoot); - } - else - { - // Non-fatal occurance. - // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader); - } - return; - } - - - // Call each of the constraints that make up this linkset and recompute the - // various transforms and variables. Create constraints of not created yet. - // Called before the simulation step to make sure the constraint based linkset - // is all initialized. - // Called at taint time!! - private void RecomputeLinksetCompound() - { - float linksetMass = LinksetMass; - LinksetRoot.UpdatePhysicalMassProperties(linksetMass); - - // DEBUG: see of inter-linkset collisions are causing problems - // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, - // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); - DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,set,rBody={1},linksetMass={2}", - LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), linksetMass); - - - } -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyrightD + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections.Generic; +using System.Text; + +using OMV = OpenMetaverse; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ +public sealed class BSLinksetCompound : BSLinkset +{ + // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]"; + + public BSLinksetCompound(BSScene scene, BSPhysObject parent) + { + base.Initialize(scene, parent); + } + + // 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) + { + // Queue to happen after all the other taint processing + PhysicsScene.PostTaintObject("BSLinksetcompound.Refresh", requestor.LocalID, delegate() + { + if (HasAnyChildren && IsRoot(requestor)) + RecomputeLinksetCompound(); + }); + } + + // 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 override 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. + // This doesn't normally happen -- OpenSim removes the objects from the physical + // world if it is a static linkset. + // Called at taint-time! + public override bool MakeStatic(BSPhysObject child) + { + // What is done for each object in BSPrim is what we want. + return false; + } + + // Called at taint-time!! + public override void UpdateProperties(BSPhysObject updated) + { + // Nothing to do for constraints on property updates + } + + // Routine called when rebuilding the body of some member of the linkset. + // Destroy all the constraints have have been made to root and set + // up to rebuild the constraints before the next simulation step. + // Returns 'true' of something was actually removed and would need restoring + // Called at taint-time!! + public override bool RemoveBodyDependencies(BSPrim child) + { + bool ret = false; + + DetailLog("{0},BSLinksetcompound.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", + child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X")); + + // Cause the current shape to be freed and the new one to be built. + Refresh(LinksetRoot); + + return ret; + } + + // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', + // this routine will restore the removed constraints. + // Called at taint-time!! + public override void RestoreBodyDependencies(BSPrim child) + { + // The Refresh operation queued by RemoveBodyDependencies() will build any missing constraints. + } + + // ================================================================ + + // Add a new child to the linkset. + // Called while LinkActivity is locked. + protected override void AddChildToLinkset(BSPhysObject child) + { + if (!HasChild(child)) + { + m_children.Add(child); + + DetailLog("{0},BSLinksetCompound.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); + + // Cause constraints and assorted properties to be recomputed before the next simulation step. + Refresh(LinksetRoot); + } + return; + } + + // Remove the specified child from the linkset. + // Safe to call even if the child is not really in my linkset. + protected override void RemoveChildFromLinkset(BSPhysObject child) + { + if (m_children.Remove(child)) + { + DetailLog("{0},BSLinksetCompound.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", + child.LocalID, + LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), + child.LocalID, child.PhysBody.ptr.ToString("X")); + + // See that the linkset parameters are recomputed at the end of the taint time. + Refresh(LinksetRoot); + } + else + { + // Non-fatal occurance. + // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader); + } + return; + } + + + // Call each of the constraints that make up this linkset and recompute the + // various transforms and variables. Create constraints of not created yet. + // Called before the simulation step to make sure the constraint based linkset + // is all initialized. + // Called at taint time!! + private void RecomputeLinksetCompound() + { + // Release the existing shape + PhysicsScene.Shapes.DereferenceShape(LinksetRoot.PhysShape, true, null); + + float linksetMass = LinksetMass; + LinksetRoot.UpdatePhysicalMassProperties(linksetMass); + + // DEBUG: see of inter-linkset collisions are causing problems + // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, + // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); + DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,set,rBody={1},linksetMass={2}", + LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), linksetMass); + + + } +} } \ No newline at end of file diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 6220b21..7d91468 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -78,6 +78,10 @@ public abstract class BSPhysObject : PhysicsActor // The objects base shape information. Null if not a prim type shape. public PrimitiveBaseShape BaseShape { get; protected set; } + // Some types of objects have preferred physical representations. + // Returns SHAPE_UNKNOWN if there is no preference. + public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape + { get { return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; } } // When the physical properties are updated, an EntityProperty holds the update values. // Keep the current and last EntityProperties to enable computation of differences diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 8dd48ca..8ce960d 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -171,6 +171,10 @@ public sealed class BSPrim : BSPhysObject ForceBodyShapeRebuild(false); } } + // Whatever the linkset wants is what I want. + public override ShapeData.PhysicsShapeType PreferredPhysicalShape + { get { return Linkset.PreferredPhysicalShape; } } + public override bool ForceBodyShapeRebuild(bool inTaintTime) { LastAssetBuildFailed = false; @@ -1310,34 +1314,11 @@ public sealed class BSPrim : BSPhysObject }// end CalculateMass #endregion Mass Calculation - // Copy prim's info into the BulletSim shape description structure - public void FillShapeInfo(out ShapeData shape) - { - shape.ID = LocalID; - shape.Type = ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; - shape.Position = _position; - shape.Rotation = _orientation; - shape.Velocity = _velocity; - shape.Size = _size; - shape.Scale = Scale; - shape.Mass = _isPhysical ? _mass : 0f; - shape.Buoyancy = _buoyancy; - shape.HullKey = 0; - shape.MeshKey = 0; - shape.Friction = _friction; - shape.Restitution = _restitution; - shape.Collidable = (!IsPhantom) ? ShapeData.numericTrue : ShapeData.numericFalse; - shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; - shape.Solid = IsSolid ? ShapeData.numericFalse : ShapeData.numericTrue; - } // Rebuild the geometry and object. // This is called when the shape changes so we need to recreate the mesh/hull. // Called at taint-time!!! private void CreateGeomAndObject(bool forceRebuild) { - ShapeData shapeData; - FillShapeInfo(out shapeData); - // If this prim is part of a linkset, we must remove and restore the physical // links if the body is rebuilt. bool needToRestoreLinkset = false; @@ -1346,8 +1327,7 @@ public sealed class BSPrim : BSPhysObject // Updates BSBody and BSShape with the new information. // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. // Returns 'true' if either the body or the shape was changed. - PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, shapeData, BaseShape, - null, delegate(BulletBody dBody) + PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, null, delegate(BulletBody dBody) { // Called if the current prim body is about to be destroyed. // Remove all the physical dependencies on the old body. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index a38e650..478924a 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -90,7 +90,6 @@ public sealed class BSShapeCollection : IDisposable // 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, ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback) { bool ret = false; @@ -101,12 +100,12 @@ public sealed class BSShapeCollection : IDisposable // Do we have the correct geometry for this type of object? // 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); + 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 bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, - prim.PhysShape, shapeData, bodyCallback); + prim.PhysShape, bodyCallback); ret = newGeom || newBody; } DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}", @@ -261,6 +260,9 @@ public sealed class BSShapeCollection : IDisposable case ShapeData.PhysicsShapeType.SHAPE_MESH: DereferenceMesh(shape, shapeCallback); break; + case ShapeData.PhysicsShapeType.SHAPE_COMPOUND: + DereferenceCompound(shape, shapeCallback); + break; case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN: break; default: @@ -317,6 +319,13 @@ public sealed class BSShapeCollection : IDisposable } } + // Remove a reference to a compound shape. + // Called at taint-time. + private void DereferenceCompound(BulletShape shape, ShapeDestructionCallback shapeCallback) + { + // Compound shape is made of a bunch of meshes and natives. + } + // Create the geometry information in Bullet for later use. // The objects needs a hull if it's physical otherwise a mesh is enough. // if 'forceRebuild' is true, the geometry is unconditionally rebuilt. For meshes and hulls, @@ -325,17 +334,17 @@ public sealed class BSShapeCollection : IDisposable // Info in prim.BSShape is updated to the new shape. // Returns 'true' if the geometry was rebuilt. // Called at taint-time! - private bool CreateGeom(bool forceRebuild, BSPhysObject prim, ShapeData shapeData, - PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback) + private bool CreateGeom(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback) { bool ret = false; bool haveShape = false; bool nativeShapePossible = true; + PrimitiveBaseShape pbs = prim.BaseShape; - if (shapeData.Type == ShapeData.PhysicsShapeType.SHAPE_AVATAR) + if (prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_AVATAR) { // an avatar capsule is close to a native shape (it is not shared) - ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_AVATAR, + ret = GetReferenceToNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_AVATAR, ShapeData.FixedShapeKey.KEY_CAPSULE, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape); ret = true; @@ -359,11 +368,11 @@ public sealed class BSShapeCollection : IDisposable { haveShape = true; if (forceRebuild - || prim.Scale != shapeData.Size + || prim.Scale != prim.Size || prim.PhysShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE ) { - ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_SPHERE, + ret = GetReferenceToNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_SPHERE, ShapeData.FixedShapeKey.KEY_SPHERE, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}", prim.LocalID, forceRebuild, prim.PhysShape); @@ -373,11 +382,11 @@ public sealed class BSShapeCollection : IDisposable { haveShape = true; if (forceRebuild - || prim.Scale != shapeData.Size + || prim.Scale != prim.Size || prim.PhysShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX ) { - ret = GetReferenceToNativeShape( prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_BOX, + ret = GetReferenceToNativeShape( prim, ShapeData.PhysicsShapeType.SHAPE_BOX, ShapeData.FixedShapeKey.KEY_BOX, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}", prim.LocalID, forceRebuild, prim.PhysShape); @@ -392,15 +401,15 @@ public sealed class BSShapeCollection : IDisposable if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects) { // Update prim.BSShape to reference a hull of this shape. - ret = GetReferenceToHull(prim, shapeData, pbs, shapeCallback); + ret = GetReferenceToHull(prim,shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}", - shapeData.ID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); + prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); } else { - ret = GetReferenceToMesh(prim, shapeData, pbs, shapeCallback); + ret = GetReferenceToMesh(prim, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}", - shapeData.ID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); + prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); } } return ret; @@ -408,44 +417,45 @@ public sealed class BSShapeCollection : IDisposable // Creates a native shape and assignes it to prim.BSShape. // "Native" shapes are never shared. they are created here and destroyed in DereferenceShape(). - private bool GetReferenceToNativeShape(BSPhysObject prim, ShapeData shapeData, + private bool GetReferenceToNativeShape(BSPhysObject prim, ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey, ShapeDestructionCallback shapeCallback) { // release any previous shape DereferenceShape(prim.PhysShape, true, shapeCallback); - shapeData.Type = shapeType; // Bullet native objects are scaled by the Bullet engine so pass the size in - prim.Scale = shapeData.Size; - shapeData.Scale = shapeData.Size; + prim.Scale = prim.Size; - BulletShape newShape = BuildPhysicalNativeShape(shapeType, shapeData, shapeKey); + BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey); // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}", - shapeData.ID, newShape, shapeData.Scale); + prim.LocalID, newShape, prim.Scale); prim.PhysShape = newShape; return true; } - private BulletShape BuildPhysicalNativeShape(ShapeData.PhysicsShapeType shapeType, - ShapeData shapeData, ShapeData.FixedShapeKey shapeKey) + private BulletShape BuildPhysicalNativeShape(BSPhysObject prim, ShapeData.PhysicsShapeType shapeType, + ShapeData.FixedShapeKey shapeKey) { BulletShape newShape; // Need to make sure the passed shape information is for the native type. - ShapeData nativeShapeData = shapeData; + ShapeData nativeShapeData = new ShapeData(); nativeShapeData.Type = shapeType; + nativeShapeData.ID = prim.LocalID; + nativeShapeData.Scale = prim.Scale; + nativeShapeData.Size = prim.Scale; nativeShapeData.MeshKey = (ulong)shapeKey; nativeShapeData.HullKey = (ulong)shapeKey; if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) { newShape = new BulletShape( - BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, nativeShapeData.Scale) + BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, prim.Scale) , shapeType); - DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", nativeShapeData.ID, nativeShapeData.Scale); + DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); } else { @@ -454,7 +464,7 @@ public sealed class BSShapeCollection : IDisposable if (newShape.ptr == IntPtr.Zero) { PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", - LogHeader, nativeShapeData.ID, nativeShapeData.Type); + LogHeader, prim.LocalID, shapeType); } newShape.shapeKey = (System.UInt64)shapeKey; newShape.isNativeShape = true; @@ -466,13 +476,12 @@ public sealed 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(BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs, - ShapeDestructionCallback shapeCallback) + private bool GetReferenceToMesh(BSPhysObject prim, ShapeDestructionCallback shapeCallback) { BulletShape newShape = new BulletShape(IntPtr.Zero); float lod; - System.UInt64 newMeshKey = ComputeShapeKey(shapeData, pbs, out lod); + System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod); // if this new shape is the same as last time, don't recreate the mesh if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH) @@ -484,9 +493,9 @@ public sealed class BSShapeCollection : IDisposable // Since we're recreating new, get rid of the reference to the previous shape DereferenceShape(prim.PhysShape, true, shapeCallback); - newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, pbs, shapeData.Size, lod); + newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, prim.BaseShape, prim.Size, lod); // Take evasive action if the mesh was not constructed. - newShape = VerifyMeshCreated(newShape, prim, shapeData, pbs); + newShape = VerifyMeshCreated(newShape, prim); ReferenceShape(newShape); @@ -541,13 +550,12 @@ public sealed 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(BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs, - ShapeDestructionCallback shapeCallback) + private bool GetReferenceToHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback) { BulletShape newShape; float lod; - System.UInt64 newHullKey = ComputeShapeKey(shapeData, pbs, out lod); + System.UInt64 newHullKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod); // if the hull hasn't changed, don't rebuild it if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL) @@ -559,8 +567,8 @@ public sealed class BSShapeCollection : IDisposable // Remove usage of the previous shape. DereferenceShape(prim.PhysShape, true, shapeCallback); - newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, pbs, shapeData.Size, lod); - newShape = VerifyMeshCreated(newShape, prim, shapeData, pbs); + newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod); + newShape = VerifyMeshCreated(newShape, prim); ReferenceShape(newShape); @@ -687,7 +695,7 @@ public sealed class BSShapeCollection : IDisposable // Create a hash of all the shape parameters to be used as a key // for this particular shape. - private System.UInt64 ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs, out float retLod) + private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod) { // level of detail based on size and type of the object float lod = PhysicsScene.MeshLOD; @@ -695,40 +703,40 @@ public sealed class BSShapeCollection : IDisposable lod = PhysicsScene.SculptLOD; // Mega prims usually get more detail because one can interact with shape approximations at this size. - float maxAxis = Math.Max(shapeData.Size.X, Math.Max(shapeData.Size.Y, shapeData.Size.Z)); + float maxAxis = Math.Max(size.X, Math.Max(size.Y, size.Z)); if (maxAxis > PhysicsScene.MeshMegaPrimThreshold) lod = PhysicsScene.MeshMegaPrimLOD; retLod = lod; - return pbs.GetMeshKey(shapeData.Size, lod); + return pbs.GetMeshKey(size, lod); } // For those who don't want the LOD - private System.UInt64 ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs) + private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs) { float lod; - return ComputeShapeKey(shapeData, pbs, out lod); + return ComputeShapeKey(size, pbs, out lod); } // The creation of a mesh or hull can fail if an underlying asset is not available. // There are two cases: 1) the asset is not in the cache and it needs to be fetched; - // and 2) the asset cannot be converted (like decompressing JPEG2000s). - // The first case causes the asset to be fetched. The second case just requires + // and 2) the asset cannot be converted (like failed decompression of JPEG2000s). + // The first case causes the asset to be fetched. The second case requires // us to not loop forever. // Called after creating a physical mesh or hull. If the physical shape was created, // just return. - private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs) + private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim) { // If the shape was successfully created, nothing more to do if (newShape.ptr != IntPtr.Zero) return newShape; // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset - if (pbs.SculptEntry && !prim.LastAssetBuildFailed && pbs.SculptTexture != OMV.UUID.Zero) + if (prim.BaseShape.SculptEntry && !prim.LastAssetBuildFailed && prim.BaseShape.SculptTexture != OMV.UUID.Zero) { prim.LastAssetBuildFailed = true; BSPhysObject xprim = prim; DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset,lID={1},lastFailed={2}", - LogHeader, shapeData.ID.ToString("X"), prim.LastAssetBuildFailed); + LogHeader, prim.LocalID, prim.LastAssetBuildFailed); Util.FireAndForget(delegate { RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod; @@ -745,7 +753,7 @@ public sealed class BSShapeCollection : IDisposable yprim.BaseShape.SculptData = asset.Data; // This will cause the prim to see that the filler shape is not the right // one and try again to build the object. - // No race condition with the native sphere setting since the rebuild is at taint time. + // No race condition with the normal shape setting since the rebuild is at taint time. yprim.ForceBodyShapeRebuild(false); }); @@ -757,13 +765,13 @@ public sealed class BSShapeCollection : IDisposable if (prim.LastAssetBuildFailed) { PhysicsScene.Logger.ErrorFormat("{0} Mesh failed to fetch asset. lID={1}, texture={2}", - LogHeader, shapeData.ID, pbs.SculptTexture); + LogHeader, prim.LocalID, prim.BaseShape.SculptTexture); } } // While we figure out the real problem, stick a simple native shape on the object. BulletShape fillinShape = - BuildPhysicalNativeShape(ShapeData.PhysicsShapeType.SHAPE_BOX, shapeData, ShapeData.FixedShapeKey.KEY_BOX); + BuildPhysicalNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_BOX, ShapeData.FixedShapeKey.KEY_BOX); return fillinShape; } @@ -773,7 +781,7 @@ public sealed class BSShapeCollection : IDisposable // Returns 'true' if an object was actually created. // Called at taint-time. private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletSim sim, BulletShape shape, - ShapeData shapeData, BodyDestructionCallback bodyCallback) + BodyDestructionCallback bodyCallback) { bool ret = false; @@ -803,16 +811,16 @@ public sealed class BSShapeCollection : IDisposable if (prim.IsSolid) { bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr, - shapeData.ID, shapeData.Position, shapeData.Rotation); + prim.LocalID, prim.ForcePosition, prim.ForceOrientation); 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); + prim.LocalID, prim.ForcePosition, prim.ForceOrientation); DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); } - aBody = new BulletBody(shapeData.ID, bodyPtr); + aBody = new BulletBody(prim.LocalID, bodyPtr); ReferenceBody(aBody, true); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 9b7ba03..3b6355c 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -194,6 +194,7 @@ public struct ShapeData // following defined by BulletSim SHAPE_GROUNDPLANE = 20, SHAPE_TERRAIN = 21, + SHAPE_COMPOUND = 22, }; public uint ID; public PhysicsShapeType Type; -- cgit v1.1 From f53b4e7a21f62a84e237c4ce8d2806124c3a76d2 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 1 Nov 2012 10:53:55 -0700 Subject: BulletSim: Add RawPosition and RawOrientation to BSPhysObject and rename MassRaw to RawMass. Fix BSShapeCollection to use Raw* for creating the body to eliminate exception from referencing the physical body before it has been created. --- OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | 20 +++++++++++++++----- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 16 ++++++++-------- OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs | 4 +++- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 14 ++++++++++++-- .../Physics/BulletSPlugin/BSShapeCollection.cs | 2 +- 5 files changed, 39 insertions(+), 17 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 2a634b9..9e1206a 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -97,7 +97,7 @@ public sealed class BSCharacter : BSPhysObject // set _avatarVolume and _mass based on capsule size, _density and Scale ComputeAvatarVolumeAndMass(); DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}", - LocalID, _size, Scale, _avatarDensity, _avatarVolume, MassRaw); + LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass); // do actual create at taint time PhysicsScene.TaintedObject("BSCharacter.create", delegate() @@ -141,7 +141,7 @@ public sealed class BSCharacter : BSPhysObject BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); } - UpdatePhysicalMassProperties(MassRaw); + UpdatePhysicalMassProperties(RawMass); // Make so capsule does not fall over BulletSimAPI.SetAngularFactorV2(PhysBody.ptr, OMV.Vector3.Zero); @@ -181,12 +181,12 @@ public sealed class BSCharacter : BSPhysObject ComputeAvatarScale(_size); ComputeAvatarVolumeAndMass(); DetailLog("{0},BSCharacter.setSize,call,scale={1},density={2},volume={3},mass={4}", - LocalID, Scale, _avatarDensity, _avatarVolume, MassRaw); + LocalID, Scale, _avatarDensity, _avatarVolume, RawMass); PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() { BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale); - UpdatePhysicalMassProperties(MassRaw); + UpdatePhysicalMassProperties(RawMass); }); } @@ -231,6 +231,11 @@ public sealed class BSCharacter : BSPhysObject public override void LockAngularMotion(OMV.Vector3 axis) { return; } + public override OMV.Vector3 RawPosition + { + get { return _position; } + set { _position = value; } + } public override OMV.Vector3 Position { get { // _position = BulletSimAPI.GetObjectPosition2(Scene.World.ptr, LocalID); @@ -316,7 +321,7 @@ public sealed class BSCharacter : BSPhysObject public override float Mass { get { return _mass; } } // used when we only want this prim's mass and not the linkset thing - public override float MassRaw { + public override float RawMass { get {return _mass; } } public override void UpdatePhysicalMassProperties(float physMass) @@ -405,6 +410,11 @@ public sealed class BSCharacter : BSPhysObject get { return _acceleration; } set { _acceleration = value; } } + public override OMV.Quaternion RawOrientation + { + get { return _orientation; } + set { _orientation = value; } + } public override OMV.Quaternion Orientation { get { return _orientation; } set { diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index f56851f..9e0f499 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -106,7 +106,7 @@ public abstract class BSLinkset PhysicsScene = scene; LinksetRoot = parent; m_children = new HashSet(); - m_mass = parent.MassRaw; + m_mass = parent.RawMass; } // Link to a linkset where the child knows the parent. @@ -242,14 +242,14 @@ public abstract class BSLinkset // ================================================================ protected virtual float ComputeLinksetMass() { - float mass = LinksetRoot.MassRaw; + float mass = LinksetRoot.RawMass; if (HasAnyChildren) { lock (m_linksetActivityLock) { foreach (BSPhysObject bp in m_children) { - mass += bp.MassRaw; + mass += bp.RawMass; } } } @@ -261,13 +261,13 @@ public abstract class BSLinkset OMV.Vector3 com; lock (m_linksetActivityLock) { - com = LinksetRoot.Position * LinksetRoot.MassRaw; - float totalMass = LinksetRoot.MassRaw; + com = LinksetRoot.Position * LinksetRoot.RawMass; + float totalMass = LinksetRoot.RawMass; foreach (BSPhysObject bp in m_children) { - com += bp.Position * bp.MassRaw; - totalMass += bp.MassRaw; + com += bp.Position * bp.RawMass; + totalMass += bp.RawMass; } if (totalMass != 0f) com /= totalMass; @@ -285,7 +285,7 @@ public abstract class BSLinkset foreach (BSPhysObject bp in m_children) { - com += bp.Position * bp.MassRaw; + com += bp.Position * bp.RawMass; } com /= (m_children.Count + 1); } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 7d91468..65d7f34 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -63,7 +63,7 @@ public abstract class BSPhysObject : PhysicsActor public BSLinkset Linkset { get; set; } // Return the object mass without calculating it or having side effects - public abstract float MassRaw { get; } + public abstract float RawMass { get; } // Set the raw mass but also update physical mass properties (inertia, ...) public abstract void UpdatePhysicalMassProperties(float mass); @@ -105,8 +105,10 @@ public abstract class BSPhysObject : PhysicsActor // Tell the object to clean up. public abstract void Destroy(); + public abstract OMV.Vector3 RawPosition { get; set; } public abstract OMV.Vector3 ForcePosition { get; set; } + public abstract OMV.Quaternion RawOrientation { get; set; } public abstract OMV.Quaternion ForceOrientation { get; set; } public abstract OMV.Vector3 ForceVelocity { get; set; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 8ce960d..1754be6 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -256,6 +256,11 @@ public sealed class BSPrim : BSPhysObject return; } + public override OMV.Vector3 RawPosition + { + get { return _position; } + set { _position = value; } + } public override OMV.Vector3 Position { get { if (!Linkset.IsRoot(this)) @@ -366,7 +371,7 @@ public sealed class BSPrim : BSPhysObject } // used when we only want this prim's mass and not the linkset thing - public override float MassRaw { + public override float RawMass { get { return _mass; } } // Set the physical mass to the passed mass. @@ -530,6 +535,11 @@ public sealed class BSPrim : BSPhysObject get { return _acceleration; } set { _acceleration = value; } } + public override OMV.Quaternion RawOrientation + { + get { return _orientation; } + set { _orientation = value; } + } public override OMV.Quaternion Orientation { get { if (!Linkset.IsRoot(this)) @@ -703,7 +713,7 @@ public sealed class BSPrim : BSPhysObject BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); // A dynamic object has mass - UpdatePhysicalMassProperties(MassRaw); + UpdatePhysicalMassProperties(RawMass); // Set collision detection parameters if (PhysicsScene.Params.ccdMotionThreshold > 0f) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 478924a..e131919 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -811,7 +811,7 @@ public sealed class BSShapeCollection : IDisposable if (prim.IsSolid) { bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr, - prim.LocalID, prim.ForcePosition, prim.ForceOrientation); + prim.LocalID, prim.RawPosition, prim.RawOrientation); DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); } else -- cgit v1.1 From b0eccd5044b1a20b995a62d6fb76fdd73b712f9a Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 2 Nov 2012 09:53:41 -0700 Subject: BulletSim: debugging of compound shape implementation of linksets. Add compound shape creation and freeing in shape manager. Add optional taint-time execution method and update code to use it. Add API2 linkage for more compound shape methods (get num, get/remove by index, ...) Modify perferred shape return so linkset children can have differet shapes than root. Add Position and Orientation calls to linksets so children can be moved around by the linkset by its own calculation. Allows for very general linkset implementations. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 13 +- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 19 ++- .../Physics/BulletSPlugin/BSLinksetCompound.cs | 106 ++++++++++---- .../Physics/BulletSPlugin/BSLinksetConstraints.cs | 12 ++ .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 4 +- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 52 +++---- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 12 +- .../Physics/BulletSPlugin/BSShapeCollection.cs | 152 ++++++++++++++++----- .../Physics/BulletSPlugin/BSTerrainManager.cs | 21 +-- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 15 +- 10 files changed, 274 insertions(+), 132 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 9e1206a..2a5397e 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -200,7 +200,9 @@ public sealed class BSCharacter : BSPhysObject } // I want the physics engine to make an avatar capsule public override ShapeData.PhysicsShapeType PreferredPhysicalShape - { get { return ShapeData.PhysicsShapeType.SHAPE_AVATAR; } } + { + get {return ShapeData.PhysicsShapeType.SHAPE_AVATAR; } + } public override bool Grabbed { set { _grabbed = value; } @@ -238,6 +240,7 @@ public sealed class BSCharacter : BSPhysObject } public override OMV.Vector3 Position { get { + // Don't refetch the position because this function is called a zillion times // _position = BulletSimAPI.GetObjectPosition2(Scene.World.ptr, LocalID); return _position; } @@ -304,15 +307,11 @@ public sealed class BSCharacter : BSPhysObject { // The new position value must be pushed into the physics engine but we can't // just assign to "Position" because of potential call loops. - BSScene.TaintCallback sanityOperation = delegate() + PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate() { DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); - }; - if (inTaintTime) - sanityOperation(); - else - PhysicsScene.TaintedObject("BSCharacter.PositionSanityCheck", sanityOperation); + }); ret = true; } return ret; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 9e0f499..8f973f4 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -48,7 +48,8 @@ public abstract class BSLinkset */ // at the moment, there is only one - ret = new BSLinksetConstraints(physScene, parent); + // ret = new BSLinksetConstraints(physScene, parent); + ret = new BSLinksetCompound(physScene, parent); return ret; } @@ -69,10 +70,19 @@ public abstract class BSLinkset protected object m_linksetActivityLock = new Object(); // Some linksets have a preferred physical shape. - // Returns SHAPE_UNKNOWN if there is no preference. - public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape - { get { return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; } } + // Returns SHAPE_UNKNOWN if there is no preference. Causes the correct shape to be selected. + public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) + { + return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; + } + // Linksets move around the children so the linkset might need to compute the child position + public virtual OMV.Vector3 Position(BSPhysObject member) + { return member.RawPosition; } + public virtual OMV.Quaternion Orientation(BSPhysObject member) + { return member.RawOrientation; } + // TODO: does this need to be done for Velocity and RotationalVelocityy? + // We keep the prim's mass in the linkset structure since it could be dependent on other prims protected float m_mass; public float LinksetMass @@ -177,7 +187,6 @@ public abstract class BSLinkset } // Perform an action on each member of the linkset including root prim. - // The action is performed only on the objects that are physically in the linkset. // Depends on the action on whether this should be done at taint time. public delegate bool ForEachMemberAction(BSPhysObject obj); public virtual bool ForEachMember(ForEachMemberAction action) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs index 638fae1..8b97ebb 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs @@ -41,18 +41,31 @@ public sealed class BSLinksetCompound : BSLinkset base.Initialize(scene, parent); } + // For compound implimented linksets, if there are children, use compound shape for the root. + public override ShapeData.PhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) + { + ShapeData.PhysicsShapeType ret = ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; + if (IsRoot(requestor) && HasAnyChildren) + { + ret = ShapeData.PhysicsShapeType.SHAPE_COMPOUND; + } + // DetailLog("{0},BSLinksetCompound.PreferredPhysicalShape,call,shape={1}", LinksetRoot.LocalID, ret); + return ret; + } + // 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) { + DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,requestor={1}", LinksetRoot.LocalID, requestor.LocalID); // Queue to happen after all the other taint processing - PhysicsScene.PostTaintObject("BSLinksetcompound.Refresh", requestor.LocalID, delegate() - { - if (HasAnyChildren && IsRoot(requestor)) - RecomputeLinksetCompound(); - }); + PhysicsScene.PostTaintObject("BSLinksetCompound.Refresh", requestor.LocalID, delegate() + { + if (IsRoot(requestor) && HasAnyChildren) + RecomputeLinksetCompound(); + }); } // The object is going dynamic (physical). Do any setup necessary @@ -63,8 +76,17 @@ public sealed class BSLinksetCompound : BSLinkset // Called at taint-time! public override bool MakeDynamic(BSPhysObject child) { - // What is done for each object in BSPrim is what we want. - return false; + bool ret = false; + DetailLog("{0},BSLinksetCompound.MakeDynamic,call,isChild={1}", child.LocalID, HasChild(child)); + if (HasChild(child)) + { + // Physical children are removed from the world as the shape ofthe root compound + // shape takes over. + BulletSimAPI.AddToCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); + BulletSimAPI.ForceActivationState2(child.PhysBody.ptr, ActivationState.DISABLE_SIMULATION); + ret = true; + } + return ret; } // The object is going static (non-physical). Do any setup necessary for a static linkset. @@ -74,8 +96,17 @@ public sealed class BSLinksetCompound : BSLinkset // Called at taint-time! public override bool MakeStatic(BSPhysObject child) { - // What is done for each object in BSPrim is what we want. - return false; + bool ret = false; + DetailLog("{0},BSLinksetCompound.MakeStatic,call,hasChild={1}", child.LocalID, HasChild(child)); + if (HasChild(child)) + { + // The non-physical children can come back to life. + BulletSimAPI.RemoveFromCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); + // Don't force activation so setting of DISABLE_SIMULATION can stay. + BulletSimAPI.Activate2(child.PhysBody.ptr, false); + ret = true; + } + return ret; } // Called at taint-time!! @@ -84,20 +115,35 @@ public sealed class BSLinksetCompound : BSLinkset // Nothing to do for constraints on property updates } + // The children move around in relationship to the root. + // Just grab the current values of wherever it is right now. + public override OMV.Vector3 Position(BSPhysObject member) + { + return BulletSimAPI.GetPosition2(member.PhysBody.ptr); + } + + public override OMV.Quaternion Orientation(BSPhysObject member) + { + return BulletSimAPI.GetOrientation2(member.PhysBody.ptr); + } + // Routine called when rebuilding the body of some member of the linkset. - // Destroy all the constraints have have been made to root and set - // up to rebuild the constraints before the next simulation step. + // Since we don't keep in-physical world relationships, do nothing unless it's a child changing. // Returns 'true' of something was actually removed and would need restoring // Called at taint-time!! public override bool RemoveBodyDependencies(BSPrim child) { bool ret = false; - DetailLog("{0},BSLinksetcompound.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", - child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X")); + DetailLog("{0},BSLinksetCompound.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2},isRoot={3}", + child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), IsRoot(child)); - // Cause the current shape to be freed and the new one to be built. - Refresh(LinksetRoot); + if (!IsRoot(child)) + { + // Cause the current shape to be freed and the new one to be built. + Refresh(LinksetRoot); + ret = true; + } return ret; } @@ -139,13 +185,19 @@ public sealed class BSLinksetCompound : BSLinkset LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), child.LocalID, child.PhysBody.ptr.ToString("X")); - // See that the linkset parameters are recomputed at the end of the taint time. - Refresh(LinksetRoot); - } - else - { - // Non-fatal occurance. - // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader); + // Cause the child's body to be rebuilt and thus restored to normal operation + child.ForceBodyShapeRebuild(false); + + if (!HasAnyChildren) + { + // The linkset is now empty. The root needs rebuilding. + LinksetRoot.ForceBodyShapeRebuild(false); + } + else + { + // Schedule a rebuild of the linkset before the next simulation tick. + Refresh(LinksetRoot); + } } return; } @@ -158,16 +210,18 @@ public sealed class BSLinksetCompound : BSLinkset // Called at taint time!! private void RecomputeLinksetCompound() { - // Release the existing shape - PhysicsScene.Shapes.DereferenceShape(LinksetRoot.PhysShape, true, null); - + DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},numChildren={2}", + LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), NumberOfChildren); + + LinksetRoot.ForceBodyShapeRebuild(true); + float linksetMass = LinksetMass; LinksetRoot.UpdatePhysicalMassProperties(linksetMass); // DEBUG: see of inter-linkset collisions are causing problems // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); - DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,set,rBody={1},linksetMass={2}", + DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,end,rBody={1},linksetMass={2}", LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), linksetMass); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs index 65aed77..67a59ef 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs @@ -84,6 +84,18 @@ public sealed class BSLinksetConstraints : BSLinkset // Nothing to do for constraints on property updates } + // The children of the linkset are moved around by the constraints. + // Just grab the current values of wherever it is right now. + public override OMV.Vector3 Position(BSPhysObject member) + { + return BulletSimAPI.GetPosition2(member.PhysBody.ptr); + } + + public override OMV.Quaternion Orientation(BSPhysObject member) + { + return BulletSimAPI.GetOrientation2(member.PhysBody.ptr); + } + // Routine called when rebuilding the body of some member of the linkset. // Destroy all the constraints have have been made to root and set // up to rebuild the constraints before the next simulation step. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 65d7f34..7127aaf 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -81,7 +81,9 @@ public abstract class BSPhysObject : PhysicsActor // Some types of objects have preferred physical representations. // Returns SHAPE_UNKNOWN if there is no preference. public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape - { get { return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; } } + { + get { return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; } + } // When the physical properties are updated, an EntityProperty holds the update values. // Keep the current and last EntityProperties to enable computation of differences diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 1754be6..af403aa 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -173,20 +173,16 @@ public sealed class BSPrim : BSPhysObject } // Whatever the linkset wants is what I want. public override ShapeData.PhysicsShapeType PreferredPhysicalShape - { get { return Linkset.PreferredPhysicalShape; } } + { get { return Linkset.PreferredPhysicalShape(this); } } public override bool ForceBodyShapeRebuild(bool inTaintTime) { LastAssetBuildFailed = false; - BSScene.TaintCallback rebuildOperation = delegate() + PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ForceBodyShapeRebuild", delegate() { _mass = CalculateMass(); // changing the shape changes the mass CreateGeomAndObject(true); - }; - if (inTaintTime) - rebuildOperation(); - else - PhysicsScene.TaintedObject("BSPrim.ForceBodyShapeRebuild", rebuildOperation); + }); return true; } public override bool Grabbed { @@ -263,9 +259,9 @@ public sealed class BSPrim : BSPhysObject } public override OMV.Vector3 Position { get { + // child prims move around based on their parent. Need to get the latest location if (!Linkset.IsRoot(this)) - // child prims move around based on their parent. Need to get the latest location - _position = BulletSimAPI.GetPosition2(PhysBody.ptr); + _position = Linkset.Position(this); // don't do the GetObjectPosition for root elements because this function is called a zillion times // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); @@ -344,16 +340,11 @@ public sealed class BSPrim : BSPhysObject { // The new position value must be pushed into the physics engine but we can't // just assign to "Position" because of potential call loops. - BSScene.TaintCallback sanityOperation = delegate() + PhysicsScene.TaintedObject(inTaintTime, "BSPrim.PositionSanityCheck", delegate() { DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); ForcePosition = _position; - }; - if (inTaintTime) - sanityOperation(); - else - PhysicsScene.TaintedObject("BSPrim.PositionSanityCheck", sanityOperation); - + }); ret = true; } return ret; @@ -542,10 +533,10 @@ public sealed class BSPrim : BSPhysObject } public override OMV.Quaternion Orientation { get { + // Children move around because tied to parent. Get a fresh value. if (!Linkset.IsRoot(this)) { - // Children move around because tied to parent. Get a fresh value. - _orientation = BulletSimAPI.GetOrientation2(PhysBody.ptr); + _orientation = Linkset.Orientation(this); } return _orientation; } @@ -946,7 +937,7 @@ public sealed class BSPrim : BSPhysObject m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); return; } - BSScene.TaintCallback addForceOperation = delegate() + PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate() { OMV.Vector3 fSum = OMV.Vector3.Zero; lock (m_accumulatedForces) @@ -961,11 +952,7 @@ public sealed class BSPrim : BSPhysObject DetailLog("{0},BSPrim.AddForce,taint,force={1}", LocalID, fSum); if (fSum != OMV.Vector3.Zero) BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, fSum); - }; - if (inTaintTime) - addForceOperation(); - else - PhysicsScene.TaintedObject("BSPrim.AddForce", addForceOperation); + }); } private List m_accumulatedAngularForces = new List(); @@ -985,7 +972,7 @@ public sealed class BSPrim : BSPhysObject m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); return; } - BSScene.TaintCallback addAngularForceOperation = delegate() + PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddAngularForce", delegate() { OMV.Vector3 fSum = OMV.Vector3.Zero; lock (m_accumulatedAngularForces) @@ -1003,26 +990,19 @@ public sealed class BSPrim : BSPhysObject BulletSimAPI.ApplyTorque2(PhysBody.ptr, fSum); _torque = fSum; } - }; - if (inTaintTime) - addAngularForceOperation(); - else - PhysicsScene.TaintedObject("BSPrim.AddAngularForce", addAngularForceOperation); + }); } // A torque impulse. public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime) { OMV.Vector3 applyImpulse = impulse; - BSScene.TaintCallback applyTorqueImpulseOperation = delegate() + PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate() { DetailLog("{0},BSPrim.ApplyTorqueImpulse,taint,tImpulse={1}", LocalID, applyImpulse); BulletSimAPI.ApplyTorqueImpulse2(PhysBody.ptr, applyImpulse); - }; - if (inTaintTime) - applyTorqueImpulseOperation(); - else - PhysicsScene.TaintedObject("BSPrim.ApplyTorqueImpulse", applyTorqueImpulseOperation); + }); } + public override void SetMomentum(OMV.Vector3 momentum) { // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index cc5dbb2..dcfcb83 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -692,6 +692,16 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters return; } + // Sometimes a potentially tainted operation can be used in and out of taint time. + // This routine executes the command immediately if in taint-time otherwise it is queued. + public void TaintedObject(bool inTaintTime, string ident, TaintCallback callback) + { + if (inTaintTime) + callback(); + else + TaintedObject(ident, callback); + } + // When someone tries to change a property on a BSPrim or BSCharacter, the object queues // a callback into itself to do the actual property change. That callback is called // here just before the physics engine is called to step the simulation. @@ -1438,7 +1448,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters { PhysicsLogging.Write(msg, args); // Add the Flush() if debugging crashes to get all the messages written out. - // PhysicsLogging.Flush(); + PhysicsLogging.Flush(); } // Used to fill in the LocalID when there isn't one. It's the correct number of characters. public const string DetailLogZero = "0000000000"; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index e131919..107befe 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -122,18 +122,14 @@ public sealed class BSShapeCollection : IDisposable lock (m_collectionActivityLock) { DetailLog("{0},BSShapeCollection.ReferenceBody,newBody", body.ID, body); - BSScene.TaintCallback createOperation = delegate() + PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.ReferenceBody", delegate() { 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); + }); } } @@ -146,7 +142,7 @@ public sealed class BSShapeCollection : IDisposable lock (m_collectionActivityLock) { - BSScene.TaintCallback removeOperation = delegate() + PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceBody", delegate() { DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}, inTaintTime={2}", body.ID, body.ptr.ToString("X"), inTaintTime); @@ -159,12 +155,7 @@ public sealed class BSShapeCollection : IDisposable // 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); + }); } } @@ -238,7 +229,7 @@ public sealed class BSShapeCollection : IDisposable if (shape.ptr == IntPtr.Zero) return; - BSScene.TaintCallback dereferenceOperation = delegate() + PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceShape", delegate() { if (shape.ptr != IntPtr.Zero) { @@ -270,18 +261,7 @@ public sealed class BSShapeCollection : IDisposable } } } - }; - if (inTaintTime) - { - lock (m_collectionActivityLock) - { - dereferenceOperation(); - } - } - else - { - PhysicsScene.TaintedObject("BSShapeCollection.DereferenceShape", dereferenceOperation); - } + }); } // Count down the reference count for a mesh shape @@ -311,7 +291,10 @@ public sealed class BSShapeCollection : IDisposable { hullDesc.referenceCount--; // TODO: release the Bullet storage (aging old entries?) + + // Tell upper layers that, if they have dependencies on this shape, this link is going away if (shapeCallback != null) shapeCallback(shape); + hullDesc.lastReferenced = System.DateTime.Now; Hulls[shape.shapeKey] = hullDesc; DetailLog("{0},BSShapeCollection.DereferenceHull,key={1},refCnt={2}", @@ -320,10 +303,48 @@ public sealed class BSShapeCollection : IDisposable } // Remove a reference to a compound shape. + // Taking a compound shape apart is a little tricky because if you just delete the + // physical object, it will free all the underlying children. We can't do that because + // they could be shared. So, this removes each of the children from the compound and + // dereferences them separately before destroying the compound collision object itself. // Called at taint-time. private void DereferenceCompound(BulletShape shape, ShapeDestructionCallback shapeCallback) { - // Compound shape is made of a bunch of meshes and natives. + if (!BulletSimAPI.IsCompound2(shape.ptr)) + { + // Failed the sanity check!! + PhysicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}", + LogHeader, shape.type, shape.ptr.ToString("X")); + DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}", + BSScene.DetailLogZero, shape.type, shape.ptr.ToString("X")); + return; + } + int numChildren = BulletSimAPI.GetNumberOfCompoundChildren2(shape.ptr); + for (int ii = 0; ii < numChildren; ii++) + { + IntPtr childShape = BulletSimAPI.RemoveChildShapeFromCompoundShapeIndex2(shape.ptr, ii); + DereferenceAnonCollisionShape(childShape); + } + BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); + } + + // Sometimes we have a pointer to a collision shape but don't know what type it is. + // Figure out type and call the correct dereference routine. + // This is coming from a compound shape that we created so we know it is either native or mesh. + // Called at taint-time. + private void DereferenceAnonCollisionShape(IntPtr cShape) + { + BulletShape shapeInfo = new BulletShape(cShape, ShapeData.PhysicsShapeType.SHAPE_MESH); + if (BulletSimAPI.IsCompound2(cShape)) + shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_COMPOUND; + + if (BulletSimAPI.IsNativeShape2(cShape)) + { + shapeInfo.isNativeShape = true; + shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter) + } + + DereferenceShape(shapeInfo, true, null); } // Create the geometry information in Bullet for later use. @@ -338,10 +359,8 @@ public sealed class BSShapeCollection : IDisposable { bool ret = false; bool haveShape = false; - bool nativeShapePossible = true; - PrimitiveBaseShape pbs = prim.BaseShape; - if (prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_AVATAR) + if (!haveShape && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_AVATAR) { // an avatar capsule is close to a native shape (it is not shared) ret = GetReferenceToNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_AVATAR, @@ -350,6 +369,31 @@ public sealed class BSShapeCollection : IDisposable ret = true; haveShape = true; } + + // Compound shapes are handled special as they are rebuilt from scratch. + // This isn't too great a hardship since most of the child shapes will already been created. + if (!haveShape && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_COMPOUND) + { + ret = GetReferenceToCompoundShape(prim, shapeCallback); + DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape); + haveShape = true; + } + + if (!haveShape) + { + ret = CreateGeomNonSpecial(forceRebuild, prim, shapeCallback); + } + + return ret; + } + + private bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback) + { + bool ret = false; + bool haveShape = false; + bool nativeShapePossible = true; + PrimitiveBaseShape pbs = prim.BaseShape; + // If the prim attributes are simple, this could be a simple Bullet native shape if (!haveShape && pbs != null @@ -363,6 +407,7 @@ public sealed class BSShapeCollection : IDisposable && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) ) { + // It doesn't look like Bullet scales spheres so make sure the scales are all equal if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z) { @@ -378,7 +423,7 @@ public sealed class BSShapeCollection : IDisposable prim.LocalID, forceRebuild, prim.PhysShape); } } - if (pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) + if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) { haveShape = true; if (forceRebuild @@ -393,9 +438,10 @@ public sealed class BSShapeCollection : IDisposable } } } + // If a simple shape is not happening, create a mesh and possibly a hull. // Note that if it's a native shape, the check for physical/non-physical is not - // made. Native shapes are best used in either case. + // made. Native shapes work in either case. if (!haveShape && pbs != null) { if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects) @@ -487,7 +533,7 @@ public sealed class BSShapeCollection : IDisposable if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH) return false; - DetailLog("{0},BSShapeCollection.CreateGeomMesh,create,oldKey={1},newKey={2}", + DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2}", prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X")); // Since we're recreating new, get rid of the reference to the previous shape @@ -535,7 +581,7 @@ public sealed class BSShapeCollection : IDisposable verticesAsFloats[vi++] = vv.Z; } - // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", + // m_log.DebugFormat("{0}: BSShapeCollection.CreatePhysicalMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count); meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, @@ -561,7 +607,7 @@ public sealed class BSShapeCollection : IDisposable if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL) return false; - DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}", + DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}", prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X")); // Remove usage of the previous shape. @@ -693,6 +739,42 @@ public sealed class BSShapeCollection : IDisposable return; } + // Compound shapes are always built from scratch. + // This shouldn't be to bad since most of the parts will be meshes that had been built previously. + private bool GetReferenceToCompoundShape(BSPhysObject prim, ShapeDestructionCallback shapeCallback) + { + BulletShape cShape = new BulletShape( + BulletSimAPI.CreateCompoundShape2(PhysicsScene.World.ptr), ShapeData.PhysicsShapeType.SHAPE_COMPOUND); + + // The prim's linkset is the source of the children. + // TODO: there is too much knowledge here about the internals of linksets and too much + // dependency on the relationship of compound shapes and linksets (what if we want to use + // compound shapes for something else?). Think through this and clean up so the + // appropriate knowledge is used at the correct software levels. + + // Recreate the geometry of the root prim (might have been a linkset root in the past) + CreateGeomNonSpecial(true, prim, null); + + BSPhysObject rootPrim = prim.Linkset.LinksetRoot; + + prim.Linkset.ForEachMember(delegate(BSPhysObject cPrim) + { + OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(rootPrim.RawOrientation); + OMV.Vector3 displacementPos = (cPrim.RawPosition - rootPrim.RawPosition) * invRootOrientation; + OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation; + + DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}", + prim.LocalID, cPrim.LocalID, cPrim.PhysShape.ptr.ToString("X"), displacementPos, displacementRot); + + BulletSimAPI.AddChildShapeToCompoundShape2(cShape.ptr, cPrim.PhysShape.ptr, displacementPos, displacementRot); + return false; + }); + + prim.PhysShape = cShape; + + return true; + } + // Create a hash of all the shape parameters to be used as a key // for this particular shape. private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index 11298fe..7c34af2 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -238,7 +238,7 @@ public sealed class BSTerrainManager DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,call,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}", BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY); - BSScene.TaintCallback rebuildOperation = delegate() + PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateOrCreateTerrain:UpdateExisting", delegate() { if (MegaRegionParentPhysicsScene != null) { @@ -337,14 +337,7 @@ public sealed class BSTerrainManager BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION); m_terrainModified = true; - }; - - // There is the option to do the changes now (we're already in 'taint time'), or - // to do the Bullet operations later. - if (inTaintTime) - rebuildOperation(); - else - PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:UpdateExisting", rebuildOperation); + }); } else { @@ -364,7 +357,7 @@ public sealed class BSTerrainManager BSScene.DetailLogZero, newTerrainID, minCoords, minCoords); // Code that must happen at taint-time - BSScene.TaintCallback createOperation = delegate() + PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateOrCreateTerrain:NewTerrain", delegate() { DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,taint,baseX={1},baseY={2}", BSScene.DetailLogZero, minCoords.X, minCoords.Y); // Create a new mapInfo that will be filled with the new info @@ -377,13 +370,7 @@ public sealed class BSTerrainManager UpdateOrCreateTerrain(newTerrainID, heightMap, minCoords, maxCoords, true); m_terrainModified = true; - }; - - // If already in taint-time, just call Bullet. Otherwise queue the operations for the safe time. - if (inTaintTime) - createOperation(); - else - PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:NewTerrain", createOperation); + }); } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 3b6355c..143b8be 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -399,8 +399,6 @@ public enum CollisionFilterGroups : uint }; - - // CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0 // ERP controls amount of correction per tick. Usable range=0.1..0.8. Default=0.2. public enum ConstraintParams : int @@ -618,10 +616,19 @@ public static extern IntPtr BuildCapsuleShape2(IntPtr world, float radius, float public static extern IntPtr CreateCompoundShape2(IntPtr sim); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void AddChildToCompoundShape2(IntPtr cShape, IntPtr addShape, Vector3 pos, Quaternion rot); +public static extern int GetNumberOfCompoundChildren2(IntPtr cShape); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void AddChildShapeToCompoundShape2(IntPtr cShape, IntPtr addShape, Vector3 pos, Quaternion rot); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern IntPtr GetChildShapeFromCompoundShapeIndex2(IntPtr cShape, int indx); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern IntPtr RemoveChildShapeFromCompoundShapeIndex2(IntPtr cShape, int indx); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void RemoveChildFromCompoundShape2(IntPtr cShape, IntPtr removeShape); +public static extern void RemoveChildShapeFromCompoundShape2(IntPtr cShape, IntPtr removeShape); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr DuplicateCollisionShape2(IntPtr sim, IntPtr srcShape, uint id); -- cgit v1.1 From 1dc23b2b9713f4099534ae0d08c2caf5c8b036b4 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 2 Nov 2012 10:35:12 -0700 Subject: BulletSim: parameterize selection of linkset implementation --- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 28 ++++++++++++++-------- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 5 ++++ .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 1 + 3 files changed, 24 insertions(+), 10 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 8f973f4..3a92f93 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -36,21 +36,29 @@ public abstract class BSLinkset { // private static string LogHeader = "[BULLETSIM LINKSET]"; + public enum LinksetImplementation + { + Constraint = 0, // linkset tied together with constraints + Compound = 1, // linkset tied together as a compound object + Manual = 2 // linkset tied together manually (code moves all the pieces) + } // Create the correct type of linkset for this child public static BSLinkset Factory(BSScene physScene, BSPhysObject parent) { BSLinkset ret = null; - /* - if (parent.IsPhysical) - ret = new BSLinksetConstraints(physScene, parent); - else - ret = new BSLinksetManual(physScene, parent); - */ - - // at the moment, there is only one - // ret = new BSLinksetConstraints(physScene, parent); - ret = new BSLinksetCompound(physScene, parent); + switch ((int)physScene.Params.linksetImplementation) + { + case (int)LinksetImplementation.Compound: + ret = new BSLinksetCompound(physScene, parent); + break; + case (int)LinksetImplementation.Manual: + // ret = new BSLinksetManual(physScene, parent); + break; + default: + ret = new BSLinksetConstraints(physScene, parent); + break; + } return ret; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index dcfcb83..13aa860 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -1214,6 +1214,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters (s) => { return s.m_params[0].numberOfSolverIterations; }, (s,p,l,v) => { s.m_params[0].numberOfSolverIterations = v; } ), + new ParameterDefn("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound)", + (float)BSLinkset.LinksetImplementation.Constraint, + (s,cf,p,v) => { s.m_params[0].linksetImplementation = cf.GetFloat(p,v); }, + (s) => { return s.m_params[0].linksetImplementation; }, + (s,p,l,v) => { s.m_params[0].linksetImplementation = v; } ), new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.", ConfigurationParameters.numericFalse, (s,cf,p,v) => { s.m_params[0].linkConstraintUseFrameOffset = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 143b8be..ac6d2b2 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -300,6 +300,7 @@ public struct ConfigurationParameters public float shouldEnableFrictionCaching; public float numberOfSolverIterations; + public float linksetImplementation; public float linkConstraintUseFrameOffset; public float linkConstraintEnableTransMotor; public float linkConstraintTransMotorMaxVel; -- cgit v1.1 From 498ea76e637961d8b4e3d39b758f7f2dea2fe998 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 2 Nov 2012 17:22:34 -0700 Subject: BulletSim: Move construction of compound linkset from ShapeCollection into LinksetCompound where it should be. Create meshes for native shapes when part of a compound linkset because scale is currently per object and not per collision shape. Don't schedule a LinksetCompound refresh if just changing properties. --- .../Physics/BulletSPlugin/BSLinksetCompound.cs | 72 ++++++++++++++---- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 24 +++++- .../Physics/BulletSPlugin/BSShapeCollection.cs | 85 +++++++++++----------- 3 files changed, 120 insertions(+), 61 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs index 8b97ebb..adf4aff 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs @@ -34,7 +34,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin { public sealed class BSLinksetCompound : BSLinkset { - // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]"; + private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]"; public BSLinksetCompound(BSScene scene, BSPhysObject parent) { @@ -59,6 +59,12 @@ public sealed class BSLinksetCompound : BSLinkset // refresh will happen once after all the other taints are applied. public override void Refresh(BSPhysObject requestor) { + // External request for Refresh (from BSPrim) is not necessary + // InternalRefresh(requestor); + } + + private void InternalRefresh(BSPhysObject requestor) + { DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,requestor={1}", LinksetRoot.LocalID, requestor.LocalID); // Queue to happen after all the other taint processing PhysicsScene.PostTaintObject("BSLinksetCompound.Refresh", requestor.LocalID, delegate() @@ -135,13 +141,13 @@ public sealed class BSLinksetCompound : BSLinkset { bool ret = false; - DetailLog("{0},BSLinksetCompound.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2},isRoot={3}", - child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), IsRoot(child)); + DetailLog("{0},BSLinksetCompound.RemoveBodyDependencies,refreshIfChild,rID={1},rBody={2},isRoot={3}", + child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), IsRoot(child)); if (!IsRoot(child)) { // Cause the current shape to be freed and the new one to be built. - Refresh(LinksetRoot); + InternalRefresh(LinksetRoot); ret = true; } @@ -169,7 +175,7 @@ public sealed class BSLinksetCompound : BSLinkset DetailLog("{0},BSLinksetCompound.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); // Cause constraints and assorted properties to be recomputed before the next simulation step. - Refresh(LinksetRoot); + InternalRefresh(LinksetRoot); } return; } @@ -196,34 +202,68 @@ public sealed class BSLinksetCompound : BSLinkset else { // Schedule a rebuild of the linkset before the next simulation tick. - Refresh(LinksetRoot); + InternalRefresh(LinksetRoot); } } return; } - - // Call each of the constraints that make up this linkset and recompute the - // various transforms and variables. Create constraints of not created yet. - // Called before the simulation step to make sure the constraint based linkset + // Called before the simulation step to make sure the compound based linkset // is all initialized. + // Constraint linksets are rebuilt every time. + // Note that this works for rebuilding just the root after a linkset is taken apart. // Called at taint time!! private void RecomputeLinksetCompound() { - DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},numChildren={2}", - LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), NumberOfChildren); - + // 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); + + ForEachMember(delegate(BSPhysObject cPrim) + { + if (!IsRoot(cPrim)) + { + OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation); + OMV.Vector3 displacementPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation; + OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation; + + DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}", + LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, displacementPos, displacementRot); + + if (cPrim.PhysShape.isNativeShape) + { + // Native shapes are not shared so we need to create a new one. + // A mesh or hull is created because scale is not available on a native shape. + // (TODO: Bullet does have a btScaledCollisionShape. Can that be used?) + BulletShape saveShape = cPrim.PhysShape; + PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null); + BulletShape newShape = cPrim.PhysShape; + cPrim.PhysShape = saveShape; + BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, newShape.ptr, displacementPos, displacementRot); + } + else + { + // For the shared shapes (meshes and hulls) just use the shape in the child + 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, displacementPos, displacementRot); + } + } + return false; + }); + + float linksetMass = LinksetMass; LinksetRoot.UpdatePhysicalMassProperties(linksetMass); // DEBUG: see of inter-linkset collisions are causing problems // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); - DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,end,rBody={1},linksetMass={2}", - LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), linksetMass); - } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 13aa860..de35359 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -116,6 +116,10 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters // True if initialized and ready to do simulation steps private bool m_initialized = false; + // Flag which is true when processing taints. + // Not guaranteed to be correct all the time (don't depend on this) but good for debugging. + public bool InTaintTime { get; private set; } + // Pinned memory used to pass step information between managed and unmanaged private int m_maxCollisionsPerFrame; private CollisionDesc[] m_collisionArray; @@ -270,6 +274,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters TerrainManager = new BSTerrainManager(this); TerrainManager.CreateInitialGroundPlaneAndTerrain(); + m_log.WarnFormat("{0} Linksets implemented with {1}", LogHeader, (BSLinkset.LinksetImplementation)Params.linksetImplementation); + + InTaintTime = false; m_initialized = true; } @@ -707,8 +714,10 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters // here just before the physics engine is called to step the simulation. public void ProcessTaints() { + InTaintTime = true; ProcessRegularTaints(); ProcessPostTaintTaints(); + InTaintTime = false; } private void ProcessRegularTaints() @@ -851,6 +860,17 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters } } + public bool AssertInTaintTime(string whereFrom) + { + if (!InTaintTime) + { + DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom); + m_log.ErrorFormat("{0} NOT IN TAINT TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom); + Util.PrintCallStack(); + } + return InTaintTime; + } + #endregion // Taints #region Vehicles @@ -1214,8 +1234,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters (s) => { return s.m_params[0].numberOfSolverIterations; }, (s,p,l,v) => { s.m_params[0].numberOfSolverIterations = v; } ), - new ParameterDefn("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound)", - (float)BSLinkset.LinksetImplementation.Constraint, + new ParameterDefn("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)", + (float)BSLinkset.LinksetImplementation.Compound, (s,cf,p,v) => { s.m_params[0].linksetImplementation = cf.GetFloat(p,v); }, (s) => { return s.m_params[0].linksetImplementation; }, (s,p,l,v) => { s.m_params[0].linksetImplementation = v; } ), diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 107befe..662b19d 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -92,6 +92,8 @@ public sealed class BSShapeCollection : IDisposable public bool GetBodyAndShape(bool forceRebuild, BulletSim 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 @@ -121,7 +123,7 @@ public sealed class BSShapeCollection : IDisposable { lock (m_collectionActivityLock) { - DetailLog("{0},BSShapeCollection.ReferenceBody,newBody", body.ID, body); + DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body); PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.ReferenceBody", delegate() { if (!BulletSimAPI.IsInWorld2(body.ptr)) @@ -165,7 +167,7 @@ public sealed class BSShapeCollection : IDisposable // Meshes and hulls for the same shape have the same hash key. // NOTE that native shapes are not added to the mesh list or removed. // Returns 'true' if this is the initial reference to the shape. Otherwise reused. - private bool ReferenceShape(BulletShape shape) + public bool ReferenceShape(BulletShape shape) { bool ret = false; switch (shape.type) @@ -276,8 +278,8 @@ public sealed class BSShapeCollection : IDisposable if (shapeCallback != null) shapeCallback(shape); meshDesc.lastReferenced = System.DateTime.Now; Meshes[shape.shapeKey] = meshDesc; - DetailLog("{0},BSShapeCollection.DereferenceMesh,key={1},refCnt={2}", - BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); + DetailLog("{0},BSShapeCollection.DereferenceMesh,shape={1},refCnt={2}", + BSScene.DetailLogZero, shape, meshDesc.referenceCount); } } @@ -297,8 +299,8 @@ public sealed class BSShapeCollection : IDisposable hullDesc.lastReferenced = System.DateTime.Now; Hulls[shape.shapeKey] = hullDesc; - DetailLog("{0},BSShapeCollection.DereferenceHull,key={1},refCnt={2}", - BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); + DetailLog("{0},BSShapeCollection.DereferenceHull,shape={1},refCnt={2}", + BSScene.DetailLogZero, shape, hullDesc.referenceCount); } } @@ -319,8 +321,11 @@ public sealed class BSShapeCollection : IDisposable BSScene.DetailLogZero, shape.type, shape.ptr.ToString("X")); return; } + int numChildren = BulletSimAPI.GetNumberOfCompoundChildren2(shape.ptr); - for (int ii = 0; ii < numChildren; ii++) + DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}", BSScene.DetailLogZero, shape, numChildren); + + for (int ii = numChildren - 1; ii >= 0; ii--) { IntPtr childShape = BulletSimAPI.RemoveChildShapeFromCompoundShapeIndex2(shape.ptr, ii); DereferenceAnonCollisionShape(childShape); @@ -343,6 +348,7 @@ public sealed class BSShapeCollection : IDisposable shapeInfo.isNativeShape = true; shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter) } + DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo); DereferenceShape(shapeInfo, true, null); } @@ -440,23 +446,32 @@ public sealed class BSShapeCollection : IDisposable } // If a simple shape is not happening, create a mesh and possibly a hull. + if (!haveShape && pbs != null) + { + ret = CreateGeomMeshOrHull(prim, shapeCallback); + } + + return ret; + } + + public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback) + { + + bool ret = false; // Note that if it's a native shape, the check for physical/non-physical is not // made. Native shapes work in either case. - if (!haveShape && pbs != null) + if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects) { - if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects) - { - // Update prim.BSShape to reference a hull of this shape. - ret = GetReferenceToHull(prim,shapeCallback); - DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}", - prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); - } - else - { - ret = GetReferenceToMesh(prim, shapeCallback); - DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}", - prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); - } + // Update prim.BSShape to reference a hull of this shape. + ret = GetReferenceToHull(prim,shapeCallback); + DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}", + prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); + } + else + { + ret = GetReferenceToMesh(prim, shapeCallback); + DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}", + prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); } return ret; } @@ -743,32 +758,16 @@ public sealed class BSShapeCollection : IDisposable // This shouldn't be to bad since most of the parts will be meshes that had been built previously. private bool GetReferenceToCompoundShape(BSPhysObject prim, ShapeDestructionCallback shapeCallback) { + // Remove reference to the old shape + // Don't need to do this as the shape is freed when we create the new root shape below. + // DereferenceShape(prim.PhysShape, true, shapeCallback); + BulletShape cShape = new BulletShape( BulletSimAPI.CreateCompoundShape2(PhysicsScene.World.ptr), ShapeData.PhysicsShapeType.SHAPE_COMPOUND); - // The prim's linkset is the source of the children. - // TODO: there is too much knowledge here about the internals of linksets and too much - // dependency on the relationship of compound shapes and linksets (what if we want to use - // compound shapes for something else?). Think through this and clean up so the - // appropriate knowledge is used at the correct software levels. - - // Recreate the geometry of the root prim (might have been a linkset root in the past) + // Create the shape for the root prim and add it to the compound shape CreateGeomNonSpecial(true, prim, null); - - BSPhysObject rootPrim = prim.Linkset.LinksetRoot; - - prim.Linkset.ForEachMember(delegate(BSPhysObject cPrim) - { - OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(rootPrim.RawOrientation); - OMV.Vector3 displacementPos = (cPrim.RawPosition - rootPrim.RawPosition) * invRootOrientation; - OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation; - - DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}", - prim.LocalID, cPrim.LocalID, cPrim.PhysShape.ptr.ToString("X"), displacementPos, displacementRot); - - BulletSimAPI.AddChildShapeToCompoundShape2(cShape.ptr, cPrim.PhysShape.ptr, displacementPos, displacementRot); - return false; - }); + BulletSimAPI.AddChildShapeToCompoundShape2(cShape.ptr, prim.PhysShape.ptr, OMV.Vector3.Zero, OMV.Quaternion.Identity); prim.PhysShape = cShape; -- cgit v1.1 From 894bb4893b8bb269f8561737e4603a9b31183f2c Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sat, 3 Nov 2012 18:26:00 -0700 Subject: BulletSim: search the mesh and hull lists to find shapes if type is not known. This makes sure the correct accounting is done for the particular shape. --- .../Physics/BulletSPlugin/BSLinksetCompound.cs | 10 +- .../Physics/BulletSPlugin/BSLinksetConstraints.cs | 2 +- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 2 +- .../Physics/BulletSPlugin/BSShapeCollection.cs | 102 ++++++++++++++++++--- 4 files changed, 96 insertions(+), 20 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs index adf4aff..6e68695 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs @@ -134,7 +134,7 @@ public sealed class BSLinksetCompound : BSLinkset } // Routine called when rebuilding the body of some member of the linkset. - // Since we don't keep in-physical world relationships, do nothing unless it's a child changing. + // Since we don't keep in world relationships, do nothing unless it's a child changing. // Returns 'true' of something was actually removed and would need restoring // Called at taint-time!! public override bool RemoveBodyDependencies(BSPrim child) @@ -221,10 +221,12 @@ public sealed class BSLinksetCompound : BSLinkset 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) { 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; @@ -245,7 +247,7 @@ public sealed class BSLinksetCompound : BSLinkset } else { - // For the shared shapes (meshes and hulls) just use the shape in the child + // For the shared shapes (meshes and hulls), just use the shape in the child. if (PhysicsScene.Shapes.ReferenceShape(cPrim.PhysShape)) { PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}", @@ -254,10 +256,10 @@ public sealed class BSLinksetCompound : BSLinkset BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, cPrim.PhysShape.ptr, displacementPos, displacementRot); } } - return false; + 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); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs index 67a59ef..d2387fb 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs @@ -294,7 +294,7 @@ public sealed class BSLinksetConstraints : BSLinkset float linksetMass = LinksetMass; LinksetRoot.UpdatePhysicalMassProperties(linksetMass); - // DEBUG: see of inter-linkset collisions are causing problems + // DEBUG: see of inter-linkset collisions are causing problems // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraints,set,rBody={1},linksetMass={2}", diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index de35359..c2e0ef1 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -1472,7 +1472,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters public void DetailLog(string msg, params Object[] args) { PhysicsLogging.Write(msg, args); - // Add the Flush() if debugging crashes to get all the messages written out. + // Add the Flush() if debugging crashes. Gets all the messages written out. PhysicsLogging.Flush(); } // Used to fill in the LocalID when there isn't one. It's the correct number of characters. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 662b19d..4a31c7d 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -48,6 +48,7 @@ public sealed class BSShapeCollection : IDisposable public IntPtr ptr; public int referenceCount; public DateTime lastReferenced; + public UInt64 shapeKey; } // Description of a hull. @@ -57,6 +58,7 @@ public sealed class BSShapeCollection : IDisposable public IntPtr ptr; public int referenceCount; public DateTime lastReferenced; + public UInt64 shapeKey; } // The sharable set of meshes and hulls. Indexed by their shape hash. @@ -116,7 +118,7 @@ public sealed class BSShapeCollection : IDisposable return ret; } - // Track another user of a body + // Track another user of a body. // We presume the caller has allocated the body. // Bodies only have one user so the body is just put into the world if not already there. public void ReferenceBody(BulletBody body, bool inTaintTime) @@ -146,13 +148,16 @@ public sealed class BSShapeCollection : IDisposable { PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceBody", delegate() { - DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}, inTaintTime={2}", - body.ID, body.ptr.ToString("X"), inTaintTime); + 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); - // It may have already been removed from the world in which case the next is a NOOP. - BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr); + if (BulletSimAPI.IsInWorld2(body.ptr)) + { + BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr); + 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, IntPtr.Zero); @@ -185,6 +190,7 @@ public sealed class BSShapeCollection : IDisposable { // This is a new reference to a mesh meshDesc.ptr = shape.ptr; + meshDesc.shapeKey = shape.shapeKey; // We keep a reference to the underlying IMesh data so a hull can be built meshDesc.referenceCount = 1; DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}", @@ -207,6 +213,7 @@ public sealed class BSShapeCollection : IDisposable { // This is a new reference to a hull hullDesc.ptr = shape.ptr; + hullDesc.shapeKey = shape.shapeKey; hullDesc.referenceCount = 1; DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}", BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); @@ -306,7 +313,7 @@ public sealed class BSShapeCollection : IDisposable // Remove a reference to a compound shape. // Taking a compound shape apart is a little tricky because if you just delete the - // physical object, it will free all the underlying children. We can't do that because + // physical shape, it will free all the underlying children. We can't do that because // they could be shared. So, this removes each of the children from the compound and // dereferences them separately before destroying the compound collision object itself. // Called at taint-time. @@ -335,22 +342,53 @@ public sealed class BSShapeCollection : IDisposable // Sometimes we have a pointer to a collision shape but don't know what type it is. // Figure out type and call the correct dereference routine. - // This is coming from a compound shape that we created so we know it is either native or mesh. // Called at taint-time. private void DereferenceAnonCollisionShape(IntPtr cShape) { - BulletShape shapeInfo = new BulletShape(cShape, ShapeData.PhysicsShapeType.SHAPE_MESH); - if (BulletSimAPI.IsCompound2(cShape)) - shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_COMPOUND; + MeshDesc meshDesc; + HullDesc hullDesc; - if (BulletSimAPI.IsNativeShape2(cShape)) + BulletShape shapeInfo = new BulletShape(cShape); + if (TryGetMeshByPtr(cShape, out meshDesc)) + { + shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_MESH; + shapeInfo.shapeKey = meshDesc.shapeKey; + } + else { - shapeInfo.isNativeShape = true; - shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter) + if (TryGetHullByPtr(cShape, out hullDesc)) + { + shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_HULL; + shapeInfo.shapeKey = hullDesc.shapeKey; + } + else + { + if (BulletSimAPI.IsCompound2(cShape)) + { + shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_COMPOUND; + } + else + { + if (BulletSimAPI.IsNativeShape2(cShape)) + { + shapeInfo.isNativeShape = true; + shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter) + } + } + } } + DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo); - DereferenceShape(shapeInfo, true, null); + if (shapeInfo.type != ShapeData.PhysicsShapeType.SHAPE_UNKNOWN) + { + DereferenceShape(shapeInfo, true, null); + } + else + { + PhysicsScene.Logger.ErrorFormat("{0} Could not decypher shape type. Region={1}, addr={2}", + LogHeader, PhysicsScene.RegionName, cShape.ToString("X")); + } } // Create the geometry information in Bullet for later use. @@ -913,6 +951,42 @@ public sealed class BSShapeCollection : IDisposable return ret; } + private bool TryGetMeshByPtr(IntPtr addr, out MeshDesc outDesc) + { + bool ret = false; + MeshDesc foundDesc = new MeshDesc(); + foreach (MeshDesc md in Meshes.Values) + { + if (md.ptr == addr) + { + foundDesc = md; + ret = true; + break; + } + + } + outDesc = foundDesc; + return ret; + } + + private bool TryGetHullByPtr(IntPtr addr, out HullDesc outDesc) + { + bool ret = false; + HullDesc foundDesc = new HullDesc(); + foreach (HullDesc hd in Hulls.Values) + { + if (hd.ptr == addr) + { + foundDesc = hd; + ret = true; + break; + } + + } + outDesc = foundDesc; + return ret; + } + private void DetailLog(string msg, params Object[] args) { if (PhysicsScene.PhysicsLogging.Enabled) -- cgit v1.1 From 79f7c466a116bf368423d4e18163f34fd8d66ce1 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sat, 3 Nov 2012 21:08:39 -0700 Subject: BulletSim: fix compound linkset crash by not freeing shape of child prims. Remove all compilation warnings (mostly 'protected' in sealed classes.) Add the dynamicAabbEnable parameter to creation of compound shapes. --- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 6 +++--- .../Region/Physics/BulletSPlugin/BSLinksetCompound.cs | 11 ++++++----- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 3 +++ OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 4 ++-- .../Region/Physics/BulletSPlugin/BSShapeCollection.cs | 16 ++++++++++------ OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs | 2 +- 6 files changed, 25 insertions(+), 17 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 38609e3..819635a 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -89,7 +89,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin //Angular properties private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor - private int m_angularMotorApply = 0; // application frame counter + // private int m_angularMotorApply = 0; // application frame counter private Vector3 m_angularMotorVelocity = Vector3.Zero; // current angular motor velocity private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate @@ -199,7 +199,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin break; case Vehicle.ANGULAR_MOTOR_DIRECTION: m_angularMotorDirection = new Vector3(pValue, pValue, pValue); - m_angularMotorApply = 100; + // m_angularMotorApply = 100; break; case Vehicle.LINEAR_FRICTION_TIMESCALE: m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); @@ -229,7 +229,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin pValue.Y = Math.Max(-12.56f, Math.Min(pValue.Y, 12.56f)); pValue.Z = Math.Max(-12.56f, Math.Min(pValue.Z, 12.56f)); m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); - m_angularMotorApply = 100; + // m_angularMotorApply = 100; break; case Vehicle.LINEAR_FRICTION_TIMESCALE: m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs index 6e68695..12c6d7a 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs @@ -83,8 +83,8 @@ public sealed class BSLinksetCompound : BSLinkset public override bool MakeDynamic(BSPhysObject child) { bool ret = false; - DetailLog("{0},BSLinksetCompound.MakeDynamic,call,isChild={1}", child.LocalID, HasChild(child)); - if (HasChild(child)) + DetailLog("{0},BSLinksetCompound.MakeDynamic,call,IsRoot={1}", child.LocalID, IsRoot(child)); + if (!IsRoot(child)) { // Physical children are removed from the world as the shape ofthe root compound // shape takes over. @@ -103,8 +103,8 @@ public sealed class BSLinksetCompound : BSLinkset public override bool MakeStatic(BSPhysObject child) { bool ret = false; - DetailLog("{0},BSLinksetCompound.MakeStatic,call,hasChild={1}", child.LocalID, HasChild(child)); - if (HasChild(child)) + DetailLog("{0},BSLinksetCompound.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child)); + if (!IsRoot(child)) { // The non-physical children can come back to life. BulletSimAPI.RemoveFromCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); @@ -240,6 +240,7 @@ public sealed class BSLinksetCompound : BSLinkset // A mesh or hull is created because scale is not available on a native shape. // (TODO: Bullet does have a btScaledCollisionShape. Can that be used?) BulletShape saveShape = cPrim.PhysShape; + cPrim.PhysShape.ptr = IntPtr.Zero; // Don't let the create free the child's shape PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null); BulletShape newShape = cPrim.PhysShape; cPrim.PhysShape = saveShape; @@ -263,7 +264,7 @@ public sealed class BSLinksetCompound : BSLinkset float linksetMass = LinksetMass; LinksetRoot.UpdatePhysicalMassProperties(linksetMass); - // DEBUG: see of inter-linkset collisions are causing problems + // DEBUG: see of inter-linkset collisions are causing problems for constraint linksets. // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index af403aa..aaa0d93 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -703,6 +703,9 @@ public sealed class BSPrim : BSPhysObject // For good measure, make sure the transform is set through to the motion state BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); + // Center of mass is at the center of the object + BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation); + // A dynamic object has mass UpdatePhysicalMassProperties(RawMass); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index c2e0ef1..740f339 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -1391,7 +1391,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters // 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 UpdateParameterObject(ref float defaultLoc, string parm, uint localID, float val) + private void UpdateParameterObject(ref float defaultLoc, string parm, uint localID, float val) { List objectIDs = new List(); switch (localID) @@ -1416,7 +1416,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters } // schedule the actual updating of the paramter to when the phys engine is not busy - protected void TaintedUpdateParameter(string parm, List lIDs, float val) + private void TaintedUpdateParameter(string parm, List lIDs, float val) { float xval = val; List xlIDs = lIDs; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 4a31c7d..29a23c0 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -38,7 +38,7 @@ public sealed class BSShapeCollection : IDisposable { private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]"; - protected BSScene PhysicsScene { get; set; } + private BSScene PhysicsScene { get; set; } private Object m_collectionActivityLock = new Object(); @@ -103,11 +103,12 @@ public sealed class BSShapeCollection : IDisposable { // Do we have the correct geometry for this type of object? // Updates prim.BSShape with information/pointers to shape. - // CreateGeom returns 'true' of BSShape as changed to a new 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; @@ -431,6 +432,7 @@ public sealed class BSShapeCollection : IDisposable return ret; } + // Create a mesh/hull shape or a native shape if 'nativeShapePossible' is 'true'. private bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback) { bool ret = false; @@ -797,15 +799,17 @@ public sealed class BSShapeCollection : IDisposable private bool GetReferenceToCompoundShape(BSPhysObject prim, ShapeDestructionCallback shapeCallback) { // Remove reference to the old shape - // Don't need to do this as the shape is freed when we create the new root shape below. + // Don't need to do this as the shape is freed when the new root shape is created below. // DereferenceShape(prim.PhysShape, true, shapeCallback); BulletShape cShape = new BulletShape( - BulletSimAPI.CreateCompoundShape2(PhysicsScene.World.ptr), ShapeData.PhysicsShapeType.SHAPE_COMPOUND); + BulletSimAPI.CreateCompoundShape2(PhysicsScene.World.ptr, false), ShapeData.PhysicsShapeType.SHAPE_COMPOUND); - // Create the shape for the root prim and add it to the compound shape - CreateGeomNonSpecial(true, prim, null); + // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape. + CreateGeomMeshOrHull(prim, shapeCallback); BulletSimAPI.AddChildShapeToCompoundShape2(cShape.ptr, prim.PhysShape.ptr, OMV.Vector3.Zero, OMV.Quaternion.Identity); + DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addRootPrim,compShape={1},rootShape={2}", + prim.LocalID, cShape, prim.PhysShape); prim.PhysShape = cShape; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index ac6d2b2..702bd77 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -614,7 +614,7 @@ public static extern bool IsNativeShape2(IntPtr shape); public static extern IntPtr BuildCapsuleShape2(IntPtr world, float radius, float height, Vector3 scale); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateCompoundShape2(IntPtr sim); +public static extern IntPtr CreateCompoundShape2(IntPtr sim, bool enableDynamicAabbTree); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern int GetNumberOfCompoundChildren2(IntPtr cShape); -- cgit v1.1 From 36d77fe27c4a49127c5d5baa4ed4653a25f1726d Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 6 Nov 2012 12:04:55 -0800 Subject: BulletSim: Add separate linear and angular damping function calls. Add function for recalculating compound shape bounding box. --- OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 702bd77..07149d8 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -632,6 +632,9 @@ public static extern IntPtr RemoveChildShapeFromCompoundShapeIndex2(IntPtr cShap public static extern void RemoveChildShapeFromCompoundShape2(IntPtr cShape, IntPtr removeShape); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void RecalculateCompoundShapeLocalAabb2(IntPtr cShape); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr DuplicateCollisionShape2(IntPtr sim, IntPtr srcShape, uint id); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] @@ -919,6 +922,12 @@ public static extern Vector3 GetGravity2(IntPtr obj); public static extern void SetDamping2(IntPtr obj, float lin_damping, float ang_damping); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void SetLinearDamping2(IntPtr obj, float lin_damping); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void SetAngularDamping2(IntPtr obj, float ang_damping); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern float GetLinearDamping2(IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -- cgit v1.1 From 702fd1e09473cede1458eef7b2c50cd39149a9f3 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 6 Nov 2012 12:07:22 -0800 Subject: BulletSim: only compute linkset mass when membership changes rather than everytime someone asks for it. --- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 3a92f93..436e043 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -49,6 +49,9 @@ public abstract class BSLinkset switch ((int)physScene.Params.linksetImplementation) { + case (int)LinksetImplementation.Constraint: + ret = new BSLinksetConstraints(physScene, parent); + break; case (int)LinksetImplementation.Compound: ret = new BSLinksetCompound(physScene, parent); break; @@ -56,7 +59,7 @@ public abstract class BSLinkset // ret = new BSLinksetManual(physScene, parent); break; default: - ret = new BSLinksetConstraints(physScene, parent); + ret = new BSLinksetCompound(physScene, parent); break; } return ret; @@ -97,7 +100,6 @@ public abstract class BSLinkset { get { - m_mass = ComputeLinksetMass(); return m_mass; } } @@ -138,6 +140,7 @@ public abstract class BSLinkset // Don't add the root to its own linkset if (!IsRoot(child)) AddChildToLinkset(child); + m_mass = ComputeLinksetMass(); } return this; } @@ -156,6 +159,7 @@ public abstract class BSLinkset return this; } RemoveChildFromLinkset(child); + m_mass = ComputeLinksetMass(); } // The child is down to a linkset of just itself -- cgit v1.1 From f70a3099b539f046e4d206a3244a3170751060b1 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 6 Nov 2012 12:08:17 -0800 Subject: BulletSim: recalculate the compound shape bounding box when built. --- OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs index 12c6d7a..3238c85 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs @@ -264,6 +264,8 @@ public sealed class BSLinksetCompound : BSLinkset float linksetMass = LinksetMass; LinksetRoot.UpdatePhysicalMassProperties(linksetMass); + BulletSimAPI.RecalculateCompoundShapeLocalAabb2(LinksetRoot.PhysShape.ptr); + // DEBUG: see of inter-linkset collisions are causing problems for constraint linksets. // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); -- cgit v1.1 From e2130817e5c033ef671f0af512f568e422ec7887 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 6 Nov 2012 17:54:36 -0800 Subject: BulletSim: remove limit on taints that can happen before a step. Remove some debugging code (detail log flushing). --- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 28 ++++++++++++++----------- 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 740f339..1cc607a 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -491,7 +491,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters // Some of the prims operate with special vehicle properties ProcessVehicles(timeStep); - numTaints += _taintOperations.Count; ProcessTaints(); // the vehicles might have added taints // step the physical world one interval @@ -500,7 +499,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters try { - // DumpVehicles(); // DEBUG + if (VehicleLoggingEnabled) DumpVehicles(); // DEBUG if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount(); numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep, @@ -509,7 +508,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime); DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}", DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount); - // DumpVehicles(); // DEBUG + if (VehicleLoggingEnabled) DumpVehicles(); // DEBUG } catch (Exception e) { @@ -521,7 +520,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters collidersCount = 0; } - // Don't have to use the pointers passed back since we know it is the same pinned memory we passed in // Get a value for 'now' so all the collision and update routines don't have to get their own @@ -724,6 +722,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters { if (_taintOperations.Count > 0) // save allocating new list if there is nothing to process { + /* + // Code to limit the number of taints processed per step. Meant to limit step time. + // Unsure if a good idea as code assumes that taints are done before the step. int taintCount = m_taintsToProcessPerStep; TaintCallbackEntry oneCallback = new TaintCallbackEntry(); while (_taintOperations.Count > 0 && taintCount-- > 0) @@ -752,13 +753,17 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters } } } - /* + if (_taintOperations.Count > 0) + { + DetailLog("{0},BSScene.ProcessTaints,leftTaintsOnList,numNotProcessed={1}", DetailLogZero, _taintOperations.Count); + } + */ // swizzle a new list into the list location so we can process what's there List oldList; lock (_taintLock) { - oldList = _taintedObjects; - _taintedObjects = new List(); + oldList = _taintOperations; + _taintOperations = new List(); } foreach (TaintCallbackEntry tcbe in oldList) @@ -774,7 +779,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters } } oldList.Clear(); - */ } } @@ -1043,7 +1047,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters (s) => { return (float)s.m_maxUpdatesPerFrame; }, (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ), new ParameterDefn("MaxTaintsToProcessPerStep", "Number of update taints to process before each simulation step", - 100f, + 500f, (s,cf,p,v) => { s.m_taintsToProcessPerStep = cf.GetInt(p, (int)v); }, (s) => { return (float)s.m_taintsToProcessPerStep; }, (s,p,l,v) => { s.m_taintsToProcessPerStep = (int)v; } ), @@ -1097,13 +1101,13 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters (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,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, v, v); } ), + (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, v, s.m_params[0].angularDamping); } ), 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,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, v, v); } ), + (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, s.m_params[0].linearDamping, 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); }, @@ -1473,7 +1477,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters { PhysicsLogging.Write(msg, args); // Add the Flush() if debugging crashes. Gets all the messages written out. - PhysicsLogging.Flush(); + // PhysicsLogging.Flush(); } // Used to fill in the LocalID when there isn't one. It's the correct number of characters. public const string DetailLogZero = "0000000000"; -- cgit v1.1 From 76cc3030314b3302da46bfe4078f076ba1b3d8a1 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 6 Nov 2012 17:58:55 -0800 Subject: BulletSim: Add ZeroAngularMotion method to physical objects. Add inTaint flag to ZeroMotion method. Update the references to those functions. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 27 +++++++--- .../Physics/BulletSPlugin/BSLinksetConstraints.cs | 2 +- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 20 +++++-- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 61 ++++++++++++++++------ 4 files changed, 82 insertions(+), 28 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 2a5397e..f33c124 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -103,7 +103,7 @@ public sealed class BSCharacter : BSPhysObject PhysicsScene.TaintedObject("BSCharacter.create", delegate() { DetailLog("{0},BSCharacter.create,taint", LocalID); - // New body and shape into BSBody and BSShape + // New body and shape into PhysBody and PhysShape PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, null, null); SetPhysicalProperties(); @@ -126,7 +126,7 @@ public sealed class BSCharacter : BSPhysObject { BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, PhysBody.ptr); - ZeroMotion(); + ZeroMotion(true); ForcePosition = _position; // Set the velocity and compute the proper friction ForceVelocity = _velocity; @@ -218,18 +218,31 @@ public sealed class BSCharacter : BSPhysObject // Do it to the properties so the values get set in the physics engine. // Push the setting of the values to the viewer. // Called at taint time! - public override void ZeroMotion() + public override void ZeroMotion(bool inTaintTime) { _velocity = OMV.Vector3.Zero; _acceleration = OMV.Vector3.Zero; _rotationalVelocity = OMV.Vector3.Zero; // Zero some other properties directly into the physics engine - BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, OMV.Vector3.Zero); - BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero); - BulletSimAPI.SetInterpolationVelocity2(PhysBody.ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); - BulletSimAPI.ClearForces2(PhysBody.ptr); + PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate() + { + BulletSimAPI.ClearAllForces2(PhysBody.ptr); + }); } + public override void ZeroAngularMotion(bool inTaintTime) + { + _rotationalVelocity = OMV.Vector3.Zero; + + PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate() + { + BulletSimAPI.SetInterpolationAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero); + BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero); + // The next also get rid of applied linear force but the linear velocity is untouched. + BulletSimAPI.ClearForces2(PhysBody.ptr); + }); + } + public override void LockAngularMotion(OMV.Vector3 axis) { return; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs index d2387fb..c855fda 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs @@ -184,7 +184,7 @@ public sealed class BSLinksetConstraints : BSLinkset private BSConstraint BuildConstraint(BSPhysObject rootPrim, BSPhysObject childPrim) { // Zero motion for children so they don't interpolate - childPrim.ZeroMotion(); + childPrim.ZeroMotion(true); // Relative position normalized to the root prim // Essentually a vector pointing from center of rootPrim to center of childPrim diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 7127aaf..e803072 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -34,9 +34,17 @@ using OpenSim.Region.Physics.Manager; namespace OpenSim.Region.Physics.BulletSPlugin { -// Class to wrap all objects. -// The rest of BulletSim doesn't need to keep checking for avatars or prims -// unless the difference is significant. +/* + * Class to wrap all objects. + * The rest of BulletSim doesn't need to keep checking for avatars or prims + * unless the difference is significant. + * + * Variables in the physicsl objects are in three forms: + * VariableName: used by the simulator and performs taint operations, etc + * RawVariableName: direct reference to the BulletSim storage for the variable value + * ForceVariableName: direct reference (store and fetch) to the value in the physics engine. + * The last two (and certainly the last one) should be referenced only in taint-time. + */ public abstract class BSPhysObject : PhysicsActor { protected void BaseInitialize(BSScene parentScene, uint localID, string name, string typeName) @@ -67,6 +75,9 @@ public abstract class BSPhysObject : PhysicsActor // Set the raw mass but also update physical mass properties (inertia, ...) public abstract void UpdatePhysicalMassProperties(float mass); + // The last value calculated for the prim's inertia + public OMV.Vector3 Inertia { get; set; } + // Reference to the physical body (btCollisionObject) of this object public BulletBody PhysBody; // Reference to the physical shape (btCollisionShape) of this object @@ -96,7 +107,8 @@ public abstract class BSPhysObject : PhysicsActor public abstract bool IsStatic { get; } // Stop all physical motion. - public abstract void ZeroMotion(); + public abstract void ZeroMotion(bool inTaintTime); + public abstract void ZeroAngularMotion(bool inTaintTime); // Step the vehicle simulation for this object. A NOOP if the vehicle was not configured. public virtual void StepVehicle(float timeStep) { } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index aaa0d93..14eb505 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -25,8 +25,6 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// Uncomment this it enable code to do all shape an body memory management -// in the C# code. using System; using System.Reflection; using System.Collections.Generic; @@ -236,14 +234,27 @@ public sealed class BSPrim : BSPhysObject // Do it to the properties so the values get set in the physics engine. // Push the setting of the values to the viewer. // Called at taint time! - public override void ZeroMotion() + public override void ZeroMotion(bool inTaintTime) { _velocity = OMV.Vector3.Zero; _acceleration = OMV.Vector3.Zero; _rotationalVelocity = OMV.Vector3.Zero; // Zero some other properties in the physics engine - BulletSimAPI.ClearAllForces2(PhysBody.ptr); + PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate() + { + BulletSimAPI.ClearAllForces2(PhysBody.ptr); + }); + } + public override void ZeroAngularMotion(bool inTaintTime) + { + _rotationalVelocity = OMV.Vector3.Zero; + // Zero some other properties in the physics engine + PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate() + { + BulletSimAPI.SetInterpolationAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero); + BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero); + }); } public override void LockAngularMotion(OMV.Vector3 axis) @@ -371,17 +382,18 @@ public sealed class BSPrim : BSPhysObject { if (IsStatic) { - BulletSimAPI.SetMassProps2(PhysBody.ptr, 0f, OMV.Vector3.Zero); + Inertia = OMV.Vector3.Zero; + BulletSimAPI.SetMassProps2(PhysBody.ptr, 0f, Inertia); BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr); } else { - OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass); - BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, localInertia); + Inertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass); + BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, Inertia); + BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr); // center of mass is at the zero of the object - BulletSimAPI.SetCenterOfMassByPosRot2(PhysBody.ptr, ForcePosition, ForceOrientation); - // BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); - DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2}", LocalID, physMass, localInertia); + // DEBUG DEBUG BulletSimAPI.SetCenterOfMassByPosRot2(PhysBody.ptr, ForcePosition, ForceOrientation); + DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2}", LocalID, physMass, Inertia); } } @@ -582,7 +594,7 @@ public sealed class BSPrim : BSPhysObject // DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical); SetObjectDynamic(true); // whether phys-to-static or static-to-phys, the object is not moving. - ZeroMotion(); + ZeroMotion(true); }); } } @@ -648,6 +660,7 @@ public sealed class BSPrim : BSPhysObject // Recompute any linkset parameters. // When going from non-physical to physical, this re-enables the constraints that // had been automatically disabled when the mass was set to zero. + // For compound based linksets, this enables and disables interactions of the children. Linkset.Refresh(this); DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}", @@ -666,9 +679,9 @@ public sealed class BSPrim : BSPhysObject // Become a Bullet 'static' object type CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_STATIC_OBJECT); // Stop all movement - ZeroMotion(); + ZeroMotion(true); // Center of mass is at the center of the object - BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation); + // DEBUG DEBUG BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation); // Mass is zero which disables a bunch of physics stuff in Bullet UpdatePhysicalMassProperties(0f); // Set collision detection parameters @@ -704,7 +717,7 @@ public sealed class BSPrim : BSPhysObject BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); // Center of mass is at the center of the object - BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation); + // DEBUG DEBUG BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation); // A dynamic object has mass UpdatePhysicalMassProperties(RawMass); @@ -958,6 +971,16 @@ public sealed class BSPrim : BSPhysObject }); } + public void ApplyForceImpulse(OMV.Vector3 impulse, bool inTaintTime) + { + OMV.Vector3 applyImpulse = impulse; + PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyForceImpulse", delegate() + { + DetailLog("{0},BSPrim.ApplyForceImpulse,taint,tImpulse={1}", LocalID, applyImpulse); + BulletSimAPI.ApplyCentralImpulse2(PhysBody.ptr, applyImpulse); + }); + } + private List m_accumulatedAngularForces = new List(); public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { AddAngularForce(force, pushforce, false); @@ -1001,7 +1024,6 @@ public sealed class BSPrim : BSPhysObject OMV.Vector3 applyImpulse = impulse; PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate() { - DetailLog("{0},BSPrim.ApplyTorqueImpulse,taint,tImpulse={1}", LocalID, applyImpulse); BulletSimAPI.ApplyTorqueImpulse2(PhysBody.ptr, applyImpulse); }); } @@ -1315,9 +1337,10 @@ public sealed class BSPrim : BSPhysObject // If this prim is part of a linkset, we must remove and restore the physical // links if the body is rebuilt. bool needToRestoreLinkset = false; + bool needToRestoreVehicle = false; // Create the correct physical representation for this type of object. - // Updates BSBody and BSShape with the new information. + // Updates PhysBody and PhysShape with the new information. // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. // Returns 'true' if either the body or the shape was changed. PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, null, delegate(BulletBody dBody) @@ -1326,6 +1349,7 @@ public sealed class BSPrim : BSPhysObject // Remove all the physical dependencies on the old body. // (Maybe someday make the changing of BSShape an event handled by BSLinkset.) needToRestoreLinkset = Linkset.RemoveBodyDependencies(this); + needToRestoreVehicle = _vehicle.RemoveBodyDependencies(this); }); if (needToRestoreLinkset) @@ -1333,6 +1357,11 @@ public sealed class BSPrim : BSPhysObject // If physical body dependencies were removed, restore them Linkset.RestoreBodyDependencies(this); } + if (needToRestoreVehicle) + { + // If physical body dependencies were removed, restore them + _vehicle.RestoreBodyDependencies(this); + } // Make sure the properties are set on the new object UpdatePhysicalParameters(); -- cgit v1.1 From ee00c5c8851dd364acef858f3fd9f5164797fc1e Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 6 Nov 2012 18:10:06 -0800 Subject: BulletSim: many changes to tune vehicles for BulletSim. The problem left is that the vehicle sitting on something needs to press down for gravity and what its sitting on pushes up so the vehicle does not penetrate. The effect is Bullet calculates a lot of random angular motion for the vehicle. Various schemes of damping and zeroing has not resolved the problem. --- OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | 224 +++++++++++++++------ 1 file changed, 161 insertions(+), 63 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 819635a..dbc9039 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -54,10 +54,15 @@ namespace OpenSim.Region.Physics.BulletSPlugin { public sealed class BSDynamics { + private static string LogHeader = "[BULLETSIM VEHICLE]"; + private BSScene PhysicsScene { get; set; } // the prim this dynamic controller belongs to private BSPrim Prim { get; set; } + // mass of the vehicle fetched each time we're calles + private float m_vehicleMass; + // Vehicle properties public Vehicle Type { get; set; } @@ -516,7 +521,29 @@ namespace OpenSim.Region.Physics.BulletSPlugin // Friction effects are handled by this vehicle code BulletSimAPI.SetFriction2(Prim.PhysBody.ptr, 0f); BulletSimAPI.SetHitFraction2(Prim.PhysBody.ptr, 0f); + + // BulletSimAPI.SetAngularDamping2(Prim.PhysBody.ptr, 0.8f); + + VDetailLog("{0},BSDynamics.Refresh,zeroingFriction and adding damping", Prim.LocalID); + } + } + + public bool RemoveBodyDependencies(BSPhysObject prim) + { + // If active, we need to add our properties back when the body is rebuilt. + return IsActive; + } + + public void RestoreBodyDependencies(BSPhysObject prim) + { + if (Prim.LocalID != prim.LocalID) + { + // The call should be on us by our prim. Error if not. + PhysicsScene.Logger.ErrorFormat("{0} RestoreBodyDependencies: called by not my prim. passedLocalID={1}, vehiclePrimLocalID={2}", + LogHeader, prim.LocalID, Prim.LocalID); + return; } + Refresh(); } // One step of the vehicle properties for the next 'pTimestep' seconds. @@ -533,16 +560,26 @@ namespace OpenSim.Region.Physics.BulletSPlugin // m_lastLinearVelocityVector = Prim.ForceVelocity * Quaternion.Inverse(Prim.ForceOrientation); // DEBUG: // END DEBUG + m_vehicleMass = Prim.Linkset.LinksetMass; + MoveLinear(pTimestep); + // Commented out for debug MoveAngular(pTimestep); - LimitRotation(pTimestep); + // Prim.ApplyTorqueImpulse(-Prim.RotationalVelocity * m_vehicleMass, false); // DEBUG DEBUG + // Prim.ForceRotationalVelocity = -Prim.RotationalVelocity; // DEBUG DEBUG - // DEBUG: Trying to figure out why Bullet goes crazy when the root prim is moved. - // BulletSimAPI.SetInterpolationVelocity2(Prim.BSBody.ptr, m_newVelocity, m_lastAngularVelocity); // DEBUG DEBUG DEBUG + LimitRotation(pTimestep); // remember the position so next step we can limit absolute movement effects m_lastPositionVector = Prim.ForcePosition; + VDetailLog("{0},BSDynamics.Step,frict={1},grav={2},inertia={3},mass={4}", // DEBUG DEBUG + Prim.LocalID, + BulletSimAPI.GetFriction2(Prim.PhysBody.ptr), + BulletSimAPI.GetGravity2(Prim.PhysBody.ptr), + Prim.Inertia, + m_vehicleMass + ); VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", Prim.LocalID, Prim.ForcePosition, Prim.Force, Prim.ForceVelocity, Prim.RotationalVelocity); }// end Step @@ -555,25 +592,26 @@ namespace OpenSim.Region.Physics.BulletSPlugin // m_lastLinearVelocityVector is the current speed we are moving in that direction if (m_linearMotorDirection.LengthSquared() > 0.001f) { - Vector3 origDir = m_linearMotorDirection; - Vector3 origVel = m_lastLinearVelocityVector; + Vector3 origDir = m_linearMotorDirection; // DEBUG + Vector3 origVel = m_lastLinearVelocityVector; // DEBUG + // DEBUG: the vehicle velocity rotated to be relative to vehicle coordinates for comparison Vector3 vehicleVelocity = Prim.ForceVelocity * Quaternion.Inverse(Prim.ForceOrientation); // DEBUG - // add drive to body + // Add (desiredVelocity - lastAppliedVelocity) / howLongItShouldTakeToComplete Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/(m_linearMotorTimescale) * pTimestep; - // lastLinearVelocityVector is the current body velocity vector m_lastLinearVelocityVector += addAmount; float decayFactor = (1.0f / m_linearMotorDecayTimescale) * pTimestep; m_linearMotorDirection *= (1f - decayFactor); - Vector3 frictionFactor = (Vector3.One / m_linearFrictionTimescale) * pTimestep; - m_lastLinearVelocityVector *= (Vector3.One - frictionFactor); - // Rotate new object velocity from vehicle relative to world coordinates m_newVelocity = m_lastLinearVelocityVector * Prim.ForceOrientation; - VDetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},vehVel={3},add={4},decay={5},frict={6},lmDir={7},lmVel={8},newVel={9}", + // Apply friction for next time + Vector3 frictionFactor = (Vector3.One / m_linearFrictionTimescale) * pTimestep; + m_lastLinearVelocityVector *= (Vector3.One - frictionFactor); + + VDetailLog("{0},MoveLinear,nonZero,origlmDir={1},origlvVel={2},vehVel={3},add={4},decay={5},frict={6},lmDir={7},lvVec={8},newVel={9}", Prim.LocalID, origDir, origVel, vehicleVelocity, addAmount, decayFactor, frictionFactor, m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity); } @@ -607,7 +645,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin // If below the terrain, move us above the ground a little. float terrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos); // Taking the rotated size doesn't work here because m_prim.Size is the size of the root prim and not the linkset. - // Need to add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass. + // TODO: Add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass. // Vector3 rotatedSize = m_prim.Size * m_prim.ForceOrientation; // if (rotatedSize.Z < terrainHeight) if (pos.Z < terrainHeight) @@ -638,13 +676,15 @@ namespace OpenSim.Region.Physics.BulletSPlugin if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0) { - // If body is aready heigher, use its height as target height - if (pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z; + // If body is already heigher, use its height as target height + if (pos.Z > m_VhoverTargetHeight) + m_VhoverTargetHeight = pos.Z; } if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) { - if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2) + if (Math.Abs(pos.Z - m_VhoverTargetHeight) > 0.2f) { + pos.Z = m_VhoverTargetHeight; Prim.ForcePosition = pos; } } @@ -709,25 +749,28 @@ namespace OpenSim.Region.Physics.BulletSPlugin } } - // Limit absolute vertical change - float Zchange = Math.Abs(posChange.Z); + #region downForce + Vector3 downForce = Vector3.Zero; + if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) { - if (Zchange > .3) - grav.Z = (float)(grav.Z * 3); - if (Zchange > .15) - grav.Z = (float)(grav.Z * 2); - if (Zchange > .75) - grav.Z = (float)(grav.Z * 1.5); - if (Zchange > .05) - grav.Z = (float)(grav.Z * 1.25); - if (Zchange > .025) - grav.Z = (float)(grav.Z * 1.125); - float postemp = (pos.Z - terrainHeight); - if (postemp > 2.5f) - grav.Z = (float)(grav.Z * 1.037125); - VDetailLog("{0},MoveLinear,limitMotorUp,grav={1}", Prim.LocalID, grav); + // If the vehicle is motoring into the sky, get it going back down. + // Is this an angular force or both linear and angular?? + float distanceAboveGround = pos.Z - terrainHeight; + if (distanceAboveGround > 2f) + { + // downForce = new Vector3(0, 0, (-distanceAboveGround / m_bankingTimescale) * pTimestep); + // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale); + downForce = new Vector3(0, 0, -distanceAboveGround); + } + // TODO: this calculation is all wrong. From the description at + // (http://wiki.secondlife.com/wiki/Category:LSL_Vehicle), the downForce + // has a decay factor. This says this force should + // be computed with a motor. + VDetailLog("{0},MoveLinear,limitMotorUp,distAbove={1},downForce={2}", + Prim.LocalID, distanceAboveGround, downForce); } + #endregion // downForce // If not changing some axis, reduce out velocity if ((m_flags & (VehicleFlag.NO_X)) != 0) @@ -737,13 +780,28 @@ namespace OpenSim.Region.Physics.BulletSPlugin if ((m_flags & (VehicleFlag.NO_Z)) != 0) m_newVelocity.Z = 0; - // Apply velocity + // Clamp REALLY high or low velocities + if (m_newVelocity.LengthSquared() > 1e6f) + { + m_newVelocity /= m_newVelocity.Length(); + m_newVelocity *= 1000f; + } + else if (m_newVelocity.LengthSquared() < 1e-6f) + m_newVelocity = Vector3.Zero; + + // Stuff new linear velocity into the vehicle Prim.ForceVelocity = m_newVelocity; - // Prim.AddForce(m_newVelocity * Prim.Linkset.LinksetMass, false); - Prim.AddForce(grav * Prim.Linkset.LinksetMass, false); + // Prim.ApplyForceImpulse((m_newVelocity - Prim.Velocity) * m_vehicleMass, false); // DEBUG DEBUG - VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},grav={4}", - Prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity, grav); + Vector3 totalDownForce = downForce + grav; + if (totalDownForce != Vector3.Zero) + { + Prim.AddForce(totalDownForce * m_vehicleMass, false); + // Prim.ApplyForceImpulse(totalDownForce * m_vehicleMass, false); + } + + VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},primVel={4},totalDown={5}", + Prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity, Prim.Velocity, totalDownForce); } // end MoveLinear() @@ -765,7 +823,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin Vector3 origDir = m_angularMotorDirection; // new velocity += error / ( time to get there / step interval) - // requested speed - last motor speed + // requested direction - current vehicle direction m_angularMotorVelocity += (m_angularMotorDirection - m_angularMotorVelocity) / (m_angularMotorTimescale / pTimestep); // decay requested direction m_angularMotorDirection *= (1.0f - (pTimestep * 1.0f/m_angularMotorDecayTimescale)); @@ -784,10 +842,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin Vector3 deflection = Vector3.Zero; Vector3 banking = Vector3.Zero; + // If vertical attaction timescale is reasonable and we applied an angular force last time... if (m_verticalAttractionTimescale < 300 && m_lastAngularVelocity != Vector3.Zero) { float VAservo = pTimestep * 0.2f / m_verticalAttractionTimescale; - if (Prim.Linkset.LinksetIsColliding) + if (Prim.IsColliding) VAservo = pTimestep * 0.05f / (m_verticalAttractionTimescale); VAservo *= (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); @@ -806,7 +865,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin verticalError.X = 2.0f - verticalError.X; verticalError.Y = 2.0f - verticalError.Y; } - // scale it by VAservo + // scale it by VAservo (timestep and timescale) verticalError = verticalError * VAservo; // As the body rotates around the X axis, then verticalError.Y increases; Rotated around Y @@ -822,25 +881,30 @@ namespace OpenSim.Region.Physics.BulletSPlugin vertattr.X += bounce * angularVelocity.X; vertattr.Y += bounce * angularVelocity.Y; - VDetailLog("{0},MoveAngular,verticalAttraction,verticalError={1},bounce={2},vertattr={3}", - Prim.LocalID, verticalError, bounce, vertattr); + VDetailLog("{0},MoveAngular,verticalAttraction,VAservo={1},effic={2},verticalError={3},bounce={4},vertattr={5}", + Prim.LocalID, VAservo, m_verticalAttractionEfficiency, verticalError, bounce, vertattr); } #endregion // Vertical attactor #region Deflection - //Forward is the prefered direction, but if the reference frame has changed, we need to take this into account as well if (m_angularDeflectionEfficiency != 0) { - Vector3 preferredAxisOfMotion = + // Compute a scaled vector that points in the preferred axis (X direction) + Vector3 scaledDefaultDirection = new Vector3((pTimestep * 10 * (m_angularDeflectionEfficiency / m_angularDeflectionTimescale)), 0, 0); - preferredAxisOfMotion *= Quaternion.Add(Prim.ForceOrientation, m_referenceFrame); + // Adding the current vehicle orientation and reference frame displaces the orientation to the frame. + // Rotate the scaled default axix relative to the actual vehicle direction giving where it should point. + Vector3 preferredAxisOfMotion = scaledDefaultDirection * Quaternion.Add(Prim.ForceOrientation, m_referenceFrame); + // Scale by efficiency and timescale deflection = (preferredAxisOfMotion * (m_angularDeflectionEfficiency) / m_angularDeflectionTimescale) * pTimestep; VDetailLog("{0},MoveAngular,Deflection,perfAxis={1},deflection={2}", Prim.LocalID, preferredAxisOfMotion, deflection); + // This deflection computation is not correct. + deflection = Vector3.Zero; } #endregion @@ -875,7 +939,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin } else banking.Z += (effSquared*(mult*mix))*(m_angularMotorVelocity.X) * 4; - if (!Prim.Linkset.LinksetIsColliding && Math.Abs(m_angularMotorVelocity.X) > mix) + if (!Prim.IsColliding && Math.Abs(m_angularMotorVelocity.X) > mix) //If they are colliding, we probably shouldn't shove the prim around... probably { float angVelZ = m_angularMotorVelocity.X*-1; @@ -904,6 +968,40 @@ namespace OpenSim.Region.Physics.BulletSPlugin // Sum velocities m_lastAngularVelocity = m_angularMotorVelocity + vertattr + banking + deflection; + #region Linear Motor Offset + + //Offset section + if (m_linearMotorOffset != Vector3.Zero) + { + //Offset of linear velocity doesn't change the linear velocity, + // but causes a torque to be applied, for example... + // + // IIIII >>> IIIII + // IIIII >>> IIIII + // IIIII >>> IIIII + // ^ + // | Applying a force at the arrow will cause the object to move forward, but also rotate + // + // + // The torque created is the linear velocity crossed with the offset + + // NOTE: this computation does should be in the linear section + // because there we know the impulse being applied. + Vector3 torqueFromOffset = Vector3.Zero; + // torqueFromOffset = Vector3.Cross(m_linearMotorOffset, appliedImpulse); + if (float.IsNaN(torqueFromOffset.X)) + torqueFromOffset.X = 0; + if (float.IsNaN(torqueFromOffset.Y)) + torqueFromOffset.Y = 0; + if (float.IsNaN(torqueFromOffset.Z)) + torqueFromOffset.Z = 0; + torqueFromOffset *= m_vehicleMass; + Prim.ApplyTorqueImpulse(torqueFromOffset, true); + VDetailLog("{0},BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", Prim.LocalID, torqueFromOffset); + } + + #endregion + if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) { m_lastAngularVelocity.X = 0; @@ -914,25 +1012,25 @@ namespace OpenSim.Region.Physics.BulletSPlugin if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) { m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. - VDetailLog("{0},MoveAngular,zeroSmallValues,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity); + Prim.ZeroAngularMotion(true); + VDetailLog("{0},MoveAngular,zeroAngularMotion,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity); + } + else + { + // Apply to the body. + // The above calculates the absolute angular velocity needed. Angular velocity is massless. + // Since we are stuffing the angular velocity directly into the object, the computed + // velocity needs to be scaled by the timestep. + Vector3 applyAngularForce = ((m_lastAngularVelocity * pTimestep) - Prim.ForceRotationalVelocity); + Prim.ForceRotationalVelocity = applyAngularForce; + + // Decay the angular movement for next time + Vector3 decayamount = (Vector3.One / m_angularFrictionTimescale) * pTimestep; + m_lastAngularVelocity *= Vector3.One - decayamount; + + VDetailLog("{0},MoveAngular,done,newRotVel={1},decay={2},lastAngular={3}", + Prim.LocalID, applyAngularForce, decayamount, m_lastAngularVelocity); } - - // Apply to the body - // The above calculates the absolute angular velocity needed - // Prim.ForceRotationalVelocity = m_lastAngularVelocity; - - // Apply a force to overcome current angular velocity - Vector3 applyAngularForce = (m_lastAngularVelocity - Prim.ForceRotationalVelocity) * Prim.Linkset.LinksetMass; - // Vector3 applyAngularForce = (m_lastAngularVelocity - Prim.ForceRotationalVelocity); - // Prim.AddAngularForce(applyAngularForce, false); - Prim.ApplyTorqueImpulse(applyAngularForce, false); - - // Apply friction for next time - Vector3 decayamount = (Vector3.One / m_angularFrictionTimescale) * pTimestep; - m_lastAngularVelocity *= Vector3.One - decayamount; - - VDetailLog("{0},MoveAngular,done,applyAForce={1},decay={2},lastAngular={3}", - Prim.LocalID, applyAngularForce, decayamount, m_lastAngularVelocity); } //end MoveAngular internal void LimitRotation(float timestep) -- cgit v1.1 From 67d5dbbb49fa44e433bc6f5448f1b3e16c242524 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 7 Nov 2012 15:28:06 -0800 Subject: BulletSim: add classes for physics motors. Eventually these will replace the manual code for vehicles and add PID functionality to avatar movement. --- OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs | 104 +++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs b/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs new file mode 100755 index 0000000..bc6e4c4 --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs @@ -0,0 +1,104 @@ +using System; +using System.Collections.Generic; +using System.Text; +using OpenMetaverse; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ +public abstract class BSMotor +{ + public virtual void Reset() { } + public virtual void Zero() { } +} +// Can all the incremental stepping be replaced with motor classes? +public class BSVMotor : BSMotor +{ + public Vector3 FrameOfReference { get; set; } + public Vector3 Offset { get; set; } + + public float TimeScale { get; set; } + public float TargetValueDecayTimeScale { get; set; } + public Vector3 CurrentValueReductionTimescale { get; set; } + public float Efficiency { get; set; } + + public Vector3 TargetValue { get; private set; } + public Vector3 CurrentValue { get; private set; } + + + + BSVMotor(float timeScale, float decayTimeScale, Vector3 frictionTimeScale, float efficiency) + { + TimeScale = timeScale; + TargetValueDecayTimeScale = decayTimeScale; + CurrentValueReductionTimescale = frictionTimeScale; + Efficiency = efficiency; + } + public void SetCurrent(Vector3 current) + { + CurrentValue = current; + } + public void SetTarget(Vector3 target) + { + TargetValue = target; + } + public Vector3 Step(float timeStep) + { + if (CurrentValue.LengthSquared() > 0.001f) + { + // Vector3 origDir = Target; // DEBUG + // Vector3 origVel = CurrentValue; // DEBUG + + // Add (desiredVelocity - currentAppliedVelocity) / howLongItShouldTakeToComplete + Vector3 addAmount = (TargetValue - CurrentValue)/(TargetValue) * timeStep; + CurrentValue += addAmount; + + float decayFactor = (1.0f / TargetValueDecayTimeScale) * timeStep; + TargetValue *= (1f - decayFactor); + + Vector3 frictionFactor = (Vector3.One / CurrentValueReductionTimescale) * timeStep; + CurrentValue *= (Vector3.One - frictionFactor); + } + else + { + // if what remains of direction is very small, zero it. + TargetValue = Vector3.Zero; + CurrentValue = Vector3.Zero; + + // VDetailLog("{0},MoveLinear,zeroed", Prim.LocalID); + } + return CurrentValue; + } +} + +public class BSFMotor : BSMotor +{ + public float TimeScale { get; set; } + public float DecayTimeScale { get; set; } + public float Friction { get; set; } + public float Efficiency { get; set; } + + public float Target { get; private set; } + public float CurrentValue { get; private set; } + + BSFMotor(float timeScale, float decayTimescale, float friction, float efficiency) + { + } + public void SetCurrent(float target) + { + } + public void SetTarget(float target) + { + } + public float Step(float timeStep) + { + return 0f; + } +} +public class BSPIDMotor : BSMotor +{ + // TODO: write and use this one + BSPIDMotor() + { + } +} +} -- cgit v1.1 From 366651831952558b03b8f6ec442a0867b257b808 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 7 Nov 2012 15:29:51 -0800 Subject: BulletSim: add skeleton classes for shape objectification. This will eventually replace all the if's and switches in ShapeCollection with polymorphism. --- OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs | 213 +++++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs new file mode 100755 index 0000000..5e2c4a8 --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs @@ -0,0 +1,213 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyrightD + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ +public abstract class BSShape +{ + public IntPtr ptr { get; set; } + public ShapeData.PhysicsShapeType type { get; set; } + public System.UInt64 key { get; set; } + public int referenceCount { get; set; } + public DateTime lastReferenced { get; set; } + + protected void Initialize() + { + ptr = IntPtr.Zero; + type = ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; + key = 0; + referenceCount = 0; + lastReferenced = DateTime.Now; + } + + // Get a reference to a physical shape. Create if it doesn't exist + public static BSShape GetShapeReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) + { + BSShape ret = null; + + if (prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_AVATAR) + { + // an avatar capsule is close to a native shape (it is not shared) + ret = BSShapeNative.GetReference(physicsScene, prim, ShapeData.PhysicsShapeType.SHAPE_AVATAR, + ShapeData.FixedShapeKey.KEY_CAPSULE); + physicsScene.DetailLog("{0},BSShape.GetShapeReference,avatarCapsule,shape={1}", prim.LocalID, ret); + } + + // Compound shapes are handled special as they are rebuilt from scratch. + // This isn't too great a hardship since most of the child shapes will already been created. + if (ret == null && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_COMPOUND) + { + // Getting a reference to a compound shape gets you the compound shape with the root prim shape added + ret = BSShapeCompound.GetReference(prim); + physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, ret); + } + + if (ret == null) + ret = GetShapeReferenceNonSpecial(physicsScene, forceRebuild, prim); + + return ret; + } + public static BSShape GetShapeReferenceNonSpecial(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) + { + return null; + } + public static BSShape GetShapeReferenceNonNative(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) + { + return null; + } + + // Release the use of a physical shape. + public abstract void Dereference(BSScene physicsScene); + + // All shapes have a static call to get a reference to the physical shape + // protected abstract static BSShape GetReference(); + + public override string ToString() + { + StringBuilder buff = new StringBuilder(); + buff.Append(""); + return buff.ToString(); + } +} + +public class BSShapeNull : BSShape +{ + public BSShapeNull() + { + base.Initialize(); + } + public static BSShape GetReference() { return new BSShapeNull(); } + public override void Dereference(BSScene physicsScene) { /* The magic of garbage collection will make this go away */ } +} + +public class BSShapeNative : BSShape +{ + private static string LogHeader = "[BULLETSIM SHAPE NATIVE]"; + public BSShapeNative() + { + base.Initialize(); + } + public static BSShape GetReference(BSScene physicsScene, BSPhysObject prim, + ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey) + { + // Native shapes are not shared and are always built anew. + return new BSShapeNative(physicsScene, prim, shapeType, shapeKey); + } + + private BSShapeNative(BSScene physicsScene, BSPhysObject prim, + ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey) + { + ShapeData nativeShapeData = new ShapeData(); + nativeShapeData.Type = shapeType; + nativeShapeData.ID = prim.LocalID; + nativeShapeData.Scale = prim.Scale; + nativeShapeData.Size = prim.Scale; + nativeShapeData.MeshKey = (ulong)shapeKey; + nativeShapeData.HullKey = (ulong)shapeKey; + + + if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) + { + ptr = BulletSimAPI.BuildCapsuleShape2(physicsScene.World.ptr, 1f, 1f, prim.Scale); + physicsScene.DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); + } + else + { + ptr = BulletSimAPI.BuildNativeShape2(physicsScene.World.ptr, nativeShapeData); + } + if (ptr == IntPtr.Zero) + { + physicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", + LogHeader, prim.LocalID, shapeType); + } + type = shapeType; + key = (UInt64)shapeKey; + } + // Make this reference to the physical shape go away since native shapes are not shared. + public override void Dereference(BSScene physicsScene) + { + // Native shapes are not tracked and are released immediately + physicsScene.DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,shape={1}", BSScene.DetailLogZero, this); + BulletSimAPI.DeleteCollisionShape2(physicsScene.World.ptr, ptr); + ptr = IntPtr.Zero; + // Garbage collection will free up this instance. + } +} + +public class BSShapeMesh : BSShape +{ + private static string LogHeader = "[BULLETSIM SHAPE MESH]"; + private static Dictionary Meshes = new Dictionary(); + + public BSShapeMesh() + { + base.Initialize(); + } + public static BSShape GetReference() { return new BSShapeNull(); } + public override void Dereference(BSScene physicsScene) { } +} + +public class BSShapeHull : BSShape +{ + private static string LogHeader = "[BULLETSIM SHAPE HULL]"; + private static Dictionary Hulls = new Dictionary(); + + public BSShapeHull() + { + base.Initialize(); + } + public static BSShape GetReference() { return new BSShapeNull(); } + public override void Dereference(BSScene physicsScene) { } +} + +public class BSShapeCompound : BSShape +{ + private static string LogHeader = "[BULLETSIM SHAPE COMPOUND]"; + public BSShapeCompound() + { + base.Initialize(); + } + public static BSShape GetReference(BSPhysObject prim) + { + return new BSShapeNull(); + } + public override void Dereference(BSScene physicsScene) { } +} +} -- cgit v1.1 From aeeaa3a0a9b965dfe5d1111b178234c94de9ba9d Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 14 Nov 2012 11:09:43 -0800 Subject: Added AssemblyInfos to every dll in the OpenSim.Region namespace. --- .../BulletSPlugin/Properties/AssemblyInfo.cs | 33 ++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs b/OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..0d1db3b --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("OpenSim.Region.Physics.BulletSPlugin")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("http://opensimulator.org")] +[assembly: AssemblyProduct("OpenSim")] +[assembly: AssemblyCopyright("OpenSimulator developers")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("520ea11b-20cb-449d-ba05-c01015fed841")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +[assembly: AssemblyVersion("0.7.5.*")] +[assembly: AssemblyFileVersion("1.0.0.0")] -- cgit v1.1 From 079a1e704fcaa9fddc9bb3de0a205969cba058bc Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sun, 18 Nov 2012 18:17:30 -0800 Subject: BulletSim: remove the obsolete interface to the Bullet code. Update BulletSim libraries with code stripped of the obsolete code. --- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 134 --------------------- 1 file changed, 134 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 07149d8..28fae13 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -429,140 +429,6 @@ static class BulletSimAPI { [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg); -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -[return: MarshalAs(UnmanagedType.LPStr)] -public static extern string GetVersion(); - -/* Remove the linkage to the old api methods -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern uint Initialize(Vector3 maxPosition, IntPtr parms, - int maxCollisions, IntPtr collisionArray, - int maxUpdates, IntPtr updateArray, - DebugLogCallback logRoutine); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void CreateInitialGroundPlaneAndTerrain(uint worldID); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetHeightmap(uint worldID, [MarshalAs(UnmanagedType.LPArray)] float[] heightMap); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void Shutdown(uint worldID); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool UpdateParameter(uint worldID, uint localID, - [MarshalAs(UnmanagedType.LPStr)]string paramCode, float value); - -// =============================================================================== -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern int PhysicsStep(uint worldID, float timeStep, int maxSubSteps, float fixedTimeStep, - out int updatedEntityCount, - out IntPtr updatedEntitiesPtr, - out int collidersCount, - out IntPtr collidersPtr); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool CreateHull(uint worldID, System.UInt64 meshKey, - int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls - ); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool CreateMesh(uint worldID, System.UInt64 meshKey, - int indexCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices, - int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices - ); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool DestroyHull(uint worldID, System.UInt64 meshKey); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool DestroyMesh(uint worldID, System.UInt64 meshKey); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool CreateObject(uint worldID, ShapeData shapeData); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetObjectPosition(uint WorldID, uint id); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Quaternion GetObjectOrientation(uint WorldID, uint id); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetObjectTranslation(uint worldID, uint id, Vector3 position, Quaternion rotation); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetObjectVelocity(uint worldID, uint id, Vector3 velocity); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetObjectAngularVelocity(uint worldID, uint id, Vector3 angularVelocity); - -// Set the current force acting on the object -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetObjectForce(uint worldID, uint id, Vector3 force); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetObjectScaleMass(uint worldID, uint id, Vector3 scale, float mass, bool isDynamic); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetObjectCollidable(uint worldID, uint id, bool phantom); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetObjectDynamic(uint worldID, uint id, bool isDynamic, float mass); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetObjectGhost(uint worldID, uint id, bool ghostly); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetObjectProperties(uint worldID, uint id, bool isStatic, bool isSolid, bool genCollisions, float mass); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetObjectBuoyancy(uint worldID, uint id, float buoyancy); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool HasObject(uint worldID, uint id); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool DestroyObject(uint worldID, uint id); - -// =============================================================================== -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern SweepHit ConvexSweepTest(uint worldID, uint id, Vector3 to, float extraMargin); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern RaycastHit RayTest(uint worldID, uint id, Vector3 from, Vector3 to); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 RecoverFromPenetration(uint worldID, uint id); - -// =============================================================================== -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void DumpBulletStatistics(); -*/ -// Log a debug message -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetDebugLogCallback(DebugLogCallback callback); - -// =============================================================================== -// =============================================================================== -// =============================================================================== -// A new version of the API that enables moving all the logic out of the C++ code and into -// the C# code. This will make modifications easier for the next person. -// This interface passes the actual pointers to the objects in the unmanaged -// address space. All the management (calls for creation/destruction/lookup) -// is done in the C# code. -// The names have a "2" tacked on. This will be removed as the C# code gets rebuilt -// and the old code is removed. - -// Functions use while converting from API1 to API2. Can be removed when totally converted. -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr GetSimHandle2(uint worldID); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr GetBodyHandleWorldID2(uint worldID, uint id); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr GetBodyHandle2(IntPtr world, uint id); - // =============================================================================== // Initialization and simulation [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -- cgit v1.1 From 22be36be69bbf571b26753307b9c2c5456a34d73 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sun, 18 Nov 2012 22:57:26 -0800 Subject: BulletSim: fix the problem with flying being disabled when crossing region boundries. --- OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index f33c124..3c48dcc 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -78,8 +78,8 @@ public sealed class BSCharacter : BSPhysObject private float _PIDHoverTao; public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying) + : base(parent_scene, localID, avName, "BSCharacter") { - base.BaseInitialize(parent_scene, localID, avName, "BSCharacter"); _physicsActorType = (int)ActorTypes.Agent; _position = pos; _size = size; @@ -131,6 +131,10 @@ public sealed class BSCharacter : BSPhysObject // Set the velocity and compute the proper friction ForceVelocity = _velocity; + // This will enable or disable the flying buoyancy of the avatar. + // Needs to be reset especially when an avatar is recreated after crossing a region boundry. + Flying = _flying; + BulletSimAPI.SetRestitution2(PhysBody.ptr, PhysicsScene.Params.avatarRestitution); BulletSimAPI.SetMargin2(PhysShape.ptr, PhysicsScene.Params.collisionMargin); BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale); @@ -615,7 +619,7 @@ public sealed class BSCharacter : BSPhysObject newScale.Y = PhysicsScene.Params.avatarCapsuleRadius; // From the total height, remove the capsule half spheres that are at each end - newScale.Z = size.Z- (newScale.X + newScale.Y); + newScale.Z = size.Z - (newScale.X + newScale.Y); Scale = newScale; } -- cgit v1.1 From 6c961d8addf5c6aad81165042e684e45429b3b21 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sun, 18 Nov 2012 22:58:36 -0800 Subject: BulletSim: Use base class constructors for initialization of BSShape and other classes. --- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 5 +- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 2 +- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 2 +- OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs | 421 ++++++++++----------- 4 files changed, 214 insertions(+), 216 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index e803072..991e5b1 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -47,7 +47,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin */ public abstract class BSPhysObject : PhysicsActor { - protected void BaseInitialize(BSScene parentScene, uint localID, string name, string typeName) + protected BSPhysObject() + { + } + protected BSPhysObject(BSScene parentScene, uint localID, string name, string typeName) { PhysicsScene = parentScene; LocalID = localID; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 14eb505..500c84a 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -88,9 +88,9 @@ public sealed class BSPrim : BSPhysObject public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) + : base(parent_scene, localID, primName, "BSPrim") { // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID); - base.BaseInitialize(parent_scene, localID, primName, "BSPrim"); _physicsActorType = (int)ActorTypes.Prim; _position = pos; _size = size; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 1cc607a..2fee95e 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -683,7 +683,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters #region Taints // Calls to the PhysicsActors can't directly call into the physics engine - // because it might be busy. We delay changes to a known time. + // because it might be busy. We delay changes to a known time. // We rely on C#'s closure to save and restore the context for the delegate. public void TaintedObject(String ident, TaintCallback callback) { diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs index 5e2c4a8..d59a486 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs @@ -1,213 +1,208 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ -public abstract class BSShape -{ - public IntPtr ptr { get; set; } - public ShapeData.PhysicsShapeType type { get; set; } - public System.UInt64 key { get; set; } - public int referenceCount { get; set; } - public DateTime lastReferenced { get; set; } - - protected void Initialize() - { - ptr = IntPtr.Zero; - type = ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; - key = 0; - referenceCount = 0; - lastReferenced = DateTime.Now; - } - - // Get a reference to a physical shape. Create if it doesn't exist - public static BSShape GetShapeReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) - { - BSShape ret = null; - - if (prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_AVATAR) - { - // an avatar capsule is close to a native shape (it is not shared) - ret = BSShapeNative.GetReference(physicsScene, prim, ShapeData.PhysicsShapeType.SHAPE_AVATAR, - ShapeData.FixedShapeKey.KEY_CAPSULE); - physicsScene.DetailLog("{0},BSShape.GetShapeReference,avatarCapsule,shape={1}", prim.LocalID, ret); - } - - // Compound shapes are handled special as they are rebuilt from scratch. - // This isn't too great a hardship since most of the child shapes will already been created. - if (ret == null && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_COMPOUND) - { - // Getting a reference to a compound shape gets you the compound shape with the root prim shape added - ret = BSShapeCompound.GetReference(prim); - physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, ret); - } - - if (ret == null) - ret = GetShapeReferenceNonSpecial(physicsScene, forceRebuild, prim); - - return ret; - } - public static BSShape GetShapeReferenceNonSpecial(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) - { - return null; - } - public static BSShape GetShapeReferenceNonNative(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) - { - return null; - } - - // Release the use of a physical shape. - public abstract void Dereference(BSScene physicsScene); - - // All shapes have a static call to get a reference to the physical shape - // protected abstract static BSShape GetReference(); - - public override string ToString() - { - StringBuilder buff = new StringBuilder(); - buff.Append(""); - return buff.ToString(); - } -} - -public class BSShapeNull : BSShape -{ - public BSShapeNull() - { - base.Initialize(); - } - public static BSShape GetReference() { return new BSShapeNull(); } - public override void Dereference(BSScene physicsScene) { /* The magic of garbage collection will make this go away */ } -} - -public class BSShapeNative : BSShape -{ - private static string LogHeader = "[BULLETSIM SHAPE NATIVE]"; - public BSShapeNative() - { - base.Initialize(); - } - public static BSShape GetReference(BSScene physicsScene, BSPhysObject prim, - ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey) - { - // Native shapes are not shared and are always built anew. - return new BSShapeNative(physicsScene, prim, shapeType, shapeKey); - } - - private BSShapeNative(BSScene physicsScene, BSPhysObject prim, - ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey) - { - ShapeData nativeShapeData = new ShapeData(); - nativeShapeData.Type = shapeType; - nativeShapeData.ID = prim.LocalID; - nativeShapeData.Scale = prim.Scale; - nativeShapeData.Size = prim.Scale; - nativeShapeData.MeshKey = (ulong)shapeKey; - nativeShapeData.HullKey = (ulong)shapeKey; - - - if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) - { - ptr = BulletSimAPI.BuildCapsuleShape2(physicsScene.World.ptr, 1f, 1f, prim.Scale); - physicsScene.DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); - } - else - { - ptr = BulletSimAPI.BuildNativeShape2(physicsScene.World.ptr, nativeShapeData); - } - if (ptr == IntPtr.Zero) - { - physicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", - LogHeader, prim.LocalID, shapeType); - } - type = shapeType; - key = (UInt64)shapeKey; - } - // Make this reference to the physical shape go away since native shapes are not shared. - public override void Dereference(BSScene physicsScene) - { - // Native shapes are not tracked and are released immediately - physicsScene.DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,shape={1}", BSScene.DetailLogZero, this); - BulletSimAPI.DeleteCollisionShape2(physicsScene.World.ptr, ptr); - ptr = IntPtr.Zero; - // Garbage collection will free up this instance. - } -} - -public class BSShapeMesh : BSShape -{ - private static string LogHeader = "[BULLETSIM SHAPE MESH]"; - private static Dictionary Meshes = new Dictionary(); - - public BSShapeMesh() - { - base.Initialize(); - } - public static BSShape GetReference() { return new BSShapeNull(); } - public override void Dereference(BSScene physicsScene) { } -} - -public class BSShapeHull : BSShape -{ - private static string LogHeader = "[BULLETSIM SHAPE HULL]"; - private static Dictionary Hulls = new Dictionary(); - - public BSShapeHull() - { - base.Initialize(); - } - public static BSShape GetReference() { return new BSShapeNull(); } - public override void Dereference(BSScene physicsScene) { } -} - -public class BSShapeCompound : BSShape -{ - private static string LogHeader = "[BULLETSIM SHAPE COMPOUND]"; - public BSShapeCompound() - { - base.Initialize(); - } - public static BSShape GetReference(BSPhysObject prim) - { - return new BSShapeNull(); - } - public override void Dereference(BSScene physicsScene) { } -} -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyrightD + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ +public abstract class BSShape +{ + public IntPtr ptr { get; set; } + public ShapeData.PhysicsShapeType type { get; set; } + public System.UInt64 key { get; set; } + public int referenceCount { get; set; } + public DateTime lastReferenced { get; set; } + + public BSShape() + { + ptr = IntPtr.Zero; + type = ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; + key = 0; + referenceCount = 0; + lastReferenced = DateTime.Now; + } + + // Get a reference to a physical shape. Create if it doesn't exist + public static BSShape GetShapeReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) + { + BSShape ret = null; + + if (prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_AVATAR) + { + // an avatar capsule is close to a native shape (it is not shared) + ret = BSShapeNative.GetReference(physicsScene, prim, ShapeData.PhysicsShapeType.SHAPE_AVATAR, + ShapeData.FixedShapeKey.KEY_CAPSULE); + physicsScene.DetailLog("{0},BSShape.GetShapeReference,avatarCapsule,shape={1}", prim.LocalID, ret); + } + + // Compound shapes are handled special as they are rebuilt from scratch. + // This isn't too great a hardship since most of the child shapes will already been created. + if (ret == null && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_COMPOUND) + { + // Getting a reference to a compound shape gets you the compound shape with the root prim shape added + ret = BSShapeCompound.GetReference(prim); + physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, ret); + } + + if (ret == null) + ret = GetShapeReferenceNonSpecial(physicsScene, forceRebuild, prim); + + return ret; + } + public static BSShape GetShapeReferenceNonSpecial(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) + { + return null; + } + public static BSShape GetShapeReferenceNonNative(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) + { + return null; + } + + // Release the use of a physical shape. + public abstract void Dereference(BSScene physicsScene); + + // All shapes have a static call to get a reference to the physical shape + // protected abstract static BSShape GetReference(); + + public override string ToString() + { + StringBuilder buff = new StringBuilder(); + buff.Append(""); + return buff.ToString(); + } +} + +public class BSShapeNull : BSShape +{ + public BSShapeNull() : base() + { + } + public static BSShape GetReference() { return new BSShapeNull(); } + public override void Dereference(BSScene physicsScene) { /* The magic of garbage collection will make this go away */ } +} + +public class BSShapeNative : BSShape +{ + private static string LogHeader = "[BULLETSIM SHAPE NATIVE]"; + public BSShapeNative() : base() + { + } + public static BSShape GetReference(BSScene physicsScene, BSPhysObject prim, + ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey) + { + // Native shapes are not shared and are always built anew. + return new BSShapeNative(physicsScene, prim, shapeType, shapeKey); + } + + private BSShapeNative(BSScene physicsScene, BSPhysObject prim, + ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey) + { + ShapeData nativeShapeData = new ShapeData(); + nativeShapeData.Type = shapeType; + nativeShapeData.ID = prim.LocalID; + nativeShapeData.Scale = prim.Scale; + nativeShapeData.Size = prim.Scale; + nativeShapeData.MeshKey = (ulong)shapeKey; + nativeShapeData.HullKey = (ulong)shapeKey; + + + if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) + { + ptr = BulletSimAPI.BuildCapsuleShape2(physicsScene.World.ptr, 1f, 1f, prim.Scale); + physicsScene.DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); + } + else + { + ptr = BulletSimAPI.BuildNativeShape2(physicsScene.World.ptr, nativeShapeData); + } + if (ptr == IntPtr.Zero) + { + physicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", + LogHeader, prim.LocalID, shapeType); + } + type = shapeType; + key = (UInt64)shapeKey; + } + // Make this reference to the physical shape go away since native shapes are not shared. + public override void Dereference(BSScene physicsScene) + { + // Native shapes are not tracked and are released immediately + physicsScene.DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,shape={1}", BSScene.DetailLogZero, this); + BulletSimAPI.DeleteCollisionShape2(physicsScene.World.ptr, ptr); + ptr = IntPtr.Zero; + // Garbage collection will free up this instance. + } +} + +public class BSShapeMesh : BSShape +{ + private static string LogHeader = "[BULLETSIM SHAPE MESH]"; + private static Dictionary Meshes = new Dictionary(); + + public BSShapeMesh() : base() + { + } + public static BSShape GetReference() { return new BSShapeNull(); } + public override void Dereference(BSScene physicsScene) { } +} + +public class BSShapeHull : BSShape +{ + private static string LogHeader = "[BULLETSIM SHAPE HULL]"; + private static Dictionary Hulls = new Dictionary(); + + public BSShapeHull() : base() + { + } + public static BSShape GetReference() { return new BSShapeNull(); } + public override void Dereference(BSScene physicsScene) { } +} + +public class BSShapeCompound : BSShape +{ + private static string LogHeader = "[BULLETSIM SHAPE COMPOUND]"; + public BSShapeCompound() : base() + { + } + public static BSShape GetReference(BSPhysObject prim) + { + return new BSShapeNull(); + } + public override void Dereference(BSScene physicsScene) { } +} +} -- cgit v1.1 From 2f5fe4b88e8eb0388cc2138c48a941b1317ed560 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 20 Nov 2012 08:34:18 -0800 Subject: BulletSim: tweek avatar capsule parameters so avatar feet don't go below ground. This solves the bouncing, short avatar problem (Mantis 6403). --- OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | 7 ++++--- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 11 ++++++----- 2 files changed, 10 insertions(+), 8 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 3c48dcc..fa1a23f 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -184,8 +184,8 @@ public sealed class BSCharacter : BSPhysObject _size = value; ComputeAvatarScale(_size); ComputeAvatarVolumeAndMass(); - DetailLog("{0},BSCharacter.setSize,call,scale={1},density={2},volume={3},mass={4}", - LocalID, Scale, _avatarDensity, _avatarVolume, RawMass); + DetailLog("{0},BSCharacter.setSize,call,size={1},scale={2},density={3},volume={4},mass={5}", + LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass); PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() { @@ -619,7 +619,8 @@ public sealed class BSCharacter : BSPhysObject newScale.Y = PhysicsScene.Params.avatarCapsuleRadius; // From the total height, remove the capsule half spheres that are at each end - newScale.Z = size.Z - (newScale.X + newScale.Y); + // The 1.15f came from ODE. Not sure what this factors in. + newScale.Z = (size.Z * 1.15f) - (newScale.X + newScale.Y); Scale = newScale; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 2fee95e..58dccea 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -712,7 +712,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters // here just before the physics engine is called to step the simulation. public void ProcessTaints() { - InTaintTime = true; + InTaintTime = true; // Only used for debugging so locking is not necessary. ProcessRegularTaints(); ProcessPostTaintTaints(); InTaintTime = false; @@ -758,6 +758,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters DetailLog("{0},BSScene.ProcessTaints,leftTaintsOnList,numNotProcessed={1}", DetailLogZero, _taintOperations.Count); } */ + // swizzle a new list into the list location so we can process what's there List oldList; lock (_taintLock) @@ -787,8 +788,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters // will replace any previous operation by the same object. public void PostTaintObject(String ident, uint ID, TaintCallback callback) { - if (!m_initialized) return; - string uniqueIdent = ident + "-" + ID.ToString(); lock (_taintLock) { @@ -864,13 +863,14 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters } } + // Only used for debugging. Does not change state of anything so locking is not necessary. public bool AssertInTaintTime(string whereFrom) { if (!InTaintTime) { DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom); m_log.ErrorFormat("{0} NOT IN TAINT TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom); - Util.PrintCallStack(); + Util.PrintCallStack(); // Prints the stack into the DEBUG log file. } return InTaintTime; } @@ -1186,7 +1186,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters (s) => { return s.m_params[0].avatarCapsuleRadius; }, (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ), new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar", - 1.5f, + // 1.5f, + 2.140599f, (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].avatarCapsuleHeight; }, (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ), -- cgit v1.1 From 4d29488216f3619455cda72aaf2d6ccf8f3e2402 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 20 Nov 2012 08:43:43 -0800 Subject: BulletSim: change PositionSanityCheck to apply a force to correct position corrections (below ground and floating). --- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 61 ++++++++++------------ .../Physics/BulletSPlugin/BSShapeCollection.cs | 2 +- 2 files changed, 30 insertions(+), 33 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 500c84a..b1b5846 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -47,7 +47,6 @@ public sealed class BSPrim : BSPhysObject // _size is what the user passed. Scale is what we pass to the physics engine with the mesh. // Often Scale is unity because the meshmerizer will apply _size when creating the mesh. private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user - // private OMV.Vector3 _scale; // the multiplier for each mesh dimension for the mesh as created by the meshmerizer private bool _grabbed; private bool _isSelected; @@ -274,19 +273,19 @@ public sealed class BSPrim : BSPhysObject if (!Linkset.IsRoot(this)) _position = Linkset.Position(this); - // don't do the GetObjectPosition for root elements because this function is called a zillion times + // don't do the GetObjectPosition for root elements because this function is called a zillion times. // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); return _position; } set { - // If you must push the position into the physics engine, use ForcePosition. + // If the position must be forced into the physics engine, use ForcePosition. if (_position == value) { return; } _position = value; // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? - PositionSanityCheck(); + PositionSanityCheck(false); PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() { // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); @@ -302,7 +301,7 @@ public sealed class BSPrim : BSPhysObject } set { _position = value; - PositionSanityCheck(); + // PositionSanityCheck(); // Don't do this! Causes a loop and caller should know better. BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); ActivateIfPhysical(false); } @@ -311,52 +310,43 @@ public sealed class BSPrim : BSPhysObject // Check that the current position is sane and, if not, modify the position to make it so. // Check for being below terrain and being out of bounds. // Returns 'true' of the position was made sane by some action. - private bool PositionSanityCheck() + private bool PositionSanityCheck(bool inTaintTime) { bool ret = false; - // If totally below the ground, move the prim up - // TODO: figure out the right solution for this... only for dynamic objects? - /* float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); + OMV.Vector3 upForce = OMV.Vector3.Zero; if (Position.Z < terrainHeight) { DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); - _position.Z = terrainHeight + 2.0f; + float targetHeight = terrainHeight + (Size.Z / 2f); + // Upforce proportional to the distance away from the terrain. Correct the error in 1 sec. + upForce.Z = (terrainHeight - Position.Z) * 1f; ret = true; } - */ + if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) { float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position); // TODO: a floating motor so object will bob in the water - if (Position.Z < waterHeight) + if (Math.Abs(Position.Z - waterHeight) > 0.1f) { - _position.Z = waterHeight; + // Upforce proportional to the distance away from the water. Correct the error in 1 sec. + upForce.Z = (waterHeight - Position.Z) * 1f; ret = true; } } // TODO: check for out of bounds - return ret; - } - // A version of the sanity check that also makes sure a new position value is - // pushed to the physics engine. This routine would be used by anyone - // who is not already pushing the value. - private bool PositionSanityCheck(bool inTaintTime) - { - bool ret = false; - if (PositionSanityCheck()) + // The above code computes a force to apply to correct any out-of-bounds problems. Apply same. + if (ret) { - // The new position value must be pushed into the physics engine but we can't - // just assign to "Position" because of potential call loops. - PhysicsScene.TaintedObject(inTaintTime, "BSPrim.PositionSanityCheck", delegate() + PhysicsScene.TaintedObject(inTaintTime, "BSPrim.PositionSanityCheck:belowTerrain", delegate() { - DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); - ForcePosition = _position; + // Apply upforce and overcome gravity. + ForceVelocity = ForceVelocity + upForce - PhysicsScene.DefaultGravity; }); - ret = true; } return ret; } @@ -940,6 +930,7 @@ public sealed class BSPrim : BSPhysObject public override void AddForce(OMV.Vector3 force, bool pushforce) { AddForce(force, pushforce, false); } + // Applying a force just adds this to the total force on the object. public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { // for an object, doesn't matter if force is a pushforce or not if (force.IsFinite()) @@ -971,6 +962,7 @@ public sealed class BSPrim : BSPhysObject }); } + // An impulse force is scaled by the mass of the object. public void ApplyForceImpulse(OMV.Vector3 impulse, bool inTaintTime) { OMV.Vector3 applyImpulse = impulse; @@ -1423,7 +1415,7 @@ public sealed class BSPrim : BSPhysObject if (changed != 0) { // Only update the position of single objects and linkset roots - if (this._parentPrim == null) + if (Linkset.IsRoot(this)) { base.RequestPhysicsterseUpdate(); } @@ -1435,19 +1427,24 @@ public sealed class BSPrim : BSPhysObject // Updates only for individual prims and for the root object of a linkset. if (Linkset.IsRoot(this)) { - // Assign to the local variables so the normal set action does not happen + // Assign directly to the local variables so the normal set action does not happen _position = entprop.Position; _orientation = entprop.Rotation; _velocity = entprop.Velocity; _acceleration = entprop.Acceleration; _rotationalVelocity = entprop.RotationalVelocity; + // The sanity check can change the velocity and/or position. + if (PositionSanityCheck(true)) + { + entprop.Position = _position; + entprop.Velocity = _velocity; + } + // remember the current and last set values LastEntityProperties = CurrentEntityProperties; CurrentEntityProperties = entprop; - PositionSanityCheck(true); - OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}", LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 29a23c0..7ef6429 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -940,7 +940,7 @@ public sealed class BSShapeCollection : IDisposable else { bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr, - prim.LocalID, prim.ForcePosition, prim.ForceOrientation); + prim.LocalID, prim.RawPosition, prim.RawOrientation); DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); } aBody = new BulletBody(prim.LocalID, bodyPtr); -- cgit v1.1 From d6db0d5740dae03174f65846556f2f06d573b5c4 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 20 Nov 2012 11:24:25 -0800 Subject: BulletSim: uplevel PhysicsShapeType out of ShapeData structure (since it is getting simplified out of existance someday) and update all the references to that enum. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 4 +- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 4 +- .../Physics/BulletSPlugin/BSLinksetCompound.cs | 6 +-- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 4 +- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 2 +- .../Physics/BulletSPlugin/BSShapeCollection.cs | 56 +++++++++++----------- OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs | 16 +++---- .../Physics/BulletSPlugin/BSTerrainManager.cs | 4 +- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 37 +++++++------- 9 files changed, 67 insertions(+), 66 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index fa1a23f..92ff804 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -203,9 +203,9 @@ public sealed class BSCharacter : BSPhysObject set { BaseShape = value; } } // I want the physics engine to make an avatar capsule - public override ShapeData.PhysicsShapeType PreferredPhysicalShape + public override PhysicsShapeType PreferredPhysicalShape { - get {return ShapeData.PhysicsShapeType.SHAPE_AVATAR; } + get {return PhysicsShapeType.SHAPE_AVATAR; } } public override bool Grabbed { diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 436e043..4ee047b 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -82,9 +82,9 @@ public abstract class BSLinkset // Some linksets have a preferred physical shape. // Returns SHAPE_UNKNOWN if there is no preference. Causes the correct shape to be selected. - public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) + public virtual PhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) { - return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; + return PhysicsShapeType.SHAPE_UNKNOWN; } // Linksets move around the children so the linkset might need to compute the child position diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs index 3238c85..cb37840 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs @@ -42,12 +42,12 @@ public sealed class BSLinksetCompound : BSLinkset } // For compound implimented linksets, if there are children, use compound shape for the root. - public override ShapeData.PhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) + public override PhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) { - ShapeData.PhysicsShapeType ret = ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; + PhysicsShapeType ret = PhysicsShapeType.SHAPE_UNKNOWN; if (IsRoot(requestor) && HasAnyChildren) { - ret = ShapeData.PhysicsShapeType.SHAPE_COMPOUND; + ret = PhysicsShapeType.SHAPE_COMPOUND; } // DetailLog("{0},BSLinksetCompound.PreferredPhysicalShape,call,shape={1}", LinksetRoot.LocalID, ret); return ret; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 991e5b1..e68b167 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -94,9 +94,9 @@ public abstract class BSPhysObject : PhysicsActor public PrimitiveBaseShape BaseShape { get; protected set; } // Some types of objects have preferred physical representations. // Returns SHAPE_UNKNOWN if there is no preference. - public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape + public virtual PhysicsShapeType PreferredPhysicalShape { - get { return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; } + get { return PhysicsShapeType.SHAPE_UNKNOWN; } } // When the physical properties are updated, an EntityProperty holds the update values. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index b1b5846..2657e4b 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -169,7 +169,7 @@ public sealed class BSPrim : BSPhysObject } } // Whatever the linkset wants is what I want. - public override ShapeData.PhysicsShapeType PreferredPhysicalShape + public override PhysicsShapeType PreferredPhysicalShape { get { return Linkset.PreferredPhysicalShape(this); } } public override bool ForceBodyShapeRebuild(bool inTaintTime) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 7ef6429..746a52e 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -178,7 +178,7 @@ public sealed class BSShapeCollection : IDisposable bool ret = false; switch (shape.type) { - case ShapeData.PhysicsShapeType.SHAPE_MESH: + case PhysicsShapeType.SHAPE_MESH: MeshDesc meshDesc; if (Meshes.TryGetValue(shape.shapeKey, out meshDesc)) { @@ -201,7 +201,7 @@ public sealed class BSShapeCollection : IDisposable meshDesc.lastReferenced = System.DateTime.Now; Meshes[shape.shapeKey] = meshDesc; break; - case ShapeData.PhysicsShapeType.SHAPE_HULL: + case PhysicsShapeType.SHAPE_HULL: HullDesc hullDesc; if (Hulls.TryGetValue(shape.shapeKey, out hullDesc)) { @@ -224,7 +224,7 @@ public sealed class BSShapeCollection : IDisposable hullDesc.lastReferenced = System.DateTime.Now; Hulls[shape.shapeKey] = hullDesc; break; - case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN: + case PhysicsShapeType.SHAPE_UNKNOWN: break; default: // Native shapes are not tracked and they don't go into any list @@ -255,16 +255,16 @@ public sealed class BSShapeCollection : IDisposable { switch (shape.type) { - case ShapeData.PhysicsShapeType.SHAPE_HULL: + case PhysicsShapeType.SHAPE_HULL: DereferenceHull(shape, shapeCallback); break; - case ShapeData.PhysicsShapeType.SHAPE_MESH: + case PhysicsShapeType.SHAPE_MESH: DereferenceMesh(shape, shapeCallback); break; - case ShapeData.PhysicsShapeType.SHAPE_COMPOUND: + case PhysicsShapeType.SHAPE_COMPOUND: DereferenceCompound(shape, shapeCallback); break; - case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN: + case PhysicsShapeType.SHAPE_UNKNOWN: break; default: break; @@ -352,28 +352,28 @@ public sealed class BSShapeCollection : IDisposable BulletShape shapeInfo = new BulletShape(cShape); if (TryGetMeshByPtr(cShape, out meshDesc)) { - shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_MESH; + shapeInfo.type = PhysicsShapeType.SHAPE_MESH; shapeInfo.shapeKey = meshDesc.shapeKey; } else { if (TryGetHullByPtr(cShape, out hullDesc)) { - shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_HULL; + shapeInfo.type = PhysicsShapeType.SHAPE_HULL; shapeInfo.shapeKey = hullDesc.shapeKey; } else { if (BulletSimAPI.IsCompound2(cShape)) { - shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_COMPOUND; + shapeInfo.type = PhysicsShapeType.SHAPE_COMPOUND; } else { if (BulletSimAPI.IsNativeShape2(cShape)) { shapeInfo.isNativeShape = true; - shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter) + shapeInfo.type = PhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter) } } } @@ -381,7 +381,7 @@ public sealed class BSShapeCollection : IDisposable DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo); - if (shapeInfo.type != ShapeData.PhysicsShapeType.SHAPE_UNKNOWN) + if (shapeInfo.type != PhysicsShapeType.SHAPE_UNKNOWN) { DereferenceShape(shapeInfo, true, null); } @@ -405,10 +405,10 @@ public sealed class BSShapeCollection : IDisposable bool ret = false; bool haveShape = false; - if (!haveShape && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_AVATAR) + if (!haveShape && prim.PreferredPhysicalShape == PhysicsShapeType.SHAPE_AVATAR) { // an avatar capsule is close to a native shape (it is not shared) - ret = GetReferenceToNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_AVATAR, + ret = GetReferenceToNativeShape(prim, PhysicsShapeType.SHAPE_AVATAR, ShapeData.FixedShapeKey.KEY_CAPSULE, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape); ret = true; @@ -417,7 +417,7 @@ public sealed class BSShapeCollection : IDisposable // Compound shapes are handled special as they are rebuilt from scratch. // This isn't too great a hardship since most of the child shapes will already been created. - if (!haveShape && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_COMPOUND) + if (!haveShape && prim.PreferredPhysicalShape == PhysicsShapeType.SHAPE_COMPOUND) { ret = GetReferenceToCompoundShape(prim, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape); @@ -460,10 +460,10 @@ public sealed class BSShapeCollection : IDisposable haveShape = true; if (forceRebuild || prim.Scale != prim.Size - || prim.PhysShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE + || prim.PhysShape.type != PhysicsShapeType.SHAPE_SPHERE ) { - ret = GetReferenceToNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_SPHERE, + ret = GetReferenceToNativeShape(prim, PhysicsShapeType.SHAPE_SPHERE, ShapeData.FixedShapeKey.KEY_SPHERE, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}", prim.LocalID, forceRebuild, prim.PhysShape); @@ -474,10 +474,10 @@ public sealed class BSShapeCollection : IDisposable haveShape = true; if (forceRebuild || prim.Scale != prim.Size - || prim.PhysShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX + || prim.PhysShape.type != PhysicsShapeType.SHAPE_BOX ) { - ret = GetReferenceToNativeShape( prim, ShapeData.PhysicsShapeType.SHAPE_BOX, + ret = GetReferenceToNativeShape( prim, PhysicsShapeType.SHAPE_BOX, ShapeData.FixedShapeKey.KEY_BOX, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}", prim.LocalID, forceRebuild, prim.PhysShape); @@ -519,7 +519,7 @@ public sealed class BSShapeCollection : IDisposable // Creates a native shape and assignes it to prim.BSShape. // "Native" shapes are never shared. they are created here and destroyed in DereferenceShape(). private bool GetReferenceToNativeShape(BSPhysObject prim, - ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey, + PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey, ShapeDestructionCallback shapeCallback) { // release any previous shape @@ -538,7 +538,7 @@ public sealed class BSShapeCollection : IDisposable return true; } - private BulletShape BuildPhysicalNativeShape(BSPhysObject prim, ShapeData.PhysicsShapeType shapeType, + private BulletShape BuildPhysicalNativeShape(BSPhysObject prim, PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey) { BulletShape newShape; @@ -551,7 +551,7 @@ public sealed class BSShapeCollection : IDisposable nativeShapeData.MeshKey = (ulong)shapeKey; nativeShapeData.HullKey = (ulong)shapeKey; - if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) + if (shapeType == PhysicsShapeType.SHAPE_AVATAR) { newShape = new BulletShape( BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, prim.Scale) @@ -585,7 +585,7 @@ public sealed class BSShapeCollection : IDisposable System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod); // if this new shape is the same as last time, don't recreate the mesh - if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH) + if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == PhysicsShapeType.SHAPE_MESH) return false; DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2}", @@ -643,7 +643,7 @@ public sealed class BSShapeCollection : IDisposable indices.GetLength(0), indices, vertices.Count, verticesAsFloats); } } - BulletShape newShape = new BulletShape(meshPtr, ShapeData.PhysicsShapeType.SHAPE_MESH); + BulletShape newShape = new BulletShape(meshPtr, PhysicsShapeType.SHAPE_MESH); newShape.shapeKey = newMeshKey; return newShape; @@ -659,7 +659,7 @@ public sealed class BSShapeCollection : IDisposable System.UInt64 newHullKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod); // if the hull hasn't changed, don't rebuild it - if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL) + if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == PhysicsShapeType.SHAPE_HULL) return false; DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}", @@ -780,7 +780,7 @@ public sealed class BSShapeCollection : IDisposable } } - BulletShape newShape = new BulletShape(hullPtr, ShapeData.PhysicsShapeType.SHAPE_HULL); + BulletShape newShape = new BulletShape(hullPtr, PhysicsShapeType.SHAPE_HULL); newShape.shapeKey = newHullKey; return newShape; // 'true' means a new shape has been added to this prim @@ -803,7 +803,7 @@ public sealed class BSShapeCollection : IDisposable // DereferenceShape(prim.PhysShape, true, shapeCallback); BulletShape cShape = new BulletShape( - BulletSimAPI.CreateCompoundShape2(PhysicsScene.World.ptr, false), ShapeData.PhysicsShapeType.SHAPE_COMPOUND); + BulletSimAPI.CreateCompoundShape2(PhysicsScene.World.ptr, false), PhysicsShapeType.SHAPE_COMPOUND); // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape. CreateGeomMeshOrHull(prim, shapeCallback); @@ -894,7 +894,7 @@ public sealed class BSShapeCollection : IDisposable // While we figure out the real problem, stick a simple native shape on the object. BulletShape fillinShape = - BuildPhysicalNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_BOX, ShapeData.FixedShapeKey.KEY_BOX); + BuildPhysicalNativeShape(prim, PhysicsShapeType.SHAPE_BOX, ShapeData.FixedShapeKey.KEY_BOX); return fillinShape; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs index d59a486..2896805 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs @@ -35,7 +35,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin public abstract class BSShape { public IntPtr ptr { get; set; } - public ShapeData.PhysicsShapeType type { get; set; } + public PhysicsShapeType type { get; set; } public System.UInt64 key { get; set; } public int referenceCount { get; set; } public DateTime lastReferenced { get; set; } @@ -43,7 +43,7 @@ public abstract class BSShape public BSShape() { ptr = IntPtr.Zero; - type = ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; + type = PhysicsShapeType.SHAPE_UNKNOWN; key = 0; referenceCount = 0; lastReferenced = DateTime.Now; @@ -54,17 +54,17 @@ public abstract class BSShape { BSShape ret = null; - if (prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_AVATAR) + if (prim.PreferredPhysicalShape == PhysicsShapeType.SHAPE_AVATAR) { // an avatar capsule is close to a native shape (it is not shared) - ret = BSShapeNative.GetReference(physicsScene, prim, ShapeData.PhysicsShapeType.SHAPE_AVATAR, + ret = BSShapeNative.GetReference(physicsScene, prim, PhysicsShapeType.SHAPE_AVATAR, ShapeData.FixedShapeKey.KEY_CAPSULE); physicsScene.DetailLog("{0},BSShape.GetShapeReference,avatarCapsule,shape={1}", prim.LocalID, ret); } // Compound shapes are handled special as they are rebuilt from scratch. // This isn't too great a hardship since most of the child shapes will already been created. - if (ret == null && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_COMPOUND) + if (ret == null && prim.PreferredPhysicalShape == PhysicsShapeType.SHAPE_COMPOUND) { // Getting a reference to a compound shape gets you the compound shape with the root prim shape added ret = BSShapeCompound.GetReference(prim); @@ -123,14 +123,14 @@ public class BSShapeNative : BSShape { } public static BSShape GetReference(BSScene physicsScene, BSPhysObject prim, - ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey) + PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey) { // Native shapes are not shared and are always built anew. return new BSShapeNative(physicsScene, prim, shapeType, shapeKey); } private BSShapeNative(BSScene physicsScene, BSPhysObject prim, - ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey) + PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey) { ShapeData nativeShapeData = new ShapeData(); nativeShapeData.Type = shapeType; @@ -141,7 +141,7 @@ public class BSShapeNative : BSShape nativeShapeData.HullKey = (ulong)shapeKey; - if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) + if (shapeType == PhysicsShapeType.SHAPE_AVATAR) { ptr = BulletSimAPI.BuildCapsuleShape2(physicsScene.World.ptr, 1f, 1f, prim.Scale); physicsScene.DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index 7c34af2..cc28e4d 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -109,7 +109,7 @@ public sealed class BSTerrainManager // The ground plane is here to catch things that are trying to drop to negative infinity BulletShape groundPlaneShape = new BulletShape( BulletSimAPI.CreateGroundPlaneShape2(BSScene.GROUNDPLANE_ID, 1f, TERRAIN_COLLISION_MARGIN), - ShapeData.PhysicsShapeType.SHAPE_GROUNDPLANE); + PhysicsShapeType.SHAPE_GROUNDPLANE); m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID, BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID, Vector3.Zero, Quaternion.Identity)); @@ -299,7 +299,7 @@ public sealed class BSTerrainManager // Create the terrain shape from the mapInfo mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr), - ShapeData.PhysicsShapeType.SHAPE_TERRAIN); + PhysicsShapeType.SHAPE_TERRAIN); // The terrain object initial position is at the center of the object Vector3 centerPos; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 28fae13..bb63b0a 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -88,11 +88,11 @@ public struct BulletShape public BulletShape(IntPtr xx) { ptr = xx; - type=ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; + type=PhysicsShapeType.SHAPE_UNKNOWN; shapeKey = 0; isNativeShape = false; } - public BulletShape(IntPtr xx, ShapeData.PhysicsShapeType typ) + public BulletShape(IntPtr xx, PhysicsShapeType typ) { ptr = xx; type = typ; @@ -100,7 +100,7 @@ public struct BulletShape isNativeShape = false; } public IntPtr ptr; - public ShapeData.PhysicsShapeType type; + public PhysicsShapeType type; public System.UInt64 shapeKey; public bool isNativeShape; public override string ToString() @@ -178,24 +178,25 @@ public struct ConvexHull int VertexCount; Vector3[] Vertices; } +public enum PhysicsShapeType +{ + SHAPE_UNKNOWN = 0, + SHAPE_AVATAR = 1, + SHAPE_BOX = 2, + SHAPE_CONE = 3, + SHAPE_CYLINDER = 4, + SHAPE_SPHERE = 5, + SHAPE_MESH = 6, + SHAPE_HULL = 7, + // following defined by BulletSim + SHAPE_GROUNDPLANE = 20, + SHAPE_TERRAIN = 21, + SHAPE_COMPOUND = 22, + SHAPE_HEIGHTMAP = 23, +}; [StructLayout(LayoutKind.Sequential)] public struct ShapeData { - public enum PhysicsShapeType - { - SHAPE_UNKNOWN = 0, - SHAPE_AVATAR = 1, - SHAPE_BOX = 2, - SHAPE_CONE = 3, - SHAPE_CYLINDER = 4, - SHAPE_SPHERE = 5, - SHAPE_MESH = 6, - SHAPE_HULL = 7, - // following defined by BulletSim - SHAPE_GROUNDPLANE = 20, - SHAPE_TERRAIN = 21, - SHAPE_COMPOUND = 22, - }; public uint ID; public PhysicsShapeType Type; public Vector3 Position; -- cgit v1.1 From 65e55ada87e110b65f3d69eb0a4f2402fb1f3ece Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 20 Nov 2012 11:30:22 -0800 Subject: BulletSim: uplevel FixedShapeKey out of ShapeData structure (since it is getting simplified out of existance someday) and update all the references to same. --- .../Physics/BulletSPlugin/BSShapeCollection.cs | 12 +++++------ OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs | 6 +++--- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 24 ++++++++++++---------- 3 files changed, 22 insertions(+), 20 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 746a52e..0232618 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -409,7 +409,7 @@ public sealed class BSShapeCollection : IDisposable { // an avatar capsule is close to a native shape (it is not shared) ret = GetReferenceToNativeShape(prim, PhysicsShapeType.SHAPE_AVATAR, - ShapeData.FixedShapeKey.KEY_CAPSULE, shapeCallback); + FixedShapeKey.KEY_CAPSULE, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape); ret = true; haveShape = true; @@ -464,7 +464,7 @@ public sealed class BSShapeCollection : IDisposable ) { ret = GetReferenceToNativeShape(prim, PhysicsShapeType.SHAPE_SPHERE, - ShapeData.FixedShapeKey.KEY_SPHERE, shapeCallback); + FixedShapeKey.KEY_SPHERE, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}", prim.LocalID, forceRebuild, prim.PhysShape); } @@ -478,7 +478,7 @@ public sealed class BSShapeCollection : IDisposable ) { ret = GetReferenceToNativeShape( prim, PhysicsShapeType.SHAPE_BOX, - ShapeData.FixedShapeKey.KEY_BOX, shapeCallback); + FixedShapeKey.KEY_BOX, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}", prim.LocalID, forceRebuild, prim.PhysShape); } @@ -519,7 +519,7 @@ public sealed class BSShapeCollection : IDisposable // Creates a native shape and assignes it to prim.BSShape. // "Native" shapes are never shared. they are created here and destroyed in DereferenceShape(). private bool GetReferenceToNativeShape(BSPhysObject prim, - PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey, + PhysicsShapeType shapeType, FixedShapeKey shapeKey, ShapeDestructionCallback shapeCallback) { // release any previous shape @@ -539,7 +539,7 @@ public sealed class BSShapeCollection : IDisposable } private BulletShape BuildPhysicalNativeShape(BSPhysObject prim, PhysicsShapeType shapeType, - ShapeData.FixedShapeKey shapeKey) + FixedShapeKey shapeKey) { BulletShape newShape; // Need to make sure the passed shape information is for the native type. @@ -894,7 +894,7 @@ public sealed class BSShapeCollection : IDisposable // While we figure out the real problem, stick a simple native shape on the object. BulletShape fillinShape = - BuildPhysicalNativeShape(prim, PhysicsShapeType.SHAPE_BOX, ShapeData.FixedShapeKey.KEY_BOX); + BuildPhysicalNativeShape(prim, PhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX); return fillinShape; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs index 2896805..71b5074 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs @@ -58,7 +58,7 @@ public abstract class BSShape { // an avatar capsule is close to a native shape (it is not shared) ret = BSShapeNative.GetReference(physicsScene, prim, PhysicsShapeType.SHAPE_AVATAR, - ShapeData.FixedShapeKey.KEY_CAPSULE); + FixedShapeKey.KEY_CAPSULE); physicsScene.DetailLog("{0},BSShape.GetShapeReference,avatarCapsule,shape={1}", prim.LocalID, ret); } @@ -123,14 +123,14 @@ public class BSShapeNative : BSShape { } public static BSShape GetReference(BSScene physicsScene, BSPhysObject prim, - PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey) + PhysicsShapeType shapeType, FixedShapeKey shapeKey) { // Native shapes are not shared and are always built anew. return new BSShapeNative(physicsScene, prim, shapeType, shapeKey); } private BSShapeNative(BSScene physicsScene, BSPhysObject prim, - PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey) + PhysicsShapeType shapeType, FixedShapeKey shapeKey) { ShapeData nativeShapeData = new ShapeData(); nativeShapeData.Type = shapeType; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index bb63b0a..75e7f99 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -89,7 +89,7 @@ public struct BulletShape { ptr = xx; type=PhysicsShapeType.SHAPE_UNKNOWN; - shapeKey = 0; + shapeKey = (System.UInt64)FixedShapeKey.KEY_NONE; isNativeShape = false; } public BulletShape(IntPtr xx, PhysicsShapeType typ) @@ -194,6 +194,18 @@ public enum PhysicsShapeType SHAPE_COMPOUND = 22, SHAPE_HEIGHTMAP = 23, }; + +// The native shapes have predefined shape hash keys +public enum FixedShapeKey : ulong +{ + KEY_NONE = 0, + KEY_BOX = 1, + KEY_SPHERE = 2, + KEY_CONE = 3, + KEY_CYLINDER = 4, + KEY_CAPSULE = 5, +} + [StructLayout(LayoutKind.Sequential)] public struct ShapeData { @@ -217,16 +229,6 @@ public struct ShapeData // note that bools are passed as floats since bool size changes by language and architecture public const float numericTrue = 1f; public const float numericFalse = 0f; - - // The native shapes have predefined shape hash keys - public enum FixedShapeKey : ulong - { - KEY_BOX = 1, - KEY_SPHERE = 2, - KEY_CONE = 3, - KEY_CYLINDER = 4, - KEY_CAPSULE = 5, - } } [StructLayout(LayoutKind.Sequential)] public struct SweepHit -- cgit v1.1 From 8dd5813889b17cc213d20491b41dbf8142b3ccb9 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 20 Nov 2012 11:33:42 -0800 Subject: BulletSim: rename SHAPE_AVATAR to SHAPE_CAPSULE with the eye to eventually having mesh avatars. --- OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | 2 +- OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs | 6 +++--- OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs | 6 +++--- OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 92ff804..799211e 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -205,7 +205,7 @@ public sealed class BSCharacter : BSPhysObject // I want the physics engine to make an avatar capsule public override PhysicsShapeType PreferredPhysicalShape { - get {return PhysicsShapeType.SHAPE_AVATAR; } + get {return PhysicsShapeType.SHAPE_CAPSULE; } } public override bool Grabbed { diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 0232618..a53ad6e 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -405,10 +405,10 @@ public sealed class BSShapeCollection : IDisposable bool ret = false; bool haveShape = false; - if (!haveShape && prim.PreferredPhysicalShape == PhysicsShapeType.SHAPE_AVATAR) + if (!haveShape && prim.PreferredPhysicalShape == PhysicsShapeType.SHAPE_CAPSULE) { // an avatar capsule is close to a native shape (it is not shared) - ret = GetReferenceToNativeShape(prim, PhysicsShapeType.SHAPE_AVATAR, + ret = GetReferenceToNativeShape(prim, PhysicsShapeType.SHAPE_CAPSULE, FixedShapeKey.KEY_CAPSULE, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape); ret = true; @@ -551,7 +551,7 @@ public sealed class BSShapeCollection : IDisposable nativeShapeData.MeshKey = (ulong)shapeKey; nativeShapeData.HullKey = (ulong)shapeKey; - if (shapeType == PhysicsShapeType.SHAPE_AVATAR) + if (shapeType == PhysicsShapeType.SHAPE_CAPSULE) { newShape = new BulletShape( BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, prim.Scale) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs index 71b5074..f2e62d9 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs @@ -54,10 +54,10 @@ public abstract class BSShape { BSShape ret = null; - if (prim.PreferredPhysicalShape == PhysicsShapeType.SHAPE_AVATAR) + if (prim.PreferredPhysicalShape == PhysicsShapeType.SHAPE_CAPSULE) { // an avatar capsule is close to a native shape (it is not shared) - ret = BSShapeNative.GetReference(physicsScene, prim, PhysicsShapeType.SHAPE_AVATAR, + ret = BSShapeNative.GetReference(physicsScene, prim, PhysicsShapeType.SHAPE_CAPSULE, FixedShapeKey.KEY_CAPSULE); physicsScene.DetailLog("{0},BSShape.GetShapeReference,avatarCapsule,shape={1}", prim.LocalID, ret); } @@ -141,7 +141,7 @@ public class BSShapeNative : BSShape nativeShapeData.HullKey = (ulong)shapeKey; - if (shapeType == PhysicsShapeType.SHAPE_AVATAR) + if (shapeType == PhysicsShapeType.SHAPE_CAPSULE) { ptr = BulletSimAPI.BuildCapsuleShape2(physicsScene.World.ptr, 1f, 1f, prim.Scale); physicsScene.DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 75e7f99..407d6d7 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -181,7 +181,7 @@ public struct ConvexHull public enum PhysicsShapeType { SHAPE_UNKNOWN = 0, - SHAPE_AVATAR = 1, + SHAPE_CAPSULE = 1, SHAPE_BOX = 2, SHAPE_CONE = 3, SHAPE_CYLINDER = 4, -- cgit v1.1 From 71b9640dfa67e830769aad64ef208d767e102c92 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 20 Nov 2012 14:51:50 -0800 Subject: BulletSim: pull heightmap implementation out of the terrain manager so a mesh terrain can be implemented. --- .../Physics/BulletSPlugin/BSTerrainHeightmap.cs | 174 ++++++++++++++ .../Physics/BulletSPlugin/BSTerrainManager.cs | 257 +++++++-------------- .../Region/Physics/BulletSPlugin/BSTerrainMesh.cs | 73 ++++++ .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 4 +- 4 files changed, 327 insertions(+), 181 deletions(-) create mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs create mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs new file mode 100755 index 0000000..3bb63cd --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs @@ -0,0 +1,174 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyrightD + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections.Generic; +using System.Text; + +using OpenSim.Framework; +using OpenSim.Region.Framework; +using OpenSim.Region.CoreModules; +using OpenSim.Region.Physics.Manager; + +using Nini.Config; +using log4net; + +using OpenMetaverse; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ +public sealed class BSTerrainHeightmap : BSTerrainPhys +{ + static string LogHeader = "[BULLETSIM TERRAIN HEIGHTMAP]"; + + BulletHeightMapInfo m_mapInfo; + + public BSTerrainHeightmap(BSScene physicsScene, uint id, Vector3 regionSize) + : base(physicsScene) + { + Vector3 minTerrainCoords = new Vector3(0f, 0f, BSTerrainManager.HEIGHT_INITIALIZATION - BSTerrainManager.HEIGHT_EQUAL_FUDGE); + Vector3 maxTerrainCoords = new Vector3(regionSize.X, regionSize.Y, BSTerrainManager.HEIGHT_INITIALIZATION); + int totalHeights = (int)maxTerrainCoords.X * (int)maxTerrainCoords.Y; + float[] initialMap = new float[totalHeights]; + for (int ii = 0; ii < totalHeights; ii++) + { + initialMap[ii] = BSTerrainManager.HEIGHT_INITIALIZATION; + } + m_mapInfo = new BulletHeightMapInfo(id, initialMap, IntPtr.Zero); + m_mapInfo.minCoords = minTerrainCoords; + m_mapInfo.maxCoords = maxTerrainCoords; + // Don't have to free any previous since we just got here. + BuildHeightmapTerrain(); + } + + // This minCoords and maxCoords passed in give the size of the terrain (min and max Z + // are the high and low points of the heightmap). + public BSTerrainHeightmap(BSScene physicsScene, uint id, float[] initialMap, + Vector3 minCoords, Vector3 maxCoords) + : base(physicsScene) + { + m_mapInfo = new BulletHeightMapInfo(id, initialMap, IntPtr.Zero); + m_mapInfo.minCoords = minCoords; + m_mapInfo.maxCoords = maxCoords; + m_mapInfo.minZ = minCoords.Z; + m_mapInfo.maxZ = maxCoords.Z; + + // Don't have to free any previous since we just got here. + BuildHeightmapTerrain(); + } + + public override void Dispose() + { + ReleaseHeightMapTerrain(); + } + + // Using the information in m_mapInfo, create the physical representation of the heightmap. + private void BuildHeightmapTerrain() + { + m_mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, m_mapInfo.ID, + m_mapInfo.minCoords, m_mapInfo.maxCoords, + m_mapInfo.heightMap, BSTerrainManager.TERRAIN_COLLISION_MARGIN); + + // Create the terrain shape from the mapInfo + m_mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(m_mapInfo.Ptr), + PhysicsShapeType.SHAPE_TERRAIN); + + // The terrain object initial position is at the center of the object + Vector3 centerPos; + centerPos.X = m_mapInfo.minCoords.X + (m_mapInfo.sizeX / 2f); + centerPos.Y = m_mapInfo.minCoords.Y + (m_mapInfo.sizeY / 2f); + centerPos.Z = m_mapInfo.minZ + ((m_mapInfo.maxZ - m_mapInfo.minZ) / 2f); + + m_mapInfo.terrainBody = new BulletBody(m_mapInfo.ID, + BulletSimAPI.CreateBodyWithDefaultMotionState2(m_mapInfo.terrainShape.ptr, + m_mapInfo.ID, centerPos, Quaternion.Identity)); + + // Set current terrain attributes + BulletSimAPI.SetFriction2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainFriction); + BulletSimAPI.SetHitFraction2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainHitFraction); + BulletSimAPI.SetRestitution2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainRestitution); + BulletSimAPI.SetCollisionFlags2(m_mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); + + // Return the new terrain to the world of physical objects + BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); + + // redo its bounding box now that it is in the world + BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); + + BulletSimAPI.SetCollisionFilterMask2(m_mapInfo.terrainBody.ptr, + (uint)CollisionFilterGroups.TerrainFilter, + (uint)CollisionFilterGroups.TerrainMask); + + // Make it so the terrain will not move or be considered for movement. + BulletSimAPI.ForceActivationState2(m_mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION); + + return; + } + + // If there is information in m_mapInfo pointing to physical structures, release same. + private void ReleaseHeightMapTerrain() + { + if (m_mapInfo != null) + { + if (m_mapInfo.terrainBody.ptr != IntPtr.Zero) + { + if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr)) + { + // Frees both the body and the shape. + BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); + BulletSimAPI.ReleaseHeightMapInfo2(m_mapInfo.Ptr); + } + } + } + m_mapInfo = null; + } + + // The passed position is relative to the base of the region. + public override float GetHeightAtXYZ(Vector3 pos) + { + float ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; + + int mapIndex = (int)pos.Y * (int)m_mapInfo.sizeY + (int)pos.X; + try + { + ret = m_mapInfo.heightMap[mapIndex]; + } + catch + { + // Sometimes they give us wonky values of X and Y. Give a warning and return something. + PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}", + LogHeader, m_mapInfo.terrainRegionBase, pos); + ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; + } + return ret; + } + + public override Vector3 TerrainBase + { + get { return m_mapInfo.terrainRegionBase; } + } +} +} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index cc28e4d..db04299 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -40,6 +40,22 @@ using OpenMetaverse; namespace OpenSim.Region.Physics.BulletSPlugin { + +// The physical implementation of the terrain is wrapped in this class. +public abstract class BSTerrainPhys : IDisposable +{ + public BSScene PhysicsScene { get; private set; } + + public BSTerrainPhys(BSScene physicsScene) + { + PhysicsScene = physicsScene; + } + public abstract void Dispose(); + public abstract float GetHeightAtXYZ(Vector3 pos); + public abstract Vector3 TerrainBase { get; } +} + +// ========================================================================================== public sealed class BSTerrainManager { static string LogHeader = "[BULLETSIM TERRAIN MANAGER]"; @@ -67,11 +83,10 @@ public sealed class BSTerrainManager // If doing mega-regions, if we're region zero we will be managing multiple // region terrains since region zero does the physics for the whole mega-region. - private Dictionary m_heightMaps; + private Dictionary m_terrains; - // True of the terrain has been modified. - // Used to force recalculation of terrain height after terrain has been modified - private bool m_terrainModified; + // Flags used to know when to recalculate the height. + private bool m_terrainModified = false; // If we are doing mega-regions, terrains are added from TERRAIN_ID to m_terrainCount. // This is incremented before assigning to new region so it is the last ID allocated. @@ -89,8 +104,7 @@ public sealed class BSTerrainManager public BSTerrainManager(BSScene physicsScene) { PhysicsScene = physicsScene; - m_heightMaps = new Dictionary(); - m_terrainModified = false; + m_terrains = new Dictionary(); // Assume one region of default size m_worldOffset = Vector3.Zero; @@ -99,9 +113,6 @@ public sealed class BSTerrainManager } // Create the initial instance of terrain and the underlying ground plane. - // The objects are allocated in the unmanaged space and the pointers are tracked - // by the managed code. - // The terrains and the groundPlane are not added to the list of PhysObjects. // This is called from the initialization routine so we presume it is // safe to call Bullet in real time. We hope no one is moving prims around yet. public void CreateInitialGroundPlaneAndTerrain() @@ -121,15 +132,9 @@ public sealed class BSTerrainManager BulletSimAPI.SetCollisionFilterMask2(m_groundPlane.ptr, (uint)CollisionFilterGroups.GroundPlaneFilter, (uint)CollisionFilterGroups.GroundPlaneMask); - Vector3 minTerrainCoords = new Vector3(0f, 0f, HEIGHT_INITIALIZATION - HEIGHT_EQUAL_FUDGE); - Vector3 maxTerrainCoords = new Vector3(DefaultRegionSize.X, DefaultRegionSize.Y, HEIGHT_INITIALIZATION); - int totalHeights = (int)maxTerrainCoords.X * (int)maxTerrainCoords.Y; - float[] initialMap = new float[totalHeights]; - for (int ii = 0; ii < totalHeights; ii++) - { - initialMap[ii] = HEIGHT_INITIALIZATION; - } - UpdateOrCreateTerrain(BSScene.TERRAIN_ID, initialMap, minTerrainCoords, maxTerrainCoords, true); + // Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain. + BSTerrainPhys initialTerrain = new BSTerrainHeightmap(PhysicsScene, BSScene.TERRAIN_ID, DefaultRegionSize); + m_terrains.Add(Vector3.Zero, initialTerrain); } // Release all the terrain structures we might have allocated @@ -150,15 +155,11 @@ public sealed class BSTerrainManager // Release all the terrain we have allocated public void ReleaseTerrain() { - foreach (KeyValuePair kvp in m_heightMaps) + foreach (KeyValuePair kvp in m_terrains) { - if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, kvp.Value.terrainBody.ptr)) - { - BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, kvp.Value.terrainBody.ptr); - BulletSimAPI.ReleaseHeightMapInfo2(kvp.Value.Ptr); - } + kvp.Value.Dispose(); } - m_heightMaps.Clear(); + m_terrains.Clear(); } // The simulator wants to set a new heightmap for the terrain. @@ -176,8 +177,9 @@ public sealed class BSTerrainManager { DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}", BSScene.DetailLogZero, m_worldOffset, m_worldMax); - ((BSScene)MegaRegionParentPhysicsScene).TerrainManager.UpdateOrCreateTerrain(BSScene.CHILDTERRAIN_ID, - localHeightMap, m_worldOffset, m_worldOffset + DefaultRegionSize, true); + ((BSScene)MegaRegionParentPhysicsScene).TerrainManager.UpdateTerrain( + BSScene.CHILDTERRAIN_ID, localHeightMap, + m_worldOffset, m_worldOffset + DefaultRegionSize, true); } } else @@ -185,7 +187,7 @@ public sealed class BSTerrainManager // If not doing the mega-prim thing, just change the terrain DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero); - UpdateOrCreateTerrain(BSScene.TERRAIN_ID, localHeightMap, + UpdateTerrain(BSScene.TERRAIN_ID, localHeightMap, m_worldOffset, m_worldOffset + DefaultRegionSize, true); } }); @@ -195,56 +197,60 @@ public sealed class BSTerrainManager // based on the passed information. The 'id' should be either the terrain id or // BSScene.CHILDTERRAIN_ID. If the latter, a new child terrain ID will be allocated and used. // The latter feature is for creating child terrains for mega-regions. - // If called with a mapInfo in m_heightMaps but the terrain has no body yet (mapInfo.terrainBody.Ptr == 0) - // then a new body and shape is created and the mapInfo is filled. - // This call is used for doing the initial terrain creation. // If called with a mapInfo in m_heightMaps and there is an existing terrain body, a new // terrain shape is created and added to the body. // This call is most often used to update the heightMap and parameters of the terrain. // (The above does suggest that some simplification/refactoring is in order.) - private void UpdateOrCreateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords, bool inTaintTime) + private void UpdateTerrain(uint id, float[] heightMap, + Vector3 minCoords, Vector3 maxCoords, bool inTaintTime) { - DetailLog("{0},BSTerrainManager.UpdateOrCreateTerrain,call,minC={1},maxC={2},inTaintTime={3}", + DetailLog("{0},BSTerrainManager.UpdateTerrain,call,minC={1},maxC={2},inTaintTime={3}", BSScene.DetailLogZero, minCoords, maxCoords, inTaintTime); + // Find high and low points of passed heightmap. + // The min and max passed in are usually the region objects can exist in (maximum + // object height, for instance). The terrain wants the bounding box for the + // terrain so we replace passed min and max Z with the actual terrain min/max Z. + // limit, for float minZ = float.MaxValue; float maxZ = float.MinValue; - Vector2 terrainRegionBase = new Vector2(minCoords.X, minCoords.Y); - - int heightMapSize = heightMap.Length; - for (int ii = 0; ii < heightMapSize; ii++) + foreach (float height in heightMap) { - float height = heightMap[ii]; if (height < minZ) minZ = height; if (height > maxZ) maxZ = height; } - - // The shape of the terrain is from its base to its extents. minCoords.Z = minZ; maxCoords.Z = maxZ; - BulletHeightMapInfo mapInfo; - if (m_heightMaps.TryGetValue(terrainRegionBase, out mapInfo)) + Vector3 terrainRegionBase = new Vector3(minCoords.X, minCoords.Y, 0f); + + BSTerrainPhys terrainPhys; + if (m_terrains.TryGetValue(terrainRegionBase, out terrainPhys)) { // If this is terrain we know about, it's easy to update - mapInfo.heightMap = heightMap; - mapInfo.minCoords = minCoords; - mapInfo.maxCoords = maxCoords; - mapInfo.minZ = minZ; - mapInfo.maxZ = maxZ; - mapInfo.sizeX = maxCoords.X - minCoords.X; - mapInfo.sizeY = maxCoords.Y - minCoords.Y; - DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,call,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}", - BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY); - - PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateOrCreateTerrain:UpdateExisting", delegate() + DetailLog("{0},UpdateTerrain:UpdateExisting,call,terrainBase={1}", BSScene.DetailLogZero, terrainRegionBase); + + PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateTerrain:UpdateExisting", delegate() { - if (MegaRegionParentPhysicsScene != null) + // Remove old terrain from the collection + m_terrains.Remove(terrainPhys.TerrainBase); + // Release any physical memory it may be using. + terrainPhys.Dispose(); + + if (MegaRegionParentPhysicsScene == null) + { + BSTerrainPhys newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, id, + heightMap, minCoords, maxCoords); + m_terrains.Add(terrainRegionBase, newTerrainPhys); + + m_terrainModified = true; + } + else { // It's possible that Combine() was called after this code was queued. // If we are a child of combined regions, we don't create any terrain for us. - DetailLog("{0},UpdateOrCreateTerrain:AmACombineChild,taint", BSScene.DetailLogZero); + DetailLog("{0},BSTerrainManager.UpdateTerrain:AmACombineChild,taint", BSScene.DetailLogZero); // Get rid of any terrain that may have been allocated for us. ReleaseGroundPlaneAndTerrain(); @@ -252,91 +258,6 @@ public sealed class BSTerrainManager // I hate doing this, but just bail return; } - - if (mapInfo.terrainBody.ptr != IntPtr.Zero) - { - // Updating an existing terrain. - DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,taint,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}", - BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY); - - // Remove from the dynamics world because we're going to mangle this object - BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr); - - // Get rid of the old terrain - BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr); - BulletSimAPI.ReleaseHeightMapInfo2(mapInfo.Ptr); - mapInfo.Ptr = IntPtr.Zero; - - /* - // NOTE: This routine is half here because I can't get the terrain shape replacement - // to work. In the short term, the above three lines completely delete the old - // terrain and the code below recreates one from scratch. - // Hopefully the Bullet community will help me out on this one. - - // First, release the old collision shape (there is only one terrain) - BulletSimAPI.DeleteCollisionShape2(m_physicsScene.World.Ptr, mapInfo.terrainShape.Ptr); - - // Fill the existing height map info with the new location and size information - BulletSimAPI.FillHeightMapInfo2(m_physicsScene.World.Ptr, mapInfo.Ptr, mapInfo.ID, - mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN); - - // Create a terrain shape based on the new info - mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr)); - - // Stuff the shape into the existing terrain body - BulletSimAPI.SetBodyShape2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr, mapInfo.terrainShape.Ptr); - */ - } - // else - { - // Creating a new terrain. - DetailLog("{0},UpdateOrCreateTerrain:CreateNewTerrain,taint,baseX={1},baseY={2},minZ={3},maxZ={4}", - BSScene.DetailLogZero, mapInfo.minCoords.X, mapInfo.minCoords.Y, minZ, maxZ); - - mapInfo.ID = id; - mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, mapInfo.ID, - mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN); - - // Create the terrain shape from the mapInfo - mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr), - PhysicsShapeType.SHAPE_TERRAIN); - - // The terrain object initial position is at the center of the object - Vector3 centerPos; - centerPos.X = minCoords.X + (mapInfo.sizeX / 2f); - centerPos.Y = minCoords.Y + (mapInfo.sizeY / 2f); - centerPos.Z = minZ + ((maxZ - minZ) / 2f); - - mapInfo.terrainBody = new BulletBody(mapInfo.ID, - BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.ptr, - id, centerPos, Quaternion.Identity)); - } - - // Make sure the entry is in the heightmap table - m_heightMaps[terrainRegionBase] = mapInfo; - - // Set current terrain attributes - BulletSimAPI.SetFriction2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainFriction); - BulletSimAPI.SetHitFraction2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainHitFraction); - BulletSimAPI.SetRestitution2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainRestitution); - BulletSimAPI.SetCollisionFlags2(mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); - - // Return the new terrain to the world of physical objects - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr); - - // redo its bounding box now that it is in the world - BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr); - - BulletSimAPI.SetCollisionFilterMask2(mapInfo.terrainBody.ptr, - (uint)CollisionFilterGroups.TerrainFilter, - (uint)CollisionFilterGroups.TerrainMask); - - // Make sure the new shape is processed. - // BulletSimAPI.Activate2(mapInfo.terrainBody.ptr, true); - // BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.ISLAND_SLEEPING); - BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION); - - m_terrainModified = true; }); } else @@ -353,34 +274,23 @@ public sealed class BSTerrainManager Vector3 minCoordsX = minCoords; Vector3 maxCoordsX = maxCoords; - DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,call,id={1}, minC={2}, maxC={3}", + DetailLog("{0},UpdateTerrain:NewTerrain,call,id={1}, minC={2}, maxC={3}", BSScene.DetailLogZero, newTerrainID, minCoords, minCoords); // Code that must happen at taint-time - PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateOrCreateTerrain:NewTerrain", delegate() + PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateTerrain:NewTerrain", delegate() { - DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,taint,baseX={1},baseY={2}", BSScene.DetailLogZero, minCoords.X, minCoords.Y); - // Create a new mapInfo that will be filled with the new info - mapInfo = new BulletHeightMapInfo(id, heightMapX, - BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, newTerrainID, - minCoordsX, maxCoordsX, heightMapX, TERRAIN_COLLISION_MARGIN)); - // Put the unfilled heightmap info into the collection of same - m_heightMaps.Add(terrainRegionBase, mapInfo); - // Build the terrain - UpdateOrCreateTerrain(newTerrainID, heightMap, minCoords, maxCoords, true); + DetailLog("{0},UpdateTerrain:NewTerrain,taint,baseX={1},baseY={2}", + BSScene.DetailLogZero, minCoordsX.X, minCoordsX.Y); + BSTerrainPhys newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, newTerrainID, + heightMapX, minCoordsX, maxCoordsX); + m_terrains.Add(terrainRegionBase, newTerrainPhys); m_terrainModified = true; }); } } - // Someday we will have complex terrain with caves and tunnels - public float GetTerrainHeightAtXYZ(Vector3 loc) - { - // For the moment, it's flat and convex - return GetTerrainHeightAtXY(loc.X, loc.Y); - } - // Given an X and Y, find the height of the terrain. // Since we could be handling multiple terrains for a mega-region, // the base of the region is calcuated assuming all regions are @@ -390,8 +300,10 @@ public sealed class BSTerrainManager private float lastHeightTX = 999999f; private float lastHeightTY = 999999f; private float lastHeight = HEIGHT_INITIAL_LASTHEIGHT; - private float GetTerrainHeightAtXY(float tX, float tY) + public float GetTerrainHeightAtXYZ(Vector3 loc) { + float tX = loc.X; + float tY = loc.Y; // You'd be surprized at the number of times this routine is called // with the same parameters as last time. if (!m_terrainModified && lastHeightTX == tX && lastHeightTY == tY) @@ -403,27 +315,14 @@ public sealed class BSTerrainManager int offsetX = ((int)(tX / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X; int offsetY = ((int)(tY / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y; - Vector2 terrainBaseXY = new Vector2(offsetX, offsetY); + Vector3 terrainBaseXYZ = new Vector3(offsetX, offsetY, 0f); - BulletHeightMapInfo mapInfo; - if (m_heightMaps.TryGetValue(terrainBaseXY, out mapInfo)) + BSTerrainPhys physTerrain; + if (m_terrains.TryGetValue(terrainBaseXYZ, out physTerrain)) { - float regionX = tX - offsetX; - float regionY = tY - offsetY; - int mapIndex = (int)regionY * (int)mapInfo.sizeY + (int)regionX; - try - { - ret = mapInfo.heightMap[mapIndex]; - } - catch - { - // Sometimes they give us wonky values of X and Y. Give a warning and return something. - PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, x={2}, y={3}", - LogHeader, terrainBaseXY, regionX, regionY); - ret = HEIGHT_GETHEIGHT_RET; - } - // DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXY,bX={1},baseY={2},szX={3},szY={4},regX={5},regY={6},index={7},ht={8}", - // BSScene.DetailLogZero, offsetX, offsetY, mapInfo.sizeX, mapInfo.sizeY, regionX, regionY, mapIndex, ret); + ret = physTerrain.GetHeightAtXYZ(loc - terrainBaseXYZ); + DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXYZ,loc={1},base={2},height={3}", + BSScene.DetailLogZero, loc, terrainBaseXYZ, ret); } else { @@ -466,7 +365,7 @@ public sealed class BSTerrainManager // Unhook all the combining that I know about. public void UnCombine(PhysicsScene pScene) { - // Just like ODE, for the moment a NOP + // Just like ODE, we don't do anything yet. DetailLog("{0},BSTerrainManager.UnCombine", BSScene.DetailLogZero); } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs new file mode 100755 index 0000000..387c78b --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs @@ -0,0 +1,73 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyrightD + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections.Generic; +using System.Text; + +using OpenSim.Framework; +using OpenSim.Region.Framework; +using OpenSim.Region.CoreModules; +using OpenSim.Region.Physics.Manager; + +using Nini.Config; +using log4net; + +using OpenMetaverse; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ +public sealed class BSTerrainMesh : BSTerrainPhys +{ + static string LogHeader = "[BULLETSIM TERRAIN MESH]"; + + public BSTerrainMesh(BSScene physicsScene, uint id, Vector3 regionSize) + : base(physicsScene) + { + } + + public BSTerrainMesh(BSScene physicsScene /* parameters for making mesh */) + : base(physicsScene) + { + } + + public override void Dispose() + { + return; + } + + public override float GetHeightAtXYZ(Vector3 pos) + { + return 12345f; + } + + public override Vector3 TerrainBase + { + get { return Vector3.Zero; } + } + +} +} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 407d6d7..bab3b3d 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -152,7 +152,7 @@ public class BulletHeightMapInfo ID = id; Ptr = xx; heightMap = hm; - terrainRegionBase = new Vector2(0f, 0f); + terrainRegionBase = Vector3.Zero; minCoords = new Vector3(100f, 100f, 25f); maxCoords = new Vector3(101f, 101f, 26f); minZ = maxZ = 0f; @@ -161,7 +161,7 @@ public class BulletHeightMapInfo public uint ID; public IntPtr Ptr; public float[] heightMap; - public Vector2 terrainRegionBase; + public Vector3 terrainRegionBase; public Vector3 minCoords; public Vector3 maxCoords; public float sizeX, sizeY; -- cgit v1.1 From 34cbc738a84b7946a87e8bfd3bb04869519b3dee Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 20 Nov 2012 20:36:49 -0800 Subject: BulletSim: enablement and debugging of mesh terrain. --- .../Physics/BulletSPlugin/BSTerrainHeightmap.cs | 28 ++- .../Physics/BulletSPlugin/BSTerrainManager.cs | 26 ++- .../Region/Physics/BulletSPlugin/BSTerrainMesh.cs | 229 ++++++++++++++++++++- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 6 +- 4 files changed, 253 insertions(+), 36 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs index 3bb63cd..e9fd0cb 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs @@ -44,10 +44,11 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys { static string LogHeader = "[BULLETSIM TERRAIN HEIGHTMAP]"; - BulletHeightMapInfo m_mapInfo; + BulletHeightMapInfo m_mapInfo = null; - public BSTerrainHeightmap(BSScene physicsScene, uint id, Vector3 regionSize) - : base(physicsScene) + // Constructor to build a default, flat heightmap terrain. + public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize) + : base(physicsScene, regionBase, id) { Vector3 minTerrainCoords = new Vector3(0f, 0f, BSTerrainManager.HEIGHT_INITIALIZATION - BSTerrainManager.HEIGHT_EQUAL_FUDGE); Vector3 maxTerrainCoords = new Vector3(regionSize.X, regionSize.Y, BSTerrainManager.HEIGHT_INITIALIZATION); @@ -60,21 +61,23 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys m_mapInfo = new BulletHeightMapInfo(id, initialMap, IntPtr.Zero); m_mapInfo.minCoords = minTerrainCoords; m_mapInfo.maxCoords = maxTerrainCoords; + m_mapInfo.terrainRegionBase = TerrainBase; // Don't have to free any previous since we just got here. BuildHeightmapTerrain(); } // This minCoords and maxCoords passed in give the size of the terrain (min and max Z // are the high and low points of the heightmap). - public BSTerrainHeightmap(BSScene physicsScene, uint id, float[] initialMap, + public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap, Vector3 minCoords, Vector3 maxCoords) - : base(physicsScene) + : base(physicsScene, regionBase, id) { m_mapInfo = new BulletHeightMapInfo(id, initialMap, IntPtr.Zero); m_mapInfo.minCoords = minCoords; m_mapInfo.maxCoords = maxCoords; m_mapInfo.minZ = minCoords.Z; m_mapInfo.maxZ = maxCoords.Z; + m_mapInfo.terrainRegionBase = TerrainBase; // Don't have to free any previous since we just got here. BuildHeightmapTerrain(); @@ -135,12 +138,10 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys { if (m_mapInfo.terrainBody.ptr != IntPtr.Zero) { - if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr)) - { - // Frees both the body and the shape. - BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); - BulletSimAPI.ReleaseHeightMapInfo2(m_mapInfo.Ptr); - } + BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); + // Frees both the body and the shape. + BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); + BulletSimAPI.ReleaseHeightMapInfo2(m_mapInfo.Ptr); } } m_mapInfo = null; @@ -165,10 +166,5 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys } return ret; } - - public override Vector3 TerrainBase - { - get { return m_mapInfo.terrainRegionBase; } - } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index db04299..ed0dfa8 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -45,14 +45,18 @@ namespace OpenSim.Region.Physics.BulletSPlugin public abstract class BSTerrainPhys : IDisposable { public BSScene PhysicsScene { get; private set; } + // Base of the region in world coordinates. Coordinates inside the region are relative to this. + public Vector3 TerrainBase { get; private set; } + public uint ID { get; private set; } - public BSTerrainPhys(BSScene physicsScene) + public BSTerrainPhys(BSScene physicsScene, Vector3 regionBase, uint id) { PhysicsScene = physicsScene; + TerrainBase = regionBase; + ID = id; } public abstract void Dispose(); public abstract float GetHeightAtXYZ(Vector3 pos); - public abstract Vector3 TerrainBase { get; } } // ========================================================================================== @@ -133,7 +137,7 @@ public sealed class BSTerrainManager (uint)CollisionFilterGroups.GroundPlaneFilter, (uint)CollisionFilterGroups.GroundPlaneMask); // Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain. - BSTerrainPhys initialTerrain = new BSTerrainHeightmap(PhysicsScene, BSScene.TERRAIN_ID, DefaultRegionSize); + BSTerrainPhys initialTerrain = new BSTerrainHeightmap(PhysicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize); m_terrains.Add(Vector3.Zero, initialTerrain); } @@ -208,10 +212,9 @@ public sealed class BSTerrainManager BSScene.DetailLogZero, minCoords, maxCoords, inTaintTime); // Find high and low points of passed heightmap. - // The min and max passed in are usually the region objects can exist in (maximum + // The min and max passed in is usually the area objects can be in (maximum // object height, for instance). The terrain wants the bounding box for the // terrain so we replace passed min and max Z with the actual terrain min/max Z. - // limit, for float minZ = float.MaxValue; float maxZ = float.MinValue; foreach (float height in heightMap) @@ -219,6 +222,11 @@ public sealed class BSTerrainManager if (height < minZ) minZ = height; if (height > maxZ) maxZ = height; } + if (minZ == maxZ) + { + // If min and max are the same, reduce min a little bit so a good bounding box is created. + minZ -= BSTerrainManager.HEIGHT_EQUAL_FUDGE; + } minCoords.Z = minZ; maxCoords.Z = maxZ; @@ -240,7 +248,9 @@ public sealed class BSTerrainManager if (MegaRegionParentPhysicsScene == null) { - BSTerrainPhys newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, id, + // BSTerrainPhys newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, terrainRegionBase, id, + // heightMap, minCoords, maxCoords); + BSTerrainPhys newTerrainPhys = new BSTerrainMesh(PhysicsScene, terrainRegionBase, id, heightMap, minCoords, maxCoords); m_terrains.Add(terrainRegionBase, newTerrainPhys); @@ -282,8 +292,8 @@ public sealed class BSTerrainManager { DetailLog("{0},UpdateTerrain:NewTerrain,taint,baseX={1},baseY={2}", BSScene.DetailLogZero, minCoordsX.X, minCoordsX.Y); - BSTerrainPhys newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, newTerrainID, - heightMapX, minCoordsX, maxCoordsX); + BSTerrainPhys newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, terrainRegionBase, + newTerrainID, heightMapX, minCoordsX, maxCoordsX); m_terrains.Add(terrainRegionBase, newTerrainPhys); m_terrainModified = true; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs index 387c78b..bbb014a 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs @@ -44,30 +44,241 @@ public sealed class BSTerrainMesh : BSTerrainPhys { static string LogHeader = "[BULLETSIM TERRAIN MESH]"; - public BSTerrainMesh(BSScene physicsScene, uint id, Vector3 regionSize) - : base(physicsScene) + private float[] m_savedHeightMap; + int m_sizeX; + int m_sizeY; + + BulletShape m_terrainShape; + BulletBody m_terrainBody; + + public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize) + : base(physicsScene, regionBase, id) { } - public BSTerrainMesh(BSScene physicsScene /* parameters for making mesh */) - : base(physicsScene) + public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id /* parameters for making mesh */) + : base(physicsScene, regionBase, id) { } + // Create terrain mesh from a heightmap. + public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap, + Vector3 minCoords, Vector3 maxCoords) + : base(physicsScene, regionBase, id) + { + int indicesCount; + int[] indices; + int verticesCount; + float[] vertices; + + m_savedHeightMap = initialMap; + + m_sizeX = (int)(maxCoords.X - minCoords.X); + m_sizeY = (int)(maxCoords.Y - minCoords.Y); + + if (!BSTerrainMesh.ConvertHeightmapToMesh(PhysicsScene, initialMap, m_sizeX, m_sizeY, + (float)m_sizeX, (float)m_sizeY, + Vector3.Zero, 1.0f, + out indicesCount, out indices, out verticesCount, out vertices)) + { + // DISASTER!! + PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedConversionOfHeightmap", ID); + PhysicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh! base={1}", LogHeader, TerrainBase); + // Something is very messed up and a crash is in our future. + return; + } + PhysicsScene.DetailLog("{0},BSTerrainMesh.create,afterConvertHeightmapToMesh,ver={1},ind={2}", + ID, verticesCount, indicesCount); + + m_terrainShape = new BulletShape(BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, + indicesCount, indices, verticesCount, vertices), + PhysicsShapeType.SHAPE_MESH); + if (m_terrainShape.ptr == IntPtr.Zero) + { + // DISASTER!! + PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedCreationOfShape", ID); + physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain mesh! base={1}", LogHeader, TerrainBase); + // Something is very messed up and a crash is in our future. + return; + } + PhysicsScene.DetailLog("{0},BSTerrainMesh.create,afterCreateShape,shape={1}", ID, m_terrainShape); + + // The terrain object initial position is at the center of the object + Vector3 centerPos; + centerPos.X = minCoords.X + (m_sizeX / 2f); + centerPos.Y = minCoords.Y + (m_sizeY / 2f); + centerPos.Z = minCoords.Z + ((maxCoords.Z - minCoords.Z) / 2f); + Quaternion rot = Quaternion.Identity; + + PhysicsScene.DetailLog("{0},BSTerrainMesh.create,creatingBody,centerPos={1},rot={2}", ID, centerPos, rot); + m_terrainBody = new BulletBody(id, BulletSimAPI.CreateBodyWithDefaultMotionState2( + m_terrainShape.ptr, ID, centerPos, rot)); + if (m_terrainBody.ptr == IntPtr.Zero) + { + // DISASTER!! + physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain body! base={1}", LogHeader, TerrainBase); + // Something is very messed up and a crash is in our future. + return; + } + PhysicsScene.DetailLog("{0},BSTerrainMesh.create,afterCreateBody,body={1}", ID, m_terrainBody); + + // Set current terrain attributes + BulletSimAPI.SetFriction2(m_terrainBody.ptr, PhysicsScene.Params.terrainFriction); + BulletSimAPI.SetHitFraction2(m_terrainBody.ptr, PhysicsScene.Params.terrainHitFraction); + BulletSimAPI.SetRestitution2(m_terrainBody.ptr, PhysicsScene.Params.terrainRestitution); + BulletSimAPI.SetCollisionFlags2(m_terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); + + // Static objects are not very massive. + BulletSimAPI.SetMassProps2(m_terrainBody.ptr, 0f, Vector3.Zero); + + // Return the new terrain to the world of physical objects + BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_terrainBody.ptr); + + // redo its bounding box now that it is in the world + BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_terrainBody.ptr); + + BulletSimAPI.SetCollisionFilterMask2(m_terrainBody.ptr, + (uint)CollisionFilterGroups.TerrainFilter, + (uint)CollisionFilterGroups.TerrainMask); + + // Make it so the terrain will not move or be considered for movement. + BulletSimAPI.ForceActivationState2(m_terrainBody.ptr, ActivationState.DISABLE_SIMULATION); + } + public override void Dispose() { - return; + if (m_terrainBody.ptr != IntPtr.Zero) + { + BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_terrainBody.ptr); + // Frees both the body and the shape. + BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_terrainBody.ptr); + } } public override float GetHeightAtXYZ(Vector3 pos) { - return 12345f; + // For the moment use the saved heightmap to get the terrain height. + // TODO: raycast downward to find the true terrain below the position. + float ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; + + int mapIndex = (int)pos.Y * m_sizeY + (int)pos.X; + try + { + ret = m_savedHeightMap[mapIndex]; + } + catch + { + // Sometimes they give us wonky values of X and Y. Give a warning and return something. + PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}", + LogHeader, TerrainBase, pos); + ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; + } + return ret; } - public override Vector3 TerrainBase + // Convert the passed heightmap to mesh information suitable for CreateMeshShape2(). + // Return 'true' if successfully created. + public static bool ConvertHeightmapToMesh( + BSScene physicsScene, + float[] heightMap, int sizeX, int sizeY, // parameters of incoming heightmap + float extentX, float extentY, // zero based range for output vertices + Vector3 extentBase, // base to be added to all vertices + float magnification, // number of vertices to create between heightMap coords + out int indicesCountO, out int[] indicesO, + out int verticesCountO, out float[] verticesO) { - get { return Vector3.Zero; } - } + bool ret = false; + + int indicesCount = 0; + int verticesCount = 0; + int[] indices = new int[0]; + float[] vertices = new float[0]; + // Simple mesh creation which assumes magnification == 1, sizeX == extentX and sizeY == extentY. + // TODO: do a more general solution that scales, adds new vertices and smoothes the result. + + try + { + // One vertice per heightmap value plus the vertices off the top and bottom edge. + int totalVertices = (sizeX + 1) * (sizeY + 1); + vertices = new float[totalVertices * 3]; + int totalIndices = sizeX * sizeY * 6; + indices = new int[totalIndices]; + + physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,totVert={1},totInd={2}", + BSScene.DetailLogZero, totalVertices, totalIndices); + float magX = (float)sizeX / extentX; + float magY = (float)sizeY / extentY; + // Note that sizeX+1 vertices are created since there is land between this and the next region. + for (int yy = 0; yy <= sizeY; yy++) + { + for (int xx = 0; xx <= sizeX; xx++) // Hint: the "<=" means we got through sizeX + 1 times + { + int offset = yy * sizeX + xx; + // Extend the height from the height from the last row or column + if (yy == sizeY) offset -= sizeX; + if (xx == sizeX) offset -= 1; + float height = heightMap[offset]; + vertices[verticesCount + 0] = (float)xx * magX + extentBase.X; + vertices[verticesCount + 1] = (float)yy * magY + extentBase.Y; + vertices[verticesCount + 2] = height + extentBase.Z; + if (physicsScene.PhysicsLogging.Enabled && verticesCount < 900) // DEBUG DEBUG DEBUG + { + Vector3 genVertex = new Vector3( + vertices[verticesCount + 0], + vertices[verticesCount + 1], + vertices[verticesCount + 2]); + physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,ii={1},vertex={2}", + BSScene.DetailLogZero, verticesCount/3, genVertex); + } + verticesCount += 3; + } + } + verticesCount = verticesCount / 3; + physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,completeVerts,verCount={1}", + BSScene.DetailLogZero, verticesCount); + + for (int yy = 0; yy < sizeY; yy++) + { + for (int xx = 0; xx < sizeX; xx++) + { + int offset = yy * sizeX + xx; + // Each vertices is presumed to be the upper left corner of a box of two triangles + indices[indicesCount + 0] = offset; + indices[indicesCount + 1] = offset + 1; + indices[indicesCount + 2] = offset + sizeX + 1; // accounting for the extra column + indices[indicesCount + 3] = offset + 1; + indices[indicesCount + 4] = offset + sizeX + 2; + indices[indicesCount + 5] = offset + sizeX + 1; + if (indicesCount < (300 * 6)) // DEBUG DEBUG DEBUG + physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,i0={1},i1={2},i2={3},i3={4},i4={5},i5={6}", // DEEBUG DEBUG DEBUG + BSScene.DetailLogZero, + indices[indicesCount + 0], + indices[indicesCount + 1], + indices[indicesCount + 2], + indices[indicesCount + 3], + indices[indicesCount + 4], + indices[indicesCount + 5] + ); + indicesCount += 6; + } + } + physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,completeIndices,indCount={1}", // DEEBUG DEBUG DEBUG + LogHeader, indicesCount); // DEBUG + ret = true; + } + catch (Exception e) + { + physicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh. Base={1}, e={2}", + LogHeader, extentBase, e); + } + + indicesCountO = indicesCount; + indicesO = indices; + verticesCountO = verticesCount; + verticesO = vertices; + + return ret; + } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index bab3b3d..a2271a9 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -391,13 +391,13 @@ public enum CollisionFilterGroups : uint ObjectFilter = BSolidFilter, ObjectMask = BAllFilter, StaticObjectFilter = BStaticFilter, - StaticObjectMask = BAllFilter, + StaticObjectMask = BAllFilter & ~BStaticFilter, // static objects don't collide with each other LinksetFilter = BLinksetFilter, - LinksetMask = BAllFilter & ~BLinksetFilter, + LinksetMask = BAllFilter & ~BLinksetFilter, // linkset objects don't collide with each other VolumeDetectFilter = BSensorTrigger, VolumeDetectMask = ~BSensorTrigger, TerrainFilter = BTerrainFilter, - TerrainMask = BAllFilter & ~BStaticFilter, + TerrainMask = BAllFilter & ~BStaticFilter, // static objects on the ground don't collide GroundPlaneFilter = BGroundPlaneFilter, GroundPlaneMask = BAllFilter -- cgit v1.1 From 2dc7e9d3fa091418814af90565244a8c1972feec Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Tue, 20 Nov 2012 20:38:51 -0800 Subject: BulletSim: fix line endings to be all Linux style (windows style keeps creeping in) --- .../Physics/BulletSPlugin/BSTerrainHeightmap.cs | 340 ++++++------ .../Region/Physics/BulletSPlugin/BSTerrainMesh.cs | 568 ++++++++++----------- 2 files changed, 454 insertions(+), 454 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs index e9fd0cb..8fc36d1 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs @@ -1,170 +1,170 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; - -using OpenSim.Framework; -using OpenSim.Region.Framework; -using OpenSim.Region.CoreModules; -using OpenSim.Region.Physics.Manager; - -using Nini.Config; -using log4net; - -using OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ -public sealed class BSTerrainHeightmap : BSTerrainPhys -{ - static string LogHeader = "[BULLETSIM TERRAIN HEIGHTMAP]"; - - BulletHeightMapInfo m_mapInfo = null; - - // Constructor to build a default, flat heightmap terrain. - public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize) - : base(physicsScene, regionBase, id) - { - Vector3 minTerrainCoords = new Vector3(0f, 0f, BSTerrainManager.HEIGHT_INITIALIZATION - BSTerrainManager.HEIGHT_EQUAL_FUDGE); - Vector3 maxTerrainCoords = new Vector3(regionSize.X, regionSize.Y, BSTerrainManager.HEIGHT_INITIALIZATION); - int totalHeights = (int)maxTerrainCoords.X * (int)maxTerrainCoords.Y; - float[] initialMap = new float[totalHeights]; - for (int ii = 0; ii < totalHeights; ii++) - { - initialMap[ii] = BSTerrainManager.HEIGHT_INITIALIZATION; - } - m_mapInfo = new BulletHeightMapInfo(id, initialMap, IntPtr.Zero); - m_mapInfo.minCoords = minTerrainCoords; - m_mapInfo.maxCoords = maxTerrainCoords; - m_mapInfo.terrainRegionBase = TerrainBase; - // Don't have to free any previous since we just got here. - BuildHeightmapTerrain(); - } - - // This minCoords and maxCoords passed in give the size of the terrain (min and max Z - // are the high and low points of the heightmap). - public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap, - Vector3 minCoords, Vector3 maxCoords) - : base(physicsScene, regionBase, id) - { - m_mapInfo = new BulletHeightMapInfo(id, initialMap, IntPtr.Zero); - m_mapInfo.minCoords = minCoords; - m_mapInfo.maxCoords = maxCoords; - m_mapInfo.minZ = minCoords.Z; - m_mapInfo.maxZ = maxCoords.Z; - m_mapInfo.terrainRegionBase = TerrainBase; - - // Don't have to free any previous since we just got here. - BuildHeightmapTerrain(); - } - - public override void Dispose() - { - ReleaseHeightMapTerrain(); - } - - // Using the information in m_mapInfo, create the physical representation of the heightmap. - private void BuildHeightmapTerrain() - { - m_mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, m_mapInfo.ID, - m_mapInfo.minCoords, m_mapInfo.maxCoords, - m_mapInfo.heightMap, BSTerrainManager.TERRAIN_COLLISION_MARGIN); - - // Create the terrain shape from the mapInfo - m_mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(m_mapInfo.Ptr), - PhysicsShapeType.SHAPE_TERRAIN); - - // The terrain object initial position is at the center of the object - Vector3 centerPos; - centerPos.X = m_mapInfo.minCoords.X + (m_mapInfo.sizeX / 2f); - centerPos.Y = m_mapInfo.minCoords.Y + (m_mapInfo.sizeY / 2f); - centerPos.Z = m_mapInfo.minZ + ((m_mapInfo.maxZ - m_mapInfo.minZ) / 2f); - - m_mapInfo.terrainBody = new BulletBody(m_mapInfo.ID, - BulletSimAPI.CreateBodyWithDefaultMotionState2(m_mapInfo.terrainShape.ptr, - m_mapInfo.ID, centerPos, Quaternion.Identity)); - - // Set current terrain attributes - BulletSimAPI.SetFriction2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainFriction); - BulletSimAPI.SetHitFraction2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainHitFraction); - BulletSimAPI.SetRestitution2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainRestitution); - BulletSimAPI.SetCollisionFlags2(m_mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); - - // Return the new terrain to the world of physical objects - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); - - // redo its bounding box now that it is in the world - BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); - - BulletSimAPI.SetCollisionFilterMask2(m_mapInfo.terrainBody.ptr, - (uint)CollisionFilterGroups.TerrainFilter, - (uint)CollisionFilterGroups.TerrainMask); - - // Make it so the terrain will not move or be considered for movement. - BulletSimAPI.ForceActivationState2(m_mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION); - - return; - } - - // If there is information in m_mapInfo pointing to physical structures, release same. - private void ReleaseHeightMapTerrain() - { - if (m_mapInfo != null) - { - if (m_mapInfo.terrainBody.ptr != IntPtr.Zero) - { - BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); - // Frees both the body and the shape. - BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); - BulletSimAPI.ReleaseHeightMapInfo2(m_mapInfo.Ptr); - } - } - m_mapInfo = null; - } - - // The passed position is relative to the base of the region. - public override float GetHeightAtXYZ(Vector3 pos) - { - float ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; - - int mapIndex = (int)pos.Y * (int)m_mapInfo.sizeY + (int)pos.X; - try - { - ret = m_mapInfo.heightMap[mapIndex]; - } - catch - { - // Sometimes they give us wonky values of X and Y. Give a warning and return something. - PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}", - LogHeader, m_mapInfo.terrainRegionBase, pos); - ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; - } - return ret; - } -} -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyrightD + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections.Generic; +using System.Text; + +using OpenSim.Framework; +using OpenSim.Region.Framework; +using OpenSim.Region.CoreModules; +using OpenSim.Region.Physics.Manager; + +using Nini.Config; +using log4net; + +using OpenMetaverse; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ +public sealed class BSTerrainHeightmap : BSTerrainPhys +{ + static string LogHeader = "[BULLETSIM TERRAIN HEIGHTMAP]"; + + BulletHeightMapInfo m_mapInfo = null; + + // Constructor to build a default, flat heightmap terrain. + public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize) + : base(physicsScene, regionBase, id) + { + Vector3 minTerrainCoords = new Vector3(0f, 0f, BSTerrainManager.HEIGHT_INITIALIZATION - BSTerrainManager.HEIGHT_EQUAL_FUDGE); + Vector3 maxTerrainCoords = new Vector3(regionSize.X, regionSize.Y, BSTerrainManager.HEIGHT_INITIALIZATION); + int totalHeights = (int)maxTerrainCoords.X * (int)maxTerrainCoords.Y; + float[] initialMap = new float[totalHeights]; + for (int ii = 0; ii < totalHeights; ii++) + { + initialMap[ii] = BSTerrainManager.HEIGHT_INITIALIZATION; + } + m_mapInfo = new BulletHeightMapInfo(id, initialMap, IntPtr.Zero); + m_mapInfo.minCoords = minTerrainCoords; + m_mapInfo.maxCoords = maxTerrainCoords; + m_mapInfo.terrainRegionBase = TerrainBase; + // Don't have to free any previous since we just got here. + BuildHeightmapTerrain(); + } + + // This minCoords and maxCoords passed in give the size of the terrain (min and max Z + // are the high and low points of the heightmap). + public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap, + Vector3 minCoords, Vector3 maxCoords) + : base(physicsScene, regionBase, id) + { + m_mapInfo = new BulletHeightMapInfo(id, initialMap, IntPtr.Zero); + m_mapInfo.minCoords = minCoords; + m_mapInfo.maxCoords = maxCoords; + m_mapInfo.minZ = minCoords.Z; + m_mapInfo.maxZ = maxCoords.Z; + m_mapInfo.terrainRegionBase = TerrainBase; + + // Don't have to free any previous since we just got here. + BuildHeightmapTerrain(); + } + + public override void Dispose() + { + ReleaseHeightMapTerrain(); + } + + // Using the information in m_mapInfo, create the physical representation of the heightmap. + private void BuildHeightmapTerrain() + { + m_mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, m_mapInfo.ID, + m_mapInfo.minCoords, m_mapInfo.maxCoords, + m_mapInfo.heightMap, BSTerrainManager.TERRAIN_COLLISION_MARGIN); + + // Create the terrain shape from the mapInfo + m_mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(m_mapInfo.Ptr), + PhysicsShapeType.SHAPE_TERRAIN); + + // The terrain object initial position is at the center of the object + Vector3 centerPos; + centerPos.X = m_mapInfo.minCoords.X + (m_mapInfo.sizeX / 2f); + centerPos.Y = m_mapInfo.minCoords.Y + (m_mapInfo.sizeY / 2f); + centerPos.Z = m_mapInfo.minZ + ((m_mapInfo.maxZ - m_mapInfo.minZ) / 2f); + + m_mapInfo.terrainBody = new BulletBody(m_mapInfo.ID, + BulletSimAPI.CreateBodyWithDefaultMotionState2(m_mapInfo.terrainShape.ptr, + m_mapInfo.ID, centerPos, Quaternion.Identity)); + + // Set current terrain attributes + BulletSimAPI.SetFriction2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainFriction); + BulletSimAPI.SetHitFraction2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainHitFraction); + BulletSimAPI.SetRestitution2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainRestitution); + BulletSimAPI.SetCollisionFlags2(m_mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); + + // Return the new terrain to the world of physical objects + BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); + + // redo its bounding box now that it is in the world + BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); + + BulletSimAPI.SetCollisionFilterMask2(m_mapInfo.terrainBody.ptr, + (uint)CollisionFilterGroups.TerrainFilter, + (uint)CollisionFilterGroups.TerrainMask); + + // Make it so the terrain will not move or be considered for movement. + BulletSimAPI.ForceActivationState2(m_mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION); + + return; + } + + // If there is information in m_mapInfo pointing to physical structures, release same. + private void ReleaseHeightMapTerrain() + { + if (m_mapInfo != null) + { + if (m_mapInfo.terrainBody.ptr != IntPtr.Zero) + { + BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); + // Frees both the body and the shape. + BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); + BulletSimAPI.ReleaseHeightMapInfo2(m_mapInfo.Ptr); + } + } + m_mapInfo = null; + } + + // The passed position is relative to the base of the region. + public override float GetHeightAtXYZ(Vector3 pos) + { + float ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; + + int mapIndex = (int)pos.Y * (int)m_mapInfo.sizeY + (int)pos.X; + try + { + ret = m_mapInfo.heightMap[mapIndex]; + } + catch + { + // Sometimes they give us wonky values of X and Y. Give a warning and return something. + PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}", + LogHeader, m_mapInfo.terrainRegionBase, pos); + ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; + } + return ret; + } +} +} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs index bbb014a..a199078 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs @@ -1,284 +1,284 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyrightD - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -using System; -using System.Collections.Generic; -using System.Text; - -using OpenSim.Framework; -using OpenSim.Region.Framework; -using OpenSim.Region.CoreModules; -using OpenSim.Region.Physics.Manager; - -using Nini.Config; -using log4net; - -using OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ -public sealed class BSTerrainMesh : BSTerrainPhys -{ - static string LogHeader = "[BULLETSIM TERRAIN MESH]"; - - private float[] m_savedHeightMap; - int m_sizeX; - int m_sizeY; - - BulletShape m_terrainShape; - BulletBody m_terrainBody; - - public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize) - : base(physicsScene, regionBase, id) - { - } - - public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id /* parameters for making mesh */) - : base(physicsScene, regionBase, id) - { - } - - // Create terrain mesh from a heightmap. - public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap, - Vector3 minCoords, Vector3 maxCoords) - : base(physicsScene, regionBase, id) - { - int indicesCount; - int[] indices; - int verticesCount; - float[] vertices; - - m_savedHeightMap = initialMap; - - m_sizeX = (int)(maxCoords.X - minCoords.X); - m_sizeY = (int)(maxCoords.Y - minCoords.Y); - - if (!BSTerrainMesh.ConvertHeightmapToMesh(PhysicsScene, initialMap, m_sizeX, m_sizeY, - (float)m_sizeX, (float)m_sizeY, - Vector3.Zero, 1.0f, - out indicesCount, out indices, out verticesCount, out vertices)) - { - // DISASTER!! - PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedConversionOfHeightmap", ID); - PhysicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh! base={1}", LogHeader, TerrainBase); - // Something is very messed up and a crash is in our future. - return; - } - PhysicsScene.DetailLog("{0},BSTerrainMesh.create,afterConvertHeightmapToMesh,ver={1},ind={2}", - ID, verticesCount, indicesCount); - - m_terrainShape = new BulletShape(BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, - indicesCount, indices, verticesCount, vertices), - PhysicsShapeType.SHAPE_MESH); - if (m_terrainShape.ptr == IntPtr.Zero) - { - // DISASTER!! - PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedCreationOfShape", ID); - physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain mesh! base={1}", LogHeader, TerrainBase); - // Something is very messed up and a crash is in our future. - return; - } - PhysicsScene.DetailLog("{0},BSTerrainMesh.create,afterCreateShape,shape={1}", ID, m_terrainShape); - - // The terrain object initial position is at the center of the object - Vector3 centerPos; - centerPos.X = minCoords.X + (m_sizeX / 2f); - centerPos.Y = minCoords.Y + (m_sizeY / 2f); - centerPos.Z = minCoords.Z + ((maxCoords.Z - minCoords.Z) / 2f); - Quaternion rot = Quaternion.Identity; - - PhysicsScene.DetailLog("{0},BSTerrainMesh.create,creatingBody,centerPos={1},rot={2}", ID, centerPos, rot); - m_terrainBody = new BulletBody(id, BulletSimAPI.CreateBodyWithDefaultMotionState2( - m_terrainShape.ptr, ID, centerPos, rot)); - if (m_terrainBody.ptr == IntPtr.Zero) - { - // DISASTER!! - physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain body! base={1}", LogHeader, TerrainBase); - // Something is very messed up and a crash is in our future. - return; - } - PhysicsScene.DetailLog("{0},BSTerrainMesh.create,afterCreateBody,body={1}", ID, m_terrainBody); - - // Set current terrain attributes - BulletSimAPI.SetFriction2(m_terrainBody.ptr, PhysicsScene.Params.terrainFriction); - BulletSimAPI.SetHitFraction2(m_terrainBody.ptr, PhysicsScene.Params.terrainHitFraction); - BulletSimAPI.SetRestitution2(m_terrainBody.ptr, PhysicsScene.Params.terrainRestitution); - BulletSimAPI.SetCollisionFlags2(m_terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); - - // Static objects are not very massive. - BulletSimAPI.SetMassProps2(m_terrainBody.ptr, 0f, Vector3.Zero); - - // Return the new terrain to the world of physical objects - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_terrainBody.ptr); - - // redo its bounding box now that it is in the world - BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_terrainBody.ptr); - - BulletSimAPI.SetCollisionFilterMask2(m_terrainBody.ptr, - (uint)CollisionFilterGroups.TerrainFilter, - (uint)CollisionFilterGroups.TerrainMask); - - // Make it so the terrain will not move or be considered for movement. - BulletSimAPI.ForceActivationState2(m_terrainBody.ptr, ActivationState.DISABLE_SIMULATION); - } - - public override void Dispose() - { - if (m_terrainBody.ptr != IntPtr.Zero) - { - BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_terrainBody.ptr); - // Frees both the body and the shape. - BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_terrainBody.ptr); - } - } - - public override float GetHeightAtXYZ(Vector3 pos) - { - // For the moment use the saved heightmap to get the terrain height. - // TODO: raycast downward to find the true terrain below the position. - float ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; - - int mapIndex = (int)pos.Y * m_sizeY + (int)pos.X; - try - { - ret = m_savedHeightMap[mapIndex]; - } - catch - { - // Sometimes they give us wonky values of X and Y. Give a warning and return something. - PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}", - LogHeader, TerrainBase, pos); - ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; - } - return ret; - } - - // Convert the passed heightmap to mesh information suitable for CreateMeshShape2(). - // Return 'true' if successfully created. - public static bool ConvertHeightmapToMesh( - BSScene physicsScene, - float[] heightMap, int sizeX, int sizeY, // parameters of incoming heightmap - float extentX, float extentY, // zero based range for output vertices - Vector3 extentBase, // base to be added to all vertices - float magnification, // number of vertices to create between heightMap coords - out int indicesCountO, out int[] indicesO, - out int verticesCountO, out float[] verticesO) - { - bool ret = false; - - int indicesCount = 0; - int verticesCount = 0; - int[] indices = new int[0]; - float[] vertices = new float[0]; - - // Simple mesh creation which assumes magnification == 1, sizeX == extentX and sizeY == extentY. - // TODO: do a more general solution that scales, adds new vertices and smoothes the result. - - try - { - // One vertice per heightmap value plus the vertices off the top and bottom edge. - int totalVertices = (sizeX + 1) * (sizeY + 1); - vertices = new float[totalVertices * 3]; - int totalIndices = sizeX * sizeY * 6; - indices = new int[totalIndices]; - - physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,totVert={1},totInd={2}", - BSScene.DetailLogZero, totalVertices, totalIndices); - float magX = (float)sizeX / extentX; - float magY = (float)sizeY / extentY; - // Note that sizeX+1 vertices are created since there is land between this and the next region. - for (int yy = 0; yy <= sizeY; yy++) - { - for (int xx = 0; xx <= sizeX; xx++) // Hint: the "<=" means we got through sizeX + 1 times - { - int offset = yy * sizeX + xx; - // Extend the height from the height from the last row or column - if (yy == sizeY) offset -= sizeX; - if (xx == sizeX) offset -= 1; - float height = heightMap[offset]; - vertices[verticesCount + 0] = (float)xx * magX + extentBase.X; - vertices[verticesCount + 1] = (float)yy * magY + extentBase.Y; - vertices[verticesCount + 2] = height + extentBase.Z; - if (physicsScene.PhysicsLogging.Enabled && verticesCount < 900) // DEBUG DEBUG DEBUG - { - Vector3 genVertex = new Vector3( - vertices[verticesCount + 0], - vertices[verticesCount + 1], - vertices[verticesCount + 2]); - physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,ii={1},vertex={2}", - BSScene.DetailLogZero, verticesCount/3, genVertex); - } - verticesCount += 3; - } - } - verticesCount = verticesCount / 3; - physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,completeVerts,verCount={1}", - BSScene.DetailLogZero, verticesCount); - - for (int yy = 0; yy < sizeY; yy++) - { - for (int xx = 0; xx < sizeX; xx++) - { - int offset = yy * sizeX + xx; - // Each vertices is presumed to be the upper left corner of a box of two triangles - indices[indicesCount + 0] = offset; - indices[indicesCount + 1] = offset + 1; - indices[indicesCount + 2] = offset + sizeX + 1; // accounting for the extra column - indices[indicesCount + 3] = offset + 1; - indices[indicesCount + 4] = offset + sizeX + 2; - indices[indicesCount + 5] = offset + sizeX + 1; - if (indicesCount < (300 * 6)) // DEBUG DEBUG DEBUG - physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,i0={1},i1={2},i2={3},i3={4},i4={5},i5={6}", // DEEBUG DEBUG DEBUG - BSScene.DetailLogZero, - indices[indicesCount + 0], - indices[indicesCount + 1], - indices[indicesCount + 2], - indices[indicesCount + 3], - indices[indicesCount + 4], - indices[indicesCount + 5] - ); - indicesCount += 6; - } - } - physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,completeIndices,indCount={1}", // DEEBUG DEBUG DEBUG - LogHeader, indicesCount); // DEBUG - ret = true; - } - catch (Exception e) - { - physicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh. Base={1}, e={2}", - LogHeader, extentBase, e); - } - - indicesCountO = indicesCount; - indicesO = indices; - verticesCountO = verticesCount; - verticesO = vertices; - - return ret; - } -} -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyrightD + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections.Generic; +using System.Text; + +using OpenSim.Framework; +using OpenSim.Region.Framework; +using OpenSim.Region.CoreModules; +using OpenSim.Region.Physics.Manager; + +using Nini.Config; +using log4net; + +using OpenMetaverse; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ +public sealed class BSTerrainMesh : BSTerrainPhys +{ + static string LogHeader = "[BULLETSIM TERRAIN MESH]"; + + private float[] m_savedHeightMap; + int m_sizeX; + int m_sizeY; + + BulletShape m_terrainShape; + BulletBody m_terrainBody; + + public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize) + : base(physicsScene, regionBase, id) + { + } + + public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id /* parameters for making mesh */) + : base(physicsScene, regionBase, id) + { + } + + // Create terrain mesh from a heightmap. + public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap, + Vector3 minCoords, Vector3 maxCoords) + : base(physicsScene, regionBase, id) + { + int indicesCount; + int[] indices; + int verticesCount; + float[] vertices; + + m_savedHeightMap = initialMap; + + m_sizeX = (int)(maxCoords.X - minCoords.X); + m_sizeY = (int)(maxCoords.Y - minCoords.Y); + + if (!BSTerrainMesh.ConvertHeightmapToMesh(PhysicsScene, initialMap, m_sizeX, m_sizeY, + (float)m_sizeX, (float)m_sizeY, + Vector3.Zero, 1.0f, + out indicesCount, out indices, out verticesCount, out vertices)) + { + // DISASTER!! + PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedConversionOfHeightmap", ID); + PhysicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh! base={1}", LogHeader, TerrainBase); + // Something is very messed up and a crash is in our future. + return; + } + PhysicsScene.DetailLog("{0},BSTerrainMesh.create,afterConvertHeightmapToMesh,ver={1},ind={2}", + ID, verticesCount, indicesCount); + + m_terrainShape = new BulletShape(BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, + indicesCount, indices, verticesCount, vertices), + PhysicsShapeType.SHAPE_MESH); + if (m_terrainShape.ptr == IntPtr.Zero) + { + // DISASTER!! + PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedCreationOfShape", ID); + physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain mesh! base={1}", LogHeader, TerrainBase); + // Something is very messed up and a crash is in our future. + return; + } + PhysicsScene.DetailLog("{0},BSTerrainMesh.create,afterCreateShape,shape={1}", ID, m_terrainShape); + + // The terrain object initial position is at the center of the object + Vector3 centerPos; + centerPos.X = minCoords.X + (m_sizeX / 2f); + centerPos.Y = minCoords.Y + (m_sizeY / 2f); + centerPos.Z = minCoords.Z + ((maxCoords.Z - minCoords.Z) / 2f); + Quaternion rot = Quaternion.Identity; + + PhysicsScene.DetailLog("{0},BSTerrainMesh.create,creatingBody,centerPos={1},rot={2}", ID, centerPos, rot); + m_terrainBody = new BulletBody(id, BulletSimAPI.CreateBodyWithDefaultMotionState2( + m_terrainShape.ptr, ID, centerPos, rot)); + if (m_terrainBody.ptr == IntPtr.Zero) + { + // DISASTER!! + physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain body! base={1}", LogHeader, TerrainBase); + // Something is very messed up and a crash is in our future. + return; + } + PhysicsScene.DetailLog("{0},BSTerrainMesh.create,afterCreateBody,body={1}", ID, m_terrainBody); + + // Set current terrain attributes + BulletSimAPI.SetFriction2(m_terrainBody.ptr, PhysicsScene.Params.terrainFriction); + BulletSimAPI.SetHitFraction2(m_terrainBody.ptr, PhysicsScene.Params.terrainHitFraction); + BulletSimAPI.SetRestitution2(m_terrainBody.ptr, PhysicsScene.Params.terrainRestitution); + BulletSimAPI.SetCollisionFlags2(m_terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); + + // Static objects are not very massive. + BulletSimAPI.SetMassProps2(m_terrainBody.ptr, 0f, Vector3.Zero); + + // Return the new terrain to the world of physical objects + BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_terrainBody.ptr); + + // redo its bounding box now that it is in the world + BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_terrainBody.ptr); + + BulletSimAPI.SetCollisionFilterMask2(m_terrainBody.ptr, + (uint)CollisionFilterGroups.TerrainFilter, + (uint)CollisionFilterGroups.TerrainMask); + + // Make it so the terrain will not move or be considered for movement. + BulletSimAPI.ForceActivationState2(m_terrainBody.ptr, ActivationState.DISABLE_SIMULATION); + } + + public override void Dispose() + { + if (m_terrainBody.ptr != IntPtr.Zero) + { + BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_terrainBody.ptr); + // Frees both the body and the shape. + BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_terrainBody.ptr); + } + } + + public override float GetHeightAtXYZ(Vector3 pos) + { + // For the moment use the saved heightmap to get the terrain height. + // TODO: raycast downward to find the true terrain below the position. + float ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; + + int mapIndex = (int)pos.Y * m_sizeY + (int)pos.X; + try + { + ret = m_savedHeightMap[mapIndex]; + } + catch + { + // Sometimes they give us wonky values of X and Y. Give a warning and return something. + PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}", + LogHeader, TerrainBase, pos); + ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; + } + return ret; + } + + // Convert the passed heightmap to mesh information suitable for CreateMeshShape2(). + // Return 'true' if successfully created. + public static bool ConvertHeightmapToMesh( + BSScene physicsScene, + float[] heightMap, int sizeX, int sizeY, // parameters of incoming heightmap + float extentX, float extentY, // zero based range for output vertices + Vector3 extentBase, // base to be added to all vertices + float magnification, // number of vertices to create between heightMap coords + out int indicesCountO, out int[] indicesO, + out int verticesCountO, out float[] verticesO) + { + bool ret = false; + + int indicesCount = 0; + int verticesCount = 0; + int[] indices = new int[0]; + float[] vertices = new float[0]; + + // Simple mesh creation which assumes magnification == 1, sizeX == extentX and sizeY == extentY. + // TODO: do a more general solution that scales, adds new vertices and smoothes the result. + + try + { + // One vertice per heightmap value plus the vertices off the top and bottom edge. + int totalVertices = (sizeX + 1) * (sizeY + 1); + vertices = new float[totalVertices * 3]; + int totalIndices = sizeX * sizeY * 6; + indices = new int[totalIndices]; + + physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,totVert={1},totInd={2}", + BSScene.DetailLogZero, totalVertices, totalIndices); + float magX = (float)sizeX / extentX; + float magY = (float)sizeY / extentY; + // Note that sizeX+1 vertices are created since there is land between this and the next region. + for (int yy = 0; yy <= sizeY; yy++) + { + for (int xx = 0; xx <= sizeX; xx++) // Hint: the "<=" means we got through sizeX + 1 times + { + int offset = yy * sizeX + xx; + // Extend the height from the height from the last row or column + if (yy == sizeY) offset -= sizeX; + if (xx == sizeX) offset -= 1; + float height = heightMap[offset]; + vertices[verticesCount + 0] = (float)xx * magX + extentBase.X; + vertices[verticesCount + 1] = (float)yy * magY + extentBase.Y; + vertices[verticesCount + 2] = height + extentBase.Z; + if (physicsScene.PhysicsLogging.Enabled && verticesCount < 900) // DEBUG DEBUG DEBUG + { + Vector3 genVertex = new Vector3( + vertices[verticesCount + 0], + vertices[verticesCount + 1], + vertices[verticesCount + 2]); + physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,ii={1},vertex={2}", + BSScene.DetailLogZero, verticesCount/3, genVertex); + } + verticesCount += 3; + } + } + verticesCount = verticesCount / 3; + physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,completeVerts,verCount={1}", + BSScene.DetailLogZero, verticesCount); + + for (int yy = 0; yy < sizeY; yy++) + { + for (int xx = 0; xx < sizeX; xx++) + { + int offset = yy * sizeX + xx; + // Each vertices is presumed to be the upper left corner of a box of two triangles + indices[indicesCount + 0] = offset; + indices[indicesCount + 1] = offset + 1; + indices[indicesCount + 2] = offset + sizeX + 1; // accounting for the extra column + indices[indicesCount + 3] = offset + 1; + indices[indicesCount + 4] = offset + sizeX + 2; + indices[indicesCount + 5] = offset + sizeX + 1; + if (indicesCount < (300 * 6)) // DEBUG DEBUG DEBUG + physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,i0={1},i1={2},i2={3},i3={4},i4={5},i5={6}", // DEEBUG DEBUG DEBUG + BSScene.DetailLogZero, + indices[indicesCount + 0], + indices[indicesCount + 1], + indices[indicesCount + 2], + indices[indicesCount + 3], + indices[indicesCount + 4], + indices[indicesCount + 5] + ); + indicesCount += 6; + } + } + physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,completeIndices,indCount={1}", // DEEBUG DEBUG DEBUG + LogHeader, indicesCount); // DEBUG + ret = true; + } + catch (Exception e) + { + physicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh. Base={1}, e={2}", + LogHeader, extentBase, e); + } + + indicesCountO = indicesCount; + indicesO = indices; + verticesCountO = verticesCount; + verticesO = vertices; + + return ret; + } +} +} -- cgit v1.1 From a59368c4a1889ccd79da9e564ee84b213a7f6fbd Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 21 Nov 2012 10:37:40 -0800 Subject: BulletSim: add terrainImplementation parameter with default to Mesh. --- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 5 +++ .../Physics/BulletSPlugin/BSTerrainManager.cs | 45 +++++++++++++++++++--- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 1 + 3 files changed, 46 insertions(+), 5 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 58dccea..0e73d04 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -1145,6 +1145,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); }, (s,o,v) => { BulletSimAPI.SetContactProcessingThreshold2(o.PhysBody.ptr, v); } ), + new ParameterDefn("TerrainImplementation", "Type of shape to use for terrain (0=heightmap, 1=mesh)", + (float)BSTerrainPhys.TerrainImplementation.Mesh, + (s,cf,p,v) => { s.m_params[0].terrainImplementation = cf.GetFloat(p,v); }, + (s) => { return s.m_params[0].terrainImplementation; }, + (s,p,l,v) => { s.m_params[0].terrainImplementation = 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); }, diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index ed0dfa8..b88f561 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -44,6 +44,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin // The physical implementation of the terrain is wrapped in this class. public abstract class BSTerrainPhys : IDisposable { + public enum TerrainImplementation + { + Heightmap = 0, + Mesh = 1 + } + public BSScene PhysicsScene { get; private set; } // Base of the region in world coordinates. Coordinates inside the region are relative to this. public Vector3 TerrainBase { get; private set; } @@ -246,12 +252,27 @@ public sealed class BSTerrainManager // Release any physical memory it may be using. terrainPhys.Dispose(); + BSTerrainPhys newTerrainPhys = null; ; if (MegaRegionParentPhysicsScene == null) { - // BSTerrainPhys newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, terrainRegionBase, id, - // heightMap, minCoords, maxCoords); - BSTerrainPhys newTerrainPhys = new BSTerrainMesh(PhysicsScene, terrainRegionBase, id, + // TODO: redo terrain implementation selection to be centralized (there is another + // use below) and to accept an asset specification (for a mesh). + switch ((int)PhysicsScene.Params.terrainImplementation) + { + case (int)BSTerrainPhys.TerrainImplementation.Heightmap: + newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, terrainRegionBase, id, + heightMap, minCoords, maxCoords); + break; + case (int)BSTerrainPhys.TerrainImplementation.Mesh: + newTerrainPhys = new BSTerrainMesh(PhysicsScene, terrainRegionBase, id, heightMap, minCoords, maxCoords); + break; + default: + PhysicsScene.Logger.ErrorFormat("{0} Bad terrain implementation specified. type={1}/{2}", + LogHeader, (int)PhysicsScene.Params.terrainImplementation, PhysicsScene.Params.terrainImplementation); + break; + } + m_terrains.Add(terrainRegionBase, newTerrainPhys); m_terrainModified = true; @@ -292,8 +313,22 @@ public sealed class BSTerrainManager { DetailLog("{0},UpdateTerrain:NewTerrain,taint,baseX={1},baseY={2}", BSScene.DetailLogZero, minCoordsX.X, minCoordsX.Y); - BSTerrainPhys newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, terrainRegionBase, - newTerrainID, heightMapX, minCoordsX, maxCoordsX); + BSTerrainPhys newTerrainPhys = null; + switch ((int)PhysicsScene.Params.terrainImplementation) + { + case (int)BSTerrainPhys.TerrainImplementation.Heightmap: + newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, terrainRegionBase, id, + heightMap, minCoords, maxCoords); + break; + case (int)BSTerrainPhys.TerrainImplementation.Mesh: + newTerrainPhys = new BSTerrainMesh(PhysicsScene, terrainRegionBase, id, + heightMap, minCoords, maxCoords); + break; + default: + PhysicsScene.Logger.ErrorFormat("{0} Bad terrain implementation specified. type={1}/{2}", + LogHeader, (int)PhysicsScene.Params.terrainImplementation, PhysicsScene.Params.terrainImplementation); + break; + } m_terrains.Add(terrainRegionBase, newTerrainPhys); m_terrainModified = true; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index a2271a9..e218053 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -283,6 +283,7 @@ public struct ConfigurationParameters public float ccdSweptSphereRadius; public float contactProcessingThreshold; + public float terrainImplementation; public float terrainFriction; public float terrainHitFraction; public float terrainRestitution; -- cgit v1.1 From 4a0de0170412a939bade6cd149c94c7fd3ef020e Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 21 Nov 2012 13:44:02 -0800 Subject: BulletSim: Properly position mesh terrain on creation (fixes terrain not appearing to be working). Centralize terrain shape creation logic. Remove very chatty detail log messages. --- .../Physics/BulletSPlugin/BSTerrainManager.cs | 74 ++++++++++------------ .../Region/Physics/BulletSPlugin/BSTerrainMesh.cs | 46 +++----------- 2 files changed, 44 insertions(+), 76 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index b88f561..097cd3e 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -241,38 +241,20 @@ public sealed class BSTerrainManager BSTerrainPhys terrainPhys; if (m_terrains.TryGetValue(terrainRegionBase, out terrainPhys)) { - // If this is terrain we know about, it's easy to update - - DetailLog("{0},UpdateTerrain:UpdateExisting,call,terrainBase={1}", BSScene.DetailLogZero, terrainRegionBase); + // There is already a terrain in this spot. Free the old and build the new. + DetailLog("{0},UpdateTerrain:UpdateExisting,call,id={1},base={2},minC={3},maxC={4}", + BSScene.DetailLogZero, id, terrainRegionBase, minCoords, minCoords); PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateTerrain:UpdateExisting", delegate() { // Remove old terrain from the collection - m_terrains.Remove(terrainPhys.TerrainBase); + m_terrains.Remove(terrainRegionBase); // Release any physical memory it may be using. terrainPhys.Dispose(); - BSTerrainPhys newTerrainPhys = null; ; if (MegaRegionParentPhysicsScene == null) { - // TODO: redo terrain implementation selection to be centralized (there is another - // use below) and to accept an asset specification (for a mesh). - switch ((int)PhysicsScene.Params.terrainImplementation) - { - case (int)BSTerrainPhys.TerrainImplementation.Heightmap: - newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, terrainRegionBase, id, - heightMap, minCoords, maxCoords); - break; - case (int)BSTerrainPhys.TerrainImplementation.Mesh: - newTerrainPhys = new BSTerrainMesh(PhysicsScene, terrainRegionBase, id, - heightMap, minCoords, maxCoords); - break; - default: - PhysicsScene.Logger.ErrorFormat("{0} Bad terrain implementation specified. type={1}/{2}", - LogHeader, (int)PhysicsScene.Params.terrainImplementation, PhysicsScene.Params.terrainImplementation); - break; - } - + BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords); m_terrains.Add(terrainRegionBase, newTerrainPhys); m_terrainModified = true; @@ -313,22 +295,7 @@ public sealed class BSTerrainManager { DetailLog("{0},UpdateTerrain:NewTerrain,taint,baseX={1},baseY={2}", BSScene.DetailLogZero, minCoordsX.X, minCoordsX.Y); - BSTerrainPhys newTerrainPhys = null; - switch ((int)PhysicsScene.Params.terrainImplementation) - { - case (int)BSTerrainPhys.TerrainImplementation.Heightmap: - newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, terrainRegionBase, id, - heightMap, minCoords, maxCoords); - break; - case (int)BSTerrainPhys.TerrainImplementation.Mesh: - newTerrainPhys = new BSTerrainMesh(PhysicsScene, terrainRegionBase, id, - heightMap, minCoords, maxCoords); - break; - default: - PhysicsScene.Logger.ErrorFormat("{0} Bad terrain implementation specified. type={1}/{2}", - LogHeader, (int)PhysicsScene.Params.terrainImplementation, PhysicsScene.Params.terrainImplementation); - break; - } + BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords); m_terrains.Add(terrainRegionBase, newTerrainPhys); m_terrainModified = true; @@ -336,6 +303,35 @@ public sealed class BSTerrainManager } } + // TODO: redo terrain implementation selection to allow other base types than heightMap. + private BSTerrainPhys BuildPhysicalTerrain(Vector3 terrainRegionBase, uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords) + { + PhysicsScene.Logger.DebugFormat("{0} Terrain for {1}/{2} created with {3}", + LogHeader, PhysicsScene.RegionName, terrainRegionBase, + PhysicsScene.Params.terrainImplementation); + BSTerrainPhys newTerrainPhys = null; + switch ((int)PhysicsScene.Params.terrainImplementation) + { + case (int)BSTerrainPhys.TerrainImplementation.Heightmap: + newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, terrainRegionBase, id, + heightMap, minCoords, maxCoords); + break; + case (int)BSTerrainPhys.TerrainImplementation.Mesh: + newTerrainPhys = new BSTerrainMesh(PhysicsScene, terrainRegionBase, id, + heightMap, minCoords, maxCoords); + break; + default: + PhysicsScene.Logger.ErrorFormat("{0} Bad terrain implementation specified. Type={1}/{2},Region={3}/{4}", + LogHeader, + (int)PhysicsScene.Params.terrainImplementation, + PhysicsScene.Params.terrainImplementation, + PhysicsScene.RegionName, terrainRegionBase); + break; + } + return newTerrainPhys; + } + + // Given an X and Y, find the height of the terrain. // Since we could be handling multiple terrains for a mega-region, // the base of the region is calcuated assuming all regions are diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs index a199078..3279b6f 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs @@ -76,7 +76,8 @@ public sealed class BSTerrainMesh : BSTerrainPhys m_sizeX = (int)(maxCoords.X - minCoords.X); m_sizeY = (int)(maxCoords.Y - minCoords.Y); - if (!BSTerrainMesh.ConvertHeightmapToMesh(PhysicsScene, initialMap, m_sizeX, m_sizeY, + if (!BSTerrainMesh.ConvertHeightmapToMesh(PhysicsScene, initialMap, + m_sizeX, m_sizeY, (float)m_sizeX, (float)m_sizeY, Vector3.Zero, 1.0f, out indicesCount, out indices, out verticesCount, out vertices)) @@ -87,8 +88,6 @@ public sealed class BSTerrainMesh : BSTerrainPhys // Something is very messed up and a crash is in our future. return; } - PhysicsScene.DetailLog("{0},BSTerrainMesh.create,afterConvertHeightmapToMesh,ver={1},ind={2}", - ID, verticesCount, indicesCount); m_terrainShape = new BulletShape(BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, indicesCount, indices, verticesCount, vertices), @@ -101,18 +100,11 @@ public sealed class BSTerrainMesh : BSTerrainPhys // Something is very messed up and a crash is in our future. return; } - PhysicsScene.DetailLog("{0},BSTerrainMesh.create,afterCreateShape,shape={1}", ID, m_terrainShape); - // The terrain object initial position is at the center of the object - Vector3 centerPos; - centerPos.X = minCoords.X + (m_sizeX / 2f); - centerPos.Y = minCoords.Y + (m_sizeY / 2f); - centerPos.Z = minCoords.Z + ((maxCoords.Z - minCoords.Z) / 2f); + Vector3 pos = regionBase; Quaternion rot = Quaternion.Identity; - PhysicsScene.DetailLog("{0},BSTerrainMesh.create,creatingBody,centerPos={1},rot={2}", ID, centerPos, rot); - m_terrainBody = new BulletBody(id, BulletSimAPI.CreateBodyWithDefaultMotionState2( - m_terrainShape.ptr, ID, centerPos, rot)); + m_terrainBody = new BulletBody(id, BulletSimAPI.CreateBodyWithDefaultMotionState2( m_terrainShape.ptr, ID, pos, rot)); if (m_terrainBody.ptr == IntPtr.Zero) { // DISASTER!! @@ -120,7 +112,6 @@ public sealed class BSTerrainMesh : BSTerrainPhys // Something is very messed up and a crash is in our future. return; } - PhysicsScene.DetailLog("{0},BSTerrainMesh.create,afterCreateBody,body={1}", ID, m_terrainBody); // Set current terrain attributes BulletSimAPI.SetFriction2(m_terrainBody.ptr, PhysicsScene.Params.terrainFriction); @@ -194,7 +185,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys int[] indices = new int[0]; float[] vertices = new float[0]; - // Simple mesh creation which assumes magnification == 1, sizeX == extentX and sizeY == extentY. + // Simple mesh creation which assumes magnification == 1. // TODO: do a more general solution that scales, adds new vertices and smoothes the result. try @@ -205,10 +196,10 @@ public sealed class BSTerrainMesh : BSTerrainPhys int totalIndices = sizeX * sizeY * 6; indices = new int[totalIndices]; - physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,totVert={1},totInd={2}", - BSScene.DetailLogZero, totalVertices, totalIndices); float magX = (float)sizeX / extentX; float magY = (float)sizeY / extentY; + physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,totVert={1},totInd={2},extentBase={3},magX={4},magY={5}", + BSScene.DetailLogZero, totalVertices, totalIndices, extentBase, magX, magY); // Note that sizeX+1 vertices are created since there is land between this and the next region. for (int yy = 0; yy <= sizeY; yy++) { @@ -222,15 +213,6 @@ public sealed class BSTerrainMesh : BSTerrainPhys vertices[verticesCount + 0] = (float)xx * magX + extentBase.X; vertices[verticesCount + 1] = (float)yy * magY + extentBase.Y; vertices[verticesCount + 2] = height + extentBase.Z; - if (physicsScene.PhysicsLogging.Enabled && verticesCount < 900) // DEBUG DEBUG DEBUG - { - Vector3 genVertex = new Vector3( - vertices[verticesCount + 0], - vertices[verticesCount + 1], - vertices[verticesCount + 2]); - physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,ii={1},vertex={2}", - BSScene.DetailLogZero, verticesCount/3, genVertex); - } verticesCount += 3; } } @@ -250,16 +232,6 @@ public sealed class BSTerrainMesh : BSTerrainPhys indices[indicesCount + 3] = offset + 1; indices[indicesCount + 4] = offset + sizeX + 2; indices[indicesCount + 5] = offset + sizeX + 1; - if (indicesCount < (300 * 6)) // DEBUG DEBUG DEBUG - physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,i0={1},i1={2},i2={3},i3={4},i4={5},i5={6}", // DEEBUG DEBUG DEBUG - BSScene.DetailLogZero, - indices[indicesCount + 0], - indices[indicesCount + 1], - indices[indicesCount + 2], - indices[indicesCount + 3], - indices[indicesCount + 4], - indices[indicesCount + 5] - ); indicesCount += 6; } } @@ -269,8 +241,8 @@ public sealed class BSTerrainMesh : BSTerrainPhys } catch (Exception e) { - physicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh. Base={1}, e={2}", - LogHeader, extentBase, e); + physicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh. For={1}/{2}, e={3}", + LogHeader, physicsScene.RegionName, extentBase, e); } indicesCountO = indicesCount; -- cgit v1.1 From cbc7e7bf85bfd9e916146b0ae4a605996c24720b Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 21 Nov 2012 16:31:23 -0800 Subject: BulletSim: Make avatar capsule so it is not circular. Simple attempt to make avatars better shaped. Replace parameter 'avatarCapsuleRadius' with 'avatarCapsuleWidth' and 'avatarCapsuleDepth'. More tweeking to avatar height calculation. A little better but short avatar's feet are above the terrain and tall avatar's feet are a little below the ground. --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 24 +++++++++++++++------- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 4 +++- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 18 +++++++++------- .../Physics/BulletSPlugin/BSShapeCollection.cs | 9 ++++---- .../Physics/BulletSPlugin/BSTerrainManager.cs | 2 +- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 3 ++- 6 files changed, 39 insertions(+), 21 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 799211e..e2aa41e 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -82,7 +82,13 @@ public sealed class BSCharacter : BSPhysObject { _physicsActorType = (int)ActorTypes.Agent; _position = pos; + + // Old versions of ScenePresence passed only the height. If width and/or depth are zero, + // replace with the default values. _size = size; + if (_size.X == 0f) _size.X = PhysicsScene.Params.avatarCapsuleDepth; + if (_size.Y == 0f) _size.Y = PhysicsScene.Params.avatarCapsuleWidth; + _flying = isFlying; _orientation = OMV.Quaternion.Identity; _velocity = OMV.Vector3.Zero; @@ -175,8 +181,7 @@ public sealed class BSCharacter : BSPhysObject get { // Avatar capsule size is kept in the scale parameter. - // return _size; - return new OMV.Vector3(Scale.X * 2f, Scale.Y * 2f, Scale.Z); + return _size; } set { @@ -614,14 +619,19 @@ public sealed class BSCharacter : BSPhysObject // The 'size' given by the simulator is the mid-point of the avatar // and X and Y are unspecified. - OMV.Vector3 newScale = OMV.Vector3.Zero; - newScale.X = PhysicsScene.Params.avatarCapsuleRadius; - newScale.Y = PhysicsScene.Params.avatarCapsuleRadius; + OMV.Vector3 newScale = size; + // newScale.X = PhysicsScene.Params.avatarCapsuleWidth; + // newScale.Y = PhysicsScene.Params.avatarCapsuleDepth; // From the total height, remove the capsule half spheres that are at each end // The 1.15f came from ODE. Not sure what this factors in. - newScale.Z = (size.Z * 1.15f) - (newScale.X + newScale.Y); - Scale = newScale; + // newScale.Z = (size.Z * 1.15f) - (newScale.X + newScale.Y); + + // The total scale height is the central cylindar plus the caps on the two ends. + newScale.Z = size.Z + (Math.Min(size.X, size.Y) * 2f); + + // Convert diameters to radii and height to half height -- the way Bullet expects it. + Scale = newScale / 2f; } // set _avatarVolume and _mass based on capsule size, _density and Scale diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 2657e4b..5d16bbf 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -93,7 +93,7 @@ public sealed class BSPrim : BSPhysObject _physicsActorType = (int)ActorTypes.Prim; _position = pos; _size = size; - Scale = new OMV.Vector3(1f, 1f, 1f); // the scale will be set by CreateGeom depending on object type + Scale = size; // the scale will be set by CreateGeom depending on object type _orientation = rotation; _buoyancy = 1f; _velocity = OMV.Vector3.Zero; @@ -154,6 +154,8 @@ public sealed class BSPrim : BSPhysObject public override OMV.Vector3 Size { get { return _size; } set { + // We presume the scale and size are the same. If scale must be changed for + // the physical shape, that is done when the geometry is built. _size = value; ForceBodyShapeRebuild(false); } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 0e73d04..27a78d1 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -1185,14 +1185,18 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].avatarRestitution; }, (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarRestitution, p, l, v); } ), - new ParameterDefn("AvatarCapsuleRadius", "Radius of space around an avatar", - 0.37f, - (s,cf,p,v) => { s.m_params[0].avatarCapsuleRadius = cf.GetFloat(p, v); }, - (s) => { return s.m_params[0].avatarCapsuleRadius; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ), + new ParameterDefn("AvatarCapsuleWidth", "The distance between the sides of the avatar capsule", + 0.6f, + (s,cf,p,v) => { s.m_params[0].avatarCapsuleWidth = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].avatarCapsuleWidth; }, + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleWidth, p, l, v); } ), + new ParameterDefn("AvatarCapsuleDepth", "The distance between the front and back of the avatar capsule", + 0.45f, + (s,cf,p,v) => { s.m_params[0].avatarCapsuleDepth = cf.GetFloat(p, v); }, + (s) => { return s.m_params[0].avatarCapsuleDepth; }, + (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleDepth, p, l, v); } ), new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar", - // 1.5f, - 2.140599f, + 1.5f, (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].avatarCapsuleHeight; }, (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ), diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index a53ad6e..869735c 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -525,9 +525,6 @@ public sealed class BSShapeCollection : IDisposable // release any previous shape DereferenceShape(prim.PhysShape, true, shapeCallback); - // Bullet native objects are scaled by the Bullet engine so pass the size in - prim.Scale = prim.Size; - BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey); // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. @@ -547,12 +544,13 @@ public sealed class BSShapeCollection : IDisposable nativeShapeData.Type = shapeType; nativeShapeData.ID = prim.LocalID; nativeShapeData.Scale = prim.Scale; - nativeShapeData.Size = prim.Scale; + nativeShapeData.Size = prim.Scale; // unneeded, I think. nativeShapeData.MeshKey = (ulong)shapeKey; nativeShapeData.HullKey = (ulong)shapeKey; if (shapeType == PhysicsShapeType.SHAPE_CAPSULE) { + // The proper scale has been calculated in the prim. newShape = new BulletShape( BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, prim.Scale) , shapeType); @@ -560,6 +558,9 @@ public sealed class BSShapeCollection : IDisposable } else { + // Native shapes are scaled in Bullet so set the scaling to the size + prim.Scale = prim.Size; + nativeShapeData.Scale = prim.Scale; newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, nativeShapeData), shapeType); } if (newShape.ptr == IntPtr.Zero) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index 097cd3e..71fca33 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -308,7 +308,7 @@ public sealed class BSTerrainManager { PhysicsScene.Logger.DebugFormat("{0} Terrain for {1}/{2} created with {3}", LogHeader, PhysicsScene.RegionName, terrainRegionBase, - PhysicsScene.Params.terrainImplementation); + (BSTerrainPhys.TerrainImplementation)PhysicsScene.Params.terrainImplementation); BSTerrainPhys newTerrainPhys = null; switch ((int)PhysicsScene.Params.terrainImplementation) { diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index e218053..4647c2d 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -291,7 +291,8 @@ public struct ConfigurationParameters public float avatarStandingFriction; public float avatarDensity; public float avatarRestitution; - public float avatarCapsuleRadius; + public float avatarCapsuleWidth; + public float avatarCapsuleDepth; public float avatarCapsuleHeight; public float avatarContactProcessingThreshold; -- cgit v1.1 From 3b2caa63b0ba890555990a88821ee37daa2607b4 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 22 Nov 2012 14:45:41 +0000 Subject: Rename BulletSim's PhysicsShapeType to BSPhysicsShapeType because it conflicts with PhysicsShape type defined in later libOMV --- .../Region/Physics/BulletSPlugin/BSCharacter.cs | 4 +- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 4 +- .../Physics/BulletSPlugin/BSLinksetCompound.cs | 6 +-- .../Region/Physics/BulletSPlugin/BSPhysObject.cs | 4 +- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 2 +- .../Physics/BulletSPlugin/BSShapeCollection.cs | 56 +++++++++++----------- OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs | 16 +++---- .../Physics/BulletSPlugin/BSTerrainHeightmap.cs | 2 +- .../Physics/BulletSPlugin/BSTerrainManager.cs | 2 +- .../Region/Physics/BulletSPlugin/BSTerrainMesh.cs | 2 +- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 10 ++-- 11 files changed, 54 insertions(+), 54 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index e2aa41e..4c195e1 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -208,9 +208,9 @@ public sealed class BSCharacter : BSPhysObject set { BaseShape = value; } } // I want the physics engine to make an avatar capsule - public override PhysicsShapeType PreferredPhysicalShape + public override BSPhysicsShapeType PreferredPhysicalShape { - get {return PhysicsShapeType.SHAPE_CAPSULE; } + get {return BSPhysicsShapeType.SHAPE_CAPSULE; } } public override bool Grabbed { diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 4ee047b..0df4310 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -82,9 +82,9 @@ public abstract class BSLinkset // Some linksets have a preferred physical shape. // Returns SHAPE_UNKNOWN if there is no preference. Causes the correct shape to be selected. - public virtual PhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) + public virtual BSPhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) { - return PhysicsShapeType.SHAPE_UNKNOWN; + return BSPhysicsShapeType.SHAPE_UNKNOWN; } // Linksets move around the children so the linkset might need to compute the child position diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs index cb37840..b9c2cf9 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs @@ -42,12 +42,12 @@ public sealed class BSLinksetCompound : BSLinkset } // For compound implimented linksets, if there are children, use compound shape for the root. - public override PhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) + public override BSPhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) { - PhysicsShapeType ret = PhysicsShapeType.SHAPE_UNKNOWN; + BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN; if (IsRoot(requestor) && HasAnyChildren) { - ret = PhysicsShapeType.SHAPE_COMPOUND; + ret = BSPhysicsShapeType.SHAPE_COMPOUND; } // DetailLog("{0},BSLinksetCompound.PreferredPhysicalShape,call,shape={1}", LinksetRoot.LocalID, ret); return ret; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index e68b167..f6a890e 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -94,9 +94,9 @@ public abstract class BSPhysObject : PhysicsActor public PrimitiveBaseShape BaseShape { get; protected set; } // Some types of objects have preferred physical representations. // Returns SHAPE_UNKNOWN if there is no preference. - public virtual PhysicsShapeType PreferredPhysicalShape + public virtual BSPhysicsShapeType PreferredPhysicalShape { - get { return PhysicsShapeType.SHAPE_UNKNOWN; } + get { return BSPhysicsShapeType.SHAPE_UNKNOWN; } } // When the physical properties are updated, an EntityProperty holds the update values. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 5d16bbf..2b3fa25 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -171,7 +171,7 @@ public sealed class BSPrim : BSPhysObject } } // Whatever the linkset wants is what I want. - public override PhysicsShapeType PreferredPhysicalShape + public override BSPhysicsShapeType PreferredPhysicalShape { get { return Linkset.PreferredPhysicalShape(this); } } public override bool ForceBodyShapeRebuild(bool inTaintTime) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 869735c..892c34b 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -178,7 +178,7 @@ public sealed class BSShapeCollection : IDisposable bool ret = false; switch (shape.type) { - case PhysicsShapeType.SHAPE_MESH: + case BSPhysicsShapeType.SHAPE_MESH: MeshDesc meshDesc; if (Meshes.TryGetValue(shape.shapeKey, out meshDesc)) { @@ -201,7 +201,7 @@ public sealed class BSShapeCollection : IDisposable meshDesc.lastReferenced = System.DateTime.Now; Meshes[shape.shapeKey] = meshDesc; break; - case PhysicsShapeType.SHAPE_HULL: + case BSPhysicsShapeType.SHAPE_HULL: HullDesc hullDesc; if (Hulls.TryGetValue(shape.shapeKey, out hullDesc)) { @@ -224,7 +224,7 @@ public sealed class BSShapeCollection : IDisposable hullDesc.lastReferenced = System.DateTime.Now; Hulls[shape.shapeKey] = hullDesc; break; - case PhysicsShapeType.SHAPE_UNKNOWN: + case BSPhysicsShapeType.SHAPE_UNKNOWN: break; default: // Native shapes are not tracked and they don't go into any list @@ -255,16 +255,16 @@ public sealed class BSShapeCollection : IDisposable { switch (shape.type) { - case PhysicsShapeType.SHAPE_HULL: + case BSPhysicsShapeType.SHAPE_HULL: DereferenceHull(shape, shapeCallback); break; - case PhysicsShapeType.SHAPE_MESH: + case BSPhysicsShapeType.SHAPE_MESH: DereferenceMesh(shape, shapeCallback); break; - case PhysicsShapeType.SHAPE_COMPOUND: + case BSPhysicsShapeType.SHAPE_COMPOUND: DereferenceCompound(shape, shapeCallback); break; - case PhysicsShapeType.SHAPE_UNKNOWN: + case BSPhysicsShapeType.SHAPE_UNKNOWN: break; default: break; @@ -352,28 +352,28 @@ public sealed class BSShapeCollection : IDisposable BulletShape shapeInfo = new BulletShape(cShape); if (TryGetMeshByPtr(cShape, out meshDesc)) { - shapeInfo.type = PhysicsShapeType.SHAPE_MESH; + shapeInfo.type = BSPhysicsShapeType.SHAPE_MESH; shapeInfo.shapeKey = meshDesc.shapeKey; } else { if (TryGetHullByPtr(cShape, out hullDesc)) { - shapeInfo.type = PhysicsShapeType.SHAPE_HULL; + shapeInfo.type = BSPhysicsShapeType.SHAPE_HULL; shapeInfo.shapeKey = hullDesc.shapeKey; } else { if (BulletSimAPI.IsCompound2(cShape)) { - shapeInfo.type = PhysicsShapeType.SHAPE_COMPOUND; + shapeInfo.type = BSPhysicsShapeType.SHAPE_COMPOUND; } else { if (BulletSimAPI.IsNativeShape2(cShape)) { shapeInfo.isNativeShape = true; - shapeInfo.type = PhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter) + shapeInfo.type = BSPhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter) } } } @@ -381,7 +381,7 @@ public sealed class BSShapeCollection : IDisposable DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo); - if (shapeInfo.type != PhysicsShapeType.SHAPE_UNKNOWN) + if (shapeInfo.type != BSPhysicsShapeType.SHAPE_UNKNOWN) { DereferenceShape(shapeInfo, true, null); } @@ -405,10 +405,10 @@ public sealed class BSShapeCollection : IDisposable bool ret = false; bool haveShape = false; - if (!haveShape && prim.PreferredPhysicalShape == PhysicsShapeType.SHAPE_CAPSULE) + if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_CAPSULE) { // an avatar capsule is close to a native shape (it is not shared) - ret = GetReferenceToNativeShape(prim, PhysicsShapeType.SHAPE_CAPSULE, + ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_CAPSULE, FixedShapeKey.KEY_CAPSULE, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape); ret = true; @@ -417,7 +417,7 @@ public sealed class BSShapeCollection : IDisposable // Compound shapes are handled special as they are rebuilt from scratch. // This isn't too great a hardship since most of the child shapes will already been created. - if (!haveShape && prim.PreferredPhysicalShape == PhysicsShapeType.SHAPE_COMPOUND) + if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND) { ret = GetReferenceToCompoundShape(prim, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape); @@ -460,10 +460,10 @@ public sealed class BSShapeCollection : IDisposable haveShape = true; if (forceRebuild || prim.Scale != prim.Size - || prim.PhysShape.type != PhysicsShapeType.SHAPE_SPHERE + || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_SPHERE ) { - ret = GetReferenceToNativeShape(prim, PhysicsShapeType.SHAPE_SPHERE, + ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_SPHERE, FixedShapeKey.KEY_SPHERE, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}", prim.LocalID, forceRebuild, prim.PhysShape); @@ -474,10 +474,10 @@ public sealed class BSShapeCollection : IDisposable haveShape = true; if (forceRebuild || prim.Scale != prim.Size - || prim.PhysShape.type != PhysicsShapeType.SHAPE_BOX + || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_BOX ) { - ret = GetReferenceToNativeShape( prim, PhysicsShapeType.SHAPE_BOX, + ret = GetReferenceToNativeShape( prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX, shapeCallback); DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}", prim.LocalID, forceRebuild, prim.PhysShape); @@ -519,7 +519,7 @@ public sealed class BSShapeCollection : IDisposable // Creates a native shape and assignes it to prim.BSShape. // "Native" shapes are never shared. they are created here and destroyed in DereferenceShape(). private bool GetReferenceToNativeShape(BSPhysObject prim, - PhysicsShapeType shapeType, FixedShapeKey shapeKey, + BSPhysicsShapeType shapeType, FixedShapeKey shapeKey, ShapeDestructionCallback shapeCallback) { // release any previous shape @@ -535,7 +535,7 @@ public sealed class BSShapeCollection : IDisposable return true; } - private BulletShape BuildPhysicalNativeShape(BSPhysObject prim, PhysicsShapeType shapeType, + private BulletShape BuildPhysicalNativeShape(BSPhysObject prim, BSPhysicsShapeType shapeType, FixedShapeKey shapeKey) { BulletShape newShape; @@ -548,7 +548,7 @@ public sealed class BSShapeCollection : IDisposable nativeShapeData.MeshKey = (ulong)shapeKey; nativeShapeData.HullKey = (ulong)shapeKey; - if (shapeType == PhysicsShapeType.SHAPE_CAPSULE) + if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE) { // The proper scale has been calculated in the prim. newShape = new BulletShape( @@ -586,7 +586,7 @@ public sealed class BSShapeCollection : IDisposable System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod); // if this new shape is the same as last time, don't recreate the mesh - if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == PhysicsShapeType.SHAPE_MESH) + if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_MESH) return false; DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2}", @@ -644,7 +644,7 @@ public sealed class BSShapeCollection : IDisposable indices.GetLength(0), indices, vertices.Count, verticesAsFloats); } } - BulletShape newShape = new BulletShape(meshPtr, PhysicsShapeType.SHAPE_MESH); + BulletShape newShape = new BulletShape(meshPtr, BSPhysicsShapeType.SHAPE_MESH); newShape.shapeKey = newMeshKey; return newShape; @@ -660,7 +660,7 @@ public sealed class BSShapeCollection : IDisposable System.UInt64 newHullKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod); // if the hull hasn't changed, don't rebuild it - if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == PhysicsShapeType.SHAPE_HULL) + if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_HULL) return false; DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}", @@ -781,7 +781,7 @@ public sealed class BSShapeCollection : IDisposable } } - BulletShape newShape = new BulletShape(hullPtr, PhysicsShapeType.SHAPE_HULL); + BulletShape newShape = new BulletShape(hullPtr, BSPhysicsShapeType.SHAPE_HULL); newShape.shapeKey = newHullKey; return newShape; // 'true' means a new shape has been added to this prim @@ -804,7 +804,7 @@ public sealed class BSShapeCollection : IDisposable // DereferenceShape(prim.PhysShape, true, shapeCallback); BulletShape cShape = new BulletShape( - BulletSimAPI.CreateCompoundShape2(PhysicsScene.World.ptr, false), PhysicsShapeType.SHAPE_COMPOUND); + BulletSimAPI.CreateCompoundShape2(PhysicsScene.World.ptr, false), BSPhysicsShapeType.SHAPE_COMPOUND); // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape. CreateGeomMeshOrHull(prim, shapeCallback); @@ -895,7 +895,7 @@ public sealed class BSShapeCollection : IDisposable // While we figure out the real problem, stick a simple native shape on the object. BulletShape fillinShape = - BuildPhysicalNativeShape(prim, PhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX); + BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX); return fillinShape; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs index f2e62d9..96cd55e 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs @@ -35,7 +35,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin public abstract class BSShape { public IntPtr ptr { get; set; } - public PhysicsShapeType type { get; set; } + public BSPhysicsShapeType type { get; set; } public System.UInt64 key { get; set; } public int referenceCount { get; set; } public DateTime lastReferenced { get; set; } @@ -43,7 +43,7 @@ public abstract class BSShape public BSShape() { ptr = IntPtr.Zero; - type = PhysicsShapeType.SHAPE_UNKNOWN; + type = BSPhysicsShapeType.SHAPE_UNKNOWN; key = 0; referenceCount = 0; lastReferenced = DateTime.Now; @@ -54,17 +54,17 @@ public abstract class BSShape { BSShape ret = null; - if (prim.PreferredPhysicalShape == PhysicsShapeType.SHAPE_CAPSULE) + if (prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_CAPSULE) { // an avatar capsule is close to a native shape (it is not shared) - ret = BSShapeNative.GetReference(physicsScene, prim, PhysicsShapeType.SHAPE_CAPSULE, + ret = BSShapeNative.GetReference(physicsScene, prim, BSPhysicsShapeType.SHAPE_CAPSULE, FixedShapeKey.KEY_CAPSULE); physicsScene.DetailLog("{0},BSShape.GetShapeReference,avatarCapsule,shape={1}", prim.LocalID, ret); } // Compound shapes are handled special as they are rebuilt from scratch. // This isn't too great a hardship since most of the child shapes will already been created. - if (ret == null && prim.PreferredPhysicalShape == PhysicsShapeType.SHAPE_COMPOUND) + if (ret == null && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND) { // Getting a reference to a compound shape gets you the compound shape with the root prim shape added ret = BSShapeCompound.GetReference(prim); @@ -123,14 +123,14 @@ public class BSShapeNative : BSShape { } public static BSShape GetReference(BSScene physicsScene, BSPhysObject prim, - PhysicsShapeType shapeType, FixedShapeKey shapeKey) + BSPhysicsShapeType shapeType, FixedShapeKey shapeKey) { // Native shapes are not shared and are always built anew. return new BSShapeNative(physicsScene, prim, shapeType, shapeKey); } private BSShapeNative(BSScene physicsScene, BSPhysObject prim, - PhysicsShapeType shapeType, FixedShapeKey shapeKey) + BSPhysicsShapeType shapeType, FixedShapeKey shapeKey) { ShapeData nativeShapeData = new ShapeData(); nativeShapeData.Type = shapeType; @@ -141,7 +141,7 @@ public class BSShapeNative : BSShape nativeShapeData.HullKey = (ulong)shapeKey; - if (shapeType == PhysicsShapeType.SHAPE_CAPSULE) + if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE) { ptr = BulletSimAPI.BuildCapsuleShape2(physicsScene.World.ptr, 1f, 1f, prim.Scale); physicsScene.DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs index 8fc36d1..3ca756c 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs @@ -97,7 +97,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys // Create the terrain shape from the mapInfo m_mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(m_mapInfo.Ptr), - PhysicsShapeType.SHAPE_TERRAIN); + BSPhysicsShapeType.SHAPE_TERRAIN); // The terrain object initial position is at the center of the object Vector3 centerPos; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index 71fca33..23fcfd3 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -130,7 +130,7 @@ public sealed class BSTerrainManager // The ground plane is here to catch things that are trying to drop to negative infinity BulletShape groundPlaneShape = new BulletShape( BulletSimAPI.CreateGroundPlaneShape2(BSScene.GROUNDPLANE_ID, 1f, TERRAIN_COLLISION_MARGIN), - PhysicsShapeType.SHAPE_GROUNDPLANE); + BSPhysicsShapeType.SHAPE_GROUNDPLANE); m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID, BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID, Vector3.Zero, Quaternion.Identity)); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs index 3279b6f..dca7150 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs @@ -91,7 +91,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys m_terrainShape = new BulletShape(BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, indicesCount, indices, verticesCount, vertices), - PhysicsShapeType.SHAPE_MESH); + BSPhysicsShapeType.SHAPE_MESH); if (m_terrainShape.ptr == IntPtr.Zero) { // DISASTER!! diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 4647c2d..e60a760 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -88,11 +88,11 @@ public struct BulletShape public BulletShape(IntPtr xx) { ptr = xx; - type=PhysicsShapeType.SHAPE_UNKNOWN; + type=BSPhysicsShapeType.SHAPE_UNKNOWN; shapeKey = (System.UInt64)FixedShapeKey.KEY_NONE; isNativeShape = false; } - public BulletShape(IntPtr xx, PhysicsShapeType typ) + public BulletShape(IntPtr xx, BSPhysicsShapeType typ) { ptr = xx; type = typ; @@ -100,7 +100,7 @@ public struct BulletShape isNativeShape = false; } public IntPtr ptr; - public PhysicsShapeType type; + public BSPhysicsShapeType type; public System.UInt64 shapeKey; public bool isNativeShape; public override string ToString() @@ -178,7 +178,7 @@ public struct ConvexHull int VertexCount; Vector3[] Vertices; } -public enum PhysicsShapeType +public enum BSPhysicsShapeType { SHAPE_UNKNOWN = 0, SHAPE_CAPSULE = 1, @@ -210,7 +210,7 @@ public enum FixedShapeKey : ulong public struct ShapeData { public uint ID; - public PhysicsShapeType Type; + public BSPhysicsShapeType Type; public Vector3 Position; public Quaternion Rotation; public Vector3 Velocity; -- cgit v1.1