Skip to content

Instantly share code, notes, and snippets.

@pollend
Created October 13, 2023 04:13
Show Gist options
  • Save pollend/fbb4b9299da95e6966505ded72d12366 to your computer and use it in GitHub Desktop.
Save pollend/fbb4b9299da95e6966505ded72d12366 to your computer and use it in GitHub Desktop.
cMaterial* cMaterialManager::LoadFromFile(const tString& asName, const tWString& asPath) {
tinyxml2::XMLDocument document;
FILE *pFile = cPlatform::OpenFile(asPath, _W("rb"));
if(!pFile) {
LOGF(LogLevel::eERROR, "failed to load material: %s", asName.c_str());
return nullptr;
}
document.LoadFile(pFile);
fclose(pFile);
auto* rootElement = document.FirstChildElement();
if (rootElement == nullptr) {
LOGF(LogLevel::eERROR,"Material-%s: Root not found", asName.c_str());
return nullptr;
}
auto* mainElement = rootElement->FirstChildElement("Main");
if (mainElement == nullptr) {
LOGF(LogLevel::eERROR,"Material-%s: Main child not found", asName.c_str());
return nullptr;
}
const char* sType = "";
if(mainElement->QueryAttribute("Type", &sType) != tinyxml2::XMLError::XML_SUCCESS) {
LOGF(LogLevel::eERROR,"Material-%s:Missing Type Attribute: ", asName.c_str());
return nullptr;
}
bool bDepthTest = true;
float fValue = 1;
const char* sPhysicsMatName = "Default"; //pMain->GetAttributeString("PhysicsMaterial", "Default");
const char* sBlendMode = "Add"; //pMain->GetAttributeString("BlendMode", "Add");
mainElement->QueryBoolAttribute("DepthTest", &bDepthTest);
mainElement->QueryFloatAttribute("Value", &fValue);
mainElement->QueryStringAttribute("PhysicsMaterial", &sPhysicsMatName);
mainElement->QueryStringAttribute("BlendMode", &sBlendMode);
/////////////////////////////
// Make a "fake" material, with a blank type
if (mbDisableRenderDataLoading) {
cMaterial* pMat = hplNew(cMaterial, (asName, asPath, mpResources));
pMat->SetPhysicsMaterial(sPhysicsMatName);
return pMat;
}
/////////////////////////////
// CreateType
tString normalizedMaterialName = cString::ToLowerCase(sType);
auto metaInfo = std::find_if(cMaterial::MaterialMetaTable.begin(), cMaterial::MaterialMetaTable.end(), [&](auto& info) {
return info.m_name == normalizedMaterialName;
});
if (metaInfo == cMaterial::MaterialMetaTable.end()) {
LOGF(eERROR, "Invalid material type %s", sType);
return NULL;
}
cMaterial* pMat = new cMaterial(asName, asPath, mpResources);
pMat->SetDepthTest(bDepthTest);
pMat->SetPhysicsMaterial(sPhysicsMatName);
///////////////////////////
// Textures
auto* textureUnits = rootElement->FirstChildElement("TextureUnits");
if (textureUnits == nullptr) {
LOGF(LogLevel::eERROR,"Material-%s: TextureUnits child not found", asName.c_str());
return NULL;
}
for (eMaterialTexture textureType : metaInfo->m_usedTextures) {
tString sTextureType = GetTextureString(textureType);
auto* pTexChild = textureUnits->FirstChildElement(sTextureType.c_str());
if (pTexChild == NULL) {
continue;
}
bool bMipMaps = true;
bool bCompress = false;
const char* textureTypeStr = "";
const char* wrapStr = "";
const char* sFileQuery = "";
const char* animModeStr = "None";
float fFrameTime = 1.0f;
pTexChild->QueryStringAttribute("AnimMode", &animModeStr);
pTexChild->QueryStringAttribute("Wrap", &wrapStr);
pTexChild->QueryStringAttribute("Type", &textureTypeStr);
pTexChild->QueryStringAttribute("File", &sFileQuery );
pTexChild->QueryBoolAttribute("MipMaps", &bMipMaps);
pTexChild->QueryBoolAttribute("Compress", &bCompress);
pTexChild->QueryFloatAttribute("AnimFrameTime", &fFrameTime);
eTextureWrap wrap = GetWrap(wrapStr);
eTextureType type = GetType(textureTypeStr);
eTextureAnimMode animMode = GetAnimMode(animModeStr);
if (strcmp(sFileQuery ,"")) {
continue;
}
tString sFile = sFileQuery;
if (cString::GetFilePath(sFile).length() <= 1) {
sFile = cString::SetFilePath(sFile, cString::To8Char(cString::GetFilePathW(asPath)));
}
cTextureManager::ImageOptions options;
iResourceBase* pImageResource = nullptr;
if (animMode != eTextureAnimMode_None) {
auto animatedImage = mpResources->GetTextureManager()->CreateAnimImage(
sFile, bMipMaps, type, eTextureUsage_Normal, mlTextureSizeDownScaleLevel);
animatedImage->SetFrameTime(fFrameTime);
animatedImage->SetAnimMode(animMode);
pMat->SetImage(textureType, animatedImage);
pImageResource = animatedImage;
} else {
Image* pImage = nullptr;
switch (type) {
case eTextureType_1D:
pImage =
mpResources->GetTextureManager()->Create1DImage(sFile, bMipMaps, eTextureUsage_Normal, mlTextureSizeDownScaleLevel);
break;
case eTextureType_2D:
pImage = mpResources->GetTextureManager()->Create2DImage(
sFile, bMipMaps, eTextureType_2D, eTextureUsage_Normal, mlTextureSizeDownScaleLevel);
break;
case eTextureType_CubeMap:
pImage = mpResources->GetTextureManager()->CreateCubeMapImage(
sFile, bMipMaps, eTextureUsage_Normal, mlTextureSizeDownScaleLevel);
break;
case eTextureType_3D:
pImage =
mpResources->GetTextureManager()->Create3DImage(sFile, bMipMaps, eTextureUsage_Normal, mlTextureSizeDownScaleLevel);
break;
default:
{
ASSERT(false && "Invalid texture type");
break;
}
}
pImageResource = pImage;
pMat->setTextureWrap(wrap);
pMat->setTextureFilter(mTextureFilter);
pMat->SetTextureAnisotropy(mfTextureAnisotropy);
if (pImage) {
pMat->SetImage(textureType, pImage);
}
}
if (!pImageResource) {
hplDelete(pMat);
return nullptr;
}
}
///////////////////////////
// Animations
auto* pUvAnimRoot = rootElement->FirstChildElement("UvAnimations");
if (pUvAnimRoot) {
auto animElement = pUvAnimRoot->FirstChildElement();
for(;animElement != nullptr; animElement = animElement->NextSiblingElement()) {
const char* animTypeStr = "";
const char* animAxisStr = "";
float fSpeed = 0;
float fAmp = 0;
auto* animationNode = animElement->ToElement();
animationNode->QueryStringAttribute("Type", &animTypeStr);
animationNode->QueryStringAttribute("Axis", &animAxisStr);
eMaterialUvAnimation animType = GetUvAnimType(animTypeStr);
eMaterialAnimationAxis animAxis = GetAnimAxis(animAxisStr);
animationNode->QueryFloatAttribute("Speed", &fSpeed);
animationNode->QueryFloatAttribute("Amplitude", &fAmp);
pMat->AddUvAnimation(animType, fSpeed, fAmp, animAxis);
}
}
///////////////////////////
// Variables
cResourceVarsObject userVars;
auto* pUserVarsRoot = rootElement->FirstChildElement("SpecificVariables");
if (pUserVarsRoot)
userVars.LoadVariables(pUserVarsRoot);
for (auto& meta : cMaterial::MaterialMetaTable) {
if (normalizedMaterialName == meta.m_name) {
pMat->SetHandle(IndexPoolHandle(&internal::m_MaterialIndexPool));
MaterialDescriptor materialDescriptor;
materialDescriptor.m_id = meta.m_id;
switch (meta.m_id) {
case MaterialID::SolidDiffuse:
{
materialDescriptor.m_solid.m_heightMapScale = userVars.GetVarFloat("HeightMapScale", 0.1f);
materialDescriptor.m_solid.m_heightMapBias = userVars.GetVarFloat("HeightMapBias", 0);
materialDescriptor.m_solid.m_frenselBias = userVars.GetVarFloat("FrenselBias", 0.2f);
materialDescriptor.m_solid.m_frenselPow = userVars.GetVarFloat("FrenselPow", 8.0f);
materialDescriptor.m_solid.m_alphaDissolveFilter = userVars.GetVarBool("AlphaDissolveFilter", false);
break;
}
case MaterialID::Translucent:
{
materialDescriptor.m_translucent.m_hasRefraction = userVars.GetVarBool("Refraction", false);
materialDescriptor.m_translucent.m_refractionNormals = userVars.GetVarBool("RefractionNormals", true);
materialDescriptor.m_translucent.m_refractionEdgeCheck = userVars.GetVarBool("RefractionEdgeCheck", true);
materialDescriptor.m_translucent.m_isAffectedByLightLevel = userVars.GetVarBool("AffectedByLightLevel", false);
materialDescriptor.m_translucent.m_refractionScale = userVars.GetVarFloat("RefractionScale", 1.0f);
materialDescriptor.m_translucent.m_frenselBias = userVars.GetVarFloat("FrenselBias", 0.2f);
materialDescriptor.m_translucent.m_frenselPow = userVars.GetVarFloat("FrenselPow", 8.0);
materialDescriptor.m_translucent.m_rimLightMul = userVars.GetVarFloat("RimLightMul", 0.0f);
materialDescriptor.m_translucent.m_rimLightPow = userVars.GetVarFloat("RimLightPow", 8.0f);
materialDescriptor.m_translucent.m_blend = GetBlendMode(sBlendMode);
break;
}
case MaterialID::Water:
{
materialDescriptor.m_water.m_hasReflection = userVars.GetVarBool("HasReflection", true);
materialDescriptor.m_water.m_refractionScale = userVars.GetVarFloat("RefractionScale", 1.0f);
materialDescriptor.m_water.m_frenselBias = userVars.GetVarFloat("FrenselBias", 0.2f);
materialDescriptor.m_water.m_frenselPow = userVars.GetVarFloat("FrenselPow", 8.0f);
materialDescriptor.m_water.m_reflectionFadeStart = userVars.GetVarFloat("ReflectionFadeStart", 0);
materialDescriptor.m_water.m_reflectionFadeEnd = userVars.GetVarFloat("ReflectionFadeEnd", 0);
materialDescriptor.m_water.m_waveSpeed = userVars.GetVarFloat("WaveSpeed", 1.0f);
materialDescriptor.m_water.m_waveAmplitude = userVars.GetVarFloat("WaveAmplitude", 1.0f);
materialDescriptor.m_water.m_waveFreq = userVars.GetVarFloat("WaveFreq", 1.0f);
materialDescriptor.m_water.m_isLargeSurface = userVars.GetVarBool("LargeSurface", false);
materialDescriptor.m_water.m_worldReflectionOcclusionTest =
userVars.GetVarBool("OcclusionCullWorldReflection", true);
break;
}
case MaterialID::Decal:
{
materialDescriptor.m_translucent.m_blend = GetBlendMode(sBlendMode);
break;
}
default:
ASSERT(false && "Invalid material type");
break;
}
pMat->SetDescriptor(materialDescriptor);
break;
}
}
return pMat;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment