Archived

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

Programmer16

New to vectors, will this work correcty?

Recommended Posts

I'm making a vector class and was wondering if my basic vector mathematics was right: The class declaration
class DFVector
{
public:
	float x, y, z;

	DFVector();
	DFVector(float X, float Y, float Z);
	DFVector(char cOperator, DFVector* vVector1, DFVector* vVector2); // this = vVector1 - vVector2

	~DFVector();
	D3DXVECTOR3 operator ()();
	void operator =(DFVector pNewVector);
	void operator +=(DFVector pPlusVector);
	void operator -=(DFVector pMinusVector);
	void operator ++();
	void operator --();

};
And the definition
  
DFVector::DFVector()
{
	x = y = z = 0.0f;
}

DFVector::DFVector(float X, float Y, float Z)
{
	x = X;
	y = Y;
	z = Z;
}

DFVector::DFVector(char cOperator, DFVector* vVector1, DFVector* vVector2) // this = vVector1 - vVector2

{
	switch(cOperator)
	{
	case '+':
		{
			x = vVector1->x + vVector2->x;
			y = vVector1->y + vVector2->y;
			z = vVector1->z + vVector2->z;
		}

	case '-':
		{
			x = vVector1->x - vVector2->x;
			y = vVector1->y - vVector2->y;
			z = vVector1->z - vVector2->z;
		}

	case '*':
		{
			x = vVector1->x * vVector2->x;
			y = vVector1->y * vVector2->y;
			z = vVector1->z * vVector2->z;
		}

	case '/':
		{
			x = vVector1->x / vVector2->x;
			y = vVector1->y / vVector2->y;
			z = vVector1->z / vVector2->z;
		}
	}
}

DFVector::~DFVector()
{
}

D3DXVECTOR3 DFVector::operator ()()
{
	return D3DXVECTOR3(x, y, z);
}

void DFVector::operator =(DFVector pNewVector)
{
	x = pNewVector.x;
	y = pNewVector.y;
	z = pNewVector.z;
}

void DFVector::operator +=(DFVector pPlusVector)
{
	x += pPlusVector.x;
	y += pPlusVector.y;
	z += pPlusVector.z;
}

void DFVector::operator -=(DFVector pMinusVector)
{
	x = pMinusVector.x;
	y = pMinusVector.y;
	z = pMinusVector.z;
}

void DFVector::operator ++()
{
	x += 0.01f;
	y += 0.01f;
	z += 0.01f;
}

