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();
}
}