forked from 0ad/0ad
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:
parent
9c2fb5a466
commit
4fff66cfce
128
source/graphics/Material.cpp
Executable file
128
source/graphics/Material.cpp
Executable 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
77
source/graphics/Material.h
Executable 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
|
256
source/graphics/MaterialReader.cpp
Executable file
256
source/graphics/MaterialReader.cpp
Executable 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;
|
||||
}
|
20
source/graphics/MaterialReader.h
Executable file
20
source/graphics/MaterialReader.h
Executable 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
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user