2
0
mirror of https://github.com/Laupetin/OpenAssetTools.git synced 2025-09-12 19:47:27 +00:00

chore: fix loading and writing code for IW5

This commit is contained in:
Jan
2024-12-28 21:12:24 +01:00
parent 9ae5aaa1db
commit a36581b06e
128 changed files with 1554 additions and 2535 deletions

View File

@@ -1,8 +1,8 @@
#options GAME(IW5, T5, T6)
#filename "Game/" + GAME + "/XModel/XModelLoader" + GAME + ".cpp"
#filename "Game/" + GAME + "/XModel/LoaderXModel" + GAME + ".cpp"
#set LOADER_HEADER "\"XModelLoader" + GAME + ".h\""
#set LOADER_HEADER "\"LoaderXModel" + GAME + ".h\""
#set COMMON_HEADER "\"Game/" + GAME + "/Common" + GAME + ".h\""
#set CONSTANTS_HEADER "\"Game/" + GAME + "/XModel/XModelConstants" + GAME + ".h\""
#set JSON_HEADER "\"Game/" + GAME + "/XModel/JsonXModel" + GAME + ".h\""
@@ -21,6 +21,7 @@
#include CONSTANTS_HEADER
#include JSON_HEADER
#include "Asset/AssetRegistration.h"
#include "ObjLoading.h"
#include "Utils/QuatInt16.h"
#include "Utils/StringUtils.h"
@@ -46,25 +47,43 @@
#include <set>
#include <vector>
namespace GAME
using namespace GAME;
namespace
{
class XModelLoader
class XModelLoader final : public AssetCreator<AssetXModel>
{
public:
XModelLoader(std::istream& stream, MemoryManager& memory, IAssetLoadingManager& manager, std::set<XAssetInfoGeneric*>& dependencies)
: m_stream(stream),
m_memory(memory),
m_script_strings(manager.GetAssetLoadingContext()->m_zone.m_script_strings),
m_manager(manager),
m_part_classification_state(*m_manager.GetAssetLoadingContext()->GetZoneAssetLoaderState<PartClassificationState>()),
m_dependencies(dependencies)
XModelLoader(MemoryManager& memory, ISearchPath& searchPath, ZoneScriptStrings& scriptStrings)
: m_memory(memory),
m_search_path(searchPath),
m_script_strings(scriptStrings)
{
}
bool Load(XModel& xmodel)
AssetCreationResult CreateAsset(const std::string& assetName, AssetCreationContext& context) override
{
const auto jRoot = nlohmann::json::parse(m_stream);
const auto file = m_search_path.Open(std::format("xmodel/{}.json", assetName));
if (!file.IsOpen())
return AssetCreationResult::NoAction();
auto* xmodel = m_memory.Alloc<XModel>();
xmodel->name = m_memory.Dup(assetName.c_str());
AssetRegistration<AssetXModel> registration(assetName, xmodel);
if (!LoadFromFile(*file.m_stream, *xmodel, context, registration))
{
std::cerr << std::format("Failed to load xmodel \"{}\"\n", assetName);
return AssetCreationResult::Failure();
}
return AssetCreationResult::Success(context.AddAsset(std::move(registration)));
}
private:
bool LoadFromFile(std::istream& jsonStream, XModel& xmodel, AssetCreationContext& context, AssetRegistration<AssetXModel>& registration)
{
const auto jRoot = nlohmann::json::parse(jsonStream);
std::string type;
unsigned version;
@@ -80,7 +99,7 @@ namespace GAME
try
{
const auto jXModel = jRoot.get<JsonXModel>();
return CreateXModelFromJson(jXModel, xmodel);
return CreateXModelFromJson(jXModel, xmodel, context, registration);
}
catch (const nlohmann::json::exception& e)
{
@@ -90,7 +109,6 @@ namespace GAME
return false;
}
private:
static void PrintError(const XModel& xmodel, const std::string& message)
{
std::cerr << std::format("Cannot load xmodel \"{}\": {}\n", xmodel.name, message);
@@ -234,12 +252,12 @@ namespace GAME
info.radiusSquared = halfSizeEigen.squaredNorm();
}
bool ApplyCommonBonesToXModel(const JsonXModelLod& jLod, XModel& xmodel, unsigned lodNumber, const XModelCommon& common) const
bool ApplyCommonBonesToXModel(const JsonXModelLod& jLod, XModel& xmodel, unsigned lodNumber, const XModelCommon& common)
{
if (common.m_bones.empty())
return true;
m_part_classification_state.Load(HITLOC_NAMES, std::extent_v<decltype(HITLOC_NAMES)>, m_manager);
m_part_classification_state.Load(HITLOC_NAMES, std::extent_v<decltype(HITLOC_NAMES)>, m_search_path);
const auto boneCount = common.m_bones.size();
constexpr auto maxBones = std::numeric_limits<decltype(XModel::numBones)>::max();
@@ -614,9 +632,9 @@ namespace GAME
return true;
}
bool LoadLod(const JsonXModelLod& jLod, XModel& xmodel, unsigned lodNumber)
bool LoadLod(const JsonXModelLod& jLod, XModel& xmodel, unsigned lodNumber, AssetCreationContext& context, AssetRegistration<AssetXModel>& registration)
{
const auto file = m_manager.GetAssetLoadingContext()->m_raw_search_path.Open(jLod.file);
const auto file = m_search_path.Open(jLod.file);
if (!file.IsOpen())
{
PrintError(xmodel, std::format("Failed to open file for lod {}: \"{}\"", lodNumber, jLod.file));
@@ -664,11 +682,11 @@ namespace GAME
materialAssets.reserve(common->m_materials.size());
for (const auto& commonMaterial : common->m_materials)
{
auto* assetInfo = m_manager.LoadDependency<AssetMaterial>(commonMaterial.name);
auto* assetInfo = context.LoadDependency<AssetMaterial>(commonMaterial.name);
if (!assetInfo)
return false;
m_dependencies.emplace(assetInfo);
registration.AddDependency(assetInfo);
materialAssets.push_back(assetInfo->Asset());
}
@@ -712,7 +730,7 @@ namespace GAME
modelSurfs->surfs = m_memory.Alloc<XSurface>(modelSurfs->numsurfs);
memcpy(modelSurfs->surfs, &m_surfaces[lodInfo.surfIndex], sizeof(XSurface) * modelSurfs->numsurfs);
m_manager.AddAsset<AssetXModelSurfs>(modelSurfsName, modelSurfs);
registration.AddDependency(context.AddAsset<AssetXModelSurfs>(modelSurfsName, modelSurfs));
lodInfo.modelSurfs = modelSurfs;
lodInfo.surfs = modelSurfs->surfs;
@@ -785,7 +803,7 @@ namespace GAME
#endif
}
bool CreateXModelFromJson(const JsonXModel& jXModel, XModel& xmodel)
bool CreateXModelFromJson(const JsonXModel& jXModel, XModel& xmodel, AssetCreationContext& context, AssetRegistration<AssetXModel>& registration)
{
constexpr auto maxLods = std::extent_v<decltype(XModel::lodInfo)>;
if (jXModel.lods.size() > maxLods)
@@ -798,7 +816,7 @@ namespace GAME
xmodel.numLods = static_cast<decltype(XModel::numLods)>(jXModel.lods.size());
for (const auto& jLod : jXModel.lods)
{
if (!LoadLod(jLod, xmodel, lodNumber++))
if (!LoadLod(jLod, xmodel, lodNumber++, context, registration))
return false;
}
@@ -835,13 +853,13 @@ namespace GAME
if (jXModel.physPreset)
{
auto* physPreset = m_manager.LoadDependency<AssetPhysPreset>(jXModel.physPreset.value());
auto* physPreset = context.LoadDependency<AssetPhysPreset>(jXModel.physPreset.value());
if (!physPreset)
{
PrintError(xmodel, "Could not find phys preset");
return false;
}
m_dependencies.emplace(physPreset);
registration.AddDependency(physPreset);
xmodel.physPreset = physPreset->Asset();
}
else
@@ -852,13 +870,13 @@ namespace GAME
#if defined(FEATURE_IW5)
if (jXModel.physCollmap)
{
auto* physCollmap = m_manager.LoadDependency<AssetPhysCollMap>(jXModel.physCollmap.value());
auto* physCollmap = context.LoadDependency<AssetPhysCollMap>(jXModel.physCollmap.value());
if (!physCollmap)
{
PrintError(xmodel, "Could not find phys collmap");
return false;
}
m_dependencies.emplace(physCollmap);
registration.AddDependency(physCollmap);
xmodel.physCollmap = physCollmap->Asset();
}
else
@@ -870,13 +888,13 @@ namespace GAME
#if defined(FEATURE_T5) || defined(FEATURE_T6)
if (jXModel.physConstraints)
{
auto* physConstraints = m_manager.LoadDependency<AssetPhysConstraints>(jXModel.physConstraints.value());
auto* physConstraints = context.LoadDependency<AssetPhysConstraints>(jXModel.physConstraints.value());
if (!physConstraints)
{
PrintError(xmodel, "Could not find phys constraints");
return false;
}
m_dependencies.emplace(physConstraints);
registration.AddDependency(physConstraints);
xmodel.physConstraints = physConstraints->Asset();
}
else
@@ -900,21 +918,17 @@ namespace GAME
std::vector<XSurface> m_surfaces;
std::vector<Material*> m_materials;
std::istream& m_stream;
MemoryManager& m_memory;
ISearchPath& m_search_path;
ZoneScriptStrings& m_script_strings;
IAssetLoadingManager& m_manager;
PartClassificationState& m_part_classification_state;
std::set<XAssetInfoGeneric*>& m_dependencies;
PartClassificationState m_part_classification_state;
};
} // namespace GAME
bool LoadXModel(std::istream& stream, XModel& xmodel, MemoryManager* memory, IAssetLoadingManager* manager, std::vector<XAssetInfoGeneric*>& dependencies)
namespace GAME
{
std::unique_ptr<AssetCreator<AssetXModel>> CreateXModelLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone)
{
std::set<XAssetInfoGeneric*> dependenciesSet;
XModelLoader loader(stream, *memory, *manager, dependenciesSet);
dependencies.assign(dependenciesSet.cbegin(), dependenciesSet.cend());
return loader.Load(xmodel);
return std::make_unique<XModelLoader>(memory, searchPath, zone.m_script_strings);
}
} // namespace GAME

View File

@@ -0,0 +1,19 @@
#options GAME (IW5, T5, T6)
#filename "Game/" + GAME + "/XModel/LoaderXModel" + GAME + ".h"
#set GAME_HEADER "\"Game/" + GAME + "/" + GAME + ".h\""
#pragma once
#include "Asset/IAssetCreator.h"
#include GAME_HEADER
#include "SearchPath/ISearchPath.h"
#include "Utils/MemoryManager.h"
#include <memory>
namespace GAME
{
std::unique_ptr<AssetCreator<AssetXModel>> CreateXModelLoader(MemoryManager& memory, ISearchPath& searchPath, Zone& zone);
} // namespace GAME

View File

@@ -12,7 +12,7 @@ PartClassificationState::PartClassificationState()
{
}
bool PartClassificationState::Load(const char** hitLocNames, const size_t hitLocNameCount, const IAssetLoadingManager& manager)
bool PartClassificationState::Load(const char** hitLocNames, const size_t hitLocNameCount, ISearchPath& searchPath)
{
if (m_loaded)
return true;
@@ -20,7 +20,7 @@ bool PartClassificationState::Load(const char** hitLocNames, const size_t hitLoc
if (ObjLoading::Configuration.Verbose)
std::cout << "Loading part classification...\n";
const auto file = manager.GetAssetLoadingContext()->m_raw_search_path.Open(PART_CLASSIFICATION_FILE);
const auto file = searchPath.Open(PART_CLASSIFICATION_FILE);
if (!file.IsOpen())
{
std::cerr << std::format("Could not load part classification: Failed to open {}\n", PART_CLASSIFICATION_FILE);

View File

@@ -1,8 +1,13 @@
#pragma once
#include "AssetLoading/IAssetLoadingManager.h"
#include "AssetLoading/IZoneAssetLoaderState.h"
class PartClassificationState final : public IZoneAssetLoaderState
#include "SearchPath/ISearchPath.h"
#include <cstdint>
#include <string>
#include <unordered_map>
#include <vector>
class PartClassificationState
{
// TODO: Use MP part classifications when building an mp fastfile
static constexpr auto PART_CLASSIFICATION_FILE = "partclassification.csv";
@@ -12,7 +17,7 @@ class PartClassificationState final : public IZoneAssetLoaderState
public:
PartClassificationState();
bool Load(const char** hitLocNames, size_t hitLocNameCount, const IAssetLoadingManager& manager);
bool Load(const char** hitLocNames, size_t hitLocNameCount, ISearchPath& searchPath);
[[nodiscard]] unsigned GetPartClassificationForBoneName(const std::string& boneName) const;

View File

@@ -1,19 +0,0 @@
#options GAME (IW5, T5, T6)
#filename "Game/" + GAME + "/XModel/XModelLoader" + GAME + ".h"
#set GAME_HEADER "\"Game/" + GAME + "/" + GAME + ".h\""
#pragma once
#include "AssetLoading/IAssetLoadingManager.h"
#include GAME_HEADER
#include "Utils/MemoryManager.h"
#include <istream>
#include <vector>
namespace GAME
{
bool LoadXModel(std::istream& stream, XModel& xmodel, MemoryManager* memory, IAssetLoadingManager* manager, std::vector<XAssetInfoGeneric*>& dependencies);
}