Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

leedude

a vector class

This topic is 5450 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

i want to make a vector class and was curious about a few things: The way the vector class was made on NeHe site (code below) uses operator overloading for basic functions between the vectors, where other places i have seen a simple class or struct used to represent a vector with just x, y, z, w values in it and then seperate functions to add, multiply, crossprduct etc. are there any advantages or disadvantages to each of these methods? are operator overloading slow?
class VECTOR3D
{
	public:
		GLfloat vertex[3];

	float ComputeLength(void);

	friend VECTOR3D operator+ (VECTOR3D v1, VECTOR3D v2);
	friend VECTOR3D operator- (VECTOR3D v1, VECTOR3D v2);
	friend VECTOR3D operator* (VECTOR3D v1, GLfloat scalar);
	friend VECTOR3D operator* (VECTOR3D v1, VECTOR3D v2);
	friend VECTOR3D operator/ (VECTOR3D v1, VECTOR3D v2);

	VECTOR3D()
		{	memset(vertex, 0, sizeof(GLfloat[3]));	}
	VECTOR3D(GLfloat x, GLfloat y, GLfloat z);
};
Secondly: see how in the above class it uses an array to store the x, y, z values...what are the differences between using an array as opposed to having a seperate float for each value? Im thinking these things just come down to personal preferences and what u feel comfortable with, but i mite be wrong, and am curious if there are differences.

Share this post


Link to post
Share on other sites
Advertisement
I''d favour operator overloading personally, it gives you a more common feel with the rest of c++, and if you want to use things such as std::vector, you need to have some of the operators overloaded.

I''d say that having a single array of float or 3 seperate floats is preference.

Bp

Share this post


Link to post
Share on other sites
quote:

i want to make a vector class and was curious about a few things:
The way the vector class was made on NeHe site (code below) uses operator overloading for basic functions between the vectors, where other places i have seen a simple class or struct used to represent a vector with just x, y, z, w values in it and then seperate functions to add, multiply, crossprduct etc. are there any advantages or disadvantages to each of these methods? are operator overloading slow?



I have read that using operator overloading is slower, but I don't know if that still holds true with the newer computers out. You can use them them both operator overloading and regular functions.

Heres an example: (Ignore the X* stuff, I just pulled it from my engine)

class XVECTOR3
{
public:
XVECTOR3(Xvoid);
XVECTOR3(const Xfloat);
XVECTOR3(const Xfloat *);
XVECTOR3(const XVECTOR3 &);
XVECTOR3(Xfloat, Xfloat, Xfloat);

Xfloat X;
Xfloat Y;
Xfloat Z;

public:
operator Xfloat* (Xvoid);
operator const Xfloat* (Xvoid) const;

XVECTOR3 operator * (const XVECTOR3 &) const;
XVECTOR3 operator / (const XVECTOR3 &) const;
XVECTOR3 operator ^ (const XVECTOR3 &) const;
XVECTOR3 operator < (const XVECTOR3 &) const;
XVECTOR3 operator > (const XVECTOR3 &) const;
XVECTOR3 operator + (const XVECTOR3 &) const;
XVECTOR3 operator - (const XVECTOR3 &) const;
Xbool operator == (const XVECTOR3 &) const;
Xbool operator != (const XVECTOR3 &) const;
Xfloat operator % (const XVECTOR3 &) const;
XVECTOR3& operator += (const XVECTOR3 &);
XVECTOR3& operator -= (const XVECTOR3 &);
XVECTOR3& operator *= (Xfloat);
XVECTOR3& operator /= (Xfloat);
XVECTOR3 operator * (Xfloat)const;
XVECTOR3 operator / (Xfloat)const;
XVECTOR3 operator + (Xvoid) const;
XVECTOR3 operator - (Xvoid) const;

public:
XVECTOR3 Add(const XVECTOR3 *, const XVECTOR3 *);
XVECTOR3 Subtract(const XVECTOR3 *, const XVECTOR3 *);
XVECTOR3 Average(const XVECTOR3 *, const XVECTOR3 *);
XVECTOR3 Divide(Xfloat, const XVECTOR3 *);
XVECTOR3 Divide(const XVECTOR3 *, Xfloat);
XVECTOR3 Divide(const XVECTOR3 *, const XVECTOR3 *);
XVECTOR3 Multiply(Xfloat, const XVECTOR3 *);
XVECTOR3 Multiply(const XVECTOR3 *, Xfloat);
XVECTOR3 Multiply(const XVECTOR3 *, const XVECTOR3 *);
Xfloat DotProduct(const XVECTOR3 *);
Xvoid Copy(XVECTOR3 *);
Xvoid Zero(Xvoid);
Xbool IsZero(Xvoid);
Xvoid Negate(Xvoid);
Xfloat Magnitude(Xvoid);
Xfloat MagnitudeSQ(Xvoid);
Xvoid Normalize(Xvoid);
Xvoid NormalizeEX(Xvoid);
Xint Sign(Xvoid);
Xvoid CrossProduct(const XVECTOR3 *, const XVECTOR3 *);
Xvoid CrossProductEX(const XVECTOR3 *, const XVECTOR3 *);
Xfloat ScalarProduct(const XVECTOR3 *, const XVECTOR3 *, const XVECTOR3 *);
Xvoid Power(const XVECTOR3 *, const XVECTOR3 *);
Xvoid Spherical(Xfloat, Xfloat, Xfloat);
Xvoid Scale(XVECTOR3 *, const XVECTOR3 *, Xfloat);
Xvoid Minimize(const XVECTOR3 *, const XVECTOR3 *);
Xvoid Maximize(const XVECTOR3 *, const XVECTOR3 *);
Xfloat Distance(const XVECTOR3 *);
Xfloat DistanceEX(const XVECTOR3 *, const XVECTOR3 *);
Xint FastDistance(Xint, Xint);
Xbool NearlyEqual(const XVECTOR3 *);
Xvoid InterpLinear(XVECTOR3 *, Xfloat, const XVECTOR3 *, const XVECTOR3 *);
Xvoid InterpHermitSpline(XVECTOR3 *, Xfloat, const XVECTOR3 *, const XVECTOR3 *, const XVECTOR3 *, const XVECTOR3 *);
Xvoid InterpBSpline(XVECTOR3 *, Xfloat, const XVECTOR3 *, const XVECTOR3 *, const XVECTOR3 *, const XVECTOR3 *);
Xvoid InterpBSplineT(XVECTOR3 *, Xfloat, const XVECTOR3 *, const XVECTOR3 *, const XVECTOR3 *, const XVECTOR3 *);
Xvoid InterpCatmulRom(XVECTOR3 *, Xfloat, const XVECTOR3 *, const XVECTOR3 *, const XVECTOR3 *, const XVECTOR3 *);
Xvoid InterpCatmulRomT(XVECTOR3 *, Xfloat, const XVECTOR3 *, const XVECTOR3 *, const XVECTOR3 *, const XVECTOR3 *);
};

