/* * 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 { // Classes to allow some type checking for the API // These hold pointers to allocated objects in the unmanaged space. // The physics engine controller class created at initialization public struct BulletSim { public BulletSim(uint worldId, BSScene bss, IntPtr xx) { ptr = xx; worldID = worldId; physicsScene = bss; } public IntPtr ptr; public uint worldID; // The scene is only in here so very low level routines have a handle to print debug/error messages public BSScene physicsScene; } // An allocated Bullet btRigidBody public struct BulletBody { public BulletBody(uint id) : this(id, IntPtr.Zero) { } public BulletBody(uint id, IntPtr xx) { ID = id; ptr = xx; collisionType = CollisionType.Static; } public IntPtr ptr; public uint ID; public CollisionType collisionType; public void Clear() { ptr = IntPtr.Zero; } public bool HasPhysicalBody { get { return ptr != IntPtr.Zero; } } // Apply the specificed collision mask into the physical world public void ApplyCollisionMask() { // Should assert the body has been added to the physical world. // (The collision masks are stored in the collision proxy cache which only exists for // a collision body that is in the world.) BulletSimAPI.SetCollisionGroupMask2(ptr, BulletSimData.CollisionTypeMasks[collisionType].group, BulletSimData.CollisionTypeMasks[collisionType].mask); } public override string ToString() { StringBuilder buff = new StringBuilder(); buff.Append(""); return buff.ToString(); } } public struct BulletShape { public BulletShape(IntPtr xx) : this(xx, BSPhysicsShapeType.SHAPE_UNKNOWN) { } public BulletShape(IntPtr xx, BSPhysicsShapeType typ) { ptr = xx; type = typ; shapeKey = (System.UInt64)FixedShapeKey.KEY_NONE; isNativeShape = false; } public IntPtr ptr; public BSPhysicsShapeType type; public System.UInt64 shapeKey; public bool isNativeShape; public void Clear() { ptr = IntPtr.Zero; } public bool HasPhysicalShape { get { return ptr != IntPtr.Zero; } } public override string ToString() { StringBuilder buff = new StringBuilder(); buff.Append(""); return buff.ToString(); } } // An allocated Bullet btConstraint public struct BulletConstraint { public BulletConstraint(IntPtr xx) { ptr = xx; } public IntPtr ptr; public void Clear() { ptr = IntPtr.Zero; } public bool HasPhysicalConstraint { get { return ptr != IntPtr.Zero; } } } // An allocated HeightMapThing which holds various heightmap info. // Made a class rather than a struct so there would be only one // instance of this and C# will pass around pointers rather // than making copies. public class BulletHeightMapInfo { public BulletHeightMapInfo(uint id, float[] hm, IntPtr xx) { ID = id; Ptr = xx; heightMap = hm; terrainRegionBase = OMV.Vector3.Zero; minCoords = new OMV.Vector3(100f, 100f, 25f); maxCoords = new OMV.Vector3(101f, 101f, 26f); minZ = maxZ = 0f; sizeX = sizeY = 256f; } public uint ID; public IntPtr Ptr; public float[] heightMap; public OMV.Vector3 terrainRegionBase; public OMV.Vector3 minCoords; public OMV.Vector3 maxCoords; public float sizeX, sizeY; public float minZ, maxZ; public BulletShape terrainShape; public BulletBody terrainBody; } // The general class of collsion object. public enum CollisionType { Avatar, Groundplane, Terrain, Static, Dynamic, VolumeDetect, // Linkset, // A linkset should be either Static or Dynamic LinksetChild, Unknown }; // Hold specification of group and mask collision flags for a CollisionType public struct CollisionTypeFilterGroup { public CollisionTypeFilterGroup(CollisionType t, uint g, uint m) { type = t; group = g; mask = m; } public CollisionType type; public uint group; public uint mask; }; /* NOTE: old definitions kept for reference. Delete when things are working. // The collsion filters and masked are defined in one place -- don't want them scattered AvatarGroup = BCharacterGroup, AvatarMask = BAllGroup, ObjectGroup = BSolidGroup, ObjectMask = BAllGroup, StaticObjectGroup = BStaticGroup, StaticObjectMask = AvatarGroup | ObjectGroup, // static things don't interact with much LinksetGroup = BLinksetGroup, LinksetMask = BAllGroup, LinksetChildGroup = BLinksetChildGroup, LinksetChildMask = BNoneGroup, // Linkset children disappear from the world VolumeDetectGroup = BSensorTrigger, VolumeDetectMask = ~BSensorTrigger, TerrainGroup = BTerrainGroup, TerrainMask = BAllGroup & ~BStaticGroup, // static objects on the ground don't collide GroundPlaneGroup = BGroundPlaneGroup, GroundPlaneMask = BAllGroup */ public static class BulletSimData { // Map of collisionTypes to flags for collision groups and masks. // As mentioned above, don't use the CollisionFilterGroups definitions directly in the code // but, instead, use references to this dictionary. Finding and debugging // collision flag problems will be made easier. public static Dictionary CollisionTypeMasks = new Dictionary() { { CollisionType.Avatar, new CollisionTypeFilterGroup(CollisionType.Avatar, (uint)CollisionFilterGroups.BCharacterGroup, (uint)CollisionFilterGroups.BAllGroup) }, { CollisionType.Groundplane, new CollisionTypeFilterGroup(CollisionType.Groundplane, (uint)CollisionFilterGroups.BGroundPlaneGroup, (uint)CollisionFilterGroups.BAllGroup) }, { CollisionType.Terrain, new CollisionTypeFilterGroup(CollisionType.Terrain, (uint)CollisionFilterGroups.BTerrainGroup, (uint)(CollisionFilterGroups.BAllGroup & ~CollisionFilterGroups.BStaticGroup)) }, { CollisionType.Static, new CollisionTypeFilterGroup(CollisionType.Static, (uint)CollisionFilterGroups.BStaticGroup, (uint)(CollisionFilterGroups.BCharacterGroup | CollisionFilterGroups.BSolidGroup)) }, { CollisionType.Dynamic, new CollisionTypeFilterGroup(CollisionType.Dynamic, (uint)CollisionFilterGroups.BSolidGroup, (uint)(CollisionFilterGroups.BAllGroup)) }, { CollisionType.VolumeDetect, new CollisionTypeFilterGroup(CollisionType.VolumeDetect, (uint)CollisionFilterGroups.BSensorTrigger, (uint)(~CollisionFilterGroups.BSensorTrigger)) }, { CollisionType.LinksetChild, new CollisionTypeFilterGroup(CollisionType.LinksetChild, (uint)CollisionFilterGroups.BTerrainGroup, (uint)(CollisionFilterGroups.BNoneGroup)) }, }; } }