Advertisement

Some classes to make your life easier

Started by July 08, 2001 12:20 AM
8 comments, last by gameovercl 23 years, 7 months ago
NOTE: This post was edited, based upon of the suggestions above. Hi there! Because of the fact that I'm an old D3D programmer just switching to OpenGL, I like to use structures, and not single variables or arrays. So, I made this classes, just for make things easier. Here it goes the header file:
      // VECTOR Class


class VECTOR
{	
public:
	VECTOR(GLfloat _x, GLfloat _y, GLfloat _z) {x=_x; y=_y; z=_z; }
	VECTOR() {x=0.0f, y=0.0f, z=0.0f; }
	void operator =(const VECTOR &source);
	
	union
	{
		struct
		{
			GLfloat x;
			GLfloat y;
			GLfloat z;
		};

		GLfloat v[3];
	};
};

VECTOR operator +(const VECTOR &v1, const VECTOR &v2);
VECTOR operator -(const VECTOR &v1, const VECTOR &v2);
// Dot product

inline float operator *(const VECTOR &v1, const VECTOR &v2)
{
	return (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z);
};
// Cross product

VECTOR operator ^(const VECTOR &v1, const VECTOR &v2);
VECTOR operator *(const VECTOR &v1, const float &value);
VECTOR operator *(const float &value, const VECTOR &v1);
VECTOR operator -(const VECTOR &v);
bool operator ==(const VECTOR &v1, const VECTOR &v2);
bool operator !=(const VECTOR &v1, const VECTOR &v2);

// MATRIX Class


class MATRIX
{
public:
	MATRIX(GLfloat __11, GLfloat __12, GLfloat __13, GLfloat __14,
		   GLfloat __21, GLfloat __22, GLfloat __23, GLfloat __24,
		   GLfloat __31, GLfloat __32, GLfloat __33, GLfloat __34,
		   GLfloat __41, GLfloat __42, GLfloat __43, GLfloat __44);
	MATRIX();
	void operator =(const MATRIX &source);

	union
	{
		struct
		{
			GLfloat _11, _12, _13, _14;
			GLfloat _21, _22, _23, _24;
			GLfloat _31, _32, _33, _34;
			GLfloat _41, _42, _43, _44;
		};

		GLfloat m[16];
	};
};  
And the main file:
  // VECTOR Class


void VECTOR::operator =(const VECTOR &source)
{
	x = source.x;
	y = source.y;
	z = source.z;
}

VECTOR operator +(const VECTOR &v1, const VECTOR &v2)
{
	VECTOR temp;

	temp.x = v1.x + v2.x;
	temp.y = v1.y + v2.y;
	temp.z = v1.z + v2.z;

	return temp;
}

VECTOR operator -(const VECTOR &v1, const VECTOR &v2)
{
	VECTOR temp;

	temp.x = v1.x - v2.x;
	temp.y = v1.y - v2.y;
	temp.z = v1.z - v2.z;

	return temp;
}

// Cross product

VECTOR operator ^(const VECTOR &v1, const VECTOR &v2)
{
	VECTOR result;

	result.x = v1.y * v2.z - v1.z * v2.y;
    result.y = v1.z * v2.x - v1.x * v2.z;
    result.z = v1.x * v2.y - v1.y * v2.x;

	return result;
}

VECTOR operator *(const float &value, const VECTOR &v1)
{
	VECTOR temp;

	temp.x = v1.x * value;
	temp.y = v1.y * value;
	temp.z = v1.z * value;

	return temp;
}

VECTOR operator -(const VECTOR &v)
{
	VECTOR temp;

	temp.x = -temp.x;
	temp.y = -temp.y;
	temp.z = -temp.z;

	return temp;
}

bool operator ==(const VECTOR &v1, const VECTOR &v2)
{	
	return ( fabs(v1.x - v2.x) < g_EPSILON &&
		fabs(v1.y - v2.x) < g_EPSILON &&
		fabs(v1.z - v2.z) < g_EPSILON );
}

bool operator !=(const VECTOR &v1, const VECTOR &v2)
{
	return (!(v1==v2));
}

// MATRIX Class


