Beispiel #1
0
        // Create the correct type of linkset for this child
        public static BSLinkset Factory(BSScene physScene, BSPrimLinkable parent)
        {
            BSLinkset ret = null;

            switch ((int)BSParam.LinksetImplementation)
            {
            case (int)LinksetImplementation.Constraint:
                ret = new BSLinksetConstraints(physScene, parent);
                break;

            case (int)LinksetImplementation.Compound:
                ret = new BSLinksetCompound(physScene, parent);
                break;

            case (int)LinksetImplementation.Manual:
                break;

            case (int)LinksetImplementation.CompoundGroup:
                ret = new BSLinksetGroupCompound(physScene, parent);
                break;

            default:
                ret = new BSLinksetCompound(physScene, parent);
                break;
            }
            if (ret == null)
            {
                physScene.Logger.ErrorFormat("[BULLETSIM LINKSET] Factory could not create linkset. Parent name={1}, ID={2}", parent.Name, parent.LocalID);
            }
            return(ret);
        }
Beispiel #2
0
 public BSActor(BSScene physicsScene, BSPhysObject pObj, string actorName)
 {
     m_physicsScene    = physicsScene;
     m_controllingPrim = pObj;
     ActorName         = actorName;
     Enabled           = true;
 }
Beispiel #3
0
        public BSTerrainManager(BSScene physicsScene)
        {
            PhysicsScene = physicsScene;

            // Assume one region of default size
            m_worldMax = new Vector3(physicsScene.Scene.RegionInfo.RegionSizeX,
                                     physicsScene.Scene.RegionInfo.RegionSizeY, physicsScene.Scene.RegionInfo.RegionSizeZ);
        }
Beispiel #4
0
 public PhysicsScene GetScene()
 {
     if (_mScene == null)
     {
         _mScene = new BSScene();
     }
     return(_mScene);
 }
Beispiel #5
0
 // Apply the specificed collision mask into the physical world
 public virtual bool ApplyCollisionMask(BSScene physicsScene)
 {
     // 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.)
     return(physicsScene.PE.SetCollisionGroupMask(this,
                                                  BulletSimData.CollisionTypeMasks[collisionType].group,
                                                  BulletSimData.CollisionTypeMasks[collisionType].mask));
 }
Beispiel #6
0
        public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying)
            : base(parent_scene, localID, avName, "BSCharacter")
        {
            _position = pos;

            _flying      = isFlying;
            _orientation = OMV.Quaternion.Identity;
            RawVelocity  = OMV.Vector3.Zero;
            _buoyancy    = ComputeBuoyancyFromFlying(isFlying);
            Friction     = BSParam.AvatarStandingFriction;
            Density      = BSParam.AvatarDensity / BSParam.DensityScaleFactor;

            // 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 = BSParam.AvatarCapsuleDepth;
            }
            if (_size.Y == 0f)
            {
                _size.Y = BSParam.AvatarCapsuleWidth;
            }

            // The dimensions of the physical capsule are kept in the scale.
            // Physics creates a unit capsule which is scaled by the physics engine.
            Scale = ComputeAvatarScale(_size);
            // set _avatarVolume and _mass based on capsule size, _density and Scale
            ComputeAvatarVolumeAndMass();

            // The avatar's movement is controlled by this motor that speeds up and slows down
            //    the avatar seeking to reach the motor's target speed.
            // This motor runs as a prestep action for the avatar so it will keep the avatar
            //    standing as well as moving. Destruction of the avatar will destroy the pre-step action.
            m_moveActor = new BSActorAvatarMove(PhysicsScene, this, AvatarMoveActorName);
            PhysicalActors.Add(AvatarMoveActorName, m_moveActor);

            DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}",
                      LocalID, _size, Scale, Density, _avatarVolume, RawMass);

            // do actual creation in taint time
            PhysicsScene.TaintedObject("BSCharacter.create", delegate()
            {
                DetailLog("{0},BSCharacter.create,taint", LocalID);
                // New body and shape into PhysBody and PhysShape
                PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this);

                SetPhysicalProperties();

                SubscribeEvents(1000);
            });
            return;
        }
        // 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 BulletHMapInfo(id, initialMap);
            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();
        }
