mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
cppkore uses string/wstring as StringBase while we use std::string/std::wstring as string/wstring. Changed all types in cppkore to String/WString instead.
169 lines
4.0 KiB
C++
169 lines
4.0 KiB
C++
#include "stdafx.h"
|
|
#include "WavefrontOBJ.h"
|
|
|
|
#include "File.h"
|
|
#include "Path.h"
|
|
#include "StreamWriter.h"
|
|
|
|
namespace Assets::Exporters
|
|
{
|
|
bool WavefrontOBJ::ExportAnimation(const Animation& Animation, const String& Path)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool WavefrontOBJ::ExportModel(const Model& Model, const String& Path)
|
|
{
|
|
auto Writer = IO::StreamWriter(IO::File::Create(Path));
|
|
auto MaterialPath = IO::Path::ChangeExtension(Path, ".mtl");
|
|
|
|
Writer.WriteLineFmt("\nmtllib %s\n", (char*)IO::Path::GetFileName(MaterialPath));
|
|
|
|
for (auto& Submesh : Model.Meshes)
|
|
{
|
|
for (auto& Face : Submesh.Faces)
|
|
{
|
|
auto& FaceVert1 = Submesh.Vertices[Face[0]].Position();
|
|
auto& FaceVert2 = Submesh.Vertices[Face[1]].Position();
|
|
auto& FaceVert3 = Submesh.Vertices[Face[2]].Position();
|
|
|
|
Writer.WriteLineFmt(
|
|
"v %f %f %f\n"
|
|
"v %f %f %f\n"
|
|
"v %f %f %f",
|
|
FaceVert1.X, FaceVert1.Y, FaceVert1.Z,
|
|
FaceVert2.X, FaceVert2.Y, FaceVert2.Z,
|
|
FaceVert3.X, FaceVert3.Y, FaceVert3.Z
|
|
);
|
|
}
|
|
}
|
|
|
|
for (auto& Submesh : Model.Meshes)
|
|
{
|
|
for (auto& Face : Submesh.Faces)
|
|
{
|
|
auto& FaceVert1 = Submesh.Vertices[Face[0]].UVLayers(0);
|
|
auto& FaceVert2 = Submesh.Vertices[Face[1]].UVLayers(0);
|
|
auto& FaceVert3 = Submesh.Vertices[Face[2]].UVLayers(0);
|
|
|
|
Writer.WriteLineFmt(
|
|
"vt %f %f\n"
|
|
"vt %f %f\n"
|
|
"vt %f %f",
|
|
FaceVert1.U, (1 - FaceVert1.V),
|
|
FaceVert2.U, (1 - FaceVert2.V),
|
|
FaceVert3.U, (1 - FaceVert3.V)
|
|
);
|
|
}
|
|
}
|
|
|
|
for (auto& Submesh : Model.Meshes)
|
|
{
|
|
for (auto& Face : Submesh.Faces)
|
|
{
|
|
auto& FaceVert1 = Submesh.Vertices[Face[0]].Normal();
|
|
auto& FaceVert2 = Submesh.Vertices[Face[1]].Normal();
|
|
auto& FaceVert3 = Submesh.Vertices[Face[2]].Normal();
|
|
|
|
Writer.WriteLineFmt(
|
|
"vn %f %f %f\n"
|
|
"vn %f %f %f\n"
|
|
"vn %f %f %f",
|
|
FaceVert1.X, FaceVert1.Y, FaceVert1.Z,
|
|
FaceVert2.X, FaceVert2.Y, FaceVert2.Z,
|
|
FaceVert3.X, FaceVert3.Y, FaceVert3.Z
|
|
);
|
|
}
|
|
}
|
|
|
|
uint64_t VertexIndex = 1;
|
|
|
|
for (auto& Submesh : Model.Meshes)
|
|
{
|
|
if (Submesh.MaterialIndices[0] > -1)
|
|
{
|
|
auto& Material = Model.Materials[Submesh.MaterialIndices[0]];
|
|
|
|
Writer.WriteLineFmt(
|
|
"g %s\n"
|
|
"usemtl %s",
|
|
(char*)Material.Name,
|
|
(char*)Material.Name
|
|
);
|
|
}
|
|
else
|
|
{
|
|
Writer.WriteLine(
|
|
"g default_material\n"
|
|
"usemtl default_material"
|
|
);
|
|
}
|
|
|
|
for (auto& Face : Submesh.Faces)
|
|
{
|
|
Writer.WriteLineFmt(
|
|
"f %d/%d/%d %d/%d/%d %d/%d/%d",
|
|
(VertexIndex + 2), (VertexIndex + 2), (VertexIndex + 2),
|
|
(VertexIndex + 1), (VertexIndex + 1), (VertexIndex + 1),
|
|
VertexIndex, VertexIndex, VertexIndex
|
|
);
|
|
|
|
VertexIndex += 3;
|
|
}
|
|
}
|
|
|
|
|
|
auto MatWriter = IO::StreamWriter(IO::File::Create(MaterialPath));
|
|
|
|
for (auto& Material : Model.Materials)
|
|
{
|
|
MatWriter.WriteLineFmt("newmtl %s", (char*)Material.Name);
|
|
|
|
MatWriter.WriteLine(
|
|
"illum 4\n"
|
|
"Kd 0.00 0.00 0.00\n"
|
|
"Ka 0.00 0.00 0.00\n"
|
|
"Ks 0.50 0.50 0.50"
|
|
);
|
|
|
|
if (Material.Slots.ContainsKey(MaterialSlotType::Albedo))
|
|
MatWriter.WriteLineFmt("map_Kd %s", (char*)Material.Slots[MaterialSlotType::Albedo].first);
|
|
else if (Material.Slots.ContainsKey(MaterialSlotType::Diffuse))
|
|
MatWriter.WriteLineFmt("map_Kd %s", (char*)Material.Slots[MaterialSlotType::Diffuse].first);
|
|
|
|
if (Material.Slots.ContainsKey(MaterialSlotType::Normal))
|
|
MatWriter.WriteLineFmt("map_bump %s", (char*)Material.Slots[MaterialSlotType::Normal].first);
|
|
if (Material.Slots.ContainsKey(MaterialSlotType::Specular))
|
|
MatWriter.WriteLineFmt("map_Ks %s", (char*)Material.Slots[MaterialSlotType::Specular].first);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
imstring WavefrontOBJ::ModelExtension()
|
|
{
|
|
return ".obj";
|
|
}
|
|
|
|
imstring WavefrontOBJ::AnimationExtension()
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
ExporterScale WavefrontOBJ::ExportScale()
|
|
{
|
|
// OBJ is considered generic, so we won't enforce a scale constant
|
|
return ExporterScale::Default;
|
|
}
|
|
|
|
bool WavefrontOBJ::SupportsAnimations()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool WavefrontOBJ::SupportsModels()
|
|
{
|
|
return true;
|
|
}
|
|
}
|