public ClipmapItem Get_Transformed(int tx, int ty, int tz) { // Clamp coordinates to the array range int xx = tx.Clamp(0, m_axes[0].Map.Length - 1); int yy = ty.Clamp(0, m_axes[1].Map.Length - 1); int zz = tz.Clamp(0, m_axes[2].Map.Length - 1); // Pick the furthest one int absX = Helpers.Abs(xx); int absY = Helpers.Abs(yy); int absZ = Helpers.Abs(zz); if (absX > absZ) { return((absX > absY) ? m_axes[0].Map[xx] : m_axes[1].Map[yy]); } return(absZ > absY ? m_axes[2].Map[zz] : m_axes[1].Map[yy]); }
protected override void OnProcessChunk(Chunk chunk) { Profiler.BeginSample("ProcessChunk"); int tx = m_clipmap.TransformX(chunk.Pos.x / Env.ChunkSize); int ty = m_clipmap.TransformY(chunk.Pos.y / Env.ChunkSize); int tz = m_clipmap.TransformZ(chunk.Pos.z / Env.ChunkSize); // Chunk is too far away. Remove it if (!m_clipmap.IsInsideBounds_Transformed(tx, ty, tz)) { chunk.RequestRemoval(); } else { // Dummy collider example - create a collider for chunks directly surrounding the viewer int xd = Helpers.Abs((m_viewerPos.x - chunk.Pos.x) / Env.ChunkSize); int yd = Helpers.Abs((m_viewerPos.y - chunk.Pos.y) / Env.ChunkSize); int zd = Helpers.Abs((m_viewerPos.z - chunk.Pos.z) / Env.ChunkSize); chunk.NeedsColliderGeometry = xd <= 1 && yd <= 1 && zd <= 1; if (!UseFrustumCulling) { ClipmapItem item = m_clipmap.Get_Transformed(tx, ty, tz); // Chunk is in visibilty range. Full update with geometry generation is possible if (item.IsInVisibleRange) { //chunk.LOD = item.LOD; chunk.PossiblyVisible = true; chunk.NeedsRenderGeometry = true; } // Chunk is in cached range. Full update except for geometry generation else { //chunk.LOD = item.LOD; chunk.PossiblyVisible = true; chunk.NeedsRenderGeometry = false; } } } }
public static Vector3Int[] ChunkPositions(int chunkLoadRadius) { var chunkLoads = new List <Vector3Int>(); for (int z = -chunkLoadRadius; z <= chunkLoadRadius; z++) { for (int x = -chunkLoadRadius; x <= chunkLoadRadius; x++) { chunkLoads.Add(new Vector3Int(x, 0, z)); } } //sort 2d vectors by closeness to center return(chunkLoads .Where(pos => pos.x * pos.x + pos.z * pos.z <= chunkLoadRadius * chunkLoadRadius) // keep this a circle .OrderBy(pos => Helpers.Abs(pos.x) + Helpers.Abs(pos.z)) //smallest magnitude vectors first .ThenBy(pos => Helpers.Abs(pos.x)) //make sure not to process e.g (-10,0) before (5,5) .ThenBy(pos => Helpers.Abs(pos.z)) .ToArray()); }
public static Vector3Int[] ChunkPositions(int chunkLoadRadius) { s_chunkLoads.Clear(); for (int z = -chunkLoadRadius; z <= chunkLoadRadius; z++) { for (int x = -chunkLoadRadius; x <= chunkLoadRadius; x++) { s_chunkLoads.Add(new Vector3Int(x, 0, z)); } } // Sort 2D vectors by closeness to the center return(s_chunkLoads .Where(pos => CheckXZ(pos.x, pos.z, chunkLoadRadius)) // Smallest magnitude vectors first .OrderBy(pos => Helpers.Abs(pos.x) + Helpers.Abs(pos.z)) // Make sure not to process e.g (-10,0) before (5,5) .ThenBy(pos => Helpers.Abs(pos.x)) .ThenBy(pos => Helpers.Abs(pos.z)) .ToArray()); }
public static Vector3Int[] ChunkPositions(int chunkLoadRadius) { var chunkLoads = new List <Vector3Int>(); for (int x = -chunkLoadRadius; x <= chunkLoadRadius; x++) { for (int z = -chunkLoadRadius; z <= chunkLoadRadius; z++) { chunkLoads.Add(new Vector3Int(x, 0, z)); } } // limit how far away the blocks can be to achieve a circular loading pattern float maxRadius = chunkLoadRadius * 1.55f; //sort 2d vectors by closeness to center return(chunkLoads .Where(pos => Helpers.Abs(pos.x) + Helpers.Abs(pos.z) < maxRadius) .OrderBy(pos => Helpers.Abs(pos.x) + Helpers.Abs(pos.z)) //smallest magnitude vectors first .ThenBy(pos => Helpers.Abs(pos.x)) //make sure not to process e.g (-10,0) before (5,5) .ThenBy(pos => Helpers.Abs(pos.z)) .ToArray()); }
public void ProcessChunk(Chunk chunk) { Profiler.BeginSample("ProcessChunk"); ChunkStateManagerClient stateManager = chunk.stateManager; int xd = (m_viewerPos.x - chunk.pos.x) / Env.ChunkSize; int yd = (m_viewerPos.y - chunk.pos.y) / Env.ChunkSize; int zd = (m_viewerPos.z - chunk.pos.z) / Env.ChunkSize; int hRadius = HorizontalChunkLoadRadius; int vRadius = VerticalChunkLoadRadius; int xDist = xd * xd + zd * zd; int yDist = yd * yd; // Remove the chunk if it is too far away if (xDist > hRadius * hRadius || yDist > vRadius * vRadius) { stateManager.RequestState(ChunkState.Remove); } else { // Dummy collider example - create a collider for chunks directly surrounding the viewer chunk.NeedsCollider = Helpers.Abs(xd) <= 1 && Helpers.Abs(yd) <= 1 && Helpers.Abs(zd) <= 1; if (!UseFrustumCulling) { // Update visibility information stateManager.Visible = xDist <= HorizontalChunkLoadRadius * HorizontalChunkLoadRadius && yDist <= VerticalChunkLoadRadius * VerticalChunkLoadRadius; stateManager.PossiblyVisible = true; } } Profiler.EndSample(); }
public void ProcessChunk(Chunk chunk) { int xd = Helpers.Abs((m_viewerPos.x - chunk.pos.x) >> Env.ChunkPower); int yd = Helpers.Abs((m_viewerPos.y - chunk.pos.y) >> Env.ChunkPower); int zd = Helpers.Abs((m_viewerPos.z - chunk.pos.z) >> Env.ChunkPower); int tx = m_clipmap.TransformX(chunk.pos.x >> Env.ChunkPower); int ty = m_clipmap.TransformY(chunk.pos.y >> Env.ChunkPower); int tz = m_clipmap.TransformZ(chunk.pos.z >> Env.ChunkPower); ChunkStateManagerClient stateManager = (ChunkStateManagerClient)chunk.stateManager; // Chunk is too far away. Remove it if (!m_clipmap.IsInsideBounds_Transformed(tx, ty, tz)) { stateManager.RequestState(ChunkState.Remove); } else { // Dummy collider example - create a collider for chunks directly surrounding the viewer chunk.NeedsCollider = xd <= 1 && yd <= 1 && zd <= 1; // Chunk is within view frustum if (FullLoadOnStartUp || IsChunkInViewFrustum(chunk)) { ClipmapItem item = m_clipmap.Get_Transformed(tx, ty, tz); // Chunk is within visibilty range. Full update with geometry generation is possible if (item.IsWithinVisibleRange) { //chunk.LOD = item.LOD; stateManager.PossiblyVisible = true; stateManager.Visible = true; } // Chunk is within cached range. Full update except for geometry generation else // if (item.IsWithinCachedRange) { //chunk.LOD = item.LOD; stateManager.PossiblyVisible = true; stateManager.Visible = false; } } else { ClipmapItem item = m_clipmap.Get_Transformed(tx, ty, tz); // Chunk is not in the view frustum but still within cached range if (item.IsWithinCachedRange) { //chunk.LOD = item.LOD; stateManager.PossiblyVisible = false; stateManager.Visible = false; } else // Weird state { Assert.IsFalse(true); stateManager.RequestState(ChunkState.Remove); } } } }
void Benchmark_AbsValue() { Debug.Log("Bechmark - abs"); using (StreamWriter writer = File.CreateText("perf_abs.txt")) { int[] number = { 0 }; double t = Clock.BenchmarkTime(() => { ++number[0]; number[0] = Mathf.Abs(number[0]); }, 1000000 ); Debug.LogFormat("Mathf.abs -> out:{0}, time:{1}", number[0], t.ToString(CultureInfo.InvariantCulture)); writer.WriteLine("Mathf.abs -> out:{0}, time:{1}", number[0], t.ToString(CultureInfo.InvariantCulture)); number[0] = 0; t = Clock.BenchmarkTime(() => { ++number[0]; number[0] = Math.Abs(number[0]); }, 1000000 ); Debug.LogFormat("Math.abs -> out:{0}, time:{1}", number[0], t.ToString(CultureInfo.InvariantCulture)); writer.WriteLine("Math.abs -> out:{0}, time:{1}", number[0], t.ToString(CultureInfo.InvariantCulture)); number[0] = 0; t = Clock.BenchmarkTime(() => { ++number[0]; number[0] = number[0] < 0 ? -number[0] : number[0]; }, 1000000 ); Debug.LogFormat("i < 0 ? -i : i -> out:{0}, time:{1}", number[0], t.ToString(CultureInfo.InvariantCulture)); writer.WriteLine("i < 0 ? -i : i -> out:{0}, time:{1}", number[0], t.ToString(CultureInfo.InvariantCulture)); number[0] = 0; t = Clock.BenchmarkTime(() => { ++number[0]; int mask = number[0] >> 31; number[0] = (number[0] + mask) ^ mask; }, 1000000 ); Debug.LogFormat("(i + mask) ^ mask -> out:{0}, time:{1}", number[0], t.ToString(CultureInfo.InvariantCulture)); writer.WriteLine("(i + mask) ^ mask -> out:{0}, time:{1}", number[0], t.ToString(CultureInfo.InvariantCulture)); number[0] = 0; t = Clock.BenchmarkTime(() => { ++number[0]; number[0] = (number[0] + (number[0] >> 31)) ^ (number[0] >> 31); }, 1000000 ); Debug.LogFormat("(i + (i >> 31)) ^ (i >> 31) -> out:{0}, time:{1}", number[0], t.ToString(CultureInfo.InvariantCulture)); writer.WriteLine("(i + (i >> 31)) ^ (i >> 31) -> out:{0}, time:{1}", number[0], t.ToString(CultureInfo.InvariantCulture)); number[0] = 0; t = Clock.BenchmarkTime(() => { ++number[0]; number[0] = Helpers.Abs(number[0]); }, 1000000 ); Debug.LogFormat("Helpers.abs -> out:{0}, time:{1}", number[0], t.ToString(CultureInfo.InvariantCulture)); writer.WriteLine("Helpers.Abs -> out:{0}, time:{1}", number[0], t.ToString(CultureInfo.InvariantCulture)); } }
protected override void OnProcessChunk(Chunk chunk) { Profiler.BeginSample("ProcessChunk"); int xd = (m_viewerPos.x - chunk.Pos.x) / Env.ChunkSize; int yd = (m_viewerPos.y - chunk.Pos.y) / Env.ChunkSize; int zd = (m_viewerPos.z - chunk.Pos.z) / Env.ChunkSize; // Remove the chunk if it is too far away if ( !ChunkLoadOrder.CheckXZ(xd, zd, HorizontalChunkLoadRadius) || !ChunkLoadOrder.CheckY(yd, VerticalChunkLoadRadius) ) { chunk.RequestRemoval(); } else { // Dummy collider example - create a collider for chunks directly surrounding the viewer chunk.NeedsColliderGeometry = Helpers.Abs(xd) <= 1 && Helpers.Abs(yd) <= 1 && Helpers.Abs(zd) <= 1; if (!UseFrustumCulling) { // Update visibility information chunk.NeedsRenderGeometry = true; chunk.PossiblyVisible = true; } } Profiler.EndSample(); }
void Benchmark_AbsValue() { const int iters = 1000000; Debug.Log("Bechmark - abs"); using (StreamWriter writer = File.CreateText("perf_abs.txt")) { int[] number = { 0 }; double t = Clock.BenchmarkTime( () => { ++number[0]; number[0] = Mathf.Abs(number[0]); }, iters ); t2 = t / iters; output = string.Format("Mathf.abs\nout:{0}\ntime:{1} | {2} ms", number[0], t.ToString(CultureInfo.InvariantCulture), t2.ToString(CultureInfo.InvariantCulture)); Debug.Log(output); foreach (string s in output.Split('\n')) { writer.WriteLine(s); } number[0] = 0; t = Clock.BenchmarkTime( () => { ++number[0]; number[0] = Math.Abs(number[0]); }, iters ); t2 = t / iters; output = string.Format("Math.abs\nout:{0}\ntime:{1} | {2} ms", number[0], t.ToString(CultureInfo.InvariantCulture), t2.ToString(CultureInfo.InvariantCulture)); Debug.Log(output); foreach (string s in output.Split('\n')) { writer.WriteLine(s); } number[0] = 0; t = Clock.BenchmarkTime( () => { ++number[0]; number[0] = Helpers.Abs(number[0]); }, iters ); t2 = t / iters; output = string.Format("Helpers.Abs\nout:{0}\ntime:{1} | {2} ms", number[0], t.ToString(CultureInfo.InvariantCulture), t2.ToString(CultureInfo.InvariantCulture)); Debug.Log(output); foreach (string s in output.Split('\n')) { writer.WriteLine(s); } number[0] = 0; t = Clock.BenchmarkTime( () => { ++number[0]; number[0] = number[0] < 0 ? -number[0] : number[0]; }, iters ); t2 = t / iters; output = string.Format("i < 0 ? -i : i\nout:{0}\ntime:{1} | {2} ms", number[0], t.ToString(CultureInfo.InvariantCulture), t2.ToString(CultureInfo.InvariantCulture)); Debug.Log(output); foreach (string s in output.Split('\n')) { writer.WriteLine(s); } number[0] = 0; t = Clock.BenchmarkTime( () => { ++number[0]; int mask = number[0] >> 31; number[0] = (number[0] + mask) ^ mask; }, iters ); t2 = t / iters; output = string.Format("(i + mask) ^ mask\nout:{0}\ntime:{1} | {2} ms", number[0], t.ToString(CultureInfo.InvariantCulture), t2.ToString(CultureInfo.InvariantCulture)); Debug.Log(output); foreach (string s in output.Split('\n')) { writer.WriteLine(s); } number[0] = 0; t = Clock.BenchmarkTime( () => { ++number[0]; number[0] = (number[0] + (number[0] >> 31)) ^ (number[0] >> 31); }, iters ); t2 = t / iters; output = string.Format("(i + (i >> 31)) ^ (i >> 31)\nout:{0}\ntime:{1} | {2} ms", number[0], t.ToString(CultureInfo.InvariantCulture), t2.ToString(CultureInfo.InvariantCulture)); Debug.Log(output); foreach (string s in output.Split('\n')) { writer.WriteLine(s); } } }
private void OnDrawGizmosSelected() { if (!enabled) { return; } float size = Env.ChunkSize * Env.BlockSize; float halfSize = size * 0.5f; float smallSize = size * 0.25f; if (world != null && world.chunks != null && (Diag_DrawWorldBounds || Diag_DrawLoadRange)) { foreach (Chunk chunk in world.chunks.chunkCollection) { if (Diag_DrawWorldBounds) { // Make central chunks more apparent by using yellow color bool isCentral = chunk.pos.x == m_viewerPos.x || chunk.pos.y == m_viewerPos.y || chunk.pos.z == m_viewerPos.z; Gizmos.color = isCentral ? Color.yellow : Color.blue; Vector3 chunkCenter = new Vector3( chunk.pos.x + (Env.ChunkSize >> 1), chunk.pos.y + (Env.ChunkSize >> 1), chunk.pos.z + (Env.ChunkSize >> 1) ); Vector3 chunkSize = new Vector3(Env.ChunkSize, Env.ChunkSize, Env.ChunkSize); Gizmos.DrawWireCube(chunkCenter, chunkSize); } if (Diag_DrawLoadRange) { Vector3Int pos = chunk.pos; int xd = Helpers.Abs((m_viewerPos.x - pos.x) / Env.ChunkSize); int zd = Helpers.Abs((m_viewerPos.z - pos.z) / Env.ChunkSize); int dist = xd * xd + zd * zd; if (dist <= HorizontalChunkLoadRadius * HorizontalChunkLoadRadius) { Gizmos.color = Color.green; Gizmos.DrawWireCube( new Vector3(chunk.pos.x + halfSize, 0, chunk.pos.z + halfSize), new Vector3(size - 1f, 0, size - 1f) ); } else { Gizmos.color = Color.red; Gizmos.DrawWireCube( new Vector3(chunk.pos.x + halfSize, 0, chunk.pos.z + halfSize), new Vector3(size - 1f, 0, size - 1f) ); } // Show generated chunks ChunkStateManagerClient stateManager = chunk.stateManager; if (stateManager.IsStateCompleted(ChunkState.Generate)) { Gizmos.color = Color.magenta; Gizmos.DrawWireCube( new Vector3(chunk.pos.x + halfSize, 0, chunk.pos.z + halfSize), new Vector3(smallSize - 0.05f, 0, smallSize - 0.05f) ); } } } } }
public static bool CheckY(int y, int dist) { return(Helpers.Abs(y) <= dist); // square }