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.