refactor: image and obj data loading

This commit is contained in:
Jan
2024-09-24 12:01:42 +01:00
parent 5fee875495
commit 5cc52c42cd
97 changed files with 1784 additions and 1878 deletions

View File

@ -1,6 +1,6 @@
#include "AssetLoadingContext.h"
AssetLoadingContext::AssetLoadingContext(Zone* zone, ISearchPath* rawSearchPath, std::vector<Gdt*> gdtFiles)
AssetLoadingContext::AssetLoadingContext(Zone& zone, ISearchPath& rawSearchPath, std::vector<Gdt*> gdtFiles)
: m_zone(zone),
m_raw_search_path(rawSearchPath),
m_gdt_files(std::move(gdtFiles))
@ -10,7 +10,7 @@ AssetLoadingContext::AssetLoadingContext(Zone* zone, ISearchPath* rawSearchPath,
void AssetLoadingContext::BuildGdtEntryCache()
{
for (auto* gdt : m_gdt_files)
for (const auto* gdt : m_gdt_files)
{
for (const auto& entry : gdt->m_entries)
{

View File

@ -12,18 +12,8 @@
class AssetLoadingContext final : public IGdtQueryable
{
std::unordered_map<std::string, std::unordered_map<std::string, GdtEntry*>> m_entries_by_gdf_and_by_name;
std::unordered_map<std::type_index, std::unique_ptr<IZoneAssetLoaderState>> m_zone_asset_loader_states;
void BuildGdtEntryCache();
public:
Zone* const m_zone;
ISearchPath* const m_raw_search_path;
const std::vector<Gdt*> m_gdt_files;
std::unordered_map<std::string, asset_type_t> m_ignored_asset_map;
AssetLoadingContext(Zone* zone, ISearchPath* rawSearchPath, std::vector<Gdt*> gdtFiles);
AssetLoadingContext(Zone& zone, ISearchPath& rawSearchPath, std::vector<Gdt*> gdtFiles);
GdtEntry* GetGdtEntryByGdfAndName(const std::string& gdfName, const std::string& entryName) override;
template<typename T> T* GetZoneAssetLoaderState()
@ -36,9 +26,21 @@ public:
return dynamic_cast<T*>(foundEntry->second.get());
auto newState = std::make_unique<T>();
newState->SetZone(m_zone);
newState->SetZone(&m_zone);
auto* newStatePtr = newState.get();
m_zone_asset_loader_states.emplace(std::make_pair<std::type_index, std::unique_ptr<IZoneAssetLoaderState>>(typeid(T), std::move(newState)));
return newStatePtr;
}
private:
void BuildGdtEntryCache();
public:
Zone& m_zone;
ISearchPath& m_raw_search_path;
const std::vector<Gdt*> m_gdt_files;
std::unordered_map<std::string, asset_type_t> m_ignored_asset_map;
std::unordered_map<std::string, std::unordered_map<std::string, GdtEntry*>> m_entries_by_gdf_and_by_name;
std::unordered_map<std::type_index, std::unique_ptr<IZoneAssetLoaderState>> m_zone_asset_loader_states;
};

View File

@ -6,7 +6,8 @@
#include <format>
#include <iostream>
AssetLoadingManager::AssetLoadingManager(const std::map<asset_type_t, std::unique_ptr<IAssetLoader>>& assetLoadersByType, AssetLoadingContext& context)
AssetLoadingManager::AssetLoadingManager(const std::unordered_map<asset_type_t, std::unique_ptr<IAssetLoader>>& assetLoadersByType,
AssetLoadingContext& context)
: m_asset_loaders_by_type(assetLoadersByType),
m_context(context),
m_last_dependency_loaded(nullptr)
@ -28,26 +29,26 @@ XAssetInfoGeneric* AssetLoadingManager::AddAssetInternal(std::unique_ptr<XAssetI
const auto assetType = xAssetInfo->m_type;
const auto* pAssetName = xAssetInfo->m_name.c_str();
m_last_dependency_loaded = m_context.m_zone->m_pools->AddAsset(std::move(xAssetInfo));
m_last_dependency_loaded = m_context.m_zone.m_pools->AddAsset(std::move(xAssetInfo));
if (m_last_dependency_loaded == nullptr)
std::cerr << "Failed to add asset of type \"" << m_context.m_zone->m_pools->GetAssetTypeName(assetType) << "\" to pool: \"" << pAssetName << "\"\n";
std::cerr << std::format("Failed to add asset of type \"{}\" to pool: \"{}\"\n", m_context.m_zone.m_pools->GetAssetTypeName(assetType), pAssetName);
return m_last_dependency_loaded;
}
XAssetInfoGeneric* AssetLoadingManager::AddAsset(std::unique_ptr<XAssetInfoGeneric> xAssetInfo)
{
xAssetInfo->m_zone = m_context.m_zone;
xAssetInfo->m_zone = &m_context.m_zone;
return AddAssetInternal(std::move(xAssetInfo));
}
XAssetInfoGeneric* AssetLoadingManager::LoadIgnoredDependency(const asset_type_t assetType, const std::string& assetName, IAssetLoader* loader)
{
auto* alreadyLoadedAsset = m_context.m_zone->m_pools->GetAssetOrAssetReference(assetType, assetName);
auto* alreadyLoadedAsset = m_context.m_zone.m_pools->GetAssetOrAssetReference(assetType, assetName);
if (alreadyLoadedAsset)
return alreadyLoadedAsset;
auto* linkAsset = loader->CreateEmptyAsset(assetName, m_context.m_zone->GetMemory());
auto* linkAsset = loader->CreateEmptyAsset(assetName, m_context.m_zone.GetMemory());
if (linkAsset)
{
AddAsset(std::make_unique<XAssetInfoGeneric>(assetType, assetName, linkAsset));
@ -65,21 +66,21 @@ XAssetInfoGeneric* AssetLoadingManager::LoadIgnoredDependency(const asset_type_t
return lastDependency;
}
std::cerr << "Failed to create empty asset \"" << assetName << "\" for type \"" << m_context.m_zone->m_pools->GetAssetTypeName(assetType) << "\"\n";
std::cerr << std::format("Failed to create empty asset \"{}\" for type \"{}\"\n", assetName, m_context.m_zone.m_pools->GetAssetTypeName(assetType));
return nullptr;
}
XAssetInfoGeneric* AssetLoadingManager::LoadAssetDependency(const asset_type_t assetType, const std::string& assetName, const IAssetLoader* loader)
{
if (loader->CanLoadFromGdt() && !m_context.m_gdt_files.empty()
&& loader->LoadFromGdt(assetName, &m_context, m_context.m_zone->GetMemory(), this, m_context.m_zone))
&& loader->LoadFromGdt(assetName, &m_context, m_context.m_zone.GetMemory(), this, &m_context.m_zone))
{
auto* lastDependency = m_last_dependency_loaded;
m_last_dependency_loaded = nullptr;
return lastDependency;
}
if (loader->CanLoadFromRaw() && loader->LoadFromRaw(assetName, m_context.m_raw_search_path, m_context.m_zone->GetMemory(), this, m_context.m_zone))
if (loader->CanLoadFromRaw() && loader->LoadFromRaw(assetName, &m_context.m_raw_search_path, m_context.m_zone.GetMemory(), this, &m_context.m_zone))
{
auto* lastDependency = m_last_dependency_loaded;
m_last_dependency_loaded = nullptr;
@ -110,7 +111,7 @@ XAssetInfoGeneric* AssetLoadingManager::LoadAssetDependency(const asset_type_t a
// Make sure any used script string is available in the created zone
// The replacement of the scr_string_t values will be done upon writing
for (const auto scrString : existingAsset->m_used_script_strings)
m_context.m_zone->m_script_strings.AddOrGetScriptString(existingAsset->m_zone->m_script_strings.CValue(scrString));
m_context.m_zone.m_script_strings.AddOrGetScriptString(existingAsset->m_zone->m_script_strings.CValue(scrString));
AddAssetInternal(std::make_unique<XAssetInfoGeneric>(existingAsset->m_type,
existingAsset->m_name,
@ -125,13 +126,13 @@ XAssetInfoGeneric* AssetLoadingManager::LoadAssetDependency(const asset_type_t a
return lastDependency;
}
std::cerr << "Failed to load asset of type \"" << m_context.m_zone->m_pools->GetAssetTypeName(assetType) << "\": \"" << assetName << "\"\n";
std::cerr << std::format("Failed to load asset of type \"{}\": \"{}\"\n", m_context.m_zone.m_pools->GetAssetTypeName(assetType), assetName);
return nullptr;
}
XAssetInfoGeneric* AssetLoadingManager::LoadDependency(const asset_type_t assetType, const std::string& assetName)
{
auto* alreadyLoadedAsset = m_context.m_zone->m_pools->GetAssetOrAssetReference(assetType, assetName);
auto* alreadyLoadedAsset = m_context.m_zone.m_pools->GetAssetOrAssetReference(assetType, assetName);
if (alreadyLoadedAsset)
return alreadyLoadedAsset;
@ -149,13 +150,13 @@ XAssetInfoGeneric* AssetLoadingManager::LoadDependency(const asset_type_t assetT
return LoadAssetDependency(assetType, assetName, loader->second.get());
}
std::cerr << "Failed to find loader for asset type \"" << m_context.m_zone->m_pools->GetAssetTypeName(assetType) << "\"\n";
std::cerr << std::format("Failed to find loader for asset type \"{}\"\n", m_context.m_zone.m_pools->GetAssetTypeName(assetType));
return nullptr;
}
IndirectAssetReference AssetLoadingManager::LoadIndirectAssetReference(const asset_type_t assetType, const std::string& assetName)
{
const auto* alreadyLoadedAsset = m_context.m_zone->m_pools->GetAssetOrAssetReference(assetType, assetName);
const auto* alreadyLoadedAsset = m_context.m_zone.m_pools->GetAssetOrAssetReference(assetType, assetName);
if (alreadyLoadedAsset)
return IndirectAssetReference(assetType, assetName);
@ -170,6 +171,6 @@ IndirectAssetReference AssetLoadingManager::LoadIndirectAssetReference(const ass
return IndirectAssetReference(assetType, assetName);
}
std::cerr << "Failed to find loader for asset type \"" << m_context.m_zone->m_pools->GetAssetTypeName(assetType) << "\"\n";
std::cerr << std::format("Failed to find loader for asset type \"{}\"\n", m_context.m_zone.m_pools->GetAssetTypeName(assetType));
return IndirectAssetReference(assetType, assetName);
}

View File

@ -4,12 +4,12 @@
#include "IAssetLoader.h"
#include "IAssetLoadingManager.h"
#include <map>
#include <unordered_map>
class AssetLoadingManager final : public IAssetLoadingManager
{
public:
AssetLoadingManager(const std::map<asset_type_t, std::unique_ptr<IAssetLoader>>& assetLoadersByType, AssetLoadingContext& context);
AssetLoadingManager(const std::unordered_map<asset_type_t, std::unique_ptr<IAssetLoader>>& assetLoadersByType, AssetLoadingContext& context);
bool LoadAssetFromLoader(asset_type_t assetType, const std::string& assetName);
@ -25,7 +25,7 @@ private:
XAssetInfoGeneric* AddAssetInternal(std::unique_ptr<XAssetInfoGeneric> xAssetInfo);
const std::map<asset_type_t, std::unique_ptr<IAssetLoader>>& m_asset_loaders_by_type;
const std::unordered_map<asset_type_t, std::unique_ptr<IAssetLoader>>& m_asset_loaders_by_type;
AssetLoadingContext& m_context;
XAssetInfoGeneric* m_last_dependency_loaded;
};

View File

@ -46,7 +46,7 @@ public:
return false;
}
virtual void FinalizeAssetsForZone(AssetLoadingContext* context) const
virtual void FinalizeAssetsForZone(AssetLoadingContext& context) const
{
// Do nothing by default
}

View File

@ -5,7 +5,9 @@
#include "Image/IwiTypes.h"
#include "Pool/GlobalAssetPool.h"
#include <algorithm>
#include <cstring>
#include <format>
#include <iostream>
using namespace IW3;
@ -32,20 +34,9 @@ bool AssetLoaderGfxImage::LoadFromRaw(
return false;
std::string safeAssetName = assetName;
for (auto& c : safeAssetName)
{
switch (c)
{
case '*':
c = '_';
break;
std::ranges::replace(safeAssetName, '*', '_');
default:
break;
}
}
const auto file = searchPath->Open("images/" + safeAssetName + ".dds");
const auto file = searchPath->Open(std::format("images/{}.dds", safeAssetName));
if (!file.IsOpen())
return false;
@ -54,7 +45,7 @@ bool AssetLoaderGfxImage::LoadFromRaw(
if (texture == nullptr)
{
std::cout << "Failed to load dds file for image asset \"" << assetName << "\"\n";
std::cout << std::format("Failed to load dds file for image asset \"{}\"\n", assetName);
return false;
}

View File

@ -4,13 +4,7 @@
#include "AssetLoaders/AssetLoaderLocalizeEntry.h"
#include "AssetLoaders/AssetLoaderRawFile.h"
#include "AssetLoading/AssetLoadingManager.h"
#include "Game/IW3/GameAssetPoolIW3.h"
#include "Game/IW3/GameIW3.h"
#include "Image/Dx9TextureLoader.h"
#include "Image/IwiLoader.h"
#include "Image/IwiTypes.h"
#include "Image/Texture.h"
#include "ObjContainer/IPak/IPak.h"
#include "ObjLoading.h"
using namespace IW3;
@ -54,129 +48,32 @@ ObjLoader::ObjLoader()
#undef REGISTER_ASSET_LOADER
}
bool ObjLoader::SupportsZone(Zone* zone) const
bool ObjLoader::SupportsZone(const Zone& zone) const
{
return zone->m_game == &g_GameIW3;
return zone.m_game == &g_GameIW3;
}
bool ObjLoader::IsMpZone(Zone* zone)
bool ObjLoader::IsMpZone(const Zone& zone)
{
return zone->m_name.compare(0, 3, "mp_") == 0 || zone->m_name.compare(zone->m_name.length() - 3, 3, "_mp") == 0;
return zone.m_name.compare(0, 3, "mp_") == 0 || zone.m_name.compare(zone.m_name.length() - 3, 3, "_mp") == 0;
}
bool ObjLoader::IsZmZone(Zone* zone)
bool ObjLoader::IsZmZone(const Zone& zone)
{
return zone->m_name.compare(0, 3, "zm_") == 0 || zone->m_name.compare(zone->m_name.length() - 3, 3, "_zm") == 0;
return zone.m_name.compare(0, 3, "zm_") == 0 || zone.m_name.compare(zone.m_name.length() - 3, 3, "_zm") == 0;
}
void ObjLoader::LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone) const {}
void ObjLoader::LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone) const {}
void ObjLoader::UnloadContainersOfZone(Zone* zone) const {}
void ObjLoader::UnloadContainersOfZone(Zone& zone) const {}
void ObjLoader::LoadImageFromLoadDef(GfxImage* image, Zone* zone)
bool ObjLoader::LoadAssetForZone(AssetLoadingContext& context, const asset_type_t assetType, const std::string& assetName) const
{
const auto* loadDef = image->texture.loadDef;
Dx9TextureLoader textureLoader(zone->GetMemory());
textureLoader.Width(loadDef->dimensions[0]).Height(loadDef->dimensions[1]).Depth(loadDef->dimensions[2]);
if (loadDef->flags & iwi6::IMG_FLAG_VOLMAP)
textureLoader.Type(TextureType::T_3D);
else if (loadDef->flags & iwi6::IMG_FLAG_CUBEMAP)
textureLoader.Type(TextureType::T_CUBE);
else
textureLoader.Type(TextureType::T_2D);
textureLoader.Format(static_cast<oat::D3DFORMAT>(loadDef->format));
textureLoader.HasMipMaps(!(loadDef->flags & iwi6::IMG_FLAG_NOMIPMAPS));
Texture* loadedTexture = textureLoader.LoadTexture(image->texture.loadDef->data);
if (loadedTexture != nullptr)
{
image->texture.texture = loadedTexture;
image->cardMemory.platform[0] = 0;
const auto textureMipCount = loadedTexture->GetMipMapCount();
for (auto mipLevel = 0; mipLevel < textureMipCount; mipLevel++)
image->cardMemory.platform[0] += static_cast<int>(loadedTexture->GetSizeOfMipLevel(mipLevel) * loadedTexture->GetFaceCount());
}
}
void ObjLoader::LoadImageFromIwi(GfxImage* image, ISearchPath* searchPath, Zone* zone)
{
Texture* loadedTexture = nullptr;
IwiLoader loader(zone->GetMemory());
const auto imageFileName = "images/" + std::string(image->name) + ".iwi";
{
const auto filePathImage = searchPath->Open(imageFileName);
if (filePathImage.IsOpen())
{
loadedTexture = loader.LoadIwi(*filePathImage.m_stream);
}
}
if (loadedTexture != nullptr)
{
image->texture.texture = loadedTexture;
image->cardMemory.platform[0] = 0;
const auto textureMipCount = loadedTexture->GetMipMapCount();
for (auto mipLevel = 0; mipLevel < textureMipCount; mipLevel++)
image->cardMemory.platform[0] += static_cast<int>(loadedTexture->GetSizeOfMipLevel(mipLevel) * loadedTexture->GetFaceCount());
}
else
{
printf("Could not find data for image \"%s\"\n", image->name);
}
}
void ObjLoader::LoadImageData(ISearchPath* searchPath, Zone* zone)
{
auto* assetPool = dynamic_cast<GameAssetPoolIW3*>(zone->m_pools.get());
if (assetPool && assetPool->m_image != nullptr)
{
for (auto* imageEntry : *assetPool->m_image)
{
auto* image = imageEntry->Asset();
if (image->cardMemory.platform[0] > 0)
{
continue;
}
// Do not load linked assets
if (image->name && image->name[0] == ',')
{
continue;
}
if (image->texture.loadDef && image->texture.loadDef->resourceSize > 0)
{
LoadImageFromLoadDef(image, zone);
}
else
{
LoadImageFromIwi(image, searchPath, zone);
}
}
}
}
void ObjLoader::LoadObjDataForZone(ISearchPath* searchPath, Zone* zone) const
{
LoadImageData(searchPath, zone);
}
bool ObjLoader::LoadAssetForZone(AssetLoadingContext* context, const asset_type_t assetType, const std::string& assetName) const
{
AssetLoadingManager assetLoadingManager(m_asset_loaders_by_type, *context);
AssetLoadingManager assetLoadingManager(m_asset_loaders_by_type, context);
return assetLoadingManager.LoadAssetFromLoader(assetType, assetName);
}
void ObjLoader::FinalizeAssetsForZone(AssetLoadingContext* context) const
void ObjLoader::FinalizeAssetsForZone(AssetLoadingContext& context) const
{
for (const auto& [type, loader] : m_asset_loaders_by_type)
loader->FinalizeAssetsForZone(context);

View File

@ -1,37 +1,30 @@
#pragma once
#include "AssetLoading/IAssetLoader.h"
#include "Game/IW3/IW3.h"
#include "IObjLoader.h"
#include "SearchPath/ISearchPath.h"
#include <map>
#include <memory>
#include <unordered_map>
namespace IW3
{
class ObjLoader final : public IObjLoader
{
std::map<asset_type_t, std::unique_ptr<IAssetLoader>> m_asset_loaders_by_type;
std::unordered_map<asset_type_t, std::unique_ptr<IAssetLoader>> m_asset_loaders_by_type;
static void LoadImageFromIwi(GfxImage* image, ISearchPath* searchPath, Zone* zone);
static void LoadImageFromLoadDef(GfxImage* image, Zone* zone);
static void LoadImageData(ISearchPath* searchPath, Zone* zone);
static bool IsMpZone(Zone* zone);
static bool IsZmZone(Zone* zone);
static bool IsMpZone(const Zone& zone);
static bool IsZmZone(const Zone& zone);
public:
ObjLoader();
bool SupportsZone(Zone* zone) const override;
[[nodiscard]] bool SupportsZone(const Zone& zone) const override;
void LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone) const override;
void UnloadContainersOfZone(Zone* zone) const override;
void LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone) const override;
void UnloadContainersOfZone(Zone& zone) const override;
void LoadObjDataForZone(ISearchPath* searchPath, Zone* zone) const override;
bool LoadAssetForZone(AssetLoadingContext* context, asset_type_t assetType, const std::string& assetName) const override;
void FinalizeAssetsForZone(AssetLoadingContext* context) const override;
bool LoadAssetForZone(AssetLoadingContext& context, asset_type_t assetType, const std::string& assetName) const override;
void FinalizeAssetsForZone(AssetLoadingContext& context) const override;
};
} // namespace IW3

View File

@ -820,10 +820,10 @@ namespace IW4
m_material->techniqueSet = techset->Asset();
auto* loadingContext = m_manager->GetAssetLoadingContext();
auto* searchPath = loadingContext->m_raw_search_path;
auto& searchPath = loadingContext->m_raw_search_path;
auto* definitionCache = loadingContext->GetZoneAssetLoaderState<techset::TechsetDefinitionCache>();
const auto* techsetDefinition = AssetLoaderTechniqueSet::LoadTechsetDefinition(techsetName, searchPath, definitionCache);
const auto* techsetDefinition = AssetLoaderTechniqueSet::LoadTechsetDefinition(techsetName, &searchPath, definitionCache);
if (techsetDefinition == nullptr)
{
std::ostringstream ss;
@ -1375,7 +1375,7 @@ bool AssetLoaderMaterial::LoadFromGdt(
if (!entry)
return false;
MaterialGdtLoader loader(*entry, memory, manager->GetAssetLoadingContext()->m_raw_search_path, manager);
MaterialGdtLoader loader(*entry, memory, &manager->GetAssetLoadingContext()->m_raw_search_path, manager);
try
{

View File

@ -227,7 +227,7 @@ bool AssetLoaderMenuList::LoadFromRaw(
return true;
}
void AssetLoaderMenuList::FinalizeAssetsForZone(AssetLoadingContext* context) const
void AssetLoaderMenuList::FinalizeAssetsForZone(AssetLoadingContext& context) const
{
context->GetZoneAssetLoaderState<MenuConversionZoneState>()->FinalizeSupportingData();
context.GetZoneAssetLoaderState<MenuConversionZoneState>()->FinalizeSupportingData();
}

View File

@ -14,6 +14,6 @@ namespace IW4
_NODISCARD bool CanLoadFromRaw() const override;
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
void FinalizeAssetsForZone(AssetLoadingContext* context) const override;
void FinalizeAssetsForZone(AssetLoadingContext& context) const override;
};
} // namespace IW4

View File

@ -37,14 +37,9 @@
#include "AssetLoaders/AssetLoaderXModel.h"
#include "AssetLoaders/AssetLoaderXModelSurfs.h"
#include "AssetLoading/AssetLoadingManager.h"
#include "Game/IW4/GameAssetPoolIW4.h"
#include "Game/IW4/GameIW4.h"
#include "Image/Dx9TextureLoader.h"
#include "Image/IwiLoader.h"
#include "Image/IwiTypes.h"
#include "Image/Texture.h"
#include "ObjContainer/IPak/IPak.h"
#include "ObjLoading.h"
using namespace IW4;
@ -97,129 +92,32 @@ ObjLoader::ObjLoader()
#undef REGISTER_ASSET_LOADER
}
bool ObjLoader::SupportsZone(Zone* zone) const
bool ObjLoader::SupportsZone(const Zone& zone) const
{
return zone->m_game == &g_GameIW4;
return zone.m_game == &g_GameIW4;
}
bool ObjLoader::IsMpZone(Zone* zone)
bool ObjLoader::IsMpZone(const Zone& zone)
{
return zone->m_name.compare(0, 3, "mp_") == 0 || zone->m_name.compare(zone->m_name.length() - 3, 3, "_mp") == 0;
return zone.m_name.compare(0, 3, "mp_") == 0 || zone.m_name.compare(zone.m_name.length() - 3, 3, "_mp") == 0;
}
bool ObjLoader::IsZmZone(Zone* zone)
bool ObjLoader::IsZmZone(const Zone& zone)
{
return zone->m_name.compare(0, 3, "zm_") == 0 || zone->m_name.compare(zone->m_name.length() - 3, 3, "_zm") == 0;
return zone.m_name.compare(0, 3, "zm_") == 0 || zone.m_name.compare(zone.m_name.length() - 3, 3, "_zm") == 0;
}
void ObjLoader::LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone) const {}
void ObjLoader::LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone) const {}
void ObjLoader::UnloadContainersOfZone(Zone* zone) const {}
void ObjLoader::UnloadContainersOfZone(Zone& zone) const {}
void ObjLoader::LoadImageFromLoadDef(GfxImage* image, Zone* zone)
bool ObjLoader::LoadAssetForZone(AssetLoadingContext& context, asset_type_t assetType, const std::string& assetName) const
{
const auto* loadDef = image->texture.loadDef;
Dx9TextureLoader textureLoader(zone->GetMemory());
textureLoader.Width(image->width).Height(image->height).Depth(image->depth);
if ((loadDef->flags & iwi8::IMG_FLAG_MAPTYPE_MASK) == iwi8::IMG_FLAG_MAPTYPE_3D)
textureLoader.Type(TextureType::T_3D);
else if ((loadDef->flags & iwi8::IMG_FLAG_MAPTYPE_MASK) == iwi8::IMG_FLAG_MAPTYPE_CUBE)
textureLoader.Type(TextureType::T_CUBE);
else
textureLoader.Type(TextureType::T_2D);
textureLoader.Format(static_cast<oat::D3DFORMAT>(loadDef->format));
textureLoader.HasMipMaps(!(loadDef->flags & iwi8::IMG_FLAG_NOMIPMAPS));
Texture* loadedTexture = textureLoader.LoadTexture(image->texture.loadDef->data);
if (loadedTexture != nullptr)
{
image->texture.texture = loadedTexture;
image->cardMemory.platform[0] = 0;
const auto textureMipCount = loadedTexture->GetMipMapCount();
for (auto mipLevel = 0; mipLevel < textureMipCount; mipLevel++)
image->cardMemory.platform[0] += static_cast<int>(loadedTexture->GetSizeOfMipLevel(mipLevel) * loadedTexture->GetFaceCount());
}
}
void ObjLoader::LoadImageFromIwi(GfxImage* image, ISearchPath* searchPath, Zone* zone)
{
Texture* loadedTexture = nullptr;
IwiLoader loader(zone->GetMemory());
const auto imageFileName = "images/" + std::string(image->name) + ".iwi";
{
const auto filePathImage = searchPath->Open(imageFileName);
if (filePathImage.IsOpen())
{
loadedTexture = loader.LoadIwi(*filePathImage.m_stream);
}
}
if (loadedTexture != nullptr)
{
image->texture.texture = loadedTexture;
image->cardMemory.platform[0] = 0;
const auto textureMipCount = loadedTexture->GetMipMapCount();
for (auto mipLevel = 0; mipLevel < textureMipCount; mipLevel++)
image->cardMemory.platform[0] += static_cast<int>(loadedTexture->GetSizeOfMipLevel(mipLevel) * loadedTexture->GetFaceCount());
}
else
{
printf("Could not find data for image \"%s\"\n", image->name);
}
}
void ObjLoader::LoadImageData(ISearchPath* searchPath, Zone* zone)
{
auto* assetPool = dynamic_cast<GameAssetPoolIW4*>(zone->m_pools.get());
if (assetPool && assetPool->m_image != nullptr)
{
for (auto* imageEntry : *assetPool->m_image)
{
auto* image = imageEntry->Asset();
if (image->cardMemory.platform[0] > 0)
{
continue;
}
// Do not load linked assets
if (image->name && image->name[0] == ',')
{
continue;
}
if (image->texture.loadDef && image->texture.loadDef->resourceSize > 0)
{
LoadImageFromLoadDef(image, zone);
}
else
{
LoadImageFromIwi(image, searchPath, zone);
}
}
}
}
void ObjLoader::LoadObjDataForZone(ISearchPath* searchPath, Zone* zone) const
{
LoadImageData(searchPath, zone);
}
bool ObjLoader::LoadAssetForZone(AssetLoadingContext* context, asset_type_t assetType, const std::string& assetName) const
{
AssetLoadingManager assetLoadingManager(m_asset_loaders_by_type, *context);
AssetLoadingManager assetLoadingManager(m_asset_loaders_by_type, context);
return assetLoadingManager.LoadAssetFromLoader(assetType, assetName);
}
void ObjLoader::FinalizeAssetsForZone(AssetLoadingContext* context) const
void ObjLoader::FinalizeAssetsForZone(AssetLoadingContext& context) const
{
for (const auto& [type, loader] : m_asset_loaders_by_type)
loader->FinalizeAssetsForZone(context);

View File

@ -1,37 +1,31 @@
#pragma once
#include "AssetLoading/IAssetLoader.h"
#include "Game/IW4/IW4.h"
#include "IObjLoader.h"
#include "SearchPath/ISearchPath.h"
#include <map>
#include <memory>
#include <unordered_map>
namespace IW4
{
class ObjLoader final : public IObjLoader
{
std::map<asset_type_t, std::unique_ptr<IAssetLoader>> m_asset_loaders_by_type;
static void LoadImageFromIwi(GfxImage* image, ISearchPath* searchPath, Zone* zone);
static void LoadImageFromLoadDef(GfxImage* image, Zone* zone);
static void LoadImageData(ISearchPath* searchPath, Zone* zone);
static bool IsMpZone(Zone* zone);
static bool IsZmZone(Zone* zone);
public:
ObjLoader();
bool SupportsZone(Zone* zone) const override;
[[nodiscard]] bool SupportsZone(const Zone& zone) const override;
void LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone) const override;
void UnloadContainersOfZone(Zone* zone) const override;
void LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone) const override;
void UnloadContainersOfZone(Zone& zone) const override;
void LoadObjDataForZone(ISearchPath* searchPath, Zone* zone) const override;
bool LoadAssetForZone(AssetLoadingContext& context, asset_type_t assetType, const std::string& assetName) const override;
void FinalizeAssetsForZone(AssetLoadingContext& context) const override;
bool LoadAssetForZone(AssetLoadingContext* context, asset_type_t assetType, const std::string& assetName) const override;
void FinalizeAssetsForZone(AssetLoadingContext* context) const override;
private:
static bool IsMpZone(const Zone& zone);
static bool IsZmZone(const Zone& zone);
std::unordered_map<asset_type_t, std::unique_ptr<IAssetLoader>> m_asset_loaders_by_type;
};
} // namespace IW4

View File

@ -35,10 +35,8 @@ bool AssetLoaderGfxImage::LoadFromRaw(
const auto fileData = std::make_unique<char[]>(fileSize);
file.m_stream->read(fileData.get(), fileSize);
MemoryManager tempMemory;
IwiLoader iwiLoader(&tempMemory);
std::istringstream ss(std::string(fileData.get(), fileSize));
const auto texture = iwiLoader.LoadIwi(ss);
const auto texture = iwi::LoadIwi(ss);
if (!texture)
{
std::cerr << std::format("Failed to load texture from: {}\n", fileName);

View File

@ -227,7 +227,7 @@ bool AssetLoaderMenuList::LoadFromRaw(
return true;
}
void AssetLoaderMenuList::FinalizeAssetsForZone(AssetLoadingContext* context) const
void AssetLoaderMenuList::FinalizeAssetsForZone(AssetLoadingContext& context) const
{
context->GetZoneAssetLoaderState<MenuConversionZoneState>()->FinalizeSupportingData();
context.GetZoneAssetLoaderState<MenuConversionZoneState>()->FinalizeSupportingData();
}

View File

@ -14,6 +14,6 @@ namespace IW5
_NODISCARD bool CanLoadFromRaw() const override;
bool
LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
void FinalizeAssetsForZone(AssetLoadingContext* context) const override;
void FinalizeAssetsForZone(AssetLoadingContext& context) const override;
};
} // namespace IW5

View File

@ -41,14 +41,9 @@
#include "AssetLoaders/AssetLoaderXModel.h"
#include "AssetLoaders/AssetLoaderXModelSurfs.h"
#include "AssetLoading/AssetLoadingManager.h"
#include "Game/IW5/GameAssetPoolIW5.h"
#include "Game/IW5/GameIW5.h"
#include "Image/Dx9TextureLoader.h"
#include "Image/IwiLoader.h"
#include "Image/IwiTypes.h"
#include "Image/Texture.h"
#include "ObjContainer/IPak/IPak.h"
#include "ObjLoading.h"
using namespace IW5;
@ -104,129 +99,32 @@ ObjLoader::ObjLoader()
#undef REGISTER_ASSET_LOADER
}
bool ObjLoader::SupportsZone(Zone* zone) const
bool ObjLoader::SupportsZone(const Zone& zone) const
{
return zone->m_game == &g_GameIW5;
return zone.m_game == &g_GameIW5;
}
bool ObjLoader::IsMpZone(Zone* zone)
bool ObjLoader::IsMpZone(const Zone& zone)
{
return zone->m_name.compare(0, 3, "mp_") == 0 || zone->m_name.compare(zone->m_name.length() - 3, 3, "_mp") == 0;
return zone.m_name.compare(0, 3, "mp_") == 0 || zone.m_name.compare(zone.m_name.length() - 3, 3, "_mp") == 0;
}
bool ObjLoader::IsZmZone(Zone* zone)
bool ObjLoader::IsZmZone(const Zone& zone)
{
return zone->m_name.compare(0, 3, "zm_") == 0 || zone->m_name.compare(zone->m_name.length() - 3, 3, "_zm") == 0;
return zone.m_name.compare(0, 3, "zm_") == 0 || zone.m_name.compare(zone.m_name.length() - 3, 3, "_zm") == 0;
}
void ObjLoader::LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone) const {}
void ObjLoader::LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone) const {}
void ObjLoader::UnloadContainersOfZone(Zone* zone) const {}
void ObjLoader::UnloadContainersOfZone(Zone& zone) const {}
void ObjLoader::LoadImageFromLoadDef(GfxImage* image, Zone* zone)
bool ObjLoader::LoadAssetForZone(AssetLoadingContext& context, const asset_type_t assetType, const std::string& assetName) const
{
const auto* loadDef = image->texture.loadDef;
Dx9TextureLoader textureLoader(zone->GetMemory());
textureLoader.Width(image->width).Height(image->height).Depth(image->depth);
if ((loadDef->flags & iwi8::IMG_FLAG_MAPTYPE_MASK) == iwi8::IMG_FLAG_MAPTYPE_3D)
textureLoader.Type(TextureType::T_3D);
else if ((loadDef->flags & iwi8::IMG_FLAG_MAPTYPE_MASK) == iwi8::IMG_FLAG_MAPTYPE_CUBE)
textureLoader.Type(TextureType::T_CUBE);
else
textureLoader.Type(TextureType::T_2D);
textureLoader.Format(static_cast<oat::D3DFORMAT>(loadDef->format));
textureLoader.HasMipMaps(!(loadDef->flags & iwi8::IMG_FLAG_NOMIPMAPS));
Texture* loadedTexture = textureLoader.LoadTexture(image->texture.loadDef->data);
if (loadedTexture != nullptr)
{
image->texture.texture = loadedTexture;
image->cardMemory.platform[0] = 0;
const auto textureMipCount = loadedTexture->GetMipMapCount();
for (auto mipLevel = 0; mipLevel < textureMipCount; mipLevel++)
image->cardMemory.platform[0] += static_cast<int>(loadedTexture->GetSizeOfMipLevel(mipLevel) * loadedTexture->GetFaceCount());
}
}
void ObjLoader::LoadImageFromIwi(GfxImage* image, ISearchPath* searchPath, Zone* zone)
{
Texture* loadedTexture = nullptr;
IwiLoader loader(zone->GetMemory());
const auto imageFileName = "images/" + std::string(image->name) + ".iwi";
{
const auto filePathImage = searchPath->Open(imageFileName);
if (filePathImage.IsOpen())
{
loadedTexture = loader.LoadIwi(*filePathImage.m_stream);
}
}
if (loadedTexture != nullptr)
{
image->texture.texture = loadedTexture;
image->cardMemory.platform[0] = 0;
const auto textureMipCount = loadedTexture->GetMipMapCount();
for (auto mipLevel = 0; mipLevel < textureMipCount; mipLevel++)
image->cardMemory.platform[0] += static_cast<int>(loadedTexture->GetSizeOfMipLevel(mipLevel) * loadedTexture->GetFaceCount());
}
else
{
printf("Could not find data for image \"%s\"\n", image->name);
}
}
void ObjLoader::LoadImageData(ISearchPath* searchPath, Zone* zone)
{
auto* assetPool = dynamic_cast<GameAssetPoolIW5*>(zone->m_pools.get());
if (assetPool && assetPool->m_image != nullptr)
{
for (auto* imageEntry : *assetPool->m_image)
{
auto* image = imageEntry->Asset();
if (image->cardMemory.platform[0] > 0)
{
continue;
}
// Do not load linked assets
if (image->name && image->name[0] == ',')
{
continue;
}
if (image->texture.loadDef && image->texture.loadDef->resourceSize > 0)
{
LoadImageFromLoadDef(image, zone);
}
else
{
LoadImageFromIwi(image, searchPath, zone);
}
}
}
}
void ObjLoader::LoadObjDataForZone(ISearchPath* searchPath, Zone* zone) const
{
LoadImageData(searchPath, zone);
}
bool ObjLoader::LoadAssetForZone(AssetLoadingContext* context, asset_type_t assetType, const std::string& assetName) const
{
AssetLoadingManager assetLoadingManager(m_asset_loaders_by_type, *context);
AssetLoadingManager assetLoadingManager(m_asset_loaders_by_type, context);
return assetLoadingManager.LoadAssetFromLoader(assetType, assetName);
}
void ObjLoader::FinalizeAssetsForZone(AssetLoadingContext* context) const
void ObjLoader::FinalizeAssetsForZone(AssetLoadingContext& context) const
{
for (const auto& [type, loader] : m_asset_loaders_by_type)
loader->FinalizeAssetsForZone(context);

View File

@ -1,37 +1,31 @@
#pragma once
#include "AssetLoading/IAssetLoader.h"
#include "Game/IW5/IW5.h"
#include "IObjLoader.h"
#include "SearchPath/ISearchPath.h"
#include <map>
#include <memory>
#include <unordered_map>
namespace IW5
{
class ObjLoader final : public IObjLoader
{
std::map<asset_type_t, std::unique_ptr<IAssetLoader>> m_asset_loaders_by_type;
static void LoadImageFromIwi(GfxImage* image, ISearchPath* searchPath, Zone* zone);
static void LoadImageFromLoadDef(GfxImage* image, Zone* zone);
static void LoadImageData(ISearchPath* searchPath, Zone* zone);
static bool IsMpZone(Zone* zone);
static bool IsZmZone(Zone* zone);
public:
ObjLoader();
bool SupportsZone(Zone* zone) const override;
[[nodiscard]] bool SupportsZone(const Zone& zone) const override;
void LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone) const override;
void UnloadContainersOfZone(Zone* zone) const override;
void LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone) const override;
void UnloadContainersOfZone(Zone& zone) const override;
void LoadObjDataForZone(ISearchPath* searchPath, Zone* zone) const override;
bool LoadAssetForZone(AssetLoadingContext& context, asset_type_t assetType, const std::string& assetName) const override;
void FinalizeAssetsForZone(AssetLoadingContext& context) const override;
bool LoadAssetForZone(AssetLoadingContext* context, asset_type_t assetType, const std::string& assetName) const override;
void FinalizeAssetsForZone(AssetLoadingContext* context) const override;
private:
static bool IsMpZone(const Zone& zone);
static bool IsZmZone(const Zone& zone);
std::unordered_map<asset_type_t, std::unique_ptr<IAssetLoader>> m_asset_loaders_by_type;
};
} // namespace IW5

