Пример #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);
        }
Пример #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;

            lock (m_terrains)
            {
                ret = m_terrains.TryGetValue(terrainBaseXYZ, out physTerrain);
            }
            outTerrainBase = terrainBaseXYZ;
            outPhysTerrain = physTerrain;
            return(ret);
        }
Пример #3
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);

            lock (m_terrains)
            {
                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);
                        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},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;
                }
            }
        }