Creating a RenderMesh from within a job

So I basically have a list of vertices, triangles, and normals that I would like to draw. They are created from a job, but I am having issues with creating a mesh for the RenderMesh component. Basically, I cannot edit a mesh from within a job because it is not a value type. So, how would I create a RenderMesh component with all my data from within a job. I need to do it within a job because all of my data for the mesh is also generated within a job and I would like to avoid sync points. Code below:

using Unity.Entities;
using Unity.Jobs;
using Unity.Collections;
using Unity.Burst;
using UnityEngine;
using Unity.Rendering;

using static Unity.Mathematics.math;

using Unity.Mathematics;
public class ChunkMeshingSystem : JobComponentSystem
{
    EntityQuery chunksQuery; //and entity query that will grab all the chunks currently in the world
    NativeArray<Entity> chunks;
    Entity chunk;

    NativeHashMap<uint, Edge> activeEdges;
    NativeHashMap<uint, uint> activeVoxels;
    NativeHashMap<uint, uint> vertexIndices;


    NativeArray<int4> AXIS_OFFSET;
    NativeArray<int4> EDGE_NODE_OFFSETS;
    NativeArray<uint> ENCODED_EDGE_OFFSETS;
    NativeArray<uint> ENCODED_EDGE_NODE_OFFSETS;


    NativeList<float3> vertices;
    NativeList<float3> normals;
    NativeList<int> triangles;


    static int4[] AXIS_OFFSET_ARRAY =
    {
        int4(1, 0, 0, 0),
        int4(0, 1, 0, 0),
        int4(0, 0, 1, 0)
    };

    static int4[] EDGE_NODE_OFFSETS_ARRAY =
    {
        int4(0), int4(0, 0, 1, 0), int4(0, 1, 0, 0), int4(0, 1, 1, 0),
        int4(0), int4(1, 0, 0, 0), int4(0, 0, 1, 0), int4(1, 0, 1, 0),
        int4(0), int4(0, 1, 0, 0), int4(1, 0, 0, 0), int4(1, 1, 0, 0),
    };

    static uint[] ENCODED_EDGE_OFFSETS_ARRAY =
        {
        0x00000000,
        0x00100000,
        0x00000400,
        0x00100400,
        0x40000000,
        0x40100000,
        0x40000001,
        0x40100001,
        0x80000000,
        0x80000400,
        0x80000001,
        0x80000401
        };


    static uint[] ENCODED_EDGE_NODE_OFFSETS_ARRAY =
    {
        0x00000000,
        0x00100000,
        0x00000400,
        0x00100400,
        0x00000000,
        0x00000001,
        0x00100000,
        0x00100001,
        0x00000000,
        0x00000400,
        0x00000001,
        0x00000401,
    };


    protected override void OnCreate()
    {
        chunksQuery = World.Active.EntityManager.CreateEntityQuery(typeof(NeedsMeshing)); //initialize the chunk query to grab everything with "ChunkInfo" on it

        activeEdges = new NativeHashMap<uint, Edge>(64 * 64 * 64 * 3, Allocator.Persistent);
        activeVoxels = new NativeHashMap<uint, uint>(64 * 64 * 64, Allocator.Persistent);
        vertexIndices = new NativeHashMap<uint, uint>(64 * 64 * 64, Allocator.Persistent);

        vertices = new NativeList<float3>(64 * 64 * 64, Allocator.Persistent);
        normals = new NativeList<float3>(64 * 64 * 64, Allocator.Persistent);
        triangles = new NativeList<int>(64 * 64 * 64, Allocator.Persistent);

        AXIS_OFFSET = new NativeArray<int4>(3, Allocator.Persistent);
        AXIS_OFFSET.CopyFrom(AXIS_OFFSET_ARRAY);

        EDGE_NODE_OFFSETS = new NativeArray<int4>(12, Allocator.Persistent);
        EDGE_NODE_OFFSETS.CopyFrom(EDGE_NODE_OFFSETS_ARRAY);

        ENCODED_EDGE_OFFSETS = new NativeArray<uint>(12, Allocator.Persistent);
        ENCODED_EDGE_OFFSETS.CopyFrom(ENCODED_EDGE_OFFSETS_ARRAY);

        ENCODED_EDGE_NODE_OFFSETS = new NativeArray<uint>(12, Allocator.Persistent);
        ENCODED_EDGE_NODE_OFFSETS.CopyFrom(ENCODED_EDGE_NODE_OFFSETS_ARRAY);


    }