I hardly ever use the Add, Subtract, etc. It's easier just to use V1 + V2;

quote:

Secondly: see how in the above class it uses an array to store the x, y, z values...what are the differences between using an array as opposed to having a seperate float for each value?



Nothing because you can use an array with "seperate" floats. Heres what I mean:

//--In the class you would have X, Y, and Z.

//--

//--In class

//--

float &operator[](unsigned int ID);
const float &operator [] (unsigned int ID) const;
//--

//--In .cpp (Or where ever)

//--

float &operator[](unsigned int ID)
{
return *(&X + ID);
}
//

const float &operator [] (unsigned int ID) const
{
return *(&X + ID);
}

Then you can access the values like a normal array.
Vector.X would now be the same as Vector[0].

-UltimaX-

"You wished for a white christmas... Now go shovel your wishes!"

[edited by - UltimaX on August 19, 2003 8:47:16 AM]

Share this post


Link to post
Share on other sites
quote:

The way the vector class was made on NeHe site (code below) uses operator overloading for basic functions between the vectors, where other places i have seen a simple class or struct used to represent a vector with just x, y, z, w values in it and then seperate functions to add, multiply, crossprduct etc. are there any advantages or disadvantages to each of these methods? are operator overloading slow?


Operator overloading can be slower than functions. That is because of the way the compiler produces the ASM code. With operator overloading, the ASM needs to make some temporary storage space to hold the result''s values before passing the it to another variable. When you use functions you can pass everything by reference and thus no temp storage is created. This can speed you up.

Personally I use both methods. I use the functions where I need the most speed. I use the operators in complicated calculations because they''re easier to read (and thus to debug).
quote:

Secondly: see how in the above class it uses an array to store the x, y, z values...what are the differences between using an array as opposed to having a seperate float for each value?


I use both by using unions. Here''s how:

union float3
{
struct
{
union {float x; float r; float t};
union {float y; float g; float u};
union {float z; float b; float v};
}
float v[3];
}

And I have overloaded the [] operator to point to v[] so I can acces my vector like:

float3 myVec;
//as array
myVec[0]=1.0f; myVec[1]=2.0f; myVec[2]=3.0f;
//as position vector
myVec.x=1.0f; myVec.y=2.0f; myVec.z=3.0f;
//as color
myVec.r=1.0f; myVec.g=2.0f; myVec.b=3.0f;
//as texture coords
myVec.t=1.0f; myVec.u=2.0f; myVec.v=3.0f;


Sander Maréchal
[Lone Wolves Game Development][RoboBlast][Articles][GD Emporium][Webdesign][E-mail]


GSACP: GameDev Society Against Crap Posting
To join: Put these lines in your signature and don''t post crap!