View File

@ -5,14 +5,9 @@
#include "AssetLoaders/AssetLoaderStringTable.h"
#include "AssetLoaders/AssetLoaderXModel.h"
#include "AssetLoading/AssetLoadingManager.h"
#include "Game/T5/GameAssetPoolT5.h"
#include "Game/T5/GameT5.h"
#include "Image/Dx9TextureLoader.h"
#include "Image/IwiLoader.h"
#include "Image/IwiTypes.h"
#include "Image/Texture.h"
#include "ObjContainer/IPak/IPak.h"
#include "ObjLoading.h"
using namespace T5;
@ -61,129 +56,32 @@ ObjLoader::ObjLoader()
#undef REGISTER_ASSET_LOADER
}
bool ObjLoader::SupportsZone(Zone* zone) const
bool ObjLoader::SupportsZone(const Zone& zone) const
{
return zone->m_game == &g_GameT5;
return zone.m_game == &g_GameT5;
}
bool ObjLoader::IsMpZone(Zone* zone)
bool ObjLoader::IsMpZone(const Zone& zone)
{
return zone->m_name.compare(0, 3, "mp_") == 0 || zone->m_name.compare(zone->m_name.length() - 3, 3, "_mp") == 0;
return zone.m_name.compare(0, 3, "mp_") == 0 || zone.m_name.compare(zone.m_name.length() - 3, 3, "_mp") == 0;
}
bool ObjLoader::IsZmZone(Zone* zone)
bool ObjLoader::IsZmZone(const Zone& zone)
{
return zone->m_name.compare(0, 3, "zm_") == 0 || zone->m_name.compare(zone->m_name.length() - 3, 3, "_zm") == 0;
return zone.m_name.compare(0, 3, "zm_") == 0 || zone.m_name.compare(zone.m_name.length() - 3, 3, "_zm") == 0;
}
void ObjLoader::LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone) const {}
void ObjLoader::LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone) const {}
void ObjLoader::UnloadContainersOfZone(Zone* zone) const {}
void ObjLoader::UnloadContainersOfZone(Zone& zone) const {}
void ObjLoader::LoadImageFromLoadDef(GfxImage* image, Zone* zone)
bool ObjLoader::LoadAssetForZone(AssetLoadingContext& context, asset_type_t assetType, const std::string& assetName) const
{
const auto* loadDef = image->texture.loadDef;
Dx9TextureLoader textureLoader(zone->GetMemory());
textureLoader.Width(image->width).Height(image->height).Depth(image->depth);
if (loadDef->flags & iwi13::IMG_FLAG_VOLMAP)
textureLoader.Type(TextureType::T_3D);
else if (loadDef->flags & iwi13::IMG_FLAG_CUBEMAP)
textureLoader.Type(TextureType::T_CUBE);
else
textureLoader.Type(TextureType::T_2D);
textureLoader.Format(static_cast<oat::D3DFORMAT>(loadDef->format));
textureLoader.HasMipMaps(!(loadDef->flags & iwi13::IMG_FLAG_NOMIPMAPS));
Texture* loadedTexture = textureLoader.LoadTexture(image->texture.loadDef->data);
if (loadedTexture != nullptr)
{
image->texture.texture = loadedTexture;
image->loadedSize = 0;
const auto textureMipCount = loadedTexture->GetMipMapCount();
for (auto mipLevel = 0; mipLevel < textureMipCount; mipLevel++)
image->loadedSize += static_cast<int>(loadedTexture->GetSizeOfMipLevel(mipLevel) * loadedTexture->GetFaceCount());
}
}
void ObjLoader::LoadImageFromIwi(GfxImage* image, ISearchPath* searchPath, Zone* zone)
{
Texture* loadedTexture = nullptr;
IwiLoader loader(zone->GetMemory());
const auto imageFileName = "images/" + std::string(image->name) + ".iwi";
{
const auto filePathImage = searchPath->Open(imageFileName);
if (filePathImage.IsOpen())
{
loadedTexture = loader.LoadIwi(*filePathImage.m_stream);
}
}
if (loadedTexture != nullptr)
{
image->texture.texture = loadedTexture;
image->loadedSize = 0;
const auto textureMipCount = loadedTexture->GetMipMapCount();
for (auto mipLevel = 0; mipLevel < textureMipCount; mipLevel++)
image->loadedSize += static_cast<int>(loadedTexture->GetSizeOfMipLevel(mipLevel) * loadedTexture->GetFaceCount());
}
else
{
printf("Could not find data for image \"%s\"\n", image->name);
}
}
void ObjLoader::LoadImageData(ISearchPath* searchPath, Zone* zone)
{
auto* assetPool = dynamic_cast<GameAssetPoolT5*>(zone->m_pools.get());
if (assetPool && assetPool->m_image != nullptr)
{
for (auto* imageEntry : *assetPool->m_image)
{
auto* image = imageEntry->Asset();
if (image->loadedSize > 0)
{
continue;
}
// Do not load linked assets
if (image->name && image->name[0] == ',')
{
continue;
}
if (image->texture.loadDef && image->texture.loadDef->resourceSize > 0)
{
LoadImageFromLoadDef(image, zone);
}
else
{
LoadImageFromIwi(image, searchPath, zone);
}
}
}
}
void ObjLoader::LoadObjDataForZone(ISearchPath* searchPath, Zone* zone) const
{
LoadImageData(searchPath, zone);
}
bool ObjLoader::LoadAssetForZone(AssetLoadingContext* context, asset_type_t assetType, const std::string& assetName) const
{
AssetLoadingManager assetLoadingManager(m_asset_loaders_by_type, *context);
AssetLoadingManager assetLoadingManager(m_asset_loaders_by_type, context);
return assetLoadingManager.LoadAssetFromLoader(assetType, assetName);
}
void ObjLoader::FinalizeAssetsForZone(AssetLoadingContext* context) const
void ObjLoader::FinalizeAssetsForZone(AssetLoadingContext& context) const
{
for (const auto& [type, loader] : m_asset_loaders_by_type)
loader->FinalizeAssetsForZone(context);

View File

@ -1,37 +1,31 @@
#pragma once
#include "AssetLoading/IAssetLoader.h"
#include "Game/T5/T5.h"
#include "IObjLoader.h"
#include "SearchPath/ISearchPath.h"
#include <map>
#include <memory>
#include <unordered_map>
namespace T5
{
class ObjLoader final : public IObjLoader
{
std::map<asset_type_t, std::unique_ptr<IAssetLoader>> m_asset_loaders_by_type;
static void LoadImageFromIwi(GfxImage* image, ISearchPath* searchPath, Zone* zone);
static void LoadImageFromLoadDef(GfxImage* image, Zone* zone);
static void LoadImageData(ISearchPath* searchPath, Zone* zone);
static bool IsMpZone(Zone* zone);
static bool IsZmZone(Zone* zone);
public:
ObjLoader();
bool SupportsZone(Zone* zone) const override;
bool SupportsZone(const Zone& zone) const override;
void LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone) const override;
void UnloadContainersOfZone(Zone* zone) const override;
void LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone) const override;
void UnloadContainersOfZone(Zone& zone) const override;
void LoadObjDataForZone(ISearchPath* searchPath, Zone* zone) const override;
bool LoadAssetForZone(AssetLoadingContext& context, asset_type_t assetType, const std::string& assetName) const override;
void FinalizeAssetsForZone(AssetLoadingContext& context) const override;
bool LoadAssetForZone(AssetLoadingContext* context, asset_type_t assetType, const std::string& assetName) const override;
void FinalizeAssetsForZone(AssetLoadingContext* context) const override;
private:
static bool IsMpZone(const Zone& zone);
static bool IsZmZone(const Zone& zone);
std::unordered_map<asset_type_t, std::unique_ptr<IAssetLoader>> m_asset_loaders_by_type;
};
} // namespace T5

