Example #1
0
        // 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)
        {
            m_physicsScene.Logger.DebugFormat("{0} Terrain for {1}/{2} created with {3}",
                                              LogHeader, m_physicsScene.RegionName, terrainRegionBase,
                                              (BSTerrainPhys.TerrainImplementation)BSParam.TerrainImplementation);
            BSTerrainPhys newTerrainPhys = null;

            switch ((int)BSParam.TerrainImplementation)
            {
            case (int)BSTerrainPhys.TerrainImplementation.Heightmap:
                newTerrainPhys = new BSTerrainHeightmap(m_physicsScene, terrainRegionBase, id,
                                                        heightMap, minCoords, maxCoords);
                break;

            case (int)BSTerrainPhys.TerrainImplementation.Mesh:
                newTerrainPhys = new BSTerrainMesh(m_physicsScene, terrainRegionBase, id,
                                                   heightMap, minCoords, maxCoords);
                break;

            default:
                m_physicsScene.Logger.ErrorFormat("{0} Bad terrain implementation specified. Type={1}/{2},Region={3}/{4}",
                                                  LogHeader,
                                                  (int)BSParam.TerrainImplementation,
                                                  BSParam.TerrainImplementation,
                                                  m_physicsScene.RegionName, terrainRegionBase);
                break;
            }
            return(newTerrainPhys);
        }