Share this post


Link to post
Share on other sites
quote:
Original post by UltimaX
Nothing because you can use an array with "seperate" floats. Heres what I mean:

//--In the class you would have X, Y, and Z.
//--
//--In class
//--
float &operator[](unsigned int ID);
const float &operator [] (unsigned int ID) const;
//--
//--In .cpp (Or where ever)
//--
float &operator[](unsigned int ID)
{
return *(&X + ID);
}
//
const float &operator [] (unsigned int ID) const
{
return *(&X + ID);
}
[/source]
Then you can access the values like a normal array.
Vector.X would now be the same as Vector[0].


Sorry, but this is non-portable code. The standard doesn''t state that the storage for class data members is guaranteed to be contiguous, and there are other important issues (padding, etc.).
quote:
Original post by Sander
Operator overloading can be slower than functions. That is because of the way the compiler produces the ASM code. With operator overloading, the ASM needs to make some temporary storage space to hold the result''s values before passing the it to another variable. When you use functions you can pass everything by reference and thus no temp storage is created. This can speed you up.


An overloaded operator will be exactly the same as a normal member function. I think that what you are talking about is the return value, but this is the same for both. Anyway, for this (I think) there is something called return value optimisation. For example, with an addition operator like this:

T operator+( const T& lhs, const T& rhs );

the compiler should be able to recognise this and rewrite the function internally to this:

void operator+( T& result, const T& lhs, const T& rhs );

and directly compute into result. The function call is also internally transformed. For example, this:

T a, b, c;
a = b + c;

becomes transformed internally to this:

operator+(a, b, c);

It is not widely implemented, and there are side effects, though.

Just use the compound assignment operators, i.e. +=, -=, %=, >>=, etc.

[ Google || Start Here || ACCU || STL || Boost || MSDN || GotW || MSVC++ Library Fixes || BarrysWorld || E-Mail Me ]

Share this post


Link to post
Share on other sites
quote:

Operator overloading can be slower than functions. That is because of the way the compiler produces the ASM code. With operator overloading, the ASM needs to make some temporary storage space to hold the result's values before passing the it to another variable. When you use functions you can pass everything by reference and thus no temp storage is created. This can speed you up.



You can even pass everything by reference when you use operator overloading.


struct vec
{
float x, y, z;
vec& operator = ( const vec& v )
{
x = v.x; y = v.y; z = v.y;
return *this;
}
};



When you use an operator, the compiler actually replaces it with a function call. when you do something like v1 = v2 the compiler would exchange that for v1.operator =( v2 ); which is technically the same as doing something like v1.Copy( v2 );

[edited by - Ali F on August 19, 2003 9:47:37 AM]

Share this post


Link to post
Share on other sites
There''s one advantage about using float[] over seperate floats if you''re using OpenGL. You can make your class return a const float* to your float[] (via member function or operator overloading) and then pass your vector directly to glVertex3fv for example:

glVertex3fv(myVector.toVertex());

If you''re convenient with operator overloading you can also do the following (no idea if it''s standard or a VC++ thing again);


Vector3D
{
private:
...
float magnitude[4]; // Note: I use four for safety since OpenGL also offers glVertex4fv!!!


public:
...
operator const float* (void)const;
};

Vector3D::operator const float* (void)const
{
return (magnitude);
}

Note that magnitude is four(!) floats, to make the vector compatible with all glVertex functions (2-4fv). With this operator the compiler will be able to convert your Vector to a const float* whenever needed. You implicitly gain a [] operator, but without boundary checking!

Share this post


Link to post
Share on other sites
The advantage of a float array member is that you can provide an overloaded subscript operator for your class, whereas I wouldn''t recommend what UltimaX does (see my second post on this thread).

Wildfire: Do you realise the implications of implicit conversion operators? They are generally not worth it.

[ Google || Start Here || ACCU || STL || Boost || MSDN || GotW || MSVC++ Library Fixes || BarrysWorld || E-Mail Me ]

Share this post


Link to post
Share on other sites
quote:

Sorry, but this is non-portable code. The standard doesn't state that the storage for class data members is guaranteed to be contiguous, and there are other important issues (padding, etc.).


I don't remember saying that it was portable.

quote:

The advantage of a float array member is that you can provide an overloaded subscript operator for your class, whereas I wouldn't recommend what UltimaX does (see my second post on this thread).


Look at my vector class, do you see them 2 overloaded operators in there? NO! I don't use them, I was just showing them for an example, so why don't you just lay off a little bit!

BTW:
It's the same way the matrix library does for the Game Programming Gems series. Isn't most of that code portable? If those operators were not portable why would they put them in there?

-UltimaX-

"You wished for a white christmas... Now go shovel your wishes!"

[edited by - UltimaX on August 19, 2003 10:52:24 AM]

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!