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:
@@ -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
|
19
src/ObjLoading/XModel/LoaderXModel.h.template
Normal file
19
src/ObjLoading/XModel/LoaderXModel.h.template
Normal 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
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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);
|
||||
}
|
Reference in New Issue
Block a user