Initial import of material code. MaterialReader is implemented and functional. Currently models do not attempt to load materials, nor does the renderer use them.

This was SVN commit r1192.
This commit is contained in:
Calefaction 2004-09-23 04:00:56 +00:00
parent 9c2fb5a466
commit 4fff66cfce
5 changed files with 485 additions and 0 deletions

128
source/graphics/Material.cpp Executable file
View File

@ -0,0 +1,128 @@
#include "ogl.h"
#include "res/res.h"
#include "Material.h"
#define SAFE_DELETE(x) \
if((x)) { delete (x); (x) = NULL; }
// Values as taken straight from the Blue Book (god bless the Blue Book)
static SMaterialColor IdentityDiffuse = { 0.8f, 0.8f, 0.8f, 1.0f };
static SMaterialColor IdentityAmbient = { 0.2f, 0.2f, 0.2f, 1.0f };
static SMaterialColor IdentitySpecular = { 0.0f, 0.0f, 0.0f, 1.0f };
static SMaterialColor IdentityEmissive = { 0.0f, 0.0f, 0.0f, 1.0f };
static SMaterialColor *CopyColor(SMaterialColor *color)
{
if(!color)
return NULL;
if(color == &IdentityDiffuse
|| color == &IdentityAmbient
|| color == &IdentitySpecular
|| color == &IdentityEmissive)
return NULL;
SMaterialColor *ret = new SMaterialColor();
memcpy(ret, color, sizeof(SMaterialColor));
return ret;
}
CMaterial::CMaterial()
: m_Diffuse(NULL),
m_Ambient(NULL),
m_Specular(NULL),
m_Emissive(NULL),
m_SpecularPower(0.0f),
m_SourceBlend(GL_NONE),
m_DestBlend(GL_NONE),
m_AlphaFunc(GL_NONE),
m_AlphaClamp(0.0f),
m_Alpha(false)
{
}
CMaterial::CMaterial(const CMaterial &material)
{
(*this) = const_cast<CMaterial &>(material);
}
CMaterial::~CMaterial()
{
SAFE_DELETE(m_Diffuse);
SAFE_DELETE(m_Ambient);
SAFE_DELETE(m_Specular);
SAFE_DELETE(m_Emissive);
}
void CMaterial::operator =(CMaterial &material)
{
m_Diffuse = CopyColor(material.m_Diffuse);
m_Ambient = CopyColor(material.m_Ambient);
m_Specular = CopyColor(material.m_Specular);
m_Emissive = CopyColor(material.m_Emissive);
m_SpecularPower = material.m_SpecularPower;
m_SourceBlend = material.m_SourceBlend;
m_DestBlend = material.m_DestBlend;
m_AlphaFunc = material.m_AlphaFunc;
m_AlphaClamp = material.m_AlphaClamp;
m_Alpha = material.m_Alpha;
}
SMaterialColor CMaterial::GetDiffuse()
{
if(!m_Diffuse)
return IdentityDiffuse;
return *m_Diffuse;
}
SMaterialColor CMaterial::GetAmbient()
{
if(!m_Ambient)
return IdentityAmbient;
return *m_Ambient;
}
SMaterialColor CMaterial::GetSpecular()
{
if(!m_Specular)
return IdentitySpecular;
return *m_Ambient;
}
SMaterialColor CMaterial::GetEmissive()
{
if(!m_Emissive)
return IdentityEmissive;
return *m_Emissive;
}
#define SETMC(var) \
if((var)) (*var) = color; \
else (var) = CopyColor(&color) ;
void CMaterial::SetDiffuse(SMaterialColor &color)
{
SETMC(m_Diffuse);
}
void CMaterial::SetAmbient(SMaterialColor &color)
{
SETMC(m_Ambient);
}
void CMaterial::SetSpecular(SMaterialColor &color)
{
SETMC(m_Specular);
}
void CMaterial::SetEmissive(SMaterialColor &color)
{
SETMC(m_Emissive);
}
#undef SETMC

77
source/graphics/Material.h Executable file
View File

