mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 16:15:43 +00:00
chore: update xmodel common to be a struct with substructs
This commit is contained in:
parent
0a65c93aa5
commit
826e59d627
@ -3,8 +3,8 @@
|
|||||||
#include "Math/Quaternion.h"
|
#include "Math/Quaternion.h"
|
||||||
#include "Utils/DistinctMapper.h"
|
#include "Utils/DistinctMapper.h"
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
struct XModelObject
|
struct XModelObject
|
||||||
{
|
{
|
||||||
@ -31,8 +31,7 @@ struct XModelBoneWeight
|
|||||||
|
|
||||||
struct XModelVertexBoneWeightCollection
|
struct XModelVertexBoneWeightCollection
|
||||||
{
|
{
|
||||||
std::unique_ptr<XModelBoneWeight[]> weights;
|
std::vector<XModelBoneWeight> weights;
|
||||||
size_t totalWeightCount;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct XModelVertexBoneWeights
|
struct XModelVertexBoneWeights
|
||||||
@ -93,6 +92,17 @@ struct XModelMaterial
|
|||||||
void ApplyDefaults();
|
void ApplyDefaults();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct XModelCommon
|
||||||
|
{
|
||||||
|
std::vector<XModelObject> m_objects;
|
||||||
|
std::vector<XModelBone> m_bones;
|
||||||
|
std::vector<XModelMaterial> m_materials;
|
||||||
|
std::vector<XModelVertex> m_vertices;
|
||||||
|
std::vector<XModelVertexBoneWeights> m_vertex_bone_weights;
|
||||||
|
std::vector<XModelFace> m_faces;
|
||||||
|
XModelVertexBoneWeightCollection m_bone_weight_data;
|
||||||
|
};
|
||||||
|
|
||||||
struct VertexMergerPos
|
struct VertexMergerPos
|
||||||
{
|
{
|
||||||
float x;
|
float x;
|
||||||
|
@ -6,12 +6,12 @@
|
|||||||
#include "Utils/DistinctMapper.h"
|
#include "Utils/DistinctMapper.h"
|
||||||
#include "Utils/HalfFloat.h"
|
#include "Utils/HalfFloat.h"
|
||||||
#include "Utils/QuatInt16.h"
|
#include "Utils/QuatInt16.h"
|
||||||
#include "XModel/AbstractXModelWriter.h"
|
|
||||||
#include "XModel/Export/XModelExportWriter.h"
|
#include "XModel/Export/XModelExportWriter.h"
|
||||||
#include "XModel/Gltf/GltfBinOutput.h"
|
#include "XModel/Gltf/GltfBinOutput.h"
|
||||||
#include "XModel/Gltf/GltfTextOutput.h"
|
#include "XModel/Gltf/GltfTextOutput.h"
|
||||||
#include "XModel/Gltf/GltfWriter.h"
|
#include "XModel/Gltf/GltfWriter.h"
|
||||||
#include "XModel/Obj/ObjWriter.h"
|
#include "XModel/Obj/ObjWriter.h"
|
||||||
|
#include "XModel/XModelWriter.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <format>
|
#include <format>
|
||||||
@ -140,7 +140,7 @@ namespace
|
|||||||
for (auto surfIndex = 0u; surfIndex < surfCount; surfIndex++)
|
for (auto surfIndex = 0u; surfIndex < surfCount; surfIndex++)
|
||||||
{
|
{
|
||||||
ObjObject object;
|
ObjObject object;
|
||||||
object.name = "surf" + std::to_string(surfIndex);
|
object.name = std::format("surf{}", surfIndex);
|
||||||
object.materialIndex = static_cast<int>(materialMapper.GetDistinctPositionByInputPosition(surfIndex + baseSurfIndex));
|
object.materialIndex = static_cast<int>(materialMapper.GetDistinctPositionByInputPosition(surfIndex + baseSurfIndex));
|
||||||
|
|
||||||
writer.AddObject(std::move(object));
|
writer.AddObject(std::move(object));
|
||||||
@ -245,7 +245,7 @@ namespace
|
|||||||
writer.WriteObj(*assetFile, std::format("{}.mtl", model->name));
|
writer.WriteObj(*assetFile, std::format("{}.mtl", model->name));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddXModelBones(const AssetDumpingContext& context, AbstractXModelWriter& writer, const XModel* model)
|
void AddXModelBones(XModelCommon& out, const AssetDumpingContext& context, const XModel* model)
|
||||||
{
|
{
|
||||||
for (auto boneNum = 0u; boneNum < model->numBones; boneNum++)
|
for (auto boneNum = 0u; boneNum < model->numBones; boneNum++)
|
||||||
{
|
{
|
||||||
@ -288,11 +288,11 @@ namespace
|
|||||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][3]));
|
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][3]));
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.AddBone(std::move(bone));
|
out.m_bones.emplace_back(std::move(bone));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddXModelMaterials(AbstractXModelWriter& writer, DistinctMapper<Material*>& materialMapper, const XModel* model)
|
void AddXModelMaterials(XModelCommon& out, DistinctMapper<Material*>& materialMapper, const XModel* model)
|
||||||
{
|
{
|
||||||
for (auto surfaceMaterialNum = 0; surfaceMaterialNum < model->numsurfs; surfaceMaterialNum++)
|
for (auto surfaceMaterialNum = 0; surfaceMaterialNum < model->numsurfs; surfaceMaterialNum++)
|
||||||
{
|
{
|
||||||
@ -307,12 +307,12 @@ namespace
|
|||||||
if (colorMap)
|
if (colorMap)
|
||||||
xMaterial.colorMapName = std::string(colorMap->name);
|
xMaterial.colorMapName = std::string(colorMap->name);
|
||||||
|
|
||||||
writer.AddMaterial(std::move(xMaterial));
|
out.m_materials.emplace_back(std::move(xMaterial));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddXModelObjects(AbstractXModelWriter& writer, const XModel* model, const unsigned lod, const DistinctMapper<Material*>& materialMapper)
|
void AddXModelObjects(XModelCommon& out, const XModel* model, const unsigned lod, const DistinctMapper<Material*>& materialMapper)
|
||||||
{
|
{
|
||||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||||
const auto baseSurfaceIndex = model->lodInfo[lod].surfIndex;
|
const auto baseSurfaceIndex = model->lodInfo[lod].surfIndex;
|
||||||
@ -320,14 +320,14 @@ namespace
|
|||||||
for (auto surfIndex = 0u; surfIndex < surfCount; surfIndex++)
|
for (auto surfIndex = 0u; surfIndex < surfCount; surfIndex++)
|
||||||
{
|
{
|
||||||
XModelObject object;
|
XModelObject object;
|
||||||
object.name = "surf" + std::to_string(surfIndex);
|
object.name = std::format("surf{}", surfIndex);
|
||||||
object.materialIndex = static_cast<int>(materialMapper.GetDistinctPositionByInputPosition(surfIndex + baseSurfaceIndex));
|
object.materialIndex = static_cast<int>(materialMapper.GetDistinctPositionByInputPosition(surfIndex + baseSurfaceIndex));
|
||||||
|
|
||||||
writer.AddObject(std::move(object));
|
out.m_objects.emplace_back(std::move(object));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddXModelVertices(AbstractXModelWriter& writer, const XModel* model, const unsigned lod)
|
void AddXModelVertices(XModelCommon& out, const XModel* model, const unsigned lod)
|
||||||
{
|
{
|
||||||
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
||||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||||
@ -361,7 +361,7 @@ namespace
|
|||||||
vertex.uv[0] = uv[0];
|
vertex.uv[0] = uv[0];
|
||||||
vertex.uv[1] = uv[1];
|
vertex.uv[1] = uv[1];
|
||||||
|
|
||||||
writer.AddVertex(vertex);
|
out.m_vertices.emplace_back(vertex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -371,29 +371,29 @@ namespace
|
|||||||
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
||||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||||
|
|
||||||
weightCollection.totalWeightCount = 0u;
|
auto totalWeightCount = 0u;
|
||||||
for (auto surfIndex = 0u; surfIndex < surfCount; surfIndex++)
|
for (auto surfIndex = 0u; surfIndex < surfCount; surfIndex++)
|
||||||
{
|
{
|
||||||
const auto& surface = surfs[surfIndex];
|
const auto& surface = surfs[surfIndex];
|
||||||
|
|
||||||
if (surface.vertList)
|
if (surface.vertList)
|
||||||
{
|
{
|
||||||
weightCollection.totalWeightCount += surface.vertListCount;
|
totalWeightCount += surface.vertListCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (surface.vertInfo.vertsBlend)
|
if (surface.vertInfo.vertsBlend)
|
||||||
{
|
{
|
||||||
weightCollection.totalWeightCount += surface.vertInfo.vertCount[0] * 1;
|
totalWeightCount += surface.vertInfo.vertCount[0] * 1;
|
||||||
weightCollection.totalWeightCount += surface.vertInfo.vertCount[1] * 2;
|
totalWeightCount += surface.vertInfo.vertCount[1] * 2;
|
||||||
weightCollection.totalWeightCount += surface.vertInfo.vertCount[2] * 3;
|
totalWeightCount += surface.vertInfo.vertCount[2] * 3;
|
||||||
weightCollection.totalWeightCount += surface.vertInfo.vertCount[3] * 4;
|
totalWeightCount += surface.vertInfo.vertCount[3] * 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
weightCollection.weights = std::make_unique<XModelBoneWeight[]>(weightCollection.totalWeightCount);
|
weightCollection.weights.resize(totalWeightCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddXModelVertexBoneWeights(AbstractXModelWriter& writer, const XModel* model, const unsigned lod, XModelVertexBoneWeightCollection& weightCollection)
|
void AddXModelVertexBoneWeights(XModelCommon& out, const XModel* model, const unsigned lod, XModelVertexBoneWeightCollection& weightCollection)
|
||||||
{
|
{
|
||||||
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
||||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||||
@ -416,7 +416,7 @@ namespace
|
|||||||
|
|
||||||
for (auto vertListVertexOffset = 0u; vertListVertexOffset < vertList.vertCount; vertListVertexOffset++)
|
for (auto vertListVertexOffset = 0u; vertListVertexOffset < vertList.vertCount; vertListVertexOffset++)
|
||||||
{
|
{
|
||||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{boneWeightOffset, 1});
|
out.m_vertex_bone_weights.emplace_back(boneWeightOffset, 1);
|
||||||
}
|
}
|
||||||
handledVertices += vertList.vertCount;
|
handledVertices += vertList.vertCount;
|
||||||
}
|
}
|
||||||
@ -434,7 +434,7 @@ namespace
|
|||||||
|
|
||||||
vertsBlendOffset += 1;
|
vertsBlendOffset += 1;
|
||||||
|
|
||||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{boneWeightOffset, 1});
|
out.m_vertex_bone_weights.emplace_back(boneWeightOffset, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2 bone weights
|
// 2 bone weights
|
||||||
@ -451,7 +451,7 @@ namespace
|
|||||||
|
|
||||||
vertsBlendOffset += 3;
|
vertsBlendOffset += 3;
|
||||||
|
|
||||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{boneWeightOffset, 2});
|
out.m_vertex_bone_weights.emplace_back(boneWeightOffset, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3 bone weights
|
// 3 bone weights
|
||||||
@ -471,7 +471,7 @@ namespace
|
|||||||
|
|
||||||
vertsBlendOffset += 5;
|
vertsBlendOffset += 5;
|
||||||
|
|
||||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{boneWeightOffset, 3});
|
out.m_vertex_bone_weights.emplace_back(boneWeightOffset, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4 bone weights
|
// 4 bone weights
|
||||||
@ -494,7 +494,7 @@ namespace
|
|||||||
|
|
||||||
vertsBlendOffset += 7;
|
vertsBlendOffset += 7;
|
||||||
|
|
||||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{boneWeightOffset, 4});
|
out.m_vertex_bone_weights.emplace_back(boneWeightOffset, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
handledVertices +=
|
handledVertices +=
|
||||||
@ -503,12 +503,12 @@ namespace
|
|||||||
|
|
||||||
for (; handledVertices < surface.vertCount; handledVertices++)
|
for (; handledVertices < surface.vertCount; handledVertices++)
|
||||||
{
|
{
|
||||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{nullptr, 0});
|
out.m_vertex_bone_weights.emplace_back(nullptr, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddXModelFaces(AbstractXModelWriter& writer, const XModel* model, const unsigned lod)
|
void AddXModelFaces(XModelCommon& out, const XModel* model, const unsigned lod)
|
||||||
{
|
{
|
||||||
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
||||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||||
@ -525,26 +525,26 @@ namespace
|
|||||||
face.vertexIndex[1] = tri[1] + surface.baseVertIndex;
|
face.vertexIndex[1] = tri[1] + surface.baseVertIndex;
|
||||||
face.vertexIndex[2] = tri[2] + surface.baseVertIndex;
|
face.vertexIndex[2] = tri[2] + surface.baseVertIndex;
|
||||||
face.objectIndex = static_cast<int>(surfIndex);
|
face.objectIndex = static_cast<int>(surfIndex);
|
||||||
writer.AddFace(face);
|
out.m_faces.emplace_back(face);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PopulateXModelWriter(const AssetDumpingContext& context, const unsigned lod, const XModel* model, AbstractXModelWriter& writer)
|
void PopulateXModelWriter(XModelCommon& out, const AssetDumpingContext& context, const unsigned lod, const XModel* model)
|
||||||
{
|
{
|
||||||
DistinctMapper<Material*> materialMapper(model->numsurfs);
|
DistinctMapper<Material*> materialMapper(model->numsurfs);
|
||||||
XModelVertexBoneWeightCollection boneWeightCollection;
|
XModelVertexBoneWeightCollection boneWeightCollection;
|
||||||
AllocateXModelBoneWeights(model, lod, boneWeightCollection);
|
AllocateXModelBoneWeights(model, lod, boneWeightCollection);
|
||||||
|
|
||||||
AddXModelBones(context, writer, model);
|
AddXModelBones(out, context, model);
|
||||||
AddXModelMaterials(writer, materialMapper, model);
|
AddXModelMaterials(out, materialMapper, model);
|
||||||
AddXModelObjects(writer, model, lod, materialMapper);
|
AddXModelObjects(out, model, lod, materialMapper);
|
||||||
AddXModelVertices(writer, model, lod);
|
AddXModelVertices(out, model, lod);
|
||||||
AddXModelVertexBoneWeights(writer, model, lod, boneWeightCollection);
|
AddXModelVertexBoneWeights(out, model, lod, boneWeightCollection);
|
||||||
AddXModelFaces(writer, model, lod);
|
AddXModelFaces(out, model, lod);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DumpXModelExportLod(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset, const unsigned lod)
|
void DumpXModelExportLod(const XModelCommon& common, const AssetDumpingContext& context, const XAssetInfo<XModel>* asset, const unsigned lod)
|
||||||
{
|
{
|
||||||
const auto* model = asset->Asset();
|
const auto* model = asset->Asset();
|
||||||
const auto assetFile = context.OpenAssetFile(GetFileNameForLod(model->name, lod, ".XMODEL_EXPORT"));
|
const auto assetFile = context.OpenAssetFile(GetFileNameForLod(model->name, lod, ".XMODEL_EXPORT"));
|
||||||
@ -552,13 +552,13 @@ namespace
|
|||||||
if (!assetFile)
|
if (!assetFile)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto writer = XModelExportWriter::CreateWriterForVersion6(context.m_zone->m_game->GetShortName(), context.m_zone->m_name);
|
const auto writer = xmodel_export::CreateWriterForVersion6(*assetFile, context.m_zone->m_game->GetShortName(), context.m_zone->m_name);
|
||||||
PopulateXModelWriter(context, lod, model, *writer);
|
writer->Write(common);
|
||||||
|
|
||||||
writer->Write(*assetFile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> void DumpGltfLod(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset, const unsigned lod, const std::string& extension)
|
template<typename T>
|
||||||
|
void DumpGltfLod(
|
||||||
|
const XModelCommon& common, const AssetDumpingContext& context, const XAssetInfo<XModel>* asset, const unsigned lod, const std::string& extension)
|
||||||
{
|
{
|
||||||
const auto* model = asset->Asset();
|
const auto* model = asset->Asset();
|
||||||
const auto assetFile = context.OpenAssetFile(GetFileNameForLod(model->name, lod, extension));
|
const auto assetFile = context.OpenAssetFile(GetFileNameForLod(model->name, lod, extension));
|
||||||
@ -568,9 +568,8 @@ namespace
|
|||||||
|
|
||||||
const auto output = std::make_unique<T>(*assetFile);
|
const auto output = std::make_unique<T>(*assetFile);
|
||||||
const auto writer = gltf::Writer::CreateWriter(output.get(), context.m_zone->m_game->GetShortName(), context.m_zone->m_name);
|
const auto writer = gltf::Writer::CreateWriter(output.get(), context.m_zone->m_game->GetShortName(), context.m_zone->m_name);
|
||||||
PopulateXModelWriter(context, lod, model, *writer);
|
|
||||||
|
|
||||||
writer->Write(*assetFile);
|
writer->Write(common);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DumpXModelSurfs(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset)
|
void DumpXModelSurfs(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset)
|
||||||
@ -582,6 +581,9 @@ namespace
|
|||||||
|
|
||||||
for (auto currentLod = 0u; currentLod < model->numLods; currentLod++)
|
for (auto currentLod = 0u; currentLod < model->numLods; currentLod++)
|
||||||
{
|
{
|
||||||
|
XModelCommon common;
|
||||||
|
PopulateXModelWriter(common, context, currentLod, asset->Asset());
|
||||||
|
|
||||||
switch (ObjWriting::Configuration.ModelOutputFormat)
|
switch (ObjWriting::Configuration.ModelOutputFormat)
|
||||||
{
|
{
|
||||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::OBJ:
|
case ObjWriting::Configuration_t::ModelOutputFormat_e::OBJ:
|
||||||
@ -589,15 +591,15 @@ namespace
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::XMODEL_EXPORT:
|
case ObjWriting::Configuration_t::ModelOutputFormat_e::XMODEL_EXPORT:
|
||||||
DumpXModelExportLod(context, asset, currentLod);
|
DumpXModelExportLod(common, context, asset, currentLod);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::GLTF:
|
case ObjWriting::Configuration_t::ModelOutputFormat_e::GLTF:
|
||||||
DumpGltfLod<gltf::TextOutput>(context, asset, currentLod, ".gltf");
|
DumpGltfLod<gltf::TextOutput>(common, context, asset, currentLod, ".gltf");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::GLB:
|
case ObjWriting::Configuration_t::ModelOutputFormat_e::GLB:
|
||||||
DumpGltfLod<gltf::BinOutput>(context, asset, currentLod, ".glb");
|
DumpGltfLod<gltf::BinOutput>(common, context, asset, currentLod, ".glb");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -6,12 +6,12 @@
|
|||||||
#include "Utils/DistinctMapper.h"
|
#include "Utils/DistinctMapper.h"
|
||||||
#include "Utils/HalfFloat.h"
|
#include "Utils/HalfFloat.h"
|
||||||
#include "Utils/QuatInt16.h"
|
#include "Utils/QuatInt16.h"
|
||||||
#include "XModel/AbstractXModelWriter.h"
|
|
||||||
#include "XModel/Export/XModelExportWriter.h"
|
#include "XModel/Export/XModelExportWriter.h"
|
||||||
#include "XModel/Gltf/GltfBinOutput.h"
|
#include "XModel/Gltf/GltfBinOutput.h"
|
||||||
#include "XModel/Gltf/GltfTextOutput.h"
|
#include "XModel/Gltf/GltfTextOutput.h"
|
||||||
#include "XModel/Gltf/GltfWriter.h"
|
#include "XModel/Gltf/GltfWriter.h"
|
||||||
#include "XModel/Obj/ObjWriter.h"
|
#include "XModel/Obj/ObjWriter.h"
|
||||||
|
#include "XModel/XModelWriter.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <format>
|
#include <format>
|
||||||
@ -147,7 +147,7 @@ namespace
|
|||||||
for (auto surfIndex = 0u; surfIndex < modelSurfs->numsurfs; surfIndex++)
|
for (auto surfIndex = 0u; surfIndex < modelSurfs->numsurfs; surfIndex++)
|
||||||
{
|
{
|
||||||
ObjObject object;
|
ObjObject object;
|
||||||
object.name = "surf" + std::to_string(surfIndex);
|
object.name = std::format("surf{}", surfIndex);
|
||||||
object.materialIndex = static_cast<int>(materialMapper.GetDistinctPositionByInputPosition(surfIndex + baseSurfaceIndex));
|
object.materialIndex = static_cast<int>(materialMapper.GetDistinctPositionByInputPosition(surfIndex + baseSurfaceIndex));
|
||||||
|
|
||||||
writer.AddObject(std::move(object));
|
writer.AddObject(std::move(object));
|
||||||
@ -251,7 +251,7 @@ namespace
|
|||||||
writer.WriteObj(*assetFile, std::format("{}.mtl", model->name));
|
writer.WriteObj(*assetFile, std::format("{}.mtl", model->name));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddXModelBones(const AssetDumpingContext& context, AbstractXModelWriter& writer, const XModel* model)
|
void AddXModelBones(XModelCommon& out, const AssetDumpingContext& context, const XModel* model)
|
||||||
{
|
{
|
||||||
for (auto boneNum = 0u; boneNum < model->numBones; boneNum++)
|
for (auto boneNum = 0u; boneNum < model->numBones; boneNum++)
|
||||||
{
|
{
|
||||||
@ -294,11 +294,11 @@ namespace
|
|||||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][3]));
|
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][3]));
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.AddBone(std::move(bone));
|
out.m_bones.emplace_back(std::move(bone));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddXModelMaterials(AbstractXModelWriter& writer, DistinctMapper<Material*>& materialMapper, const XModel* model)
|
void AddXModelMaterials(XModelCommon& out, DistinctMapper<Material*>& materialMapper, const XModel* model)
|
||||||
{
|
{
|
||||||
for (auto surfaceMaterialNum = 0; surfaceMaterialNum < model->numsurfs; surfaceMaterialNum++)
|
for (auto surfaceMaterialNum = 0; surfaceMaterialNum < model->numsurfs; surfaceMaterialNum++)
|
||||||
{
|
{
|
||||||
@ -313,27 +313,24 @@ namespace
|
|||||||
if (colorMap)
|
if (colorMap)
|
||||||
xMaterial.colorMapName = std::string(colorMap->name);
|
xMaterial.colorMapName = std::string(colorMap->name);
|
||||||
|
|
||||||
writer.AddMaterial(std::move(xMaterial));
|
out.m_materials.emplace_back(std::move(xMaterial));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddXModelObjects(AbstractXModelWriter& writer,
|
void AddXModelObjects(XModelCommon& out, const XModelSurfs* modelSurfs, const DistinctMapper<Material*>& materialMapper, const int baseSurfaceIndex)
|
||||||
const XModelSurfs* modelSurfs,
|
|
||||||
const DistinctMapper<Material*>& materialMapper,
|
|
||||||
const int baseSurfaceIndex)
|
|
||||||
{
|
{
|
||||||
for (auto surfIndex = 0u; surfIndex < modelSurfs->numsurfs; surfIndex++)
|
for (auto surfIndex = 0u; surfIndex < modelSurfs->numsurfs; surfIndex++)
|
||||||
{
|
{
|
||||||
XModelObject object;
|
XModelObject object;
|
||||||
object.name = "surf" + std::to_string(surfIndex);
|
object.name = std::format("surf{}", surfIndex);
|
||||||
object.materialIndex = static_cast<int>(materialMapper.GetDistinctPositionByInputPosition(surfIndex + baseSurfaceIndex));
|
object.materialIndex = static_cast<int>(materialMapper.GetDistinctPositionByInputPosition(surfIndex + baseSurfaceIndex));
|
||||||
|
|
||||||
writer.AddObject(std::move(object));
|
out.m_objects.emplace_back(std::move(object));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddXModelVertices(AbstractXModelWriter& writer, const XModelSurfs* modelSurfs)
|
void AddXModelVertices(XModelCommon& out, const XModelSurfs* modelSurfs)
|
||||||
{
|
{
|
||||||
for (auto surfIndex = 0u; surfIndex < modelSurfs->numsurfs; surfIndex++)
|
for (auto surfIndex = 0u; surfIndex < modelSurfs->numsurfs; surfIndex++)
|
||||||
{
|
{
|
||||||
@ -364,36 +361,36 @@ namespace
|
|||||||
vertex.uv[0] = uv[0];
|
vertex.uv[0] = uv[0];
|
||||||
vertex.uv[1] = uv[1];
|
vertex.uv[1] = uv[1];
|
||||||
|
|
||||||
writer.AddVertex(vertex);
|
out.m_vertices.emplace_back(vertex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AllocateXModelBoneWeights(const XModelSurfs* modelSurfs, XModelVertexBoneWeightCollection& weightCollection)
|
void AllocateXModelBoneWeights(const XModelSurfs* modelSurfs, XModelVertexBoneWeightCollection& weightCollection)
|
||||||
{
|
{
|
||||||
weightCollection.totalWeightCount = 0u;
|
auto totalWeightCount = 0u;
|
||||||
for (auto surfIndex = 0u; surfIndex < modelSurfs->numsurfs; surfIndex++)
|
for (auto surfIndex = 0u; surfIndex < modelSurfs->numsurfs; surfIndex++)
|
||||||
{
|
{
|
||||||
const auto& surface = modelSurfs->surfs[surfIndex];
|
const auto& surface = modelSurfs->surfs[surfIndex];
|
||||||
|
|
||||||
if (surface.vertList)
|
if (surface.vertList)
|
||||||
{
|
{
|
||||||
weightCollection.totalWeightCount += surface.vertListCount;
|
totalWeightCount += surface.vertListCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (surface.vertInfo.vertsBlend)
|
if (surface.vertInfo.vertsBlend)
|
||||||
{
|
{
|
||||||
weightCollection.totalWeightCount += surface.vertInfo.vertCount[0] * 1;
|
totalWeightCount += surface.vertInfo.vertCount[0] * 1;
|
||||||
weightCollection.totalWeightCount += surface.vertInfo.vertCount[1] * 2;
|
totalWeightCount += surface.vertInfo.vertCount[1] * 2;
|
||||||
weightCollection.totalWeightCount += surface.vertInfo.vertCount[2] * 3;
|
totalWeightCount += surface.vertInfo.vertCount[2] * 3;
|
||||||
weightCollection.totalWeightCount += surface.vertInfo.vertCount[3] * 4;
|
totalWeightCount += surface.vertInfo.vertCount[3] * 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
weightCollection.weights = std::make_unique<XModelBoneWeight[]>(weightCollection.totalWeightCount);
|
weightCollection.weights.resize(totalWeightCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddXModelVertexBoneWeights(AbstractXModelWriter& writer, const XModelSurfs* modelSurfs, XModelVertexBoneWeightCollection& weightCollection)
|
void AddXModelVertexBoneWeights(XModelCommon& out, const XModelSurfs* modelSurfs, XModelVertexBoneWeightCollection& weightCollection)
|
||||||
{
|
{
|
||||||
size_t weightOffset = 0u;
|
size_t weightOffset = 0u;
|
||||||
|
|
||||||
@ -413,7 +410,7 @@ namespace
|
|||||||
|
|
||||||
for (auto vertListVertexOffset = 0u; vertListVertexOffset < vertList.vertCount; vertListVertexOffset++)
|
for (auto vertListVertexOffset = 0u; vertListVertexOffset < vertList.vertCount; vertListVertexOffset++)
|
||||||
{
|
{
|
||||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{boneWeightOffset, 1});
|
out.m_vertex_bone_weights.emplace_back(boneWeightOffset, 1);
|
||||||
}
|
}
|
||||||
handledVertices += vertList.vertCount;
|
handledVertices += vertList.vertCount;
|
||||||
}
|
}
|
||||||
@ -431,7 +428,7 @@ namespace
|
|||||||
|
|
||||||
vertsBlendOffset += 1;
|
vertsBlendOffset += 1;
|
||||||
|
|
||||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{boneWeightOffset, 1});
|
out.m_vertex_bone_weights.emplace_back(boneWeightOffset, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2 bone weights
|
// 2 bone weights
|
||||||
@ -448,7 +445,7 @@ namespace
|
|||||||
|
|
||||||
vertsBlendOffset += 3;
|
vertsBlendOffset += 3;
|
||||||
|
|
||||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{boneWeightOffset, 2});
|
out.m_vertex_bone_weights.emplace_back(boneWeightOffset, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3 bone weights
|
// 3 bone weights
|
||||||
@ -468,7 +465,7 @@ namespace
|
|||||||
|
|
||||||
vertsBlendOffset += 5;
|
vertsBlendOffset += 5;
|
||||||
|
|
||||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{boneWeightOffset, 3});
|
out.m_vertex_bone_weights.emplace_back(boneWeightOffset, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4 bone weights
|
// 4 bone weights
|
||||||
@ -491,7 +488,7 @@ namespace
|
|||||||
|
|
||||||
vertsBlendOffset += 7;
|
vertsBlendOffset += 7;
|
||||||
|
|
||||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{boneWeightOffset, 4});
|
out.m_vertex_bone_weights.emplace_back(boneWeightOffset, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
handledVertices +=
|
handledVertices +=
|
||||||
@ -500,12 +497,12 @@ namespace
|
|||||||
|
|
||||||
for (; handledVertices < surface.vertCount; handledVertices++)
|
for (; handledVertices < surface.vertCount; handledVertices++)
|
||||||
{
|
{
|
||||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{nullptr, 0});
|
out.m_vertex_bone_weights.emplace_back(nullptr, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddXModelFaces(AbstractXModelWriter& writer, const XModelSurfs* modelSurfs)
|
void AddXModelFaces(XModelCommon& out, const XModelSurfs* modelSurfs)
|
||||||
{
|
{
|
||||||
for (auto surfIndex = 0u; surfIndex < modelSurfs->numsurfs; surfIndex++)
|
for (auto surfIndex = 0u; surfIndex < modelSurfs->numsurfs; surfIndex++)
|
||||||
{
|
{
|
||||||
@ -519,12 +516,12 @@ namespace
|
|||||||
face.vertexIndex[1] = tri[1] + surface.baseVertIndex;
|
face.vertexIndex[1] = tri[1] + surface.baseVertIndex;
|
||||||
face.vertexIndex[2] = tri[2] + surface.baseVertIndex;
|
face.vertexIndex[2] = tri[2] + surface.baseVertIndex;
|
||||||
face.objectIndex = static_cast<int>(surfIndex);
|
face.objectIndex = static_cast<int>(surfIndex);
|
||||||
writer.AddFace(face);
|
out.m_faces.emplace_back(face);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PopulateXModelWriter(const AssetDumpingContext& context, const unsigned lod, const XModel* model, AbstractXModelWriter& writer)
|
void PopulateXModelWriter(XModelCommon& out, const AssetDumpingContext& context, const unsigned lod, const XModel* model)
|
||||||
{
|
{
|
||||||
const auto* modelSurfs = model->lodInfo[lod].modelSurfs;
|
const auto* modelSurfs = model->lodInfo[lod].modelSurfs;
|
||||||
|
|
||||||
@ -532,15 +529,15 @@ namespace
|
|||||||
XModelVertexBoneWeightCollection boneWeightCollection;
|
XModelVertexBoneWeightCollection boneWeightCollection;
|
||||||
AllocateXModelBoneWeights(modelSurfs, boneWeightCollection);
|
AllocateXModelBoneWeights(modelSurfs, boneWeightCollection);
|
||||||
|
|
||||||
AddXModelBones(context, writer, model);
|
AddXModelBones(out, context, model);
|
||||||
AddXModelMaterials(writer, materialMapper, model);
|
AddXModelMaterials(out, materialMapper, model);
|
||||||
AddXModelObjects(writer, modelSurfs, materialMapper, model->lodInfo[lod].surfIndex);
|
AddXModelObjects(out, modelSurfs, materialMapper, model->lodInfo[lod].surfIndex);
|
||||||
AddXModelVertices(writer, modelSurfs);
|
AddXModelVertices(out, modelSurfs);
|
||||||
AddXModelVertexBoneWeights(writer, modelSurfs, boneWeightCollection);
|
AddXModelVertexBoneWeights(out, modelSurfs, boneWeightCollection);
|
||||||
AddXModelFaces(writer, modelSurfs);
|
AddXModelFaces(out, modelSurfs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DumpXModelExportLod(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset, const unsigned lod)
|
void DumpXModelExportLod(const XModelCommon& common, const AssetDumpingContext& context, const XAssetInfo<XModel>* asset, const unsigned lod)
|
||||||
{
|
{
|
||||||
const auto* model = asset->Asset();
|
const auto* model = asset->Asset();
|
||||||
const auto* modelSurfs = model->lodInfo[lod].modelSurfs;
|
const auto* modelSurfs = model->lodInfo[lod].modelSurfs;
|
||||||
@ -549,13 +546,13 @@ namespace
|
|||||||
if (!assetFile)
|
if (!assetFile)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto writer = XModelExportWriter::CreateWriterForVersion6(context.m_zone->m_game->GetShortName(), context.m_zone->m_name);
|
const auto writer = xmodel_export::CreateWriterForVersion6(*assetFile, context.m_zone->m_game->GetShortName(), context.m_zone->m_name);
|
||||||
PopulateXModelWriter(context, lod, model, *writer);
|
writer->Write(common);
|
||||||
|
|
||||||
writer->Write(*assetFile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> void DumpGltfLod(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset, const unsigned lod, const std::string& extension)
|
template<typename T>
|
||||||
|
void DumpGltfLod(
|
||||||
|
const XModelCommon& common, const AssetDumpingContext& context, const XAssetInfo<XModel>* asset, const unsigned lod, const std::string& extension)
|
||||||
{
|
{
|
||||||
const auto* model = asset->Asset();
|
const auto* model = asset->Asset();
|
||||||
const auto* modelSurfs = model->lodInfo[lod].modelSurfs;
|
const auto* modelSurfs = model->lodInfo[lod].modelSurfs;
|
||||||
@ -566,9 +563,8 @@ namespace
|
|||||||
|
|
||||||
const auto output = std::make_unique<T>(*assetFile);
|
const auto output = std::make_unique<T>(*assetFile);
|
||||||
const auto writer = gltf::Writer::CreateWriter(output.get(), context.m_zone->m_game->GetShortName(), context.m_zone->m_name);
|
const auto writer = gltf::Writer::CreateWriter(output.get(), context.m_zone->m_game->GetShortName(), context.m_zone->m_name);
|
||||||
PopulateXModelWriter(context, lod, model, *writer);
|
|
||||||
|
|
||||||
writer->Write(*assetFile);
|
writer->Write(common);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DumpXModelSurfs(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset)
|
void DumpXModelSurfs(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset)
|
||||||
@ -580,6 +576,9 @@ namespace
|
|||||||
|
|
||||||
for (auto currentLod = 0u; currentLod < model->numLods; currentLod++)
|
for (auto currentLod = 0u; currentLod < model->numLods; currentLod++)
|
||||||
{
|
{
|
||||||
|
XModelCommon common;
|
||||||
|
PopulateXModelWriter(common, context, currentLod, asset->Asset());
|
||||||
|
|
||||||
switch (ObjWriting::Configuration.ModelOutputFormat)
|
switch (ObjWriting::Configuration.ModelOutputFormat)
|
||||||
{
|
{
|
||||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::OBJ:
|
case ObjWriting::Configuration_t::ModelOutputFormat_e::OBJ:
|
||||||
@ -587,15 +586,15 @@ namespace
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::XMODEL_EXPORT:
|
case ObjWriting::Configuration_t::ModelOutputFormat_e::XMODEL_EXPORT:
|
||||||
DumpXModelExportLod(context, asset, currentLod);
|
DumpXModelExportLod(common, context, asset, currentLod);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::GLTF:
|
case ObjWriting::Configuration_t::ModelOutputFormat_e::GLTF:
|
||||||
DumpGltfLod<gltf::TextOutput>(context, asset, currentLod, ".gltf");
|
DumpGltfLod<gltf::TextOutput>(common, context, asset, currentLod, ".gltf");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::GLB:
|
case ObjWriting::Configuration_t::ModelOutputFormat_e::GLB:
|
||||||
DumpGltfLod<gltf::BinOutput>(context, asset, currentLod, ".glb");
|
DumpGltfLod<gltf::BinOutput>(common, context, asset, currentLod, ".glb");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -6,12 +6,12 @@
|
|||||||
#include "Utils/DistinctMapper.h"
|
#include "Utils/DistinctMapper.h"
|
||||||
#include "Utils/HalfFloat.h"
|
#include "Utils/HalfFloat.h"
|
||||||
#include "Utils/QuatInt16.h"
|
#include "Utils/QuatInt16.h"
|
||||||
#include "XModel/AbstractXModelWriter.h"
|
|
||||||
#include "XModel/Export/XModelExportWriter.h"
|
#include "XModel/Export/XModelExportWriter.h"
|
||||||
#include "XModel/Gltf/GltfBinOutput.h"
|
#include "XModel/Gltf/GltfBinOutput.h"
|
||||||
#include "XModel/Gltf/GltfTextOutput.h"
|
#include "XModel/Gltf/GltfTextOutput.h"
|
||||||
#include "XModel/Gltf/GltfWriter.h"
|
#include "XModel/Gltf/GltfWriter.h"
|
||||||
#include "XModel/Obj/ObjWriter.h"
|
#include "XModel/Obj/ObjWriter.h"
|
||||||
|
#include "XModel/XModelWriter.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <format>
|
#include <format>
|
||||||
@ -146,7 +146,7 @@ namespace
|
|||||||
for (auto surfIndex = 0u; surfIndex < modelSurfs->numsurfs; surfIndex++)
|
for (auto surfIndex = 0u; surfIndex < modelSurfs->numsurfs; surfIndex++)
|
||||||
{
|
{
|
||||||
ObjObject object;
|
ObjObject object;
|
||||||
object.name = "surf" + std::to_string(surfIndex);
|
object.name = std::format("surf{}", surfIndex);
|
||||||
object.materialIndex = static_cast<int>(materialMapper.GetDistinctPositionByInputPosition(surfIndex + baseSurfaceIndex));
|
object.materialIndex = static_cast<int>(materialMapper.GetDistinctPositionByInputPosition(surfIndex + baseSurfaceIndex));
|
||||||
|
|
||||||
writer.AddObject(std::move(object));
|
writer.AddObject(std::move(object));
|
||||||
@ -250,7 +250,7 @@ namespace
|
|||||||
writer.WriteObj(*assetFile, std::format("{}.mtl", model->name));
|
writer.WriteObj(*assetFile, std::format("{}.mtl", model->name));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddXModelBones(const AssetDumpingContext& context, AbstractXModelWriter& writer, const XModel* model)
|
void AddXModelBones(XModelCommon& out, const AssetDumpingContext& context, const XModel* model)
|
||||||
{
|
{
|
||||||
for (auto boneNum = 0u; boneNum < model->numBones; boneNum++)
|
for (auto boneNum = 0u; boneNum < model->numBones; boneNum++)
|
||||||
{
|
{
|
||||||
@ -293,11 +293,11 @@ namespace
|
|||||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][3]));
|
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][3]));
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.AddBone(std::move(bone));
|
out.m_bones.emplace_back(std::move(bone));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddXModelMaterials(AbstractXModelWriter& writer, DistinctMapper<Material*>& materialMapper, const XModel* model)
|
void AddXModelMaterials(XModelCommon& out, DistinctMapper<Material*>& materialMapper, const XModel* model)
|
||||||
{
|
{
|
||||||
for (auto surfaceMaterialNum = 0; surfaceMaterialNum < model->numsurfs; surfaceMaterialNum++)
|
for (auto surfaceMaterialNum = 0; surfaceMaterialNum < model->numsurfs; surfaceMaterialNum++)
|
||||||
{
|
{
|
||||||
@ -312,27 +312,24 @@ namespace
|
|||||||
if (colorMap)
|
if (colorMap)
|
||||||
xMaterial.colorMapName = std::string(colorMap->name);
|
xMaterial.colorMapName = std::string(colorMap->name);
|
||||||
|
|
||||||
writer.AddMaterial(std::move(xMaterial));
|
out.m_materials.emplace_back(std::move(xMaterial));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddXModelObjects(AbstractXModelWriter& writer,
|
void AddXModelObjects(XModelCommon& out, const XModelSurfs* modelSurfs, const DistinctMapper<Material*>& materialMapper, const int baseSurfaceIndex)
|
||||||
const XModelSurfs* modelSurfs,
|
|
||||||
const DistinctMapper<Material*>& materialMapper,
|
|
||||||
const int baseSurfaceIndex)
|
|
||||||
{
|
{
|
||||||
for (auto surfIndex = 0u; surfIndex < modelSurfs->numsurfs; surfIndex++)
|
for (auto surfIndex = 0u; surfIndex < modelSurfs->numsurfs; surfIndex++)
|
||||||
{
|
{
|
||||||
XModelObject object;
|
XModelObject object;
|
||||||
object.name = "surf" + std::to_string(surfIndex);
|
object.name = std::format("surf{}", surfIndex);
|
||||||
object.materialIndex = static_cast<int>(materialMapper.GetDistinctPositionByInputPosition(surfIndex + baseSurfaceIndex));
|
object.materialIndex = static_cast<int>(materialMapper.GetDistinctPositionByInputPosition(surfIndex + baseSurfaceIndex));
|
||||||
|
|
||||||
writer.AddObject(std::move(object));
|
out.m_objects.emplace_back(std::move(object));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddXModelVertices(AbstractXModelWriter& writer, const XModelSurfs* modelSurfs)
|
void AddXModelVertices(XModelCommon& out, const XModelSurfs* modelSurfs)
|
||||||
{
|
{
|
||||||
for (auto surfIndex = 0u; surfIndex < modelSurfs->numsurfs; surfIndex++)
|
for (auto surfIndex = 0u; surfIndex < modelSurfs->numsurfs; surfIndex++)
|
||||||
{
|
{
|
||||||
@ -363,36 +360,36 @@ namespace
|
|||||||
vertex.uv[0] = uv[0];
|
vertex.uv[0] = uv[0];
|
||||||
vertex.uv[1] = uv[1];
|
vertex.uv[1] = uv[1];
|
||||||
|
|
||||||
writer.AddVertex(vertex);
|
out.m_vertices.emplace_back(vertex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AllocateXModelBoneWeights(const XModelSurfs* modelSurfs, XModelVertexBoneWeightCollection& weightCollection)
|
void AllocateXModelBoneWeights(const XModelSurfs* modelSurfs, XModelVertexBoneWeightCollection& weightCollection)
|
||||||
{
|
{
|
||||||
weightCollection.totalWeightCount = 0u;
|
auto totalWeightCount = 0u;
|
||||||
for (auto surfIndex = 0u; surfIndex < modelSurfs->numsurfs; surfIndex++)
|
for (auto surfIndex = 0u; surfIndex < modelSurfs->numsurfs; surfIndex++)
|
||||||
{
|
{
|
||||||
const auto& surface = modelSurfs->surfs[surfIndex];
|
const auto& surface = modelSurfs->surfs[surfIndex];
|
||||||
|
|
||||||
if (surface.vertList)
|
if (surface.vertList)
|
||||||
{
|
{
|
||||||
weightCollection.totalWeightCount += surface.vertListCount;
|
totalWeightCount += surface.vertListCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (surface.vertInfo.vertsBlend)
|
if (surface.vertInfo.vertsBlend)
|
||||||
{
|
{
|
||||||
weightCollection.totalWeightCount += surface.vertInfo.vertCount[0] * 1;
|
totalWeightCount += surface.vertInfo.vertCount[0] * 1;
|
||||||
weightCollection.totalWeightCount += surface.vertInfo.vertCount[1] * 2;
|
totalWeightCount += surface.vertInfo.vertCount[1] * 2;
|
||||||
weightCollection.totalWeightCount += surface.vertInfo.vertCount[2] * 3;
|
totalWeightCount += surface.vertInfo.vertCount[2] * 3;
|
||||||
weightCollection.totalWeightCount += surface.vertInfo.vertCount[3] * 4;
|
totalWeightCount += surface.vertInfo.vertCount[3] * 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
weightCollection.weights = std::make_unique<XModelBoneWeight[]>(weightCollection.totalWeightCount);
|
weightCollection.weights.resize(totalWeightCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddXModelVertexBoneWeights(AbstractXModelWriter& writer, const XModelSurfs* modelSurfs, XModelVertexBoneWeightCollection& weightCollection)
|
void AddXModelVertexBoneWeights(XModelCommon& out, const XModelSurfs* modelSurfs, XModelVertexBoneWeightCollection& weightCollection)
|
||||||
{
|
{
|
||||||
size_t weightOffset = 0u;
|
size_t weightOffset = 0u;
|
||||||
|
|
||||||
@ -412,7 +409,7 @@ namespace
|
|||||||
|
|
||||||
for (auto vertListVertexOffset = 0u; vertListVertexOffset < vertList.vertCount; vertListVertexOffset++)
|
for (auto vertListVertexOffset = 0u; vertListVertexOffset < vertList.vertCount; vertListVertexOffset++)
|
||||||
{
|
{
|
||||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{boneWeightOffset, 1});
|
out.m_vertex_bone_weights.emplace_back(boneWeightOffset, 1);
|
||||||
}
|
}
|
||||||
handledVertices += vertList.vertCount;
|
handledVertices += vertList.vertCount;
|
||||||
}
|
}
|
||||||
@ -430,7 +427,7 @@ namespace
|
|||||||
|
|
||||||
vertsBlendOffset += 1;
|
vertsBlendOffset += 1;
|
||||||
|
|
||||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{boneWeightOffset, 1});
|
out.m_vertex_bone_weights.emplace_back(boneWeightOffset, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2 bone weights
|
// 2 bone weights
|
||||||
@ -447,7 +444,7 @@ namespace
|
|||||||
|
|
||||||
vertsBlendOffset += 3;
|
vertsBlendOffset += 3;
|
||||||
|
|
||||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{boneWeightOffset, 2});
|
out.m_vertex_bone_weights.emplace_back(boneWeightOffset, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3 bone weights
|
// 3 bone weights
|
||||||
@ -467,7 +464,7 @@ namespace
|
|||||||
|
|
||||||
vertsBlendOffset += 5;
|
vertsBlendOffset += 5;
|
||||||
|
|
||||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{boneWeightOffset, 3});
|
out.m_vertex_bone_weights.emplace_back(boneWeightOffset, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4 bone weights
|
// 4 bone weights
|
||||||
@ -490,7 +487,7 @@ namespace
|
|||||||
|
|
||||||
vertsBlendOffset += 7;
|
vertsBlendOffset += 7;
|
||||||
|
|
||||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{boneWeightOffset, 4});
|
out.m_vertex_bone_weights.emplace_back(boneWeightOffset, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
handledVertices +=
|
handledVertices +=
|
||||||
@ -499,12 +496,12 @@ namespace
|
|||||||
|
|
||||||
for (; handledVertices < surface.vertCount; handledVertices++)
|
for (; handledVertices < surface.vertCount; handledVertices++)
|
||||||
{
|
{
|
||||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{nullptr, 0});
|
out.m_vertex_bone_weights.emplace_back(nullptr, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddXModelFaces(AbstractXModelWriter& writer, const XModelSurfs* modelSurfs)
|
void AddXModelFaces(XModelCommon& out, const XModelSurfs* modelSurfs)
|
||||||
{
|
{
|
||||||
for (auto surfIndex = 0u; surfIndex < modelSurfs->numsurfs; surfIndex++)
|
for (auto surfIndex = 0u; surfIndex < modelSurfs->numsurfs; surfIndex++)
|
||||||
{
|
{
|
||||||
@ -518,12 +515,12 @@ namespace
|
|||||||
face.vertexIndex[1] = tri[1] + surface.baseVertIndex;
|
face.vertexIndex[1] = tri[1] + surface.baseVertIndex;
|
||||||
face.vertexIndex[2] = tri[2] + surface.baseVertIndex;
|
face.vertexIndex[2] = tri[2] + surface.baseVertIndex;
|
||||||
face.objectIndex = static_cast<int>(surfIndex);
|
face.objectIndex = static_cast<int>(surfIndex);
|
||||||
writer.AddFace(face);
|
out.m_faces.emplace_back(face);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PopulateXModelWriter(const AssetDumpingContext& context, const unsigned lod, const XModel* model, AbstractXModelWriter& writer)
|
void PopulateXModelWriter(XModelCommon& out, const AssetDumpingContext& context, const unsigned lod, const XModel* model)
|
||||||
{
|
{
|
||||||
const auto* modelSurfs = model->lodInfo[lod].modelSurfs;
|
const auto* modelSurfs = model->lodInfo[lod].modelSurfs;
|
||||||
|
|
||||||
@ -531,15 +528,15 @@ namespace
|
|||||||
XModelVertexBoneWeightCollection boneWeightCollection;
|
XModelVertexBoneWeightCollection boneWeightCollection;
|
||||||
AllocateXModelBoneWeights(modelSurfs, boneWeightCollection);
|
AllocateXModelBoneWeights(modelSurfs, boneWeightCollection);
|
||||||
|
|
||||||
AddXModelBones(context, writer, model);
|
AddXModelBones(out, context, model);
|
||||||
AddXModelMaterials(writer, materialMapper, model);
|
AddXModelMaterials(out, materialMapper, model);
|
||||||
AddXModelObjects(writer, modelSurfs, materialMapper, model->lodInfo[lod].surfIndex);
|
AddXModelObjects(out, modelSurfs, materialMapper, model->lodInfo[lod].surfIndex);
|
||||||
AddXModelVertices(writer, modelSurfs);
|
AddXModelVertices(out, modelSurfs);
|
||||||
AddXModelVertexBoneWeights(writer, modelSurfs, boneWeightCollection);
|
AddXModelVertexBoneWeights(out, modelSurfs, boneWeightCollection);
|
||||||
AddXModelFaces(writer, modelSurfs);
|
AddXModelFaces(out, modelSurfs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DumpXModelExportLod(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset, const unsigned lod)
|
void DumpXModelExportLod(const XModelCommon& common, const AssetDumpingContext& context, const XAssetInfo<XModel>* asset, const unsigned lod)
|
||||||
{
|
{
|
||||||
const auto* model = asset->Asset();
|
const auto* model = asset->Asset();
|
||||||
const auto* modelSurfs = model->lodInfo[lod].modelSurfs;
|
const auto* modelSurfs = model->lodInfo[lod].modelSurfs;
|
||||||
@ -548,13 +545,13 @@ namespace
|
|||||||
if (!assetFile)
|
if (!assetFile)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto writer = XModelExportWriter::CreateWriterForVersion6(context.m_zone->m_game->GetShortName(), context.m_zone->m_name);
|
const auto writer = xmodel_export::CreateWriterForVersion6(*assetFile, context.m_zone->m_game->GetShortName(), context.m_zone->m_name);
|
||||||
PopulateXModelWriter(context, lod, model, *writer);
|
writer->Write(common);
|
||||||
|
|
||||||
writer->Write(*assetFile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> void DumpGltfLod(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset, const unsigned lod, const std::string& extension)
|
template<typename T>
|
||||||
|
void DumpGltfLod(
|
||||||
|
const XModelCommon& common, const AssetDumpingContext& context, const XAssetInfo<XModel>* asset, const unsigned lod, const std::string& extension)
|
||||||
{
|
{
|
||||||
const auto* model = asset->Asset();
|
const auto* model = asset->Asset();
|
||||||
const auto* modelSurfs = model->lodInfo[lod].modelSurfs;
|
const auto* modelSurfs = model->lodInfo[lod].modelSurfs;
|
||||||
@ -565,9 +562,8 @@ namespace
|
|||||||
|
|
||||||
const auto output = std::make_unique<T>(*assetFile);
|
const auto output = std::make_unique<T>(*assetFile);
|
||||||
const auto writer = gltf::Writer::CreateWriter(output.get(), context.m_zone->m_game->GetShortName(), context.m_zone->m_name);
|
const auto writer = gltf::Writer::CreateWriter(output.get(), context.m_zone->m_game->GetShortName(), context.m_zone->m_name);
|
||||||
PopulateXModelWriter(context, lod, model, *writer);
|
|
||||||
|
|
||||||
writer->Write(*assetFile);
|
writer->Write(common);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DumpXModelSurfs(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset)
|
void DumpXModelSurfs(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset)
|
||||||
@ -579,6 +575,9 @@ namespace
|
|||||||
|
|
||||||
for (auto currentLod = 0u; currentLod < model->numLods; currentLod++)
|
for (auto currentLod = 0u; currentLod < model->numLods; currentLod++)
|
||||||
{
|
{
|
||||||
|
XModelCommon common;
|
||||||
|
PopulateXModelWriter(common, context, currentLod, asset->Asset());
|
||||||
|
|
||||||
switch (ObjWriting::Configuration.ModelOutputFormat)
|
switch (ObjWriting::Configuration.ModelOutputFormat)
|
||||||
{
|
{
|
||||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::OBJ:
|
case ObjWriting::Configuration_t::ModelOutputFormat_e::OBJ:
|
||||||
@ -586,15 +585,15 @@ namespace
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::XMODEL_EXPORT:
|
case ObjWriting::Configuration_t::ModelOutputFormat_e::XMODEL_EXPORT:
|
||||||
DumpXModelExportLod(context, asset, currentLod);
|
DumpXModelExportLod(common, context, asset, currentLod);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::GLTF:
|
case ObjWriting::Configuration_t::ModelOutputFormat_e::GLTF:
|
||||||
DumpGltfLod<gltf::TextOutput>(context, asset, currentLod, ".gltf");
|
DumpGltfLod<gltf::TextOutput>(common, context, asset, currentLod, ".gltf");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::GLB:
|
case ObjWriting::Configuration_t::ModelOutputFormat_e::GLB:
|
||||||
DumpGltfLod<gltf::BinOutput>(context, asset, currentLod, ".glb");
|
DumpGltfLod<gltf::BinOutput>(common, context, asset, currentLod, ".glb");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -6,12 +6,12 @@
|
|||||||
#include "Utils/DistinctMapper.h"
|
#include "Utils/DistinctMapper.h"
|
||||||
#include "Utils/HalfFloat.h"
|
#include "Utils/HalfFloat.h"
|
||||||
#include "Utils/QuatInt16.h"
|
#include "Utils/QuatInt16.h"
|
||||||
#include "XModel/AbstractXModelWriter.h"
|
|
||||||
#include "XModel/Export/XModelExportWriter.h"
|
#include "XModel/Export/XModelExportWriter.h"
|
||||||
#include "XModel/Gltf/GltfBinOutput.h"
|
#include "XModel/Gltf/GltfBinOutput.h"
|
||||||
#include "XModel/Gltf/GltfTextOutput.h"
|
#include "XModel/Gltf/GltfTextOutput.h"
|
||||||
#include "XModel/Gltf/GltfWriter.h"
|
#include "XModel/Gltf/GltfWriter.h"
|
||||||
#include "XModel/Obj/ObjWriter.h"
|
#include "XModel/Obj/ObjWriter.h"
|
||||||
|
#include "XModel/XModelWriter.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <format>
|
#include <format>
|
||||||
@ -140,7 +140,7 @@ namespace
|
|||||||
for (auto surfIndex = 0u; surfIndex < surfCount; surfIndex++)
|
for (auto surfIndex = 0u; surfIndex < surfCount; surfIndex++)
|
||||||
{
|
{
|
||||||
ObjObject object;
|
ObjObject object;
|
||||||
object.name = "surf" + std::to_string(surfIndex);
|
object.name = std::format("surf{}", surfIndex);
|
||||||
object.materialIndex = static_cast<int>(materialMapper.GetDistinctPositionByInputPosition(surfIndex + baseSurfIndex));
|
object.materialIndex = static_cast<int>(materialMapper.GetDistinctPositionByInputPosition(surfIndex + baseSurfIndex));
|
||||||
|
|
||||||
writer.AddObject(std::move(object));
|
writer.AddObject(std::move(object));
|
||||||
@ -245,7 +245,7 @@ namespace
|
|||||||
writer.WriteObj(*assetFile, std::format("{}.mtl", model->name));
|
writer.WriteObj(*assetFile, std::format("{}.mtl", model->name));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddXModelBones(const AssetDumpingContext& context, AbstractXModelWriter& writer, const XModel* model)
|
void AddXModelBones(XModelCommon& out, const AssetDumpingContext& context, const XModel* model)
|
||||||
{
|
{
|
||||||
for (auto boneNum = 0u; boneNum < model->numBones; boneNum++)
|
for (auto boneNum = 0u; boneNum < model->numBones; boneNum++)
|
||||||
{
|
{
|
||||||
@ -288,11 +288,11 @@ namespace
|
|||||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][3]));
|
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][3]));
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.AddBone(std::move(bone));
|
out.m_bones.emplace_back(std::move(bone));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddXModelMaterials(AbstractXModelWriter& writer, DistinctMapper<Material*>& materialMapper, const XModel* model)
|
void AddXModelMaterials(XModelCommon& out, DistinctMapper<Material*>& materialMapper, const XModel* model)
|
||||||
{
|
{
|
||||||
for (auto surfaceMaterialNum = 0; surfaceMaterialNum < model->numsurfs; surfaceMaterialNum++)
|
for (auto surfaceMaterialNum = 0; surfaceMaterialNum < model->numsurfs; surfaceMaterialNum++)
|
||||||
{
|
{
|
||||||
@ -307,12 +307,12 @@ namespace
|
|||||||
if (colorMap)
|
if (colorMap)
|
||||||
xMaterial.colorMapName = std::string(colorMap->name);
|
xMaterial.colorMapName = std::string(colorMap->name);
|
||||||
|
|
||||||
writer.AddMaterial(std::move(xMaterial));
|
out.m_materials.emplace_back(std::move(xMaterial));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddXModelObjects(AbstractXModelWriter& writer, const XModel* model, const unsigned lod, const DistinctMapper<Material*>& materialMapper)
|
void AddXModelObjects(XModelCommon& out, const XModel* model, const unsigned lod, const DistinctMapper<Material*>& materialMapper)
|
||||||
{
|
{
|
||||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||||
const auto baseSurfaceIndex = model->lodInfo[lod].surfIndex;
|
const auto baseSurfaceIndex = model->lodInfo[lod].surfIndex;
|
||||||
@ -320,14 +320,14 @@ namespace
|
|||||||
for (auto surfIndex = 0u; surfIndex < surfCount; surfIndex++)
|
for (auto surfIndex = 0u; surfIndex < surfCount; surfIndex++)
|
||||||
{
|
{
|
||||||
XModelObject object;
|
XModelObject object;
|
||||||
object.name = "surf" + std::to_string(surfIndex);
|
object.name = std::format("surf{}", surfIndex);
|
||||||
object.materialIndex = static_cast<int>(materialMapper.GetDistinctPositionByInputPosition(surfIndex + baseSurfaceIndex));
|
object.materialIndex = static_cast<int>(materialMapper.GetDistinctPositionByInputPosition(surfIndex + baseSurfaceIndex));
|
||||||
|
|
||||||
writer.AddObject(std::move(object));
|
out.m_objects.emplace_back(std::move(object));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddXModelVertices(AbstractXModelWriter& writer, const XModel* model, const unsigned lod)
|
void AddXModelVertices(XModelCommon& out, const XModel* model, const unsigned lod)
|
||||||
{
|
{
|
||||||
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
||||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||||
@ -361,7 +361,7 @@ namespace
|
|||||||
vertex.uv[0] = uv[0];
|
vertex.uv[0] = uv[0];
|
||||||
vertex.uv[1] = uv[1];
|
vertex.uv[1] = uv[1];
|
||||||
|
|
||||||
writer.AddVertex(vertex);
|
out.m_vertices.emplace_back(vertex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -371,29 +371,29 @@ namespace
|
|||||||
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
||||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||||
|
|
||||||
weightCollection.totalWeightCount = 0u;
|
auto totalWeightCount = 0u;
|
||||||
for (auto surfIndex = 0u; surfIndex < surfCount; surfIndex++)
|
for (auto surfIndex = 0u; surfIndex < surfCount; surfIndex++)
|
||||||
{
|
{
|
||||||
const auto& surface = surfs[surfIndex];
|
const auto& surface = surfs[surfIndex];
|
||||||
|
|
||||||
if (surface.vertList)
|
if (surface.vertList)
|
||||||
{
|
{
|
||||||
weightCollection.totalWeightCount += surface.vertListCount;
|
totalWeightCount += surface.vertListCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (surface.vertInfo.vertsBlend)
|
if (surface.vertInfo.vertsBlend)
|
||||||
{
|
{
|
||||||
weightCollection.totalWeightCount += surface.vertInfo.vertCount[0] * 1;
|
totalWeightCount += surface.vertInfo.vertCount[0] * 1;
|
||||||
weightCollection.totalWeightCount += surface.vertInfo.vertCount[1] * 2;
|
totalWeightCount += surface.vertInfo.vertCount[1] * 2;
|
||||||
weightCollection.totalWeightCount += surface.vertInfo.vertCount[2] * 3;
|
totalWeightCount += surface.vertInfo.vertCount[2] * 3;
|
||||||
weightCollection.totalWeightCount += surface.vertInfo.vertCount[3] * 4;
|
totalWeightCount += surface.vertInfo.vertCount[3] * 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
weightCollection.weights = std::make_unique<XModelBoneWeight[]>(weightCollection.totalWeightCount);
|
weightCollection.weights.resize(totalWeightCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddXModelVertexBoneWeights(AbstractXModelWriter& writer, const XModel* model, const unsigned lod, XModelVertexBoneWeightCollection& weightCollection)
|
void AddXModelVertexBoneWeights(XModelCommon& out, const XModel* model, const unsigned lod, XModelVertexBoneWeightCollection& weightCollection)
|
||||||
{
|
{
|
||||||
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
||||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||||
@ -416,7 +416,7 @@ namespace
|
|||||||
|
|
||||||
for (auto vertListVertexOffset = 0u; vertListVertexOffset < vertList.vertCount; vertListVertexOffset++)
|
for (auto vertListVertexOffset = 0u; vertListVertexOffset < vertList.vertCount; vertListVertexOffset++)
|
||||||
{
|
{
|
||||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{boneWeightOffset, 1});
|
out.m_vertex_bone_weights.emplace_back(boneWeightOffset, 1);
|
||||||
}
|
}
|
||||||
handledVertices += vertList.vertCount;
|
handledVertices += vertList.vertCount;
|
||||||
}
|
}
|
||||||
@ -434,7 +434,7 @@ namespace
|
|||||||
|
|
||||||
vertsBlendOffset += 1;
|
vertsBlendOffset += 1;
|
||||||
|
|
||||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{boneWeightOffset, 1});
|
out.m_vertex_bone_weights.emplace_back(boneWeightOffset, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2 bone weights
|
// 2 bone weights
|
||||||
@ -451,7 +451,7 @@ namespace
|
|||||||
|
|
||||||
vertsBlendOffset += 3;
|
vertsBlendOffset += 3;
|
||||||
|
|
||||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{boneWeightOffset, 2});
|
out.m_vertex_bone_weights.emplace_back(boneWeightOffset, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3 bone weights
|
// 3 bone weights
|
||||||
@ -471,7 +471,7 @@ namespace
|
|||||||
|
|
||||||
vertsBlendOffset += 5;
|
vertsBlendOffset += 5;
|
||||||
|
|
||||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{boneWeightOffset, 3});
|
out.m_vertex_bone_weights.emplace_back(boneWeightOffset, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4 bone weights
|
// 4 bone weights
|
||||||
@ -494,7 +494,7 @@ namespace
|
|||||||
|
|
||||||
vertsBlendOffset += 7;
|
vertsBlendOffset += 7;
|
||||||
|
|
||||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{boneWeightOffset, 4});
|
out.m_vertex_bone_weights.emplace_back(boneWeightOffset, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
handledVertices +=
|
handledVertices +=
|
||||||
@ -503,12 +503,12 @@ namespace
|
|||||||
|
|
||||||
for (; handledVertices < surface.vertCount; handledVertices++)
|
for (; handledVertices < surface.vertCount; handledVertices++)
|
||||||
{
|
{
|
||||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{nullptr, 0});
|
out.m_vertex_bone_weights.emplace_back(nullptr, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddXModelFaces(AbstractXModelWriter& writer, const XModel* model, const unsigned lod)
|
void AddXModelFaces(XModelCommon& out, const XModel* model, const unsigned lod)
|
||||||
{
|
{
|
||||||
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
||||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||||
@ -525,26 +525,26 @@ namespace
|
|||||||
face.vertexIndex[1] = tri[1] + surface.baseVertIndex;
|
face.vertexIndex[1] = tri[1] + surface.baseVertIndex;
|
||||||
face.vertexIndex[2] = tri[2] + surface.baseVertIndex;
|
face.vertexIndex[2] = tri[2] + surface.baseVertIndex;
|
||||||
face.objectIndex = static_cast<int>(surfIndex);
|
face.objectIndex = static_cast<int>(surfIndex);
|
||||||
writer.AddFace(face);
|
out.m_faces.emplace_back(face);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PopulateXModelWriter(const AssetDumpingContext& context, const unsigned lod, const XModel* model, AbstractXModelWriter& writer)
|
void PopulateXModelWriter(XModelCommon& out, const AssetDumpingContext& context, const unsigned lod, const XModel* model)
|
||||||
{
|
{
|
||||||
DistinctMapper<Material*> materialMapper(model->numsurfs);
|
DistinctMapper<Material*> materialMapper(model->numsurfs);
|
||||||
XModelVertexBoneWeightCollection boneWeightCollection;
|
XModelVertexBoneWeightCollection boneWeightCollection;
|
||||||
AllocateXModelBoneWeights(model, lod, boneWeightCollection);
|
AllocateXModelBoneWeights(model, lod, boneWeightCollection);
|
||||||
|
|
||||||
AddXModelBones(context, writer, model);
|
AddXModelBones(out, context, model);
|
||||||
AddXModelMaterials(writer, materialMapper, model);
|
AddXModelMaterials(out, materialMapper, model);
|
||||||
AddXModelObjects(writer, model, lod, materialMapper);
|
AddXModelObjects(out, model, lod, materialMapper);
|
||||||
AddXModelVertices(writer, model, lod);
|
AddXModelVertices(out, model, lod);
|
||||||
AddXModelVertexBoneWeights(writer, model, lod, boneWeightCollection);
|
AddXModelVertexBoneWeights(out, model, lod, boneWeightCollection);
|
||||||
AddXModelFaces(writer, model, lod);
|
AddXModelFaces(out, model, lod);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DumpXModelExportLod(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset, const unsigned lod)
|
void DumpXModelExportLod(const XModelCommon& common, const AssetDumpingContext& context, const XAssetInfo<XModel>* asset, const unsigned lod)
|
||||||
{
|
{
|
||||||
const auto* model = asset->Asset();
|
const auto* model = asset->Asset();
|
||||||
const auto assetFile = context.OpenAssetFile(GetFileNameForLod(model->name, lod, ".XMODEL_EXPORT"));
|
const auto assetFile = context.OpenAssetFile(GetFileNameForLod(model->name, lod, ".XMODEL_EXPORT"));
|
||||||
@ -552,13 +552,13 @@ namespace
|
|||||||
if (!assetFile)
|
if (!assetFile)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto writer = XModelExportWriter::CreateWriterForVersion6(context.m_zone->m_game->GetShortName(), context.m_zone->m_name);
|
const auto writer = xmodel_export::CreateWriterForVersion6(*assetFile, context.m_zone->m_game->GetShortName(), context.m_zone->m_name);
|
||||||
PopulateXModelWriter(context, lod, model, *writer);
|
writer->Write(common);
|
||||||
|
|
||||||
writer->Write(*assetFile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> void DumpGltfLod(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset, const unsigned lod, const std::string& extension)
|
template<typename T>
|
||||||
|
void DumpGltfLod(
|
||||||
|
const XModelCommon& common, const AssetDumpingContext& context, const XAssetInfo<XModel>* asset, const unsigned lod, const std::string& extension)
|
||||||
{
|
{
|
||||||
const auto* model = asset->Asset();
|
const auto* model = asset->Asset();
|
||||||
const auto assetFile = context.OpenAssetFile(GetFileNameForLod(model->name, lod, extension));
|
const auto assetFile = context.OpenAssetFile(GetFileNameForLod(model->name, lod, extension));
|
||||||
@ -568,9 +568,8 @@ namespace
|
|||||||
|
|
||||||
const auto output = std::make_unique<T>(*assetFile);
|
const auto output = std::make_unique<T>(*assetFile);
|
||||||
const auto writer = gltf::Writer::CreateWriter(output.get(), context.m_zone->m_game->GetShortName(), context.m_zone->m_name);
|
const auto writer = gltf::Writer::CreateWriter(output.get(), context.m_zone->m_game->GetShortName(), context.m_zone->m_name);
|
||||||
PopulateXModelWriter(context, lod, model, *writer);
|
|
||||||
|
|
||||||
writer->Write(*assetFile);
|
writer->Write(common);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DumpXModelSurfs(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset)
|
void DumpXModelSurfs(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset)
|
||||||
@ -582,6 +581,9 @@ namespace
|
|||||||
|
|
||||||
for (auto currentLod = 0u; currentLod < model->numLods; currentLod++)
|
for (auto currentLod = 0u; currentLod < model->numLods; currentLod++)
|
||||||
{
|
{
|
||||||
|
XModelCommon common;
|
||||||
|
PopulateXModelWriter(common, context, currentLod, asset->Asset());
|
||||||
|
|
||||||
switch (ObjWriting::Configuration.ModelOutputFormat)
|
switch (ObjWriting::Configuration.ModelOutputFormat)
|
||||||
{
|
{
|
||||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::OBJ:
|
case ObjWriting::Configuration_t::ModelOutputFormat_e::OBJ:
|
||||||
@ -589,15 +591,15 @@ namespace
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::XMODEL_EXPORT:
|
case ObjWriting::Configuration_t::ModelOutputFormat_e::XMODEL_EXPORT:
|
||||||
DumpXModelExportLod(context, asset, currentLod);
|
DumpXModelExportLod(common, context, asset, currentLod);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::GLTF:
|
case ObjWriting::Configuration_t::ModelOutputFormat_e::GLTF:
|
||||||
DumpGltfLod<gltf::TextOutput>(context, asset, currentLod, ".gltf");
|
DumpGltfLod<gltf::TextOutput>(common, context, asset, currentLod, ".gltf");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::GLB:
|
case ObjWriting::Configuration_t::ModelOutputFormat_e::GLB:
|
||||||
DumpGltfLod<gltf::BinOutput>(context, asset, currentLod, ".glb");
|
DumpGltfLod<gltf::BinOutput>(common, context, asset, currentLod, ".glb");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -6,12 +6,12 @@
|
|||||||
#include "Utils/DistinctMapper.h"
|
#include "Utils/DistinctMapper.h"
|
||||||
#include "Utils/HalfFloat.h"
|
#include "Utils/HalfFloat.h"
|
||||||
#include "Utils/QuatInt16.h"
|
#include "Utils/QuatInt16.h"
|
||||||
#include "XModel/AbstractXModelWriter.h"
|
|
||||||
#include "XModel/Export/XModelExportWriter.h"
|
#include "XModel/Export/XModelExportWriter.h"
|
||||||
#include "XModel/Gltf/GltfBinOutput.h"
|
#include "XModel/Gltf/GltfBinOutput.h"
|
||||||
#include "XModel/Gltf/GltfTextOutput.h"
|
#include "XModel/Gltf/GltfTextOutput.h"
|
||||||
#include "XModel/Gltf/GltfWriter.h"
|
#include "XModel/Gltf/GltfWriter.h"
|
||||||
#include "XModel/Obj/ObjWriter.h"
|
#include "XModel/Obj/ObjWriter.h"
|
||||||
|
#include "XModel/XModelWriter.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <format>
|
#include <format>
|
||||||
@ -152,7 +152,7 @@ namespace
|
|||||||
for (auto surfIndex = 0u; surfIndex < surfCount; surfIndex++)
|
for (auto surfIndex = 0u; surfIndex < surfCount; surfIndex++)
|
||||||
{
|
{
|
||||||
ObjObject object;
|
ObjObject object;
|
||||||
object.name = "surf" + std::to_string(surfIndex);
|
object.name = std::format("surf{}", surfIndex);
|
||||||
object.materialIndex = static_cast<int>(materialMapper.GetDistinctPositionByInputPosition(surfIndex + baseSurfIndex));
|
object.materialIndex = static_cast<int>(materialMapper.GetDistinctPositionByInputPosition(surfIndex + baseSurfIndex));
|
||||||
|
|
||||||
writer.AddObject(std::move(object));
|
writer.AddObject(std::move(object));
|
||||||
@ -257,7 +257,7 @@ namespace
|
|||||||
writer.WriteObj(*assetFile, std::format("{}.mtl", model->name));
|
writer.WriteObj(*assetFile, std::format("{}.mtl", model->name));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddXModelBones(const AssetDumpingContext& context, AbstractXModelWriter& writer, const XModel* model)
|
void AddXModelBones(XModelCommon& out, const AssetDumpingContext& context, const XModel* model)
|
||||||
{
|
{
|
||||||
for (auto boneNum = 0u; boneNum < model->numBones; boneNum++)
|
for (auto boneNum = 0u; boneNum < model->numBones; boneNum++)
|
||||||
{
|
{
|
||||||
@ -300,11 +300,11 @@ namespace
|
|||||||
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][3]));
|
QuatInt16::ToFloat(model->quats[boneNum - model->numRootBones][3]));
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.AddBone(std::move(bone));
|
out.m_bones.emplace_back(std::move(bone));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddXModelMaterials(AbstractXModelWriter& writer, DistinctMapper<Material*>& materialMapper, const XModel* model)
|
void AddXModelMaterials(XModelCommon& out, DistinctMapper<Material*>& materialMapper, const XModel* model)
|
||||||
{
|
{
|
||||||
for (auto surfaceMaterialNum = 0; surfaceMaterialNum < model->numsurfs; surfaceMaterialNum++)
|
for (auto surfaceMaterialNum = 0; surfaceMaterialNum < model->numsurfs; surfaceMaterialNum++)
|
||||||
{
|
{
|
||||||
@ -319,12 +319,12 @@ namespace
|
|||||||
if (colorMap)
|
if (colorMap)
|
||||||
xMaterial.colorMapName = std::string(colorMap->name);
|
xMaterial.colorMapName = std::string(colorMap->name);
|
||||||
|
|
||||||
writer.AddMaterial(std::move(xMaterial));
|
out.m_materials.emplace_back(std::move(xMaterial));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddXModelObjects(AbstractXModelWriter& writer, const XModel* model, const unsigned lod, const DistinctMapper<Material*>& materialMapper)
|
void AddXModelObjects(XModelCommon& out, const XModel* model, const unsigned lod, const DistinctMapper<Material*>& materialMapper)
|
||||||
{
|
{
|
||||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||||
const auto baseSurfaceIndex = model->lodInfo[lod].surfIndex;
|
const auto baseSurfaceIndex = model->lodInfo[lod].surfIndex;
|
||||||
@ -332,14 +332,14 @@ namespace
|
|||||||
for (auto surfIndex = 0u; surfIndex < surfCount; surfIndex++)
|
for (auto surfIndex = 0u; surfIndex < surfCount; surfIndex++)
|
||||||
{
|
{
|
||||||
XModelObject object;
|
XModelObject object;
|
||||||
object.name = "surf" + std::to_string(surfIndex);
|
object.name = std::format("surf{}", surfIndex);
|
||||||
object.materialIndex = static_cast<int>(materialMapper.GetDistinctPositionByInputPosition(surfIndex + baseSurfaceIndex));
|
object.materialIndex = static_cast<int>(materialMapper.GetDistinctPositionByInputPosition(surfIndex + baseSurfaceIndex));
|
||||||
|
|
||||||
writer.AddObject(std::move(object));
|
out.m_objects.emplace_back(std::move(object));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddXModelVertices(AbstractXModelWriter& writer, const XModel* model, const unsigned lod)
|
void AddXModelVertices(XModelCommon& out, const XModel* model, const unsigned lod)
|
||||||
{
|
{
|
||||||
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
||||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||||
@ -376,7 +376,7 @@ namespace
|
|||||||
vertex.uv[0] = uv.x;
|
vertex.uv[0] = uv.x;
|
||||||
vertex.uv[1] = uv.y;
|
vertex.uv[1] = uv.y;
|
||||||
|
|
||||||
writer.AddVertex(vertex);
|
out.m_vertices.emplace_back(vertex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -389,29 +389,29 @@ namespace
|
|||||||
if (!surfs)
|
if (!surfs)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
weightCollection.totalWeightCount = 0u;
|
auto totalWeightCount = 0u;
|
||||||
for (auto surfIndex = 0u; surfIndex < surfCount; surfIndex++)
|
for (auto surfIndex = 0u; surfIndex < surfCount; surfIndex++)
|
||||||
{
|
{
|
||||||
const auto& surface = surfs[surfIndex];
|
const auto& surface = surfs[surfIndex];
|
||||||
|
|
||||||
if (surface.vertList)
|
if (surface.vertList)
|
||||||
{
|
{
|
||||||
weightCollection.totalWeightCount += surface.vertListCount;
|
totalWeightCount += surface.vertListCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (surface.vertInfo.vertsBlend)
|
if (surface.vertInfo.vertsBlend)
|
||||||
{
|
{
|
||||||
weightCollection.totalWeightCount += surface.vertInfo.vertCount[0] * 1;
|
totalWeightCount += surface.vertInfo.vertCount[0] * 1;
|
||||||
weightCollection.totalWeightCount += surface.vertInfo.vertCount[1] * 2;
|
totalWeightCount += surface.vertInfo.vertCount[1] * 2;
|
||||||
weightCollection.totalWeightCount += surface.vertInfo.vertCount[2] * 3;
|
totalWeightCount += surface.vertInfo.vertCount[2] * 3;
|
||||||
weightCollection.totalWeightCount += surface.vertInfo.vertCount[3] * 4;
|
totalWeightCount += surface.vertInfo.vertCount[3] * 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
weightCollection.weights = std::make_unique<XModelBoneWeight[]>(weightCollection.totalWeightCount);
|
weightCollection.weights.resize(totalWeightCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddXModelVertexBoneWeights(AbstractXModelWriter& writer, const XModel* model, const unsigned lod, XModelVertexBoneWeightCollection& weightCollection)
|
void AddXModelVertexBoneWeights(XModelCommon& out, const XModel* model, const unsigned lod, XModelVertexBoneWeightCollection& weightCollection)
|
||||||
{
|
{
|
||||||
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
||||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||||
@ -437,7 +437,7 @@ namespace
|
|||||||
|
|
||||||
for (auto vertListVertexOffset = 0u; vertListVertexOffset < vertList.vertCount; vertListVertexOffset++)
|
for (auto vertListVertexOffset = 0u; vertListVertexOffset < vertList.vertCount; vertListVertexOffset++)
|
||||||
{
|
{
|
||||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{boneWeightOffset, 1});
|
out.m_vertex_bone_weights.emplace_back(boneWeightOffset, 1);
|
||||||
}
|
}
|
||||||
handledVertices += vertList.vertCount;
|
handledVertices += vertList.vertCount;
|
||||||
}
|
}
|
||||||
@ -455,7 +455,7 @@ namespace
|
|||||||
|
|
||||||
vertsBlendOffset += 1;
|
vertsBlendOffset += 1;
|
||||||
|
|
||||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{boneWeightOffset, 1});
|
out.m_vertex_bone_weights.emplace_back(boneWeightOffset, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2 bone weights
|
// 2 bone weights
|
||||||
@ -472,7 +472,7 @@ namespace
|
|||||||
|
|
||||||
vertsBlendOffset += 3;
|
vertsBlendOffset += 3;
|
||||||
|
|
||||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{boneWeightOffset, 2});
|
out.m_vertex_bone_weights.emplace_back(boneWeightOffset, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3 bone weights
|
// 3 bone weights
|
||||||
@ -492,7 +492,7 @@ namespace
|
|||||||
|
|
||||||
vertsBlendOffset += 5;
|
vertsBlendOffset += 5;
|
||||||
|
|
||||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{boneWeightOffset, 3});
|
out.m_vertex_bone_weights.emplace_back(boneWeightOffset, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4 bone weights
|
// 4 bone weights
|
||||||
@ -515,7 +515,7 @@ namespace
|
|||||||
|
|
||||||
vertsBlendOffset += 7;
|
vertsBlendOffset += 7;
|
||||||
|
|
||||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{boneWeightOffset, 4});
|
out.m_vertex_bone_weights.emplace_back(boneWeightOffset, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
handledVertices +=
|
handledVertices +=
|
||||||
@ -524,12 +524,12 @@ namespace
|
|||||||
|
|
||||||
for (; handledVertices < surface.vertCount; handledVertices++)
|
for (; handledVertices < surface.vertCount; handledVertices++)
|
||||||
{
|
{
|
||||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{nullptr, 0});
|
out.m_vertex_bone_weights.emplace_back(nullptr, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddXModelFaces(AbstractXModelWriter& writer, const XModel* model, const unsigned lod)
|
void AddXModelFaces(XModelCommon& out, const XModel* model, const unsigned lod)
|
||||||
{
|
{
|
||||||
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
||||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||||
@ -549,26 +549,26 @@ namespace
|
|||||||
face.vertexIndex[1] = tri[1] + surface.baseVertIndex;
|
face.vertexIndex[1] = tri[1] + surface.baseVertIndex;
|
||||||
face.vertexIndex[2] = tri[2] + surface.baseVertIndex;
|
face.vertexIndex[2] = tri[2] + surface.baseVertIndex;
|
||||||
face.objectIndex = static_cast<int>(surfIndex);
|
face.objectIndex = static_cast<int>(surfIndex);
|
||||||
writer.AddFace(face);
|
out.m_faces.emplace_back(face);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PopulateXModelWriter(const AssetDumpingContext& context, const unsigned lod, const XModel* model, AbstractXModelWriter& writer)
|
void PopulateXModelWriter(XModelCommon& out, const AssetDumpingContext& context, const unsigned lod, const XModel* model)
|
||||||
{
|
{
|
||||||
DistinctMapper<Material*> materialMapper(model->numsurfs);
|
DistinctMapper<Material*> materialMapper(model->numsurfs);
|
||||||
XModelVertexBoneWeightCollection boneWeightCollection;
|
XModelVertexBoneWeightCollection boneWeightCollection;
|
||||||
AllocateXModelBoneWeights(model, lod, boneWeightCollection);
|
AllocateXModelBoneWeights(model, lod, boneWeightCollection);
|
||||||
|
|
||||||
AddXModelBones(context, writer, model);
|
AddXModelBones(out, context, model);
|
||||||
AddXModelMaterials(writer, materialMapper, model);
|
AddXModelMaterials(out, materialMapper, model);
|
||||||
AddXModelObjects(writer, model, lod, materialMapper);
|
AddXModelObjects(out, model, lod, materialMapper);
|
||||||
AddXModelVertices(writer, model, lod);
|
AddXModelVertices(out, model, lod);
|
||||||
AddXModelVertexBoneWeights(writer, model, lod, boneWeightCollection);
|
AddXModelVertexBoneWeights(out, model, lod, boneWeightCollection);
|
||||||
AddXModelFaces(writer, model, lod);
|
AddXModelFaces(out, model, lod);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DumpXModelExportLod(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset, const unsigned lod)
|
void DumpXModelExportLod(const XModelCommon& common, const AssetDumpingContext& context, const XAssetInfo<XModel>* asset, const unsigned lod)
|
||||||
{
|
{
|
||||||
const auto* model = asset->Asset();
|
const auto* model = asset->Asset();
|
||||||
const auto assetFile = context.OpenAssetFile(GetFileNameForLod(model->name, lod, ".XMODEL_EXPORT"));
|
const auto assetFile = context.OpenAssetFile(GetFileNameForLod(model->name, lod, ".XMODEL_EXPORT"));
|
||||||
@ -576,13 +576,13 @@ namespace
|
|||||||
if (!assetFile)
|
if (!assetFile)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto writer = XModelExportWriter::CreateWriterForVersion6(context.m_zone->m_game->GetShortName(), context.m_zone->m_name);
|
const auto writer = xmodel_export::CreateWriterForVersion6(*assetFile, context.m_zone->m_game->GetShortName(), context.m_zone->m_name);
|
||||||
PopulateXModelWriter(context, lod, model, *writer);
|
writer->Write(common);
|
||||||
|
|
||||||
writer->Write(*assetFile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> void DumpGltfLod(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset, const unsigned lod, const std::string& extension)
|
template<typename T>
|
||||||
|
void DumpGltfLod(
|
||||||
|
const XModelCommon& common, const AssetDumpingContext& context, const XAssetInfo<XModel>* asset, const unsigned lod, const std::string& extension)
|
||||||
{
|
{
|
||||||
const auto* model = asset->Asset();
|
const auto* model = asset->Asset();
|
||||||
const auto assetFile = context.OpenAssetFile(GetFileNameForLod(model->name, lod, extension));
|
const auto assetFile = context.OpenAssetFile(GetFileNameForLod(model->name, lod, extension));
|
||||||
@ -592,9 +592,8 @@ namespace
|
|||||||
|
|
||||||
const auto output = std::make_unique<T>(*assetFile);
|
const auto output = std::make_unique<T>(*assetFile);
|
||||||
const auto writer = gltf::Writer::CreateWriter(output.get(), context.m_zone->m_game->GetShortName(), context.m_zone->m_name);
|
const auto writer = gltf::Writer::CreateWriter(output.get(), context.m_zone->m_game->GetShortName(), context.m_zone->m_name);
|
||||||
PopulateXModelWriter(context, lod, model, *writer);
|
|
||||||
|
|
||||||
writer->Write(*assetFile);
|
writer->Write(common);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DumpXModelSurfs(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset)
|
void DumpXModelSurfs(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset)
|
||||||
@ -606,6 +605,9 @@ namespace
|
|||||||
|
|
||||||
for (auto currentLod = 0u; currentLod < model->numLods; currentLod++)
|
for (auto currentLod = 0u; currentLod < model->numLods; currentLod++)
|
||||||
{
|
{
|
||||||
|
XModelCommon common;
|
||||||
|
PopulateXModelWriter(common, context, currentLod, asset->Asset());
|
||||||
|
|
||||||
switch (ObjWriting::Configuration.ModelOutputFormat)
|
switch (ObjWriting::Configuration.ModelOutputFormat)
|
||||||
{
|
{
|
||||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::OBJ:
|
case ObjWriting::Configuration_t::ModelOutputFormat_e::OBJ:
|
||||||
@ -613,15 +615,15 @@ namespace
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::XMODEL_EXPORT:
|
case ObjWriting::Configuration_t::ModelOutputFormat_e::XMODEL_EXPORT:
|
||||||
DumpXModelExportLod(context, asset, currentLod);
|
DumpXModelExportLod(common, context, asset, currentLod);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::GLTF:
|
case ObjWriting::Configuration_t::ModelOutputFormat_e::GLTF:
|
||||||
DumpGltfLod<gltf::TextOutput>(context, asset, currentLod, ".gltf");
|
DumpGltfLod<gltf::TextOutput>(common, context, asset, currentLod, ".gltf");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::GLB:
|
case ObjWriting::Configuration_t::ModelOutputFormat_e::GLB:
|
||||||
DumpGltfLod<gltf::BinOutput>(context, asset, currentLod, ".glb");
|
DumpGltfLod<gltf::BinOutput>(common, context, asset, currentLod, ".glb");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
#include "AbstractXModelWriter.h"
|
|
||||||
|
|
||||||
AbstractXModelWriter::AbstractXModelWriter() = default;
|
|
||||||
|
|
||||||
void AbstractXModelWriter::AddObject(XModelObject object)
|
|
||||||
{
|
|
||||||
m_objects.emplace_back(std::move(object));
|
|
||||||
}
|
|
||||||
|
|
||||||
void AbstractXModelWriter::AddBone(XModelBone bone)
|
|
||||||
{
|
|
||||||
m_bones.emplace_back(std::move(bone));
|
|
||||||
}
|
|
||||||
|
|
||||||
void AbstractXModelWriter::AddMaterial(XModelMaterial material)
|
|
||||||
{
|
|
||||||
m_materials.emplace_back(std::move(material));
|
|
||||||
}
|
|
||||||
|
|
||||||
void AbstractXModelWriter::AddVertex(XModelVertex vertex)
|
|
||||||
{
|
|
||||||
m_vertices.emplace_back(vertex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AbstractXModelWriter::AddVertexBoneWeights(XModelVertexBoneWeights vertexBoneWeights)
|
|
||||||
{
|
|
||||||
m_vertex_bone_weights.emplace_back(vertexBoneWeights);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AbstractXModelWriter::AddFace(XModelFace face)
|
|
||||||
{
|
|
||||||
m_faces.emplace_back(face);
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "XModel/XModelCommon.h"
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
class AbstractXModelWriter
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
std::vector<XModelObject> m_objects;
|
|
||||||
std::vector<XModelBone> m_bones;
|
|
||||||
std::vector<XModelMaterial> m_materials;
|
|
||||||
std::vector<XModelVertex> m_vertices;
|
|
||||||
std::vector<XModelVertexBoneWeights> m_vertex_bone_weights;
|
|
||||||
std::vector<XModelFace> m_faces;
|
|
||||||
|
|
||||||
public:
|
|
||||||
AbstractXModelWriter();
|
|
||||||
|
|
||||||
void AddObject(XModelObject object);
|
|
||||||
void AddBone(XModelBone bone);
|
|
||||||
void AddMaterial(XModelMaterial material);
|
|
||||||
void AddVertex(XModelVertex vertex);
|
|
||||||
void AddVertexBoneWeights(XModelVertexBoneWeights vertexBoneWeights);
|
|
||||||
void AddFace(XModelFace face);
|
|
||||||
};
|
|
@ -6,25 +6,20 @@
|
|||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
class XModelExportWriterBase : public XModelExportWriter
|
class XModelExportWriterBase : public XModelWriter
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
std::string m_game_name;
|
void PrepareVertexMerger(const XModelCommon& xmodel)
|
||||||
std::string m_zone_name;
|
|
||||||
|
|
||||||
VertexMerger m_vertex_merger;
|
|
||||||
|
|
||||||
void PrepareVertexMerger()
|
|
||||||
{
|
{
|
||||||
m_vertex_merger = VertexMerger(m_vertices.size());
|
m_vertex_merger = VertexMerger(xmodel.m_vertices.size());
|
||||||
|
|
||||||
auto vertexOffset = 0u;
|
auto vertexOffset = 0u;
|
||||||
for (const auto& vertex : m_vertices)
|
for (const auto& vertex : xmodel.m_vertices)
|
||||||
{
|
{
|
||||||
XModelVertexBoneWeights weights{nullptr, 0};
|
XModelVertexBoneWeights weights{nullptr, 0};
|
||||||
|
|
||||||
if (vertexOffset < m_vertex_bone_weights.size())
|
if (vertexOffset < xmodel.m_vertex_bone_weights.size())
|
||||||
weights = m_vertex_bone_weights[vertexOffset];
|
weights = xmodel.m_vertex_bone_weights[vertexOffset];
|
||||||
|
|
||||||
m_vertex_merger.Add(VertexMergerPos{vertex.coordinates[0], vertex.coordinates[1], vertex.coordinates[2], weights.weights, weights.weightCount});
|
m_vertex_merger.Add(VertexMergerPos{vertex.coordinates[0], vertex.coordinates[1], vertex.coordinates[2], weights.weights, weights.weightCount});
|
||||||
|
|
||||||
@ -32,103 +27,99 @@ protected:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteHeader(std::ostream& stream, const int version) const
|
void WriteHeader(const int version) const
|
||||||
{
|
{
|
||||||
stream << "// OpenAssetTools XMODEL_EXPORT File\n";
|
m_stream << "// OpenAssetTools XMODEL_EXPORT File\n";
|
||||||
stream << "// Game Origin: " << m_game_name << "\n";
|
m_stream << "// Game Origin: " << m_game_name << "\n";
|
||||||
stream << "// Zone Origin: " << m_zone_name << "\n";
|
m_stream << "// Zone Origin: " << m_zone_name << "\n";
|
||||||
stream << "MODEL\n";
|
m_stream << "MODEL\n";
|
||||||
stream << "VERSION " << version << "\n";
|
m_stream << "VERSION " << version << "\n";
|
||||||
stream << "\n";
|
m_stream << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteBones(std::ostream& stream) const
|
void WriteBones(const XModelCommon& xmodel) const
|
||||||
{
|
{
|
||||||
stream << "NUMBONES " << m_bones.size() << "\n";
|
m_stream << "NUMBONES " << xmodel.m_bones.size() << "\n";
|
||||||
size_t boneNum = 0u;
|
size_t boneNum = 0u;
|
||||||
for (const auto& bone : m_bones)
|
for (const auto& bone : xmodel.m_bones)
|
||||||
{
|
{
|
||||||
stream << "BONE " << boneNum << " ";
|
m_stream << "BONE " << boneNum << " ";
|
||||||
if (bone.parentIndex < 0)
|
if (bone.parentIndex < 0)
|
||||||
stream << "-1";
|
m_stream << "-1";
|
||||||
else
|
else
|
||||||
stream << bone.parentIndex;
|
m_stream << bone.parentIndex;
|
||||||
|
|
||||||
stream << " \"" << bone.name << "\"\n";
|
m_stream << " \"" << bone.name << "\"\n";
|
||||||
boneNum++;
|
boneNum++;
|
||||||
}
|
}
|
||||||
stream << "\n";
|
m_stream << "\n";
|
||||||
|
|
||||||
boneNum = 0u;
|
boneNum = 0u;
|
||||||
for (const auto& bone : m_bones)
|
for (const auto& bone : xmodel.m_bones)
|
||||||
{
|
{
|
||||||
stream << "BONE " << boneNum << "\n";
|
m_stream << "BONE " << boneNum << "\n";
|
||||||
stream << "OFFSET ";
|
m_stream << std::format("OFFSET {:.6f}, {:.6f}, {:.6f}\n", bone.globalOffset[0], bone.globalOffset[1], bone.globalOffset[2]);
|
||||||
stream << std::setprecision(6) << std::fixed << bone.globalOffset[0] << ", " << std::setprecision(6) << std::fixed << bone.globalOffset[1] << ", "
|
m_stream << std::format("SCALE {:.6f}, {:.6f}, {:.6f}\n", bone.scale[0], bone.scale[1], bone.scale[2]);
|
||||||
<< std::setprecision(6) << std::fixed << bone.globalOffset[2] << "\n";
|
|
||||||
|
|
||||||
stream << "SCALE ";
|
|
||||||
stream << std::setprecision(6) << std::fixed << bone.scale[0] << ", " << std::setprecision(6) << std::fixed << bone.scale[1] << ", "
|
|
||||||
<< std::setprecision(6) << std::fixed << bone.scale[2] << "\n";
|
|
||||||
|
|
||||||
const Matrix32 mat = bone.globalRotation.ToMatrix();
|
const Matrix32 mat = bone.globalRotation.ToMatrix();
|
||||||
stream << "X " << std::setprecision(6) << std::fixed << mat.m_data[0][0] << ", " << std::setprecision(6) << std::fixed << mat.m_data[1][0] << ", "
|
m_stream << std::format("X {:.6f}, {:.6f}, {:.6f}\n", mat.m_data[0][0], mat.m_data[1][0], mat.m_data[2][0]);
|
||||||
<< std::setprecision(6) << std::fixed << mat.m_data[2][0] << "\n";
|
m_stream << std::format("Y {:.6f}, {:.6f}, {:.6f}\n", mat.m_data[0][1], mat.m_data[1][1], mat.m_data[2][1]);
|
||||||
stream << "Y " << std::setprecision(6) << std::fixed << mat.m_data[0][1] << ", " << std::setprecision(6) << std::fixed << mat.m_data[1][1] << ", "
|
m_stream << std::format("Z {:.6f}, {:.6f}, {:.6f}\n", mat.m_data[0][2], mat.m_data[1][2], mat.m_data[2][2]);
|
||||||
<< std::setprecision(6) << std::fixed << mat.m_data[2][1] << "\n";
|
m_stream << '\n';
|
||||||
stream << "Z " << std::setprecision(6) << std::fixed << mat.m_data[0][2] << ", " << std::setprecision(6) << std::fixed << mat.m_data[1][2] << ", "
|
|
||||||
<< std::setprecision(6) << std::fixed << mat.m_data[2][2] << "\n";
|
|
||||||
stream << "\n";
|
|
||||||
boneNum++;
|
boneNum++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
XModelExportWriterBase(std::string gameName, std::string zoneName)
|
XModelExportWriterBase(std::ostream& stream, std::string gameName, std::string zoneName)
|
||||||
: m_game_name(std::move(gameName)),
|
: m_stream(stream),
|
||||||
|
m_game_name(std::move(gameName)),
|
||||||
m_zone_name(std::move(zoneName))
|
m_zone_name(std::move(zoneName))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::ostream& m_stream;
|
||||||
|
std::string m_game_name;
|
||||||
|
std::string m_zone_name;
|
||||||
|
VertexMerger m_vertex_merger;
|
||||||
};
|
};
|
||||||
|
|
||||||
class XModelExportWriter6 final : public XModelExportWriterBase
|
class XModelExportWriter6 final : public XModelExportWriterBase
|
||||||
{
|
{
|
||||||
void WriteVertices(std::ostream& stream) const
|
void WriteVertices(const XModelCommon& xmodel) const
|
||||||
{
|
{
|
||||||
const auto& distinctVertexValues = m_vertex_merger.GetDistinctValues();
|
const auto& distinctVertexValues = m_vertex_merger.GetDistinctValues();
|
||||||
stream << "NUMVERTS " << distinctVertexValues.size() << "\n";
|
m_stream << "NUMVERTS " << distinctVertexValues.size() << "\n";
|
||||||
size_t vertexNum = 0u;
|
size_t vertexNum = 0u;
|
||||||
for (const auto& vertexPos : distinctVertexValues)
|
for (const auto& vertexPos : distinctVertexValues)
|
||||||
{
|
{
|
||||||
stream << "VERT " << vertexNum << "\n";
|
m_stream << "VERT " << vertexNum << "\n";
|
||||||
stream << "OFFSET ";
|
m_stream << std::format("OFFSET {:.6f}, {:.6f}, {:.6f}\n", vertexPos.x, vertexPos.y, vertexPos.z);
|
||||||
stream << std::setprecision(6) << std::fixed << vertexPos.x << ", " << std::setprecision(6) << std::fixed << vertexPos.y << ", "
|
m_stream << "BONES " << vertexPos.weightCount << "\n";
|
||||||
<< std::setprecision(6) << std::fixed << vertexPos.z << "\n";
|
|
||||||
stream << "BONES " << vertexPos.weightCount << "\n";
|
|
||||||
|
|
||||||
for (auto weightIndex = 0u; weightIndex < vertexPos.weightCount; weightIndex++)
|
for (auto weightIndex = 0u; weightIndex < vertexPos.weightCount; weightIndex++)
|
||||||
{
|
{
|
||||||
stream << "BONE " << vertexPos.weights[weightIndex].boneIndex << " " << std::setprecision(6) << std::fixed
|
const auto& weight = vertexPos.weights[weightIndex];
|
||||||
<< vertexPos.weights[weightIndex].weight << "\n";
|
m_stream << std::format("BONE {} {:.6f}\n", weight.boneIndex, weight.weight);
|
||||||
}
|
}
|
||||||
stream << "\n";
|
m_stream << "\n";
|
||||||
vertexNum++;
|
vertexNum++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WriteFaceVertex(std::ostream& stream, const size_t index, const XModelVertex& vertex)
|
void WriteFaceVertex(const size_t index, const XModelVertex& vertex) const
|
||||||
{
|
{
|
||||||
stream << "VERT " << index << "\n";
|
m_stream << "VERT " << index << "\n";
|
||||||
stream << "NORMAL " << std::setprecision(6) << std::fixed << vertex.normal[0] << " " << std::setprecision(6) << std::fixed << vertex.normal[1] << " "
|
m_stream << std::format("NORMAL {:.6f} {:.6f} {:.6f}\n", vertex.normal[0], vertex.normal[1], vertex.normal[2]);
|
||||||
|
m_stream << "NORMAL " << std::setprecision(6) << std::fixed << vertex.normal[0] << " " << std::setprecision(6) << std::fixed << vertex.normal[1] << " "
|
||||||
<< std::setprecision(6) << std::fixed << vertex.normal[2] << "\n";
|
<< std::setprecision(6) << std::fixed << vertex.normal[2] << "\n";
|
||||||
stream << "COLOR " << std::setprecision(6) << std::fixed << vertex.color[0] << " " << std::setprecision(6) << std::fixed << vertex.color[1] << " "
|
m_stream << std::format("COLOR {:.6f} {:.6f} {:.6f} {:.6f}\n", vertex.color[0], vertex.color[1], vertex.color[2], vertex.color[3]);
|
||||||
<< std::setprecision(6) << std::fixed << vertex.color[2] << " " << std::setprecision(6) << std::fixed << vertex.color[3] << "\n";
|
m_stream << std::format("UV 1 {:.6f} {:.6f}\n", vertex.uv[0], vertex.uv[1]);
|
||||||
stream << "UV 1 " << std::setprecision(6) << std::fixed << vertex.uv[0] << " " << std::setprecision(6) << std::fixed << vertex.uv[1] << "\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteFaces(std::ostream& stream) const
|
void WriteFaces(const XModelCommon& xmodel) const
|
||||||
{
|
{
|
||||||
stream << "NUMFACES " << m_faces.size() << "\n";
|
m_stream << "NUMFACES " << xmodel.m_faces.size() << "\n";
|
||||||
for (const auto& face : m_faces)
|
for (const auto& face : xmodel.m_faces)
|
||||||
{
|
{
|
||||||
const size_t distinctPositions[3]{
|
const size_t distinctPositions[3]{
|
||||||
m_vertex_merger.GetDistinctPositionByInputPosition(face.vertexIndex[0]),
|
m_vertex_merger.GetDistinctPositionByInputPosition(face.vertexIndex[0]),
|
||||||
@ -136,87 +127,97 @@ class XModelExportWriter6 final : public XModelExportWriterBase
|
|||||||
m_vertex_merger.GetDistinctPositionByInputPosition(face.vertexIndex[2]),
|
m_vertex_merger.GetDistinctPositionByInputPosition(face.vertexIndex[2]),
|
||||||
};
|
};
|
||||||
|
|
||||||
const XModelVertex& v0 = m_vertices[face.vertexIndex[0]];
|
const XModelVertex& v0 = xmodel.m_vertices[face.vertexIndex[0]];
|
||||||
const XModelVertex& v1 = m_vertices[face.vertexIndex[1]];
|
const XModelVertex& v1 = xmodel.m_vertices[face.vertexIndex[1]];
|
||||||
const XModelVertex& v2 = m_vertices[face.vertexIndex[2]];
|
const XModelVertex& v2 = xmodel.m_vertices[face.vertexIndex[2]];
|
||||||
|
|
||||||
stream << "TRI " << face.objectIndex << " " << m_objects[face.objectIndex].materialIndex << " 0 0\n";
|
m_stream << "TRI " << face.objectIndex << " " << xmodel.m_objects[face.objectIndex].materialIndex << " 0 0\n";
|
||||||
WriteFaceVertex(stream, distinctPositions[0], v0);
|
WriteFaceVertex(distinctPositions[0], v0);
|
||||||
WriteFaceVertex(stream, distinctPositions[1], v1);
|
WriteFaceVertex(distinctPositions[1], v1);
|
||||||
WriteFaceVertex(stream, distinctPositions[2], v2);
|
WriteFaceVertex(distinctPositions[2], v2);
|
||||||
stream << "\n";
|
m_stream << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteObjects(std::ostream& stream) const
|
void WriteObjects(const XModelCommon& xmodel) const
|
||||||
{
|
{
|
||||||
stream << "NUMOBJECTS " << m_objects.size() << "\n";
|
m_stream << "NUMOBJECTS " << xmodel.m_objects.size() << "\n";
|
||||||
size_t objectNum = 0u;
|
size_t objectNum = 0u;
|
||||||
for (const auto& object : m_objects)
|
for (const auto& object : xmodel.m_objects)
|
||||||
{
|
{
|
||||||
stream << "OBJECT " << objectNum << " \"" << object.name << "\"\n";
|
m_stream << "OBJECT " << objectNum << " \"" << object.name << "\"\n";
|
||||||
objectNum++;
|
objectNum++;
|
||||||
}
|
}
|
||||||
stream << "\n";
|
m_stream << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteMaterials(std::ostream& stream) const
|
void WriteMaterials(const XModelCommon& xmodel) const
|
||||||
{
|
{
|
||||||
stream << "NUMMATERIALS " << m_materials.size() << "\n";
|
m_stream << "NUMMATERIALS " << xmodel.m_materials.size() << "\n";
|
||||||
size_t materialNum = 0u;
|
size_t materialNum = 0u;
|
||||||
for (const auto& material : m_materials)
|
for (const auto& material : xmodel.m_materials)
|
||||||
{
|
{
|
||||||
const auto colorMapPath = "../images/" + material.colorMapName + ".dds";
|
const auto colorMapPath = "../images/" + material.colorMapName + ".dds";
|
||||||
stream << "MATERIAL " << materialNum << " \"" << material.name << "\" \"" << material.materialTypeName << "\" \"" << colorMapPath << "\"\n";
|
m_stream << "MATERIAL " << materialNum << " \"" << material.name << "\" \"" << material.materialTypeName << "\" \"" << colorMapPath << "\"\n";
|
||||||
stream << "COLOR " << std::setprecision(6) << std::fixed << material.color[0] << " " << std::setprecision(6) << std::fixed << material.color[1]
|
m_stream << std::format("COLOR {:.6f} {:.6f} {:.6f} {:.6f}\n", material.color[0], material.color[1], material.color[2], material.color[3]);
|
||||||
<< " " << std::setprecision(6) << std::fixed << material.color[2] << " " << std::setprecision(6) << std::fixed << material.color[3] << "\n";
|
m_stream << std::format("TRANSPARENCY {:.6f} {:.6f} {:.6f} {:.6f}\n",
|
||||||
stream << "TRANSPARENCY " << std::setprecision(6) << std::fixed << material.transparency[0] << " " << std::setprecision(6) << std::fixed
|
material.transparency[0],
|
||||||
<< material.transparency[1] << " " << std::setprecision(6) << std::fixed << material.transparency[2] << " " << std::setprecision(6)
|
material.transparency[1],
|
||||||
<< std::fixed << material.transparency[3] << "\n";
|
material.transparency[2],
|
||||||
stream << "AMBIENTCOLOR " << std::setprecision(6) << std::fixed << material.ambientColor[0] << " " << std::setprecision(6) << std::fixed
|
material.transparency[3]);
|
||||||
<< material.ambientColor[1] << " " << std::setprecision(6) << std::fixed << material.ambientColor[2] << " " << std::setprecision(6)
|
m_stream << std::format("AMBIENTCOLOR {:.6f} {:.6f} {:.6f} {:.6f}\n",
|
||||||
<< std::fixed << material.ambientColor[3] << "\n";
|
material.ambientColor[0],
|
||||||
stream << "INCANDESCENCE " << std::setprecision(6) << std::fixed << material.incandescence[0] << " " << std::setprecision(6) << std::fixed
|
material.ambientColor[1],
|
||||||
<< material.incandescence[1] << " " << std::setprecision(6) << std::fixed << material.incandescence[2] << " " << std::setprecision(6)
|
material.ambientColor[2],
|
||||||
<< std::fixed << material.incandescence[3] << "\n";
|
material.ambientColor[3]);
|
||||||
stream << "COEFFS " << std::setprecision(6) << std::fixed << material.coeffs[0] << " " << std::setprecision(6) << std::fixed << material.coeffs[1]
|
m_stream << std::format("INCANDESCENCE {:.6f} {:.6f} {:.6f} {:.6f}\n",
|
||||||
<< "\n";
|
material.incandescence[0],
|
||||||
stream << "GLOW " << std::setprecision(6) << std::fixed << material.glow.x << " " << material.glow.y << "\n";
|
material.incandescence[1],
|
||||||
stream << "REFRACTIVE " << material.refractive.x << " " << std::setprecision(6) << std::fixed << material.refractive.y << "\n";
|
material.incandescence[2],
|
||||||
stream << "SPECULARCOLOR " << std::setprecision(6) << std::fixed << material.specularColor[0] << " " << std::setprecision(6) << std::fixed
|
material.incandescence[3]);
|
||||||
<< material.specularColor[1] << " " << std::setprecision(6) << std::fixed << material.specularColor[2] << " " << std::setprecision(6)
|
m_stream << std::format("COEFFS {:.6f} {:.6f}\n", material.coeffs[0], material.coeffs[1]);
|
||||||
<< std::fixed << material.specularColor[3] << "\n";
|
m_stream << std::format("GLOW {:.6f} {}\n", material.glow.x, material.glow.y);
|
||||||
stream << "REFLECTIVECOLOR " << std::setprecision(6) << std::fixed << material.reflectiveColor[0] << " " << std::setprecision(6) << std::fixed
|
m_stream << std::format("REFRACTIVE {} {:.6f}\n", material.refractive.x, material.refractive.y);
|
||||||
<< material.reflectiveColor[1] << " " << std::setprecision(6) << std::fixed << material.reflectiveColor[2] << " " << std::setprecision(6)
|
m_stream << std::format("SPECULARCOLOR {:.6f} {:.6f} {:.6f} {:.6f}\n",
|
||||||
<< std::fixed << material.reflectiveColor[3] << "\n";
|
material.specularColor[0],
|
||||||
stream << "REFLECTIVE " << material.reflective.x << " " << std::setprecision(6) << std::fixed << material.reflective.y << "\n";
|
material.specularColor[1],
|
||||||
stream << "BLINN " << std::setprecision(6) << std::fixed << material.blinn[0] << " " << std::setprecision(6) << std::fixed << material.blinn[1]
|
material.specularColor[2],
|
||||||
<< "\n";
|
material.specularColor[3]);
|
||||||
stream << "PHONG " << std::setprecision(6) << std::fixed << material.phong << "\n";
|
m_stream << std::format("REFLECTIVECOLOR {:.6f} {:.6f} {:.6f} {:.6f}\n",
|
||||||
stream << "\n";
|
material.reflectiveColor[0],
|
||||||
|
material.reflectiveColor[1],
|
||||||
|
material.reflectiveColor[2],
|
||||||
|
material.reflectiveColor[3]);
|
||||||
|
m_stream << std::format("REFLECTIVE {} {:.6f}\n", material.reflective.x, material.reflective.y);
|
||||||
|
m_stream << std::format("BLINN {:.6f} {:.6f}\n", material.blinn[0], material.blinn[1]);
|
||||||
|
m_stream << std::format("PHONG {:.6f}\n", material.phong);
|
||||||
|
m_stream << '\n';
|
||||||
materialNum++;
|
materialNum++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
XModelExportWriter6(std::string gameName, std::string zoneName)
|
XModelExportWriter6(std::ostream& stream, std::string gameName, std::string zoneName)
|
||||||
: XModelExportWriterBase(std::move(gameName), std::move(zoneName))
|
: XModelExportWriterBase(stream, std::move(gameName), std::move(zoneName))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write(std::ostream& stream) override
|
void Write(const XModelCommon& xmodel) override
|
||||||
{
|
{
|
||||||
PrepareVertexMerger();
|
PrepareVertexMerger(xmodel);
|
||||||
WriteHeader(stream, 6);
|
WriteHeader(6);
|
||||||
WriteBones(stream);
|
WriteBones(xmodel);
|
||||||
WriteVertices(stream);
|
WriteVertices(xmodel);
|
||||||
WriteFaces(stream);
|
WriteFaces(xmodel);
|
||||||
WriteObjects(stream);
|
WriteObjects(xmodel);
|
||||||
WriteMaterials(stream);
|
WriteMaterials(xmodel);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<XModelExportWriter> XModelExportWriter::CreateWriterForVersion6(std::string gameName, std::string zoneName)
|
namespace xmodel_export
|
||||||
{
|
{
|
||||||
return std::make_unique<XModelExportWriter6>(std::move(gameName), std::move(zoneName));
|
std::unique_ptr<XModelWriter> CreateWriterForVersion6(std::ostream& stream, std::string gameName, std::string zoneName)
|
||||||
}
|
{
|
||||||
|
return std::make_unique<XModelExportWriter6>(stream, std::move(gameName), std::move(zoneName));
|
||||||
|
}
|
||||||
|
} // namespace xmodel_export
|
||||||
|
@ -1,21 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "XModel/AbstractXModelWriter.h"
|
#include "XModel/XModelWriter.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
|
||||||
class XModelExportWriter : public AbstractXModelWriter
|
namespace xmodel_export
|
||||||
{
|
{
|
||||||
public:
|
std::unique_ptr<XModelWriter> CreateWriterForVersion6(std::ostream& stream, std::string gameName, std::string zoneName);
|
||||||
XModelExportWriter() = default;
|
}
|
||||||
virtual ~XModelExportWriter() = default;
|
|
||||||
XModelExportWriter(const XModelExportWriter& other) = default;
|
|
||||||
XModelExportWriter(XModelExportWriter&& other) noexcept = default;
|
|
||||||
XModelExportWriter& operator=(const XModelExportWriter& other) = default;
|
|
||||||
XModelExportWriter& operator=(XModelExportWriter&& other) noexcept = default;
|
|
||||||
|
|
||||||
virtual void Write(std::ostream& stream) = 0;
|
|
||||||
|
|
||||||
static std::unique_ptr<XModelExportWriter> CreateWriterForVersion6(std::string gameName, std::string zoneName);
|
|
||||||
};
|
|
||||||
|
@ -24,15 +24,15 @@ namespace
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write(std::ostream& stream) override
|
void Write(const XModelCommon& xmodel) override
|
||||||
{
|
{
|
||||||
JsonRoot gltf;
|
JsonRoot gltf;
|
||||||
CreateJsonAsset(gltf.asset);
|
CreateJsonAsset(gltf.asset);
|
||||||
CreateMeshNode(gltf);
|
CreateMeshNode(gltf, xmodel);
|
||||||
CreateMesh(gltf);
|
CreateMesh(gltf, xmodel);
|
||||||
CreateSkeletonNodes(gltf);
|
CreateSkeletonNodes(gltf, xmodel);
|
||||||
CreateSkin(gltf);
|
CreateSkin(gltf, xmodel);
|
||||||
CreateScene(gltf);
|
CreateScene(gltf, xmodel);
|
||||||
|
|
||||||
const json jRoot = gltf;
|
const json jRoot = gltf;
|
||||||
m_output->EmitJson(jRoot);
|
m_output->EmitJson(jRoot);
|
||||||
@ -46,7 +46,7 @@ namespace
|
|||||||
asset.generator = GLTF_GENERATOR;
|
asset.generator = GLTF_GENERATOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateMeshNode(JsonRoot& gltf) const
|
static void CreateMeshNode(JsonRoot& gltf, const XModelCommon& xmodel)
|
||||||
{
|
{
|
||||||
JsonNode meshNode;
|
JsonNode meshNode;
|
||||||
|
|
||||||
@ -54,7 +54,7 @@ namespace
|
|||||||
meshNode.mesh = 0u;
|
meshNode.mesh = 0u;
|
||||||
|
|
||||||
// Only add skin if the model has bones
|
// Only add skin if the model has bones
|
||||||
if (!m_bones.empty())
|
if (!xmodel.m_bones.empty())
|
||||||
{
|
{
|
||||||
// We only have one skin
|
// We only have one skin
|
||||||
meshNode.skin = 0u;
|
meshNode.skin = 0u;
|
||||||
@ -66,7 +66,7 @@ namespace
|
|||||||
gltf.nodes->emplace_back(std::move(meshNode));
|
gltf.nodes->emplace_back(std::move(meshNode));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateMesh(JsonRoot& gltf) const
|
static void CreateMesh(JsonRoot& gltf, const XModelCommon& xmodel)
|
||||||
{
|
{
|
||||||
if (!gltf.meshes.has_value())
|
if (!gltf.meshes.has_value())
|
||||||
gltf.meshes.emplace();
|
gltf.meshes.emplace();
|
||||||
@ -76,19 +76,19 @@ namespace
|
|||||||
gltf.meshes->emplace_back(std::move(mesh));
|
gltf.meshes->emplace_back(std::move(mesh));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateSkeletonNodes(JsonRoot& gltf) const
|
static void CreateSkeletonNodes(JsonRoot& gltf, const XModelCommon& xmodel)
|
||||||
{
|
{
|
||||||
if (m_bones.empty())
|
if (xmodel.m_bones.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!gltf.nodes.has_value())
|
if (!gltf.nodes.has_value())
|
||||||
gltf.nodes.emplace();
|
gltf.nodes.emplace();
|
||||||
|
|
||||||
const auto boneCount = m_bones.size();
|
const auto boneCount = xmodel.m_bones.size();
|
||||||
for (auto boneIndex = 0u; boneIndex < boneCount; boneIndex++)
|
for (auto boneIndex = 0u; boneIndex < boneCount; boneIndex++)
|
||||||
{
|
{
|
||||||
JsonNode boneNode;
|
JsonNode boneNode;
|
||||||
const auto& bone = m_bones[boneIndex];
|
const auto& bone = xmodel.m_bones[boneIndex];
|
||||||
|
|
||||||
boneNode.name = bone.name;
|
boneNode.name = bone.name;
|
||||||
boneNode.translation = std::to_array(bone.globalOffset);
|
boneNode.translation = std::to_array(bone.globalOffset);
|
||||||
@ -97,7 +97,7 @@ namespace
|
|||||||
std::vector<unsigned> children;
|
std::vector<unsigned> children;
|
||||||
for (auto maybeChildIndex = 0u; maybeChildIndex < boneCount; maybeChildIndex++)
|
for (auto maybeChildIndex = 0u; maybeChildIndex < boneCount; maybeChildIndex++)
|
||||||
{
|
{
|
||||||
if (m_bones[maybeChildIndex].parentIndex == static_cast<int>(boneIndex))
|
if (xmodel.m_bones[maybeChildIndex].parentIndex == static_cast<int>(boneIndex))
|
||||||
children.emplace_back(boneIndex + NODE_FIRST_INDEX_BONES);
|
children.emplace_back(boneIndex + NODE_FIRST_INDEX_BONES);
|
||||||
}
|
}
|
||||||
if (!children.empty())
|
if (!children.empty())
|
||||||
@ -107,9 +107,9 @@ namespace
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateSkin(JsonRoot& gltf) const
|
static void CreateSkin(JsonRoot& gltf, const XModelCommon& xmodel)
|
||||||
{
|
{
|
||||||
if (m_bones.empty())
|
if (xmodel.m_bones.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!gltf.skins.has_value())
|
if (!gltf.skins.has_value())
|
||||||
@ -117,7 +117,7 @@ namespace
|
|||||||
|
|
||||||
JsonSkin skin;
|
JsonSkin skin;
|
||||||
|
|
||||||
const auto boneCount = m_bones.size();
|
const auto boneCount = xmodel.m_bones.size();
|
||||||
|
|
||||||
skin.joints.reserve(boneCount);
|
skin.joints.reserve(boneCount);
|
||||||
for (auto boneIndex = 0u; boneIndex < boneCount; boneIndex++)
|
for (auto boneIndex = 0u; boneIndex < boneCount; boneIndex++)
|
||||||
@ -126,12 +126,12 @@ namespace
|
|||||||
gltf.skins->emplace_back(std::move(skin));
|
gltf.skins->emplace_back(std::move(skin));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateScene(JsonRoot& gltf) const
|
void CreateScene(JsonRoot& gltf, const XModelCommon& xmodel) const
|
||||||
{
|
{
|
||||||
JsonScene scene;
|
JsonScene scene;
|
||||||
|
|
||||||
// Only add skin if the model has bones
|
// Only add skin if the model has bones
|
||||||
if (m_bones.empty())
|
if (xmodel.m_bones.empty())
|
||||||
scene.nodes.emplace_back(NODE_INDEX_MESH);
|
scene.nodes.emplace_back(NODE_INDEX_MESH);
|
||||||
else
|
else
|
||||||
scene.nodes.emplace_back(m_skeleton_node);
|
scene.nodes.emplace_back(m_skeleton_node);
|
||||||
|
@ -1,26 +1,24 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "GltfOutput.h"
|
#include "GltfOutput.h"
|
||||||
#include "XModel/AbstractXModelWriter.h"
|
|
||||||
#include "XModel/Gltf/JsonGltf.h"
|
#include "XModel/Gltf/JsonGltf.h"
|
||||||
|
#include "XModel/XModelWriter.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
|
||||||
namespace gltf
|
namespace gltf
|
||||||
{
|
{
|
||||||
class Writer : public AbstractXModelWriter
|
class Writer : public XModelWriter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Writer() = default;
|
Writer() = default;
|
||||||
virtual ~Writer() = default;
|
~Writer() override = default;
|
||||||
Writer(const Writer& other) = default;
|
Writer(const Writer& other) = default;
|
||||||
Writer(Writer&& other) noexcept = default;
|
Writer(Writer&& other) noexcept = default;
|
||||||
Writer& operator=(const Writer& other) = default;
|
Writer& operator=(const Writer& other) = default;
|
||||||
Writer& operator=(Writer&& other) noexcept = default;
|
Writer& operator=(Writer&& other) noexcept = default;
|
||||||
|
|
||||||
virtual void Write(std::ostream& stream) = 0;
|
|
||||||
|
|
||||||
static std::unique_ptr<Writer> CreateWriter(const Output* output, std::string gameName, std::string zoneName);
|
static std::unique_ptr<Writer> CreateWriter(const Output* output, std::string gameName, std::string zoneName);
|
||||||
};
|
};
|
||||||
} // namespace gltf
|
} // namespace gltf
|
||||||
|
18
src/ObjWriting/XModel/XModelWriter.h
Normal file
18
src/ObjWriting/XModel/XModelWriter.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "XModel/XModelCommon.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class XModelWriter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
XModelWriter() = default;
|
||||||
|
virtual ~XModelWriter() = default;
|
||||||
|
XModelWriter(const XModelWriter& other) = default;
|
||||||
|
XModelWriter(XModelWriter&& other) noexcept = default;
|
||||||
|
XModelWriter& operator=(const XModelWriter& other) = default;
|
||||||
|
XModelWriter& operator=(XModelWriter&& other) noexcept = default;
|
||||||
|
|
||||||
|
virtual void Write(const XModelCommon& xmodel) = 0;
|
||||||
|
};
|
Loading…
x
Reference in New Issue
Block a user