Color class

Started by
2 comments, last by JohnBolton 19 years, 1 month ago
This is my class to hold a color. It is written to work with OpenGL.

#ifndef _CCOLOR_H_
#define _CCOLOR_H_

#include <iostream>
using namespace std;

#include <windows.h>
#include <gl/gl.h>		// Header file for OpenGL32 Library
#include <gl/glu.h>		// Header file for the GLu32 library
#include <gl/glaux.h>	// Header file for the GLaux library

/**
 * This is a class that will represent a color with 4 parts.
 * Alpha, Red, Green, Blue. Within the class, the color will be represented
 * by a 32-bit unsigned integer.
 * Eg. First 8 bits will represent alpha, second 8, red, third 8, green, last 8, blue.
 * So, each value can only be from 0-255.
 */
class CColor
{
private:
	size_t color;	///< 32-bit unsigned integer representing the color


public:
	/** Constructor that inits 'color' to 0 */
	CColor()	:	color(0) { }

	/** Constructor that inits the color when given the four parts.
	 * \param a Unsigned integer value from 0-255 representing the alpha value of the color.
 	 * \param r Unsigned integer value from 0-255 representing the red value of the color.
	 * \param g Unsigned integer value from 0-255 representing the green value of the color.
	 * \param b Unsigned integer value from 0-255 representing the blue value of the color.
	 */
	CColor(size_t a, size_t r, size_t g, size_t b)
	{
		// Set the color
		set(a, r, g, b);
	}

	/** Constructor that inits the color when given three parts.
 	 * \param r Unsigned integer value from 0-255 representing the red value of the color.
	 * \param g Unsigned integer value from 0-255 representing the green value of the color.
	 * \param b Unsigned integer value from 0-255 representing the blue value of the color.
	 */
	CColor(size_t r, size_t g, size_t b)
	{
		// Set the color
		set(255, r, g, b);
	}

	/**
	 * This function sets the various values of the color.
	 * \param a Unsigned integer value from 0-255 representing the alpha value of the color.
 	 * \param r Unsigned integer value from 0-255 representing the red value of the color.
	 * \param g Unsigned integer value from 0-255 representing the green value of the color.
	 * \param b Unsigned integer value from 0-255 representing the blue value of the color.
	 */
	void set(size_t a, size_t r, size_t g, size_t b)
	{
		// Check for invalid color values
		if( a > 255 || r > 255 || g > 255 || b > 255 ){
			cout << "Invalid color values. Color not set." << endl;
			return;
		}

		// reset color
		color = 0;

		// init alpha
		color = color | (a << 24);
		// init red
		color = color | (r << 16);
		// init green
		color = color | (g << 8);
		// init blue
		color = color | b;
	}

	/**
	 * Sets the values of this CColor object to the current openGL color.
	 */
	void setToOpenGLColor()
	{
		float openglcolor[4];	// Store the 4 opengl color elements in here

		// Get the 4 color elements and store them in the float array.
		glGetFloatv(GL_CURRENT_COLOR, openglcolor );

		setRed( (size_t)(openglcolor[0] * 255) );	// Set red element of color
		setBlue( (size_t)(openglcolor[1] * 255) );	// Set blue element of color
		setGreen( (size_t)(openglcolor[2] * 255) );	// Set green element of color
		setAlpha( (size_t)(openglcolor[3] * 255) );	// Set alpha element of color
	}

	/**
	 * Sets the current openGL color to the values of this CColor object.
	 */
	void setOpenGLColor()
	{
		// Set the opengl color
		glColor4f(	(float)(getRed()/255.0f), (float)(getGreen()/255.0f), 
					(float)(getBlue()/255.0f), (float)(getAlpha()/255.0f) );
	}


	/**
	 * This function sets the alpha value of the color.
	 * \param a Unsigned integer from 0-255 representing the alpha value of the color.
	 */
	void setAlpha(size_t a)
	{
		if( a > 255 ){
			cout << "Invalid alpha value. Alpha not set." << endl;
			return;
		}

		color = color | (a << 24);
	}

	/**
	 * This function sets the red value of the color.
	 * \param r Unsigned integer from 0-255 representing the red value of the color.
	 */
	void setRed(size_t r)
	{
		if( r > 255 ){
			cout << "Invalid red value. Red not set." << endl;
			return;
		}

		color = color | (r << 16);
	}

	/**
	 * This function sets the green value of the color.
	 * \param g Unsigned integer from 0-255 representing the green value of the color.
	 */
	void setGreen(size_t g)
	{
		if( g > 255 ){
			cout << "Invalid green value. Green not set." << endl;
			return;
		}

		color = color | (g << 8);
	}

	/**
	 * This function sets the blue value of the color.
	 * \param r Unsigned integer from 0-255 representing the blue value of the color.
	 */
	void setBlue(size_t b)
	{
		if( b > 255 ){
			cout << "Invalid blue value. Blue not set." << endl;
			return;
		}

		color = color | b;
	}

	/**
	 * Returns a value from 0-255 representing the alpha value of the color.
	 */
	size_t getAlpha()
	{
		return ( (color&0xFF000000) >> 24 );
	}

	/**
	 * Returns a value from 0-255 representing the red value of the color.
	 */
	size_t getRed()
	{
		return ( (color&0x00FF0000) >> 16 );
	}

	/**
	 * Returns a value from 0-255 representing the green value of the color.
	 */
	size_t getGreen()
	{
		return ( (color&0x0000FF00) >> 8 );
	}

	/**
	 * Returns a value from 0-255 representing the blue value of the color.
	 */
	size_t getBlue()
	{
		return (color & 0x000000FF);
	}

