HomeNewsFeaturesLicensingDownloadsScreenshotsFAQRoadmap Contact Us
Search:
8 Online

Community

Discussion Topics Recent Postings User Contributions General Articles Example Documentation Credits

Licensed Developer

Programmer's Manual Artists Manual Tutorials and Articles

Programming: Game Code

Game Code Overview Server Side Game Code Client Side Game Code

Programming: System

Alphabetical Function List Renderer File System Collision & Ray Casting Low Level Audio Game Audio The Console Console Variable List Multiplayer Localisation Maths Library Memory Manager Model File Formats Texture Formats

Art: Overviews

Specifications Shaders Particle Systems Lens Flares Cipher console Cipher file types Tutorials Reference

Art: Tools

Shader Designer Particle Designer 3dsmax tools Model Conversion Font Generator

Cipher Engine
Game Development Search Engine
GameDev.net
You are not signed in - [sign in] [register]

C++ Colour classes

Overview

Author: philk
Date Submitted: 2004-07-19 14:04:26

Source Code

struct Color
{
	float	red;
	float	green;
	float	blue;
	float	alpha;
	
	Color(const float _r = 1.0f, const float _g = 1.0f, const float _b = 1.0f, const float _a = 1.0f):
		red(_r),
		green(_g),
		blue(_b),
		alpha(_a)
	{
		Clamp();
	}

	
	Color(const int _r, const int _g, const int _b, const int _a = 255):
		red(_r / 255.f),
		green(_g / 255.f),
		blue(_b / 255.f),
		alpha(_a / 255.f)
	{
		Clamp();
	}

	Color(const Color& _rOther):
		red(_rOther.red),
		green(_rOther.green),
		blue(_rOther.blue),
		alpha(_rOther.alpha)
	{
		// Not neccessary since the parent is already clamped, hopefully ;)
		//Clamp();
	}

	const Color& operator = (const Color& _rOther)
	{
		red	= _rOther.red;
		green	= _rOther.green;
		blue	= _rOther.blue;
		alpha	= _rOther.alpha;
		return *this;
	}

	void Normalize()
	{
		red /= 255.f;
		if (red < 0.0f)
		{
			red = 0.0f;
		}
		
		green /= 255.f;
		if (green < 0.0f)
		{
			green = 0.0f;
		}
		
		blue /= 255.f;
		if (blue < 0.0f)
		{
			blue = 0.0f;
		}
		
		alpha /= 255.f;
		if (alpha < 0.0f)
		{
			alpha = 0.0f;
		}		
	}

	void Clamp()
	{
		if (red < 0.0f)
		{
			red = 0.0f;
		}
		else if (red > 1.0f)
		{
			red = 1.0f;
		}
		
		if (green < 0.0f)
		{
			green = 0.0f;
		}
		else if (green > 1.0f)
		{
			green = 1.0f;
		}

		if (blue < 0.0f)
		{
			blue = 0.0f;
		}
		else if (blue > 1.0f)
		{
			blue = 1.0f;
		}

		if (alpha < 0.0f)
		{
			alpha = 0.0f;
		}
		else if (alpha > 1.0f)
		{
			alpha = 1.0f;
		}
	}
		
	void Set() const
	{
		cipher_r_SetColour((float*)this);
	}

	void Unset() const
	{
		cipher_r_SetColour(NULL);
	}

	const Color& Lerp(const Color& _rOther, float _fFactor)
	{
		red = red + _fFactor * (_rOther.red - red);
		green = green + _fFactor * (_rOther.green - green);
		blue = blue + _fFactor * (_rOther.blue - blue);
		alpha = alpha + _fFactor * (_rOther.alpha - alpha);
	
		return *this;
	}
};

// A helper to set a color.
// If the class goes out of scope its destructor will reset the color value
// Since all the members are const the class does not take any memory. 
// It just sits on the stack and all methods are inlined into the code.
class StackColor
{
	const bool		m_bSet;
	Color const&	m_rColor;
	
public:
	StackColor(Color const& _rColor, const bool _bSet = true):
		m_rColor(_rColor),
		m_bSet(_bSet)
	{
		if (_bSet)
		{
			m_rColor.Set();
		}
	}

