Example #1
0
        protected float[] GetTile(int tx, int ty)
        {
            var key = Tile.Key(tx, ty, Width / TileSize + 1);

            if (!Cache.ContainsKey(key))
            {
                var data = ReadTile(tx, ty);

                if (Cache.Count() == Capacity)
                {
                    // Vvict least recently used tile if cache is full
                    Cache.RemoveFirst();
                }

                // Create tile, put it at the end of tileCache
                var tile = new Tile(tx, ty, data);

                Cache.AddLast(key, tile);

                return(data);
            }
            else
            {
                var tile = Cache.Get(key);

                Cache.Remove(key);
                Cache.AddLast(key, tile);

                return(tile.Data);
            }
        }
Example #2
0
        private float[] GetTile(int tx, int ty)
        {
            var key = new Id(tx, ty);

            if (!Cache.ContainsKey(key))
            {
                var data = GetValues(tx * TileSize, ty * TileSize);

                if (Cache.Count() == Capacity)
                {
                    // Evict least recently used tile if cache is full
                    Cache.RemoveFirst();
                }

                // Create tile, put it at the end of tileCache
                var tile = new Tile(tx, ty, data);

                Cache.AddLast(key, tile);

                return(data);
            }
            else
            {
                var tile = Cache.Get(key);

                Cache.Remove(key);
                Cache.AddLast(key, tile);

                return(tile.Data);
            }
        }
Example #3
0
        /// <summary>
        /// Call this when a tile is no longer needed.
        /// If the number of users of the tile is 0, then the tile will be moved from the used to the unused cache.
        /// </summary>
        /// <param name="tile">Tile.</param>
        public void PutTile(Tile tile)
        {
            if (tile == null)
            {
                return;
            }

            tile.DecrementUsers();

            // If there are no more users of this tile move the tile from the used cahce to the unused cache
            if (tile.Users <= 0)
            {
                var id = tile.TID;

                if (UsedTiles.ContainsKey(id))
                {
                    UsedTiles.Remove(id);
                }

                if (!UnusedTiles.ContainsKey(id))
                {
                    UnusedTiles.AddLast(id, tile);
                }
            }
        }
Example #4
0
        /*
         * Call this when a tile is no longer needed.
         * If the number of users of the tile is 0 then the tile will be moved from the used to the unused cache
         */
        public void PutTile(Tile tile)
        {
            if (tile == null)
            {
                return;
            }

            tile.DecrementUsers();

            //if there are no more users of this tile move the tile from the used cahce to the unused cache
            if (tile.GetUsers() <= 0)
            {
                Tile.TId id = tile.GetTId();

                if (m_usedTiles.ContainsKey(id))
                {
                    m_usedTiles.Remove(id);
                }

                if (!m_unusedTiles.ContainsKey(id))
                {
                    m_unusedTiles.AddLast(id, tile);
                }
            }
        }
Example #5
0
        private float[] GetTile(int tx, int ty)
        {
            var key = new Id(tx, ty);

            // TODO : Cache initialization...
            if (Cache == null)
            {
                Cache = new DictionaryQueue <Id, Tile>(new EqualityComparerID());
            }

            if (!Cache.ContainsKey(key))
            {
                var data = GetValues(tx * (int)TileSize.x, ty * (int)TileSize.y);

                if (Cache.Count() == Capacity)
                {
                    // Evict least recently used tile if cache is full
                    Cache.RemoveFirst();
                }

                // Create tile, put it at the end of tileCache
                var tile = new Tile(tx, ty, data);

                Cache.AddLast(key, tile);

                return(data);
            }
            else
            {
                var tile = Cache.Get(key);

                Cache.Remove(key);
                Cache.AddLast(key, tile);

                return(tile.Data);
            }
        }