View File

@ -6,6 +6,7 @@
#include "Pool/GlobalAssetPool.h"
#include <cstring>
#include <format>
#include <iostream>
#include <sstream>
#include <zlib.h>
@ -27,7 +28,7 @@ bool AssetLoaderGfxImage::CanLoadFromRaw() const
bool AssetLoaderGfxImage::LoadFromRaw(
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
{
const auto fileName = "images/" + assetName + ".iwi";
const auto fileName = std::format("images/{}.iwi", assetName);
const auto file = searchPath->Open(fileName);
if (!file.IsOpen())
return false;
@ -37,13 +38,11 @@ bool AssetLoaderGfxImage::LoadFromRaw(
file.m_stream->read(fileData.get(), fileSize);
const auto dataHash = static_cast<unsigned>(crc32(0u, reinterpret_cast<const Bytef*>(fileData.get()), fileSize));
MemoryManager tempMemory;
IwiLoader iwiLoader(&tempMemory);
std::istringstream ss(std::string(fileData.get(), fileSize));
const auto texture = iwiLoader.LoadIwi(ss);
const auto texture = iwi::LoadIwi(ss);
if (!texture)
{
std::cerr << "Failed to load texture from: " << fileName << "\n";
std::cerr << std::format("Failed to load texture from: {}\n", fileName);
return false;
}

View File

@ -58,12 +58,12 @@
#include "ObjContainer/IPak/IPak.h"
#include "ObjLoading.h"
#include <sstream>
#include <format>
namespace T6
{
const int ObjLoader::IPAK_READ_HASH = Common::Com_HashKey("ipak_read", 64);
const int ObjLoader::GLOBAL_HASH = Common::Com_HashKey("GLOBAL", 64);
constexpr auto IPAK_READ_HASH = Common::Com_HashKey("ipak_read", 64);
constexpr auto GLOBAL_HASH = Common::Com_HashKey("GLOBAL", 64);
ObjLoader::ObjLoader()
{
@ -125,37 +125,37 @@ namespace T6
#undef REGISTER_ASSET_LOADER
}
bool ObjLoader::SupportsZone(Zone* zone) const
bool ObjLoader::SupportsZone(const Zone& zone) const
{
return zone->m_game == &g_GameT6;
return zone.m_game == &g_GameT6;
}
bool ObjLoader::VerifySoundBankChecksum(const SoundBank* soundBank, const SndRuntimeAssetBank& sndRuntimeAssetBank)
bool ObjLoader::VerifySoundBankChecksum(const SoundBank& soundBank, const SndRuntimeAssetBank& sndRuntimeAssetBank)
{
SoundAssetBankChecksum checksum{};
static_assert(sizeof(SoundAssetBankChecksum::checksumBytes) == sizeof(SndRuntimeAssetBank::linkTimeChecksum));
for (auto i = 0u; i < sizeof(SoundAssetBankChecksum::checksumBytes); i++)
checksum.checksumBytes[i] = sndRuntimeAssetBank.linkTimeChecksum[i];
return soundBank->VerifyChecksum(checksum);
return soundBank.VerifyChecksum(checksum);
}
SoundBank* ObjLoader::LoadSoundBankForZone(ISearchPath* searchPath, const std::string& soundBankFileName, Zone* zone)
SoundBank* ObjLoader::LoadSoundBankForZone(ISearchPath& searchPath, const std::string& soundBankFileName, Zone& zone)
{
if (ObjLoading::Configuration.Verbose)
std::cout << "Trying to load sound bank '" << soundBankFileName << "' for zone '" << zone->m_name << "'\n";
std::cout << std::format("Trying to load sound bank '{}' for zone '{}'\n", soundBankFileName, zone.m_name);
auto* existingSoundBank = SoundBank::Repository.GetContainerByName(soundBankFileName);
if (existingSoundBank != nullptr)
{
if (ObjLoading::Configuration.Verbose)
std::cout << "Referencing loaded sound bank '" << soundBankFileName << "'.\n";
std::cout << std::format("Referencing loaded sound bank '{}'.\n", soundBankFileName);
SoundBank::Repository.AddContainerReference(existingSoundBank, zone);
SoundBank::Repository.AddContainerReference(existingSoundBank, &zone);
return existingSoundBank;
}
auto file = searchPath->Open(soundBankFileName);
auto file = searchPath.Open(soundBankFileName);
if (file.IsOpen())
{
auto sndBank = std::make_unique<SoundBank>(soundBankFileName, std::move(file.m_stream), file.m_length);
@ -163,26 +163,26 @@ namespace T6
if (!sndBank->Initialize())
{
std::cout << "Failed to load sound bank '" << soundBankFileName << "'\n";
std::cerr << std::format("Failed to load sound bank '{}'\n", soundBankFileName);
return nullptr;
}
SoundBank::Repository.AddContainer(std::move(sndBank), zone);
SoundBank::Repository.AddContainer(std::move(sndBank), &zone);
if (ObjLoading::Configuration.Verbose)
std::cout << "Found and loaded sound bank '" << soundBankFileName << "'\n";
std::cout << std::format("Found and loaded sound bank '{}'\n", soundBankFileName);
return sndBankPtr;
}
std::cout << "Failed to load sound bank '" << soundBankFileName << "'\n";
std::cerr << std::format("Failed to load sound bank '{}'\n", soundBankFileName);
return nullptr;
}
void ObjLoader::LoadSoundBankFromLinkedInfo(ISearchPath* searchPath,
void ObjLoader::LoadSoundBankFromLinkedInfo(ISearchPath& searchPath,
const std::string& soundBankFileName,
const SndRuntimeAssetBank* sndBankLinkedInfo,
Zone* zone,
const SndRuntimeAssetBank& sndBankLinkedInfo,
Zone& zone,
std::set<std::string>& loadedBanksForZone,
std::stack<std::string>& dependenciesToLoad)
{
@ -192,10 +192,9 @@ namespace T6
if (soundBank)
{
if (!VerifySoundBankChecksum(soundBank, *sndBankLinkedInfo))
{
std::cout << "Checksum of sound bank does not match link time checksum for '" << soundBankFileName << "'\n";
}
if (!VerifySoundBankChecksum(*soundBank, sndBankLinkedInfo))
std::cout << std::format("Checksum of sound bank does not match link time checksum for '{}'\n", soundBankFileName);
loadedBanksForZone.emplace(soundBankFileName);
for (const auto& dependency : soundBank->GetDependencies())
@ -206,20 +205,20 @@ namespace T6
}
}
void ObjLoader::LoadSoundBanksFromAsset(ISearchPath* searchPath, const SndBank* sndBank, Zone* zone, std::set<std::string>& loadedBanksForZone)
void ObjLoader::LoadSoundBanksFromAsset(ISearchPath& searchPath, const SndBank& sndBank, Zone& zone, std::set<std::string>& loadedBanksForZone)
{
std::stack<std::string> dependenciesToLoad;
if (sndBank->streamAssetBank.zone)
if (sndBank.streamAssetBank.zone)
{
const auto soundBankFileName = SoundBank::GetFileNameForDefinition(true, sndBank->streamAssetBank.zone, sndBank->streamAssetBank.language);
LoadSoundBankFromLinkedInfo(searchPath, soundBankFileName, &sndBank->streamAssetBank, zone, loadedBanksForZone, dependenciesToLoad);
const auto soundBankFileName = SoundBank::GetFileNameForDefinition(true, sndBank.streamAssetBank.zone, sndBank.streamAssetBank.language);
LoadSoundBankFromLinkedInfo(searchPath, soundBankFileName, sndBank.streamAssetBank, zone, loadedBanksForZone, dependenciesToLoad);
}
if (sndBank->runtimeAssetLoad && sndBank->loadAssetBank.zone)
if (sndBank.runtimeAssetLoad && sndBank.loadAssetBank.zone)
{
const auto soundBankFileName = SoundBank::GetFileNameForDefinition(false, sndBank->loadAssetBank.zone, sndBank->loadAssetBank.language);
LoadSoundBankFromLinkedInfo(searchPath, soundBankFileName, &sndBank->loadAssetBank, zone, loadedBanksForZone, dependenciesToLoad);
const auto soundBankFileName = SoundBank::GetFileNameForDefinition(false, sndBank.loadAssetBank.zone, sndBank.loadAssetBank.language);
LoadSoundBankFromLinkedInfo(searchPath, soundBankFileName, sndBank.loadAssetBank, zone, loadedBanksForZone, dependenciesToLoad);
}
while (!dependenciesToLoad.empty())
@ -236,76 +235,72 @@ namespace T6
loadedBanksForZone.emplace(dependencyFileName);
for (const auto& dependency : soundBank->GetDependencies())
{
dependenciesToLoad.emplace(dependency);
}
}
}
}
}
void ObjLoader::LoadIPakForZone(ISearchPath* searchPath, const std::string& ipakName, Zone* zone)
void ObjLoader::LoadIPakForZone(ISearchPath& searchPath, const std::string& ipakName, Zone& zone)
{
if (ObjLoading::Configuration.Verbose)
printf("Trying to load ipak '%s' for zone '%s'\n", ipakName.c_str(), zone->m_name.c_str());
std::cout << std::format("Trying to load ipak '{}' for zone '{}'\n", ipakName, zone.m_name);
auto* existingIPak = IPak::Repository.GetContainerByName(ipakName);
if (existingIPak != nullptr)
{
if (ObjLoading::Configuration.Verbose)
printf("Referencing loaded ipak '%s'.\n", ipakName.c_str());
std::cout << std::format("Referencing loaded ipak '{}'.\n", ipakName);
IPak::Repository.AddContainerReference(existingIPak, zone);
IPak::Repository.AddContainerReference(existingIPak, &zone);
return;
}
const auto ipakFilename = ipakName + ".ipak";
const auto ipakFilename = std::format("{}.ipak", ipakName);
auto file = searchPath->Open(ipakFilename);
auto file = searchPath.Open(ipakFilename);
if (file.IsOpen())
{
auto ipak = std::make_unique<IPak>(ipakFilename, std::move(file.m_stream));
if (ipak->Initialize())
{
IPak::Repository.AddContainer(std::move(ipak), zone);
IPak::Repository.AddContainer(std::move(ipak), &zone);
if (ObjLoading::Configuration.Verbose)
printf("Found and loaded ipak '%s'.\n", ipakFilename.c_str());
std::cout << std::format("Found and loaded ipak '{}'.\n", ipakFilename);
}
else
{
printf("Failed to load ipak '%s'!\n", ipakFilename.c_str());
std::cerr << std::format("Failed to load ipak '{}'!\n", ipakFilename);
}
}
}
bool ObjLoader::IsMpZone(Zone* zone)
bool ObjLoader::IsMpZone(const Zone& zone)
{
return zone->m_name.compare(0, 3, "mp_") == 0 || zone->m_name.compare(zone->m_name.length() - 3, 3, "_mp") == 0;
return zone.m_name.compare(0, 3, "mp_") == 0 || zone.m_name.compare(zone.m_name.length() - 3, 3, "_mp") == 0;
}
bool ObjLoader::IsZmZone(Zone* zone)
bool ObjLoader::IsZmZone(const Zone& zone)
{
return zone->m_name.compare(0, 3, "zm_") == 0 || zone->m_name.compare(zone->m_name.length() - 3, 3, "_zm") == 0;
return zone.m_name.compare(0, 3, "zm_") == 0 || zone.m_name.compare(zone.m_name.length() - 3, 3, "_zm") == 0;
}
void ObjLoader::LoadCommonIPaks(ISearchPath* searchPath, Zone* zone)
void ObjLoader::LoadCommonIPaks(ISearchPath& searchPath, Zone& zone)
{
if (ObjLoading::Configuration.Verbose)
printf("Loading common ipaks for zone \"%s\"\n", zone->m_name.c_str());
std::cout << std::format("Loading common ipaks for zone \"{}\"\n", zone.m_name);
LoadIPakForZone(searchPath, "base", zone);
auto languagePrefixes = g_GameT6.GetLanguagePrefixes();
const auto languagePrefixes = g_GameT6.GetLanguagePrefixes();
for (const auto& languagePrefix : languagePrefixes)
{
LoadIPakForZone(searchPath, languagePrefix.m_prefix + "base", zone);
}
LoadIPakForZone(searchPath, std::format("{}base", languagePrefix.m_prefix), zone);
if (IsMpZone(zone))
{
if (ObjLoading::Configuration.Verbose)
printf("Loading multiplayer ipaks for zone \"%s\"\n", zone->m_name.c_str());
std::cout << std::format("Loading multiplayer ipaks for zone \"{}\"\n", zone.m_name);
LoadIPakForZone(searchPath, "mp", zone);
LoadIPakForZone(searchPath, "so", zone);
@ -313,23 +308,23 @@ namespace T6
else if (IsZmZone(zone))
{
if (ObjLoading::Configuration.Verbose)
printf("Loading zombie ipak for zone \"%s\"\n", zone->m_name.c_str());
std::cout << std::format("Loading zombie ipak for zone \"{}\"\n", zone.m_name);
LoadIPakForZone(searchPath, "zm", zone);
}
else
{
if (ObjLoading::Configuration.Verbose)
printf("Loading singleplayer ipak for zone \"%s\"\n", zone->m_name.c_str());
std::cout << std::format("Loading singleplayer ipak for zone \"{}\"\n", zone.m_name);
LoadIPakForZone(searchPath, "sp", zone);
}
}
void ObjLoader::LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone) const
void ObjLoader::LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone) const
{
auto* assetPoolT6 = dynamic_cast<GameAssetPoolT6*>(zone->m_pools.get());
const auto zoneNameHash = Common::Com_HashKey(zone->m_name.c_str(), 64);
const auto* assetPoolT6 = dynamic_cast<GameAssetPoolT6*>(zone.m_pools.get());
const auto zoneNameHash = Common::Com_HashKey(zone.m_name.c_str(), 64);
LoadCommonIPaks(searchPath, zone);
@ -337,7 +332,7 @@ namespace T6
{
for (auto* keyValuePairsEntry : *assetPoolT6->m_key_value_pairs)
{
auto* keyValuePairs = keyValuePairsEntry->Asset();
const auto* keyValuePairs = keyValuePairsEntry->Asset();
for (auto variableIndex = 0; variableIndex < keyValuePairs->numVariables; variableIndex++)
{
auto* variable = &keyValuePairs->keyValuePairs[variableIndex];
@ -356,143 +351,23 @@ namespace T6
for (auto* sndBankAssetInfo : *assetPoolT6->m_sound_bank)
{
LoadSoundBanksFromAsset(searchPath, sndBankAssetInfo->Asset(), zone, loadedSoundBanksForZone);
LoadSoundBanksFromAsset(searchPath, *sndBankAssetInfo->Asset(), zone, loadedSoundBanksForZone);
}
}
}
void ObjLoader::UnloadContainersOfZone(Zone* zone) const
void ObjLoader::UnloadContainersOfZone(Zone& zone) const
{
IPak::Repository.RemoveContainerReferences(zone);
IPak::Repository.RemoveContainerReferences(&zone);
}
void ObjLoader::LoadImageFromLoadDef(GfxImage* image, Zone* zone)
bool ObjLoader::LoadAssetForZone(AssetLoadingContext& context, const asset_type_t assetType, const std::string& assetName) const
{
const auto* loadDef = image->texture.loadDef;
Dx12TextureLoader textureLoader(zone->GetMemory());
textureLoader.Width(image->width).Height(image->height).Depth(image->depth);
if (loadDef->flags & iwi27::IMG_FLAG_VOLMAP)
textureLoader.Type(TextureType::T_3D);
else if (loadDef->flags & iwi27::IMG_FLAG_CUBEMAP)
textureLoader.Type(TextureType::T_CUBE);
else
textureLoader.Type(TextureType::T_2D);
textureLoader.Format(static_cast<oat::DXGI_FORMAT>(loadDef->format));
textureLoader.HasMipMaps(!(loadDef->flags & iwi27::IMG_FLAG_NOMIPMAPS));
Texture* loadedTexture = textureLoader.LoadTexture(image->texture.loadDef->data);
if (loadedTexture != nullptr)
{
image->texture.texture = loadedTexture;
image->loadedSize = 0;
const auto textureMipCount = loadedTexture->GetMipMapCount();
for (auto mipLevel = 0; mipLevel < textureMipCount; mipLevel++)
image->loadedSize += static_cast<int>(loadedTexture->GetSizeOfMipLevel(mipLevel) * loadedTexture->GetFaceCount());
}
}
void ObjLoader::LoadImageFromIwi(GfxImage* image, ISearchPath* searchPath, Zone* zone)
{
Texture* loadedTexture = nullptr;
IwiLoader loader(zone->GetMemory());
if (image->streamedPartCount > 0)
{
for (auto* ipak : IPak::Repository)
{
auto ipakStream = ipak->GetEntryStream(image->hash, image->streamedParts[0].hash);
if (ipakStream)
{
loadedTexture = loader.LoadIwi(*ipakStream);
ipakStream->close();
if (loadedTexture != nullptr)
{
break;
}
}
}
}
if (loadedTexture == nullptr)
{
const auto imageFileName = "images/" + std::string(image->name) + ".iwi";
{
const auto filePathImage = searchPath->Open(imageFileName);
if (filePathImage.IsOpen())
{
loadedTexture = loader.LoadIwi(*filePathImage.m_stream);
}
}
}
if (loadedTexture != nullptr)
{
image->texture.texture = loadedTexture;
image->loadedSize = 0;
const auto textureMipCount = loadedTexture->GetMipMapCount();
for (auto mipLevel = 0; mipLevel < textureMipCount; mipLevel++)
image->loadedSize += loadedTexture->GetSizeOfMipLevel(mipLevel) * loadedTexture->GetFaceCount();
}
else
{
printf("Could not find data for image \"%s\"\n", image->name);
}
}
void ObjLoader::LoadImageData(ISearchPath* searchPath, Zone* zone)
{
auto* assetPoolT6 = dynamic_cast<GameAssetPoolT6*>(zone->m_pools.get());
if (assetPoolT6 && assetPoolT6->m_image != nullptr)
{
for (auto* imageEntry : *assetPoolT6->m_image)
{
auto* image = imageEntry->Asset();
if (image->loadedSize > 0)
{
continue;
}
// Do not load linked assets
if (image->name && image->name[0] == ',')
{
continue;
}
if (image->texture.loadDef && image->texture.loadDef->resourceSize > 0)
{
LoadImageFromLoadDef(image, zone);
}
else
{
LoadImageFromIwi(image, searchPath, zone);
}
}
}
}
void ObjLoader::LoadObjDataForZone(ISearchPath* searchPath, Zone* zone) const
{
LoadImageData(searchPath, zone);
}
bool ObjLoader::LoadAssetForZone(AssetLoadingContext* context, const asset_type_t assetType, const std::string& assetName) const
{
AssetLoadingManager assetLoadingManager(m_asset_loaders_by_type, *context);
AssetLoadingManager assetLoadingManager(m_asset_loaders_by_type, context);
return assetLoadingManager.LoadAssetFromLoader(assetType, assetName);
}
void ObjLoader::FinalizeAssetsForZone(AssetLoadingContext* context) const
void ObjLoader::FinalizeAssetsForZone(AssetLoadingContext& context) const
{
for (const auto& [type, loader] : m_asset_loaders_by_type)
loader->FinalizeAssetsForZone(context);

View File

@ -6,52 +6,44 @@
#include "ObjContainer/SoundBank/SoundBank.h"
#include "SearchPath/ISearchPath.h"
#include <map>
#include <memory>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
namespace T6
{
class ObjLoader final : public IObjLoader
{
static const int IPAK_READ_HASH;
static const int GLOBAL_HASH;
std::map<asset_type_t, std::unique_ptr<IAssetLoader>> m_asset_loaders_by_type;
static bool VerifySoundBankChecksum(const SoundBank* soundBank, const SndRuntimeAssetBank& sndRuntimeAssetBank);
static SoundBank* LoadSoundBankForZone(ISearchPath* searchPath, const std::string& soundBankFileName, Zone* zone);
static void LoadSoundBankFromLinkedInfo(ISearchPath* searchPath,
const std::string& soundBankFileName,
const SndRuntimeAssetBank* sndBankLinkedInfo,
Zone* zone,
std::set<std::string>& loadedBanksForZone,
std::stack<std::string>& dependenciesToLoad);
static void LoadSoundBanksFromAsset(ISearchPath* searchPath, const SndBank* sndBank, Zone* zone, std::set<std::string>& loadedBanksForZone);
static void LoadIPakForZone(ISearchPath* searchPath, const std::string& ipakName, Zone* zone);
static void LoadImageFromIwi(GfxImage* image, ISearchPath* searchPath, Zone* zone);
static void LoadImageFromLoadDef(GfxImage* image, Zone* zone);
static void LoadImageData(ISearchPath* searchPath, Zone* zone);
static bool IsMpZone(Zone* zone);
static bool IsZmZone(Zone* zone);
static void LoadCommonIPaks(ISearchPath* searchPath, Zone* zone);
public:
ObjLoader();
bool SupportsZone(Zone* zone) const override;
[[nodiscard]] bool SupportsZone(const Zone& zone) const override;
void LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone) const override;
void UnloadContainersOfZone(Zone* zone) const override;
void LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone) const override;
void UnloadContainersOfZone(Zone& zone) const override;
void LoadObjDataForZone(ISearchPath* searchPath, Zone* zone) const override;
bool LoadAssetForZone(AssetLoadingContext& context, asset_type_t assetType, const std::string& assetName) const override;
void FinalizeAssetsForZone(AssetLoadingContext& context) const override;
bool LoadAssetForZone(AssetLoadingContext* context, asset_type_t assetType, const std::string& assetName) const override;
void FinalizeAssetsForZone(AssetLoadingContext* context) const override;
private:
static bool VerifySoundBankChecksum(const SoundBank& soundBank, const SndRuntimeAssetBank& sndRuntimeAssetBank);
static SoundBank* LoadSoundBankForZone(ISearchPath& searchPath, const std::string& soundBankFileName, Zone& zone);
static void LoadSoundBankFromLinkedInfo(ISearchPath& searchPath,
const std::string& soundBankFileName,
const SndRuntimeAssetBank& sndBankLinkedInfo,
Zone& zone,
std::set<std::string>& loadedBanksForZone,
std::stack<std::string>& dependenciesToLoad);
static void LoadSoundBanksFromAsset(ISearchPath& searchPath, const SndBank& sndBank, Zone& zone, std::set<std::string>& loadedBanksForZone);
static void LoadIPakForZone(ISearchPath& searchPath, const std::string& ipakName, Zone& zone);
static void LoadCommonIPaks(ISearchPath& searchPath, Zone& zone);
static bool IsMpZone(const Zone& zone);
static bool IsZmZone(const Zone& zone);
std::unordered_map<asset_type_t, std::unique_ptr<IAssetLoader>> m_asset_loaders_by_type;
};
} // namespace T6

View File

@ -7,35 +7,33 @@
class IObjLoader
{
public:
IObjLoader() = default;
virtual ~IObjLoader() = default;
IObjLoader(const IObjLoader& other) = default;
IObjLoader(IObjLoader&& other) noexcept = default;
IObjLoader& operator=(const IObjLoader& other) = default;
IObjLoader& operator=(IObjLoader&& other) noexcept = default;
/**
* \brief Checks whether this ObjLoader supports a specified zone.
* \param zone The zone to check.
* \return \c true if the specified zone is supported.
*/
virtual bool SupportsZone(Zone* zone) const = 0;
[[nodiscard]] virtual bool SupportsZone(const Zone& zone) const = 0;
/**
* \brief Loads all containers that are referenced by a specified zone.
* \param searchPath The search path object to use to find the referenced containers.
* \param zone The zone to check for referenced containers.
*/
virtual void LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone) const = 0;
virtual void LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone) const = 0;
/**
* \brief Unloads all containers of a specified zone. If a container is also loaded by another zone it will only be unloaded when all referencing zones are
* unloaded. \param zone The zone to unload all containers for.
*/
virtual void UnloadContainersOfZone(Zone* zone) const = 0;
virtual void UnloadContainersOfZone(Zone& zone) const = 0;
/**
* \brief Loads the obj data for all assets of a specified zone.
* \param searchPath The search path object to use to find obj files.
* \param zone The zone of the assets to load the obj data for.
*/
virtual void LoadObjDataForZone(ISearchPath* searchPath, Zone* zone) const = 0;
virtual bool LoadAssetForZone(AssetLoadingContext* context, asset_type_t assetType, const std::string& assetName) const = 0;
virtual void FinalizeAssetsForZone(AssetLoadingContext* context) const = 0;
virtual bool LoadAssetForZone(AssetLoadingContext& context, asset_type_t assetType, const std::string& assetName) const = 0;
virtual void FinalizeAssetsForZone(AssetLoadingContext& context) const = 0;
};