	~StackColor()
	{
		if (m_bSet)
		{
			m_rColor.Unset();
		}
	}
};


Description

I use these classes to simplify my color management.
Especially the StackColor saved me a lot of debugging time. How often you forget to call "cipher_r_SetColour" and wonder why some shaders are drawn with the wrong colour?
StackColor ensures the colour is set back to NULL (white) when the object leaves the scope.

Example:


Color textColor(255,0,0);
{
StackColor col(textColor);
} // Here the StackColor::~StackColor is called, and resets the colour


So the state of the current vertex colour is always set back to the state it was before, when using StackColor.

Maybe some of your may find this helpful.

Phil

[Recent Contributions] [Recent Source Code]

User Contributed Comments

ebrownlee 20th July, 2004 05:29
I just recently changed Cipher's SetColour to no longer use floating point real numbers since the floats were getting converted to bytes anyway. I wrote a Color class to accompany the change, but I've yet to use it since my SDK is still C. Here it is just for the sake of everyone's reference/comparison/whatever:

class Color
{
unsigned int m_uiColor;
public:

Color( void ) : m_uiColor(0xFFFFFFFF) {}
Color( unsigned int uiColor ) : m_uiColor(uiColor) { };
Color( unsigned char uiRed, unsigned char uiGreen,
unsigned char uiBlue, unsigned char uiAlpha )
{
m_uiColor = ((uiRed & 0xFF) << 24) | ((uiGreen & 0xFF) << 16) |
((uiBlue & 0xFF) << 8) | (uiAlpha & 0xFF);
}

const Color& operator = ( const Color& clrSource )
{
m_uiColor = clrSource.m_uiColor;
return *this;
}
operator unsigned int ( void ) const
{
return m_uiColor;
}
// prefer indirect access with Color::Red, Color::Green, Color::Blue, and Color::Alpha
const unsigned char operator [] ( int iIndex ) const
{
unsigned char uiBytes[4] =
{
((m_uiColor & 0xff000000)>>24), ((m_uiColor & 0x00ff0000)>>16),
((m_uiColor & 0x0000ff00)>>8), ((m_uiColor & 0x000000ff))
};
return uiBytes[iIndex];
}
unsigned char getRed( void ) const
{
return this->operator[](Color::Red);
}
unsigned char getGreen( void ) const
{
return this->operator[](Color::Green);
}
unsigned char getBlue( void ) const
{
return this->operator[](Color::Blue);
}
unsigned char getAlpha( void ) const
{
return this->operator[](Color::Alpha);
}

void setRed( unsigned char uiRed )
{
m_uiColor &= ~0xFF000000;
m_uiColor |= ((uiRed & 0xFF) << 24);
}
void setGreen( unsigned char uiGreen )
{
m_uiColor &= ~0x00FF0000;
m_uiColor |= ((uiGreen & 0xFF) << 16);
}
void setBlue( unsigned char uiBlue )
{
m_uiColor &= ~0x0000FF00;
m_uiColor |= ((uiBlue & 0xFF) << 8);
}
void setAlpha( unsigned char uiAlpha )
{
m_uiColor &= ~0x000000FF;
m_uiColor |= (uiAlpha & 0xFF);
}

Color asBigEndian( void ) const // flip from ABGR to RGBA on big endian machines
{
unsigned char uiBytes[4] =
{
((m_uiColor & 0xff000000)>>24), ((m_uiColor & 0x00ff0000)>>16),
((m_uiColor & 0x0000ff00)>>8), ((m_uiColor & 0x000000ff))
};
return Color(uiBytes[Color::Alpha], uiBytes[Color::Blue],
uiBytes[Color::Green], uiBytes[Color::Red]);
}

enum indices_e { Red = 0, Green = 1, Blue = 2, Alpha = 3 };

};


The whole StackColor idea is great. I use that method for my profiling code, and I never really thought to adapt it to more casual uses such as this. Nice contribution. :)

- Ernest

[edit: fixed formatting, made code fit on 1024x768 resolution]
Edited 20th July, 2004 05:40


Serapth 20th July, 2004 22:15
Well, I have the first bug to report... you spelt colour wrong... you missed the "u"! Sorry... can never resist taking a shot at "american english".

Nice contribution btw, keep em coming.




Register and Sign In to discuss this article