From a27e4ce6cbfb0a2e852624fd4d81121ca829f85c Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 19 Sep 2012 08:21:29 -0700 Subject: BulletSim: add class and infrastructure for shape and object tracking in the C# code. Needed for the changing body type (to and from GhostObjects) for volumeDetect. --- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 47 +++++++++-- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 16 ++-- .../Physics/BulletSPlugin/BSShapeCollection.cs | 70 +++++++++++++++++ .../Physics/BulletSPlugin/BSTerrainManager.cs | 7 +- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 91 ++++++++++++++++------ 5 files changed, 192 insertions(+), 39 deletions(-) create mode 100755 OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 4f10d46..4d17e6c 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -474,12 +474,13 @@ public sealed class BSPrim : BSPhysObject */ BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.Ptr, BSBody.Ptr); - // Set up the object physicalness (does gravity and collisions move this object) - MakeDynamic(IsStatic); - // Make solid or not (do things bounce off or pass through this object) + // This is done first because it can change the collisionObject type. MakeSolid(IsSolid); + // Set up the object physicalness (does gravity and collisions move this object) + MakeDynamic(IsStatic); + // Arrange for collisions events if the simulator wants them EnableCollisions(SubscribedEvents()); @@ -554,17 +555,51 @@ public sealed class BSPrim : BSPhysObject } // "Making solid" means that other object will not pass through this object. + // To make transparent, we create a Bullet ghost object. + // Note: This expects to be called from the UpdatePhysicalParameters() routine as + // 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); + /* if (makeSolid) { - // Easy in Bullet -- just remove the object flag that controls collision response - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); + if ((bodyType & CollisionObjectTypes.CO_RIGID_BODY) == 0) + { + // Solid things are made out of rigid bodies. Remove this old body from the world + // and use this shape in a new rigid body. + BulletBody oldBody = BSBody; + BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.Ptr, BSBody.Ptr); + BSShape = new BulletShape(BulletSimAPI.GetCollisionShape2(BSBody.Ptr)); + BSBody = new BulletBody(LocalID, BulletSimAPI.CreateBodyFromShape2(PhysicsScene.World.Ptr, BSShape.Ptr, _position, _orientation)); + BulletSimAPI.DestroyObject2(PhysicsScene.World.Ptr, oldBody.Ptr); + BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.Ptr, BSBody.Ptr); + } } else { - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.Ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); + if ((bodyType & CollisionObjectTypes.CO_GHOST_OBJECT) == 0) + { + // Non-solid things are made out of ghost objects. Remove this old body from the world + // and use this shape in a new rigid body. + BulletBody oldBody = BSBody; + BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.Ptr, BSBody.Ptr); + BSShape = new BulletShape(BulletSimAPI.GetCollisionShape2(BSBody.Ptr)); + BSBody = new BulletBody(LocalID, + BulletSimAPI.CreateGhostFromShape2(PhysicsScene.World.Ptr, BSShape.Ptr, _position, _orientation)); + if (BSBody.Ptr == IntPtr.Zero) + { + m_log.ErrorFormat("{0} BSPrim.MakeSolid: failed creation of ghost object. LocalID=[1}", LogHeader, LocalID); + BSBody = oldBody; + } + else + { + BulletSimAPI.DestroyObject2(PhysicsScene.World.Ptr, oldBody.Ptr); + BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.Ptr, BSBody.Ptr); + } + } } + */ } // Turn on or off the flag controlling whether collision events are returned to the simulator. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index dabced5..76da42d 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -73,8 +73,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters public string BulletSimVersion = "?"; - public Dictionary PhysObjects = new Dictionary(); + public Dictionary PhysObjects; + public BSShapeCollection Shapes; + // Keeping track of the objects with collisions so we can report begin and end of a collision public HashSet ObjectsWithCollisions = new HashSet(); public HashSet ObjectsWithNoMoreCollisions = new HashSet(); // Keep track of all the avatars so we can send them a collision event @@ -203,6 +205,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters public override void Initialise(IMesher meshmerizer, IConfigSource config) { + mesher = meshmerizer; + _taintedObjects = new List(); + PhysObjects = new Dictionary(); + Shapes = new BSShapeCollection(this); + // Allocate pinned memory to pass parameters. m_params = new ConfigurationParameters[1]; m_paramsHandle = GCHandle.Alloc(m_params, GCHandleType.Pinned); @@ -216,12 +223,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters m_updateArray = new EntityProperties[m_maxUpdatesPerFrame]; m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned); - mesher = meshmerizer; - _taintedObjects = new List(); - // Enable very detailed logging. // By creating an empty logger when not logging, the log message invocation code - // can be left in and every call doesn't have to check for null. + // can be left in and every call doesn't have to check for null. if (m_physicsLoggingEnabled) { PhysicsLogging = new Logging.LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes); @@ -252,7 +256,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters // a child in a mega-region. // Turns out that Bullet really doesn't care about the extents of the simulated // area. It tracks active objects no matter where they are. - Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, 8192f); + Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); // m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader); WorldID = BulletSimAPI.Initialize(worldExtent, m_paramsHandle.AddrOfPinnedObject(), diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs new file mode 100755 index 0000000..eb4b2ad --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -0,0 +1,70 @@ +/* + * 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 BSShapeCollection : IDisposable +{ + protected BSScene PhysicsScene { get; set; } + + public BSShapeCollection(BSScene physScene) + { + PhysicsScene = physScene; + } + + public void Dispose() + { + } + + // Track another user of a body + public void ReferenceBody(BulletBody shape) + { + } + + // Release the usage of a body + public void DereferenceBody(BulletBody shape) + { + } + + // Track another user of the shape + public void ReferenceShape(BulletShape shape) + { + } + + // Release the usage of a shape + public void DereferenceShape(BulletShape shape) + { + } + + + +} +} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index c113db1..fb802e4 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs @@ -107,7 +107,9 @@ public class BSTerrainManager public void CreateInitialGroundPlaneAndTerrain() { // 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)); + BulletShape groundPlaneShape = new BulletShape( + BulletSimAPI.CreateGroundPlaneShape2(BSScene.GROUNDPLANE_ID, 1f, TERRAIN_COLLISION_MARGIN), + ShapeData.PhysicsShapeType.SHAPE_GROUNDPLANE); m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID, BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.Ptr, Vector3.Zero, Quaternion.Identity)); BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.Ptr, m_groundPlane.Ptr); @@ -297,7 +299,8 @@ public class BSTerrainManager centerPos.Z = minZ + ((maxZ - minZ) / 2f); // Create the terrain shape from the mapInfo - mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr)); + mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr), + ShapeData.PhysicsShapeType.SHAPE_TERRAIN); mapInfo.terrainBody = new BulletBody(mapInfo.ID, BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.Ptr, diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 4d2d962..52c8a24 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -38,31 +38,54 @@ namespace OpenSim.Region.Physics.BulletSPlugin { // The physics engine controller class created at initialization public struct BulletSim { - public BulletSim(uint worldId, BSScene bss, IntPtr xx) { worldID = worldId; scene = bss; Ptr = xx; } + public BulletSim(uint worldId, BSScene bss, IntPtr xx) + { + worldID = worldId; scene = bss; Ptr = xx; + } public uint worldID; // The scene is only in here so very low level routines have a handle to print debug/error messages public BSScene scene; public IntPtr Ptr; } -public struct BulletShape +// An allocated Bullet btRigidBody +public struct BulletBody { - public BulletShape(IntPtr xx) { Ptr = xx; } + public BulletBody(uint id, IntPtr xx) + { + ID = id; + Ptr = xx; + } public IntPtr Ptr; + public uint ID; } -// An allocated Bullet btRigidBody -public struct BulletBody +public struct BulletShape { - public BulletBody(uint id, IntPtr xx) { ID = id; Ptr = xx; } + public BulletShape(IntPtr xx) + { + Ptr = xx; + type=ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; + hashKey = 0; + } + public BulletShape(IntPtr xx, ShapeData.PhysicsShapeType typ) + { + Ptr = xx; + type = typ; + hashKey = 0; + } public IntPtr Ptr; - public uint ID; + public ShapeData.PhysicsShapeType type; + public ulong hashKey; } // An allocated Bullet btConstraint public struct BulletConstraint { - public BulletConstraint(IntPtr xx) { Ptr = xx; } + public BulletConstraint(IntPtr xx) + { + Ptr = xx; + } public IntPtr Ptr; } @@ -96,14 +119,14 @@ public class BulletHeightMapInfo // =============================================================================== [StructLayout(LayoutKind.Sequential)] -public struct ConvexHull +public struct ConvexHull { Vector3 Offset; int VertexCount; Vector3[] Vertices; } [StructLayout(LayoutKind.Sequential)] -public struct ShapeData +public struct ShapeData { public enum PhysicsShapeType { @@ -114,7 +137,9 @@ public struct ShapeData SHAPE_CYLINDER = 4, SHAPE_SPHERE = 5, SHAPE_MESH = 6, - SHAPE_HULL = 7 + SHAPE_HULL = 7, + SHAPE_GROUNDPLANE = 8, + SHAPE_TERRAIN = 9, }; public uint ID; public PhysicsShapeType Type; @@ -136,7 +161,7 @@ public struct ShapeData public const float numericFalse = 0f; } [StructLayout(LayoutKind.Sequential)] -public struct SweepHit +public struct SweepHit { public uint ID; public float Fraction; @@ -227,7 +252,17 @@ public enum ActivationState : uint ISLAND_SLEEPING, WANTS_DEACTIVATION, DISABLE_DEACTIVATION, - DISABLE_SIMULATION + DISABLE_SIMULATION, +} + +public enum CollisionObjectTypes : int +{ + CO_COLLISION_OBJECT = 1 << 0, + CO_RIGID_BODY = 1 << 1, + CO_GHOST_OBJECT = 1 << 2, + CO_SOFT_BODY = 1 << 3, + CO_HF_FLUID = 1 << 4, + CO_USER_TYPE = 1 << 5, } // Values used by Bullet and BulletSim to control object properties. @@ -313,8 +348,8 @@ public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg public static extern string GetVersion(); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern uint Initialize(Vector3 maxPosition, IntPtr parms, - int maxCollisions, IntPtr collisionArray, +public static extern uint Initialize(Vector3 maxPosition, IntPtr parms, + int maxCollisions, IntPtr collisionArray, int maxUpdates, IntPtr updateArray, DebugLogCallback logRoutine); @@ -333,19 +368,19 @@ public static extern bool UpdateParameter(uint worldID, uint localID, // =============================================================================== [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern int PhysicsStep(uint worldID, float timeStep, int maxSubSteps, float fixedTimeStep, - out int updatedEntityCount, +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, +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, +public static extern bool CreateMesh(uint worldID, System.UInt64 meshKey, int indexCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices, int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices ); @@ -459,7 +494,7 @@ public static extern void Shutdown2(IntPtr sim); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern int PhysicsStep2(IntPtr world, float timeStep, int maxSubSteps, float fixedTimeStep, - out int updatedEntityCount, + out int updatedEntityCount, out IntPtr updatedEntitiesPtr, out int collidersCount, out IntPtr collidersPtr); @@ -470,8 +505,8 @@ public static extern bool PushUpdate2(IntPtr obj); // ===================================================================================== // Mesh, hull, shape and body creation helper routines [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateMeshShape2(IntPtr world, - int indicesCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices, +public static extern IntPtr CreateMeshShape2(IntPtr world, + int indicesCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices, int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices ); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] @@ -504,12 +539,18 @@ public static extern IntPtr CreateBodyFromShapeAndInfo2(IntPtr sim, IntPtr shape public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern int GetBodyType2(IntPtr obj); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, Vector3 pos, Quaternion rot); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr CreateBodyWithDefaultMotionState2(IntPtr shape, Vector3 pos, Quaternion rot); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern IntPtr CreateGhostFromShape2(IntPtr sim, IntPtr shape, Vector3 pos, Quaternion rot); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr AllocateBodyInfo2(IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] @@ -521,11 +562,11 @@ public static extern void DestroyObject2(IntPtr sim, IntPtr obj); // ===================================================================================== // Terrain creation and helper routines [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateHeightMapInfo2(IntPtr sim, uint id, Vector3 minCoords, Vector3 maxCoords, +public static extern IntPtr CreateHeightMapInfo2(IntPtr sim, uint id, Vector3 minCoords, Vector3 maxCoords, [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr FillHeightMapInfo2(IntPtr sim, IntPtr mapInfo, uint id, Vector3 minCoords, Vector3 maxCoords, +public static extern IntPtr FillHeightMapInfo2(IntPtr sim, IntPtr mapInfo, uint id, Vector3 minCoords, Vector3 maxCoords, [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] @@ -563,7 +604,7 @@ public static extern void SetConstraintEnable2(IntPtr constrain, float numericTr public static extern void SetConstraintNumSolverIterations2(IntPtr constrain, float iterations); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetFrames2(IntPtr constrain, +public static extern bool SetFrames2(IntPtr constrain, Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -- cgit v1.1