Trying to build a mesh per SCD value and it proving to be a big mess. My Ideal solution would be to build the separate meshes on two different Jobs and only running whenPlanetBuildComponent changed but the mesh is a reference type. This is my best effort below if anyone has any advice please chip in. It works but it clumsy and Im very unhappy with it
Thanks
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
JobHandle sequentialDeps = inputDeps;
Entities
.WithAll<PlanetBuildComponent>()
.WithChangeFilter<PlanetBuildComponent>()
.ForEach((int entityInQueryIndex, in Entity e) =>
{
Debug.Log(
"<b> <size=13> <color=#EA70A3>Info : PlanetCreateBiomsSystem : GetPlanetIDs.</color> </size> </b>");
_planetId = new List<PlanetIdComponent>();
EntityManager.GetAllUniqueSharedComponentData<PlanetIdComponent>(_planetId);
})
.WithName("GetPlanetIDs")
.WithoutBurst()
.Run();
//
//
foreach (PlanetIdComponent id in _planetId)
{
Entities
.WithChangeFilter<PlanetBuildComponent>()
.WithSharedComponentFilter(id)
.WithReadOnly(id)
.ForEach((int entityInQueryIndex, in Entity e, in PlanetGraphComponent g, in RenderMesh m, in PlanetBuildComponent b ) =>
{
Debug.Log(
"<b> <size=13> <color=#EA70A3>Info : PlanetCreateBiomsSystem : PlanetBuildMesh 1.</color> </size> </b>");
Mesh newPlanetMesh = new Mesh();
int numVertices = b.VertexCount;
int numTriangles = numVertices * 2 - 4;
var vertexDataArray = new NativeArray<PlanetVertexData>(numTriangles * 3, Allocator.TempJob);
var vertexIndexDataArray = new NativeArray<PlanetVertexIndexData>(numTriangles * 3, Allocator.TempJob);
//
// Get mesh data
for (var i = 0; i < g.TileGraph.Value.Triangles.Length; i++)
{
//
// GetMeshTrianglePositions
var posVertA =
new float3(
g.TileGraph.Value.Vertices[g.TileGraph.Value.Triangles[i].VertA].PositionX,
g.TileGraph.Value.Vertices[g.TileGraph.Value.Triangles[i].VertA].PositionY,
g.TileGraph.Value.Vertices[g.TileGraph.Value.Triangles[i].VertA].PositionZ);
var posVertB =
new float3(
g.TileGraph.Value.Vertices[g.TileGraph.Value.Triangles[i].VertB].PositionX,
g.TileGraph.Value.Vertices[g.TileGraph.Value.Triangles[i].VertB].PositionY,
g.TileGraph.Value.Vertices[g.TileGraph.Value.Triangles[i].VertB].PositionZ);
var posVertC =
new float3(
g.TileGraph.Value.Vertices[g.TileGraph.Value.Triangles[i].VertC].PositionX,
g.TileGraph.Value.Vertices[g.TileGraph.Value.Triangles[i].VertC].PositionY,
g.TileGraph.Value.Vertices[g.TileGraph.Value.Triangles[i].VertC].PositionZ);
//
// GetMeshTriangleNormals
float3 norVertA =
math.normalize(
new float3(
g.TileGraph.Value.Vertices[g.TileGraph.Value.Triangles[i].VertA].PositionX,
g.TileGraph.Value.Vertices[g.TileGraph.Value.Triangles[i].VertA].PositionY,
g.TileGraph.Value.Vertices[g.TileGraph.Value.Triangles[i].VertA].PositionZ
)
);
float3 norVertB =
math.normalize(
new float3(
g.TileGraph.Value.Vertices[g.TileGraph.Value.Triangles[i].VertB].PositionX,
g.TileGraph.Value.Vertices[g.TileGraph.Value.Triangles[i].VertB].PositionY,
g.TileGraph.Value.Vertices[g.TileGraph.Value.Triangles[i].VertB].PositionZ
)
);
float3 norVertC =
math.normalize(
new float3(
g.TileGraph.Value.Vertices[g.TileGraph.Value.Triangles[i].VertC].PositionX,
g.TileGraph.Value.Vertices[g.TileGraph.Value.Triangles[i].VertC].PositionY,
g.TileGraph.Value.Vertices[g.TileGraph.Value.Triangles[i].VertC].PositionZ
)
);
//
// GetMeshTriangleTangents
var tanVertA = new float4(-norVertA.z, 0, norVertA.x, -1);
var tanVertB = new float4(-norVertB.z, 0, norVertB.x, -1);
var tanVertC = new float4(-norVertC.z, 0, norVertC.x, -1);
//
// GetMeshTriangleUv
var uvVertA = new
float2(
math.atan2(norVertA.x, norVertA.z) / (-2f * math.PI),
math.asin(norVertA.y) / math.PI + 0.5f
);
if (uvVertA.x < 0f) uvVertA.x += 1f;
var uvVertB = new
float2(
math.atan2(norVertB.x, norVertB.z) / (-2f * math.PI),
math.asin(norVertB.y) / math.PI + 0.5f
);
if (uvVertB.x < 0f) uvVertB.x += 1f;
var uvVertC = new
float2(
math.atan2(norVertC.x, norVertC.z) / (-2f * math.PI),
math.asin(norVertC.y) / math.PI + 0.5f
);
if (uvVertC.x < 0f) uvVertC.x += 1f;
//
// TODO : GetMeshTriangleColo
//
// Set VertexDataArray
var vertexDataA = new PlanetVertexData
{
Position = posVertA,
Normal = norVertA,
Tangent = tanVertA,
UVs = uvVertA,
Color = new int4(1, 1, 1, 1)
};
vertexDataArray[3 * i + 0] = vertexDataA;
var vertexDataB = new PlanetVertexData
{
Position = posVertB,
Normal = norVertB,
Tangent = tanVertB,
UVs = uvVertB,
Color = new int4(1, 1, 1, 1)
};
vertexDataArray[3 * i + 1] = vertexDataB;
var vertexDataC = new PlanetVertexData
{
Position = posVertC,
Normal = norVertC,
Tangent = tanVertC,
UVs = uvVertC,
Color = new int4(1, 1, 1, 1)
};
vertexDataArray[3 * i + 2] = vertexDataC;
//
// GetMeshTriangleIndices
vertexIndexDataArray[3 * i + 0] = 3 * i + 0;
vertexIndexDataArray[3 * i + 1] = 3 * i + 1;
vertexIndexDataArray[3 * i + 2] = 3 * i + 2;
}
//
// This descriptor must match VertexData structure.
var vertexAttrDescriptor = new[]
{
new VertexAttributeDescriptor(VertexAttribute.Position),
new VertexAttributeDescriptor(VertexAttribute.Normal),
new VertexAttributeDescriptor(VertexAttribute.Tangent, VertexAttributeFormat.Float32, 4),
new VertexAttributeDescriptor(VertexAttribute.Color, VertexAttributeFormat.UInt32, 4),
new VertexAttributeDescriptor(VertexAttribute.TexCoord0, VertexAttributeFormat.Float32, 2)
};
//
// Tell the mesh what format the params will be sent. Note the format must match VertexIndexData struct
newPlanetMesh.SetVertexBufferParams(vertexDataArray.Length, vertexAttrDescriptor);
newPlanetMesh.SetVertexBufferData(vertexDataArray, 0, 0, vertexDataArray.Length);
newPlanetMesh.SetIndexBufferParams(vertexIndexDataArray.Length, IndexFormat.UInt32);
newPlanetMesh.SetIndexBufferData(vertexIndexDataArray, 0, 0, vertexIndexDataArray.Length);
newPlanetMesh.subMeshCount = 1;
//
// Set SubMeshDescriptor
var descr = new SubMeshDescriptor
{
baseVertex = 0,
bounds = default,
indexCount = vertexDataArray.Length,
indexStart = 0,
topology = MeshTopology.Triangles
};
newPlanetMesh.SetSubMesh(0, descr);
//
// Bounds
newPlanetMesh.RecalculateBounds();
//
// Set SCD
EntityManager.SetSharedComponentData(e, new RenderMesh
{
material = m.material,
mesh = newPlanetMesh,
castShadows = m.castShadows,
receiveShadows = m.receiveShadows
});
//
// Cleanup
vertexDataArray.Dispose();
vertexIndexDataArray.Dispose();
})
.WithStructuralChanges()
.WithoutBurst()
.Run();
}
//
// Cleanup
_planetId.Clear();
return sequentialDeps;
}