Ejemplo n.º 1
0
        /// <summary>
        /// Looks for all visual mesh tasks and writes the generated meshes to the chunk.
        /// </summary>
        /// <param name="taskStack">The task stack.</param>
        /// <param name="chunk">The chunk to update.</param>
        private void UpdateVisualMesh(RemeshTaskStack taskStack, BlockChunk chunk)
        {
            var meshFilter   = chunk.GetComponent <MeshFilter>();
            var meshRenderer = chunk.GetComponent <MeshRenderer>();
            var visualMesh   = meshFilter.sharedMesh;

            ApplyVertexData <VisualRemeshTask>(taskStack, visualMesh);

            var materials = new Material[visualMesh.subMeshCount];

            int baseVertex   = 0;
            int submeshIndex = 0;

            for (int i = 0; i < taskStack.TaskCount; i++)
            {
                var task = taskStack.GetTask(i);

                if (task is VisualRemeshTask vis)
                {
                    var newMesh = vis.Finish();
                    visualMesh.SetTriangles(newMesh.Triangles, submeshIndex, true, baseVertex);
                    materials[submeshIndex] = m_BlockList.GetMaterial(vis.MaterialID);

                    submeshIndex++;
                    baseVertex += newMesh.Vertices.Count;
                }
            }

            meshFilter.sharedMesh        = visualMesh;
            meshRenderer.sharedMaterials = materials;
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Looks for all collision mesh tasks and writes the generated meshes to the chunk.
        /// </summary>
        /// <param name="taskStack">The task stack.</param>
        /// <param name="chunk">The chunk to update.</param>
        private void UpdateCollisionMesh(RemeshTaskStack taskStack, BlockChunk chunk)
        {
            var meshCollider  = chunk.GetComponent <MeshCollider>();
            var collisionMesh = meshCollider.sharedMesh;

            ApplyVertexData <CollisionRemeshTask>(taskStack, collisionMesh);

            int baseVertex   = 0;
            int submeshIndex = 0;

            for (int i = 0; i < taskStack.TaskCount; i++)
            {
                var task = taskStack.GetTask(i);

                if (task is CollisionRemeshTask vis)
                {
                    var newMesh = vis.Finish();
                    collisionMesh.SetTriangles(newMesh.Triangles, submeshIndex, true, baseVertex);

                    submeshIndex++;
                    baseVertex += newMesh.Vertices.Count;
                }
            }

            meshCollider.sharedMesh = collisionMesh;
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Updates mesh data for the given chunk.
        /// </summary>
        /// <param name="taskStack">The set of remesh tasks.</param>
        /// <param name="chunk">The chunk to update.</param>
        internal void UpdateMesh(RemeshTaskStack taskStack, BlockChunk chunk)
        {
            UpdateVisualMesh(taskStack, chunk);
            UpdateCollisionMesh(taskStack, chunk);

            m_ProcMesh.Clear();
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Iterates over all blocks in the chunk, creating visual tasks as needed.
        /// </summary>
        /// <param name="properties">The chunk properties.</param>
        /// <param name="tasks">The task list to add to.</param>
        private void VisualBlockIterator(ChunkProperties properties, RemeshTaskStack taskStack)
        {
            var volume = m_BlockWorld.ChunkSize.Volume;
            var blocks = properties.Blocks;

            for (int i = 0; i < volume; i++)
            {
                var type = blocks[i];

                if (!type.IsVisible)
                {
                    continue;
                }

                var faces = type.Faces;
                for (int j = 0; j < 6; j++)
                {
                    var material = faces[j].MaterialID;
                    if (m_MaterialBuffer[material])
                    {
                        continue;
                    }

                    m_MaterialBuffer[material] = true;
                    taskStack.AddTask(new VisualRemeshTask(properties, material, PullMesher()));
                }
            }
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Iterates over all blocks in the chunk, creating visual tasks as needed.
        /// </summary>
        /// <param name="properties">The chunk properties.</param>
        /// <param name="tasks">The task list to add to.</param>
        private void VisualBlockIterator(ChunkGroup properties, RemeshTaskStack taskStack)
        {
            var volume = m_ChunkSize.Volume;
            var blocks = properties.Blocks;

            for (int i = 0; i < volume; i++)
            {
                var type = m_BlockList.GetBlockType(blocks[i]);

                if (!type.Visible)
                {
                    continue;
                }

                // TODO Make sure block type is a cube

                for (int j = 0; j < type.FaceCount; j++)
                {
                    var material = type.Face(j).MaterialID;
                    if (m_MaterialBuffer[material])
                    {
                        continue;
                    }

                    m_MaterialBuffer[material] = true;
                    taskStack.AddTask(new VisualRemeshTask(properties, material, PullMesher()));
                }
            }
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Retrieves vertex data from the task stack and writes it to the mesh object.
        /// </summary>
        /// <param name="taskStack">The task stack to pull from.</param>
        /// <param name="mesh">The mesh to write to.</param>
        /// <typeparam name="T">The type of tasks to look for in the stack.</typeparam>
        private void ApplyVertexData <T>(RemeshTaskStack taskStack, Mesh mesh)
        {
            GetVertexData <T>(taskStack, out int submeshCount);

            mesh.Clear();
            mesh.subMeshCount = submeshCount;
            mesh.SetVertices(m_ProcMesh.Vertices);
            mesh.SetNormals(m_ProcMesh.Normals);
            mesh.SetUVs(0, m_ProcMesh.UVs);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Analyses the given chunk and starts a set of remesh tasks for handling that chunk.
        /// This method blocks until all remesh tasks have been completed.
        /// </summary>
        /// <param name="worldContainer">The world to operate on.</param>
        /// <param name="chunkPos">The chunk target position.</param>
        internal RemeshTaskStack RemeshChunk(WorldContainer worldContainer, ChunkPosition chunkPos)
        {
            var taskStack  = new RemeshTaskStack(chunkPos);
            var chunkGroup = new ChunkGroup(worldContainer, chunkPos);

            foreach (var dis in m_Distributors)
            {
                dis.CreateTasks(chunkGroup, taskStack);
            }

            return(taskStack);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Generates the collision remesh task, as needed.
        /// </summary>
        /// <param name="properties">The chunk properties.</param>
        /// <param name="tasks">The task list to add to.</param>
        private void GenerateCollision(ChunkProperties properties, RemeshTaskStack taskStack)
        {
            int volume = m_BlockWorld.ChunkSize.Volume;

            for (int i = 0; i < volume; i++)
            {
                var type = properties.Blocks[i];

                if (type.IsSolid)
                {
                    taskStack.AddTask(new CollisionRemeshTask(properties, PullMesher()));
                    return;
                }
            }
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Generates the collision remesh task, as needed.
        /// </summary>
        /// <param name="properties">The chunk properties.</param>
        /// <param name="tasks">The task list to add to.</param>
        private void GenerateCollision(ChunkGroup properties, RemeshTaskStack taskStack)
        {
            int volume = m_ChunkSize.Volume;
            var blocks = properties.Blocks;

            for (int i = 0; i < volume; i++)
            {
                var type = m_BlockList.GetBlockType(blocks[i]);

                if (type.Solid)
                {
                    taskStack.AddTask(new CollisionRemeshTask(properties, PullMesher()));
                    return;
                }
            }
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Pulls vertex data from the task stack and puts it into the procMesh.
        /// </summary>
        /// <param name="taskStack">The task stack to pull from.</param>
        /// <param name="submeshCount">The number of submeshes being generated.</param>
        /// <typeparam name="T">The type of task to look for.</typeparam>
        private void GetVertexData <T>(RemeshTaskStack taskStack, out int submeshCount)
        {
            m_ProcMesh.Clear();
            submeshCount = 0;

            for (int i = 0; i < taskStack.TaskCount; i++)
            {
                var task = taskStack.GetTask(i);

                if (task is T)
                {
                    var newMesh = task.Finish();
                    m_ProcMesh.Vertices.AddRange(newMesh.Vertices);
                    m_ProcMesh.Normals.AddRange(newMesh.Normals);
                    m_ProcMesh.UVs.AddRange(newMesh.UVs);
                    submeshCount++;
                }
            }
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Analyses the given chunk and starts a set of remesh tasks for handling that chunk.
        /// If the chunk was scheduled to be remeshed later, it will be immediately be remeshed.
        /// If the chunk is already being remeshed, this method does nothing.
        /// </summary>
        /// <param name="chunkPos">The chunk target position.</param>
        /// <param name="pendingTask">
        /// If true, this task is allowed to task any number of frames to finish. Otherwise, the task
        /// is required to finish the next frame.
        /// </param>
        internal void RemeshChunk(ChunkPosition chunkPos, bool pendingTask = false)
        {
            for (int i = 0; i < m_ActiveTasks.Count; i++)
            {
                if (m_ActiveTasks[i].ChunkPosition.Equals(chunkPos))
                {
                    m_ActiveTasks[i].IsPendingTask = false;
                    return;
                }
            }

            for (int i = 0; i < m_PendingRemesh.Count; i++)
            {
                if (m_PendingRemesh[i].Equals(chunkPos))
                {
                    m_PendingRemesh.RemoveAt(i);
                    break;
                }
            }

            var properties = m_ChunkPropertiesPool.Pull();
            var blockList  = m_BlockWorld.BlockList;
            var world      = m_BlockWorld.WorldContainer.World;

            ChunkAnalyzer.LoadProperties(properties, blockList, world, chunkPos);

            var taskStack = new RemeshTaskStack(properties);

            taskStack.IsPendingTask = pendingTask;
            m_ActiveTasks.Add(taskStack);

            foreach (var dis in m_Distributors)
            {
                dis.CreateTasks(properties, taskStack);
            }
        }
Ejemplo n.º 12
0
 /// <summary>
 /// Generates the visual remeshing tasks, as needed.
 /// </summary>
 /// <param name="properties">The chunk properties.</param>
 /// <param name="tasks">The task list to add to.</param>
 private void GenerateVisuals(ChunkGroup properties, RemeshTaskStack taskStack)
 {
     PrepareMaterialBuffer();
     VisualBlockIterator(properties, taskStack);
     ResetMaterialBuffer();
 }
Ejemplo n.º 13
0
 /// <inheritdoc cref="IRemeshTask"/>
 public void CreateTasks(ChunkGroup properties, RemeshTaskStack taskStack)
 {
     GenerateVisuals(properties, taskStack);
     GenerateCollision(properties, taskStack);
 }
Ejemplo n.º 14
0
        /// <summary>
        /// Updates a chunk mesh based on the results of a finished task stack.
        /// </summary>
        /// <param name="task">The finished task stack.</param>
        private void BuildChunkMesh(RemeshTaskStack task)
        {
            var chunk = GetChunk(task.ChunkPosition);

            m_ChunkMeshBuilder.UpdateMesh(task, chunk);
        }