1
0
forked from 0ad/0ad

Fixed prop player-colouring. Allowed per-object colours. (Coming soon: data to demonstrate it.)

This was SVN commit r2113.
This commit is contained in:
Ykkrosh 2005-04-07 04:29:07 +00:00
parent 13da7d0aab
commit d2948937a0
11 changed files with 249 additions and 160 deletions

View File

@ -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 =

View File

@ -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;

View File

@ -169,26 +169,26 @@ CMaterialManager::~CMaterialManager()
CMaterial &CMaterialManager::LoadMaterial(const char *file)
{
if(!strlen(file))
return NullMaterial;
if(!strlen(file))
return NullMaterial;
std::map<std::string, CMaterial *>::iterator iter;
if((iter = m_Materials.find(std::string(file))) != m_Materials.end())
{
if((*iter).second)
return *(*iter).second;
}
std::map<std::string, CMaterial *>::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;
}

View File

@ -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;i<m_Props.size();i++) {
// eek! TODO, RC - need to investigate shallow clone here
clone->AddProp(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<Prop>::iterator it = m_Props.begin(); it != m_Props.end(); ++it)
it->m_Model->SetPlayerID(id);
}
void CModel::SetPlayerColor(CColor& colour)
{
m_Material.SetPlayerColor(colour);
}

View File

@ -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

View File

@ -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)

View File

@ -39,6 +39,7 @@ public:
int m_Frequency;
CStr m_ModelFilename;
CStr m_TextureFilename;
CStr m_Color;
std::vector<Anim> m_Anims;
std::vector<Prop> m_Props;

View File

@ -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<CStr, CObjectBase::Prop> chosenProps;
std::map<CStr, CObjectBase::Anim> 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<CObjectBase::Prop>::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<CStr, CObjectBase::Prop>::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();

View File

@ -7,6 +7,7 @@ class CSkeletonAnim;
#include <vector>
#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<CObjectBase::Anim> m_Animations;
CSkeletonAnim* m_IdleAnim;

View File

@ -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.
*

View File

@ -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();