diff --git a/source/graphics/Material.cpp b/source/graphics/Material.cpp index eaf030dbb1..f7287aac2d 100755 --- a/source/graphics/Material.cpp +++ b/source/graphics/Material.cpp @@ -14,118 +14,135 @@ 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_Diffuse(IdentityDiffuse), + m_Ambient(IdentityAmbient), + m_Specular(IdentitySpecular), + m_Emissive(IdentityEmissive), m_SpecularPower(0.0f), - m_SourceBlend(GL_NONE), - m_DestBlend(GL_NONE), - m_AlphaFunc(GL_NONE), - m_AlphaClamp(1.0f), m_Alpha(false) { + ComputeHash(); } CMaterial::CMaterial(const CMaterial &material) { - (*this) = const_cast(material); + (*this) = material; } CMaterial::~CMaterial() { - SAFE_DELETE(m_Diffuse); - SAFE_DELETE(m_Ambient); - SAFE_DELETE(m_Specular); - SAFE_DELETE(m_Emissive); } -void CMaterial::operator =(CMaterial &material) +void CMaterial::operator =(const 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_Diffuse = material.m_Diffuse; + m_Ambient = material.m_Ambient; + m_Specular = material.m_Specular; + m_Emissive = 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; + ComputeHash(); +} + +bool CMaterial::operator ==(const CMaterial &material) +{ + return( + m_Texture == m_Texture && + m_Diffuse == material.m_Diffuse && + m_Ambient == material.m_Ambient && + m_Specular == material.m_Specular && + m_Emissive == material.m_Emissive && + m_SpecularPower == material.m_SpecularPower && + m_Alpha == material.m_Alpha + ); +} + +void CMaterial::Bind() +{ + glMaterialfv(GL_FRONT, GL_DIFFUSE, m_Diffuse.data); + glMaterialfv(GL_FRONT, GL_AMBIENT, m_Ambient.data); + glMaterialfv(GL_FRONT, GL_SPECULAR, m_Specular.data); + glMaterialfv(GL_FRONT, GL_EMISSION, m_Emissive.data); + glMaterialf(GL_FRONT, GL_SHININESS, m_SpecularPower); + + oglCheck(); +} + +void CMaterial::Unbind() +{ } SMaterialColor CMaterial::GetDiffuse() { - if(!m_Diffuse) - return IdentityDiffuse; - - return *m_Diffuse; + return m_Diffuse; } SMaterialColor CMaterial::GetAmbient() { - if(!m_Ambient) - return IdentityAmbient; - - return *m_Ambient; + return m_Ambient; } SMaterialColor CMaterial::GetSpecular() { - if(!m_Specular) - return IdentitySpecular; - - return *m_Specular; + return m_Specular; } SMaterialColor CMaterial::GetEmissive() { - if(!m_Emissive) - return IdentityEmissive; - - return *m_Emissive; + return m_Emissive; } -#define SETMC(var) \ - if((var)) (*var) = color; \ - else (var) = CopyColor(&color) ; +void CMaterial::SetTexture(const CStr &texture) +{ + m_Texture = texture; + ComputeHash(); +} void CMaterial::SetDiffuse(SMaterialColor &color) { - SETMC(m_Diffuse); + m_Diffuse = color; + ComputeHash(); } void CMaterial::SetAmbient(SMaterialColor &color) { - SETMC(m_Ambient); + m_Ambient = color; + ComputeHash(); } void CMaterial::SetSpecular(SMaterialColor &color) { - SETMC(m_Specular); + m_Specular = color; + ComputeHash(); } void CMaterial::SetEmissive(SMaterialColor &color) { - SETMC(m_Emissive); + m_Emissive = color; + ComputeHash(); } -#undef SETMC \ No newline at end of file +void CMaterial::SetSpecularPower(float power) +{ + m_SpecularPower = power; + ComputeHash(); +} + +void CMaterial::SetUsesAlpha(bool flag) +{ + m_Alpha = flag; + ComputeHash(); +} + +void CMaterial::ComputeHash() +{ + m_Hash = + m_Diffuse.Sum() + + m_Ambient.Sum() + + m_Specular.Sum() + + m_Emissive.Sum() + + m_SpecularPower + + (float)m_Texture.GetHashCode(); +} diff --git a/source/graphics/Material.h b/source/graphics/Material.h index d4a4aaa8e2..c36b73a66c 100755 --- a/source/graphics/Material.h +++ b/source/graphics/Material.h @@ -14,10 +14,17 @@ public: b = _b; a = _a; } + SMaterialColor(const SMaterialColor &color) + { + r = color.r; + g = color.g; + b = color.b; + a = color.a; + } union { - struct + struct { float r; float g; @@ -26,6 +33,28 @@ public: }; float data[4]; }; + + void operator =(const SMaterialColor color) + { + r = color.r; + g = color.g; + b = color.b; + a = color.a; + } + bool operator ==(const SMaterialColor color) + { + return ( + r == color.r && + g == color.g && + b == color.b && + a == color.a + ); + } + + float Sum() + { + return (r + g + b + a); + } }; class CMaterial @@ -35,7 +64,9 @@ public: CMaterial(const CMaterial &material); virtual ~CMaterial(); - bool Apply(); + void Bind(); + void Unbind(); + float GetHash() { return m_Hash; } CStr GetTexture() { return m_Texture; } SMaterialColor GetDiffuse(); @@ -43,41 +74,32 @@ public: 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 SetTexture(const CStr &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 SetSpecularPower(float power); + void SetUsesAlpha(bool flag); - void operator =(CMaterial &material); + void operator =(const CMaterial &material); + bool operator ==(const CMaterial &material); protected: + void ComputeHash(); + + float m_Hash; + // Various reflective color properties - SMaterialColor *m_Diffuse; - SMaterialColor *m_Ambient; - SMaterialColor *m_Specular; - SMaterialColor *m_Emissive; + 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; diff --git a/source/graphics/MaterialManager.cpp b/source/graphics/MaterialManager.cpp index 2394af9be3..8b1102fb0c 100755 --- a/source/graphics/MaterialManager.cpp +++ b/source/graphics/MaterialManager.cpp @@ -169,6 +169,9 @@ CMaterialManager::~CMaterialManager() CMaterial &CMaterialManager::LoadMaterial(const char *file) { + if(!strlen(file)) + return NullMaterial; + std::map::iterator iter; if((iter = m_Materials.find(std::string(file))) != m_Materials.end()) { @@ -193,12 +196,6 @@ CMaterial &CMaterialManager::LoadMaterial(const char *file) EL(alpha); AT(usage); - AT(function); - AT(clamp); - - EL(blend); - AT(sourcefunction); - AT(destfunction); #undef AT #undef EL @@ -244,21 +241,6 @@ CMaterial &CMaterialManager::LoadMaterial(const char *file) { 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)); } } diff --git a/source/graphics/Model.cpp b/source/graphics/Model.cpp index 15170acfaa..b98288c059 100755 --- a/source/graphics/Model.cpp +++ b/source/graphics/Model.cpp @@ -314,6 +314,7 @@ CModel* CModel::Clone() const clone->m_ObjectBounds=m_ObjectBounds; clone->InitModel(m_pModelDef); clone->SetTexture(m_Texture); + clone->SetMaterial(m_Material); clone->SetAnimation(m_Anim); for (uint i=0;iSetTexture((const char*) m_TextureName); + m_Model->SetMaterial(g_MaterialManager.LoadMaterial((const char *)m_Material)); m_Model->InitModel(modeldef); // calculate initial object space bounds, based on vertex positions