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); } }
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); } }
/// <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); } } }
/* * 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); } } }
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); } }
/// <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(); } }
/* * 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(); } }