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();
        }
示例#3
0
        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;
                    }
                }
            }
        }
示例#4
0
 protected abstract void OnProcessChunk(Chunk chunk);
示例#5
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.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
        }
示例#6
0
 public static void RemoveChunk(Chunk chunk)
 {
     chunk.Reset();
     chunk.world = null;
     Globals.MemPools.ChunkPool.Push(chunk);
 }