Structure of FStaticMeshLODResources (pulling Vertices, UVs, Normals & Triangles)?

I’ve been trying to pull the verices, UVs, triangles & Vertex Normals from a UStaticMesh. With mixed results. Anybody out there actively understand the layout of FStaticMeshLODResources?

Here’s what I’ve found so far:

Vertices

GetNumVertices() ← returns how many there are

PositionVertexBuffer.VertexPosition() ← returns a vertex

Thing is I get far, far, far more vertices than I would expect with many vertices duplicated many times

Normals

Engine code pulls them with .VertexBuffer.VertexTangentZ()

However if I link that call into my game I get :

error LNK2001: unresolved external symbol "__declspec(dllimport) union __m128 const GVectorPackingConstants" (__imp_?GVectorPackingConstants@@3T__m128@@B)

UVs

Seem relatively straight forward with VertexBuffer.GetVertexUV() but again, due to the duplicated vertices, I have lots of UVs. Plus I have 4 UV sets for a simple texture mapped piece of geometry.

Triangles

Engine code pulls these (FBXMainExport.cpp line 1800) with:

TArray<uint32> Indices;
for (int32 PolygonsIndex = 0; PolygonsIndex < PolygonsCount; ++PolygonsIndex)
{
	FIndexArrayView RawIndices = RenderMesh.IndexBuffer.GetArrayView();
	FStaticMeshSection& Polygons = RenderMesh.Sections[PolygonsIndex];
	const uint32 TriangleCount = Polygons.NumTriangles;
	for (uint32 TriangleIndex = 0; TriangleIndex < TriangleCount; ++TriangleIndex)
	{
		for (uint32 PointIndex = 0; PointIndex < 3; PointIndex++)
		{
			uint32 UnrealVertIndex = RawIndices[Polygons.FirstIndex + ((TriangleIndex * 3) + PointIndex)];
		}
	}
}

However when I run that in my code the triangle list comes out as 0,1,2,3,4,5,6,7,8. Is that why there are so many vertices because there is a vert / triangle?

I’m just wondering

  • Why are there so many verts?
  • Why can’t I VertexBuffer.VertexTangentZ (why is it Z?) and how do I link in GVectorPackingConstants?
  • Why are there so many UVs?
  • Why does a hierarchical mesh of 4 pieces seem to get welded into one single piece when I look at it in UStaticMesh?
  • Why is my triangle indices increasing by 1 each time from 0, i.e. 0,1,2,3,4
  • Are there any experts out there that understand this data structure and how to decypher it?

Answering my own question, for anybody else that comes across this. Source for this was the FBXMainExport.cpp file.

  • Why are there so many verts?

No idea, but the first thing you do is generate a list of unique vertices, as they are duplicated, and then have a mapping between welded verts and unwelded. This is done by the DetermineVertsToWeld function.

  • Why can’t I VertexBuffer.VertexTangentZ (why is it Z?) and how do I link in GVectorPackingConstants?

This in an external module that you need to link into your game. You do this by going to \source\.Build.cs and adding “RenderCore” to the PublicDependencyModuleNames. You can then call that function and unpack normals.

  • Why are there so many UVs?

Again no idea but you can pull the UV for each vertex by simply calling:

	const FVector2D& TexCoord = RenderMesh.VertexBuffer.GetVertexUV(UnrealPosIndex, 0);
  • Why does a hierarchical mesh of 4 pieces seem to get welded into one single piece when I look at it in UStaticMesh?

This is to do with how you import a static mesh. There is an option to “Combine Meshes” if you untick that then you get the individual mesh pieces when you import your FBX

  • Why is my triangle indices increasing by 1 each time from 0, i.e. 0,1,2,3,4

Again no idea but refering to the FBXMainExport.cpp file you will see that it initially generates a load of indices, then builds the triangle list towards the end of the function. If you literally rip that code across then you will get end up with a triangle list that seems to look sane.

  • Are there any experts out there that understand this data structure and how to decypher it?

I don’t think anybody truly understands the data structure, across all platforms, but FBXMainExport.cpp is the definitive guide on how to decypher it.