public void PreProcessChunks() { Profiler.BeginSample("PreProcessChunks"); // Recalculate camera frustum planes Planes.CalculateFrustumPlanes(myCamera, cameraPlanes); // Update clipmap based on range values UpdateRanges(); // Update viewer position UpdateViewerPosition(); OnPreProcessChunks(); Profiler.EndSample(); }
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.CHUNK_SIZE; int wy = y * Env.CHUNK_SIZE; int wz = z * Env.CHUNK_SIZE; // 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 = clipmap.TransformX(x); int ty = clipmap.TransformY(y); int tz = clipmap.TransformZ(z); // Skip chunks which are too far away if (clipmap.IsInsideBounds_Transformed(tx, ty, tz)) { // Update visibility information ClipmapItem item = clipmap.Get_Transformed(tx, ty, tz); bool isVisible = Planes.TestPlanesAABB(cameraPlanes, ref chunk.worldBounds); chunk.NeedsRenderGeometry = isVisible && item.isInVisibleRange; chunk.PossiblyVisible = isVisible; } } Profiler.EndSample(); // CullLast Profiler.EndSample(); // Cull return; } int rx = rangeX * Env.CHUNK_SIZE; int ry = rangeY * Env.CHUNK_SIZE; int rz = rangeZ * Env.CHUNK_SIZE; // 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(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.CHUNK_SIZE) { for (int cz = wz; cz < wz + rz; cz += Env.CHUNK_SIZE) { for (int cx = wx; cx < wx + rx; cx += Env.CHUNK_SIZE) { // Update chunk's visibility information Vector3Int chunkPos = new Vector3Int(cx, cy, cz); Chunk chunk = world.GetChunk(ref chunkPos); if (chunk == null) { continue; } int tx = clipmap.TransformX(x); int ty = clipmap.TransformY(y); int tz = clipmap.TransformZ(z); // Update visibility information ClipmapItem item = 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 -= offX; } int offY = rangeY; if (rangeY > 1) { offY = rangeY >> 1; rangeY -= offY; } int offZ = rangeZ; if (rangeZ > 1) { offZ = rangeZ >> 1; 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 }