Beispiel #8
0
        public BSPrimLinkable(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size,
                              OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical, int material, float friction,
                              float restitution, float gravityMultiplier, float density)
            : base(localID, primName, parent_scene, pos, size, rotation, pbs, pisPhysical)
        {
            Linkset = BSLinkset.Factory(PhysicsScene, this);

            PhysicsScene.TaintedObject("BSPrimLinksetCompound.Refresh", delegate()
            {
                base.SetMaterial(material);
                base.Friction          = friction;
                base.Restitution       = restitution;
                base.GravityMultiplier = gravityMultiplier;
                base.Density           = density;
                Linkset.Refresh(this);
            });
        }
Beispiel #9
0
        protected BSLinkset(BSScene scene, BSPrimLinkable parent)
        {
            // A simple linkset of one (no children)
            LinksetID = m_nextLinksetID++;
            // We create LOTS of linksets.
            if (m_nextLinksetID <= 0)
            {
                m_nextLinksetID = 1;
            }
            PhysicsScene = scene;
            LinksetRoot  = parent;
            m_children   = new HashSet <BSPrimLinkable>();
            LinksetMass  = parent.RawMass;
            Rebuilding   = false;

            parent.ClearDisplacement();
        }
        // 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 BulletHMapInfo(id, initialMap);
            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();
        }
Beispiel #11
0
        // 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 == BSPhysicsShapeType.SHAPE_CAPSULE)
            {
                // an avatar capsule is close to a native shape (it is not shared)
                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 have already been created.
            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);
                physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, ret);
            }

            // Avatars have their own unique shape
            if (ret == null && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_AVATAR)
            {
                // Getting a reference to a compound shape gets you the compound shape with the root prim shape added
                ret = BSShapeAvatar.GetReference(prim);
                physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,avatarShape,shape={1}", prim.LocalID, ret);
            }

            if (ret == null)
            {
                ret = GetShapeReferenceNonSpecial(physicsScene, forceRebuild, prim);
            }

            return(ret);
        }
Beispiel #12
0
        protected BSPhysObject(BSScene parentScene, uint localID, string name, string typeName)
        {
            PhysicsScene   = parentScene;
            LocalID        = localID;
            PhysObjectName = name;
            Name           = name; // PhysicsActor also has the name of the object. Someday consolidate.
            TypeName       = typeName;

            // The collection of things that push me around
            PhysicalActors = new BSActorCollection(PhysicsScene);

            // Initialize variables kept in base.
            GravityMultiplier = 1.0f;
            Gravity           = new OMV.Vector3(0f, 0f, BSParam.Gravity);

            // We don't have any physical representation yet.
            PhysBody  = new BulletBody(localID);
            PhysShape = new BulletShape();

            PrimAssetState = PrimAssetCondition.Unknown;

            // Default material type. Also sets Friction, Restitution and Density.
            SetMaterial((int)MaterialAttributes.Material.Wood);

            CollisionCollection   = new CollisionEventUpdate();
            CollisionsLastTick    = CollisionCollection;
            SubscribedEventsMs    = 0;
            CollidingStep         = 0;
            TrueCollidingStep     = 0;
            CollisionAccumulation = 0;
            ColliderIsMoving      = false;
            CollisionScore        = 0;

            // All axis free.
            LockedAxis = LockedAxisFree;
        }
Beispiel #13
0
 public BSActorSetForce(BSScene physicsScene, BSPhysObject pObj, string actorName)
     : base(physicsScene, pObj, actorName)
 {
     m_forceMotor = null;
     m_physicsScene.DetailLog("{0},BSActorSetForce,constructor", m_controllingPrim.LocalID);
 }
