2
0
mirror of https://github.com/Laupetin/OpenAssetTools.git synced 2026-06-17 14:02:12 +00:00
Files
OpenAssetTools/src/ObjWriting/Image/ImageDumper.cpp.template
T
mo 44d6710991 feat: initial T4 support (#807)
* feat: initial T4 support

* chore: adjust t4 symbols a bit for accuracy

* chore: add PackIndex asset to T4

* chore: remove unused AssetXModelPieces

* chore: add default and global asset pools loader for T4

* chore: use separate defines for T4 in ImageDumper

* chore: remove unnecessary namespaces in gfximage_actions

* chore: small things

* chore: fix T4 PhysPreset type

* chore: use proper XQuat2 type for T4 xanims

* chore: fix errors on T4 types

* chore: use iw3 like struct for XModelStreamInfo

* docs: add basic docs for T4

* chore: add basic ObjCompiler setup for T4

* chore: adjust loaded sound definition

* chore: make sure t4 material has the correct alignment

* chore: make sure t4 uses similar names for assets as other games

* fix: asset references should not be reusable

* chore: add content writer for t4

* feat: add t4 localize loader

* chore: reorder game ids to be alphabetically ordered

---------

Co-authored-by: Jan Laupetin <jan@laupetin.net>
2026-06-07 14:06:33 +02:00

207 lines
5.6 KiB
Plaintext

#options GAME (IW3, IW4, IW5, T4, T5, T6)
#filename "Game/" + GAME + "/Image/ImageDumper" + GAME + ".cpp"
#set DUMPER_HEADER "\"ImageDumper" + GAME + ".h\""
#if GAME == "IW3"
#define FEATURE_IW3
#define DX9
#define IWI6
#elif GAME == "T4"
#define FEATURE_T4
#define DX9
#define IWI6
#elif GAME == "IW4"
#define FEATURE_IW4
#define DX9
#define IWI8
#elif GAME == "IW5"
#define FEATURE_IW5
#define DX9
#define IWI8
#elif GAME == "T5"
#define FEATURE_T5
#define DX9
#define IWI13
#elif GAME == "T6"
#define FEATURE_T6
#define DX11
#define IWI27
#endif
// This file was templated.
// See ImageDumper.cpp.template.
// Do not modify, changes will be lost.
#include DUMPER_HEADER
#ifdef DX9
#include "Image/Dx9TextureLoader.h"
#else
#include "Image/Dx12TextureLoader.h"
#endif
#ifdef FEATURE_T6
#include "ObjContainer/IPak/IPak.h"
#endif
#if defined(IWI6)
#include "Image/IwiWriter6.h"
#define IWI_NS iwi6
#elif defined(IWI8)
#include "Image/IwiWriter8.h"
#define IWI_NS iwi8
#elif defined(IWI13)
#include "Image/IwiWriter13.h"
#define IWI_NS iwi13
#elif defined(IWI27)
#include "Image/IwiWriter27.h"
#define IWI_NS iwi27
#endif
#include "Image/DdsWriter.h"
#include "Image/ImageCommon.h"
#include "Image/IwiLoader.h"
#include "ObjWriting.h"
#include "Utils/Logging/Log.h"
#include <algorithm>
#include <cassert>
#include <format>
using namespace GAME;
using namespace image;
namespace
{
std::unique_ptr<Texture> LoadImageFromLoadDef(const GfxImage& image)
{
#ifdef DX9
Dx9TextureLoader textureLoader;
#else
Dx12TextureLoader textureLoader;
#endif
const auto& loadDef = *image.texture.loadDef;
#if defined(FEATURE_IW3) || defined(FEATURE_T4)
textureLoader.Width(loadDef.dimensions[0]).Height(loadDef.dimensions[1]).Depth(loadDef.dimensions[2]);
#else
textureLoader.Width(image.width).Height(image.height).Depth(image.depth);
#endif
#if defined(IWI8)
if ((loadDef.flags & image::IWI_NS::IMG_FLAG_MAPTYPE_MASK) == image::IWI_NS::IMG_FLAG_MAPTYPE_3D)
textureLoader.Type(TextureType::T_3D);
else if ((loadDef.flags & image::IWI_NS::IMG_FLAG_MAPTYPE_MASK) == image::IWI_NS::IMG_FLAG_MAPTYPE_CUBE)
textureLoader.Type(TextureType::T_CUBE);
else
textureLoader.Type(TextureType::T_2D);
#else
if (loadDef.flags & image::IWI_NS::IMG_FLAG_VOLMAP)
textureLoader.Type(TextureType::T_3D);
else if (loadDef.flags & image::IWI_NS::IMG_FLAG_CUBEMAP)
textureLoader.Type(TextureType::T_CUBE);
else
textureLoader.Type(TextureType::T_2D);
#endif
#ifdef DX9
textureLoader.Format(static_cast<oat::D3DFORMAT>(loadDef.format));
#else
textureLoader.Format(static_cast<oat::DXGI_FORMAT>(loadDef.format));
#endif
textureLoader.HasMipMaps(!(loadDef.flags & image::IWI_NS::IMG_FLAG_NOMIPMAPS));
return textureLoader.LoadTexture(loadDef.data);
}
std::unique_ptr<Texture> LoadImageFromIwi(const GfxImage& image, ISearchPath& searchPath)
{
#ifdef FEATURE_T6
if (image.streamedPartCount > 0)
{
for (auto* ipak : IIPak::Repository)
{
auto ipakStream = ipak->GetEntryStream(image.hash, image.streamedParts[0].hash);
if (ipakStream)
{
auto loadResult = image::LoadIwi(*ipakStream);
ipakStream->close();
if (loadResult)
return std::move(loadResult->m_texture);
}
}
}
#endif
const auto imageFileName = image::GetFileNameForAsset(image.name, ".iwi");
const auto filePathImage = searchPath.Open(imageFileName);
if (!filePathImage.IsOpen())
{
con::error("Could not find data for image \"{}\"", image.name);
return nullptr;
}
auto loadResult = image::LoadIwi(*filePathImage.m_stream);
return loadResult ? std::move(loadResult->m_texture) : nullptr;
}
std::unique_ptr<Texture> LoadImageData(ISearchPath& searchPath, const GfxImage& image)
{
if (image.texture.loadDef && image.texture.loadDef->resourceSize > 0)
return LoadImageFromLoadDef(image);
return LoadImageFromIwi(image, searchPath);
}
} // namespace
#set CLASS_NAME "Dumper" + GAME
namespace image
{
CLASS_NAME::CLASS_NAME()
{
switch (ObjWriting::Configuration.ImageOutputFormat)
{
case ImageOutputFormat_e::DDS:
m_writer = std::make_unique<DdsWriter>();
break;
case ImageOutputFormat_e::IWI:
m_writer = std::make_unique<IWI_NS::IwiWriter>();
break;
default:
assert(false);
m_writer = nullptr;
break;
}
}
void CLASS_NAME::DumpAsset(AssetDumpingContext& context, const XAssetInfo<AssetImage::Type>& asset)
{
const auto* image = asset.Asset();
const auto texture = LoadImageData(context.m_obj_search_path, *image);
if (!texture)
return;
if (!m_writer->SupportsImageFormat(texture->GetFormat()))
{
con::warn("Not dumping image {} as {} does not support the image format {}",
image->name,
GetImageOutputFormatName(ObjWriting::Configuration.ImageOutputFormat),
GetImageFormatName(texture->GetFormat()->GetId()));
return;
}
const auto assetFile = context.OpenAssetFile(GetFileNameForAsset(asset.m_name, m_writer->GetFileExtension()));
if (!assetFile)
return;
auto& stream = *assetFile;
m_writer->DumpImage(stream, texture.get());
}
} // namespace image