    [BurstCompile]
    public struct ClearBuffersJob : IJob
    {
        public NativeHashMap<uint, Edge> activeEdges;
        public NativeHashMap<uint, uint> activeVoxels;
        public NativeHashMap<uint, uint> vertexIndices;


        public NativeList<float3> vertices;
        public NativeList<float3> normals;
        public NativeList<int> triangles;

        public void Execute()
        {
            activeEdges.Clear();
            activeVoxels.Clear();
            vertices.Clear();
            normals.Clear();
            vertexIndices.Clear();
            triangles.Clear();
        }
    }


    [BurstCompile]
    public struct assembleRenderMeshJob : IJob
    {

        public NativeList<float3> vertices;
        public NativeList<float3> normals;
        public NativeList<int> triangles;

        public RenderMesh renderMesh;

        public Entity chunk;

        public EntityManager em;

        public void Execute()
        {
            renderMesh.mesh.SetVertices(vertices.AsArray());
            renderMesh.mesh.SetNormals(normals.AsArray());
            renderMesh.mesh.SetIndices(triangles.AsArray(), MeshTopology.Triangles, 0);


            em.AddSharedComponentData<RenderMesh>(chunk, renderMesh);

        }
    }





    protected override JobHandle OnUpdate(JobHandle inputDeps)
    {

        chunks = chunksQuery.ToEntityArray(Allocator.TempJob);

        if(chunks.Length == 0)
        {
            chunks.Dispose();
            return inputDeps;
        }

        chunk = chunks[0];
        chunks.Dispose();
        EntityManager.RemoveComponent<NeedsMeshing>(chunk);

        ChunkInfo chunkInfo = EntityManager.GetComponentData<ChunkInfo>(chunk);

        RenderMesh renderMesh = new RenderMesh()
        {
          

        };


        var ClearBuffers = new ClearBuffersJob()
        {
            activeEdges = activeEdges,
            activeVoxels = activeVoxels,
            vertexIndices = vertexIndices,
            vertices = vertices,
            normals = normals,
            triangles = triangles

        };

        var FindActiveVoxels = new FindActiveVoxelsAndEdgesJobs() {
            activeEdges = activeEdges.AsParallelWriter(),
            activeVoxels = activeVoxels.AsParallelWriter(),
            AXIS_OFFSET = AXIS_OFFSET,
            EDGE_NODE_OFFSETS = EDGE_NODE_OFFSETS,
            voxelData = EntityManager.GetBuffer<VoxelData>(chunk).Reinterpret<float>().ToNativeArray(Allocator.TempJob),
            SizeX = chunkInfo.size.x,
            SizeY = chunkInfo.size.y,
        };

        var GenerateVertexData = new GenerateVertexDataJob
        {
            activeEdges = activeEdges,
            activeVoxels = activeVoxels,
            vertexIndices = vertexIndices,
            vertices = vertices,
            normals = normals,
            ENCODED_EDGE_OFFSETS = ENCODED_EDGE_OFFSETS
           
        };

        var GenerateTriangleData = new GenerateTriangleDataJob
        {
            activeEdges = activeEdges,
            vertexIndices = vertexIndices,
            triangles = triangles,
            ENCODED_EDGE_NODE_OFFSETS = ENCODED_EDGE_NODE_OFFSETS
        };

        var AssembleRenderMesh = new assembleRenderMeshJob
        {
            renderMesh = renderMesh,
            vertices = vertices,
            normals = normals,
            triangles = triangles,
            em = EntityManager,
            chunk = chunk

        };

        JobHandle clearBufferHandle = ClearBuffers.Schedule(inputDeps);
        JobHandle FindActiveVoxelsHandle = FindActiveVoxels.Schedule(chunkInfo.size.x * chunkInfo.size.y * chunkInfo.size.z, 1, clearBufferHandle);
        JobHandle GenerateVertexDataHandle = GenerateVertexData.Schedule(FindActiveVoxelsHandle);
        JobHandle GenerateTriangleDataHandle = GenerateTriangleData.Schedule(GenerateVertexDataHandle);

        return GenerateTriangleDataHandle;


    }
    protected override void OnDestroy()
    {
        activeEdges.Dispose();
        activeVoxels.Dispose();
        vertexIndices.Dispose();

        vertices.Dispose();
        normals.Dispose();
        triangles.Dispose();

        AXIS_OFFSET.Dispose();
        EDGE_NODE_OFFSETS.Dispose();
        ENCODED_EDGE_OFFSETS.Dispose();
        ENCODED_EDGE_NODE_OFFSETS.Dispose();
    }
}
1 Like

Did you find a solution for mesh updates?