mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-06-10 23:08:05 -05:00
Dump IW4 xmodels as obj
This commit is contained in:
183
src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperXModel.cpp
Normal file
183
src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperXModel.cpp
Normal file
@ -0,0 +1,183 @@
|
||||
#include "AssetDumperXModel.h"
|
||||
|
||||
#include <set>
|
||||
|
||||
#include "Game/IW4/CommonIW4.h"
|
||||
|
||||
using namespace IW4;
|
||||
|
||||
bool AssetDumperXModel::ShouldDump(XAssetInfo<XModel>* asset)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpObjMatMaterial(AssetDumpingContext& context, const Material* material, std::ostream& stream)
|
||||
{
|
||||
stream << "\n";
|
||||
stream << "newmtl " << material->info.name << "\n";
|
||||
|
||||
GfxImage* colorMap = nullptr;
|
||||
GfxImage* normalMap = nullptr;
|
||||
GfxImage* specularMap = nullptr;
|
||||
|
||||
for(auto i = 0u; i < material->textureCount; i++)
|
||||
{
|
||||
const auto& texture = material->textureTable[i];
|
||||
|
||||
switch (texture.semantic)
|
||||
{
|
||||
case TS_COLOR_MAP:
|
||||
colorMap = texture.u.image;
|
||||
break;
|
||||
|
||||
case TS_NORMAL_MAP:
|
||||
normalMap = texture.u.image;
|
||||
break;
|
||||
|
||||
case TS_SPECULAR_MAP:
|
||||
specularMap = texture.u.image;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (colorMap)
|
||||
stream << "map_Ka " << colorMap->name << ".dds\n";
|
||||
|
||||
if (normalMap)
|
||||
stream << "map_bump " << normalMap->name << ".dds\n";
|
||||
|
||||
if (specularMap)
|
||||
stream << "map_Ks " << specularMap->name << ".dds\n";
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpObjMat(AssetDumpingContext& context, XAssetInfo<XModel>* asset)
|
||||
{
|
||||
const auto* model = asset->Asset();
|
||||
const auto matFile = context.OpenAssetFile("xmodelsurfs/" + std::string(model->name) + ".mat");
|
||||
|
||||
if (!matFile)
|
||||
return;
|
||||
|
||||
auto& stream = *matFile;
|
||||
stream << "# OpenAssetTools MAT File (IW4)\n";
|
||||
|
||||
if (model->numsurfs == 0 || model->materialHandles == nullptr)
|
||||
return;
|
||||
|
||||
std::set<Material*> uniqueMaterials;
|
||||
for (auto i = 0u; i < model->numsurfs; i++)
|
||||
{
|
||||
if(model->materialHandles[i] != nullptr)
|
||||
uniqueMaterials.emplace(model->materialHandles[i]);
|
||||
}
|
||||
|
||||
stream << "# Material count: " << uniqueMaterials.size() << "\n";
|
||||
|
||||
for(const auto* material : uniqueMaterials)
|
||||
{
|
||||
DumpObjMatMaterial(context, material, stream);
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpObjLod(AssetDumpingContext& context, XAssetInfo<XModel>* asset, const unsigned lod)
|
||||
{
|
||||
const auto* model = asset->Asset();
|
||||
const auto* modelSurfs = model->lodInfo[lod].modelSurfs;
|
||||
const auto assetFile = context.OpenAssetFile("xmodelsurfs/" + std::string(modelSurfs->name) + ".obj");
|
||||
|
||||
if (!assetFile)
|
||||
return;
|
||||
|
||||
auto& stream = *assetFile;
|
||||
stream << "# OpenAssetTools OBJ File (IW4)\n";
|
||||
|
||||
stream << "mtllib " << model->name << ".mtl\n";
|
||||
|
||||
if (model->lodInfo[lod].modelSurfs == nullptr || model->lodInfo[lod].modelSurfs->surfs == nullptr)
|
||||
return;
|
||||
|
||||
for (auto i = 0; i < model->lodInfo[lod].numsurfs; i++)
|
||||
{
|
||||
const auto* surf = &modelSurfs->surfs[i];
|
||||
|
||||
stream << "o surf" << i << "\n";
|
||||
|
||||
for (auto vi = 0; vi < surf->vertCount; vi++)
|
||||
{
|
||||
const auto* vertex = &surf->verts0[vi];
|
||||
stream << "v " << vertex->xyz[0] << " " << vertex->xyz[1] << " " << vertex->xyz[2] << "\n";
|
||||
}
|
||||
|
||||
stream << "\n";
|
||||
|
||||
for (auto vi = 0; vi < surf->vertCount; vi++)
|
||||
{
|
||||
const auto* vertex = &surf->verts0[vi];
|
||||
vec2_t texCoords;
|
||||
Common::Vec2UnpackTexCoords(vertex->texCoord, &texCoords);
|
||||
|
||||
stream << "vt " << texCoords[0] << " " << (1.0f - texCoords[1]) << "\n";
|
||||
}
|
||||
|
||||
stream << "\n";
|
||||
|
||||
for (auto vi = 0; vi < surf->vertCount; vi++)
|
||||
{
|
||||
const auto* vertex = &surf->verts0[vi];
|
||||
vec3_t normalVec;
|
||||
Common::Vec3UnpackUnitVec(vertex->normal, &normalVec);
|
||||
|
||||
stream << "vn " << normalVec[0] << " " << normalVec[1] << " " << normalVec[2] << "\n";
|
||||
}
|
||||
|
||||
stream << "\n";
|
||||
|
||||
if(model->numsurfs > i && model->materialHandles && model->materialHandles[i])
|
||||
{
|
||||
stream << "usemtl " << model->materialHandles[i]->info.name << "\n";
|
||||
}
|
||||
|
||||
stream << "\n";
|
||||
|
||||
for (auto ti = 0; ti < surf->triCount; ti++)
|
||||
{
|
||||
const auto* indices = reinterpret_cast<r_index16_t*>(surf->triIndices);
|
||||
|
||||
const auto i0 = surf->baseVertIndex + indices[ti * 3 + 0] + 1;
|
||||
const auto i1 = surf->baseVertIndex + indices[ti * 3 + 1] + 1;
|
||||
const auto i2 = surf->baseVertIndex + indices[ti * 3 + 2] + 1;
|
||||
|
||||
stream << "f " << i2 << "/" << i2 << "/" << i2
|
||||
<< " " << i1 << "/" << i1 << "/" << i1
|
||||
<< " " << i0 << "/" << i0 << "/" << i0
|
||||
<< "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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::DumpXModelExportLod(AssetDumpingContext& context, XAssetInfo<XModel>* asset, unsigned lod)
|
||||
{
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpXModelExport(AssetDumpingContext& context, XAssetInfo<XModel>* asset)
|
||||
{
|
||||
}
|
||||
|
||||
void AssetDumperXModel::DumpAsset(AssetDumpingContext& context, XAssetInfo<XModel>* asset)
|
||||
{
|
||||
DumpObj(context, asset);
|
||||
}
|
23
src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperXModel.h
Normal file
23
src/ObjWriting/Game/IW4/AssetDumpers/AssetDumperXModel.h
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <ostream>
|
||||
|
||||
#include "Dumping/AbstractAssetDumper.h"
|
||||
#include "Game/IW4/IW4.h"
|
||||
|
||||
namespace IW4
|
||||
{
|
||||
class AssetDumperXModel final : public AbstractAssetDumper<XModel>
|
||||
{
|
||||
static void DumpObjLod(AssetDumpingContext& context, XAssetInfo<XModel>* asset, unsigned lod);
|
||||
static void DumpObjMatMaterial(AssetDumpingContext& context, const Material* material, std::ostream& stream);
|
||||
static void DumpObjMat(AssetDumpingContext& context, XAssetInfo<XModel>* asset);
|
||||
static void DumpObj(AssetDumpingContext& context, XAssetInfo<XModel>* asset);
|
||||
static void DumpXModelExportLod(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;
|
||||
};
|
||||
}
|
@ -11,6 +11,7 @@
|
||||
#include "AssetDumpers/AssetDumperStringTable.h"
|
||||
#include "AssetDumpers/AssetDumperVehicle.h"
|
||||
#include "AssetDumpers/AssetDumperWeapon.h"
|
||||
#include "AssetDumpers/AssetDumperXModel.h"
|
||||
|
||||
using namespace IW4;
|
||||
|
||||
@ -33,7 +34,7 @@ bool ZoneDumper::DumpZone(AssetDumpingContext& context) const
|
||||
// DUMP_ASSET_POOL(AssetDumperPhysPreset, m_phys_preset)
|
||||
// DUMP_ASSET_POOL(AssetDumperPhysCollmap, m_phys_collmap)
|
||||
// DUMP_ASSET_POOL(AssetDumperXAnimParts, m_xanim_parts)
|
||||
// DUMP_ASSET_POOL(AssetDumperXModel, m_xmodel)
|
||||
DUMP_ASSET_POOL(AssetDumperXModel, m_xmodel)
|
||||
// DUMP_ASSET_POOL(AssetDumperMaterial, m_material)
|
||||
// DUMP_ASSET_POOL(AssetDumperMaterialPixelShader, m_material_pixel_shader)
|
||||
// DUMP_ASSET_POOL(AssetDumperMaterialVertexShader, m_material_vertex_shader)
|
||||
|
@ -14,8 +14,15 @@ public:
|
||||
IWI
|
||||
};
|
||||
|
||||
enum class ModelOutputFormat_e
|
||||
{
|
||||
XMODEL_EXPORT,
|
||||
OBJ
|
||||
};
|
||||
|
||||
bool Verbose = false;
|
||||
ImageOutputFormat_e ImageOutputFormat = ImageOutputFormat_e::DDS;
|
||||
ModelOutputFormat_e ModelOutputFormat = ModelOutputFormat_e::XMODEL_EXPORT;
|
||||
|
||||
} Configuration;
|
||||
|
||||
|
Reference in New Issue
Block a user