I am trying to procedurally generate large amount of geometry. According to the tutorial (here) and other sources I should be using the MeshAccessor class to achieve this. I am wondering how I am supposed to do this?
Between extensive reading of the API docs and various AI hallucinations pointing me in hopefully the right direction I have come up with the following proof of concept to learn the API. Note that none of the following code was written by AI, it was only used as reference material.
public class TrackBuilder : Script
{
public Actor trackHolder;
public Material material;
public override void OnStart()
{
//create and instanciante the new object
StaticModel actor = new StaticModel();
actor.Parent = trackHolder;
//do the thing magic thing to allow dynamic geometery
actor.Model = Content.CreateVirtualAsset<Model>();
//create a list of LODs each containing n meshes. In out case 1 LOD containing 1 mesh.
//also maybe initialise the mesh coresponding to the LOD?
actor.Model.SetupLODs(new[] { 1 });
//create the Mesh accessesor
MeshAccessor accessor = new MeshAccessor();
//create the data
Float3[] verticies = new[]
{
/*0*/ new Float3(-1.5f, 0.0f, 0.0f),
/*1*/ new Float3(-1.0f, 0.5f, 0.0f),
/*2*/ new Float3( 1.0f, 0.5f, 0.0f),
/*3*/ new Float3( 1.5f, 0.0f, 0.0f),
/*4*/ new Float3(-1.5f, 0.0f, 1.0f),
/*5*/ new Float3(-1.0f, 0.5f, 1.0f),
/*6*/ new Float3( 1.0f, 0.5f, 1.0f),
/*7*/ new Float3( 1.5f, 0.0f, 1.0f),
/*8*/ new Float3(-1.5f, 0.0f, 2.0f),
/*9*/ new Float3(-1.0f, 0.5f, 2.0f),
/*10*/ new Float3( 1.0f, 0.5f, 2.0f),
/*11*/ new Float3( 1.5f, 0.0f, 2.0f),
};
Int32[] indicies = new[]
{
//front face
0, 1, 2,
0, 2, 3,
//first "cube"
//left face
4, 5, 1,
4, 1, 0,
//right face
3, 2, 6,
3, 6, 7,
//top face
1, 5, 6,
1, 6, 2,
//bottom face
4, 0, 3,
4, 3, 7,
//second "cube"
//left face
8, 9, 5,
8, 5, 4,
//right face
7, 6, 10,
7, 10, 11,
//top face
5, 9, 10,
5, 10, 6,
//bottom face
8, 4, 7,
8, 7, 11,
//back face
11, 10, 9,
11, 9, 8,
};
Float3[] normals = new[]
{
((verticies[1] - verticies[0]) + (verticies[3] - verticies[0]) + (verticies[4] - verticies[0])).Normalized,
((verticies[2] - verticies[1]) + (verticies[0] - verticies[1]) + (verticies[5] - verticies[1])).Normalized,
((verticies[3] - verticies[2]) + (verticies[1] - verticies[2]) + (verticies[6] - verticies[2])).Normalized,
((verticies[0] - verticies[3]) + (verticies[2] - verticies[3]) + (verticies[7] - verticies[3])).Normalized,
((verticies[5] - verticies[4]) + (verticies[7] - verticies[4]) + (verticies[8] - verticies[4]) + (verticies[0] - verticies[4])).Normalized,
((verticies[6] - verticies[5]) + (verticies[4] - verticies[5]) + (verticies[9] - verticies[5]) + (verticies[1] - verticies[5])).Normalized,
((verticies[7] - verticies[6]) + (verticies[5] - verticies[6]) + (verticies[10] - verticies[6]) + (verticies[2] - verticies[6])).Normalized,
((verticies[4] - verticies[7]) + (verticies[6] - verticies[7]) + (verticies[11] - verticies[7]) + (verticies[3] - verticies[7])).Normalized,
((verticies[9] - verticies[8]) + (verticies[11] - verticies[8]) + (verticies[4] - verticies[8])).Normalized,
((verticies[10] - verticies[9]) + (verticies[8] - verticies[9]) + (verticies[5] - verticies[9])).Normalized,
((verticies[11] - verticies[10]) + (verticies[9] - verticies[10]) + (verticies[6] - verticies[10])).Normalized,
((verticies[8] - verticies[11]) + (verticies[10] - verticies[11]) + (verticies[7] - verticies[11])).Normalized,
};
//give the accessor the changes
MeshAccessor.Stream vertexStream = accessor.Position();
for(int i = 0; i < verticies.Length; i++)
{
vertexStream.SetFloat3(i, verticies[i]);
}
MeshAccessor.Stream indexStream = accessor.Index();
for(int i = 0; i < indicies.Length; i++)
{
vertexStream.SetInt(i, indicies[i]);
}
MeshAccessor.Stream normalStream = accessor.Normal();
for(int i = 0; i < normals.Length; i++)
{
vertexStream.SetFloat3(i, normals[i]);
}
//write the chcnages to the GPU
accessor.UpdateMesh(actor.Model.LODs[0].Meshes[0]);
//boring things to make the mesh visable
actor.SetMaterial(0, material);
actor.Scale = new Vector3(100,100,100);
}
}
Currently this code does not work producing the following error, Cannot marshal 'parameter #2': Cannot marshal managed types when the runtime marshalling system is disabled. According to the stack trade the error is caused by this line vertexStream.SetFloat3(i, verticies[i]);. Based on my limited understanding of C# the only way to make a non-primiative type like Float3 unmanaged would be to delve into unsafe code which is unrecommended. Am I misusing MeshAccessor.Stream, or is unsafe required, or is my entire approach floored?
I am new to both the Flax Engine and this forum so apologies in advance if I get anything wrong.
Any advice would be greatly appreciated,
Ebony