Beispiel #14
0
 public BSPrimDisplaced(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size,
                        OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
     : base(localID, primName, parent_scene, pos, size, rotation, pbs, pisPhysical)
 {
     ClearDisplacement();
 }
Beispiel #15
0
 public BSConstraint(BulletWorld world)
 {
     m_world      = world;
     PhysicsScene = m_world.physicsScene;
 }
Beispiel #16
0
 public BSActorCollection(BSScene physicsScene)
 {
     m_physicsScene = physicsScene;
     m_actors       = new Dictionary <string, BSActor>();
 }
Beispiel #17
0
 public BSTerrainPhys(BSScene physicsScene, Vector3 regionBase, uint id)
 {
     PhysicsScene = physicsScene;
     TerrainBase  = regionBase;
     ID           = id;
 }
Beispiel #18
0
        // Convert the passed heightmap to mesh information suitable for CreateMeshShape2().
        // Version that handles magnification.
        // Return 'true' if successfully created.
        public static bool ConvertHeightmapToMesh2(BSScene physicsScene,
                                                   float[] heightMap, int sizeX, int sizeY, // parameters of incoming heightmap
                                                   int magnification,                       // number of vertices per heighmap step
                                                   Vector3 extent,                          // dimensions of the output mesh
                                                   Vector3 extentBase,                      // base to be added to all vertices
                                                   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];

            HeightMapGetter hmap = new HeightMapGetter(heightMap, sizeX, sizeY);

            // The vertices dimension of the output mesh
            int meshX = sizeX * magnification;
            int meshY = sizeY * magnification;
            // The output size of one mesh step
            float meshXStep = extent.X / meshX;
            float meshYStep = extent.Y / meshY;

            // Create an array of vertices that is meshX+1 by meshY+1 (note the loop
            //    from zero to <= meshX). The triangle indices are then generated as two triangles
            //    per heightmap point. There are meshX by meshY of these squares. The extra row and
            //    column of vertices are used to complete the triangles of the last row and column
            //    of the heightmap.
            try
            {
                // Vertices for the output heightmap plus one on the side and bottom to complete triangles
                int totalVertices = (meshX + 1) * (meshY + 1);
                vertices = new float[totalVertices * 3];
                int totalIndices = meshX * meshY * 6;
                indices = new int[totalIndices];

                if (physicsScene != null)
                {
                    physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh2,inSize={1},outSize={2},totVert={3},totInd={4},extentBase={5}",
                                           BSScene.DetailLogZero, new Vector2(sizeX, sizeY), new Vector2(meshX, meshY),
                                           totalVertices, totalIndices, extentBase);
                }

                float minHeight = float.MaxValue;
                // Note that sizeX+1 vertices are created since there is land between this and the next region.
                // Loop through the output vertices and compute the mediun height in between the input vertices
                for (int yy = 0; yy <= meshY; yy++)
                {
                    for (int xx = 0; xx <= meshX; xx++)                              // Hint: the "<=" means we go around sizeX + 1 times
                    {
                        float offsetY     = (float)yy * (float)sizeY / (float)meshY; // The Y that is closest to the mesh point
                        int   stepY       = (int)offsetY;
                        float fractionalY = offsetY - (float)stepY;
                        float offsetX     = (float)xx * (float)sizeX / (float)meshX; // The X that is closest to the mesh point
                        int   stepX       = (int)offsetX;
                        float fractionalX = offsetX - (float)stepX;

                        // get the four corners of the heightmap square the mesh point is in
                        float heightUL = hmap.GetHeight(stepX, stepY);
                        float heightUR = hmap.GetHeight(stepX + 1, stepY);
                        float heightLL = hmap.GetHeight(stepX, stepY + 1);
                        float heightLR = hmap.GetHeight(stepX + 1, stepY + 1);

                        // bilinear interplolation
                        float height = heightUL * (1 - fractionalX) * (1 - fractionalY)
                                       + heightUR * fractionalX * (1 - fractionalY)
                                       + heightLL * (1 - fractionalX) * fractionalY
                                       + heightLR * fractionalX * fractionalY;

                        minHeight = Math.Min(minHeight, height);

                        vertices[verticesCount + 0] = (float)xx * meshXStep + extentBase.X;
                        vertices[verticesCount + 1] = (float)yy * meshYStep + extentBase.Y;
                        vertices[verticesCount + 2] = height + extentBase.Z;
                        verticesCount += 3;
                    }
                }
                // The number of vertices generated
                verticesCount /= 3;

                // Loop through all the heightmap squares and create indices for the two triangles for that square
                for (int yy = 0; yy < meshY; yy++)
                {
                    for (int xx = 0; xx < meshX; xx++)
                    {
                        int offset = yy * (meshX + 1) + 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 + meshX + 1; // accounting for the extra column
                        indices[indicesCount + 3] = offset + 1;
                        indices[indicesCount + 4] = offset + meshX + 2;
                        indices[indicesCount + 5] = offset + meshX + 1;
                        indicesCount += 6;
                    }
                }

                ret = true;
            }
            catch (Exception e)
            {
                if (physicsScene != null)
                {
                    physicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh. For={1}/{2}, e={3}",
                                                    LogHeader, physicsScene.RegionName, extentBase, e);
                }
            }

            indicesCountO  = indicesCount;
            indicesO       = indices;
            verticesCountO = verticesCount;
            verticesO      = vertices;

            return(ret);
        }