Example #6
0
        /// <summary>
        /// Updates the <see cref="TerrainQuad.ZMin"/> and <see cref="TerrainQuad.ZMax"/> values.
        /// Used to create a better fitting bounding box.
        /// Is not essental and can be disabled if retriving the heights data from the GPU is causing performance issues.
        /// </summary>
        private void UpdateMinMax()
        {
            // If no quads need read back or if disabled return
            if (NeedsReadBackDictionary.Count == 0 || !EnableReadBack)
            {
                return;
            }

            // Make a copy of all the keys of the tiles that need to be read back
            var ids = new Tile.Id[NeedsReadBackDictionary.Count];

            NeedsReadBackDictionary.Keys.CopyTo(ids, 0);

            // Sort the keys by there level, lowest -> highest
            Array.Sort(ids, new Tile.ComparerID());

            var count = 0;

            // Foreach key read back the tiles data until the maxReadBacksPerFrame limit is reached
            foreach (var id in ids)
            {
                var treeZ = NeedsReadBackDictionary[id];

                // If elevations container already contains key then data has been read back before so just reapply the [min, max] values to TerranQuad
                if (ElevationsDicionary.ContainsKey(id))
                {
                    var info = ElevationsDicionary.Get(id);

                    treeZ.TerrainQuad.ZMin = info.Min;
                    treeZ.TerrainQuad.ZMax = info.Max;

                    NeedsReadBackDictionary.Remove(id);
                }
                else
                {
                    // If for some reason the tile is null remove from container and continue
                    if (treeZ.Tile == null)
                    {
                        NeedsReadBackDictionary.Remove(id);

                        continue;
                    }

                    var slot = treeZ.Tile.Slot[0] as GPUTileStorage.GPUSlot;

                    // If for some reason this is not a GPUSlot remove and continue
                    if (slot == null)
                    {
                        NeedsReadBackDictionary.Remove(id);

                        continue;
                    }

                    var texture = slot.Texture;
                    var size    = texture.width * texture.height;

                    var elevationInfo = new ElevationInfo();
                    elevationInfo.Elevations = new float[size];

                    // Read back heights data from texture
                    CBUtility.ReadFromRenderTexture(texture, CBUtility.Channels.R, ElevationsBuffer, GodManager.Instance.ReadData);

                    // Copy into elevations info
                    ElevationsBuffer.GetData(elevationInfo.Elevations);

                    // Find the min/max values
                    for (int i = 0; i < size; i++)
                    {
                        if (elevationInfo.Elevations[i] < elevationInfo.Min)
                        {
                            elevationInfo.Min = elevationInfo.Elevations[i];
                        }
                        if (elevationInfo.Elevations[i] > elevationInfo.Max)
                        {
                            elevationInfo.Max = elevationInfo.Elevations[i];
                        }
                    }

                    // Update TerrainQuad
                    treeZ.TerrainQuad.ZMin = elevationInfo.Min;
                    treeZ.TerrainQuad.ZMax = elevationInfo.Max;

                    // Store elevations to prevent having to read back again soon
                    // Add to end of container
                    ElevationsDicionary.AddLast(id, elevationInfo);
                    NeedsReadBackDictionary.Remove(id);

                    count++;

                    // If the number of rad back to do per frame has hit the limit stop loop.
                    if (count >= MaxReadBacksPerFrame)
                    {
                        break;
                    }
                }
            }

            // If the number of elevation info to store has exceded limit remove from start of container
            while (ElevationsDicionary.Count() > MaxStoredElevations)
            {
                ElevationsDicionary.RemoveFirst();
            }
        }
Example #7
0
        /*
         * Updates the terrainQuads min and max values. Used to create a better fitting bounding box.
         * Is not essental and can be disabled if retriving the heights data from the GPU is causing
         * performance issues.
         */
        void UpdateMinMax()
        {
            //if no quads need read back or if disabled return
            if (m_needReadBack.Count == 0 || !m_enableMinMaxReadBack)
            {
                return;
            }

            //Make a copy of all the keys of the tiles that need to be read back
            Tile.Id[] ids = new Tile.Id[m_needReadBack.Count];
            m_needReadBack.Keys.CopyTo(ids, 0);
            //Sort the keys by there level, lowest -> highest
            System.Array.Sort(ids, new Tile.ComparerID());

            int count = 0;

            //foreach key read back the tiles data until the maxReadBacksPerFrame limit is reached
            foreach (Tile.Id id in ids)
            {
                QuadTreeZ t = m_needReadBack[id];

                //If elevations container already contains key then data has been
                //read back before so just reapply the min/max values to TerranQuad
                if (m_elevations.ContainsKey(id))
                {
                    ElevationInfo info = m_elevations.Get(id);

                    t.quad.SetZMin(info.min);
                    t.quad.SetZMax(info.max);

                    m_needReadBack.Remove(id);
                }
                else
                {
                    //if for some reason the tile is null remove from container and continue
                    if (t.tile == null)
                    {
                        m_needReadBack.Remove(id);
                        continue;
                    }

                    GPUTileStorage.GPUSlot slot = t.tile.GetSlot()[0] as GPUTileStorage.GPUSlot;

                    //If for some reason this is not a GPUSlot remove and continue
                    if (slot == null)
                    {
                        m_needReadBack.Remove(id);
                        continue;
                    }

                    RenderTexture tex = slot.GetTexture();

                    int size = tex.width * tex.height;

                    ElevationInfo info = new ElevationInfo();
                    info.elevations = new float[size];
                    //Read back heights data from texture
                    CBUtility.ReadFromRenderTexture(tex, 1, m_elevationsBuffer, m_manager.GetReadData());
                    //Copy into elevations info
                    m_elevationsBuffer.GetData(info.elevations);
                    //Find the min/max values
                    for (int i = 0; i < size; i++)
                    {
                        if (info.elevations[i] < info.min)
                        {
                            info.min = info.elevations[i];
                        }
                        if (info.elevations[i] > info.max)
                        {
                            info.max = info.elevations[i];
                        }
                    }
                    //Update quad
                    t.quad.SetZMin(info.min);
                    t.quad.SetZMax(info.max);
                    //Store elevations to prevent having to read back again soon
                    //Add to end of container
                    m_elevations.AddLast(id, info);

                    m_needReadBack.Remove(id);

                    count++;
                    //If the number of rad back to do per frame has hit the limit stop loop.
                    if (count >= m_maxReadBacksPerFrame)
                    {
                        break;
                    }
                }
            }

            //If the number of elevation info to store has exceded limit remove from start of container
            while (m_elevations.Count() > m_maxStoredElevations)
            {
                m_elevations.RemoveFirst();
            }
        }