Collision response mirrored reflection

Started by
6 comments, last by jamwaffles 13 years, 9 months ago
Hi all.

I've managed to get collision detection and rotation working, and am now working on collision response. I have got a small demo working which has a triangle and a line. The line represents the motion of a point at the current frame, and the frame after (the vertex's direction and speed). I am using the algorithm from the NeHe tutorial, which is as follows

R = 2 * (-I dot N) * N + I

Now I'm pretty sure I've implemented this maths properly, first in a literal interpretation of the algorithm:

R.x = 2 * innerProduct(negLineVec, N) * N.x + lineVec.x;

And also adapting the code given on the website:

R.x = N.x * (2 * innerProduct(N, negLineVec)) + lineVec.x;

Both of these give the same result: a reflection vector. The problem is, this reflection vector is on the wrong side of the face. The normal of the face points towards the side the original line is coming from.

What am I doing wrong?

Thanks for reading,

James
http://www.jamwaffles.co.uk - my site - new look, faster loading, free wallpapers, tutorials and other pointless crap.
Advertisement
When you write R.x and so one you mean the components of vector R.
Did you just use them as an example or did you really just calculate the
x component of vector R?
The two equations you gave are exactly the same just some more brackets.

Say you got 2 dimensional vectors you have to calculate x and y the same way:
R.x = 2 * innerProduct(negLineVec, N) * N.x + lineVec.x;R.y = 2 * innerProduct(negLineVec, N) * N.y + lineVec.y;


By the way, it would be more efficient to negate the scalar instead of a vector
because negating a vector means n negations where n is the vector's dimension.
What I mean looks like this:
R.x = lineVec.x - 2 * innerProduct(lineVec, N) * N.x;
R.y = lineVec.y - 2 * innerProduct(lineVec, N) * N.y;
Thanks for the optimisation tip there - it will clear up some useless "turn into negative" code :)

As for R.x yes it is the X component of R. I only included one out of the 3 X Y Z axes as an example.

I'll give your new algorithmic layout a go and get back to you. Thanks for the help :)

James
http://www.jamwaffles.co.uk - my site - new look, faster loading, free wallpapers, tutorials and other pointless crap.
Ok. That didn't change much, probably because it wasn't supposed to :P

The code I have is as follows:

// Work out normal of plane		vector(edge1, plane1, plane2);		vector(edge2, plane3, plane2);		crossProduct(N, edge2, edge1);		Normalize(N);			// Find magnitude of vector		vector(lineVec, point, point2);			float magnitude = fastsqrt(lineVec.x * lineVec.x + lineVec.y * lineVec.y + lineVec.z * lineVec.z);		//cout << magnitude << endl;			Normalize(lineVec);		Vector negLineVec;		negLineVec.x = lineVec.x * -1;		negLineVec.y = lineVec.y * -1;		negLineVec.z = lineVec.z * -1;		//ArrayVel[BallNr]=TVector::unit( (normal*(2*normal.dot(-ArrayVel[BallNr]))) + ArrayVel[BallNr] );		/*R.x = 2 * innerProduct(negLineVec, N) * N.x + lineVec.x;		R.y = 2 * innerProduct(negLineVec, N) * N.y + lineVec.y;		R.z = 2 * innerProduct(negLineVec, N) * N.z + lineVec.z;*/				R.x = lineVec.x - 2 * innerProduct(lineVec, N) * N.x;		R.y = lineVec.y - 2 * innerProduct(lineVec, N) * N.y;		R.z = lineVec.z - 2 * innerProduct(lineVec, N) * N.z;				//Normalize(R);				R.x *= magnitude;		R.y *= magnitude;		R.z *= magnitude;			cout << R.x << ", " << R.y << ", " << R.z << endl;


Hopefully it's easy enough to understand :/

James
http://www.jamwaffles.co.uk - my site - new look, faster loading, free wallpapers, tutorials and other pointless crap.
The reflection calculation looks fine. I'd check if you really got the input you expect, namely:

- Do you calculate the normal correctly, i.e. do you take the triangle vertices in the right order (s. note at bottom)
- Do you calculate your lineVec correctly: How does vector(lineVec, point, point2) work ? It looks like a simple difference (a-b) operation but is point2 the end point or the start point ? Check that!

Anywhere you do that difference with (wrongly) swapped arguments, you get a sign flip in your result. Since you are using it three times you could actually have three flips :(

Setup a test where you know the answer or give us some real numbers. And if possible show us the code of crossProduct and vector.

As an aside: Does that library support operator overloading for vectors ? I always found it hard to code (and read) vector math with function calls, let alone component-wise calculations. Operator overloading could make your (arithmetic) life way easier.


Edit: Sorry for the confusion: the direction of the normal is irrelevant in this case. Your problem must lie in the input.
Sorry to be all vague and stuff

Yeah - the vector() and crossProduct() code is as follows:

#define crossProduct(a,b,c) 	(a).x = (b).y * (c).z - (c).y * (b).z; 	(a).y = (b).z * (c).x - (c).z * (b).x; 	(a).z = (b).x * (c).y - (c).x * (b).y;/* a = b - c */#define vector(a,b,c) 	(a).x = (b).x - (c).x;		(a).y = (b).y - (c).y;		(a).z = (b).z - (c).z;


As for your operator overloading comment, yes I will definitely look into this - I hate having to do things thrice! Still, this is a very early development project so it doesn't matter too much.

For point and point2, point2 is the end of the line and point is the beginning.

On a side note: the reflected vector is not quite at 90 degrees, which is no huge issue right now and is probably down to me using a fast square root function off wikipedia.
I'll try and post more info some other time - I'm kind of in a rush. Sorry.

James
http://www.jamwaffles.co.uk - my site - new look, faster loading, free wallpapers, tutorials and other pointless crap.
Quote:For point and point2, point2 is the end of the line and point is the beginning.


Bullseye. In vector notation your vector(a,b,c) does this
a = b - c

so
lineVec = point - point2


Now take a look here : Vector Subtraction.

You got it the wrong way, "point" is the end of your line.

By the way: I think you do an unecessary calculation here. You first get the length of your line (magnitude), normalize the line, reflect it and then scale to the original length again. This is not necessary, the reflection will return the same length (well, if N is normalized, which it is).

Maybe that fast calculation has issues, at least I'd check. Or leave it entirely. If your compiler's fine: modern CPU's can handle square-roots easily, so maybe it isn't faster at all.
Ahh thank you so much for that - changing the points around was perfect.

As for the fastsqrt, it seems accurate enough and I think I'll leave it as it is for the time being - it will give me more CPU to play with but thanks for your info on modern CPUs :)

Thanks for your time and help :)

James
http://www.jamwaffles.co.uk - my site - new look, faster loading, free wallpapers, tutorials and other pointless crap.

This topic is closed to new replies.

Advertisement