@ -0,0 +1,77 @@
#ifndef __H_MATERIAL_H__
#define __H_MATERIAL_H__
#include "CStr.h"
struct SMaterialColor
{
public:
union
{
struct
{
float r;
float g;
float b;
float a;
};
float data[4];
};
};
class CMaterial
{
public:
CMaterial();
CMaterial(const CMaterial &material);
virtual ~CMaterial();
bool Apply();
CStr GetTexture() { return m_Texture; }
SMaterialColor GetDiffuse();
SMaterialColor GetAmbient();
SMaterialColor GetSpecular();
SMaterialColor GetEmissive();
float GetSpecularPower() { return m_SpecularPower; }
GLenum GetSourceBlend() { return m_SourceBlend; }
GLenum GetDestBlend() { return m_DestBlend; }
GLenum GetAlphaFunc() { return m_AlphaFunc; }
float GetAlphaClamp() { return m_AlphaClamp; }
bool UsesAlpha() { return m_Alpha; }
void SetTexture(CStr &texture) { m_Texture = texture; }
void SetDiffuse(SMaterialColor &color);
void SetAmbient(SMaterialColor &color);
void SetSpecular(SMaterialColor &color);
void SetEmissive(SMaterialColor &color);
void SetSpecularPower(float power) { m_SpecularPower = power; }
void SetSourceBlend(GLenum func) { m_SourceBlend = func; }
void SetDestBlend(GLenum func) { m_DestBlend = func; }
void SetAlphaFunc(GLenum func) { m_AlphaFunc = func; }
void SetAlphaClamp(float clamp) { m_AlphaClamp = clamp; }
void SetUsesAlpha(bool flag) { m_Alpha = flag; }
void operator =(CMaterial &material);
protected:
// Various reflective color properties
SMaterialColor *m_Diffuse;
SMaterialColor *m_Ambient;
SMaterialColor *m_Specular;
SMaterialColor *m_Emissive;
float m_SpecularPower;
// Path to the materials texture
CStr m_Texture;
// OpenGL blend and alpha func states for the materials render pass
GLenum m_SourceBlend;
GLenum m_DestBlend;
GLenum m_AlphaFunc;
float m_AlphaClamp;
// Alpha required flag
bool m_Alpha;
};
#endif

View File

