Create UStaticMesh from triangle datas

Hi everyone, i trying to find the way for create UStaticMesh from triangle data.
Here is my result so far. It make app crash with error “Array index out of bounds: 0 from an array of size 0”.


UStaticMesh* staticMesh = NewObject<UStaticMesh>();

// Create the static mesh render data
TUniquePtr<FStaticMeshRenderData> renderData = MakeUnique<FStaticMeshRenderData>();
staticMesh->SetRenderData(MoveTemp(renderData));
FStaticMeshLODResources* lODResource = new FStaticMeshLODResources();
staticMesh->GetRenderData()->LODResources.Add(lODResource);

//For vertices
numberItem2 = data["vertices"].size() / 3;
lODResource->VertexBuffers.PositionVertexBuffer.Init(numberItem2);
lODResource->VertexBuffers.StaticMeshVertexBuffer.Init(numberItem2, 1);
lODResource->VertexBuffers.ColorVertexBuffer.Init(numberItem2);
for (size_t j = 0; j < numberItem2; j++)
{
	FVector3f vertex = FVector3f(data["vertices"][j * 3].get<float>(),
	data["vertices"][j * 3 + 1].get<float>(), data["vertices"][j * 3 + 2].get<float>());

        lODResource->VertexBuffers.PositionVertexBuffer.VertexPosition(j) = vertex;
	lODResource->VertexBuffers.StaticMeshVertexBuffer.SetVertexTangents(j, FVector3f::ZeroVector, FVector3f::ZeroVector, FVector3f::ZeroVector);
	lODResource->VertexBuffers.StaticMeshVertexBuffer.SetVertexUV(j, 0, FVector2f(vertex));
	lODResource->VertexBuffers.ColorVertexBuffer.VertexColor(j) = FColor::White;
}

//For triangle
numberItem2 = data["triangles"].size();
TArray<uint32> indexBuffer;
indexBuffer.SetNum(numberItem2);
for (size_t j = 0; j < numberItem2; j++) {
	indexBuffer[j] = data["triangles"][j].get<uint32>();
}
lODResource->IndexBuffer.SetIndices(indexBuffer, EIndexBufferStride::Type::AutoDetect);

FStaticMeshSourceModel& SourceModel = staticMesh->AddSourceModel();
/*SourceModel.BuildSettings.bRecomputeNormals = true;
SourceModel.BuildSettings.bRecomputeTangents = true;
SourceModel.BuildSettings.bRemoveDegenerates = true;*/
//SourceModel.BuildSettings.bBuildReversedIndexBuffer = true;
/*SourceModel.BuildSettings.bUseFullPrecisionUVs = true;
SourceModel.BuildSettings.bGenerateLightmapUVs = true;
SourceModel.BuildSettings.SrcLightmapIndex = 0;
SourceModel.BuildSettings.DstLightmapIndex = 0;*/

staticMesh->PostEditChange();
staticMesh->MarkPackageDirty();
staticMesh->Build(false);

I tend to use RuntimeMeshComponent plugin (use the provided RuntimeMeshActor to set geometry).

But for your code, it seems for each LOD, it also want a vertex factory. And then to create the mesh, it wants a MeshDescription for each LOD.

Add this just after the line with LODResources.Add()

	staticMesh->GetRenderData()->LODVertexFactories.Add(FStaticMeshVertexFactories(ERHIFeatureLevel::SM6));

You’ll need to provide the shader model. That seems a bit weird to me. I’m sure there’s a way to get the current shader model instead of hardcoding it like this.

Then just before staticMesh->PostEditChange();, add this:

	staticMesh->CreateMeshDescription(0);

The 0 is the LOD number.

I still don’t know if this will work. But it compiled and it ran all the way through with no errors.

1 Like

Thank you, i found the way to using “UStaticMeshDescription” for create UStaticMesh.

For anyone who need this, you can find example to create/edit your mesh in UStaticMeshDescription::CreateCube

Ex:

UStaticMesh* staticMesh = NewObject<UStaticMesh>();
UStaticMeshDescription* staticMeshDescription = UStaticMesh::CreateStaticMeshDescription();
FPolygonGroupID polygonGroupId = staticMeshDescription->CreatePolygonGroup();
staticMeshDescription->CreateCube(pass_parrams_here);

staticMesh->BuildFromStaticMeshDescriptions(staticMeshDescriptions);