mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 16:15:43 +00:00
Material loading base
This commit is contained in:
parent
bc91738ee9
commit
82349d3432
@ -960,9 +960,9 @@ namespace IW4
|
|||||||
struct GfxImage
|
struct GfxImage
|
||||||
{
|
{
|
||||||
GfxTexture texture;
|
GfxTexture texture;
|
||||||
char mapType;
|
unsigned char mapType;
|
||||||
char semantic;
|
unsigned char semantic;
|
||||||
char category;
|
unsigned char category;
|
||||||
bool useSrgbReads;
|
bool useSrgbReads;
|
||||||
Picmip picmip;
|
Picmip picmip;
|
||||||
bool noPicmip;
|
bool noPicmip;
|
||||||
|
@ -12,6 +12,7 @@ namespace IW4
|
|||||||
static constexpr const char* INFO_STRING_PREFIX_VEHICLE = "VEHICLEFILE";
|
static constexpr const char* INFO_STRING_PREFIX_VEHICLE = "VEHICLEFILE";
|
||||||
static constexpr const char* INFO_STRING_PREFIX_WEAPON = "WEAPONFILE";
|
static constexpr const char* INFO_STRING_PREFIX_WEAPON = "WEAPONFILE";
|
||||||
|
|
||||||
|
static constexpr const char* GDF_FILENAME_MATERIAL = "material.gdf";
|
||||||
static constexpr const char* GDF_FILENAME_PHYS_PRESET = "physpreset.gdf";
|
static constexpr const char* GDF_FILENAME_PHYS_PRESET = "physpreset.gdf";
|
||||||
static constexpr const char* GDF_FILENAME_TRACER = "tracer.gdf";
|
static constexpr const char* GDF_FILENAME_TRACER = "tracer.gdf";
|
||||||
static constexpr const char* GDF_FILENAME_VEHICLE = "vehicle.gdf";
|
static constexpr const char* GDF_FILENAME_VEHICLE = "vehicle.gdf";
|
||||||
|
82
src/ObjLoading/AssetLoading/AbstractGdtEntryReader.cpp
Normal file
82
src/ObjLoading/AssetLoading/AbstractGdtEntryReader.cpp
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
#include "AbstractGdtEntryReader.h"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
GdtReadingException::GdtReadingException(std::string message)
|
||||||
|
: exception(message.c_str()),
|
||||||
|
m_message(std::move(message))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* GdtReadingException::what() const
|
||||||
|
{
|
||||||
|
return m_message.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractGdtEntryReader::AbstractGdtEntryReader(const GdtEntry& entry)
|
||||||
|
: m_entry(entry)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string AbstractGdtEntryReader::ReadStringProperty(const std::string& propertyName, std::string defaultValue) const
|
||||||
|
{
|
||||||
|
const auto foundProperty = m_entry.m_properties.find(propertyName);
|
||||||
|
if (foundProperty == m_entry.m_properties.end())
|
||||||
|
return defaultValue;
|
||||||
|
|
||||||
|
return foundProperty->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AbstractGdtEntryReader::ReadBoolProperty(const std::string& propertyName, const bool defaultValue) const
|
||||||
|
{
|
||||||
|
const auto foundProperty = m_entry.m_properties.find(propertyName);
|
||||||
|
if (foundProperty == m_entry.m_properties.end())
|
||||||
|
return defaultValue;
|
||||||
|
|
||||||
|
char* endPtr = nullptr;
|
||||||
|
const auto result = std::strtol(foundProperty->second.c_str(), &endPtr, 10);
|
||||||
|
if (endPtr != &foundProperty->second[foundProperty->second.size()])
|
||||||
|
{
|
||||||
|
std::ostringstream ss;
|
||||||
|
ss << "\"" << foundProperty->second << "\" is not a valid boolean value";
|
||||||
|
throw GdtReadingException(ss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
return result != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AbstractGdtEntryReader::ReadIntegerProperty(const std::string& propertyName, const int defaultValue) const
|
||||||
|
{
|
||||||
|
const auto foundProperty = m_entry.m_properties.find(propertyName);
|
||||||
|
if (foundProperty == m_entry.m_properties.end())
|
||||||
|
return defaultValue;
|
||||||
|
|
||||||
|
char* endPtr = nullptr;
|
||||||
|
const auto result = std::strtol(foundProperty->second.c_str(), &endPtr, 10);
|
||||||
|
if (endPtr != &foundProperty->second[foundProperty->second.size()])
|
||||||
|
{
|
||||||
|
std::ostringstream ss;
|
||||||
|
ss << "\"" << foundProperty->second << "\" is not a valid integer value";
|
||||||
|
throw GdtReadingException(ss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
float AbstractGdtEntryReader::ReadFloatProperty(const std::string& propertyName, const float defaultValue) const
|
||||||
|
{
|
||||||
|
const auto foundProperty = m_entry.m_properties.find(propertyName);
|
||||||
|
if (foundProperty == m_entry.m_properties.end())
|
||||||
|
return defaultValue;
|
||||||
|
|
||||||
|
char* endPtr = nullptr;
|
||||||
|
const auto result = std::strtof(foundProperty->second.c_str(), &endPtr);
|
||||||
|
if (endPtr != &foundProperty->second[foundProperty->second.size()])
|
||||||
|
{
|
||||||
|
std::ostringstream ss;
|
||||||
|
ss << "\"" << foundProperty->second << "\" is not a valid float value";
|
||||||
|
throw GdtReadingException(ss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
29
src/ObjLoading/AssetLoading/AbstractGdtEntryReader.h
Normal file
29
src/ObjLoading/AssetLoading/AbstractGdtEntryReader.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
|
#include "Utils/ClassUtils.h"
|
||||||
|
#include "Obj/Gdt/GdtEntry.h"
|
||||||
|
|
||||||
|
class GdtReadingException : public std::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit GdtReadingException(std::string message);
|
||||||
|
_NODISCARD const char* what() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_message;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AbstractGdtEntryReader
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
explicit AbstractGdtEntryReader(const GdtEntry& entry);
|
||||||
|
|
||||||
|
_NODISCARD std::string ReadStringProperty(const std::string& propertyName, std::string defaultValue = std::string()) const;
|
||||||
|
_NODISCARD bool ReadBoolProperty(const std::string& propertyName, bool defaultValue = false) const;
|
||||||
|
_NODISCARD int ReadIntegerProperty(const std::string& propertyName, int defaultValue = 0) const;
|
||||||
|
_NODISCARD float ReadFloatProperty(const std::string& propertyName, float defaultValue = 0.0f) const;
|
||||||
|
|
||||||
|
const GdtEntry& m_entry;
|
||||||
|
};
|
@ -1,13 +1,309 @@
|
|||||||
#include "AssetLoaderMaterial.h"
|
#include "AssetLoaderMaterial.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include "ObjLoading.h"
|
#include "ObjLoading.h"
|
||||||
|
#include "AssetLoading/AbstractGdtEntryReader.h"
|
||||||
|
#include "Game/IW4/CommonIW4.h"
|
||||||
#include "Game/IW4/IW4.h"
|
#include "Game/IW4/IW4.h"
|
||||||
|
#include "Game/IW4/ObjConstantsIW4.h"
|
||||||
#include "Pool/GlobalAssetPool.h"
|
#include "Pool/GlobalAssetPool.h"
|
||||||
|
|
||||||
using namespace IW4;
|
using namespace IW4;
|
||||||
|
|
||||||
|
namespace IW4
|
||||||
|
{
|
||||||
|
class MaterialGdtLoader : AbstractGdtEntryReader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MaterialGdtLoader(const GdtEntry& entry, MemoryManager* memory, IAssetLoadingManager* manager)
|
||||||
|
: AbstractGdtEntryReader(entry),
|
||||||
|
m_memory(memory),
|
||||||
|
m_manager(manager),
|
||||||
|
m_material(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Load()
|
||||||
|
{
|
||||||
|
m_material = m_memory->Create<Material>();
|
||||||
|
memset(m_material, 0, sizeof(Material));
|
||||||
|
|
||||||
|
m_material->info.name = m_memory->Dup(m_entry.m_name.c_str());
|
||||||
|
material_template();
|
||||||
|
|
||||||
|
FinalizeMaterial();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_NODISCARD Material* GetMaterial() const
|
||||||
|
{
|
||||||
|
return m_material;
|
||||||
|
}
|
||||||
|
|
||||||
|
_NODISCARD std::vector<XAssetInfoGeneric*> GetDependencies()
|
||||||
|
{
|
||||||
|
return std::move(m_dependencies);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void material_template()
|
||||||
|
{
|
||||||
|
const auto materialType = ReadStringProperty("materialType");
|
||||||
|
|
||||||
|
if (materialType == "model phong" || materialType == "world phong" || materialType == "impact mark")
|
||||||
|
{
|
||||||
|
mtl_phong_template();
|
||||||
|
}
|
||||||
|
else if (materialType == "model ambient")
|
||||||
|
{
|
||||||
|
mtl_ambient_template();
|
||||||
|
}
|
||||||
|
else if (materialType == "2d")
|
||||||
|
{
|
||||||
|
mtl_2d_template();
|
||||||
|
}
|
||||||
|
else if (materialType == "model unlit" || materialType == "world unlit")
|
||||||
|
{
|
||||||
|
mtl_unlit_template();
|
||||||
|
}
|
||||||
|
else if (materialType == "unlit")
|
||||||
|
{
|
||||||
|
mtl_unlit_deprecated_template();
|
||||||
|
}
|
||||||
|
else if (materialType == "effect")
|
||||||
|
{
|
||||||
|
mtl_effect_template();
|
||||||
|
}
|
||||||
|
else if (materialType == "distortion")
|
||||||
|
{
|
||||||
|
mtl_distortion_template();
|
||||||
|
}
|
||||||
|
else if (materialType == "particle cloud")
|
||||||
|
{
|
||||||
|
mtl_particlecloud_template();
|
||||||
|
}
|
||||||
|
else if (materialType == "tools")
|
||||||
|
{
|
||||||
|
mtl_tools_template();
|
||||||
|
}
|
||||||
|
else if (materialType == "sky")
|
||||||
|
{
|
||||||
|
mtl_sky_template();
|
||||||
|
}
|
||||||
|
else if (materialType == "water")
|
||||||
|
{
|
||||||
|
mtl_water_template();
|
||||||
|
}
|
||||||
|
else if (materialType == "objective")
|
||||||
|
{
|
||||||
|
mtl_objective_template();
|
||||||
|
}
|
||||||
|
else if (materialType == "custom")
|
||||||
|
{
|
||||||
|
custom_template();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::ostringstream ss;
|
||||||
|
ss << "Unknown material type: \"" << materialType << "\"";
|
||||||
|
throw GdtReadingException(ss.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mtl_phong_template()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void mtl_ambient_template()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void mtl_2d_template()
|
||||||
|
{
|
||||||
|
commonsetup_template();
|
||||||
|
|
||||||
|
SetTechniqueSet("2d");
|
||||||
|
|
||||||
|
const auto colorMapName = ReadStringProperty("colorMap");
|
||||||
|
|
||||||
|
if (!colorMapName.empty())
|
||||||
|
AddMapTexture("colorMap", TS_2D, colorMapName);
|
||||||
|
else
|
||||||
|
throw GdtReadingException("ColorMap may not be blank in 2d materials");
|
||||||
|
}
|
||||||
|
|
||||||
|
void mtl_unlit_template()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void mtl_unlit_deprecated_template()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void mtl_effect_template()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void mtl_distortion_template()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void mtl_particlecloud_template()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void mtl_tools_template()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void mtl_sky_template()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void mtl_water_template()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void mtl_objective_template()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void custom_template()
|
||||||
|
{
|
||||||
|
const auto customTemplate = ReadStringProperty("customTemplate");
|
||||||
|
|
||||||
|
if (customTemplate == "mtl_custom")
|
||||||
|
{
|
||||||
|
mtl_custom_template();
|
||||||
|
}
|
||||||
|
else if (customTemplate == "mtl_phong_flag")
|
||||||
|
{
|
||||||
|
mtl_phong_flag_template();
|
||||||
|
}
|
||||||
|
else if (customTemplate == "mtl_grain_overlay")
|
||||||
|
{
|
||||||
|
mtl_grain_overlay_template();
|
||||||
|
}
|
||||||
|
else if (customTemplate == "mtl_effect_eyeoffset")
|
||||||
|
{
|
||||||
|
mtl_effect_eyeoffset_template();
|
||||||
|
}
|
||||||
|
else if (customTemplate == "mtl_reflexsight")
|
||||||
|
{
|
||||||
|
mtl_reflexsight_template();
|
||||||
|
}
|
||||||
|
else if (customTemplate == "mtl_shadowclear")
|
||||||
|
{
|
||||||
|
mtl_shadowclear_template();
|
||||||
|
}
|
||||||
|
else if (customTemplate == "mtl_shadowoverlay")
|
||||||
|
{
|
||||||
|
mtl_shadowoverlay_template();
|
||||||
|
}
|
||||||
|
else if (customTemplate == "mtl_splatter")
|
||||||
|
{
|
||||||
|
mtl_splatter_template();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::ostringstream ss;
|
||||||
|
ss << "Unknown custom template: \"" << customTemplate << "\"";
|
||||||
|
throw GdtReadingException(ss.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mtl_custom_template()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void mtl_phong_flag_template()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void mtl_grain_overlay_template()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void mtl_effect_eyeoffset_template()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void mtl_reflexsight_template()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void mtl_shadowclear_template()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void mtl_shadowoverlay_template()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void mtl_splatter_template()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void commonsetup_template()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetTechniqueSet(const std::string& techsetName)
|
||||||
|
{
|
||||||
|
auto* techset = reinterpret_cast<XAssetInfo<MaterialTechniqueSet>*>(m_manager->LoadDependency(ASSET_TYPE_TECHNIQUE_SET, techsetName));
|
||||||
|
|
||||||
|
if (techset == nullptr)
|
||||||
|
{
|
||||||
|
std::ostringstream ss;
|
||||||
|
ss << "Could not load techset: \"" << techsetName << "\"";
|
||||||
|
throw GdtReadingException(ss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
m_dependencies.push_back(techset);
|
||||||
|
m_material->techniqueSet = techset->Asset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddMapTexture(const std::string& typeName, const TextureSemantic semantic, const std::string& textureName)
|
||||||
|
{
|
||||||
|
MaterialTextureDef textureDef{};
|
||||||
|
textureDef.nameHash = Common::R_HashString(typeName.c_str());
|
||||||
|
textureDef.nameStart = typeName[0];
|
||||||
|
textureDef.nameEnd = typeName[typeName.size() - 1];
|
||||||
|
textureDef.samplerState = 0; // TODO
|
||||||
|
textureDef.semantic = static_cast<unsigned char>(semantic);
|
||||||
|
|
||||||
|
auto* image = reinterpret_cast<XAssetInfo<GfxImage>*>(m_manager->LoadDependency(ASSET_TYPE_IMAGE, textureName));
|
||||||
|
|
||||||
|
if (image == nullptr)
|
||||||
|
{
|
||||||
|
std::ostringstream ss;
|
||||||
|
ss << "Could not load image: \"" << textureName << "\"";
|
||||||
|
throw GdtReadingException(ss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
m_dependencies.push_back(image);
|
||||||
|
textureDef.u.image = image->Asset();
|
||||||
|
|
||||||
|
m_texture.push_back(textureDef);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FinalizeMaterial()
|
||||||
|
{
|
||||||
|
// TODO Realloc all arrays and assign to material
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryManager* m_memory;
|
||||||
|
IAssetLoadingManager* m_manager;
|
||||||
|
std::vector<XAssetInfoGeneric*> m_dependencies;
|
||||||
|
|
||||||
|
Material* m_material;
|
||||||
|
std::vector<MaterialTextureDef> m_texture;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
void* AssetLoaderMaterial::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
void* AssetLoaderMaterial::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
||||||
{
|
{
|
||||||
auto* material = memory->Create<Material>();
|
auto* material = memory->Create<Material>();
|
||||||
@ -15,3 +311,30 @@ void* AssetLoaderMaterial::CreateEmptyAsset(const std::string& assetName, Memory
|
|||||||
material->info.name = memory->Dup(assetName.c_str());
|
material->info.name = memory->Dup(assetName.c_str());
|
||||||
return material;
|
return material;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AssetLoaderMaterial::CanLoadFromGdt() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AssetLoaderMaterial::LoadFromGdt(const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
|
||||||
|
{
|
||||||
|
const auto* entry = gdtQueryable->GetGdtEntryByGdfAndName(ObjConstants::GDF_FILENAME_MATERIAL, assetName);
|
||||||
|
if (!entry)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
MaterialGdtLoader loader(*entry, memory, manager);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (loader.Load())
|
||||||
|
manager->AddAsset(ASSET_TYPE_MATERIAL, assetName, loader.GetMaterial(), loader.GetDependencies(), std::vector<scr_string_t>());
|
||||||
|
}
|
||||||
|
catch (const GdtReadingException& e)
|
||||||
|
{
|
||||||
|
std::cerr << "Error while trying to load material from gdt: " << e.what() << " @ GdtEntry \"" << entry->m_name << "\"\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@ -10,5 +10,7 @@ namespace IW4
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
||||||
|
_NODISCARD bool CanLoadFromGdt() const override;
|
||||||
|
bool LoadFromGdt(const std::string& assetName, IGdtQueryable* gdtQueryable, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "Utils/ClassUtils.h"
|
#include "Utils/ClassUtils.h"
|
||||||
#include "Game/IW4/MaterialConstantsIW4.h"
|
#include "Game/IW4/MaterialConstantsIW4.h"
|
||||||
|
#include "Game/IW4/ObjConstantsIW4.h"
|
||||||
#include "Game/IW4/TechsetConstantsIW4.h"
|
#include "Game/IW4/TechsetConstantsIW4.h"
|
||||||
#include "Math/Vector.h"
|
#include "Math/Vector.h"
|
||||||
|
|
||||||
@ -1431,7 +1432,7 @@ namespace IW4
|
|||||||
GdtEntry& CreateGdtEntry()
|
GdtEntry& CreateGdtEntry()
|
||||||
{
|
{
|
||||||
m_entry = GdtEntry();
|
m_entry = GdtEntry();
|
||||||
m_entry.m_gdf_name = "material.gdf";
|
m_entry.m_gdf_name = ObjConstants::GDF_FILENAME_MATERIAL;
|
||||||
m_entry.m_name = m_material->info.name;
|
m_entry.m_name = m_material->info.name;
|
||||||
|
|
||||||
SetCommonValues();
|
SetCommonValues();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user