예제 #1
0
        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();
        }
예제 #2
0
        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
        }