Beispiel #19
0
 public BulletWorld(uint worldId, BSScene bss)
 {
     worldID      = worldId;
     physicsScene = bss;
 }
Beispiel #20
0
 public static BSShape GetShapeReferenceNonNative(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
 {
     return(null);
 }
Beispiel #21
0
 // Release the use of a physical shape.
 public abstract void Dereference(BSScene physicsScene);
Beispiel #22
0
 public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize)
     : base(physicsScene, regionBase, id)
 {
 }
Beispiel #23
0
 public override void Dereference(BSScene physicsScene) /* The magic of garbage collection will make this go away */ }
Beispiel #24
0
 public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id /* parameters for making mesh */)
     : base(physicsScene, regionBase, id)
 {
 }
 public BSLinksetConstraints(BSScene scene, BSPrimLinkable parent)
     : base(scene, parent)
 {
 }
Beispiel #26
0
        // 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
                                                  Vector3 extentBase,                      // base to be added to all vertices
                                                  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.
            // TODO: do a more general solution that scales, adds new vertices and smoothes the result.

            // Create an array of vertices that is sizeX+1 by sizeY+1 (note the loop
            //    from zero to <= sizeX). The triangle indices are then generated as two triangles
            //    per heightmap point. There are sizeX by sizeY of these squares. The extra row and
            //    column of vertices are used to complete the triangles of the last row and column
            //    of the heightmap.
            try
            {
                // One vertice per heightmap value plus the vertices off the side and bottom edge.
                int totalVertices = (sizeX + 1) * (sizeY + 1);
                vertices = new float[totalVertices * 3];
                int totalIndices = sizeX * sizeY * 6;
                indices = new int[totalIndices];

                if (physicsScene != null)
                {
                    physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,totVert={1},totInd={2},extentBase={3}",
                                           BSScene.DetailLogZero, totalVertices, totalIndices, extentBase);
                }
                float minHeight = float.MaxValue;
                // 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 go around sizeX + 1 times
                    {
                        int offset = yy * sizeX + xx;
                        // Extend the height with the height from the last row or column
                        if (yy == sizeY)
                        {
                            offset -= sizeX;
                        }
                        if (xx == sizeX)
                        {
                            offset -= 1;
                        }
                        float height = heightMap[offset];
                        minHeight = Math.Min(minHeight, height);
                        vertices[verticesCount + 0] = (float)xx + extentBase.X;
                        vertices[verticesCount + 1] = (float)yy + extentBase.Y;
                        vertices[verticesCount + 2] = height + extentBase.Z;
                        verticesCount += 3;
                    }
                }
                verticesCount = verticesCount / 3;

                for (int yy = 0; yy < sizeY; yy++)
                {
                    for (int xx = 0; xx < sizeX; xx++)
                    {
                        int offset = yy * (sizeX + 1) + 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;
                        indicesCount += 6;
                    }
                }

                ret = true;
            }
            catch (Exception e)
            {
                if (physicsScene != null)
                {
                    physicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh. For={1}/{2}, e={3}",
                                                    LogHeader, physicsScene.RegionName, extentBase, e);
                }
            }

            indicesCountO  = indicesCount;
            indicesO       = indices;
            verticesCountO = verticesCount;
            verticesO      = vertices;

            return(ret);
        }
 public BSLinksetGroupCompound(BSScene scene, BSPrimLinkable parent)
     : base(scene, parent)
 {
 }
