Saving a Static Mesh as an obj file at runtime

Hi all, I’m working on a project where I need to load an .obj file as a static mesh, edit it with a set of sculpting tools and finally save the resulting mesh as a new obj file to disk. All this has to be done at runtime.
I have managed the first two steps and am now working on the exporting and saving part of the mesh.

In formatting the file I am only interested in entering the position of the vertices (v), normals (vn) and faces (f). For the first two I used, respectively, FPositionVertexBuffer and FStaticMeshVertexBuffer of the static mesh from which it is easy to extract position and tangent of the vertex, for the faces I do not know what I should do. In particular I have no idea how the information about the triangles in the mesh is stored. The formatting requires that for each face (each triangle) I must have at least two values: vertex index1/normal index1, vertex index2/normal index2, vertex index3/normal index3 (with reference to the vertices that have been indicated in the list of v and vn). But how do I know which are the vertices of each face? And then, even once I’ve found out what the vertices of the face are, how do I associate them with the indices of the FStaticMeshVertexBuffer?

This is my code:

#include "MeshExporter.h"
#include "Math/Vector.h"
#include "RawIndexBuffer.h"
#include "StaticMeshResources.h"
#include "Rendering/StaticMeshVertexBuffer.h"
#include "Rendering/PositionVertexBuffer.h"

void UMeshExporter::ExportStaticMesh(UStaticMesh* staticMesh, FString path, FString fileName, bool triangleVertices)
{
	FString file = path;
	file.Append(fileName + ".txt");

	// We will use this FileManager to deal with the file.
	IPlatformFile& FileManager = FPlatformFileManager::Get().GetPlatformFile();

	const FStaticMeshVertexBuffer& VertexBuffer = staticMesh->RenderData->LODResources[0].VertexBuffers.StaticMeshVertexBuffer;
	const FPositionVertexBuffer& PositionVertexBuffer = staticMesh->RenderData->LODResources[0].VertexBuffers.PositionVertexBuffer;


	// Build the vertex list
	TArray<FVector> Vertices;
	TArray<FVector> Normals;
	const int32 VertexCount = PositionVertexBuffer.GetNumVertices();
	for (int32 i = 0; i < VertexCount; i++)
	{
		FVector Vertex = PositionVertexBuffer.VertexPosition(i);
		FVector Normal = VertexBuffer.VertexTangentZ(i);

		// save in your vertex array
		Vertices.Add(Vertex);
		Normals.Add(Normal);
	}
	
	for (int32 i = 0; i < Vertices.Num(); i++)
	{
		FString v = "v ";
		FString X_value = FString::SanitizeFloat(Vertices[i].X) + " ";
		FString Y_value = FString::SanitizeFloat(Vertices[i].Y) + " ";
		FString Z_value = FString::SanitizeFloat(Vertices[i].Z);
		FFileHelper::SaveStringToFile("\r\n" + v + X_value + Y_value + Z_value, *file, FFileHelper::EEncodingOptions::AutoDetect, &IFileManager::Get(), EFileWrite::FILEWRITE_Append);
	}
	for (int32 i = 0; i < Normals.Num(); i++)
	{
		FString StringToSave = Normals[i].ToString();
		FString vn = "vn ";
		FString X_value = FString::SanitizeFloat(Normals[i].X) + " ";
		FString Y_value = FString::SanitizeFloat(Normals[i].Y) + " ";
		FString Z_value = FString::SanitizeFloat(Normals[i].Z);
		FFileHelper::SaveStringToFile("\r\n" + vn + X_value + Y_value + Z_value, *file, FFileHelper::EEncodingOptions::AutoDetect, &IFileManager::Get(), EFileWrite::FILEWRITE_Append);
	}

	file.ReplaceInline(TEXT(".txt"), TEXT(".obj"), ESearchCase::IgnoreCase);
}

I hope I have made myself sufficiently clear, otherwise I am happy to specify the problem further.

I’d like to look into this sort of function as well, also stuck on the saving and exporting part. Unfortunately it does not seem like anyone has shared much of this process anywhere else yet, yours is the only topic I found.

Neither do I,I want to get obj meshes or vertexes locations from animation sequence by frame.