	/**
	 * Overloaded == operator.
	 * \param c A const reference to another CColor object.
	 * \return A boolean value indicating whether the two CColor objects are equal
	 * to each other.
	 */
	bool operator==(const CColor& c)	{	return color == c.color;	}

	/**
	 * Overloaded != operator.
	 * \param c A const reference to another CColor object.
	 * \return A boolean value indicating whether the two CColor objects are not equal
	 * to each other.
	 */
	bool operator!=(const CColor& c)	{	return color != c.color;	}

	/**
	 * Overloaded = operator.
	 * \param c A const reference to another CColor object.
	 * \return A reference to 'this' CColor object.
	 */
	CColor& operator=(const CColor& c)	{	color = c.color;	return *this;	}


};
#endif

Perhaps a little long, but I'm having a specific problem. When I change the color for an object, the alpha doesn't seem to have an effect.

// Line that changes the color
plane.setColor(CShape::COLORITEM_SURFACE, CColor(255,255,0,0) );


// This is basically the function
void CShape::setColor(ColorItem citem, CColor& c)
{
     switch(citem){
          case COLORITEM_SURFACE:
               shape_color = c;
               break;
     };
}


// and then, later on, my render function calls this
void drawSurface()
{
	// Save the current open gl color
	CColor temp;
	temp.setToOpenGLColor();
		
	// Set surface color
	color.setOpenGLColor();

	glBegin(GL_TRIANGLES);

		glVertex3f(vertex_buffer[0].x, vertex_buffer[0].y, vertex_buffer[0].z);
		glVertex3f(vertex_buffer[1].x, vertex_buffer[1].y, vertex_buffer[1].z);
		glVertex3f(vertex_buffer[2].x, vertex_buffer[2].y, vertex_buffer[2].z);

		glVertex3f(vertex_buffer[1].x, vertex_buffer[1].y, vertex_buffer[1].z);
		glVertex3f(vertex_buffer[2].x, vertex_buffer[2].y, vertex_buffer[2].z);
		glVertex3f(vertex_buffer[3].x, vertex_buffer[3].y, vertex_buffer[3].z);

	glEnd();	// Stop drawing triangles

	temp.setOpenGLColor();		// Restore the opengl color
}


Its important to note, that the render function doesn't change anything. It calls push matrix, and then depending on what should be drawn for the object, it calls the right functions. All the functions that draw something are exactly the same as the drawSurface function. Here is my problem: with this line of code: "plane.setColor(CShape::COLORITEM_SURFACE, CColor(255,255,0,0) );", it doens't matter whether the first param in CColor constructor (which is the alpha value) is 0 or 255. It makes absolutely no difference either way. The thing being drawn does not change one iota. Can anyone spot a bug, or something I should have done another way to avoid a problem like this?
[size="2"][size=2]Mort, Duke of Sto Helit: NON TIMETIS MESSOR -- Don't Fear The Reaper
Advertisement
If changing the alpha doesn't change the display then it is likely that your blending setup is not right. Does changing the color work?

Anyway, here are some unrelated tips:
  1. Don't use size_t like that. size_t is the type returned by the sizeof operator and is totally wrong for what you are using it for. size_t is not always 32 bits. If you want a 32-bit type, use the types provided by the compiler (e.g. __int32 in MSVC) or make your own if they aren't provided.
  2. The OpenGL glGet* functions are generally very slow and should be avoided.
  3. setAlpha, setRed, setGreen, and setBlue are broken because they don't reset the old value before oring in the new value. setAlpha should look like this:
        color &= ~( 0xff << 24 );    color |= a << 24; 
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
Quote:Original post by JohnBolton
If changing the alpha doesn't change the display then it is likely that your blending setup is not right. Does changing the color work?

Anyway, here are some unrelated tips:
  1. Don't use size_t like that. size_t is the type returned by the sizeof operator and is totally wrong for what you are using it for. size_t is not always 32 bits. If you want a 32-bit type, use the types provided by the compiler (e.g. __int32 in MSVC) or make your own if they aren't provided.
  2. The OpenGL glGet* functions are generally very slow and should be avoided.
  3. setAlpha, setRed, setGreen, and setBlue are broken because they don't reset the old value before oring in the new value. setAlpha should look like this:
        color &= ~( 0xff << 24 );    color |= a << 24; 


Yeah, changing the color in the constructor does work. So, changing from CColor(255,255,0,0) to CColor(255,100,100,0) does work.

I'm only using size_t to make sure that whoever's using it knows that its an unsigned int, and it doens't matter if its 32 or not, just as long as its at least 8 bits. I don't really use size_t anywhere else.

I changed the setAlpha, etc functions, thanks for that. I can't raelly believe that I didn't see that. Anyway, the contructor doens't use those functions, it uses a set(size_t, size_t, size_t, size_t) function, which resets the whole color to 0.

YOu say the OpenGL get functions are slow? Whats another way to get, the color, or something else? Are there extra functions?
[size="2"][size=2]Mort, Duke of Sto Helit: NON TIMETIS MESSOR -- Don't Fear The Reaper
Quote:Original post by Endar
I'm only using size_t to make sure that whoever's using it knows that its an unsigned int, and it doens't matter if its 32 or not, just as long as its at least 8 bits.

Well, the member variable color is a size_t and it must be 32 bits. Regardless, using size_t is wrong here -- use unsigned int if you want the type to be an unsigned int.

Quote:Original post by Endar
You say the OpenGL get functions are slow? Whats another way to get, the color, or something else? Are there extra functions?

Normally, you simply don't save and restore the state, or you cache the values yourself. Generally, getting the state requires the hardware to stop what it is doing, wait for the pipeline to be empty, return the state, and then start up again. Also, state changes are slow and saving/restoring the state like that could double the number of state changes.
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!

This topic is closed to new replies.

Advertisement