@ -0,0 +1,256 @@
#include "precompiled.h"
#include "ogl.h"
#include "Xeromyces.h"
#include "MaterialReader.h"
#define SAFE_DELETE(x) \
if((x)) { delete (x); (x) = NULL; }
static SMaterialColor ParseColor(CStr colorStr)
{
SMaterialColor color;
colorStr = colorStr.Trim(PS_TRIM_BOTH);
CStr tmp;
int idx = 0;
long pos = colorStr.Find(' ');
while(colorStr.Length())
{
if(pos == -1)
pos = colorStr.Length();
tmp = colorStr.GetSubstring(0, pos);
colorStr = colorStr.GetSubstring(pos, colorStr.Length() - pos);
colorStr = colorStr.Trim(PS_TRIM_LEFT);
pos = colorStr.Find(' ');
float value = 0.0f;
if(tmp.Find('.') != -1)
value = tmp.ToFloat();
else
{
int intValue = tmp.ToInt();
if(intValue > 0)
{
if(intValue > 255)
intValue = 255;
value = ((float)intValue) / 255.0f;
}
}
switch(idx)
{
case 0:
color.r = value;
break;
case 1:
color.g = value;
break;
case 2:
color.b = value;
break;
case 3:
color.a = value;
break;
default:
break;
}
if(idx >= 3)
break;
idx++;
}
return color;
}
static bool ParseUsage(CStr temp)
{
temp = temp.LCase().Trim(PS_TRIM_BOTH);
if(temp == CStr("blend") ||
temp == CStr("true") ||
temp == CStr("yes") ||
temp.ToInt() > 0)
return true;
return false;
}
static GLenum ParseAlphaFunc(CStr temp)
{
temp = temp.LCase().Trim(PS_TRIM_BOTH);
if(!temp.Length())
return GL_NONE;
if(temp == CStr("never"))
return GL_NEVER;
else if(temp == CStr("less"))
return GL_LESS;
else if(temp == CStr("lequal"))
return GL_LEQUAL;
else if(temp == CStr("greater"))
return GL_GREATER;
else if(temp == CStr("gequal"))
return GL_GEQUAL;
else if(temp == CStr("equal"))
return GL_EQUAL;
else if(temp == CStr("notequal"))
return GL_NOTEQUAL;
else if(temp == CStr("always"))
return GL_ALWAYS;
else
return GL_NONE;
}
static GLenum ParseBlendFunc(CStr temp)
{
temp = temp.LCase().Trim(PS_TRIM_BOTH);
if(!temp.Length())
return GL_NONE;
if(temp == CStr("zero"))
return GL_ZERO;
else if(temp == CStr("one"))
return GL_ONE;
else if(temp == CStr("sourcecolor"))
return GL_SRC_COLOR;
else if(temp == CStr("oneminussourcecolor"))
return GL_ONE_MINUS_SRC_COLOR;
else if(temp == CStr("destcolor"))
return GL_DST_COLOR;
else if(temp == CStr("oneminusdestcolor"))
return GL_ONE_MINUS_DST_COLOR;
else if(temp == CStr("sourcealpha"))
return GL_SRC_ALPHA;
else if(temp == CStr("oneminussourcealpha"))
return GL_ONE_MINUS_SRC_ALPHA;
else if(temp == CStr("destalpha"))
return GL_DST_ALPHA;
else if(temp == CStr("oneminusdestalpha"))
return GL_ONE_MINUS_DST_ALPHA;
else if(temp == CStr("sourcealphasaturate"))
return GL_SRC_ALPHA_SATURATE;
return GL_NONE;
}
static float ClampFloat(float value, float min, float max)
{
if(value < min)
return min;
else if(value > max)
return max;
return value;
}
CMaterialReader::CMaterialReader()
{
}
CMaterialReader::~CMaterialReader()
{
}
CMaterial *CMaterialReader::LoadMaterial(const char *file)
{
CXeromyces xeroFile;
if (xeroFile.Load(file) != PSRETURN_OK)
return NULL;
#define EL(x) int el_##x = xeroFile.getElementID(#x)
#define AT(x) int at_##x = xeroFile.getAttributeID(#x)
EL(texture);
EL(colors);
AT(diffuse);
AT(ambient);
AT(specular);
AT(emissive);
AT(specularpower);
EL(alpha);
AT(usage);
AT(function);
AT(clamp);
EL(blend);
AT(sourcefunction);
AT(destfunction);
#undef AT
#undef EL
CMaterial *material = NULL;
try
{
XMBElement root = xeroFile.getRoot();
XMBElementList childNodes = root.getChildNodes();
material = new CMaterial();
for(i32 i = 0; i < childNodes.Count; i++)
{
XMBElement node = childNodes.item(i);
int token = node.getNodeName();
XMBAttributeList attrs = node.getAttributes();
CStr temp;
if(token == el_texture)
{
CStr value(node.getText());
material->SetTexture(value);
}
else if(token == el_colors)
{
temp = (CStr)attrs.getNamedItem(at_diffuse);
if(temp.Length() > 0)
material->SetDiffuse(ParseColor(temp));
temp = (CStr)attrs.getNamedItem(at_ambient);
if(temp.Length() > 0)
material->SetAmbient(ParseColor(temp));
temp = (CStr)attrs.getNamedItem(at_specular);
if(temp.Length() > 0)
material->SetSpecular(ParseColor(temp));
temp = (CStr)attrs.getNamedItem(at_specularpower);
if(temp.Length() > 0)
material->SetSpecularPower(ClampFloat(temp.ToFloat(), 0.0f, 1.0f));
}
else if(token == el_alpha)
{
temp = (CStr)attrs.getNamedItem(at_usage);
material->SetUsesAlpha(ParseUsage(temp));
temp = (CStr)attrs.getNamedItem(at_function);
material->SetAlphaFunc(ParseAlphaFunc(temp));
temp = (CStr)attrs.getNamedItem(at_clamp);
if(temp.Length() > 0)
material->SetAlphaClamp(ClampFloat(temp.ToFloat(), 0.0f, 1.0f));
}
else if(token == el_blend)
{
temp = (CStr)attrs.getNamedItem(at_sourcefunction);
material->SetSourceBlend(ParseBlendFunc(temp));
temp = (CStr)attrs.getNamedItem(at_destfunction);
material->SetDestBlend(ParseBlendFunc(temp));
}
}
}
catch(...)
{
SAFE_DELETE(material);
throw;
}
return material;
}

View File

@ -0,0 +1,20 @@
#ifndef __H_MATERIALREADER_H__
#define __H_MATERIALREADER_H__
#include "Singleton.h"
#include "Material.h"
#define g_MaterialReader CMaterialReader::GetSingleton()
class CMaterialReader : public Singleton<CMaterialReader>
{
public:
CMaterialReader();
~CMaterialReader();
CMaterial *LoadMaterial(const char *file);
private:
};
#endif

View File

@ -36,6 +36,7 @@
#include "LightEnv.h"
#include "Model.h"
#include "UnitManager.h"
#include "MaterialReader.h"
#include "Interact.h"
#include "Hotkey.h"
@ -906,6 +907,9 @@ PREVTSC=CURTSC;
// create terrain related stuff
new CTextureManager;
// create the material reader
new CMaterialReader;
// create actor related stuff
new CSkeletonAnimManager;
new CObjectManager;