PDA

View Full Version : Vector Reflection - Still having problems



jdarling
11-09-2009, 02:37 PM
Due to real life and work I haven't had much time to look at or even think about my entry for this years competition. WILL spurred me a bit about it and I decided I'd at least try and get something done in the few minutes I have here and there. Problem is, I still haven't managed to get segment->segment reflection working within the system.

Basic problem, a point moving from one frame to another frame creates a collision with a ray (tested using segment intersection tests). Using the previous point to the current point to create a segment and then testing against the current segment I can easily find when and where the intersection happened. Now I need to create a reflection of the segment for the point so I can re-calculate the previous and current positions of the point.

I've tried a lot of different things and none seem to work. I'm convinced its me and not the examples I've read up on, but I just don't have time to fix it. If ANYONE can take a look at the attached download in the test/reflection folder there is a simple demo. Click and move the mouse to move the points. Green line is the moving point line, blue line is the "reflection plane", the red line is the "calculated reflection", and the black circle is the intersection point. The red line should bisect the black dot and blue line and be a proper reflection of the green line (currently isn't). Any help on getting this fixed would be greatly appreciated, if I can get it working in the test I know I can fix the actual Verlet system.

Download source at: http://www.eonclash.com/PGD/Verlet2.zip

- Jeremy

Andreaz
11-09-2009, 03:15 PM
It sounds like it is a vector reflect thing you need:

Vect1 is the direction of the ball before hitting the wall
Vect2 is after the wall
WallN is the normal of the wall
DOT is the dot product

Vect2 = Vect1 - 2 * WallN * (WallN DOT Vect1)

Here is the code in 2D ripped directly from my Phoenix Math Lib ;)



// Vector reflection, V is the vector to reflect, N is the wall normal
Function VectorReflect(const V, N: TVector2f ): TVector2f;
var d: Single;
begin
d:= VectorDot(N, V);

Result.X:= V.X - 2 * N.X * d;
Result.Y:= V.Y - 2 * N.Y * d;
end;

jdarling
11-09-2009, 03:59 PM
Funny thing Andreaz, I saw that EXACT same post on GameDev, didn't help :(. I've tried several different iterations of the same formula (when I had time), no avail :(. I know I'm the problem, I just don't know why I'm the problem LOL.

I'm guessing its how I'm calculating the "wall normal" I'm using L.Seg.Normal (Seg is P2-P1) is this the wrong thing to do?

Here is my code for reflection within a vector:
function TVector.ReflectAbout(aNormal: IVector): IVector;
var
d : TVectorNumber;
//s, n : IVector;
begin
d := Dot(aNormal);
result := self - 2 * aNormal * d;
(*
s := Normal;
n := aNormal.Direction;
result := 2 * n.Dot(self) * normal - self;
//result := n * (2 * s.dot(n)) - s;
*)
end;

And how I'm calling it:

// L1 - Blue = Collision Line
// L2 - Green = Point falling
// RL - Red = Reflected Line
IP := SegmentIntersection2D(L1.P1, L1.P2, L2.P1, L2.P2);
if(IP<>nil)then
begin
n := L1.seg;
RL.P1 := L2.P1.ReflectAbout(n);
RL.P2 := L2.P2.ReflectAbout(n);
end;

grudzio
11-09-2009, 10:00 PM
I'm guessing its how I'm calculating the "wall normal" I'm using L.Seg.Normal (Seg is P2-P1) is this the wrong thing to do?
Yes, the formula for a normal vector is incorrect. The normal vector is a vector of length one which is perpendicular to the object it is calculated for (line in your case).

A function for finding a normal vector for a segment in 2D can be like this

//finds a normal vector to a segment
function NormalVector(seg : TVector) : TVector;
begin
//find vector perpendicular to seg
Result.x := - seg.y;
Result.y := seg.x;
//normalize
Result := Normalize(Result);
end;

You should also change some code in your test application to correctly display the results.
This is how I have changed the "reflection" part of FormPaint method in Reflect demo.

...
RL:= TVLine.Create;
try
IP := SegmentIntersection2D(L1.P1, L1.P2, L2.P1, L2.P2);
if(IP<>nil)then
begin
//n and len are declared in var section as m : TVector; len : TVectorNumber;
//a normal vector to a segment
n := TVector.Create;
n.X := -l1.seg.Y;
n.Y := L1.seg.X;
//I had to normalize vector "manually" cause I had some problems (segfaults)
//when mixing IVector and TVector
len := n.Length;
n.X := n.X / len;
n.Y := n.Y / Len;
//find a vector to reflect. It is a vector from object position (l2.P1) to incidence point (ip)
s := ip - l2.P1;
//find reflection vector
r := s.ReflectAbout(n);
//and normalize it
r := r.Normal;
//line showing the reflected vector
rl.P1 := ip;
rl.P2 := rl.P1 + 40*r; //I multiplied r by forty to make line long enough to be visible

plotLine(RL, clRed);
plotVector(IP, clBlack);
end;
finally
RL.Free;
...

Hopefully, this should solve your problem.

jdarling
14-09-2009, 03:49 PM
Awsome thanks greatly Grudzio, that gave me enough of a pointer for me understand what I was doing wrong. Now I have that fixed and it looks like reflection is working great. Had to make a few minor changes to get the proper lastpos and pos, but that was easy to figure out.

Now its on to expanding the search for collision to contain the size of the point to the size of the constraint (IOW thicken up the lines that are tested).