Example #2
0
        // Given an address, return 'true' of there is a description of that terrain and output
        //    the descriptor class and the 'base' fo the addresses therein.
        private bool GetTerrainPhysicalAtXYZ(Vector3 pos, out BSTerrainPhys outPhysTerrain, out Vector3 outTerrainBase)
        {
            bool ret = false;

            Vector3 terrainBaseXYZ = Vector3.Zero;

            if (pos.X < 0f || pos.Y < 0f)
            {
                // We don't handle negative addresses so just make up a base that will not be found.
                terrainBaseXYZ = new Vector3(-DefaultRegionSize.X, -DefaultRegionSize.Y, 0f);
            }
            else
            {
                int offsetX = ((int)(pos.X / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X;
                int offsetY = ((int)(pos.Y / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y;
                terrainBaseXYZ = new Vector3(offsetX, offsetY, 0f);
            }

            BSTerrainPhys physTerrain = null;

            m_terrainsRwLock.AcquireReaderLock(-1);
            try
            {
                ret = m_terrains.TryGetValue(terrainBaseXYZ, out physTerrain);
            }
            finally
            {
                m_terrainsRwLock.ReleaseReaderLock();
            }
            outTerrainBase = terrainBaseXYZ;
            outPhysTerrain = physTerrain;
            return(ret);
        }
        // TODO: redo terrain implementation selection to allow other base types than heightMap.
        private BSTerrainPhys BuildPhysicalTerrain(uint id, float[] heightMap)
        {
            // Find high and low points of passed heightmap.
            // 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 replace passed min and max Z with the actual terrain min/max Z.
            float minZ = float.MaxValue;
            float maxZ = float.MinValue;

            foreach (float height in heightMap)
            {
                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;
            }
            Vector3 minCoords = new Vector3(0, 0, minZ);
            Vector3 maxCoords = new Vector3(PhysicsScene.Scene.RegionInfo.RegionSizeX, PhysicsScene.Scene.RegionInfo.RegionSizeY, maxZ);

            PhysicsScene.Logger.DebugFormat("{0} Terrain for {1}/ created with {2}",
                                            LogHeader, PhysicsScene.RegionName,
                                            (BSTerrainPhys.TerrainImplementation)BSParam.TerrainImplementation);
            BSTerrainPhys newTerrainPhys = null;

            switch ((int)BSParam.TerrainImplementation)
            {
            case (int)BSTerrainPhys.TerrainImplementation.Heightmap:
                newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, Vector3.Zero, id,
                                                        heightMap, minCoords, maxCoords);
                break;

            case (int)BSTerrainPhys.TerrainImplementation.Mesh:
                newTerrainPhys = new BSTerrainMesh(PhysicsScene, Vector3.Zero, id,
                                                   heightMap, minCoords, maxCoords);
                break;

            default:
                PhysicsScene.Logger.ErrorFormat("{0} Bad terrain implementation specified. Type={1}/{2},Region={3}",
                                                LogHeader,
                                                (int)BSParam.TerrainImplementation,
                                                BSParam.TerrainImplementation,
                                                PhysicsScene.RegionName);
                break;
            }
            return(newTerrainPhys);
        }
Example #4
0
        // Given an address, return 'true' of there is a description of that terrain and output
        //    the descriptor class and the 'base' fo the addresses therein.
        private bool GetTerrainPhysicalAtXYZ(Vector3 pos, out BSTerrainPhys outPhysTerrain, out Vector3 outTerrainBase)
        {
            int     offsetX        = ((int)(pos.X / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X;
            int     offsetY        = ((int)(pos.Y / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y;
            Vector3 terrainBaseXYZ = new Vector3(offsetX, offsetY, 0f);

            BSTerrainPhys physTerrain = null;

            lock (m_terrains)
            {
                m_terrains.TryGetValue(terrainBaseXYZ, out physTerrain);
            }
            outTerrainBase = terrainBaseXYZ;
            outPhysTerrain = physTerrain;
            return(physTerrain != null);
        }
        // Create the initial instance of terrain and the underlying ground plane.
        // 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()
        {
            DetailLog("{0},BSTerrainManager.CreateInitialGroundPlaneAndTerrain,region={1}", BSScene.DetailLogZero, PhysicsScene.RegionName);
            // The ground plane is here to catch things that are trying to drop to negative infinity
            BulletShape groundPlaneShape = PhysicsScene.PE.CreateGroundPlaneShape(BSScene.GROUNDPLANE_ID, 1f, BSParam.TerrainCollisionMargin);

            m_groundPlane = PhysicsScene.PE.CreateBodyWithDefaultMotionState(groundPlaneShape,
                                                                             BSScene.GROUNDPLANE_ID, Vector3.Zero, Quaternion.Identity);

            PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, m_groundPlane);
            PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, m_groundPlane);
            // Ground plane does not move
            PhysicsScene.PE.ForceActivationState(m_groundPlane, ActivationState.DISABLE_SIMULATION);
            // Everything collides with the ground plane.
            m_groundPlane.collisionType = CollisionType.Groundplane;
            m_groundPlane.ApplyCollisionMask(PhysicsScene);

            m_terrain = new BSTerrainHeightmap(PhysicsScene, Vector3.Zero, BSScene.TERRAIN_ID, m_worldMax);
        }
        // If called for terrain has has not been previously allocated, a new terrain will be built
        //     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 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.)
        // Called during taint-time.
        private void UpdateTerrain(uint id, float[] heightMap)
        {
            DetailLog("{0},BSTerrainManager.UpdateTerrain,call,id={1}",
                      BSScene.DetailLogZero, id);

            if (m_terrain != null)
            {
                // There is already a terrain in this spot. Free the old and build the new.
                DetailLog("{0},BSTErrainManager.UpdateTerrain:UpdateExisting,call,id={1}",
                          BSScene.DetailLogZero, id);

                // Release any physical memory it may be using.
                m_terrain.Dispose();

                m_terrain = BuildPhysicalTerrain(id, heightMap);

                m_terrainModified = true;
            }
            else
            {
                // We don't know about this terrain so either we are creating a new terrain or
                //    our mega-prim child is giving us a new terrain to add to the phys world

                // if this is a child terrain, calculate a unique terrain id
                uint newTerrainID = id;
                if (newTerrainID >= BSScene.CHILDTERRAIN_ID)
                {
                    newTerrainID = ++m_terrainCount;
                }

                DetailLog("{0},BSTerrainManager.UpdateTerrain:NewTerrain,taint,newID={1}",
                          BSScene.DetailLogZero, newTerrainID);
                m_terrain = BuildPhysicalTerrain(id, heightMap);

                m_terrainModified = true;
            }
        }
Example #7
0
        // If called for terrain has has not been previously allocated, a new terrain will be built
        //     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 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.)
        // Called during taint-time.
        private void UpdateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords)
        {
            // Find high and low points of passed heightmap.
            // 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 replace passed min and max Z with the actual terrain min/max Z.
            float minZ = float.MaxValue;
            float maxZ = float.MinValue;

            foreach (float height in heightMap)
            {
                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;

            DetailLog("{0},BSTerrainManager.UpdateTerrain,call,id={1},minC={2},maxC={3}",
                      BSScene.DetailLogZero, id, minCoords, maxCoords);

            Vector3 terrainRegionBase = new Vector3(minCoords.X, minCoords.Y, 0f);

            m_terrainsRwLock.AcquireReaderLock(-1);
            try
            {
                BSTerrainPhys terrainPhys;
                if (m_terrains.TryGetValue(terrainRegionBase, out terrainPhys))
                {
                    // There is already a terrain in this spot. Free the old and build the new.
                    DetailLog("{0},BSTerrainManager.UpdateTerrain:UpdateExisting,call,id={1},base={2},minC={3},maxC={4}",
                              BSScene.DetailLogZero, id, terrainRegionBase, minCoords, maxCoords);

                    // Remove old terrain from the collection
                    m_terrains.Remove(terrainRegionBase);
                    // Release any physical memory it may be using.
                    terrainPhys.Dispose();

                    if (MegaRegionParentPhysicsScene == null)
                    {
                        // This terrain is not part of the mega-region scheme. Create vanilla terrain.
                        BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords);
                        LockCookie    lc             = m_terrainsRwLock.UpgradeToWriterLock(-1);
                        try
                        {
                            m_terrains.Add(terrainRegionBase, newTerrainPhys);
                        }
                        finally
                        {
                            m_terrainsRwLock.DowngradeFromWriterLock(ref lc);
                        }

                        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},BSTerrainManager.UpdateTerrain:AmACombineChild,taint", BSScene.DetailLogZero);

                        // Get rid of any terrain that may have been allocated for us.
                        ReleaseGroundPlaneAndTerrain();

                        // I hate doing this, but just bail
                        return;
                    }
                }
                else
                {
                    // We don't know about this terrain so either we are creating a new terrain or
                    //    our mega-prim child is giving us a new terrain to add to the phys world

                    // if this is a child terrain, calculate a unique terrain id
                    uint newTerrainID = id;
                    if (newTerrainID >= BSScene.CHILDTERRAIN_ID)
                    {
                        newTerrainID = ++m_terrainCount;
                    }

                    DetailLog("{0},BSTerrainManager.UpdateTerrain:NewTerrain,taint,newID={1},minCoord={2},maxCoord={3}",
                              BSScene.DetailLogZero, newTerrainID, minCoords, maxCoords);
                    BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords);
                    m_terrains.Add(terrainRegionBase, newTerrainPhys);

                    m_terrainModified = true;
                }
            }
            finally
            {
                m_terrainsRwLock.ReleaseReaderLock();
            }
        }
Example #8
0
    // Given an address, return 'true' of there is a description of that terrain and output
    //    the descriptor class and the 'base' fo the addresses therein.
    private bool GetTerrainPhysicalAtXYZ(Vector3 pos, out BSTerrainPhys outPhysTerrain, out Vector3 outTerrainBase)
    {
        bool ret = false;

        Vector3 terrainBaseXYZ = Vector3.Zero;
        if (pos.X < 0f || pos.Y < 0f)
        {
            // We don't handle negative addresses so just make up a base that will not be found.
            terrainBaseXYZ = new Vector3(-DefaultRegionSize.X, -DefaultRegionSize.Y, 0f);
        }
        else
        {
            int offsetX = ((int)(pos.X / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X;
            int offsetY = ((int)(pos.Y / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y;
            terrainBaseXYZ = new Vector3(offsetX, offsetY, 0f);
        }

        BSTerrainPhys physTerrain = null;
        lock (m_terrains)
        {
            ret = m_terrains.TryGetValue(terrainBaseXYZ, out physTerrain);
        }
        outTerrainBase = terrainBaseXYZ;
        outPhysTerrain = physTerrain;
        return ret;
    }
    // Given an address, return 'true' of there is a description of that terrain and output
    //    the descriptor class and the 'base' fo the addresses therein.
    private bool GetTerrainPhysicalAtXYZ(Vector3 pos, out BSTerrainPhys outPhysTerrain, out Vector3 outTerrainBase)
    {
        int offsetX = ((int)(pos.X / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X;
        int offsetY = ((int)(pos.Y / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y;
        Vector3 terrainBaseXYZ = new Vector3(offsetX, offsetY, 0f);

        BSTerrainPhys physTerrain = null;
        lock (m_terrains)
        {
            m_terrains.TryGetValue(terrainBaseXYZ, out physTerrain);
        }
        outTerrainBase = terrainBaseXYZ;
        outPhysTerrain = physTerrain;
        return (physTerrain != null);
    }
Example #10
0
        // If called for terrain has has not been previously allocated, a new terrain will be built
        //     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 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.)
        // Called during taint-time.
        private void UpdateTerrain(uint id, float[] heightMap)
        {
            DetailLog("{0},BSTerrainManager.UpdateTerrain,call,id={1}",
                            BSScene.DetailLogZero, id);

            if (m_terrain != null)
            {
            // There is already a terrain in this spot. Free the old and build the new.
            DetailLog("{0},BSTErrainManager.UpdateTerrain:UpdateExisting,call,id={1}",
                            BSScene.DetailLogZero, id);

            // Release any physical memory it may be using.
            m_terrain.Dispose();

            m_terrain = BuildPhysicalTerrain(id, heightMap);

            m_terrainModified = true;
            }
            else
            {
            // We don't know about this terrain so either we are creating a new terrain or
            //    our mega-prim child is giving us a new terrain to add to the phys world

            // if this is a child terrain, calculate a unique terrain id
            uint newTerrainID = id;
            if (newTerrainID >= BSScene.CHILDTERRAIN_ID)
                newTerrainID = ++m_terrainCount;

            DetailLog("{0},BSTerrainManager.UpdateTerrain:NewTerrain,taint,newID={1}",
                                        BSScene.DetailLogZero, newTerrainID);
            m_terrain = BuildPhysicalTerrain(id, heightMap);

            m_terrainModified = true;
            }
        }
Example #11
0
        // Create the initial instance of terrain and the underlying ground plane.
        // 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()
        {
            DetailLog("{0},BSTerrainManager.CreateInitialGroundPlaneAndTerrain,region={1}", BSScene.DetailLogZero, PhysicsScene.RegionName);
            // The ground plane is here to catch things that are trying to drop to negative infinity
            BulletShape groundPlaneShape = PhysicsScene.PE.CreateGroundPlaneShape(BSScene.GROUNDPLANE_ID, 1f, BSParam.TerrainCollisionMargin);
            m_groundPlane = PhysicsScene.PE.CreateBodyWithDefaultMotionState(groundPlaneShape,
                                        BSScene.GROUNDPLANE_ID, Vector3.Zero, Quaternion.Identity);

            PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, m_groundPlane);
            PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, m_groundPlane);
            // Ground plane does not move
            PhysicsScene.PE.ForceActivationState(m_groundPlane, ActivationState.DISABLE_SIMULATION);
            // Everything collides with the ground plane.
            m_groundPlane.collisionType = CollisionType.Groundplane;
            m_groundPlane.ApplyCollisionMask(PhysicsScene);

            m_terrain = new BSTerrainHeightmap(PhysicsScene, Vector3.Zero, BSScene.TERRAIN_ID, m_worldMax);
        }