void DFVector::operator --()
{
	x -= 0.01f;
	y -= 0.01f;
	z -= 0.01f;
}
Thanks for any advice! /* I use DirectX 8.1 and C++ (Microsoft Visual C++ 6.0 Professional edition) */ [edited by - Programmer16 on March 20, 2004 10:47:13 PM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
dude, read some vector faq operator++ for vectors ? gosh. and try to use some const references...
and... where''s the vector math ? dot ? cross ?
oh... dont try to do your own vector math if ya have no idea how to cuz the d3dx can do it much faster than ya.
sorry for being rude - couldnt hold myself :>

Share this post


Link to post
Share on other sites
I said basic vector mathematics; dot and cross multiplication aren't basic vector math. I'm not using D3DX because I'm trying to learn vector math and you learn better by doing than by reading. I just added the ++ operator for something that I'm doing that needs to increase and decrease in all directions at once. And, what the difference make in using a const reference? I'm programming it so I know when I should/shouldn't modify code and when I'm supposed.

I'm testing it now, and its not working correctly for some reason:

DFVector g_dfVector(7,3,9);
DFVector g_dfVector2(2,6,5);
DFVector g_dfVector3('+', &g_dfVector, &g_dfVector2);

And then I print it to my log, and I get this:
g_dfVector g_dfVector2 g_dfVector3
X: 7.000000 - 2.000000 = 3.500000
Y: 3.000000 - 6.000000 = 0.500000
Z: 9.000000 - 5.000000 = 1.800000

Thanks for your help.

/*
I use DirectX 8.1 and C++ (Microsoft Visual C++ 6.0 Professional edition)
*/

[edited by - Programmer16 on March 20, 2004 11:15:00 PM]

Share this post


Link to post
Share on other sites
I must admit that I haven''t looked the code completely through ... but if you would have tried it out it either doesn''t compile at all or you''ll get strange artefacts when testing it.

Two things I noticed:

the switch()-statement completely misses the "break;"s. even though you make nice blocks, the code won''t give you the results you want.
but after all, you might want to reconsider this system ... really no offense, maybe you do need it for some reason i can''t imagine, but i would design that without that switch statement (and passing the operation as char-parameter is something i wouldn''t do either), but never mind, i don''t know what you''re going to do with that...

Operator += (and similar) with a void type? If it even compiles ... I don''t know what you''re planning to do with that. Better check out a tutorial on operator overloading...

Oh yeah and the ++ / -- operators are really pointless in vector math (especially what you are doing with them ... the length of a vector is calculated by the sqrt of the sum of the squares of each component within the vector. i.e. sqrt(x*x+y*y+z*z). and if you intended to ++ the length of the vector, you''ll see that this won''t work...)

Hope it helped you a little!


Indeterminatus

--si tacuisses, philosophus mansisses--

Share this post


Link to post
Share on other sites
quote:

And then I print it to my log, and I get this:
g_dfVector g_dfVector2 g_dfVector3
X: 7.000000 - 2.000000 = 3.500000
Y: 3.000000 - 6.000000 = 0.500000
Z: 9.000000 - 5.000000 = 1.800000



THIS results from the the missing breaks. No matter what you do, you''ll always get the division (last case in the switch-statement). just add a "break;" at the end of each case-block and at least this should work out the way you want it.

But still - you should work on the operators, since they are pointless without return value...



Indeterminatus

--si tacuisses, philosophus mansisses--

Share this post


Link to post
Share on other sites
Ok, nevermind. I wasn't asking for advice on the class, I was asking for advice on the math since this is the math and physics forum.

The increment and decrement operators are for my current project and are for moving. Why do say my operators won't work? If I add g_dfVector3 += g_dfVector; It prints out 12,0,13 which is correct (7-2+7, 3-6+3, 9-5+9). Whats wrong with my overloaded constructor that uses the char? It I can instantly create a vector that is the result of any of the 4 basic operations without having four different functions.

/*
I use DirectX 8.1 and C++ (Microsoft Visual C++ 6.0 Professional edition)
*/

[edited by - Programmer16 on March 20, 2004 11:36:26 PM]

Share this post


Link to post
Share on other sites
quote:
Original post by Programmer16
I said basic vector mathematics; dot and cross multiplication aren''t basic vector math. I''m not using D3DX because I''m trying to learn vector math and you learn better by doing than by reading.


However, you need to read how to do things before you implement them. Dot and cross products are a fundamental part of vector mathematics. Go learn them. Now.

You have to remember that you''re unique, just like everybody else.

Share this post


Link to post
Share on other sites
I''m going to learn Dot and Cross, but I don''t know what they''re used for, so I''m just using basic operations in my current project.

/*
I use DirectX 8.1 and C++ (Microsoft Visual C++ 6.0 Professional edition)
*/

Share this post


Link to post
Share on other sites
Programmer16, you''re right, this is the math&physics forum. But even though you haven''t explicitly asked for it, I thought I should tell you that your code was buggy ... which will result in wrong results, speaking in mathematical terms. Never mind. And as for the operators: Don''t know where exactly it is (and frankly speaking I''m too lazy to look it up right now) specified, but it is somewhere in the c-standard that operators should return the result of the operation rather than void (which will allow for consistent usage of your code ... don''t forget that C/C++ is expression-based!)
And if they returned void, things like a = b = c = 10.0f; wouldn''t be possible.

Enough for today, now I really gotta go to bed ... nearly sunrise ... darn ... *fg* ...


Indeterminatus

--si tacuisses, philosophus mansisses--

Share this post


Link to post
Share on other sites
One word: DUH. I know my code is buggy. I'm trying to learn vectors and if I just use Direct3DX stuff I won't get anywhere. I haven't gotten anywhere actually. I didn't think about the situation that you pointed out about the operator. Would it be better to do this:
DFVector operator=(DFVector vVector)
{
x = vVector.x;
y = vVector.y;
z = vVector.z;
return (*this);
}
Thanks.
Sorry for getting pissy, I haven't slept in 26 hours.

/*
I use DirectX 8.1 and C++ (Microsoft Visual C++ 6.0 Professional edition)
*/

[edited by - Programmer16 on March 20, 2004 11:59:16 PM]

Share this post


Link to post
Share on other sites
Never mind, I haven''t slept for quite a time myself . But I''ll do, soon, but thought to reply to your last post at first (but this _definitely_ will be the last one for today ... since here the sun already starts to rise again ... )

As far as I''m concerned, I''ve learned most things by trying things out, but that''s not the topic here...

The operator looks WAYS better now ... the only (really last!) thing I would change about it was to return( *this ) except return this. Erm. Erm. Erm. Now I''m really going to bed.

Night!



Indeterminatus

--si tacuisses, philosophus mansisses--

Share this post


Link to post
Share on other sites
Yeah, I figured that out after I tested it. I also added a *= and /= operator. Thanks for all your help.

/*
I use DirectX 8.1 and C++ (Microsoft Visual C++ 6.0 Professional edition)
*/

Share this post


Link to post
Share on other sites
One thing about your operator=() functions is that it''s returning by value. operator=() should generally return by reference. For one, it saves on spurious temporaries, and two it allows certain syntactic constructs to work properly.

Also operator-=() doesn''t look like it''s doing the right thing.

Share this post


Link to post
Share on other sites
Yeah, I fixed my -= operator. I''m not sure what you mean about the = operator, but is this it:

DFVector* DFVector::operator =(DFVector pNewVector)
{
x = pNewVector.x;
y = pNewVector.y;
z = pNewVector.z;
return this;
}
// or this?

DFVector DFVector::operator =(const DFVector& pNewVector)
{
x = pNewVector.x;
y = pNewVector.y;
z = pNewVector.z;
return (*this);
}
// or both?



/*
I use DirectX 8.1 and C++ (Microsoft Visual C++ 6.0 Professional edition)
*/

Share this post


Link to post
Share on other sites
Vectors...

That was some harsh replies up top.

Here is what you need to know and have:
Dot Product -> http://mathworld.wolfram.com/DotProduct.html
Cross Product -> http://mathworld.wolfram.com/CrossProduct.html

double DFVector::DotProduct(const DFVector &v1) const {
double result;
result = x*v1.x + y*v1.y + z*v1.z;
return result;
}

DFVector DFVector::CrossProduct(const DFVector &v1) const {
DFVector vResult;
vResult.x = y*v1.z - z*v1.y;
vResult.y = x*v1.z - z*v1.x;
vResult.z = x*v1.y - y*v1.x;
return vResult;
}

What is not needed or is in Vector math is :
Vector multiplication/division. There is no such thing as multiplying or dividing 2 vectors. Instead it should be a vector multiplied/divided by a Scalar value.

DFVector DFVector::operator*(const double &s) const{
DFVector result( x*s, y*s, z*s );
return result;
}

DFVector DFVector::operator/(const double &s) const{
return this->operator*(1/s);
}

List of must include :
DotProduct, CrossProduct, Normalize, Magnitude

Things you might want to consider adding:
Vector Projection, Scalar Projection

If you have problems just go to http://mathworld.wolfram.com

Share this post


Link to post
Share on other sites
Returning a pointer from operator=() is an abomination. The standard function signature syntax for operator=() would be like:
DFVector & DFVector::operator=(const DFVector & rhs)

Having a plain DFVector return type means you''re return by value. In that case you create an extra copy of the DFVector object every time you use operator=().

Share this post


Link to post
Share on other sites
Use the second assignment operator...ALWAYS!!!
Why? Because it is more efficient.

You need to add more thing into your assignment operator.
You need to check if you are copying to the same location.

DFVector DFVector::operator=(const DFVector &v1) {
//Make sure it''s not the same object.
if( this != &v1 ) {
x = v1.x;
y = v1.y;
z = v1.z;
}

return *this;
}

Share this post


Link to post
Share on other sites
Alright, thanks. I haven''t added the * or / yet, just the *= and /=. Thanks for the links too!

/*
I use DirectX 8.1 and C++ (Microsoft Visual C++ 6.0 Professional edition)
*/

Share this post


Link to post
Share on other sites
Does it make any difference if you return a const reference instead of a non-const reference from the assignment operator? I return the former, just wondering if there's any reason to use the latter.
DFVector const& DFVector::operator = ( DFVector const& );  
as opposed to
DFVector& DFVector::operator = ( DFVector const& );  


edit: By the way Programmer16, if you're interested in why (const) references are better than returning temporaries, look up return value optimization (RVO). I found it a rather interesting read.

Also, to reduce copy-and-pasting code needlessly, you can make your binary operators simply call your assignment operators (not sure of correct terminology), like this:
DFVector operator / ( DFVector vec, float f ) {
DFVector temp( vec );
return temp /= f;
}


[edited by - psykr on March 21, 2004 1:18:48 AM]

Share this post


Link to post
Share on other sites
quote:
Original post by gspdriver
Use the second assignment operator...ALWAYS!!!
Why? Because it is more efficient.


Nope. See above comment about spurious temporary objects being constructed.

quote:

You need to add more thing into your assignment operator.
You need to check if you are copying to the same location.


Checking for self-assignment for a simple class like this is counter-productive. Self-assignment in a 3d vector class is unlikely to occur that frequently, so its likely waste cycles for evaluating the conditional. Not only that, but due to branch prediction, you''re likely going to cause a nice pipeline bubble even when you do skip the assignments, so you won''t gain a cycles. There''s also the fact that you''ll be polluting the branch prediction cache, causing other branch predicitons to be less accurate; thus reducing the overall performance of your application.

Share this post


Link to post
Share on other sites
quote:
Original post by psykr
Does it make any difference if you return a const reference instead of a non-const reference from the assignment operator?

Returning a non-const reference is usually preferred. In a few very limited situations you might want to return a non-const reference. (So limited, that I cannot in fact think of any situation where it would be better off the top of my head.)

Share this post


Link to post
Share on other sites
Hi again!

I just wanted to apologize for my misbehaviour. I was really tired and nearly brain-dead .

The links seem to be very good, I''m glad you''re working it out, programmer16 .

And don''t ever stop trying things out because of mean guys like me *fg*



Indeterminatus

--si tacuisses, philosophus mansisses--

Share this post


Link to post
Share on other sites
No problem (my behavior wasn''t that great either). I see why you said not to use the switch statement now. I got everything working fin for now. One question though, how come D3DXVECTOR3 doesn''t have an = operator (or does D3DXVECTOR have one)? Thanks for all your help guys!

/*
I use DirectX 8.1 and C++ (Microsoft Visual C++ 6.0 Professional edition)
*/

Share this post


Link to post
Share on other sites
D3DXVECTOR3 doesn''t explicitly define an assignment operator because the one that the compiler automatically generates is good enough.

Share this post


Link to post
Share on other sites