mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-21 00:25:44 +00:00
feat: add gltf and glb as model dumping formats
This commit is contained in:
parent
f2438bea12
commit
8a0c93d3d8
@ -3,21 +3,29 @@
|
||||
#include "Game/IW3/CommonIW3.h"
|
||||
#include "Math/Quaternion.h"
|
||||
#include "ObjWriting.h"
|
||||
#include "Utils/DistinctMapper.h"
|
||||
#include "Utils/HalfFloat.h"
|
||||
#include "Utils/QuatInt16.h"
|
||||
#include "XModel/AbstractXModelWriter.h"
|
||||
#include "XModel/Export/XModelExportWriter.h"
|
||||
#include "XModel/Gltf/GltfBinOutput.h"
|
||||
#include "XModel/Gltf/GltfTextOutput.h"
|
||||
#include "XModel/Gltf/GltfWriter.h"
|
||||
#include "XModel/Obj/ObjWriter.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include <format>
|
||||
|
||||
using namespace IW3;
|
||||
|
||||
bool AssetDumperXModel::ShouldDump(XAssetInfo<XModel>* asset)
|
||||
namespace
|
||||
{
|
||||
return !asset->m_name.empty() && asset->m_name[0] != ',';
|
||||
std::string GetFileNameForLod(const std::string& modelName, const unsigned lod, const std::string& extension)
|
||||
{
|
||||
return std::format("model_export/{}_lod{}{}", modelName, lod, extension);
|
||||
}
|
||||
|
||||
GfxImage* AssetDumperXModel::GetMaterialColorMap(const Material* material)
|
||||
GfxImage* GetMaterialColorMap(const Material* material)
|
||||
{
|
||||
std::vector<MaterialTextureDef*> potentialTextureDefs;
|
||||
|
||||
@ -43,7 +51,7 @@ GfxImage* AssetDumperXModel::GetMaterialColorMap(const Material* material)
|
||||
return potentialTextureDefs[0]->u.image;
|
||||
}
|
||||
|
||||
GfxImage* AssetDumperXModel::GetMaterialNormalMap(const Material* material)
|
||||
GfxImage* GetMaterialNormalMap(const Material* material)
|
||||
{
|
||||
std::vector<MaterialTextureDef*> potentialTextureDefs;
|
||||
|
||||
@ -69,7 +77,7 @@ GfxImage* AssetDumperXModel::GetMaterialNormalMap(const Material* material)
|
||||
return potentialTextureDefs[0]->u.image;
|
||||
}
|
||||
|
||||
GfxImage* AssetDumperXModel::GetMaterialSpecularMap(const Material* material)
|
||||
GfxImage* GetMaterialSpecularMap(const Material* material)
|
||||
{
|
||||
std::vector<MaterialTextureDef*> potentialTextureDefs;
|
||||
|
||||
@ -95,7 +103,7 @@ GfxImage* AssetDumperXModel::GetMaterialSpecularMap(const Material* material)
|
||||
return potentialTextureDefs[0]->u.image;
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddObjMaterials(ObjWriter& writer, DistinctMapper<Material*>& materialMapper, const XModel* model)
|
||||
void AddObjMaterials(ObjWriter& writer, DistinctMapper<Material*>& materialMapper, const XModel* model)
|
||||
{
|
||||
if (!model->materialHandles)
|
||||
return;
|
||||
@ -124,7 +132,7 @@ void AssetDumperXModel::AddObjMaterials(ObjWriter& writer, DistinctMapper<Materi
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddObjObjects(ObjWriter& writer, const DistinctMapper<Material*>& materialMapper, const XModel* model, const unsigned lod)
|
||||
void AddObjObjects(ObjWriter& writer, const DistinctMapper<Material*>& materialMapper, const XModel* model, const unsigned lod)
|
||||
{
|
||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||
const auto baseSurfIndex = model->lodInfo[lod].surfIndex;
|
||||
@ -139,7 +147,7 @@ void AssetDumperXModel::AddObjObjects(ObjWriter& writer, const DistinctMapper<Ma
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddObjVertices(ObjWriter& writer, const XModel* model, const unsigned lod)
|
||||
void AddObjVertices(ObjWriter& writer, const XModel* model, const unsigned lod)
|
||||
{
|
||||
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||
@ -176,7 +184,7 @@ void AssetDumperXModel::AddObjVertices(ObjWriter& writer, const XModel* model, c
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddObjFaces(ObjWriter& writer, const XModel* model, const unsigned lod)
|
||||
void AddObjFaces(ObjWriter& writer, const XModel* model, const unsigned lod)
|
||||
{
|
||||
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||
@ -203,10 +211,10 @@ void AssetDumperXModel::AddObjFaces(ObjWriter& writer, const XModel* model, cons
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpObjMat(const AssetDumpingContext& context, XAssetInfo<XModel>* asset)
|
||||
void DumpObjMat(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset)
|
||||
{
|
||||
const auto* model = asset->Asset();
|
||||
const auto matFile = context.OpenAssetFile("model_export/" + std::string(model->name) + ".mtl");
|
||||
const auto matFile = context.OpenAssetFile(std::format("model_export/{}.mtl", model->name));
|
||||
|
||||
if (!matFile)
|
||||
return;
|
||||
@ -218,13 +226,10 @@ void AssetDumperXModel::DumpObjMat(const AssetDumpingContext& context, XAssetInf
|
||||
writer.WriteMtl(*matFile);
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpObjLod(AssetDumpingContext& context, XAssetInfo<XModel>* asset, const unsigned lod)
|
||||
void DumpObjLod(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset, const unsigned lod)
|
||||
{
|
||||
const auto* model = asset->Asset();
|
||||
std::ostringstream ss;
|
||||
ss << "model_export/" << model->name << "_lod" << lod << ".OBJ";
|
||||
|
||||
const auto assetFile = context.OpenAssetFile(ss.str());
|
||||
const auto assetFile = context.OpenAssetFile(GetFileNameForLod(model->name, lod, ".obj"));
|
||||
|
||||
if (!assetFile)
|
||||
return;
|
||||
@ -237,21 +242,10 @@ void AssetDumperXModel::DumpObjLod(AssetDumpingContext& context, XAssetInfo<XMod
|
||||
AddObjVertices(writer, model, lod);
|
||||
AddObjFaces(writer, model, lod);
|
||||
|
||||
writer.WriteObj(*assetFile, std::string(model->name) + ".mtl");
|
||||
writer.WriteObj(*assetFile, std::format("{}.mtl", model->name));
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpObj(AssetDumpingContext& context, XAssetInfo<XModel>* asset)
|
||||
{
|
||||
const auto* model = asset->Asset();
|
||||
|
||||
DumpObjMat(context, asset);
|
||||
for (auto currentLod = 0u; currentLod < model->numLods; currentLod++)
|
||||
{
|
||||
DumpObjLod(context, asset, currentLod);
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddXModelBones(const AssetDumpingContext& context, AbstractXModelWriter& writer, const XModel* model)
|
||||
void AddXModelBones(const AssetDumpingContext& context, AbstractXModelWriter& writer, const XModel* model)
|
||||
{
|
||||
for (auto boneNum = 0u; boneNum < model->numBones; boneNum++)
|
||||
{
|
||||
@ -273,8 +267,8 @@ void AssetDumperXModel::AddXModelBones(const AssetDumpingContext& context, Abstr
|
||||
bone.globalOffset[0] = model->baseMat[boneNum].trans[0];
|
||||
bone.globalOffset[1] = model->baseMat[boneNum].trans[1];
|
||||
bone.globalOffset[2] = model->baseMat[boneNum].trans[2];
|
||||
bone.globalRotation =
|
||||
Quaternion32(model->baseMat[boneNum].quat[0], model->baseMat[boneNum].quat[1], model->baseMat[boneNum].quat[2], model->baseMat[boneNum].quat[3]);
|
||||
bone.globalRotation = Quaternion32(
|
||||
model->baseMat[boneNum].quat[0], model->baseMat[boneNum].quat[1], model->baseMat[boneNum].quat[2], model->baseMat[boneNum].quat[3]);
|
||||
|
||||
if (boneNum < model->numRootBones)
|
||||
{
|
||||
@ -298,7 +292,7 @@ void AssetDumperXModel::AddXModelBones(const AssetDumpingContext& context, Abstr
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddXModelMaterials(AbstractXModelWriter& writer, DistinctMapper<Material*>& materialMapper, const XModel* model)
|
||||
void AddXModelMaterials(AbstractXModelWriter& writer, DistinctMapper<Material*>& materialMapper, const XModel* model)
|
||||
{
|
||||
for (auto surfaceMaterialNum = 0; surfaceMaterialNum < model->numsurfs; surfaceMaterialNum++)
|
||||
{
|
||||
@ -318,7 +312,7 @@ void AssetDumperXModel::AddXModelMaterials(AbstractXModelWriter& writer, Distinc
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddXModelObjects(AbstractXModelWriter& writer, const XModel* model, const unsigned lod)
|
||||
void AddXModelObjects(AbstractXModelWriter& writer, const XModel* model, const unsigned lod)
|
||||
{
|
||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||
|
||||
@ -331,7 +325,7 @@ void AssetDumperXModel::AddXModelObjects(AbstractXModelWriter& writer, const XMo
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddXModelVertices(AbstractXModelWriter& writer, const XModel* model, const unsigned lod)
|
||||
void AddXModelVertices(AbstractXModelWriter& writer, const XModel* model, const unsigned lod)
|
||||
{
|
||||
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||
@ -370,7 +364,7 @@ void AssetDumperXModel::AddXModelVertices(AbstractXModelWriter& writer, const XM
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AllocateXModelBoneWeights(const XModel* model, const unsigned lod, XModelVertexBoneWeightCollection& weightCollection)
|
||||
void AllocateXModelBoneWeights(const XModel* model, const unsigned lod, XModelVertexBoneWeightCollection& weightCollection)
|
||||
{
|
||||
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||
@ -397,10 +391,7 @@ void AssetDumperXModel::AllocateXModelBoneWeights(const XModel* model, const uns
|
||||
weightCollection.weights = std::make_unique<XModelBoneWeight[]>(weightCollection.totalWeightCount);
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddXModelVertexBoneWeights(AbstractXModelWriter& writer,
|
||||
const XModel* model,
|
||||
const unsigned lod,
|
||||
XModelVertexBoneWeightCollection& weightCollection)
|
||||
void AddXModelVertexBoneWeights(AbstractXModelWriter& writer, const XModel* model, const unsigned lod, XModelVertexBoneWeightCollection& weightCollection)
|
||||
{
|
||||
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||
@ -504,7 +495,8 @@ void AssetDumperXModel::AddXModelVertexBoneWeights(AbstractXModelWriter& writer,
|
||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{boneWeightOffset, 4});
|
||||
}
|
||||
|
||||
handledVertices += surface.vertInfo.vertCount[0] + surface.vertInfo.vertCount[1] + surface.vertInfo.vertCount[2] + surface.vertInfo.vertCount[3];
|
||||
handledVertices +=
|
||||
surface.vertInfo.vertCount[0] + surface.vertInfo.vertCount[1] + surface.vertInfo.vertCount[2] + surface.vertInfo.vertCount[3];
|
||||
}
|
||||
|
||||
for (; handledVertices < surface.vertCount; handledVertices++)
|
||||
@ -514,7 +506,7 @@ void AssetDumperXModel::AddXModelVertexBoneWeights(AbstractXModelWriter& writer,
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddXModelFaces(AbstractXModelWriter& writer, const DistinctMapper<Material*>& materialMapper, const XModel* model, const unsigned lod)
|
||||
void AddXModelFaces(AbstractXModelWriter& writer, const DistinctMapper<Material*>& materialMapper, const XModel* model, const unsigned lod)
|
||||
{
|
||||
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||
@ -538,52 +530,74 @@ void AssetDumperXModel::AddXModelFaces(AbstractXModelWriter& writer, const Disti
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpXModelExportLod(const AssetDumpingContext& context, XAssetInfo<XModel>* asset, const unsigned lod)
|
||||
void PopulateXModelWriter(const AssetDumpingContext& context, const unsigned lod, const XModel* model, AbstractXModelWriter& writer)
|
||||
{
|
||||
DistinctMapper<Material*> materialMapper(model->numsurfs);
|
||||
XModelVertexBoneWeightCollection boneWeightCollection;
|
||||
AllocateXModelBoneWeights(model, lod, boneWeightCollection);
|
||||
|
||||
AddXModelBones(context, writer, model);
|
||||
AddXModelMaterials(writer, materialMapper, model);
|
||||
AddXModelObjects(writer, model, lod);
|
||||
AddXModelVertices(writer, model, lod);
|
||||
AddXModelVertexBoneWeights(writer, model, lod, boneWeightCollection);
|
||||
AddXModelFaces(writer, materialMapper, model, lod);
|
||||
}
|
||||
|
||||
void DumpXModelExportLod(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset, const unsigned lod)
|
||||
{
|
||||
const auto* model = asset->Asset();
|
||||
|
||||
std::ostringstream ss;
|
||||
ss << "model_export/" << model->name << "_lod" << lod << ".XMODEL_EXPORT";
|
||||
|
||||
const auto assetFile = context.OpenAssetFile(ss.str());
|
||||
const auto assetFile = context.OpenAssetFile(GetFileNameForLod(model->name, lod, ".XMODEL_EXPORT"));
|
||||
|
||||
if (!assetFile)
|
||||
return;
|
||||
|
||||
const auto writer = XModelExportWriter::CreateWriterForVersion6(context.m_zone->m_game->GetShortName(), context.m_zone->m_name);
|
||||
DistinctMapper<Material*> materialMapper(model->numsurfs);
|
||||
XModelVertexBoneWeightCollection boneWeightCollection;
|
||||
AllocateXModelBoneWeights(model, lod, boneWeightCollection);
|
||||
|
||||
AddXModelBones(context, *writer, model);
|
||||
AddXModelMaterials(*writer, materialMapper, model);
|
||||
AddXModelObjects(*writer, model, lod);
|
||||
AddXModelVertices(*writer, model, lod);
|
||||
AddXModelVertexBoneWeights(*writer, model, lod, boneWeightCollection);
|
||||
AddXModelFaces(*writer, materialMapper, model, lod);
|
||||
PopulateXModelWriter(context, lod, model, *writer);
|
||||
|
||||
writer->Write(*assetFile);
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpXModelExport(const AssetDumpingContext& context, XAssetInfo<XModel>* asset)
|
||||
template<typename T> void DumpGltfLod(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset, const unsigned lod, const std::string& extension)
|
||||
{
|
||||
const auto* model = asset->Asset();
|
||||
for (auto currentLod = 0u; currentLod < model->numLods; currentLod++)
|
||||
{
|
||||
DumpXModelExportLod(context, asset, currentLod);
|
||||
}
|
||||
const auto assetFile = context.OpenAssetFile(GetFileNameForLod(model->name, lod, extension));
|
||||
|
||||
if (!assetFile)
|
||||
return;
|
||||
|
||||
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);
|
||||
PopulateXModelWriter(context, lod, model, *writer);
|
||||
|
||||
writer->Write(*assetFile);
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpAsset(AssetDumpingContext& context, XAssetInfo<XModel>* asset)
|
||||
void DumpXModelSurfs(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset)
|
||||
{
|
||||
const auto* model = asset->Asset();
|
||||
|
||||
if (ObjWriting::Configuration.ModelOutputFormat == ObjWriting::Configuration_t::ModelOutputFormat_e::OBJ)
|
||||
DumpObjMat(context, asset);
|
||||
|
||||
for (auto currentLod = 0u; currentLod < model->numLods; currentLod++)
|
||||
{
|
||||
switch (ObjWriting::Configuration.ModelOutputFormat)
|
||||
{
|
||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::OBJ:
|
||||
DumpObj(context, asset);
|
||||
DumpObjLod(context, asset, currentLod);
|
||||
break;
|
||||
|
||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::XMODEL_EXPORT:
|
||||
DumpXModelExport(context, asset);
|
||||
DumpXModelExportLod(context, asset, currentLod);
|
||||
break;
|
||||
|
||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::GLTF:
|
||||
DumpGltfLod<gltf::TextOutput>(context, asset, currentLod, ".gltf");
|
||||
break;
|
||||
|
||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::GLB:
|
||||
DumpGltfLod<gltf::BinOutput>(context, asset, currentLod, ".glb");
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -591,3 +605,15 @@ void AssetDumperXModel::DumpAsset(AssetDumpingContext& context, XAssetInfo<XMode
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
bool AssetDumperXModel::ShouldDump(XAssetInfo<XModel>* asset)
|
||||
{
|
||||
return !asset->m_name.empty() && asset->m_name[0] != ',';
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpAsset(AssetDumpingContext& context, XAssetInfo<XModel>* asset)
|
||||
{
|
||||
DumpXModelSurfs(context, asset);
|
||||
}
|
||||
|
@ -2,37 +2,11 @@
|
||||
|
||||
#include "Dumping/AbstractAssetDumper.h"
|
||||
#include "Game/IW3/IW3.h"
|
||||
#include "Utils/DistinctMapper.h"
|
||||
#include "XModel/AbstractXModelWriter.h"
|
||||
#include "XModel/Obj/ObjWriter.h"
|
||||
|
||||
namespace IW3
|
||||
{
|
||||
class AssetDumperXModel final : public AbstractAssetDumper<XModel>
|
||||
{
|
||||
static GfxImage* GetMaterialColorMap(const Material* material);
|
||||
static GfxImage* GetMaterialNormalMap(const Material* material);
|
||||
static GfxImage* GetMaterialSpecularMap(const Material* material);
|
||||
|
||||
static void AddObjMaterials(ObjWriter& writer, DistinctMapper<Material*>& materialMapper, const XModel* model);
|
||||
static void AddObjObjects(ObjWriter& writer, const DistinctMapper<Material*>& materialMapper, const XModel* model, unsigned lod);
|
||||
static void AddObjVertices(ObjWriter& writer, const XModel* model, unsigned lod);
|
||||
static void AddObjFaces(ObjWriter& writer, const XModel* model, unsigned lod);
|
||||
static void DumpObjLod(AssetDumpingContext& context, XAssetInfo<XModel>* asset, unsigned lod);
|
||||
static void DumpObjMat(const AssetDumpingContext& context, XAssetInfo<XModel>* asset);
|
||||
static void DumpObj(AssetDumpingContext& context, XAssetInfo<XModel>* asset);
|
||||
|
||||
static void AddXModelBones(const AssetDumpingContext& context, AbstractXModelWriter& writer, const XModel* model);
|
||||
static void AddXModelMaterials(AbstractXModelWriter& writer, DistinctMapper<Material*>& materialMapper, const XModel* model);
|
||||
static void AddXModelObjects(AbstractXModelWriter& writer, const XModel* model, unsigned lod);
|
||||
static void AddXModelVertices(AbstractXModelWriter& writer, const XModel* model, unsigned lod);
|
||||
static void AllocateXModelBoneWeights(const XModel* model, unsigned lod, XModelVertexBoneWeightCollection& weightCollection);
|
||||
static void
|
||||
AddXModelVertexBoneWeights(AbstractXModelWriter& writer, const XModel* model, unsigned lod, XModelVertexBoneWeightCollection& weightCollection);
|
||||
static void AddXModelFaces(AbstractXModelWriter& writer, const DistinctMapper<Material*>& materialMapper, const XModel* model, unsigned lod);
|
||||
static void DumpXModelExportLod(const AssetDumpingContext& context, XAssetInfo<XModel>* asset, unsigned lod);
|
||||
static void DumpXModelExport(const AssetDumpingContext& context, XAssetInfo<XModel>* asset);
|
||||
|
||||
protected:
|
||||
bool ShouldDump(XAssetInfo<XModel>* asset) override;
|
||||
void DumpAsset(AssetDumpingContext& context, XAssetInfo<XModel>* asset) override;
|
||||
|
@ -3,15 +3,22 @@
|
||||
#include "Game/IW4/CommonIW4.h"
|
||||
#include "Math/Quaternion.h"
|
||||
#include "ObjWriting.h"
|
||||
#include "Utils/DistinctMapper.h"
|
||||
#include "Utils/HalfFloat.h"
|
||||
#include "Utils/QuatInt16.h"
|
||||
#include "XModel/AbstractXModelWriter.h"
|
||||
#include "XModel/Export/XModelExportWriter.h"
|
||||
#include "XModel/Gltf/GltfBinOutput.h"
|
||||
#include "XModel/Gltf/GltfTextOutput.h"
|
||||
#include "XModel/Gltf/GltfWriter.h"
|
||||
#include "XModel/Obj/ObjWriter.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <format>
|
||||
|
||||
using namespace IW4;
|
||||
|
||||
namespace IW4
|
||||
namespace
|
||||
{
|
||||
class SurfsDumpingZoneState final : public IZoneAssetDumperState
|
||||
{
|
||||
@ -20,21 +27,15 @@ namespace IW4
|
||||
public:
|
||||
bool ShouldDumpTechnique(const XModelSurfs* surfs)
|
||||
{
|
||||
if (m_dumped_surfs.find(surfs) != m_dumped_surfs.end())
|
||||
if (m_dumped_surfs.contains(surfs))
|
||||
return false;
|
||||
|
||||
m_dumped_surfs.emplace(surfs);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
} // namespace IW4
|
||||
|
||||
bool AssetDumperXModel::ShouldDump(XAssetInfo<XModel>* asset)
|
||||
{
|
||||
return !asset->m_name.empty() && asset->m_name[0] != ',';
|
||||
}
|
||||
|
||||
GfxImage* AssetDumperXModel::GetMaterialColorMap(const Material* material)
|
||||
GfxImage* GetMaterialColorMap(const Material* material)
|
||||
{
|
||||
std::vector<MaterialTextureDef*> potentialTextureDefs;
|
||||
|
||||
@ -60,7 +61,7 @@ GfxImage* AssetDumperXModel::GetMaterialColorMap(const Material* material)
|
||||
return potentialTextureDefs[0]->u.image;
|
||||
}
|
||||
|
||||
GfxImage* AssetDumperXModel::GetMaterialNormalMap(const Material* material)
|
||||
GfxImage* GetMaterialNormalMap(const Material* material)
|
||||
{
|
||||
std::vector<MaterialTextureDef*> potentialTextureDefs;
|
||||
|
||||
@ -86,7 +87,7 @@ GfxImage* AssetDumperXModel::GetMaterialNormalMap(const Material* material)
|
||||
return potentialTextureDefs[0]->u.image;
|
||||
}
|
||||
|
||||
GfxImage* AssetDumperXModel::GetMaterialSpecularMap(const Material* material)
|
||||
GfxImage* GetMaterialSpecularMap(const Material* material)
|
||||
{
|
||||
std::vector<MaterialTextureDef*> potentialTextureDefs;
|
||||
|
||||
@ -112,7 +113,7 @@ GfxImage* AssetDumperXModel::GetMaterialSpecularMap(const Material* material)
|
||||
return potentialTextureDefs[0]->u.image;
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddObjMaterials(ObjWriter& writer, DistinctMapper<Material*>& materialMapper, const XModel* model)
|
||||
void AddObjMaterials(ObjWriter& writer, DistinctMapper<Material*>& materialMapper, const XModel* model)
|
||||
{
|
||||
if (!model->materialHandles)
|
||||
return;
|
||||
@ -141,7 +142,7 @@ void AssetDumperXModel::AddObjMaterials(ObjWriter& writer, DistinctMapper<Materi
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddObjObjects(ObjWriter& writer, const DistinctMapper<Material*>& materialMapper, const XModelSurfs* modelSurfs, int baseSurfaceIndex)
|
||||
void AddObjObjects(ObjWriter& writer, const DistinctMapper<Material*>& materialMapper, const XModelSurfs* modelSurfs, int baseSurfaceIndex)
|
||||
{
|
||||
for (auto surfIndex = 0u; surfIndex < modelSurfs->numsurfs; surfIndex++)
|
||||
{
|
||||
@ -153,7 +154,7 @@ void AssetDumperXModel::AddObjObjects(ObjWriter& writer, const DistinctMapper<Ma
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddObjVertices(ObjWriter& writer, const XModelSurfs* modelSurfs)
|
||||
void AddObjVertices(ObjWriter& writer, const XModelSurfs* modelSurfs)
|
||||
{
|
||||
for (auto surfIndex = 0u; surfIndex < modelSurfs->numsurfs; surfIndex++)
|
||||
{
|
||||
@ -187,7 +188,7 @@ void AssetDumperXModel::AddObjVertices(ObjWriter& writer, const XModelSurfs* mod
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddObjFaces(ObjWriter& writer, const XModelSurfs* modelSurfs)
|
||||
void AddObjFaces(ObjWriter& writer, const XModelSurfs* modelSurfs)
|
||||
{
|
||||
for (auto surfIndex = 0u; surfIndex < modelSurfs->numsurfs; surfIndex++)
|
||||
{
|
||||
@ -211,10 +212,10 @@ void AssetDumperXModel::AddObjFaces(ObjWriter& writer, const XModelSurfs* modelS
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpObjMat(const AssetDumpingContext& context, XAssetInfo<XModel>* asset)
|
||||
void DumpObjMat(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset)
|
||||
{
|
||||
const auto* model = asset->Asset();
|
||||
const auto matFile = context.OpenAssetFile("model_export/" + std::string(model->name) + ".mtl");
|
||||
const auto matFile = context.OpenAssetFile(std::format("model_export/{}.mtl", model->name));
|
||||
|
||||
if (!matFile)
|
||||
return;
|
||||
@ -226,7 +227,7 @@ void AssetDumperXModel::DumpObjMat(const AssetDumpingContext& context, XAssetInf
|
||||
writer.WriteMtl(*matFile);
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpObjLod(const AssetDumpingContext& context, XAssetInfo<XModel>* asset, const unsigned lod)
|
||||
void DumpObjLod(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset, const unsigned lod)
|
||||
{
|
||||
const auto* model = asset->Asset();
|
||||
const auto* modelSurfs = model->lodInfo[lod].modelSurfs;
|
||||
@ -234,7 +235,7 @@ void AssetDumperXModel::DumpObjLod(const AssetDumpingContext& context, XAssetInf
|
||||
if (modelSurfs->name[0] == ',' || modelSurfs->surfs == nullptr)
|
||||
return;
|
||||
|
||||
const auto assetFile = context.OpenAssetFile("model_export/" + std::string(modelSurfs->name) + ".obj");
|
||||
const auto assetFile = context.OpenAssetFile(std::format("model_export/{}.obj", modelSurfs->name));
|
||||
|
||||
if (!assetFile)
|
||||
return;
|
||||
@ -247,25 +248,10 @@ void AssetDumperXModel::DumpObjLod(const AssetDumpingContext& context, XAssetInf
|
||||
AddObjVertices(writer, modelSurfs);
|
||||
AddObjFaces(writer, modelSurfs);
|
||||
|
||||
writer.WriteObj(*assetFile, std::string(model->name) + ".mtl");
|
||||
writer.WriteObj(*assetFile, std::format("{}.mtl", model->name));
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpObj(AssetDumpingContext& context, XAssetInfo<XModel>* asset)
|
||||
{
|
||||
const auto* model = asset->Asset();
|
||||
auto* surfZoneState = context.GetZoneAssetDumperState<SurfsDumpingZoneState>();
|
||||
|
||||
DumpObjMat(context, asset);
|
||||
for (auto currentLod = 0u; currentLod < model->numLods; currentLod++)
|
||||
{
|
||||
if (!model->lodInfo[currentLod].modelSurfs || !surfZoneState->ShouldDumpTechnique(model->lodInfo[currentLod].modelSurfs))
|
||||
continue;
|
||||
|
||||
DumpObjLod(context, asset, currentLod);
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddXModelBones(const AssetDumpingContext& context, AbstractXModelWriter& writer, const XModel* model)
|
||||
void AddXModelBones(const AssetDumpingContext& context, AbstractXModelWriter& writer, const XModel* model)
|
||||
{
|
||||
for (auto boneNum = 0u; boneNum < model->numBones; boneNum++)
|
||||
{
|
||||
@ -287,8 +273,8 @@ void AssetDumperXModel::AddXModelBones(const AssetDumpingContext& context, Abstr
|
||||
bone.globalOffset[0] = model->baseMat[boneNum].trans[0];
|
||||
bone.globalOffset[1] = model->baseMat[boneNum].trans[1];
|
||||
bone.globalOffset[2] = model->baseMat[boneNum].trans[2];
|
||||
bone.globalRotation =
|
||||
Quaternion32(model->baseMat[boneNum].quat[0], model->baseMat[boneNum].quat[1], model->baseMat[boneNum].quat[2], model->baseMat[boneNum].quat[3]);
|
||||
bone.globalRotation = Quaternion32(
|
||||
model->baseMat[boneNum].quat[0], model->baseMat[boneNum].quat[1], model->baseMat[boneNum].quat[2], model->baseMat[boneNum].quat[3]);
|
||||
|
||||
if (boneNum < model->numRootBones)
|
||||
{
|
||||
@ -312,7 +298,7 @@ void AssetDumperXModel::AddXModelBones(const AssetDumpingContext& context, Abstr
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddXModelMaterials(AbstractXModelWriter& writer, DistinctMapper<Material*>& materialMapper, const XModel* model)
|
||||
void AddXModelMaterials(AbstractXModelWriter& writer, DistinctMapper<Material*>& materialMapper, const XModel* model)
|
||||
{
|
||||
for (auto surfaceMaterialNum = 0; surfaceMaterialNum < model->numsurfs; surfaceMaterialNum++)
|
||||
{
|
||||
@ -332,7 +318,7 @@ void AssetDumperXModel::AddXModelMaterials(AbstractXModelWriter& writer, Distinc
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddXModelObjects(AbstractXModelWriter& writer, const XModelSurfs* modelSurfs)
|
||||
void AddXModelObjects(AbstractXModelWriter& writer, const XModelSurfs* modelSurfs)
|
||||
{
|
||||
for (auto surfIndex = 0u; surfIndex < modelSurfs->numsurfs; surfIndex++)
|
||||
{
|
||||
@ -343,7 +329,7 @@ void AssetDumperXModel::AddXModelObjects(AbstractXModelWriter& writer, const XMo
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddXModelVertices(AbstractXModelWriter& writer, const XModelSurfs* modelSurfs)
|
||||
void AddXModelVertices(AbstractXModelWriter& writer, const XModelSurfs* modelSurfs)
|
||||
{
|
||||
for (auto surfIndex = 0u; surfIndex < modelSurfs->numsurfs; surfIndex++)
|
||||
{
|
||||
@ -379,7 +365,7 @@ void AssetDumperXModel::AddXModelVertices(AbstractXModelWriter& writer, const XM
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AllocateXModelBoneWeights(const XModelSurfs* modelSurfs, XModelVertexBoneWeightCollection& weightCollection)
|
||||
void AllocateXModelBoneWeights(const XModelSurfs* modelSurfs, XModelVertexBoneWeightCollection& weightCollection)
|
||||
{
|
||||
weightCollection.totalWeightCount = 0u;
|
||||
for (auto surfIndex = 0u; surfIndex < modelSurfs->numsurfs; surfIndex++)
|
||||
@ -403,9 +389,7 @@ void AssetDumperXModel::AllocateXModelBoneWeights(const XModelSurfs* modelSurfs,
|
||||
weightCollection.weights = std::make_unique<XModelBoneWeight[]>(weightCollection.totalWeightCount);
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddXModelVertexBoneWeights(AbstractXModelWriter& writer,
|
||||
const XModelSurfs* modelSurfs,
|
||||
XModelVertexBoneWeightCollection& weightCollection)
|
||||
void AddXModelVertexBoneWeights(AbstractXModelWriter& writer, const XModelSurfs* modelSurfs, XModelVertexBoneWeightCollection& weightCollection)
|
||||
{
|
||||
size_t weightOffset = 0u;
|
||||
|
||||
@ -506,7 +490,8 @@ void AssetDumperXModel::AddXModelVertexBoneWeights(AbstractXModelWriter& writer,
|
||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{boneWeightOffset, 4});
|
||||
}
|
||||
|
||||
handledVertices += surface.vertInfo.vertCount[0] + surface.vertInfo.vertCount[1] + surface.vertInfo.vertCount[2] + surface.vertInfo.vertCount[3];
|
||||
handledVertices +=
|
||||
surface.vertInfo.vertCount[0] + surface.vertInfo.vertCount[1] + surface.vertInfo.vertCount[2] + surface.vertInfo.vertCount[3];
|
||||
}
|
||||
|
||||
for (; handledVertices < surface.vertCount; handledVertices++)
|
||||
@ -516,10 +501,8 @@ void AssetDumperXModel::AddXModelVertexBoneWeights(AbstractXModelWriter& writer,
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddXModelFaces(AbstractXModelWriter& writer,
|
||||
const DistinctMapper<Material*>& materialMapper,
|
||||
const XModelSurfs* modelSurfs,
|
||||
const int baseSurfaceIndex)
|
||||
void
|
||||
AddXModelFaces(AbstractXModelWriter& writer, const DistinctMapper<Material*>& materialMapper, const XModelSurfs* modelSurfs, const int baseSurfaceIndex)
|
||||
{
|
||||
for (auto surfIndex = 0u; surfIndex < modelSurfs->numsurfs; surfIndex++)
|
||||
{
|
||||
@ -539,56 +522,78 @@ void AssetDumperXModel::AddXModelFaces(AbstractXModelWriter& writer,
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpXModelExportLod(const AssetDumpingContext& context, XAssetInfo<XModel>* asset, const unsigned lod)
|
||||
void PopulateXModelWriter(const AssetDumpingContext& context, const unsigned lod, const XModel* model, AbstractXModelWriter& writer)
|
||||
{
|
||||
const auto* modelSurfs = model->lodInfo[lod].modelSurfs;
|
||||
|
||||
DistinctMapper<Material*> materialMapper(model->numsurfs);
|
||||
XModelVertexBoneWeightCollection boneWeightCollection;
|
||||
AllocateXModelBoneWeights(modelSurfs, boneWeightCollection);
|
||||
|
||||
AddXModelBones(context, writer, model);
|
||||
AddXModelMaterials(writer, materialMapper, model);
|
||||
AddXModelObjects(writer, modelSurfs);
|
||||
AddXModelVertices(writer, modelSurfs);
|
||||
AddXModelVertexBoneWeights(writer, modelSurfs, boneWeightCollection);
|
||||
AddXModelFaces(writer, materialMapper, modelSurfs, model->lodInfo[lod].surfIndex);
|
||||
}
|
||||
|
||||
void DumpXModelExportLod(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset, const unsigned lod)
|
||||
{
|
||||
const auto* model = asset->Asset();
|
||||
const auto* modelSurfs = model->lodInfo[lod].modelSurfs;
|
||||
|
||||
if (modelSurfs->name[0] == ',' || modelSurfs->surfs == nullptr)
|
||||
return;
|
||||
|
||||
const auto assetFile = context.OpenAssetFile("model_export/" + std::string(modelSurfs->name) + ".XMODEL_EXPORT");
|
||||
const auto assetFile = context.OpenAssetFile(std::format("model_export/{}.XMODEL_EXPORT", modelSurfs->name));
|
||||
|
||||
if (!assetFile)
|
||||
return;
|
||||
|
||||
const auto writer = XModelExportWriter::CreateWriterForVersion6(context.m_zone->m_game->GetShortName(), context.m_zone->m_name);
|
||||
DistinctMapper<Material*> materialMapper(model->numsurfs);
|
||||
XModelVertexBoneWeightCollection boneWeightCollection;
|
||||
AllocateXModelBoneWeights(modelSurfs, boneWeightCollection);
|
||||
|
||||
AddXModelBones(context, *writer, model);
|
||||
AddXModelMaterials(*writer, materialMapper, model);
|
||||
AddXModelObjects(*writer, modelSurfs);
|
||||
AddXModelVertices(*writer, modelSurfs);
|
||||
AddXModelVertexBoneWeights(*writer, modelSurfs, boneWeightCollection);
|
||||
AddXModelFaces(*writer, materialMapper, modelSurfs, model->lodInfo[lod].surfIndex);
|
||||
PopulateXModelWriter(context, lod, model, *writer);
|
||||
|
||||
writer->Write(*assetFile);
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpXModelExport(AssetDumpingContext& context, XAssetInfo<XModel>* asset)
|
||||
template<typename T> void DumpGltfLod(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset, const unsigned lod, const std::string& extension)
|
||||
{
|
||||
auto* surfZoneState = context.GetZoneAssetDumperState<SurfsDumpingZoneState>();
|
||||
const auto* model = asset->Asset();
|
||||
for (auto currentLod = 0u; currentLod < model->numLods; currentLod++)
|
||||
{
|
||||
if (!model->lodInfo[currentLod].modelSurfs || !surfZoneState->ShouldDumpTechnique(model->lodInfo[currentLod].modelSurfs))
|
||||
continue;
|
||||
DumpXModelExportLod(context, asset, currentLod);
|
||||
}
|
||||
const auto* modelSurfs = model->lodInfo[lod].modelSurfs;
|
||||
const auto assetFile = context.OpenAssetFile(std::format("model_export/{}{}", modelSurfs->name, extension));
|
||||
|
||||
if (!assetFile)
|
||||
return;
|
||||
|
||||
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);
|
||||
PopulateXModelWriter(context, lod, model, *writer);
|
||||
|
||||
writer->Write(*assetFile);
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpAsset(AssetDumpingContext& context, XAssetInfo<XModel>* asset)
|
||||
void DumpXModelSurfs(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset)
|
||||
{
|
||||
const auto* model = asset->Asset();
|
||||
|
||||
if (ObjWriting::Configuration.ModelOutputFormat == ObjWriting::Configuration_t::ModelOutputFormat_e::OBJ)
|
||||
DumpObjMat(context, asset);
|
||||
|
||||
for (auto currentLod = 0u; currentLod < model->numLods; currentLod++)
|
||||
{
|
||||
switch (ObjWriting::Configuration.ModelOutputFormat)
|
||||
{
|
||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::OBJ:
|
||||
DumpObj(context, asset);
|
||||
DumpObjLod(context, asset, currentLod);
|
||||
break;
|
||||
|
||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::XMODEL_EXPORT:
|
||||
DumpXModelExport(context, asset);
|
||||
DumpXModelExportLod(context, asset, currentLod);
|
||||
break;
|
||||
|
||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::GLTF:
|
||||
DumpGltfLod<gltf::TextOutput>(context, asset, currentLod, ".gltf");
|
||||
break;
|
||||
|
||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::GLB:
|
||||
DumpGltfLod<gltf::BinOutput>(context, asset, currentLod, ".glb");
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -596,3 +601,15 @@ void AssetDumperXModel::DumpAsset(AssetDumpingContext& context, XAssetInfo<XMode
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
bool AssetDumperXModel::ShouldDump(XAssetInfo<XModel>* asset)
|
||||
{
|
||||
return !asset->m_name.empty() && asset->m_name[0] != ',';
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpAsset(AssetDumpingContext& context, XAssetInfo<XModel>* asset)
|
||||
{
|
||||
DumpXModelSurfs(context, asset);
|
||||
}
|
||||
|
@ -2,37 +2,11 @@
|
||||
|
||||
#include "Dumping/AbstractAssetDumper.h"
|
||||
#include "Game/IW4/IW4.h"
|
||||
#include "Utils/DistinctMapper.h"
|
||||
#include "XModel/AbstractXModelWriter.h"
|
||||
#include "XModel/Obj/ObjWriter.h"
|
||||
|
||||
namespace IW4
|
||||
{
|
||||
class AssetDumperXModel final : public AbstractAssetDumper<XModel>
|
||||
{
|
||||
static GfxImage* GetMaterialColorMap(const Material* material);
|
||||
static GfxImage* GetMaterialNormalMap(const Material* material);
|
||||
static GfxImage* GetMaterialSpecularMap(const Material* material);
|
||||
|
||||
static void AddObjMaterials(ObjWriter& writer, DistinctMapper<Material*>& materialMapper, const XModel* model);
|
||||
static void AddObjObjects(ObjWriter& writer, const DistinctMapper<Material*>& materialMapper, const XModelSurfs* modelSurfs, int baseSurfaceIndex);
|
||||
static void AddObjVertices(ObjWriter& writer, const XModelSurfs* modelSurfs);
|
||||
static void AddObjFaces(ObjWriter& writer, const XModelSurfs* modelSurfs);
|
||||
static void DumpObjLod(const AssetDumpingContext& context, XAssetInfo<XModel>* asset, const unsigned lod);
|
||||
static void DumpObjMat(const AssetDumpingContext& context, XAssetInfo<XModel>* asset);
|
||||
static void DumpObj(AssetDumpingContext& context, XAssetInfo<XModel>* asset);
|
||||
|
||||
static void AddXModelBones(const AssetDumpingContext& context, AbstractXModelWriter& writer, const XModel* model);
|
||||
static void AddXModelMaterials(AbstractXModelWriter& writer, DistinctMapper<Material*>& materialMapper, const XModel* model);
|
||||
static void AddXModelObjects(AbstractXModelWriter& writer, const XModelSurfs* modelSurfs);
|
||||
static void AddXModelVertices(AbstractXModelWriter& writer, const XModelSurfs* modelSurfs);
|
||||
static void AllocateXModelBoneWeights(const XModelSurfs* modelSurfs, XModelVertexBoneWeightCollection& weightCollection);
|
||||
static void AddXModelVertexBoneWeights(AbstractXModelWriter& writer, const XModelSurfs* modelSurfs, XModelVertexBoneWeightCollection& weightCollection);
|
||||
static void
|
||||
AddXModelFaces(AbstractXModelWriter& writer, const DistinctMapper<Material*>& materialMapper, const XModelSurfs* modelSurfs, int baseSurfaceIndex);
|
||||
static void DumpXModelExportLod(const AssetDumpingContext& context, XAssetInfo<XModel>* asset, unsigned lod);
|
||||
static void DumpXModelExport(AssetDumpingContext& context, XAssetInfo<XModel>* asset);
|
||||
|
||||
protected:
|
||||
bool ShouldDump(XAssetInfo<XModel>* asset) override;
|
||||
void DumpAsset(AssetDumpingContext& context, XAssetInfo<XModel>* asset) override;
|
||||
|
@ -3,15 +3,22 @@
|
||||
#include "Game/IW5/CommonIW5.h"
|
||||
#include "Math/Quaternion.h"
|
||||
#include "ObjWriting.h"
|
||||
#include "Utils/DistinctMapper.h"
|
||||
#include "Utils/HalfFloat.h"
|
||||
#include "Utils/QuatInt16.h"
|
||||
#include "XModel/AbstractXModelWriter.h"
|
||||
#include "XModel/Export/XModelExportWriter.h"
|
||||
#include "XModel/Gltf/GltfBinOutput.h"
|
||||
#include "XModel/Gltf/GltfTextOutput.h"
|
||||
#include "XModel/Gltf/GltfWriter.h"
|
||||
#include "XModel/Obj/ObjWriter.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <format>
|
||||
|
||||
using namespace IW5;
|
||||
|
||||
namespace IW5
|
||||
namespace
|
||||
{
|
||||
class SurfsDumpingZoneState final : public IZoneAssetDumperState
|
||||
{
|
||||
@ -20,21 +27,15 @@ namespace IW5
|
||||
public:
|
||||
bool ShouldDumpTechnique(const XModelSurfs* surfs)
|
||||
{
|
||||
if (m_dumped_surfs.find(surfs) != m_dumped_surfs.end())
|
||||
if (m_dumped_surfs.contains(surfs))
|
||||
return false;
|
||||
|
||||
m_dumped_surfs.emplace(surfs);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
} // namespace IW5
|
||||
|
||||
bool AssetDumperXModel::ShouldDump(XAssetInfo<XModel>* asset)
|
||||
{
|
||||
return !asset->m_name.empty() && asset->m_name[0] != ',';
|
||||
}
|
||||
|
||||
GfxImage* AssetDumperXModel::GetMaterialColorMap(const Material* material)
|
||||
GfxImage* GetMaterialColorMap(const Material* material)
|
||||
{
|
||||
std::vector<MaterialTextureDef*> potentialTextureDefs;
|
||||
|
||||
@ -60,7 +61,7 @@ GfxImage* AssetDumperXModel::GetMaterialColorMap(const Material* material)
|
||||
return potentialTextureDefs[0]->u.image;
|
||||
}
|
||||
|
||||
GfxImage* AssetDumperXModel::GetMaterialNormalMap(const Material* material)
|
||||
GfxImage* GetMaterialNormalMap(const Material* material)
|
||||
{
|
||||
std::vector<MaterialTextureDef*> potentialTextureDefs;
|
||||
|
||||
@ -86,7 +87,7 @@ GfxImage* AssetDumperXModel::GetMaterialNormalMap(const Material* material)
|
||||
return potentialTextureDefs[0]->u.image;
|
||||
}
|
||||
|
||||
GfxImage* AssetDumperXModel::GetMaterialSpecularMap(const Material* material)
|
||||
GfxImage* GetMaterialSpecularMap(const Material* material)
|
||||
{
|
||||
std::vector<MaterialTextureDef*> potentialTextureDefs;
|
||||
|
||||
@ -112,7 +113,7 @@ GfxImage* AssetDumperXModel::GetMaterialSpecularMap(const Material* material)
|
||||
return potentialTextureDefs[0]->u.image;
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddObjMaterials(ObjWriter& writer, DistinctMapper<Material*>& materialMapper, const XModel* model)
|
||||
void AddObjMaterials(ObjWriter& writer, DistinctMapper<Material*>& materialMapper, const XModel* model)
|
||||
{
|
||||
if (!model->materialHandles)
|
||||
return;
|
||||
@ -140,7 +141,7 @@ void AssetDumperXModel::AddObjMaterials(ObjWriter& writer, DistinctMapper<Materi
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddObjObjects(ObjWriter& writer, const DistinctMapper<Material*>& materialMapper, const XModelSurfs* modelSurfs, int baseSurfaceIndex)
|
||||
void AddObjObjects(ObjWriter& writer, const DistinctMapper<Material*>& materialMapper, const XModelSurfs* modelSurfs, int baseSurfaceIndex)
|
||||
{
|
||||
for (auto surfIndex = 0u; surfIndex < modelSurfs->numsurfs; surfIndex++)
|
||||
{
|
||||
@ -152,7 +153,7 @@ void AssetDumperXModel::AddObjObjects(ObjWriter& writer, const DistinctMapper<Ma
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddObjVertices(ObjWriter& writer, const XModelSurfs* modelSurfs)
|
||||
void AddObjVertices(ObjWriter& writer, const XModelSurfs* modelSurfs)
|
||||
{
|
||||
for (auto surfIndex = 0u; surfIndex < modelSurfs->numsurfs; surfIndex++)
|
||||
{
|
||||
@ -186,7 +187,7 @@ void AssetDumperXModel::AddObjVertices(ObjWriter& writer, const XModelSurfs* mod
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddObjFaces(ObjWriter& writer, const XModelSurfs* modelSurfs)
|
||||
void AddObjFaces(ObjWriter& writer, const XModelSurfs* modelSurfs)
|
||||
{
|
||||
for (auto surfIndex = 0u; surfIndex < modelSurfs->numsurfs; surfIndex++)
|
||||
{
|
||||
@ -210,10 +211,10 @@ void AssetDumperXModel::AddObjFaces(ObjWriter& writer, const XModelSurfs* modelS
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpObjMat(const AssetDumpingContext& context, XAssetInfo<XModel>* asset)
|
||||
void DumpObjMat(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset)
|
||||
{
|
||||
const auto* model = asset->Asset();
|
||||
const auto matFile = context.OpenAssetFile("model_export/" + std::string(model->name) + ".mtl");
|
||||
const auto matFile = context.OpenAssetFile(std::format("model_export/{}.mtl", model->name));
|
||||
|
||||
if (!matFile)
|
||||
return;
|
||||
@ -225,7 +226,7 @@ void AssetDumperXModel::DumpObjMat(const AssetDumpingContext& context, XAssetInf
|
||||
writer.WriteMtl(*matFile);
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpObjLod(const AssetDumpingContext& context, XAssetInfo<XModel>* asset, const unsigned lod)
|
||||
void DumpObjLod(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset, const unsigned lod)
|
||||
{
|
||||
const auto* model = asset->Asset();
|
||||
const auto* modelSurfs = model->lodInfo[lod].modelSurfs;
|
||||
@ -233,7 +234,7 @@ void AssetDumperXModel::DumpObjLod(const AssetDumpingContext& context, XAssetInf
|
||||
if (modelSurfs->name[0] == ',' || modelSurfs->surfs == nullptr)
|
||||
return;
|
||||
|
||||
const auto assetFile = context.OpenAssetFile("model_export/" + std::string(modelSurfs->name) + ".obj");
|
||||
const auto assetFile = context.OpenAssetFile(std::format("model_export/{}.obj", modelSurfs->name));
|
||||
|
||||
if (!assetFile)
|
||||
return;
|
||||
@ -246,25 +247,10 @@ void AssetDumperXModel::DumpObjLod(const AssetDumpingContext& context, XAssetInf
|
||||
AddObjVertices(writer, modelSurfs);
|
||||
AddObjFaces(writer, modelSurfs);
|
||||
|
||||
writer.WriteObj(*assetFile, std::string(model->name) + ".mtl");
|
||||
writer.WriteObj(*assetFile, std::format("{}.mtl", model->name));
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpObj(AssetDumpingContext& context, XAssetInfo<XModel>* asset)
|
||||
{
|
||||
const auto* model = asset->Asset();
|
||||
auto* surfZoneState = context.GetZoneAssetDumperState<SurfsDumpingZoneState>();
|
||||
|
||||
DumpObjMat(context, asset);
|
||||
for (auto currentLod = 0u; currentLod < model->numLods; currentLod++)
|
||||
{
|
||||
if (!model->lodInfo[currentLod].modelSurfs || !surfZoneState->ShouldDumpTechnique(model->lodInfo[currentLod].modelSurfs))
|
||||
continue;
|
||||
|
||||
DumpObjLod(context, asset, currentLod);
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddXModelBones(const AssetDumpingContext& context, AbstractXModelWriter& writer, const XModel* model)
|
||||
void AddXModelBones(const AssetDumpingContext& context, AbstractXModelWriter& writer, const XModel* model)
|
||||
{
|
||||
for (auto boneNum = 0u; boneNum < model->numBones; boneNum++)
|
||||
{
|
||||
@ -286,8 +272,8 @@ void AssetDumperXModel::AddXModelBones(const AssetDumpingContext& context, Abstr
|
||||
bone.globalOffset[0] = model->baseMat[boneNum].trans[0];
|
||||
bone.globalOffset[1] = model->baseMat[boneNum].trans[1];
|
||||
bone.globalOffset[2] = model->baseMat[boneNum].trans[2];
|
||||
bone.globalRotation =
|
||||
Quaternion32(model->baseMat[boneNum].quat[0], model->baseMat[boneNum].quat[1], model->baseMat[boneNum].quat[2], model->baseMat[boneNum].quat[3]);
|
||||
bone.globalRotation = Quaternion32(
|
||||
model->baseMat[boneNum].quat[0], model->baseMat[boneNum].quat[1], model->baseMat[boneNum].quat[2], model->baseMat[boneNum].quat[3]);
|
||||
|
||||
if (boneNum < model->numRootBones)
|
||||
{
|
||||
@ -311,7 +297,7 @@ void AssetDumperXModel::AddXModelBones(const AssetDumpingContext& context, Abstr
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddXModelMaterials(AbstractXModelWriter& writer, DistinctMapper<Material*>& materialMapper, const XModel* model)
|
||||
void AddXModelMaterials(AbstractXModelWriter& writer, DistinctMapper<Material*>& materialMapper, const XModel* model)
|
||||
{
|
||||
for (auto surfaceMaterialNum = 0; surfaceMaterialNum < model->numsurfs; surfaceMaterialNum++)
|
||||
{
|
||||
@ -331,7 +317,7 @@ void AssetDumperXModel::AddXModelMaterials(AbstractXModelWriter& writer, Distinc
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddXModelObjects(AbstractXModelWriter& writer, const XModelSurfs* modelSurfs)
|
||||
void AddXModelObjects(AbstractXModelWriter& writer, const XModelSurfs* modelSurfs)
|
||||
{
|
||||
for (auto surfIndex = 0u; surfIndex < modelSurfs->numsurfs; surfIndex++)
|
||||
{
|
||||
@ -342,7 +328,7 @@ void AssetDumperXModel::AddXModelObjects(AbstractXModelWriter& writer, const XMo
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddXModelVertices(AbstractXModelWriter& writer, const XModelSurfs* modelSurfs)
|
||||
void AddXModelVertices(AbstractXModelWriter& writer, const XModelSurfs* modelSurfs)
|
||||
{
|
||||
for (auto surfIndex = 0u; surfIndex < modelSurfs->numsurfs; surfIndex++)
|
||||
{
|
||||
@ -378,7 +364,7 @@ void AssetDumperXModel::AddXModelVertices(AbstractXModelWriter& writer, const XM
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AllocateXModelBoneWeights(const XModelSurfs* modelSurfs, XModelVertexBoneWeightCollection& weightCollection)
|
||||
void AllocateXModelBoneWeights(const XModelSurfs* modelSurfs, XModelVertexBoneWeightCollection& weightCollection)
|
||||
{
|
||||
weightCollection.totalWeightCount = 0u;
|
||||
for (auto surfIndex = 0u; surfIndex < modelSurfs->numsurfs; surfIndex++)
|
||||
@ -402,9 +388,7 @@ void AssetDumperXModel::AllocateXModelBoneWeights(const XModelSurfs* modelSurfs,
|
||||
weightCollection.weights = std::make_unique<XModelBoneWeight[]>(weightCollection.totalWeightCount);
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddXModelVertexBoneWeights(AbstractXModelWriter& writer,
|
||||
const XModelSurfs* modelSurfs,
|
||||
XModelVertexBoneWeightCollection& weightCollection)
|
||||
void AddXModelVertexBoneWeights(AbstractXModelWriter& writer, const XModelSurfs* modelSurfs, XModelVertexBoneWeightCollection& weightCollection)
|
||||
{
|
||||
size_t weightOffset = 0u;
|
||||
|
||||
@ -505,7 +489,8 @@ void AssetDumperXModel::AddXModelVertexBoneWeights(AbstractXModelWriter& writer,
|
||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{boneWeightOffset, 4});
|
||||
}
|
||||
|
||||
handledVertices += surface.vertInfo.vertCount[0] + surface.vertInfo.vertCount[1] + surface.vertInfo.vertCount[2] + surface.vertInfo.vertCount[3];
|
||||
handledVertices +=
|
||||
surface.vertInfo.vertCount[0] + surface.vertInfo.vertCount[1] + surface.vertInfo.vertCount[2] + surface.vertInfo.vertCount[3];
|
||||
}
|
||||
|
||||
for (; handledVertices < surface.vertCount; handledVertices++)
|
||||
@ -515,10 +500,8 @@ void AssetDumperXModel::AddXModelVertexBoneWeights(AbstractXModelWriter& writer,
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddXModelFaces(AbstractXModelWriter& writer,
|
||||
const DistinctMapper<Material*>& materialMapper,
|
||||
const XModelSurfs* modelSurfs,
|
||||
const int baseSurfaceIndex)
|
||||
void
|
||||
AddXModelFaces(AbstractXModelWriter& writer, const DistinctMapper<Material*>& materialMapper, const XModelSurfs* modelSurfs, const int baseSurfaceIndex)
|
||||
{
|
||||
for (auto surfIndex = 0u; surfIndex < modelSurfs->numsurfs; surfIndex++)
|
||||
{
|
||||
@ -538,56 +521,78 @@ void AssetDumperXModel::AddXModelFaces(AbstractXModelWriter& writer,
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpXModelExportLod(const AssetDumpingContext& context, XAssetInfo<XModel>* asset, const unsigned lod)
|
||||
void PopulateXModelWriter(const AssetDumpingContext& context, const unsigned lod, const XModel* model, AbstractXModelWriter& writer)
|
||||
{
|
||||
const auto* modelSurfs = model->lodInfo[lod].modelSurfs;
|
||||
|
||||
DistinctMapper<Material*> materialMapper(model->numsurfs);
|
||||
XModelVertexBoneWeightCollection boneWeightCollection;
|
||||
AllocateXModelBoneWeights(modelSurfs, boneWeightCollection);
|
||||
|
||||
AddXModelBones(context, writer, model);
|
||||
AddXModelMaterials(writer, materialMapper, model);
|
||||
AddXModelObjects(writer, modelSurfs);
|
||||
AddXModelVertices(writer, modelSurfs);
|
||||
AddXModelVertexBoneWeights(writer, modelSurfs, boneWeightCollection);
|
||||
AddXModelFaces(writer, materialMapper, modelSurfs, model->lodInfo[lod].surfIndex);
|
||||
}
|
||||
|
||||
void DumpXModelExportLod(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset, const unsigned lod)
|
||||
{
|
||||
const auto* model = asset->Asset();
|
||||
const auto* modelSurfs = model->lodInfo[lod].modelSurfs;
|
||||
|
||||
if (modelSurfs->name[0] == ',' || modelSurfs->surfs == nullptr)
|
||||
return;
|
||||
|
||||
const auto assetFile = context.OpenAssetFile("model_export/" + std::string(modelSurfs->name) + ".XMODEL_EXPORT");
|
||||
const auto assetFile = context.OpenAssetFile(std::format("model_export/{}.XMODEL_EXPORT", modelSurfs->name));
|
||||
|
||||
if (!assetFile)
|
||||
return;
|
||||
|
||||
const auto writer = XModelExportWriter::CreateWriterForVersion6(context.m_zone->m_game->GetShortName(), context.m_zone->m_name);
|
||||
DistinctMapper<Material*> materialMapper(model->numsurfs);
|
||||
XModelVertexBoneWeightCollection boneWeightCollection;
|
||||
AllocateXModelBoneWeights(modelSurfs, boneWeightCollection);
|
||||
|
||||
AddXModelBones(context, *writer, model);
|
||||
AddXModelMaterials(*writer, materialMapper, model);
|
||||
AddXModelObjects(*writer, modelSurfs);
|
||||
AddXModelVertices(*writer, modelSurfs);
|
||||
AddXModelVertexBoneWeights(*writer, modelSurfs, boneWeightCollection);
|
||||
AddXModelFaces(*writer, materialMapper, modelSurfs, model->lodInfo[lod].surfIndex);
|
||||
PopulateXModelWriter(context, lod, model, *writer);
|
||||
|
||||
writer->Write(*assetFile);
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpXModelExport(AssetDumpingContext& context, XAssetInfo<XModel>* asset)
|
||||
template<typename T> void DumpGltfLod(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset, const unsigned lod, const std::string& extension)
|
||||
{
|
||||
auto* surfZoneState = context.GetZoneAssetDumperState<SurfsDumpingZoneState>();
|
||||
const auto* model = asset->Asset();
|
||||
for (auto currentLod = 0u; currentLod < model->numLods; currentLod++)
|
||||
{
|
||||
if (!model->lodInfo[currentLod].modelSurfs || !surfZoneState->ShouldDumpTechnique(model->lodInfo[currentLod].modelSurfs))
|
||||
continue;
|
||||
DumpXModelExportLod(context, asset, currentLod);
|
||||
}
|
||||
const auto* modelSurfs = model->lodInfo[lod].modelSurfs;
|
||||
const auto assetFile = context.OpenAssetFile(std::format("model_export/{}{}", modelSurfs->name, extension));
|
||||
|
||||
if (!assetFile)
|
||||
return;
|
||||
|
||||
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);
|
||||
PopulateXModelWriter(context, lod, model, *writer);
|
||||
|
||||
writer->Write(*assetFile);
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpAsset(AssetDumpingContext& context, XAssetInfo<XModel>* asset)
|
||||
void DumpXModelSurfs(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset)
|
||||
{
|
||||
const auto* model = asset->Asset();
|
||||
|
||||
if (ObjWriting::Configuration.ModelOutputFormat == ObjWriting::Configuration_t::ModelOutputFormat_e::OBJ)
|
||||
DumpObjMat(context, asset);
|
||||
|
||||
for (auto currentLod = 0u; currentLod < model->numLods; currentLod++)
|
||||
{
|
||||
switch (ObjWriting::Configuration.ModelOutputFormat)
|
||||
{
|
||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::OBJ:
|
||||
DumpObj(context, asset);
|
||||
DumpObjLod(context, asset, currentLod);
|
||||
break;
|
||||
|
||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::XMODEL_EXPORT:
|
||||
DumpXModelExport(context, asset);
|
||||
DumpXModelExportLod(context, asset, currentLod);
|
||||
break;
|
||||
|
||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::GLTF:
|
||||
DumpGltfLod<gltf::TextOutput>(context, asset, currentLod, ".gltf");
|
||||
break;
|
||||
|
||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::GLB:
|
||||
DumpGltfLod<gltf::BinOutput>(context, asset, currentLod, ".glb");
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -595,3 +600,15 @@ void AssetDumperXModel::DumpAsset(AssetDumpingContext& context, XAssetInfo<XMode
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
bool AssetDumperXModel::ShouldDump(XAssetInfo<XModel>* asset)
|
||||
{
|
||||
return !asset->m_name.empty() && asset->m_name[0] != ',';
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpAsset(AssetDumpingContext& context, XAssetInfo<XModel>* asset)
|
||||
{
|
||||
DumpXModelSurfs(context, asset);
|
||||
}
|
||||
|
@ -2,37 +2,11 @@
|
||||
|
||||
#include "Dumping/AbstractAssetDumper.h"
|
||||
#include "Game/IW5/IW5.h"
|
||||
#include "Utils/DistinctMapper.h"
|
||||
#include "XModel/AbstractXModelWriter.h"
|
||||
#include "XModel/Obj/ObjWriter.h"
|
||||
|
||||
namespace IW5
|
||||
{
|
||||
class AssetDumperXModel final : public AbstractAssetDumper<XModel>
|
||||
{
|
||||
static GfxImage* GetMaterialColorMap(const Material* material);
|
||||
static GfxImage* GetMaterialNormalMap(const Material* material);
|
||||
static GfxImage* GetMaterialSpecularMap(const Material* material);
|
||||
|
||||
static void AddObjMaterials(ObjWriter& writer, DistinctMapper<Material*>& materialMapper, const XModel* model);
|
||||
static void AddObjObjects(ObjWriter& writer, const DistinctMapper<Material*>& materialMapper, const XModelSurfs* modelSurfs, int baseSurfaceIndex);
|
||||
static void AddObjVertices(ObjWriter& writer, const XModelSurfs* modelSurfs);
|
||||
static void AddObjFaces(ObjWriter& writer, const XModelSurfs* modelSurfs);
|
||||
static void DumpObjLod(const AssetDumpingContext& context, XAssetInfo<XModel>* asset, const unsigned lod);
|
||||
static void DumpObjMat(const AssetDumpingContext& context, XAssetInfo<XModel>* asset);
|
||||
static void DumpObj(AssetDumpingContext& context, XAssetInfo<XModel>* asset);
|
||||
|
||||
static void AddXModelBones(const AssetDumpingContext& context, AbstractXModelWriter& writer, const XModel* model);
|
||||
static void AddXModelMaterials(AbstractXModelWriter& writer, DistinctMapper<Material*>& materialMapper, const XModel* model);
|
||||
static void AddXModelObjects(AbstractXModelWriter& writer, const XModelSurfs* modelSurfs);
|
||||
static void AddXModelVertices(AbstractXModelWriter& writer, const XModelSurfs* modelSurfs);
|
||||
static void AllocateXModelBoneWeights(const XModelSurfs* modelSurfs, XModelVertexBoneWeightCollection& weightCollection);
|
||||
static void AddXModelVertexBoneWeights(AbstractXModelWriter& writer, const XModelSurfs* modelSurfs, XModelVertexBoneWeightCollection& weightCollection);
|
||||
static void
|
||||
AddXModelFaces(AbstractXModelWriter& writer, const DistinctMapper<Material*>& materialMapper, const XModelSurfs* modelSurfs, int baseSurfaceIndex);
|
||||
static void DumpXModelExportLod(const AssetDumpingContext& context, XAssetInfo<XModel>* asset, unsigned lod);
|
||||
static void DumpXModelExport(AssetDumpingContext& context, XAssetInfo<XModel>* asset);
|
||||
|
||||
protected:
|
||||
bool ShouldDump(XAssetInfo<XModel>* asset) override;
|
||||
void DumpAsset(AssetDumpingContext& context, XAssetInfo<XModel>* asset) override;
|
||||
|
@ -3,21 +3,29 @@
|
||||
#include "Game/T5/CommonT5.h"
|
||||
#include "Math/Quaternion.h"
|
||||
#include "ObjWriting.h"
|
||||
#include "Utils/DistinctMapper.h"
|
||||
#include "Utils/HalfFloat.h"
|
||||
#include "Utils/QuatInt16.h"
|
||||
#include "XModel/AbstractXModelWriter.h"
|
||||
#include "XModel/Export/XModelExportWriter.h"
|
||||
#include "XModel/Gltf/GltfBinOutput.h"
|
||||
#include "XModel/Gltf/GltfTextOutput.h"
|
||||
#include "XModel/Gltf/GltfWriter.h"
|
||||
#include "XModel/Obj/ObjWriter.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include <format>
|
||||
|
||||
using namespace T5;
|
||||
|
||||
bool AssetDumperXModel::ShouldDump(XAssetInfo<XModel>* asset)
|
||||
namespace
|
||||
{
|
||||
return !asset->m_name.empty() && asset->m_name[0] != ',';
|
||||
std::string GetFileNameForLod(const std::string& modelName, const unsigned lod, const std::string& extension)
|
||||
{
|
||||
return std::format("model_export/{}_lod{}{}", modelName, lod, extension);
|
||||
}
|
||||
|
||||
GfxImage* AssetDumperXModel::GetMaterialColorMap(const Material* material)
|
||||
GfxImage* GetMaterialColorMap(const Material* material)
|
||||
{
|
||||
std::vector<MaterialTextureDef*> potentialTextureDefs;
|
||||
|
||||
@ -43,7 +51,7 @@ GfxImage* AssetDumperXModel::GetMaterialColorMap(const Material* material)
|
||||
return potentialTextureDefs[0]->u.image;
|
||||
}
|
||||
|
||||
GfxImage* AssetDumperXModel::GetMaterialNormalMap(const Material* material)
|
||||
GfxImage* GetMaterialNormalMap(const Material* material)
|
||||
{
|
||||
std::vector<MaterialTextureDef*> potentialTextureDefs;
|
||||
|
||||
@ -69,7 +77,7 @@ GfxImage* AssetDumperXModel::GetMaterialNormalMap(const Material* material)
|
||||
return potentialTextureDefs[0]->u.image;
|
||||
}
|
||||
|
||||
GfxImage* AssetDumperXModel::GetMaterialSpecularMap(const Material* material)
|
||||
GfxImage* GetMaterialSpecularMap(const Material* material)
|
||||
{
|
||||
std::vector<MaterialTextureDef*> potentialTextureDefs;
|
||||
|
||||
@ -95,7 +103,7 @@ GfxImage* AssetDumperXModel::GetMaterialSpecularMap(const Material* material)
|
||||
return potentialTextureDefs[0]->u.image;
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddObjMaterials(ObjWriter& writer, DistinctMapper<Material*>& materialMapper, const XModel* model)
|
||||
void AddObjMaterials(ObjWriter& writer, DistinctMapper<Material*>& materialMapper, const XModel* model)
|
||||
{
|
||||
if (!model->materialHandles)
|
||||
return;
|
||||
@ -124,7 +132,7 @@ void AssetDumperXModel::AddObjMaterials(ObjWriter& writer, DistinctMapper<Materi
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddObjObjects(ObjWriter& writer, const DistinctMapper<Material*>& materialMapper, const XModel* model, const unsigned lod)
|
||||
void AddObjObjects(ObjWriter& writer, const DistinctMapper<Material*>& materialMapper, const XModel* model, const unsigned lod)
|
||||
{
|
||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||
const auto baseSurfIndex = model->lodInfo[lod].surfIndex;
|
||||
@ -139,7 +147,7 @@ void AssetDumperXModel::AddObjObjects(ObjWriter& writer, const DistinctMapper<Ma
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddObjVertices(ObjWriter& writer, const XModel* model, const unsigned lod)
|
||||
void AddObjVertices(ObjWriter& writer, const XModel* model, const unsigned lod)
|
||||
{
|
||||
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||
@ -176,7 +184,7 @@ void AssetDumperXModel::AddObjVertices(ObjWriter& writer, const XModel* model, c
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddObjFaces(ObjWriter& writer, const XModel* model, const unsigned lod)
|
||||
void AddObjFaces(ObjWriter& writer, const XModel* model, const unsigned lod)
|
||||
{
|
||||
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||
@ -203,10 +211,10 @@ void AssetDumperXModel::AddObjFaces(ObjWriter& writer, const XModel* model, cons
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpObjMat(const AssetDumpingContext& context, XAssetInfo<XModel>* asset)
|
||||
void DumpObjMat(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset)
|
||||
{
|
||||
const auto* model = asset->Asset();
|
||||
const auto matFile = context.OpenAssetFile("model_export/" + std::string(model->name) + ".mtl");
|
||||
const auto matFile = context.OpenAssetFile(std::format("model_export/{}.mtl", model->name));
|
||||
|
||||
if (!matFile)
|
||||
return;
|
||||
@ -218,13 +226,10 @@ void AssetDumperXModel::DumpObjMat(const AssetDumpingContext& context, XAssetInf
|
||||
writer.WriteMtl(*matFile);
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpObjLod(AssetDumpingContext& context, XAssetInfo<XModel>* asset, const unsigned lod)
|
||||
void DumpObjLod(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset, const unsigned lod)
|
||||
{
|
||||
const auto* model = asset->Asset();
|
||||
std::ostringstream ss;
|
||||
ss << "model_export/" << model->name << "_lod" << lod << ".OBJ";
|
||||
|
||||
const auto assetFile = context.OpenAssetFile(ss.str());
|
||||
const auto assetFile = context.OpenAssetFile(GetFileNameForLod(model->name, lod, ".obj"));
|
||||
|
||||
if (!assetFile)
|
||||
return;
|
||||
@ -237,21 +242,10 @@ void AssetDumperXModel::DumpObjLod(AssetDumpingContext& context, XAssetInfo<XMod
|
||||
AddObjVertices(writer, model, lod);
|
||||
AddObjFaces(writer, model, lod);
|
||||
|
||||
writer.WriteObj(*assetFile, std::string(model->name) + ".mtl");
|
||||
writer.WriteObj(*assetFile, std::format("{}.mtl", model->name));
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpObj(AssetDumpingContext& context, XAssetInfo<XModel>* asset)
|
||||
{
|
||||
const auto* model = asset->Asset();
|
||||
|
||||
DumpObjMat(context, asset);
|
||||
for (auto currentLod = 0u; currentLod < model->numLods; currentLod++)
|
||||
{
|
||||
DumpObjLod(context, asset, currentLod);
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddXModelBones(const AssetDumpingContext& context, AbstractXModelWriter& writer, const XModel* model)
|
||||
void AddXModelBones(const AssetDumpingContext& context, AbstractXModelWriter& writer, const XModel* model)
|
||||
{
|
||||
for (auto boneNum = 0u; boneNum < model->numBones; boneNum++)
|
||||
{
|
||||
@ -273,8 +267,8 @@ void AssetDumperXModel::AddXModelBones(const AssetDumpingContext& context, Abstr
|
||||
bone.globalOffset[0] = model->baseMat[boneNum].trans[0];
|
||||
bone.globalOffset[1] = model->baseMat[boneNum].trans[1];
|
||||
bone.globalOffset[2] = model->baseMat[boneNum].trans[2];
|
||||
bone.globalRotation =
|
||||
Quaternion32(model->baseMat[boneNum].quat[0], model->baseMat[boneNum].quat[1], model->baseMat[boneNum].quat[2], model->baseMat[boneNum].quat[3]);
|
||||
bone.globalRotation = Quaternion32(
|
||||
model->baseMat[boneNum].quat[0], model->baseMat[boneNum].quat[1], model->baseMat[boneNum].quat[2], model->baseMat[boneNum].quat[3]);
|
||||
|
||||
if (boneNum < model->numRootBones)
|
||||
{
|
||||
@ -298,7 +292,7 @@ void AssetDumperXModel::AddXModelBones(const AssetDumpingContext& context, Abstr
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddXModelMaterials(AbstractXModelWriter& writer, DistinctMapper<Material*>& materialMapper, const XModel* model)
|
||||
void AddXModelMaterials(AbstractXModelWriter& writer, DistinctMapper<Material*>& materialMapper, const XModel* model)
|
||||
{
|
||||
for (auto surfaceMaterialNum = 0; surfaceMaterialNum < model->numsurfs; surfaceMaterialNum++)
|
||||
{
|
||||
@ -318,7 +312,7 @@ void AssetDumperXModel::AddXModelMaterials(AbstractXModelWriter& writer, Distinc
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddXModelObjects(AbstractXModelWriter& writer, const XModel* model, const unsigned lod)
|
||||
void AddXModelObjects(AbstractXModelWriter& writer, const XModel* model, const unsigned lod)
|
||||
{
|
||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||
|
||||
@ -331,7 +325,7 @@ void AssetDumperXModel::AddXModelObjects(AbstractXModelWriter& writer, const XMo
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddXModelVertices(AbstractXModelWriter& writer, const XModel* model, const unsigned lod)
|
||||
void AddXModelVertices(AbstractXModelWriter& writer, const XModel* model, const unsigned lod)
|
||||
{
|
||||
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||
@ -370,7 +364,7 @@ void AssetDumperXModel::AddXModelVertices(AbstractXModelWriter& writer, const XM
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AllocateXModelBoneWeights(const XModel* model, const unsigned lod, XModelVertexBoneWeightCollection& weightCollection)
|
||||
void AllocateXModelBoneWeights(const XModel* model, const unsigned lod, XModelVertexBoneWeightCollection& weightCollection)
|
||||
{
|
||||
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||
@ -397,10 +391,7 @@ void AssetDumperXModel::AllocateXModelBoneWeights(const XModel* model, const uns
|
||||
weightCollection.weights = std::make_unique<XModelBoneWeight[]>(weightCollection.totalWeightCount);
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddXModelVertexBoneWeights(AbstractXModelWriter& writer,
|
||||
const XModel* model,
|
||||
const unsigned lod,
|
||||
XModelVertexBoneWeightCollection& weightCollection)
|
||||
void AddXModelVertexBoneWeights(AbstractXModelWriter& writer, const XModel* model, const unsigned lod, XModelVertexBoneWeightCollection& weightCollection)
|
||||
{
|
||||
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||
@ -504,7 +495,8 @@ void AssetDumperXModel::AddXModelVertexBoneWeights(AbstractXModelWriter& writer,
|
||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{boneWeightOffset, 4});
|
||||
}
|
||||
|
||||
handledVertices += surface.vertInfo.vertCount[0] + surface.vertInfo.vertCount[1] + surface.vertInfo.vertCount[2] + surface.vertInfo.vertCount[3];
|
||||
handledVertices +=
|
||||
surface.vertInfo.vertCount[0] + surface.vertInfo.vertCount[1] + surface.vertInfo.vertCount[2] + surface.vertInfo.vertCount[3];
|
||||
}
|
||||
|
||||
for (; handledVertices < surface.vertCount; handledVertices++)
|
||||
@ -514,7 +506,7 @@ void AssetDumperXModel::AddXModelVertexBoneWeights(AbstractXModelWriter& writer,
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddXModelFaces(AbstractXModelWriter& writer, const DistinctMapper<Material*>& materialMapper, const XModel* model, const unsigned lod)
|
||||
void AddXModelFaces(AbstractXModelWriter& writer, const DistinctMapper<Material*>& materialMapper, const XModel* model, const unsigned lod)
|
||||
{
|
||||
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||
@ -538,52 +530,74 @@ void AssetDumperXModel::AddXModelFaces(AbstractXModelWriter& writer, const Disti
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpXModelExportLod(const AssetDumpingContext& context, XAssetInfo<XModel>* asset, const unsigned lod)
|
||||
void PopulateXModelWriter(const AssetDumpingContext& context, const unsigned lod, const XModel* model, AbstractXModelWriter& writer)
|
||||
{
|
||||
DistinctMapper<Material*> materialMapper(model->numsurfs);
|
||||
XModelVertexBoneWeightCollection boneWeightCollection;
|
||||
AllocateXModelBoneWeights(model, lod, boneWeightCollection);
|
||||
|
||||
AddXModelBones(context, writer, model);
|
||||
AddXModelMaterials(writer, materialMapper, model);
|
||||
AddXModelObjects(writer, model, lod);
|
||||
AddXModelVertices(writer, model, lod);
|
||||
AddXModelVertexBoneWeights(writer, model, lod, boneWeightCollection);
|
||||
AddXModelFaces(writer, materialMapper, model, lod);
|
||||
}
|
||||
|
||||
void DumpXModelExportLod(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset, const unsigned lod)
|
||||
{
|
||||
const auto* model = asset->Asset();
|
||||
|
||||
std::ostringstream ss;
|
||||
ss << "model_export/" << model->name << "_lod" << lod << ".XMODEL_EXPORT";
|
||||
|
||||
const auto assetFile = context.OpenAssetFile(ss.str());
|
||||
const auto assetFile = context.OpenAssetFile(GetFileNameForLod(model->name, lod, ".XMODEL_EXPORT"));
|
||||
|
||||
if (!assetFile)
|
||||
return;
|
||||
|
||||
const auto writer = XModelExportWriter::CreateWriterForVersion6(context.m_zone->m_game->GetShortName(), context.m_zone->m_name);
|
||||
DistinctMapper<Material*> materialMapper(model->numsurfs);
|
||||
XModelVertexBoneWeightCollection boneWeightCollection;
|
||||
AllocateXModelBoneWeights(model, lod, boneWeightCollection);
|
||||
|
||||
AddXModelBones(context, *writer, model);
|
||||
AddXModelMaterials(*writer, materialMapper, model);
|
||||
AddXModelObjects(*writer, model, lod);
|
||||
AddXModelVertices(*writer, model, lod);
|
||||
AddXModelVertexBoneWeights(*writer, model, lod, boneWeightCollection);
|
||||
AddXModelFaces(*writer, materialMapper, model, lod);
|
||||
PopulateXModelWriter(context, lod, model, *writer);
|
||||
|
||||
writer->Write(*assetFile);
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpXModelExport(const AssetDumpingContext& context, XAssetInfo<XModel>* asset)
|
||||
template<typename T> void DumpGltfLod(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset, const unsigned lod, const std::string& extension)
|
||||
{
|
||||
const auto* model = asset->Asset();
|
||||
for (auto currentLod = 0u; currentLod < model->numLods; currentLod++)
|
||||
{
|
||||
DumpXModelExportLod(context, asset, currentLod);
|
||||
}
|
||||
const auto assetFile = context.OpenAssetFile(GetFileNameForLod(model->name, lod, extension));
|
||||
|
||||
if (!assetFile)
|
||||
return;
|
||||
|
||||
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);
|
||||
PopulateXModelWriter(context, lod, model, *writer);
|
||||
|
||||
writer->Write(*assetFile);
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpAsset(AssetDumpingContext& context, XAssetInfo<XModel>* asset)
|
||||
void DumpXModelSurfs(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset)
|
||||
{
|
||||
const auto* model = asset->Asset();
|
||||
|
||||
if (ObjWriting::Configuration.ModelOutputFormat == ObjWriting::Configuration_t::ModelOutputFormat_e::OBJ)
|
||||
DumpObjMat(context, asset);
|
||||
|
||||
for (auto currentLod = 0u; currentLod < model->numLods; currentLod++)
|
||||
{
|
||||
switch (ObjWriting::Configuration.ModelOutputFormat)
|
||||
{
|
||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::OBJ:
|
||||
DumpObj(context, asset);
|
||||
DumpObjLod(context, asset, currentLod);
|
||||
break;
|
||||
|
||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::XMODEL_EXPORT:
|
||||
DumpXModelExport(context, asset);
|
||||
DumpXModelExportLod(context, asset, currentLod);
|
||||
break;
|
||||
|
||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::GLTF:
|
||||
DumpGltfLod<gltf::TextOutput>(context, asset, currentLod, ".gltf");
|
||||
break;
|
||||
|
||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::GLB:
|
||||
DumpGltfLod<gltf::BinOutput>(context, asset, currentLod, ".glb");
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -591,3 +605,15 @@ void AssetDumperXModel::DumpAsset(AssetDumpingContext& context, XAssetInfo<XMode
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
bool AssetDumperXModel::ShouldDump(XAssetInfo<XModel>* asset)
|
||||
{
|
||||
return !asset->m_name.empty() && asset->m_name[0] != ',';
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpAsset(AssetDumpingContext& context, XAssetInfo<XModel>* asset)
|
||||
{
|
||||
DumpXModelSurfs(context, asset);
|
||||
}
|
||||
|
@ -2,37 +2,11 @@
|
||||
|
||||
#include "Dumping/AbstractAssetDumper.h"
|
||||
#include "Game/T5/T5.h"
|
||||
#include "Utils/DistinctMapper.h"
|
||||
#include "XModel/AbstractXModelWriter.h"
|
||||
#include "XModel/Obj/ObjWriter.h"
|
||||
|
||||
namespace T5
|
||||
{
|
||||
class AssetDumperXModel final : public AbstractAssetDumper<XModel>
|
||||
{
|
||||
static GfxImage* GetMaterialColorMap(const Material* material);
|
||||
static GfxImage* GetMaterialNormalMap(const Material* material);
|
||||
static GfxImage* GetMaterialSpecularMap(const Material* material);
|
||||
|
||||
static void AddObjMaterials(ObjWriter& writer, DistinctMapper<Material*>& materialMapper, const XModel* model);
|
||||
static void AddObjObjects(ObjWriter& writer, const DistinctMapper<Material*>& materialMapper, const XModel* model, unsigned lod);
|
||||
static void AddObjVertices(ObjWriter& writer, const XModel* model, unsigned lod);
|
||||
static void AddObjFaces(ObjWriter& writer, const XModel* model, unsigned lod);
|
||||
static void DumpObjLod(AssetDumpingContext& context, XAssetInfo<XModel>* asset, unsigned lod);
|
||||
static void DumpObjMat(const AssetDumpingContext& context, XAssetInfo<XModel>* asset);
|
||||
static void DumpObj(AssetDumpingContext& context, XAssetInfo<XModel>* asset);
|
||||
|
||||
static void AddXModelBones(const AssetDumpingContext& context, AbstractXModelWriter& writer, const XModel* model);
|
||||
static void AddXModelMaterials(AbstractXModelWriter& writer, DistinctMapper<Material*>& materialMapper, const XModel* model);
|
||||
static void AddXModelObjects(AbstractXModelWriter& writer, const XModel* model, unsigned lod);
|
||||
static void AddXModelVertices(AbstractXModelWriter& writer, const XModel* model, unsigned lod);
|
||||
static void AllocateXModelBoneWeights(const XModel* model, unsigned lod, XModelVertexBoneWeightCollection& weightCollection);
|
||||
static void
|
||||
AddXModelVertexBoneWeights(AbstractXModelWriter& writer, const XModel* model, unsigned lod, XModelVertexBoneWeightCollection& weightCollection);
|
||||
static void AddXModelFaces(AbstractXModelWriter& writer, const DistinctMapper<Material*>& materialMapper, const XModel* model, unsigned lod);
|
||||
static void DumpXModelExportLod(const AssetDumpingContext& context, XAssetInfo<XModel>* asset, unsigned lod);
|
||||
static void DumpXModelExport(const AssetDumpingContext& context, XAssetInfo<XModel>* asset);
|
||||
|
||||
protected:
|
||||
bool ShouldDump(XAssetInfo<XModel>* asset) override;
|
||||
void DumpAsset(AssetDumpingContext& context, XAssetInfo<XModel>* asset) override;
|
||||
|
@ -3,21 +3,29 @@
|
||||
#include "Game/T6/CommonT6.h"
|
||||
#include "Math/Quaternion.h"
|
||||
#include "ObjWriting.h"
|
||||
#include "Utils/DistinctMapper.h"
|
||||
#include "Utils/HalfFloat.h"
|
||||
#include "Utils/QuatInt16.h"
|
||||
#include "XModel/AbstractXModelWriter.h"
|
||||
#include "XModel/Export/XModelExportWriter.h"
|
||||
#include "XModel/Gltf/GltfBinOutput.h"
|
||||
#include "XModel/Gltf/GltfTextOutput.h"
|
||||
#include "XModel/Gltf/GltfWriter.h"
|
||||
#include "XModel/Obj/ObjWriter.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include <format>
|
||||
|
||||
using namespace T6;
|
||||
|
||||
bool AssetDumperXModel::ShouldDump(XAssetInfo<XModel>* asset)
|
||||
namespace
|
||||
{
|
||||
return !asset->m_name.empty() && asset->m_name[0] != ',';
|
||||
std::string GetFileNameForLod(const std::string& modelName, const unsigned lod, const std::string& extension)
|
||||
{
|
||||
return std::format("model_export/{}_lod{}{}", modelName, lod, extension);
|
||||
}
|
||||
|
||||
GfxImage* AssetDumperXModel::GetMaterialColorMap(const Material* material)
|
||||
GfxImage* GetMaterialColorMap(const Material* material)
|
||||
{
|
||||
std::vector<MaterialTextureDef*> potentialTextureDefs;
|
||||
|
||||
@ -55,7 +63,7 @@ GfxImage* AssetDumperXModel::GetMaterialColorMap(const Material* material)
|
||||
return potentialTextureDefs[0]->image;
|
||||
}
|
||||
|
||||
GfxImage* AssetDumperXModel::GetMaterialNormalMap(const Material* material)
|
||||
GfxImage* GetMaterialNormalMap(const Material* material)
|
||||
{
|
||||
std::vector<MaterialTextureDef*> potentialTextureDefs;
|
||||
|
||||
@ -81,7 +89,7 @@ GfxImage* AssetDumperXModel::GetMaterialNormalMap(const Material* material)
|
||||
return potentialTextureDefs[0]->image;
|
||||
}
|
||||
|
||||
GfxImage* AssetDumperXModel::GetMaterialSpecularMap(const Material* material)
|
||||
GfxImage* GetMaterialSpecularMap(const Material* material)
|
||||
{
|
||||
std::vector<MaterialTextureDef*> potentialTextureDefs;
|
||||
|
||||
@ -107,7 +115,7 @@ GfxImage* AssetDumperXModel::GetMaterialSpecularMap(const Material* material)
|
||||
return potentialTextureDefs[0]->image;
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddObjMaterials(ObjWriter& writer, DistinctMapper<Material*>& materialMapper, const XModel* model)
|
||||
void AddObjMaterials(ObjWriter& writer, DistinctMapper<Material*>& materialMapper, const XModel* model)
|
||||
{
|
||||
if (!model->materialHandles)
|
||||
return;
|
||||
@ -136,7 +144,7 @@ void AssetDumperXModel::AddObjMaterials(ObjWriter& writer, DistinctMapper<Materi
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddObjObjects(ObjWriter& writer, const DistinctMapper<Material*>& materialMapper, const XModel* model, const unsigned lod)
|
||||
void AddObjObjects(ObjWriter& writer, const DistinctMapper<Material*>& materialMapper, const XModel* model, const unsigned lod)
|
||||
{
|
||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||
const auto baseSurfIndex = model->lodInfo[lod].surfIndex;
|
||||
@ -151,7 +159,7 @@ void AssetDumperXModel::AddObjObjects(ObjWriter& writer, const DistinctMapper<Ma
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddObjVertices(ObjWriter& writer, const XModel* model, const unsigned lod)
|
||||
void AddObjVertices(ObjWriter& writer, const XModel* model, const unsigned lod)
|
||||
{
|
||||
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||
@ -188,7 +196,7 @@ void AssetDumperXModel::AddObjVertices(ObjWriter& writer, const XModel* model, c
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddObjFaces(ObjWriter& writer, const XModel* model, const unsigned lod)
|
||||
void AddObjFaces(ObjWriter& writer, const XModel* model, const unsigned lod)
|
||||
{
|
||||
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||
@ -215,10 +223,10 @@ void AssetDumperXModel::AddObjFaces(ObjWriter& writer, const XModel* model, cons
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpObjMat(const AssetDumpingContext& context, XAssetInfo<XModel>* asset)
|
||||
void DumpObjMat(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset)
|
||||
{
|
||||
const auto* model = asset->Asset();
|
||||
const auto matFile = context.OpenAssetFile("model_export/" + std::string(model->name) + ".mtl");
|
||||
const auto matFile = context.OpenAssetFile(std::format("model_export/{}.mtl", model->name));
|
||||
|
||||
if (!matFile)
|
||||
return;
|
||||
@ -230,13 +238,10 @@ void AssetDumperXModel::DumpObjMat(const AssetDumpingContext& context, XAssetInf
|
||||
writer.WriteMtl(*matFile);
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpObjLod(AssetDumpingContext& context, XAssetInfo<XModel>* asset, const unsigned lod)
|
||||
void DumpObjLod(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset, const unsigned lod)
|
||||
{
|
||||
const auto* model = asset->Asset();
|
||||
std::ostringstream ss;
|
||||
ss << "model_export/" << model->name << "_lod" << lod << ".OBJ";
|
||||
|
||||
const auto assetFile = context.OpenAssetFile(ss.str());
|
||||
const auto assetFile = context.OpenAssetFile(GetFileNameForLod(model->name, lod, ".obj"));
|
||||
|
||||
if (!assetFile)
|
||||
return;
|
||||
@ -249,21 +254,10 @@ void AssetDumperXModel::DumpObjLod(AssetDumpingContext& context, XAssetInfo<XMod
|
||||
AddObjVertices(writer, model, lod);
|
||||
AddObjFaces(writer, model, lod);
|
||||
|
||||
writer.WriteObj(*assetFile, std::string(model->name) + ".mtl");
|
||||
writer.WriteObj(*assetFile, std::format("{}.mtl", model->name));
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpObj(AssetDumpingContext& context, XAssetInfo<XModel>* asset)
|
||||
{
|
||||
const auto* model = asset->Asset();
|
||||
|
||||
DumpObjMat(context, asset);
|
||||
for (auto currentLod = 0u; currentLod < model->numLods; currentLod++)
|
||||
{
|
||||
DumpObjLod(context, asset, currentLod);
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddXModelBones(const AssetDumpingContext& context, AbstractXModelWriter& writer, const XModel* model)
|
||||
void AddXModelBones(const AssetDumpingContext& context, AbstractXModelWriter& writer, const XModel* model)
|
||||
{
|
||||
for (auto boneNum = 0u; boneNum < model->numBones; boneNum++)
|
||||
{
|
||||
@ -310,7 +304,7 @@ void AssetDumperXModel::AddXModelBones(const AssetDumpingContext& context, Abstr
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddXModelMaterials(AbstractXModelWriter& writer, DistinctMapper<Material*>& materialMapper, const XModel* model)
|
||||
void AddXModelMaterials(AbstractXModelWriter& writer, DistinctMapper<Material*>& materialMapper, const XModel* model)
|
||||
{
|
||||
for (auto surfaceMaterialNum = 0; surfaceMaterialNum < model->numsurfs; surfaceMaterialNum++)
|
||||
{
|
||||
@ -330,7 +324,7 @@ void AssetDumperXModel::AddXModelMaterials(AbstractXModelWriter& writer, Distinc
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddXModelObjects(AbstractXModelWriter& writer, const XModel* model, const unsigned lod)
|
||||
void AddXModelObjects(AbstractXModelWriter& writer, const XModel* model, const unsigned lod)
|
||||
{
|
||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||
|
||||
@ -343,7 +337,7 @@ void AssetDumperXModel::AddXModelObjects(AbstractXModelWriter& writer, const XMo
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddXModelVertices(AbstractXModelWriter& writer, const XModel* model, const unsigned lod)
|
||||
void AddXModelVertices(AbstractXModelWriter& writer, const XModel* model, const unsigned lod)
|
||||
{
|
||||
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||
@ -385,7 +379,7 @@ void AssetDumperXModel::AddXModelVertices(AbstractXModelWriter& writer, const XM
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AllocateXModelBoneWeights(const XModel* model, const unsigned lod, XModelVertexBoneWeightCollection& weightCollection)
|
||||
void AllocateXModelBoneWeights(const XModel* model, const unsigned lod, XModelVertexBoneWeightCollection& weightCollection)
|
||||
{
|
||||
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||
@ -415,10 +409,7 @@ void AssetDumperXModel::AllocateXModelBoneWeights(const XModel* model, const uns
|
||||
weightCollection.weights = std::make_unique<XModelBoneWeight[]>(weightCollection.totalWeightCount);
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddXModelVertexBoneWeights(AbstractXModelWriter& writer,
|
||||
const XModel* model,
|
||||
const unsigned lod,
|
||||
XModelVertexBoneWeightCollection& weightCollection)
|
||||
void AddXModelVertexBoneWeights(AbstractXModelWriter& writer, const XModel* model, const unsigned lod, XModelVertexBoneWeightCollection& weightCollection)
|
||||
{
|
||||
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||
@ -525,7 +516,8 @@ void AssetDumperXModel::AddXModelVertexBoneWeights(AbstractXModelWriter& writer,
|
||||
writer.AddVertexBoneWeights(XModelVertexBoneWeights{boneWeightOffset, 4});
|
||||
}
|
||||
|
||||
handledVertices += surface.vertInfo.vertCount[0] + surface.vertInfo.vertCount[1] + surface.vertInfo.vertCount[2] + surface.vertInfo.vertCount[3];
|
||||
handledVertices +=
|
||||
surface.vertInfo.vertCount[0] + surface.vertInfo.vertCount[1] + surface.vertInfo.vertCount[2] + surface.vertInfo.vertCount[3];
|
||||
}
|
||||
|
||||
for (; handledVertices < surface.vertCount; handledVertices++)
|
||||
@ -535,7 +527,7 @@ void AssetDumperXModel::AddXModelVertexBoneWeights(AbstractXModelWriter& writer,
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::AddXModelFaces(AbstractXModelWriter& writer, const DistinctMapper<Material*>& materialMapper, const XModel* model, const unsigned lod)
|
||||
void AddXModelFaces(AbstractXModelWriter& writer, const DistinctMapper<Material*>& materialMapper, const XModel* model, const unsigned lod)
|
||||
{
|
||||
const auto* surfs = &model->surfs[model->lodInfo[lod].surfIndex];
|
||||
const auto surfCount = model->lodInfo[lod].numsurfs;
|
||||
@ -562,52 +554,74 @@ void AssetDumperXModel::AddXModelFaces(AbstractXModelWriter& writer, const Disti
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpXModelExportLod(const AssetDumpingContext& context, XAssetInfo<XModel>* asset, const unsigned lod)
|
||||
void PopulateXModelWriter(const AssetDumpingContext& context, const unsigned lod, const XModel* model, AbstractXModelWriter& writer)
|
||||
{
|
||||
DistinctMapper<Material*> materialMapper(model->numsurfs);
|
||||
XModelVertexBoneWeightCollection boneWeightCollection;
|
||||
AllocateXModelBoneWeights(model, lod, boneWeightCollection);
|
||||
|
||||
AddXModelBones(context, writer, model);
|
||||
AddXModelMaterials(writer, materialMapper, model);
|
||||
AddXModelObjects(writer, model, lod);
|
||||
AddXModelVertices(writer, model, lod);
|
||||
AddXModelVertexBoneWeights(writer, model, lod, boneWeightCollection);
|
||||
AddXModelFaces(writer, materialMapper, model, lod);
|
||||
}
|
||||
|
||||
void DumpXModelExportLod(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset, const unsigned lod)
|
||||
{
|
||||
const auto* model = asset->Asset();
|
||||
|
||||
std::ostringstream ss;
|
||||
ss << "model_export/" << model->name << "_lod" << lod << ".XMODEL_EXPORT";
|
||||
|
||||
const auto assetFile = context.OpenAssetFile(ss.str());
|
||||
const auto assetFile = context.OpenAssetFile(GetFileNameForLod(model->name, lod, ".XMODEL_EXPORT"));
|
||||
|
||||
if (!assetFile)
|
||||
return;
|
||||
|
||||
const auto writer = XModelExportWriter::CreateWriterForVersion6(context.m_zone->m_game->GetShortName(), context.m_zone->m_name);
|
||||
DistinctMapper<Material*> materialMapper(model->numsurfs);
|
||||
XModelVertexBoneWeightCollection boneWeightCollection;
|
||||
AllocateXModelBoneWeights(model, lod, boneWeightCollection);
|
||||
|
||||
AddXModelBones(context, *writer, model);
|
||||
AddXModelMaterials(*writer, materialMapper, model);
|
||||
AddXModelObjects(*writer, model, lod);
|
||||
AddXModelVertices(*writer, model, lod);
|
||||
AddXModelVertexBoneWeights(*writer, model, lod, boneWeightCollection);
|
||||
AddXModelFaces(*writer, materialMapper, model, lod);
|
||||
PopulateXModelWriter(context, lod, model, *writer);
|
||||
|
||||
writer->Write(*assetFile);
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpXModelExport(const AssetDumpingContext& context, XAssetInfo<XModel>* asset)
|
||||
template<typename T> void DumpGltfLod(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset, const unsigned lod, const std::string& extension)
|
||||
{
|
||||
const auto* model = asset->Asset();
|
||||
for (auto currentLod = 0u; currentLod < model->numLods; currentLod++)
|
||||
{
|
||||
DumpXModelExportLod(context, asset, currentLod);
|
||||
}
|
||||
const auto assetFile = context.OpenAssetFile(GetFileNameForLod(model->name, lod, extension));
|
||||
|
||||
if (!assetFile)
|
||||
return;
|
||||
|
||||
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);
|
||||
PopulateXModelWriter(context, lod, model, *writer);
|
||||
|
||||
writer->Write(*assetFile);
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpAsset(AssetDumpingContext& context, XAssetInfo<XModel>* asset)
|
||||
void DumpXModelSurfs(const AssetDumpingContext& context, const XAssetInfo<XModel>* asset)
|
||||
{
|
||||
const auto* model = asset->Asset();
|
||||
|
||||
if (ObjWriting::Configuration.ModelOutputFormat == ObjWriting::Configuration_t::ModelOutputFormat_e::OBJ)
|
||||
DumpObjMat(context, asset);
|
||||
|
||||
for (auto currentLod = 0u; currentLod < model->numLods; currentLod++)
|
||||
{
|
||||
switch (ObjWriting::Configuration.ModelOutputFormat)
|
||||
{
|
||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::OBJ:
|
||||
DumpObj(context, asset);
|
||||
DumpObjLod(context, asset, currentLod);
|
||||
break;
|
||||
|
||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::XMODEL_EXPORT:
|
||||
DumpXModelExport(context, asset);
|
||||
DumpXModelExportLod(context, asset, currentLod);
|
||||
break;
|
||||
|
||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::GLTF:
|
||||
DumpGltfLod<gltf::TextOutput>(context, asset, currentLod, ".gltf");
|
||||
break;
|
||||
|
||||
case ObjWriting::Configuration_t::ModelOutputFormat_e::GLB:
|
||||
DumpGltfLod<gltf::BinOutput>(context, asset, currentLod, ".glb");
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -615,3 +629,15 @@ void AssetDumperXModel::DumpAsset(AssetDumpingContext& context, XAssetInfo<XMode
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
bool AssetDumperXModel::ShouldDump(XAssetInfo<XModel>* asset)
|
||||
{
|
||||
return !asset->m_name.empty() && asset->m_name[0] != ',';
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpAsset(AssetDumpingContext& context, XAssetInfo<XModel>* asset)
|
||||
{
|
||||
DumpXModelSurfs(context, asset);
|
||||
}
|
||||
|
@ -2,37 +2,11 @@
|
||||
|
||||
#include "Dumping/AbstractAssetDumper.h"
|
||||
#include "Game/T6/T6.h"
|
||||
#include "Utils/DistinctMapper.h"
|
||||
#include "XModel/AbstractXModelWriter.h"
|
||||
#include "XModel/Obj/ObjWriter.h"
|
||||
|
||||
namespace T6
|
||||
{
|
||||
class AssetDumperXModel final : public AbstractAssetDumper<XModel>
|
||||
{
|
||||
static GfxImage* GetMaterialColorMap(const Material* material);
|
||||
static GfxImage* GetMaterialNormalMap(const Material* material);
|
||||
static GfxImage* GetMaterialSpecularMap(const Material* material);
|
||||
|
||||
static void AddObjMaterials(ObjWriter& writer, DistinctMapper<Material*>& materialMapper, const XModel* model);
|
||||
static void AddObjObjects(ObjWriter& writer, const DistinctMapper<Material*>& materialMapper, const XModel* model, unsigned lod);
|
||||
static void AddObjVertices(ObjWriter& writer, const XModel* model, unsigned lod);
|
||||
static void AddObjFaces(ObjWriter& writer, const XModel* model, unsigned lod);
|
||||
static void DumpObjLod(AssetDumpingContext& context, XAssetInfo<XModel>* asset, unsigned lod);
|
||||
static void DumpObjMat(const AssetDumpingContext& context, XAssetInfo<XModel>* asset);
|
||||
static void DumpObj(AssetDumpingContext& context, XAssetInfo<XModel>* asset);
|
||||
|
||||
static void AddXModelBones(const AssetDumpingContext& context, AbstractXModelWriter& writer, const XModel* model);
|
||||
static void AddXModelMaterials(AbstractXModelWriter& writer, DistinctMapper<Material*>& materialMapper, const XModel* model);
|
||||
static void AddXModelObjects(AbstractXModelWriter& writer, const XModel* model, unsigned lod);
|
||||
static void AddXModelVertices(AbstractXModelWriter& writer, const XModel* model, unsigned lod);
|
||||
static void AllocateXModelBoneWeights(const XModel* model, unsigned lod, XModelVertexBoneWeightCollection& weightCollection);
|
||||
static void
|
||||
AddXModelVertexBoneWeights(AbstractXModelWriter& writer, const XModel* model, unsigned lod, XModelVertexBoneWeightCollection& weightCollection);
|
||||
static void AddXModelFaces(AbstractXModelWriter& writer, const DistinctMapper<Material*>& materialMapper, const XModel* model, unsigned lod);
|
||||
static void DumpXModelExportLod(const AssetDumpingContext& context, XAssetInfo<XModel>* asset, unsigned lod);
|
||||
static void DumpXModelExport(const AssetDumpingContext& context, XAssetInfo<XModel>* asset);
|
||||
|
||||
protected:
|
||||
bool ShouldDump(XAssetInfo<XModel>* asset) override;
|
||||
void DumpAsset(AssetDumpingContext& context, XAssetInfo<XModel>* asset) override;
|
||||
|
@ -20,14 +20,16 @@ public:
|
||||
enum class ModelOutputFormat_e
|
||||
{
|
||||
XMODEL_EXPORT,
|
||||
OBJ
|
||||
OBJ,
|
||||
GLTF,
|
||||
GLB
|
||||
};
|
||||
|
||||
bool Verbose = false;
|
||||
std::vector<bool> AssetTypesToHandleBitfield;
|
||||
|
||||
ImageOutputFormat_e ImageOutputFormat = ImageOutputFormat_e::DDS;
|
||||
ModelOutputFormat_e ModelOutputFormat = ModelOutputFormat_e::XMODEL_EXPORT;
|
||||
ModelOutputFormat_e ModelOutputFormat = ModelOutputFormat_e::GLB;
|
||||
bool MenuLegacyMode = false;
|
||||
|
||||
} Configuration;
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "ObjWriting.h"
|
||||
#include "Utils/Arguments/UsageInformation.h"
|
||||
#include "Utils/FileUtils.h"
|
||||
#include "Utils/StringUtils.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <regex>
|
||||
@ -79,7 +80,7 @@ const CommandLineOption* const OPTION_IMAGE_FORMAT =
|
||||
const CommandLineOption* const OPTION_MODEL_FORMAT =
|
||||
CommandLineOption::Builder::Create()
|
||||
.WithLongName("model-format")
|
||||
.WithDescription("Specifies the format of dumped model files. Valid values are: XMODEL_EXPORT, OBJ")
|
||||
.WithDescription("Specifies the format of dumped model files. Valid values are: XMODEL_EXPORT, OBJ, GLTF, GLB")
|
||||
.WithParameter("modelFormatValue")
|
||||
.Build();
|
||||
|
||||
@ -179,8 +180,7 @@ void UnlinkerArgs::SetVerbose(const bool isVerbose)
|
||||
bool UnlinkerArgs::SetImageDumpingMode()
|
||||
{
|
||||
auto specifiedValue = m_argument_parser.GetValueForOption(OPTION_IMAGE_FORMAT);
|
||||
for (auto& c : specifiedValue)
|
||||
c = static_cast<char>(tolower(c));
|
||||
utils::MakeStringLowerCase(specifiedValue);
|
||||
|
||||
if (specifiedValue == "dds")
|
||||
{
|
||||
@ -202,8 +202,7 @@ bool UnlinkerArgs::SetImageDumpingMode()
|
||||
bool UnlinkerArgs::SetModelDumpingMode()
|
||||
{
|
||||
auto specifiedValue = m_argument_parser.GetValueForOption(OPTION_MODEL_FORMAT);
|
||||
for (auto& c : specifiedValue)
|
||||
c = static_cast<char>(tolower(c));
|
||||
utils::MakeStringLowerCase(specifiedValue);
|
||||
|
||||
if (specifiedValue == "xmodel_export")
|
||||
{
|
||||
@ -217,6 +216,18 @@ bool UnlinkerArgs::SetModelDumpingMode()
|
||||
return true;
|
||||
}
|
||||
|
||||
if (specifiedValue == "gltf")
|
||||
{
|
||||
ObjWriting::Configuration.ModelOutputFormat = ObjWriting::Configuration_t::ModelOutputFormat_e::GLTF;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (specifiedValue == "glb")
|
||||
{
|
||||
ObjWriting::Configuration.ModelOutputFormat = ObjWriting::Configuration_t::ModelOutputFormat_e::GLB;
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::string originalValue = m_argument_parser.GetValueForOption(OPTION_MODEL_FORMAT);
|
||||
printf("Illegal value: \"%s\" is not a valid model output format. Use -? to see usage information.\n", originalValue.c_str());
|
||||
return false;
|
||||
@ -238,8 +249,7 @@ void UnlinkerArgs::ParseCommaSeparatedAssetTypeString(const std::string& input)
|
||||
size_t endPos;
|
||||
|
||||
std::string lowerInput(input);
|
||||
for (auto& c : lowerInput)
|
||||
c = static_cast<char>(tolower(c));
|
||||
utils::MakeStringLowerCase(lowerInput);
|
||||
|
||||
while (currentPos < lowerInput.size() && (endPos = lowerInput.find_first_of(',', currentPos)) != std::string::npos)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user