From d2948937a0cd9279b9a4c9a8e7a9c9e62b94db06 Mon Sep 17 00:00:00 2001 From: Ykkrosh Date: Thu, 7 Apr 2005 04:29:07 +0000 Subject: [PATCH] Fixed prop player-colouring. Allowed per-object colours. (Coming soon: data to demonstrate it.) This was SVN commit r2113. --- source/graphics/Material.cpp | 94 +++++++++++++------- source/graphics/Material.h | 127 ++++++++++++++++------------ source/graphics/MaterialManager.cpp | 107 +++++++++++------------ source/graphics/Model.cpp | 19 ++++- source/graphics/Model.h | 22 +++-- source/graphics/ObjectBase.cpp | 5 ++ source/graphics/ObjectBase.h | 1 + source/graphics/ObjectEntry.cpp | 18 +++- source/graphics/ObjectEntry.h | 3 + source/ps/Overlay.h | 4 +- source/renderer/PlayerRenderer.cpp | 9 +- 11 files changed, 249 insertions(+), 160 deletions(-) diff --git a/source/graphics/Material.cpp b/source/graphics/Material.cpp index d33eaac652..586d81dd34 100755 --- a/source/graphics/Material.cpp +++ b/source/graphics/Material.cpp @@ -3,6 +3,9 @@ #include "ogl.h" #include "res/res.h" #include "Material.h" +#include "Player.h" +#include "Game.h" +#include "Overlay.h" // for CColor #define SAFE_DELETE(x) \ if((x)) { delete (x); (x) = NULL; } @@ -16,6 +19,8 @@ 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 BrokenColor(1.0f, 0.0f, 1.0f, 1.0f); + bool SMaterialColor::operator ==(const SMaterialColor color) { return ( @@ -28,19 +33,20 @@ bool SMaterialColor::operator ==(const SMaterialColor color) CMaterial::CMaterial() : m_Diffuse(IdentityDiffuse), - m_Ambient(IdentityAmbient), - m_Specular(IdentitySpecular), - m_Emissive(IdentityEmissive), + m_Ambient(IdentityAmbient), + m_Specular(IdentitySpecular), + m_Emissive(IdentityEmissive), m_SpecularPower(0.0f), m_Alpha(false), - m_bPlayer(false) + m_PlayerID(PLAYER_NONE), + m_TextureColor(BrokenColor) { - ComputeHash(); + ComputeHash(); } CMaterial::CMaterial(const CMaterial &material) { - (*this) = material; + (*this) = material; } CMaterial::~CMaterial() @@ -50,28 +56,30 @@ CMaterial::~CMaterial() void CMaterial::operator =(const CMaterial &material) { m_Diffuse = material.m_Diffuse; - m_Ambient = material.m_Ambient; - m_Specular = material.m_Specular; - m_Emissive = material.m_Emissive; + 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; - m_bPlayer = material.m_bPlayer; - ComputeHash(); + m_SpecularPower = material.m_SpecularPower; + m_Alpha = material.m_Alpha; + m_PlayerID = material.m_PlayerID; + m_TextureColor = material.m_TextureColor; + 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 && - m_bPlayer == material.m_bPlayer - ); + 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 && + m_PlayerID == material.m_PlayerID && + m_TextureColor == material.m_TextureColor + ); } void CMaterial::Bind() @@ -109,6 +117,40 @@ SMaterialColor CMaterial::GetEmissive() return m_Emissive; } +SMaterialColor CMaterial::GetPlayerColor() +{ + assert(m_PlayerID != PLAYER_NONE); + // because this should never be called unless IsPlayer returned true + + if (m_PlayerID == PLAYER_OTHER /* TODO: or if player-colour is globally disabled */ ) + return m_TextureColor; + + if (m_PlayerID >= 0) + { + CPlayer* player = g_Game->GetPlayer(m_PlayerID); + if (player) + { + const SPlayerColour& c (player->GetColour()); + return SMaterialColor(c.r, c.g, c.b, c.a); + } + } + + // Oops, something failed. + return BrokenColor; +} + +void CMaterial::SetPlayerColor(int id) +{ + if (m_PlayerID == PLAYER_COMINGSOON || m_PlayerID >= 0) + m_PlayerID = id; +} + +void CMaterial::SetPlayerColor(CColor &colour) +{ + m_TextureColor = SMaterialColor(colour.r, colour.g, colour.b, colour.a); +} + + void CMaterial::SetTexture(const CStr &texture) { m_Texture = texture; @@ -163,12 +205,6 @@ void CMaterial::SetUsesAlpha(bool flag) ComputeHash(); } -void CMaterial::SetIsPlayer(bool flag) -{ - m_bPlayer = flag; - ComputeHash(); -} - void CMaterial::ComputeHash() { m_Hash = diff --git a/source/graphics/Material.h b/source/graphics/Material.h index ef3850a6e9..f618924c02 100755 --- a/source/graphics/Material.h +++ b/source/graphics/Material.h @@ -3,43 +3,45 @@ #include "CStr.h" +struct CColor; + struct SMaterialColor { public: - float r; - float g; - float b; - float a; + float r; + float g; + float b; + float a; - SMaterialColor() { r = 0.0f; g = 0.0f; b = 0.0f; a = 1.0f; } - SMaterialColor(float _r, float _g, float _b, float _a) - { - r = _r; - g = _g; - b = _b; - a = _a; - } - SMaterialColor(const SMaterialColor &color) - { - r = color.r; - g = color.g; - b = color.b; - a = color.a; - } + SMaterialColor() : r(0.0f), g(0.0f), b(0.0f), a(1.0f) {} + SMaterialColor(float _r, float _g, float _b, float _a) + { + r = _r; + g = _g; + b = _b; + a = _a; + } + SMaterialColor(const SMaterialColor &color) + { + r = color.r; + g = color.g; + b = color.b; + a = color.a; + } - void operator =(const SMaterialColor color) - { - r = color.r; - g = color.g; - b = color.b; - a = color.a; - } - bool operator ==(const SMaterialColor color); + void operator =(const SMaterialColor color) + { + r = color.r; + g = color.g; + b = color.b; + a = color.a; + } + bool operator ==(const SMaterialColor color); - float Sum() - { - return (r + g + b + a); - } + float Sum() + { + return (r + g + b + a); + } }; class CMaterial @@ -50,12 +52,12 @@ public: virtual ~CMaterial(); void Bind(); - void Unbind(); - float GetHash() { return m_Hash; } + void Unbind(); + float GetHash() { return m_Hash; } CStr GetTexture() { return m_Texture; } - CStr GetVertexProgram() { return m_VertexProgram; } - CStr GetFragmentProgram() { return m_FragmentProgram; } + CStr GetVertexProgram() { return m_VertexProgram; } + CStr GetFragmentProgram() { return m_FragmentProgram; } SMaterialColor GetDiffuse(); SMaterialColor GetAmbient(); SMaterialColor GetSpecular(); @@ -63,28 +65,35 @@ public: float GetSpecularPower() { return m_SpecularPower; } bool UsesAlpha() { return m_Alpha; } - // Determines whether or not the model goes into the PlayerRenderer - bool IsPlayer() { return m_bPlayer; } // John M. Mena - void SetTexture(const CStr &texture); - void SetVertexProgram(const CStr &prog); - void SetFragmentProgram(const CStr &prog); + // Determines whether or not the model goes into the PlayerRenderer + bool IsPlayer() { return (m_PlayerID != PLAYER_NONE); } + // Get the player colour (in a non-zero amount of time, so don't call it + // an unreasonable number of times. But it's fairly close to zero, so + // don't worry too much about it.) + SMaterialColor GetPlayerColor(); + + void SetPlayerColor_PerPlayer() { m_PlayerID = PLAYER_COMINGSOON; } + void SetPlayerColor_PerObject() { m_PlayerID = PLAYER_OTHER; } + void SetPlayerColor(int id); + void SetPlayerColor(CColor &colour); + + void SetTexture(const CStr &texture); + void SetVertexProgram(const CStr &prog); + void SetFragmentProgram(const CStr &prog); void SetDiffuse(const SMaterialColor &color); void SetAmbient(const SMaterialColor &color); void SetSpecular(const SMaterialColor &color); void SetEmissive(const SMaterialColor &color); - void SetSpecularPower(float power); - void SetUsesAlpha(bool flag); - // Sets the player flag which is used to - // place the model in the player renderer - void SetIsPlayer(bool flag); + void SetSpecularPower(float power); + void SetUsesAlpha(bool flag); - void operator =(const CMaterial &material); - bool operator ==(const CMaterial &material); + void operator =(const CMaterial &material); + bool operator ==(const CMaterial &material); protected: - void ComputeHash(); + void ComputeHash(); - float m_Hash; + float m_Hash; // Various reflective color properties SMaterialColor m_Diffuse; @@ -96,15 +105,25 @@ protected: // Path to the materials texture CStr m_Texture; - // Paths to vertex/fragment programs - CStr m_VertexProgram; - CStr m_FragmentProgram; + // Paths to vertex/fragment programs + CStr m_VertexProgram; + CStr m_FragmentProgram; // Alpha required flag bool m_Alpha; - // Player required flag for PlayerRenderer : John M. Mena - bool m_bPlayer; + // Player-colour settings. + // If m_PlayerID >= 0, the colour is retrieved from g_Game whenever it's needed. + // (It's not cached, because the player might change colour.) + // If m_PlayerID == PLAYER_OTHER, or if player-colouring has been globally + // disabled, m_TextureColor is used instead. This allows per-model colours to + // be specified, instead of only a single colour per player. + // If m_PlayerID == PLAYER_NONE, there's no player colour at all. + // If m_PlayerID == PLAYER_COMINGSOON, it's going to be linked to a player, + // but hasn't yet. + enum { PLAYER_NONE = -1, PLAYER_OTHER = -2, PLAYER_COMINGSOON = -3 }; + int m_PlayerID; + SMaterialColor m_TextureColor; // used as an alternative to the per-player colour }; extern CMaterial NullMaterial; diff --git a/source/graphics/MaterialManager.cpp b/source/graphics/MaterialManager.cpp index dc87460075..d5064afd4b 100755 --- a/source/graphics/MaterialManager.cpp +++ b/source/graphics/MaterialManager.cpp @@ -169,26 +169,26 @@ CMaterialManager::~CMaterialManager() CMaterial &CMaterialManager::LoadMaterial(const char *file) { - if(!strlen(file)) - return NullMaterial; + if(!strlen(file)) + return NullMaterial; - std::map::iterator iter; - if((iter = m_Materials.find(std::string(file))) != m_Materials.end()) - { - if((*iter).second) - return *(*iter).second; - } + std::map::iterator iter; + if((iter = m_Materials.find(std::string(file))) != m_Materials.end()) + { + if((*iter).second) + return *(*iter).second; + } CXeromyces xeroFile; if(xeroFile.Load(file) != PSRETURN_OK) - return NullMaterial; + return NullMaterial; #define EL(x) int el_##x = xeroFile.getElementID(#x) #define AT(x) int at_##x = xeroFile.getAttributeID(#x) EL(texture); - EL(vertexprogram); - EL(fragmentprogram); - + EL(vertexprogram); + EL(fragmentprogram); + EL(colors); AT(diffuse); AT(ambient); @@ -209,65 +209,66 @@ CMaterial &CMaterialManager::LoadMaterial(const char *file) XMBElementList childNodes = root.getChildNodes(); material = new CMaterial(); - for(i32 i = 0; i < childNodes.Count; i++) + for(int 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_vertexprogram) - { - CStr value(node.getText()); - material->SetVertexProgram(value); - } - else if(token == el_fragmentprogram) - { - CStr value(node.getText()); - material->SetFragmentProgram(value); - } + XMBAttributeList attrs = node.getAttributes(); + CStr temp; + if(token == el_texture) + { + CStr value(node.getText()); + material->SetTexture(value); + } + else if(token == el_vertexprogram) + { + CStr value(node.getText()); + material->SetVertexProgram(value); + } + else if(token == el_fragmentprogram) + { + CStr value(node.getText()); + material->SetFragmentProgram(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_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_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)); + 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); + else if(token == el_alpha) + { + temp = (CStr)attrs.getNamedItem(at_usage); // Determine whether the alpha is used for basic transparency or player color - if (temp == CStr("playercolor")) - material->SetIsPlayer(true); + if (temp == "playercolor") + material->SetPlayerColor_PerPlayer(); + else if (temp == "objectcolor") + material->SetPlayerColor_PerObject(); else material->SetUsesAlpha(ParseUsage(temp)); - } + } } - m_Materials[std::string(file)] = material; + m_Materials[file] = material; + } + catch(...) + { + SAFE_DELETE(material); + throw; } - catch(...) - { - SAFE_DELETE(material); - throw; - } - return *material; + return *material; } diff --git a/source/graphics/Model.cpp b/source/graphics/Model.cpp index 1e56b6b642..12497da7f8 100755 --- a/source/graphics/Model.cpp +++ b/source/graphics/Model.cpp @@ -25,7 +25,7 @@ ///////////////////////////////////////////////////////////////////////////////////////////////////////////// // Constructor CModel::CModel() - : m_Flags(0), m_PlayerID(0), m_Anim(0), m_AnimTime(0), + : m_Flags(0), m_Anim(0), m_AnimTime(0), m_BoneMatrices(0), m_InvBoneMatrices(0), m_BoneMatricesValid(false) { } @@ -370,11 +370,10 @@ CModel* CModel::Clone() const if (m_Texture.GetHandle()) h_add_ref(m_Texture.GetHandle()); clone->SetMaterial(m_Material); clone->SetAnimation(m_Anim); - clone->SetPlayerID(m_PlayerID); clone->SetFlags(m_Flags); for (uint i=0;iAddProp(m_Props[i].m_Point,m_Props[i].m_Model->Clone()); + clone->AddProp(m_Props[i].m_Point, m_Props[i].m_Model->Clone()); } return clone; } @@ -404,6 +403,8 @@ void CModel::SetTransform(const CMatrix3D& transform) } } +////////////////////////////////////////////////////////////////////////// + void CModel::SetMaterial(const CMaterial &material) { m_Material = material; @@ -411,3 +412,15 @@ void CModel::SetMaterial(const CMaterial &material) { } } + +void CModel::SetPlayerID(int id) +{ + m_Material.SetPlayerColor(id); + for (std::vector::iterator it = m_Props.begin(); it != m_Props.end(); ++it) + it->m_Model->SetPlayerID(id); +} + +void CModel::SetPlayerColor(CColor& colour) +{ + m_Material.SetPlayerColor(colour); +} diff --git a/source/graphics/Model.h b/source/graphics/Model.h index b16486c886..10bb9a762c 100755 --- a/source/graphics/Model.h +++ b/source/graphics/Model.h @@ -52,16 +52,16 @@ public: // set the model's texture void SetTexture(const CTexture& tex) { m_Texture=tex; } - // set the model's material - void SetMaterial(const CMaterial &material); - // set the model's player ID - void SetPlayerID(PS_uint id) { m_PlayerID=id; } + // set the model's material + void SetMaterial(const CMaterial &material); + // set the model's player ID, recursively through props + void SetPlayerID(int id); + // set the model's player colour + void SetPlayerColor(CColor& colour); // get the model's texture CTexture* GetTexture() { return &m_Texture; } - // get the models material - CMaterial &GetMaterial() { return m_Material; } - // get the model's player ID - PS_uint GetPlayerID() { return m_PlayerID; } + // get the models material + CMaterial &GetMaterial() { return m_Material; } // set the given animation as the current animation on this model bool SetAnimation(CSkeletonAnim* anim, bool once = false); @@ -125,10 +125,8 @@ private: u32 m_Flags; // texture used by model CTexture m_Texture; - // model's material - CMaterial m_Material; - // model's player ID - used for entities in the renderer - PS_uint m_PlayerID; + // model's material + CMaterial m_Material; // pointer to the model's raw 3d data CModelDefPtr m_pModelDef; // object space bounds of model - accounts for bounds of all possible animations diff --git a/source/graphics/ObjectBase.cpp b/source/graphics/ObjectBase.cpp index df65d60ee6..20a52b0771 100644 --- a/source/graphics/ObjectBase.cpp +++ b/source/graphics/ObjectBase.cpp @@ -155,12 +155,14 @@ bool CObjectBase::Load(const char* filename) EL(prop); EL(mesh); EL(texture); + EL(color); AT(file); AT(name); AT(speed); AT(attachpoint); AT(actor); AT(frequency); + AT(rgb); #undef AT #undef EL @@ -198,6 +200,9 @@ bool CObjectBase::Load(const char* filename) else if (option_name == el_texture) m_Variants.back().back().m_TextureFilename = "art/textures/skins/" + CStr(option.getText()); + else if (option_name == el_color) + m_Variants.back().back().m_Color = CStr(option.getAttributes().getNamedItem(at_rgb)); + else if (option_name == el_animations) { XERO_ITER_EL(option, anim_element) diff --git a/source/graphics/ObjectBase.h b/source/graphics/ObjectBase.h index 5007e2c558..52a1db337a 100644 --- a/source/graphics/ObjectBase.h +++ b/source/graphics/ObjectBase.h @@ -39,6 +39,7 @@ public: int m_Frequency; CStr m_ModelFilename; CStr m_TextureFilename; + CStr m_Color; std::vector m_Anims; std::vector m_Props; diff --git a/source/graphics/ObjectEntry.cpp b/source/graphics/ObjectEntry.cpp index 077950fdb8..924c1289ac 100755 --- a/source/graphics/ObjectEntry.cpp +++ b/source/graphics/ObjectEntry.cpp @@ -21,7 +21,7 @@ CObjectEntry::CObjectEntry(int type, CObjectBase* base) -: m_Model(0), m_Type(type), m_Base(base) +: m_Model(0), m_Type(type), m_Base(base), m_Color(1.0f, 1.0f, 1.0f, 1.0f) { m_IdleAnim=0; m_WalkAnim=0; @@ -44,6 +44,7 @@ bool CObjectEntry::BuildRandomVariant(CObjectBase::variation_key& vars, CObjectB { CStr chosenTexture; CStr chosenModel; + CStr chosenColor; std::map chosenProps; std::map chosenAnims; @@ -72,6 +73,9 @@ bool CObjectEntry::BuildRandomVariant(CObjectBase::variation_key& vars, CObjectB if (var.m_ModelFilename.Length()) chosenModel = var.m_ModelFilename; + if (var.m_Color.Length()) + chosenColor = var.m_Color; + for (std::vector::iterator it = var.m_Props.begin(); it != var.m_Props.end(); ++it) chosenProps[it->m_PropPointName] = *it; @@ -84,6 +88,17 @@ bool CObjectEntry::BuildRandomVariant(CObjectBase::variation_key& vars, CObjectB m_TextureName = chosenTexture; m_ModelName = chosenModel; + if (chosenColor.Length()) + { + std::stringstream str; + str << chosenColor; + int r, g, b; + if (! (str >> r >> g >> b)) // Any trailing data is ignored + LOG(ERROR, LOG_CATEGORY, "Invalid RGB colour '%s'", chosenColor.c_str()); + else + m_Color = CColor(r/255.0f, g/255.0f, b/255.0f, 1.0f); + } + for (std::map::iterator it = chosenProps.begin(); it != chosenProps.end(); ++it) m_Props.push_back(it->second); @@ -117,6 +132,7 @@ bool CObjectEntry::BuildRandomVariant(CObjectBase::variation_key& vars, CObjectB m_Model->SetTexture((const char*) m_TextureName); m_Model->SetMaterial(g_MaterialManager.LoadMaterial(m_Base->m_Material)); m_Model->InitModel(modeldef); + m_Model->SetPlayerColor(m_Color); // calculate initial object space bounds, based on vertex positions m_Model->CalcObjectBounds(); diff --git a/source/graphics/ObjectEntry.h b/source/graphics/ObjectEntry.h index f8738d33a3..dc7a4e6495 100755 --- a/source/graphics/ObjectEntry.h +++ b/source/graphics/ObjectEntry.h @@ -7,6 +7,7 @@ class CSkeletonAnim; #include #include "CStr.h" #include "ObjectBase.h" +#include "Overlay.h" class CObjectEntry { @@ -26,6 +27,8 @@ public: CStr m_TextureName; // model name CStr m_ModelName; + // colour (used when doing alpha-channel colouring, but not doing player-colour) + CColor m_Color; // list of valid animations for this object std::vector m_Animations; CSkeletonAnim* m_IdleAnim; diff --git a/source/ps/Overlay.h b/source/ps/Overlay.h index 86d471e3bf..a125c2c9a8 100755 --- a/source/ps/Overlay.h +++ b/source/ps/Overlay.h @@ -12,7 +12,7 @@ by Rich Cross, rich@0ad.wildfiregames.com #ifndef COVERLAY_H #define COVERLAY_H -#include "lib.h" +#include "types.h" struct CColor { @@ -52,7 +52,7 @@ class CSize; /** * @author Gustav Larsson * - * Rectangle class used for screen rectangles. It's very similiar to the MS + * Rectangle class used for screen rectangles. It's very similar to the MS * CRect, but with FLOATS because it's meant to be used with OpenGL which * takes float values. * diff --git a/source/renderer/PlayerRenderer.cpp b/source/renderer/PlayerRenderer.cpp index cd1dd5959d..f86f145f93 100644 --- a/source/renderer/PlayerRenderer.cpp +++ b/source/renderer/PlayerRenderer.cpp @@ -75,7 +75,7 @@ void CPlayerRenderer::Render() glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR); // Set the proper LOD bias - glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, g_Renderer.m_Options.m_LodBias); + glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, g_Renderer.m_Options.m_LodBias); // Render two passes: first, render the unit as normal. Second, // render it again but modulated with the player-colour, using @@ -207,12 +207,9 @@ void CPlayerRenderer::RenderObjectsStreams(u32 streamflags, bool iscolorpass, u3 // If I am wrong, then just move everything except for the // SetupColorRenderStates() below this if statement. - // Get the models player ID - PS_uint playerid = m_Objects[i].m_Model->GetPlayerID(); - // Get the player color - const SPlayerColour& colour = g_Game->GetPlayer( playerid )->GetColour(); - float color[] = { colour.r, colour.g, colour.b, colour.a }; + SMaterialColor colour = m_Objects[i].m_Model->GetMaterial().GetPlayerColor(); + float* color = &colour.r; // because it's stored RGBA // Just like it says, Sets up the player color render states SetupColorRenderStates();