Material loading base

This commit is contained in:
Jan 2022-07-15 11:21:54 +02:00
parent bc91738ee9
commit 82349d3432
7 changed files with 442 additions and 4 deletions

View File

@ -960,9 +960,9 @@ namespace IW4
struct GfxImage
{
GfxTexture texture;
char mapType;
char semantic;
char category;
unsigned char mapType;
unsigned char semantic;
unsigned char category;
bool useSrgbReads;
Picmip picmip;
bool noPicmip;

View File

@ -12,6 +12,7 @@ namespace IW4
static constexpr const char* INFO_STRING_PREFIX_VEHICLE = "VEHICLEFILE";
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_TRACER = "tracer.gdf";
static constexpr const char* GDF_FILENAME_VEHICLE = "vehicle.gdf";

View 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;
}

View 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;
};

View File

@ -1,13 +1,309 @@
#include "AssetLoaderMaterial.h"
#include <cstring>
#include <iostream>
#include <sstream>
#include "ObjLoading.h"
#include "AssetLoading/AbstractGdtEntryReader.h"
#include "Game/IW4/CommonIW4.h"
#include "Game/IW4/IW4.h"
#include "Game/IW4/ObjConstantsIW4.h"
#include "Pool/GlobalAssetPool.h"
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)
{
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());
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;
}

View File

@ -10,5 +10,7 @@ namespace IW4
{
public:
_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;
};
}

View File

@ -9,6 +9,7 @@
#include "Utils/ClassUtils.h"
#include "Game/IW4/MaterialConstantsIW4.h"
#include "Game/IW4/ObjConstantsIW4.h"
#include "Game/IW4/TechsetConstantsIW4.h"
#include "Math/Vector.h"
@ -1431,7 +1432,7 @@ namespace IW4
GdtEntry& CreateGdtEntry()
{
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;
SetCommonValues();