View File

@ -2,9 +2,8 @@
#include <cstring>
Dx12TextureLoader::Dx12TextureLoader(MemoryManager* memoryManager)
: m_memory_manager(memoryManager),
m_format(oat::DXGI_FORMAT_UNKNOWN),
Dx12TextureLoader::Dx12TextureLoader()
: m_format(oat::DXGI_FORMAT_UNKNOWN),
m_type(TextureType::T_2D),
m_has_mip_maps(false),
m_width(1u),
@ -60,26 +59,26 @@ Dx12TextureLoader& Dx12TextureLoader::Depth(const size_t depth)
return *this;
}
Texture* Dx12TextureLoader::LoadTexture(const void* data)
std::unique_ptr<Texture> Dx12TextureLoader::LoadTexture(const void* data)
{
const auto* format = GetFormatForDx12Format();
if (format == nullptr)
return nullptr;
Texture* texture;
std::unique_ptr<Texture> texture;
switch (m_type)
{
case TextureType::T_2D:
texture = m_memory_manager->Create<Texture2D>(format, m_width, m_height, m_has_mip_maps);
texture = std::make_unique<Texture2D>(format, m_width, m_height, m_has_mip_maps);
break;
case TextureType::T_3D:
texture = m_memory_manager->Create<Texture3D>(format, m_width, m_height, m_depth, m_has_mip_maps);
texture = std::make_unique<Texture3D>(format, m_width, m_height, m_depth, m_has_mip_maps);
break;
case TextureType::T_CUBE:
texture = m_memory_manager->Create<TextureCube>(format, m_width, m_width, m_has_mip_maps);
texture = std::make_unique<TextureCube>(format, m_width, m_width, m_has_mip_maps);
break;
default:

View File

@ -5,24 +5,13 @@
#include "Utils/ClassUtils.h"
#include "Utils/MemoryManager.h"
#include <memory>
#include <unordered_map>
class Dx12TextureLoader
{
static std::unordered_map<ImageFormatId, ImageFormatId> m_conversion_table;
MemoryManager* m_memory_manager;
oat::DXGI_FORMAT m_format;
TextureType m_type;
bool m_has_mip_maps;
size_t m_width;
size_t m_height;
size_t m_depth;
_NODISCARD const ImageFormat* GetFormatForDx12Format() const;
public:
explicit Dx12TextureLoader(MemoryManager* memoryManager);
Dx12TextureLoader();
Dx12TextureLoader& Format(oat::DXGI_FORMAT format);
Dx12TextureLoader& Type(TextureType textureType);
@ -31,5 +20,17 @@ public:
Dx12TextureLoader& Height(size_t height);
Dx12TextureLoader& Depth(size_t depth);
Texture* LoadTexture(const void* data);
std::unique_ptr<Texture> LoadTexture(const void* data);
private:
_NODISCARD const ImageFormat* GetFormatForDx12Format() const;
static std::unordered_map<ImageFormatId, ImageFormatId> m_conversion_table;
oat::DXGI_FORMAT m_format;
TextureType m_type;
bool m_has_mip_maps;
size_t m_width;
size_t m_height;
size_t m_depth;
};

View File

@ -2,9 +2,8 @@
#include <cstring>
Dx9TextureLoader::Dx9TextureLoader(MemoryManager* memoryManager)
: m_memory_manager(memoryManager),
m_format(oat::D3DFMT_UNKNOWN),
Dx9TextureLoader::Dx9TextureLoader()
: m_format(oat::D3DFMT_UNKNOWN),
m_type(TextureType::T_2D),
m_has_mip_maps(false),
m_width(1u),
@ -15,7 +14,7 @@ Dx9TextureLoader::Dx9TextureLoader(MemoryManager* memoryManager)
const ImageFormat* Dx9TextureLoader::GetFormatForDx9Format() const
{
for (auto i : ImageFormat::ALL_FORMATS)
for (const auto* i : ImageFormat::ALL_FORMATS)
{
if (i->GetD3DFormat() == m_format)
return i;
@ -60,26 +59,26 @@ Dx9TextureLoader& Dx9TextureLoader::Depth(const size_t depth)
return *this;
}
Texture* Dx9TextureLoader::LoadTexture(const void* data)
std::unique_ptr<Texture> Dx9TextureLoader::LoadTexture(const void* data)
{
const auto* format = GetFormatForDx9Format();
if (format == nullptr)
return nullptr;
Texture* texture;
std::unique_ptr<Texture> texture;
switch (m_type)
{
case TextureType::T_2D:
texture = m_memory_manager->Create<Texture2D>(format, m_width, m_height, m_has_mip_maps);
texture = std::make_unique<Texture2D>(format, m_width, m_height, m_has_mip_maps);
break;
case TextureType::T_3D:
texture = m_memory_manager->Create<Texture3D>(format, m_width, m_height, m_depth, m_has_mip_maps);
texture = std::make_unique<Texture3D>(format, m_width, m_height, m_depth, m_has_mip_maps);
break;
case TextureType::T_CUBE:
texture = m_memory_manager->Create<TextureCube>(format, m_width, m_width, m_has_mip_maps);
texture = std::make_unique<TextureCube>(format, m_width, m_width, m_has_mip_maps);
break;
default:

View File

@ -5,22 +5,13 @@
#include "Utils/ClassUtils.h"
#include "Utils/MemoryManager.h"
#include <memory>
#include <unordered_map>
class Dx9TextureLoader
{
MemoryManager* m_memory_manager;
oat::D3DFORMAT m_format;
TextureType m_type;
bool m_has_mip_maps;
size_t m_width;
size_t m_height;
size_t m_depth;
_NODISCARD const ImageFormat* GetFormatForDx9Format() const;
public:
explicit Dx9TextureLoader(MemoryManager* memoryManager);
Dx9TextureLoader();
Dx9TextureLoader& Format(oat::D3DFORMAT format);
Dx9TextureLoader& Type(TextureType textureType);
@ -29,5 +20,15 @@ public:
Dx9TextureLoader& Height(size_t height);
Dx9TextureLoader& Depth(size_t depth);
Texture* LoadTexture(const void* data);
std::unique_ptr<Texture> LoadTexture(const void* data);
private:
_NODISCARD const ImageFormat* GetFormatForDx9Format() const;
oat::D3DFORMAT m_format;
TextureType m_type;
bool m_has_mip_maps;
size_t m_width;
size_t m_height;
size_t m_depth;
};

View File

@ -3,474 +3,441 @@
#include "Image/IwiTypes.h"
#include <cassert>
#include <format>
#include <iostream>
#include <type_traits>
IwiLoader::IwiLoader(MemoryManager* memoryManager)
namespace iwi
{
m_memory_manager = memoryManager;
}
const ImageFormat* IwiLoader::GetFormat6(int8_t format)
{
switch (static_cast<iwi6::IwiFormat>(format))
const ImageFormat* GetFormat6(int8_t format)
{
case iwi6::IwiFormat::IMG_FORMAT_BITMAP_RGBA:
return &ImageFormat::FORMAT_R8_G8_B8_A8;
case iwi6::IwiFormat::IMG_FORMAT_BITMAP_RGB:
return &ImageFormat::FORMAT_R8_G8_B8;
case iwi6::IwiFormat::IMG_FORMAT_BITMAP_ALPHA:
return &ImageFormat::FORMAT_A8;
case iwi6::IwiFormat::IMG_FORMAT_DXT1:
return &ImageFormat::FORMAT_BC1;
case iwi6::IwiFormat::IMG_FORMAT_DXT3:
return &ImageFormat::FORMAT_BC2;
case iwi6::IwiFormat::IMG_FORMAT_DXT5:
return &ImageFormat::FORMAT_BC3;
case iwi6::IwiFormat::IMG_FORMAT_DXN:
return &ImageFormat::FORMAT_BC5;
case iwi6::IwiFormat::IMG_FORMAT_BITMAP_LUMINANCE_ALPHA:
return &ImageFormat::FORMAT_R8_A8;
case iwi6::IwiFormat::IMG_FORMAT_BITMAP_LUMINANCE:
return &ImageFormat::FORMAT_R8;
case iwi6::IwiFormat::IMG_FORMAT_WAVELET_RGBA: // used
case iwi6::IwiFormat::IMG_FORMAT_WAVELET_RGB: // used
case iwi6::IwiFormat::IMG_FORMAT_WAVELET_LUMINANCE_ALPHA:
case iwi6::IwiFormat::IMG_FORMAT_WAVELET_LUMINANCE:
case iwi6::IwiFormat::IMG_FORMAT_WAVELET_ALPHA:
printf("Unsupported IWI format: %i\n", format);
break;
default:
printf("Unknown IWI format: %i\n", format);
break;
}
return nullptr;
}
Texture* IwiLoader::LoadIwi6(std::istream& stream) const
{
iwi6::IwiHeader header{};
stream.read(reinterpret_cast<char*>(&header), sizeof(header));
if (stream.gcount() != sizeof(header))
return nullptr;
const auto* format = GetFormat6(header.format);
if (format == nullptr)
return nullptr;
auto width = header.dimensions[0];
auto height = header.dimensions[1];
auto depth = header.dimensions[2];
auto hasMipMaps = !(header.flags & iwi6::IwiFlags::IMG_FLAG_NOMIPMAPS);
Texture* texture;
if (header.flags & iwi6::IwiFlags::IMG_FLAG_CUBEMAP)
{
texture = m_memory_manager->Create<TextureCube>(format, width, height, hasMipMaps);
}
else if (header.flags & iwi6::IwiFlags::IMG_FLAG_VOLMAP)
{
texture = m_memory_manager->Create<Texture3D>(format, width, height, depth, hasMipMaps);
}
else
{
texture = m_memory_manager->Create<Texture2D>(format, width, height, hasMipMaps);
}
texture->Allocate();
auto currentFileSize = sizeof(iwi6::IwiHeader) + sizeof(IwiVersion);
const auto mipMapCount = hasMipMaps ? texture->GetMipMapCount() : 1;
for (auto currentMipLevel = mipMapCount - 1; currentMipLevel >= 0; currentMipLevel--)
{
const auto sizeOfMipLevel = texture->GetSizeOfMipLevel(currentMipLevel) * texture->GetFaceCount();
currentFileSize += sizeOfMipLevel;
if (currentMipLevel < static_cast<int>(std::extent_v<decltype(iwi6::IwiHeader::fileSizeForPicmip)>)
&& currentFileSize != header.fileSizeForPicmip[currentMipLevel])
switch (static_cast<iwi6::IwiFormat>(format))
{
printf("Iwi has invalid file size for picmip %i\n", currentMipLevel);
case iwi6::IwiFormat::IMG_FORMAT_BITMAP_RGBA:
return &ImageFormat::FORMAT_R8_G8_B8_A8;
case iwi6::IwiFormat::IMG_FORMAT_BITMAP_RGB:
return &ImageFormat::FORMAT_R8_G8_B8;
case iwi6::IwiFormat::IMG_FORMAT_BITMAP_ALPHA:
return &ImageFormat::FORMAT_A8;
case iwi6::IwiFormat::IMG_FORMAT_DXT1:
return &ImageFormat::FORMAT_BC1;
case iwi6::IwiFormat::IMG_FORMAT_DXT3:
return &ImageFormat::FORMAT_BC2;
case iwi6::IwiFormat::IMG_FORMAT_DXT5:
return &ImageFormat::FORMAT_BC3;
case iwi6::IwiFormat::IMG_FORMAT_DXN:
return &ImageFormat::FORMAT_BC5;
case iwi6::IwiFormat::IMG_FORMAT_BITMAP_LUMINANCE_ALPHA:
return &ImageFormat::FORMAT_R8_A8;
case iwi6::IwiFormat::IMG_FORMAT_BITMAP_LUMINANCE:
return &ImageFormat::FORMAT_R8;
case iwi6::IwiFormat::IMG_FORMAT_WAVELET_RGBA: // used
case iwi6::IwiFormat::IMG_FORMAT_WAVELET_RGB: // used
case iwi6::IwiFormat::IMG_FORMAT_WAVELET_LUMINANCE_ALPHA:
case iwi6::IwiFormat::IMG_FORMAT_WAVELET_LUMINANCE:
case iwi6::IwiFormat::IMG_FORMAT_WAVELET_ALPHA:
std::cerr << std::format("Unsupported IWI format: {}\n", format);
break;
default:
std::cerr << std::format("Unknown IWI format: {}\n", format);
break;
}
m_memory_manager->Delete(texture);
return nullptr;
}
std::unique_ptr<Texture> LoadIwi6(std::istream& stream)
{
iwi6::IwiHeader header{};
stream.read(reinterpret_cast<char*>(&header), sizeof(header));
if (stream.gcount() != sizeof(header))
return nullptr;
const auto* format = GetFormat6(header.format);
if (format == nullptr)
return nullptr;
auto width = header.dimensions[0];
auto height = header.dimensions[1];
auto depth = header.dimensions[2];
auto hasMipMaps = !(header.flags & iwi6::IwiFlags::IMG_FLAG_NOMIPMAPS);
std::unique_ptr<Texture> texture;
if (header.flags & iwi6::IwiFlags::IMG_FLAG_CUBEMAP)
texture = std::make_unique<TextureCube>(format, width, height, hasMipMaps);
else if (header.flags & iwi6::IwiFlags::IMG_FLAG_VOLMAP)
texture = std::make_unique<Texture3D>(format, width, height, depth, hasMipMaps);
else
texture = std::make_unique<Texture2D>(format, width, height, hasMipMaps);
texture->Allocate();
auto currentFileSize = sizeof(iwi6::IwiHeader) + sizeof(IwiVersion);
const auto mipMapCount = hasMipMaps ? texture->GetMipMapCount() : 1;
for (auto currentMipLevel = mipMapCount - 1; currentMipLevel >= 0; currentMipLevel--)
{
const auto sizeOfMipLevel = texture->GetSizeOfMipLevel(currentMipLevel) * texture->GetFaceCount();
currentFileSize += sizeOfMipLevel;
if (currentMipLevel < static_cast<int>(std::extent_v<decltype(iwi6::IwiHeader::fileSizeForPicmip)>)
&& currentFileSize != header.fileSizeForPicmip[currentMipLevel])
{
std::cerr << std::format("Iwi has invalid file size for picmip {}\n", currentMipLevel);
return nullptr;
}
stream.read(reinterpret_cast<char*>(texture->GetBufferForMipLevel(currentMipLevel)), sizeOfMipLevel);
if (stream.gcount() != sizeOfMipLevel)
{
std::cerr << std::format("Unexpected eof of iwi in mip level {}\n", currentMipLevel);
return nullptr;
}
}
return texture;
}
const ImageFormat* GetFormat8(int8_t format)
{
switch (static_cast<iwi8::IwiFormat>(format))
{
case iwi8::IwiFormat::IMG_FORMAT_BITMAP_RGBA:
return &ImageFormat::FORMAT_R8_G8_B8_A8;
case iwi8::IwiFormat::IMG_FORMAT_BITMAP_RGB:
return &ImageFormat::FORMAT_R8_G8_B8;
case iwi8::IwiFormat::IMG_FORMAT_BITMAP_ALPHA:
return &ImageFormat::FORMAT_A8;
case iwi8::IwiFormat::IMG_FORMAT_DXT1:
return &ImageFormat::FORMAT_BC1;
case iwi8::IwiFormat::IMG_FORMAT_DXT3:
return &ImageFormat::FORMAT_BC2;
case iwi8::IwiFormat::IMG_FORMAT_DXT5:
return &ImageFormat::FORMAT_BC3;
case iwi8::IwiFormat::IMG_FORMAT_DXN:
return &ImageFormat::FORMAT_BC5;
case iwi8::IwiFormat::IMG_FORMAT_BITMAP_LUMINANCE_ALPHA:
return &ImageFormat::FORMAT_R8_A8;
case iwi8::IwiFormat::IMG_FORMAT_BITMAP_LUMINANCE:
return &ImageFormat::FORMAT_R8;
case iwi8::IwiFormat::IMG_FORMAT_WAVELET_RGBA: // used
case iwi8::IwiFormat::IMG_FORMAT_WAVELET_RGB: // used
case iwi8::IwiFormat::IMG_FORMAT_WAVELET_LUMINANCE_ALPHA:
case iwi8::IwiFormat::IMG_FORMAT_WAVELET_LUMINANCE:
case iwi8::IwiFormat::IMG_FORMAT_WAVELET_ALPHA:
case iwi8::IwiFormat::IMG_FORMAT_DXT3A_AS_LUMINANCE:
case iwi8::IwiFormat::IMG_FORMAT_DXT5A_AS_LUMINANCE:
case iwi8::IwiFormat::IMG_FORMAT_DXT3A_AS_ALPHA:
case iwi8::IwiFormat::IMG_FORMAT_DXT5A_AS_ALPHA:
case iwi8::IwiFormat::IMG_FORMAT_DXT1_AS_LUMINANCE_ALPHA:
case iwi8::IwiFormat::IMG_FORMAT_DXN_AS_LUMINANCE_ALPHA:
case iwi8::IwiFormat::IMG_FORMAT_DXT1_AS_LUMINANCE:
case iwi8::IwiFormat::IMG_FORMAT_DXT1_AS_ALPHA:
std::cerr << std::format("Unsupported IWI format: {}\n", format);
break;
default:
std::cerr << std::format("Unknown IWI format: {}\n", format);
break;
}
return nullptr;
}
std::unique_ptr<Texture> LoadIwi8(std::istream& stream)
{
iwi8::IwiHeader header{};
stream.read(reinterpret_cast<char*>(&header), sizeof(header));
if (stream.gcount() != sizeof(header))
return nullptr;
const auto* format = GetFormat8(header.format);
if (format == nullptr)
return nullptr;
auto width = header.dimensions[0];
auto height = header.dimensions[1];
auto depth = header.dimensions[2];
auto hasMipMaps = !(header.flags & iwi8::IwiFlags::IMG_FLAG_NOMIPMAPS);
std::unique_ptr<Texture> texture;
if ((header.flags & iwi8::IwiFlags::IMG_FLAG_MAPTYPE_MASK) == iwi8::IwiFlags::IMG_FLAG_MAPTYPE_CUBE)
{
texture = std::make_unique<TextureCube>(format, width, height, hasMipMaps);
}
else if ((header.flags & iwi8::IwiFlags::IMG_FLAG_MAPTYPE_MASK) == iwi8::IwiFlags::IMG_FLAG_MAPTYPE_3D)
{
texture = std::make_unique<Texture3D>(format, width, height, depth, hasMipMaps);
}
else if ((header.flags & iwi8::IwiFlags::IMG_FLAG_MAPTYPE_MASK) == iwi8::IwiFlags::IMG_FLAG_MAPTYPE_2D)
{
texture = std::make_unique<Texture2D>(format, width, height, hasMipMaps);
}
else if ((header.flags & iwi8::IwiFlags::IMG_FLAG_MAPTYPE_MASK) == iwi8::IwiFlags::IMG_FLAG_MAPTYPE_1D)
{
std::cerr << "Iwi has unsupported map type 1D\n";
return nullptr;
}
else
{
std::cerr << "Iwi has unsupported map type\n";
return nullptr;
}
stream.read(reinterpret_cast<char*>(texture->GetBufferForMipLevel(currentMipLevel)), sizeOfMipLevel);
if (stream.gcount() != sizeOfMipLevel)
{
printf("Unexpected eof of iwi in mip level %i\n", currentMipLevel);
texture->Allocate();
m_memory_manager->Delete(texture);
return nullptr;
auto currentFileSize = sizeof(iwi8::IwiHeader) + sizeof(IwiVersion);
const auto mipMapCount = hasMipMaps ? texture->GetMipMapCount() : 1;
for (auto currentMipLevel = mipMapCount - 1; currentMipLevel >= 0; currentMipLevel--)
{
const auto sizeOfMipLevel = texture->GetSizeOfMipLevel(currentMipLevel) * texture->GetFaceCount();
currentFileSize += sizeOfMipLevel;
if (currentMipLevel < static_cast<int>(std::extent_v<decltype(iwi8::IwiHeader::fileSizeForPicmip)>)
&& currentFileSize != header.fileSizeForPicmip[currentMipLevel])
{
std::cerr << std::format("Iwi has invalid file size for picmip {}\n", currentMipLevel);
return nullptr;
}
stream.read(reinterpret_cast<char*>(texture->GetBufferForMipLevel(currentMipLevel)), sizeOfMipLevel);
if (stream.gcount() != sizeOfMipLevel)
{
std::cerr << std::format("Unexpected eof of iwi in mip level {}\n", currentMipLevel);
return nullptr;
}
}
return texture;
}
return texture;
}
const ImageFormat* IwiLoader::GetFormat8(int8_t format)
{
switch (static_cast<iwi8::IwiFormat>(format))
const ImageFormat* GetFormat13(int8_t format)
{
case iwi8::IwiFormat::IMG_FORMAT_BITMAP_RGBA:
return &ImageFormat::FORMAT_R8_G8_B8_A8;
case iwi8::IwiFormat::IMG_FORMAT_BITMAP_RGB:
return &ImageFormat::FORMAT_R8_G8_B8;
case iwi8::IwiFormat::IMG_FORMAT_BITMAP_ALPHA:
return &ImageFormat::FORMAT_A8;
case iwi8::IwiFormat::IMG_FORMAT_DXT1:
return &ImageFormat::FORMAT_BC1;
case iwi8::IwiFormat::IMG_FORMAT_DXT3:
return &ImageFormat::FORMAT_BC2;
case iwi8::IwiFormat::IMG_FORMAT_DXT5:
return &ImageFormat::FORMAT_BC3;
case iwi8::IwiFormat::IMG_FORMAT_DXN:
return &ImageFormat::FORMAT_BC5;
case iwi8::IwiFormat::IMG_FORMAT_BITMAP_LUMINANCE_ALPHA:
return &ImageFormat::FORMAT_R8_A8;
case iwi8::IwiFormat::IMG_FORMAT_BITMAP_LUMINANCE:
return &ImageFormat::FORMAT_R8;
case iwi8::IwiFormat::IMG_FORMAT_WAVELET_RGBA: // used
case iwi8::IwiFormat::IMG_FORMAT_WAVELET_RGB: // used
case iwi8::IwiFormat::IMG_FORMAT_WAVELET_LUMINANCE_ALPHA:
case iwi8::IwiFormat::IMG_FORMAT_WAVELET_LUMINANCE:
case iwi8::IwiFormat::IMG_FORMAT_WAVELET_ALPHA:
case iwi8::IwiFormat::IMG_FORMAT_DXT3A_AS_LUMINANCE:
case iwi8::IwiFormat::IMG_FORMAT_DXT5A_AS_LUMINANCE:
case iwi8::IwiFormat::IMG_FORMAT_DXT3A_AS_ALPHA:
case iwi8::IwiFormat::IMG_FORMAT_DXT5A_AS_ALPHA:
case iwi8::IwiFormat::IMG_FORMAT_DXT1_AS_LUMINANCE_ALPHA:
case iwi8::IwiFormat::IMG_FORMAT_DXN_AS_LUMINANCE_ALPHA:
case iwi8::IwiFormat::IMG_FORMAT_DXT1_AS_LUMINANCE:
case iwi8::IwiFormat::IMG_FORMAT_DXT1_AS_ALPHA:
printf("Unsupported IWI format: %i\n", format);
break;
default:
printf("Unknown IWI format: %i\n", format);
break;
}
return nullptr;
}
Texture* IwiLoader::LoadIwi8(std::istream& stream) const
{
iwi8::IwiHeader header{};
stream.read(reinterpret_cast<char*>(&header), sizeof(header));
if (stream.gcount() != sizeof(header))
return nullptr;
const auto* format = GetFormat8(header.format);
if (format == nullptr)
return nullptr;
auto width = header.dimensions[0];
auto height = header.dimensions[1];
auto depth = header.dimensions[2];
auto hasMipMaps = !(header.flags & iwi8::IwiFlags::IMG_FLAG_NOMIPMAPS);
Texture* texture;
if ((header.flags & iwi8::IwiFlags::IMG_FLAG_MAPTYPE_MASK) == iwi8::IwiFlags::IMG_FLAG_MAPTYPE_CUBE)
{
texture = m_memory_manager->Create<TextureCube>(format, width, height, hasMipMaps);
}
else if ((header.flags & iwi8::IwiFlags::IMG_FLAG_MAPTYPE_MASK) == iwi8::IwiFlags::IMG_FLAG_MAPTYPE_3D)
{
texture = m_memory_manager->Create<Texture3D>(format, width, height, depth, hasMipMaps);
}
else if ((header.flags & iwi8::IwiFlags::IMG_FLAG_MAPTYPE_MASK) == iwi8::IwiFlags::IMG_FLAG_MAPTYPE_2D)
{
texture = m_memory_manager->Create<Texture2D>(format, width, height, hasMipMaps);
}
else if ((header.flags & iwi8::IwiFlags::IMG_FLAG_MAPTYPE_MASK) == iwi8::IwiFlags::IMG_FLAG_MAPTYPE_1D)
{
printf("Iwi has unsupported map type 1D\n");
return nullptr;
}
else
{
printf("Iwi has unsupported map type\n");
return nullptr;
}
texture->Allocate();
auto currentFileSize = sizeof(iwi8::IwiHeader) + sizeof(IwiVersion);
const auto mipMapCount = hasMipMaps ? texture->GetMipMapCount() : 1;
for (auto currentMipLevel = mipMapCount - 1; currentMipLevel >= 0; currentMipLevel--)
{
const auto sizeOfMipLevel = texture->GetSizeOfMipLevel(currentMipLevel) * texture->GetFaceCount();
currentFileSize += sizeOfMipLevel;
if (currentMipLevel < static_cast<int>(std::extent_v<decltype(iwi8::IwiHeader::fileSizeForPicmip)>)
&& currentFileSize != header.fileSizeForPicmip[currentMipLevel])
switch (static_cast<iwi13::IwiFormat>(format))
{
printf("Iwi has invalid file size for picmip %i\n", currentMipLevel);
case iwi13::IwiFormat::IMG_FORMAT_BITMAP_RGBA:
return &ImageFormat::FORMAT_R8_G8_B8_A8;
case iwi13::IwiFormat::IMG_FORMAT_BITMAP_RGB:
return &ImageFormat::FORMAT_R8_G8_B8;
case iwi13::IwiFormat::IMG_FORMAT_BITMAP_ALPHA:
return &ImageFormat::FORMAT_A8;
case iwi13::IwiFormat::IMG_FORMAT_DXT1:
return &ImageFormat::FORMAT_BC1;
case iwi13::IwiFormat::IMG_FORMAT_DXT3:
return &ImageFormat::FORMAT_BC2;
case iwi13::IwiFormat::IMG_FORMAT_DXT5:
return &ImageFormat::FORMAT_BC3;
case iwi13::IwiFormat::IMG_FORMAT_DXN:
return &ImageFormat::FORMAT_BC5;
case iwi13::IwiFormat::IMG_FORMAT_BITMAP_LUMINANCE_ALPHA:
return &ImageFormat::FORMAT_R8_A8;
case iwi13::IwiFormat::IMG_FORMAT_BITMAP_LUMINANCE:
return &ImageFormat::FORMAT_R8;
case iwi13::IwiFormat::IMG_FORMAT_WAVELET_RGBA: // used
case iwi13::IwiFormat::IMG_FORMAT_WAVELET_RGB: // used
case iwi13::IwiFormat::IMG_FORMAT_WAVELET_LUMINANCE_ALPHA:
case iwi13::IwiFormat::IMG_FORMAT_WAVELET_LUMINANCE:
case iwi13::IwiFormat::IMG_FORMAT_WAVELET_ALPHA:
case iwi13::IwiFormat::IMG_FORMAT_BITMAP_RGB565:
case iwi13::IwiFormat::IMG_FORMAT_BITMAP_RGB5A3:
case iwi13::IwiFormat::IMG_FORMAT_BITMAP_C8:
case iwi13::IwiFormat::IMG_FORMAT_BITMAP_RGBA8:
case iwi13::IwiFormat::IMG_FORMAT_A16B16G16R16F:
std::cerr << std::format("Unsupported IWI format: {}\n", format);
break;
default:
std::cerr << std::format("Unknown IWI format: {}\n", format);
break;
}
m_memory_manager->Delete(texture);
return nullptr;
}
std::unique_ptr<Texture> LoadIwi13(std::istream& stream)
{
iwi13::IwiHeader header{};
stream.read(reinterpret_cast<char*>(&header), sizeof(header));
if (stream.gcount() != sizeof(header))
return nullptr;
const auto* format = GetFormat6(header.format);
if (format == nullptr)
return nullptr;
auto width = header.dimensions[0];
auto height = header.dimensions[1];
auto depth = header.dimensions[2];
auto hasMipMaps = !(header.flags & iwi13::IwiFlags::IMG_FLAG_NOMIPMAPS);
std::unique_ptr<Texture> texture;
if (header.flags & iwi13::IwiFlags::IMG_FLAG_CUBEMAP)
texture = std::make_unique<TextureCube>(format, width, height, hasMipMaps);
else if (header.flags & iwi13::IwiFlags::IMG_FLAG_VOLMAP)
texture = std::make_unique<Texture3D>(format, width, height, depth, hasMipMaps);
else
texture = std::make_unique<Texture2D>(format, width, height, hasMipMaps);
texture->Allocate();
auto currentFileSize = sizeof(iwi13::IwiHeader) + sizeof(IwiVersion);
const auto mipMapCount = hasMipMaps ? texture->GetMipMapCount() : 1;
for (auto currentMipLevel = mipMapCount - 1; currentMipLevel >= 0; currentMipLevel--)
{
const auto sizeOfMipLevel = texture->GetSizeOfMipLevel(currentMipLevel) * texture->GetFaceCount();
currentFileSize += sizeOfMipLevel;
if (currentMipLevel < static_cast<int>(std::extent_v<decltype(iwi13::IwiHeader::fileSizeForPicmip)>)
&& currentFileSize != header.fileSizeForPicmip[currentMipLevel])
{
std::cerr << std::format("Iwi has invalid file size for picmip {}\n", currentMipLevel);
return nullptr;
}
stream.read(reinterpret_cast<char*>(texture->GetBufferForMipLevel(currentMipLevel)), sizeOfMipLevel);
if (stream.gcount() != sizeOfMipLevel)
{
std::cerr << std::format("Unexpected eof of iwi in mip level {}\n", currentMipLevel);
return nullptr;
}
}
return texture;
}
const ImageFormat* GetFormat27(int8_t format)
{
switch (static_cast<iwi27::IwiFormat>(format))
{
case iwi27::IwiFormat::IMG_FORMAT_BITMAP_RGBA:
return &ImageFormat::FORMAT_R8_G8_B8_A8;
case iwi27::IwiFormat::IMG_FORMAT_BITMAP_ALPHA:
return &ImageFormat::FORMAT_A8;
case iwi27::IwiFormat::IMG_FORMAT_DXT1:
return &ImageFormat::FORMAT_BC1;
case iwi27::IwiFormat::IMG_FORMAT_DXT3:
return &ImageFormat::FORMAT_BC2;
case iwi27::IwiFormat::IMG_FORMAT_DXT5:
return &ImageFormat::FORMAT_BC3;
case iwi27::IwiFormat::IMG_FORMAT_DXN:
return &ImageFormat::FORMAT_BC5;
case iwi27::IwiFormat::IMG_FORMAT_A16B16G16R16F:
assert(false); // Unsupported yet
return &ImageFormat::FORMAT_R16_G16_B16_A16_FLOAT;
case iwi27::IwiFormat::IMG_FORMAT_BITMAP_RGB:
return &ImageFormat::FORMAT_R8_G8_B8;
case iwi27::IwiFormat::IMG_FORMAT_BITMAP_LUMINANCE_ALPHA:
return &ImageFormat::FORMAT_R8_A8;
case iwi27::IwiFormat::IMG_FORMAT_BITMAP_LUMINANCE:
return &ImageFormat::FORMAT_R8;
case iwi27::IwiFormat::IMG_FORMAT_WAVELET_RGBA:
case iwi27::IwiFormat::IMG_FORMAT_WAVELET_RGB:
case iwi27::IwiFormat::IMG_FORMAT_WAVELET_LUMINANCE_ALPHA:
case iwi27::IwiFormat::IMG_FORMAT_WAVELET_LUMINANCE:
case iwi27::IwiFormat::IMG_FORMAT_WAVELET_ALPHA:
case iwi27::IwiFormat::IMG_FORMAT_BITMAP_RGB565:
case iwi27::IwiFormat::IMG_FORMAT_BITMAP_RGB5A3:
case iwi27::IwiFormat::IMG_FORMAT_BITMAP_C8:
case iwi27::IwiFormat::IMG_FORMAT_BITMAP_RGBA8:
std::cerr << std::format("Unsupported IWI format: {}\n", format);
break;
default:
std::cerr << std::format("Unknown IWI format: {}\n", format);
break;
}
return nullptr;
}
std::unique_ptr<Texture> LoadIwi27(std::istream& stream)
{
iwi27::IwiHeader header{};
stream.read(reinterpret_cast<char*>(&header), sizeof(header));
if (stream.gcount() != sizeof(header))
return nullptr;
const auto* format = GetFormat27(header.format);
if (format == nullptr)
return nullptr;
auto width = header.dimensions[0];
auto height = header.dimensions[1];
auto depth = header.dimensions[2];
auto hasMipMaps = !(header.flags & iwi27::IwiFlags::IMG_FLAG_NOMIPMAPS);
std::unique_ptr<Texture> texture;
if (header.flags & iwi27::IwiFlags::IMG_FLAG_CUBEMAP)
texture = std::make_unique<TextureCube>(format, width, height, hasMipMaps);
else if (header.flags & iwi27::IwiFlags::IMG_FLAG_VOLMAP)
texture = std::make_unique<Texture3D>(format, width, height, depth, hasMipMaps);
else
texture = std::make_unique<Texture2D>(format, width, height, hasMipMaps);
texture->Allocate();
auto currentFileSize = sizeof(iwi27::IwiHeader) + sizeof(IwiVersion);
const auto mipMapCount = hasMipMaps ? texture->GetMipMapCount() : 1;
for (auto currentMipLevel = mipMapCount - 1; currentMipLevel >= 0; currentMipLevel--)
{
const auto sizeOfMipLevel = texture->GetSizeOfMipLevel(currentMipLevel) * texture->GetFaceCount();
currentFileSize += sizeOfMipLevel;
if (currentMipLevel < static_cast<int>(std::extent_v<decltype(iwi27::IwiHeader::fileSizeForPicmip)>)
&& currentFileSize != header.fileSizeForPicmip[currentMipLevel])
{
std::cerr << std::format("Iwi has invalid file size for picmip {}\n", currentMipLevel);
return nullptr;
}
stream.read(reinterpret_cast<char*>(texture->GetBufferForMipLevel(currentMipLevel)), sizeOfMipLevel);
if (stream.gcount() != sizeOfMipLevel)
{
std::cerr << std::format("Unexpected eof of iwi in mip level {}\n", currentMipLevel);
return nullptr;
}
}
return texture;
}
std::unique_ptr<Texture> LoadIwi(std::istream& stream)
{
IwiVersion iwiVersion{};
stream.read(reinterpret_cast<char*>(&iwiVersion), sizeof(iwiVersion));
if (stream.gcount() != sizeof(iwiVersion))
return nullptr;
if (iwiVersion.tag[0] != 'I' || iwiVersion.tag[1] != 'W' || iwiVersion.tag[2] != 'i')
{
std::cerr << "Invalid IWI magic\n";
return nullptr;
}
stream.read(reinterpret_cast<char*>(texture->GetBufferForMipLevel(currentMipLevel)), sizeOfMipLevel);
if (stream.gcount() != sizeOfMipLevel)
switch (iwiVersion.version)
{
printf("Unexpected eof of iwi in mip level %i\n", currentMipLevel);
case 6:
return LoadIwi6(stream);
m_memory_manager->Delete(texture);
return nullptr;
}
}
case 8:
return LoadIwi8(stream);
return texture;
}
case 13:
return LoadIwi13(stream);
const ImageFormat* IwiLoader::GetFormat13(int8_t format)
{
switch (static_cast<iwi13::IwiFormat>(format))
{
case iwi13::IwiFormat::IMG_FORMAT_BITMAP_RGBA:
return &ImageFormat::FORMAT_R8_G8_B8_A8;
case iwi13::IwiFormat::IMG_FORMAT_BITMAP_RGB:
return &ImageFormat::FORMAT_R8_G8_B8;
case iwi13::IwiFormat::IMG_FORMAT_BITMAP_ALPHA:
return &ImageFormat::FORMAT_A8;
case iwi13::IwiFormat::IMG_FORMAT_DXT1:
return &ImageFormat::FORMAT_BC1;
case iwi13::IwiFormat::IMG_FORMAT_DXT3:
return &ImageFormat::FORMAT_BC2;
case iwi13::IwiFormat::IMG_FORMAT_DXT5:
return &ImageFormat::FORMAT_BC3;
case iwi13::IwiFormat::IMG_FORMAT_DXN:
return &ImageFormat::FORMAT_BC5;
case iwi13::IwiFormat::IMG_FORMAT_BITMAP_LUMINANCE_ALPHA:
return &ImageFormat::FORMAT_R8_A8;
case iwi13::IwiFormat::IMG_FORMAT_BITMAP_LUMINANCE:
return &ImageFormat::FORMAT_R8;
case iwi13::IwiFormat::IMG_FORMAT_WAVELET_RGBA: // used
case iwi13::IwiFormat::IMG_FORMAT_WAVELET_RGB: // used
case iwi13::IwiFormat::IMG_FORMAT_WAVELET_LUMINANCE_ALPHA:
case iwi13::IwiFormat::IMG_FORMAT_WAVELET_LUMINANCE:
case iwi13::IwiFormat::IMG_FORMAT_WAVELET_ALPHA:
case iwi13::IwiFormat::IMG_FORMAT_BITMAP_RGB565:
case iwi13::IwiFormat::IMG_FORMAT_BITMAP_RGB5A3:
case iwi13::IwiFormat::IMG_FORMAT_BITMAP_C8:
case iwi13::IwiFormat::IMG_FORMAT_BITMAP_RGBA8:
case iwi13::IwiFormat::IMG_FORMAT_A16B16G16R16F:
printf("Unsupported IWI format: %i\n", format);
break;
default:
printf("Unknown IWI format: %i\n", format);
break;
}
case 27:
return LoadIwi27(stream);
return nullptr;
}
Texture* IwiLoader::LoadIwi13(std::istream& stream) const
{
iwi13::IwiHeader header{};
stream.read(reinterpret_cast<char*>(&header), sizeof(header));
if (stream.gcount() != sizeof(header))
return nullptr;
const auto* format = GetFormat6(header.format);
if (format == nullptr)
return nullptr;
auto width = header.dimensions[0];
auto height = header.dimensions[1];
auto depth = header.dimensions[2];
auto hasMipMaps = !(header.flags & iwi13::IwiFlags::IMG_FLAG_NOMIPMAPS);
Texture* texture;
if (header.flags & iwi13::IwiFlags::IMG_FLAG_CUBEMAP)
{
texture = m_memory_manager->Create<TextureCube>(format, width, height, hasMipMaps);
}
else if (header.flags & iwi13::IwiFlags::IMG_FLAG_VOLMAP)
{
texture = m_memory_manager->Create<Texture3D>(format, width, height, depth, hasMipMaps);
}
else
{
texture = m_memory_manager->Create<Texture2D>(format, width, height, hasMipMaps);
}
texture->Allocate();
auto currentFileSize = sizeof(iwi13::IwiHeader) + sizeof(IwiVersion);
const auto mipMapCount = hasMipMaps ? texture->GetMipMapCount() : 1;
for (auto currentMipLevel = mipMapCount - 1; currentMipLevel >= 0; currentMipLevel--)
{
const auto sizeOfMipLevel = texture->GetSizeOfMipLevel(currentMipLevel) * texture->GetFaceCount();
currentFileSize += sizeOfMipLevel;
if (currentMipLevel < static_cast<int>(std::extent_v<decltype(iwi13::IwiHeader::fileSizeForPicmip)>)
&& currentFileSize != header.fileSizeForPicmip[currentMipLevel])
{
printf("Iwi has invalid file size for picmip %i\n", currentMipLevel);
m_memory_manager->Delete(texture);
return nullptr;
default:
break;
}
stream.read(reinterpret_cast<char*>(texture->GetBufferForMipLevel(currentMipLevel)), sizeOfMipLevel);
if (stream.gcount() != sizeOfMipLevel)
{
printf("Unexpected eof of iwi in mip level %i\n", currentMipLevel);
m_memory_manager->Delete(texture);
return nullptr;
}
}
return texture;
}
const ImageFormat* IwiLoader::GetFormat27(int8_t format)
{
switch (static_cast<iwi27::IwiFormat>(format))
{
case iwi27::IwiFormat::IMG_FORMAT_BITMAP_RGBA:
return &ImageFormat::FORMAT_R8_G8_B8_A8;
case iwi27::IwiFormat::IMG_FORMAT_BITMAP_ALPHA:
return &ImageFormat::FORMAT_A8;
case iwi27::IwiFormat::IMG_FORMAT_DXT1:
return &ImageFormat::FORMAT_BC1;
case iwi27::IwiFormat::IMG_FORMAT_DXT3:
return &ImageFormat::FORMAT_BC2;
case iwi27::IwiFormat::IMG_FORMAT_DXT5:
return &ImageFormat::FORMAT_BC3;
case iwi27::IwiFormat::IMG_FORMAT_DXN:
return &ImageFormat::FORMAT_BC5;
case iwi27::IwiFormat::IMG_FORMAT_A16B16G16R16F:
assert(false); // Unsupported yet
return &ImageFormat::FORMAT_R16_G16_B16_A16_FLOAT;
case iwi27::IwiFormat::IMG_FORMAT_BITMAP_RGB:
return &ImageFormat::FORMAT_R8_G8_B8;
case iwi27::IwiFormat::IMG_FORMAT_BITMAP_LUMINANCE_ALPHA:
return &ImageFormat::FORMAT_R8_A8;
case iwi27::IwiFormat::IMG_FORMAT_BITMAP_LUMINANCE:
return &ImageFormat::FORMAT_R8;
case iwi27::IwiFormat::IMG_FORMAT_WAVELET_RGBA:
case iwi27::IwiFormat::IMG_FORMAT_WAVELET_RGB:
case iwi27::IwiFormat::IMG_FORMAT_WAVELET_LUMINANCE_ALPHA:
case iwi27::IwiFormat::IMG_FORMAT_WAVELET_LUMINANCE:
case iwi27::IwiFormat::IMG_FORMAT_WAVELET_ALPHA:
case iwi27::IwiFormat::IMG_FORMAT_BITMAP_RGB565:
case iwi27::IwiFormat::IMG_FORMAT_BITMAP_RGB5A3:
case iwi27::IwiFormat::IMG_FORMAT_BITMAP_C8:
case iwi27::IwiFormat::IMG_FORMAT_BITMAP_RGBA8:
printf("Unsupported IWI format: %i\n", format);
break;
default:
printf("Unknown IWI format: %i\n", format);
break;
}
return nullptr;
}
Texture* IwiLoader::LoadIwi27(std::istream& stream) const
{
iwi27::IwiHeader header{};
stream.read(reinterpret_cast<char*>(&header), sizeof(header));
if (stream.gcount() != sizeof(header))
std::cerr << std::format("Unknown IWI version {}\n", iwiVersion.version);
return nullptr;
const auto* format = GetFormat27(header.format);
if (format == nullptr)
return nullptr;
auto width = header.dimensions[0];
auto height = header.dimensions[1];
auto depth = header.dimensions[2];
auto hasMipMaps = !(header.flags & iwi27::IwiFlags::IMG_FLAG_NOMIPMAPS);
Texture* texture;
if (header.flags & iwi27::IwiFlags::IMG_FLAG_CUBEMAP)
{
texture = m_memory_manager->Create<TextureCube>(format, width, height, hasMipMaps);
}
else if (header.flags & iwi27::IwiFlags::IMG_FLAG_VOLMAP)
{
texture = m_memory_manager->Create<Texture3D>(format, width, height, depth, hasMipMaps);
}
else
{
texture = m_memory_manager->Create<Texture2D>(format, width, height, hasMipMaps);
}
texture->Allocate();
auto currentFileSize = sizeof(iwi27::IwiHeader) + sizeof(IwiVersion);
const auto mipMapCount = hasMipMaps ? texture->GetMipMapCount() : 1;
for (auto currentMipLevel = mipMapCount - 1; currentMipLevel >= 0; currentMipLevel--)
{
const auto sizeOfMipLevel = texture->GetSizeOfMipLevel(currentMipLevel) * texture->GetFaceCount();
currentFileSize += sizeOfMipLevel;
if (currentMipLevel < static_cast<int>(std::extent_v<decltype(iwi27::IwiHeader::fileSizeForPicmip)>)
&& currentFileSize != header.fileSizeForPicmip[currentMipLevel])
{
printf("Iwi has invalid file size for picmip %i\n", currentMipLevel);
m_memory_manager->Delete(texture);
return nullptr;
}
stream.read(reinterpret_cast<char*>(texture->GetBufferForMipLevel(currentMipLevel)), sizeOfMipLevel);
if (stream.gcount() != sizeOfMipLevel)
{
printf("Unexpected eof of iwi in mip level %i\n", currentMipLevel);
m_memory_manager->Delete(texture);
return nullptr;
}
}
return texture;
}
Texture* IwiLoader::LoadIwi(std::istream& stream)
{
IwiVersion iwiVersion{};
stream.read(reinterpret_cast<char*>(&iwiVersion), sizeof(iwiVersion));
if (stream.gcount() != sizeof(iwiVersion))
return nullptr;
if (iwiVersion.tag[0] != 'I' || iwiVersion.tag[1] != 'W' || iwiVersion.tag[2] != 'i')
{
printf("Invalid IWI magic\n");
}
switch (iwiVersion.version)
{
case 6:
return LoadIwi6(stream);
case 8:
return LoadIwi8(stream);
case 13:
return LoadIwi13(stream);
case 27:
return LoadIwi27(stream);
default:
break;
}
printf("Unknown IWI version %i\n", iwiVersion.version);
return nullptr;
}
} // namespace iwi

View File

@ -1,28 +1,11 @@
#pragma once
#include "Image/Texture.h"
#include "Utils/MemoryManager.h"
#include <istream>
#include <memory>
class IwiLoader
namespace iwi
{
MemoryManager* m_memory_manager;
static const ImageFormat* GetFormat6(int8_t format);
Texture* LoadIwi6(std::istream& stream) const;
static const ImageFormat* GetFormat8(int8_t format);
Texture* LoadIwi8(std::istream& stream) const;
static const ImageFormat* GetFormat13(int8_t format);
Texture* LoadIwi13(std::istream& stream) const;
static const ImageFormat* GetFormat27(int8_t format);
Texture* LoadIwi27(std::istream& stream) const;
public:
explicit IwiLoader(MemoryManager* memoryManager);
Texture* LoadIwi(std::istream& stream);
};
std::unique_ptr<Texture> LoadIwi(std::istream& stream);
}; // namespace iwi

View File

@ -29,8 +29,6 @@ template<typename ContainerType, typename ReferencerType> class ObjContainerRepo
ObjContainerEntry& operator=(ObjContainerEntry&& other) noexcept = default;
};
std::vector<ObjContainerEntry> m_containers;
public:
ObjContainerRepository() = default;
~ObjContainerRepository() = default;
@ -120,4 +118,7 @@ public:
return entry.m_container.get();
});
}
private:
std::vector<ObjContainerEntry> m_containers;
};

