Esempio n. 1
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();
            }
        }
Esempio n. 2
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();
			
		}