Beispiel #28
0
 public BSActorLockAxis(BSScene physicsScene, BSPhysObject pObj, string actorName)
     : base(physicsScene, pObj, actorName)
 {
     m_physicsScene.DetailLog("{0},BSActorLockAxis,constructor", m_controllingPrim.LocalID);
     LockAxisConstraint = null;
 }
 public BSActorAvatarMove(BSScene physicsScene, BSPhysObject pObj, string actorName)
     : base(physicsScene, pObj, actorName)
 {
     m_velocityMotor = null;
     m_physicsScene.DetailLog("{0},BSActorAvatarMove,constructor", m_controllingPrim.LocalID);
 }
Beispiel #30
0
        // 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);

            bool meshCreationSuccess = false;

            if (BSParam.TerrainMeshMagnification == 1)
            {
                // If a magnification of one, use the old routine that is tried and true.
                meshCreationSuccess = BSTerrainMesh.ConvertHeightmapToMesh(PhysicsScene,
                                                                           initialMap, m_sizeX, m_sizeY, // input size
                                                                           Vector3.Zero,                 // base for mesh
                                                                           out indicesCount, out indices, out verticesCount, out vertices);
            }
            else
            {
                // Other magnifications use the newer routine
                meshCreationSuccess = BSTerrainMesh.ConvertHeightmapToMesh2(PhysicsScene,
                                                                            initialMap, m_sizeX, m_sizeY, // input size
                                                                            BSParam.TerrainMeshMagnification,
                                                                            physicsScene.TerrainManager.WorldMax,
                                                                            Vector3.Zero, // base for mesh
                                                                            out indicesCount, out indices, out verticesCount, out vertices);
            }
            if (!meshCreationSuccess)
            {
                // DISASTER!!
                PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedConversionOfHeightmap,id={1}", BSScene.DetailLogZero, 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,meshed,id={1},indices={2},indSz={3},vertices={4},vertSz={5}",
                                   BSScene.DetailLogZero, ID, indicesCount, indices.Length, verticesCount, vertices.Length);

            m_terrainShape = PhysicsScene.PE.CreateMeshShape(PhysicsScene.World, indicesCount, indices, verticesCount, vertices);
            if (!m_terrainShape.HasPhysicalShape)
            {
                // DISASTER!!
                PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedCreationOfShape,id={1}", BSScene.DetailLogZero, 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;
            }

            Vector3    pos = regionBase;
            Quaternion rot = Quaternion.Identity;

            m_terrainBody = PhysicsScene.PE.CreateBodyWithDefaultMotionState(m_terrainShape, ID, pos, rot);
            if (!m_terrainBody.HasPhysicalBody)
            {
                // 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.PE.SetShapeCollisionMargin(m_terrainShape, BSParam.TerrainCollisionMargin);

            // Set current terrain attributes
            PhysicsScene.PE.SetFriction(m_terrainBody, BSParam.TerrainFriction);
            PhysicsScene.PE.SetHitFraction(m_terrainBody, BSParam.TerrainHitFraction);
            PhysicsScene.PE.SetRestitution(m_terrainBody, BSParam.TerrainRestitution);
            PhysicsScene.PE.SetContactProcessingThreshold(m_terrainBody, BSParam.TerrainContactProcessingThreshold);
            PhysicsScene.PE.SetCollisionFlags(m_terrainBody, CollisionFlags.CF_STATIC_OBJECT);

            // Static objects are not very massive.
            PhysicsScene.PE.SetMassProps(m_terrainBody, 0f, Vector3.Zero);

            // Put the new terrain to the world of physical objects
            PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, m_terrainBody);

            // Redo its bounding box now that it is in the world
            PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, m_terrainBody);

            m_terrainBody.collisionType = CollisionType.Terrain;
            m_terrainBody.ApplyCollisionMask(PhysicsScene);

            if (BSParam.UseSingleSidedMeshes)
            {
                PhysicsScene.DetailLog("{0},BSTerrainMesh.settingCustomMaterial,id={1}", BSScene.DetailLogZero, id);
                PhysicsScene.PE.AddToCollisionFlags(m_terrainBody, CollisionFlags.CF_CUSTOM_MATERIAL_CALLBACK);
            }

            // Make it so the terrain will not move or be considered for movement.
            PhysicsScene.PE.ForceActivationState(m_terrainBody, ActivationState.DISABLE_SIMULATION);
        }