MATRIX::MATRIX(GLfloat __11, GLfloat __12, GLfloat __13, GLfloat __14,
			   GLfloat __21, GLfloat __22, GLfloat __23, GLfloat __24,
			   GLfloat __31, GLfloat __32, GLfloat __33, GLfloat __34,
		       GLfloat __41, GLfloat __42, GLfloat __43, GLfloat __44)
{
	_11 = __11; _12 = __12; _13 = __13; _14 = __14;
	_21 = __21; _22 = __22; _23 = __23; _24 = __24;
	_31 = __31; _32 = __32; _33 = __33; _34 = __34;
	_41 = __41; _42 = __42; _43 = __43; _44 = __44;
}

MATRIX::MATRIX()
{
	ZeroMemory(&m, sizeof(m));
}

void MATRIX::operator =(const MATRIX &source)
{
	memcpy(m, source.m, sizeof(m));
}  
The nice thing is that you can fill a matrix by setting _11, _12, etc. and then simply call the array 'm'. The same way, you can store values for a vector for 'x', 'y' and 'z' and then call:
  glVertex3f(vector.x, vector.y, vector.z);

// Or much simpler and faster:


glVertex3fv(vector.v);  
BTW, you may set g_EPSILON (Tolerance for float) as you wish; I use const float g_EPSILON = 1.0e-5f; as Microsoft does. Hope you find this stuff useful Email Me Cristián Ramírez (gameovercl) ICQ #38991565 Viña del Mar CHILE Edited by - gameovercl on July 9, 2001 9:33:19 PM
Nice use of unions!
Advertisement
Thanks, gameovercl!

I''m sure I''ll find this very usefull soon

-tee
-tee
bool operator !=(const VECTOR &v1, const VECTOR &v2){        if(!(v1==v2))                return true;        return false;}

I think the following is better:
inline bool operator !=(const VECTOR &v1, const VECTOR &v2){        return !(v1==v2);}


The idea with the Union is this that I was searching for, to combine the x,y,z writing with handing a pointer to the vector (It was possible if you define x,y and z directly after each other, but then I assumed sth. that wasn''t covered by the standard I think. Just have to read a little bitto fully understand unions.

Greetings Ben
Thanks for the code, it looks very useful.

Two things though. What's the purpose of the VECTOR operator * (VECTOR, VECTOR)? I don't see how it's useful in vector math. Maybe you should use that operator for a cross product instead?

Second, it would probably help to define a dot product. Maybe
GLfloat operator * (VECTOR, VECTOR)

Er... no wait... you can't have the same operator and operands return a different type. I guess you could do
GLfloat operator / (VECTOR, VECTOR)
for a dot product.

Edited by - Dobbs on July 9, 2001 5:38:49 PM
Use * for dot product and ^ for cross product.

Nice code, btw.
Advertisement
if(!(v1==v2))
return true;
return false;

PLEASE program better

return !(v1==v2);

does the same work
quote:
Original post by gameovercl

  bool operator ==(const VECTOR &v1, const VECTOR &v2){	if(v1.x==v2.x && v1.y==v2.y && v1.z==v2.z)		return true;	return false;}  



You should never (except in very specific cases) use the == and != operator on floats. Because of rounding errors and suchlike in your calculations, it is always better to use an "almost equals" operator, like so:

  bool operator == (const VECTOR &v1, const VECTOR &v2 ){    const float epsilon = 1e-3f;    return ( ABS(v1.x - v2.x) < epsilon &&             ABS(v1.y - v2.x) < epsilon &&             ABS(v1.z - v2.z) < epsilon );}  


That''s the good thing with operator overloads, you can hide such details from the application. Actually, the way I do it is to define the == operator as you did, but also have an Equals() member function, that way I know it''s not exactly equals, and I can pass in the epsilon if I want to.


War Worlds - A 3D Real-Time Strategy game in development.
Oh yeah, another thing, you can make an operator like this:

  float *VECTOR::operator float *(){    return v;}  


And that way, you calls to glVertex3fv() become:

  VECTOR v( 1.0, 0.0, 0.0 );glVertex3fv( v );  



War Worlds - A 3D Real-Time Strategy game in development.
Thanks a lot guys for the good ideas!
I will edit my first post with all the tips you mention.

As for the "Anonymous Poster", I think that saying "PLEASE PROGRAM BETTER" isn't the most constructive way to share knowledge and information.

Thanks again!

Cristián Ramírez (gameovercl)
ICQ #38991565
Viña del Mar
CHILE

Edited by - gameovercl on July 9, 2001 9:19:16 PM

This topic is closed to new replies.

Advertisement