View File

@ -22,7 +22,7 @@ const IObjLoader* const OBJ_LOADERS[]{
new T6::ObjLoader(),
};
void ObjLoading::LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone)
void ObjLoading::LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone)
{
for (const auto* loader : OBJ_LOADERS)
{
@ -34,19 +34,7 @@ void ObjLoading::LoadReferencedContainersForZone(ISearchPath* searchPath, Zone*
}
}
void ObjLoading::LoadObjDataForZone(ISearchPath* searchPath, Zone* zone)
{
for (const auto* loader : OBJ_LOADERS)
{
if (loader->SupportsZone(zone))
{
loader->LoadObjDataForZone(searchPath, zone);
return;
}
}
}
void ObjLoading::UnloadContainersOfZone(Zone* zone)
void ObjLoading::UnloadContainersOfZone(Zone& zone)
{
for (const auto* loader : OBJ_LOADERS)
{
@ -58,28 +46,28 @@ void ObjLoading::UnloadContainersOfZone(Zone* zone)
}
}
void ObjLoading::LoadIWDsInSearchPath(ISearchPath* searchPath)
void ObjLoading::LoadIWDsInSearchPath(ISearchPath& searchPath)
{
searchPath->Find(SearchPathSearchOptions().IncludeSubdirectories(false).FilterExtensions("iwd"),
[searchPath](const std::string& path)
{
auto file = std::make_unique<std::ifstream>(path, std::fstream::in | std::fstream::binary);
searchPath.Find(SearchPathSearchOptions().IncludeSubdirectories(false).FilterExtensions("iwd"),
[&searchPath](const std::string& path)
{
auto file = std::make_unique<std::ifstream>(path, std::fstream::in | std::fstream::binary);
if (file->is_open())
{
auto iwd = std::make_unique<IWD>(path, std::move(file));
if (file->is_open())
{
auto iwd = std::make_unique<IWD>(path, std::move(file));
if (iwd->Initialize())
{
IWD::Repository.AddContainer(std::move(iwd), searchPath);
}
}
});
if (iwd->Initialize())
{
IWD::Repository.AddContainer(std::move(iwd), &searchPath);
}
}
});
}
void ObjLoading::UnloadIWDsInSearchPath(ISearchPath* searchPath)
void ObjLoading::UnloadIWDsInSearchPath(ISearchPath& searchPath)
{
IWD::Repository.RemoveContainerReferences(searchPath);
IWD::Repository.RemoveContainerReferences(&searchPath);
}
SearchPaths ObjLoading::GetIWDSearchPaths()
@ -94,11 +82,11 @@ SearchPaths ObjLoading::GetIWDSearchPaths()
return iwdPaths;
}
bool ObjLoading::LoadAssetForZone(AssetLoadingContext* context, const asset_type_t assetType, const std::string& assetName)
bool ObjLoading::LoadAssetForZone(AssetLoadingContext& context, const asset_type_t assetType, const std::string& assetName)
{
for (const auto* loader : OBJ_LOADERS)
{
if (loader->SupportsZone(context->m_zone))
if (loader->SupportsZone(context.m_zone))
{
return loader->LoadAssetForZone(context, assetType, assetName);
}
@ -107,11 +95,11 @@ bool ObjLoading::LoadAssetForZone(AssetLoadingContext* context, const asset_type
return false;
}
void ObjLoading::FinalizeAssetsForZone(AssetLoadingContext* context)
void ObjLoading::FinalizeAssetsForZone(AssetLoadingContext& context)
{
for (const auto* loader : OBJ_LOADERS)
{
if (loader->SupportsZone(context->m_zone))
if (loader->SupportsZone(context.m_zone))
{
loader->FinalizeAssetsForZone(context);
return;

View File

@ -21,25 +21,25 @@ public:
* \param searchPath The search path to use to find the referenced containers.
* \param zone The zone to load all referenced containers of.
*/
static void LoadReferencedContainersForZone(ISearchPath* searchPath, Zone* zone);
static void LoadReferencedContainersForZone(ISearchPath& searchPath, Zone& zone);
/**
* \brief Unloads all containers that were referenced by a specified zone. If referenced by more than one zone a container will only be unloaded once all
* referencing zones were unloaded the container. \param zone The zone to unload all referenced containers for.
*/
static void UnloadContainersOfZone(Zone* zone);
static void UnloadContainersOfZone(Zone& zone);
/**
* \brief Loads all IWDs that can be found in a specified search path.
* \param searchPath The search path that contains IWDs to be loaded.
*/
static void LoadIWDsInSearchPath(ISearchPath* searchPath);
static void LoadIWDsInSearchPath(ISearchPath& searchPath);
/**
* \brief Unloads all IWDs that were loaded from the specified search path.
* \param searchPath The search path that was used to load the IWDs to be unloaded.
*/
static void UnloadIWDsInSearchPath(ISearchPath* searchPath);
static void UnloadIWDsInSearchPath(ISearchPath& searchPath);
/**
* \brief Creates a \c SearchPaths object containing all IWDs that are currently loaded.
@ -47,13 +47,6 @@ public:
*/
static SearchPaths GetIWDSearchPaths();
/**
* \brief Loads the obj data for all assets of a zone.
* \param searchPath The search path to use to search for all obj data files.
* \param zone The zone of the assets to load the obj data for.
*/
static void LoadObjDataForZone(ISearchPath* searchPath, Zone* zone);
static bool LoadAssetForZone(AssetLoadingContext* context, asset_type_t assetType, const std::string& assetName);
static void FinalizeAssetsForZone(AssetLoadingContext* context);
static bool LoadAssetForZone(AssetLoadingContext& context, asset_type_t assetType, const std::string& assetName);
static void FinalizeAssetsForZone(AssetLoadingContext& context);
};

View File

@ -1,5 +1,6 @@
#include "SearchPaths.h"
#include <cassert>
#include <filesystem>
SearchPathOpenFile SearchPaths::Open(const std::string& fileName)
@ -38,11 +39,13 @@ void SearchPaths::CommitSearchPath(std::unique_ptr<ISearchPath> searchPath)
void SearchPaths::IncludeSearchPath(ISearchPath* searchPath)
{
assert(searchPath);
m_search_paths.push_back(searchPath);
}
void SearchPaths::RemoveSearchPath(ISearchPath* searchPath)
void SearchPaths::RemoveSearchPath(const ISearchPath* searchPath)
{
assert(searchPath);
for (auto i = m_search_paths.begin(); i != m_search_paths.end(); ++i)
{
if (*i == searchPath)

View File

@ -40,7 +40,7 @@ public:
* \brief Removes a search path from the \c SearchPaths object. If the search path was committed then it will \b NOT be deleted when destructing the \c
* SearchPaths object. \param searchPath The search path to remove.
*/
void RemoveSearchPath(ISearchPath* searchPath);
void RemoveSearchPath(const ISearchPath* searchPath);
iterator begin();
iterator end();

View File

@ -8,9 +8,9 @@ namespace sound_curve
{
std::unique_ptr<GenericGraph2D> LoadSoundCurve(const IAssetLoadingManager* manager, const std::string& soundCurveName)
{
auto* searchPath = manager->GetAssetLoadingContext()->m_raw_search_path;
auto& searchPath = manager->GetAssetLoadingContext()->m_raw_search_path;
const auto fileName = std::format("soundaliases/{}.vfcurve", soundCurveName);
const auto file = searchPath->Open(fileName);
const auto file = searchPath.Open(fileName);
if (!file.IsOpen())
{
return nullptr;

View File

@ -9,9 +9,9 @@ namespace
{
std::unique_ptr<GenericGraph2D> LoadAccuracyGraph(const IAssetLoadingManager* manager, const std::string& graphName, const std::string& subFolder)
{
auto* searchPath = manager->GetAssetLoadingContext()->m_raw_search_path;
auto& searchPath = manager->GetAssetLoadingContext()->m_raw_search_path;
const auto fileName = std::format("accuracy/{}/{}", subFolder, graphName);
const auto file = searchPath->Open(fileName);
const auto file = searchPath.Open(fileName);
if (!file.IsOpen())
{
std::cerr << std::format("Failed to open file for accuracy graph: {}/{}\n", subFolder, graphName);

View File

@ -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 = manager.GetAssetLoadingContext()->m_raw_search_path.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

@ -54,7 +54,7 @@ namespace GAME
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_script_strings(manager.GetAssetLoadingContext()->m_zone.m_script_strings),
m_manager(manager),
m_part_classification_state(*m_manager.GetAssetLoadingContext()->GetZoneAssetLoaderState<PartClassificationState>()),
m_dependencies(dependencies)
@ -616,7 +616,7 @@ namespace GAME
bool LoadLod(const JsonXModelLod& jLod, XModel& xmodel, unsigned lodNumber)
{
const auto file = m_manager.GetAssetLoadingContext()->m_raw_search_path->Open(jLod.file);
const auto file = m_manager.GetAssetLoadingContext()->m_raw_search_path.Open(jLod.file);
if (!file.IsOpen())
{
PrintError(xmodel, std::format("Failed to open file for lod {}: \"{}\"", lodNumber, jLod.file));