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(); }
public void ProcessChunks() { Profiler.BeginSample("ProcessChunks"); HandleVisibility(); // Process removal requests for (int i = 0; i < m_updateRequests.Count;) { Chunk chunk = m_updateRequests[i]; OnProcessChunk(chunk); // Update the chunk if possible if (chunk.Update()) { // Build geometry if there is enough time if (Globals.GeometryBudget.HasTimeBudget) { Globals.GeometryBudget.StartMeasurement(); bool wasBuilt = chunk.UpdateCollisionGeometry(); wasBuilt |= chunk.UpdateRenderGeometry(); if (wasBuilt) { Globals.GeometryBudget.StopMeasurement(); } } } // Automatically collect chunks which are ready to be removed from the world if (chunk.IsStateCompleted(ChunkState.Remove)) { // Remove the chunk from our provider and unregister it from chunk storage world.RemoveChunk(chunk); // Unregister from updates m_updateRequests.RemoveAt(i); continue; } ++i; } world.PerformBlockActions(); FullLoadOnStartUp = false; Profiler.EndSample(); }
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; } } } }
protected abstract void OnProcessChunk(Chunk chunk);
protected override void UpdateVisibility(int x, int y, int z, int rangeX, int rangeY, int rangeZ) { if (rangeX == 0 || rangeY == 0 || rangeZ == 0) { return; } Profiler.BeginSample("Cull"); bool isLast = rangeX == 1 && rangeY == 1 && rangeZ == 1; int wx = x * Env.ChunkSize; int wy = y * Env.ChunkSize; int wz = z * Env.ChunkSize; // Stop if there is no further subdivision possible if (isLast) { Profiler.BeginSample("CullLast"); // Update chunk's visibility information Vector3Int chunkPos = new Vector3Int(wx, wy, wz); Chunk chunk = world.GetChunk(ref chunkPos); if (chunk != null) { int tx = m_clipmap.TransformX(x); int ty = m_clipmap.TransformY(y); int tz = m_clipmap.TransformZ(z); // Skip chunks which are too far away if (m_clipmap.IsInsideBounds_Transformed(tx, ty, tz)) { // Update visibility information ClipmapItem item = m_clipmap.Get_Transformed(tx, ty, tz); bool isVisible = Planes.TestPlanesAABB(m_cameraPlanes, ref chunk.WorldBounds); chunk.NeedsRenderGeometry = isVisible && item.IsInVisibleRange; chunk.PossiblyVisible = isVisible; } } Profiler.EndSample(); // CullLast Profiler.EndSample(); // Cull return; } int rx = rangeX * Env.ChunkSize; int ry = rangeY * Env.ChunkSize; int rz = rangeZ * Env.ChunkSize; // Check whether the bouding box lies inside the camera's frustum AABB bounds2 = new AABB(wx, wy, wz, wx + rx, wy + ry, wz + rz); Planes.TestPlanesResult res = Planes.TestPlanesAABB2(m_cameraPlanes, ref bounds2); #region Full invisibility // Everything is invisible by default if (res == Planes.TestPlanesResult.Outside) { Profiler.EndSample(); // Cull return; } #endregion #region Full visibility if (res == Planes.TestPlanesResult.Inside) { Profiler.BeginSample("CullFullInside"); // Full visibility. All chunks in this area need to be made visible for (int cy = wy; cy < wy + ry; cy += Env.ChunkSize) { for (int cz = wz; cz < wz + rz; cz += Env.ChunkSize) { for (int cx = wx; cx < wx + rx; cx += Env.ChunkSize) { // Update chunk's visibility information Vector3Int chunkPos = new Vector3Int(cx, cy, cz); Chunk chunk = world.GetChunk(ref chunkPos); if (chunk == null) { continue; } int tx = m_clipmap.TransformX(x); int ty = m_clipmap.TransformY(y); int tz = m_clipmap.TransformZ(z); // Update visibility information ClipmapItem item = m_clipmap.Get_Transformed(tx, ty, tz); chunk.NeedsRenderGeometry = item.IsInVisibleRange; chunk.PossiblyVisible = true; } } } Profiler.EndSample(); // CullLast Profiler.EndSample(); // Cull return; } #endregion #region Partial visibility int offX = rangeX; if (rangeX > 1) { offX = rangeX >> 1; rangeX = rangeX - offX; } int offY = rangeY; if (rangeY > 1) { offY = rangeY >> 1; rangeY = rangeY - offY; } int offZ = rangeZ; if (rangeZ > 1) { offZ = rangeZ >> 1; rangeZ = rangeZ - offZ; } Profiler.EndSample(); // Subdivide if possible // TODO: Avoid the recursion UpdateVisibility(x, y, z, offX, offY, offZ); UpdateVisibility(x + offX, y, z, rangeX, offY, offZ); UpdateVisibility(x, y, z + offZ, offX, offY, rangeZ); UpdateVisibility(x + offX, y, z + offZ, rangeX, offY, rangeZ); UpdateVisibility(x, y + offY, z, offX, rangeY, offZ); UpdateVisibility(x + offX, y + offY, z, rangeX, rangeY, offZ); UpdateVisibility(x, y + offY, z + offZ, offX, rangeY, rangeZ); UpdateVisibility(x + offX, y + offY, z + offZ, rangeX, rangeY, rangeZ); #endregion }
public static void RemoveChunk(Chunk chunk) { chunk.Reset(); chunk.world = null; Globals.MemPools.ChunkPool.Push(chunk); }