void AllocateWork(Chunk chunk, TerrainWorkerAction action)
        {
            if (GlobalNetwork.IsServer && action != TerrainWorkerAction.Populate)
            {
                return;
            }

            chunk.BeingWorkedOn = true;

            // Find the first worker that isnt busy, or the worker with the smallest
            // work count and add the action to it's queue.
            TerrainWorker worker = null;

            if (action != TerrainWorkerAction.CalculateLighting)
            {
                for (int i = 0; i < workers.Length; i++)
                {
                    TerrainWorker _worker = workers[i];
                    if (!_worker.IsBusy && (worker == null || _worker.WorkCount < worker.WorkCount))
                    {
                        worker = _worker;
                    }
                    else if (i == workers.Length - 1 && worker == null)
                    {
                        worker = _worker;
                    }
                }
            }
            else
            {
                worker = workers[workers.Length - 1];
            }

            worker.Enqueue(chunk, action);
        }
Example #2
0
        public void Enqueue(Chunk chunk, TerrainWorkerAction action)
        {
            if (disposed)
            {
                throw new ObjectDisposedException("TerrainWorker", "Cannot enqueue work, this TerrainWorker has been disposed!");
            }

            queue.Enqueue(new TerrainWorkerInstruction(chunk, action));
            resetEvent.Set();
        }
        public void Generate(int width, int height, int depth)
        {
            Chunk.rand = Maths.RandomRange(-1, 1);

            Width  = width;
            Height = height;
            Depth  = depth;

            currentPreAction = TerrainWorkerAction.Populate;
            preGenerating    = true;
            PopulateChunks();
        }
        public override void Update(float deltaTime)
        {
            if (!Ready && preGenerating)
            {
                // Handle pre-generation
                if (IsWorkersDone())
                {
                    if (currentPreAction == TerrainWorkerAction.Populate)
                    {
                        currentPreAction = TerrainWorkerAction.Shape;
                        ShapeChunks();
                    }
                    else if (currentPreAction == TerrainWorkerAction.Shape && !GlobalNetwork.IsServer)
                    {
                        currentPreAction = TerrainWorkerAction.CalculateLighting;
                        CalculateChunkLighting();
                    }
                    else if (currentPreAction == TerrainWorkerAction.CalculateLighting && !GlobalNetwork.IsServer)
                    {
                        currentPreAction = TerrainWorkerAction.BuildMesh;
                        BuildChunkMeshes();
                    }
                    else if (currentPreAction == TerrainWorkerAction.BuildMesh && !GlobalNetwork.IsServer)
                    {
                        while (MeshReadyChunks.Count > 0)
                        {
                            Chunk chunk;
                            if (MeshReadyChunks.TryDequeue(out chunk))
                            {
                                chunk.CreateOrUpdateMesh(BufferUsageHint.DynamicDraw);
                                chunk.State         = ChunkState.Renderable;
                                chunk.BeingWorkedOn = false;
                            }
                        }

                        Ready = true;
                    }
                    else if (currentPreAction != TerrainWorkerAction.Populate && GlobalNetwork.IsServer)
                    {
                        Ready = true;
                    }
                }
            }
            else if (!GlobalNetwork.IsServer)
            {
                // Every so often, check if any chunks need an update.
                if (applyWorkTime > 0)
                {
                    applyWorkTime -= deltaTime;
                }
                else
                {
                    applyWorkTime = applyWorkDelay;
                    foreach (Chunk chunk in Chunks.Values)
                    {
                        if (!chunk.BeingWorkedOn && (chunk.IsDirty || chunk.Lighting.IsDirty))
                        {
                            if (chunk.State == ChunkState.Renderable || chunk.Lighting.IsDirty)
                            {
                                chunk.State = ChunkState.Unlit;
                            }

                            if (chunk.State == ChunkState.Unlit)
                            {
                                chunk.IsDirty = true;

                                //if (chunk.Lighting.CanProcess())
                                AllocateWork(chunk, TerrainWorkerAction.CalculateLighting);
                            }
                            else if (chunk.State == ChunkState.Unbuilt)
                            {
                                if (chunk.Lighting.IsMeshReady())
                                {
                                    AllocateWork(chunk, TerrainWorkerAction.BuildMesh);
                                }
                            }
                        }
                    }
                }

                // Finish mesh ready chunks
                while (MeshReadyChunks.Count > 0)
                {
                    Chunk chunk;
                    if (MeshReadyChunks.TryDequeue(out chunk))
                    {
                        chunk.CreateOrUpdateMesh(BufferUsageHint.DynamicDraw);
                        chunk.State         = ChunkState.Renderable;
                        chunk.BeingWorkedOn = false;
                        chunk.IsDirty       = false;
                    }
                }
            }
        }
 public TerrainWorkerInstruction(Chunk chunk, TerrainWorkerAction action)
 {
     Chunk  = chunk;
     Action = action;
 }