
Hi everyone,
Is there an easy way to compute the deflection of a ray off a geometry surface using RayHelper? From what I see, it gives you just the intersection points, but not the polygon segment which was intersected, so I can see no way of getting at the normal to
use for computing deflection.
It would seem a common scenario for deflecting beams and whatnot.
Any ideas?
Looking forward to Farseer 3.0 :)
Keep up the good work!



With Farseer 3.0 you get the normal when casting a ray. In Farseer 2.1 I think it's not possible.



Thanks for the observation, Pnikosis.
Based on that I set out to compute my own normal. It turns out that LineSegmentGeomIntersect isn't awfully smart in computing intersections, it just iterates through all the line segments in the geometry and calls LineIntersect on the possible pairs,
like this:
for (int i = 0; i < vertices.Count; i++)
{
Vector2 point;
if (LineIntersect(vertices[i], vertices[vertices.NextIndex(i)],
point1, point2, true, true, _epsilon, out point))
{
intersectionPoints.Add(point);
}
}
So what we have to do is just perform this iteration ourselves and then just use Vector2.Reflect() to compute the deflection based on vertices[i] and vertices[vertices.NextIndex(i)].
In the meantime, I was getting extremely jittery behavior in the deflection, and I traced it down to the LineIntersect() method itself. I found out that although it receives a floatTolerance parameter as input, it doesn't use it anywhere in the body, falling
back instead to a constant _epsilon static variable declared inside RayHelper.
Worse still, it didn't use these floating point tolerance checks in all numeric tests inside the code, so LineIntersect() currently suffers from all sorts of rounding issues. I guess that it won't be updated since Farseer 3.0 is the next step, so here is
a quick patch for LineIntersect() if anyone else is experiencing rounding issues or overall strange intersection misses in Farseer 2.1.3:
public static bool LineIntersect(ref Vector2 point1, ref Vector2 point2, ref Vector2 point3, ref Vector2 point4,
bool firstIsSegment, bool secondIsSegment, float floatTolerance,
out Vector2 point)
{
point = new Vector2();
// these are reused later.
// each lettered subcalculation is used twice, except
// for b and d, which are used 3 times
float a = point4.Y  point3.Y;
float b = point2.X  point1.X;
float c = point4.X  point3.X;
float d = point2.Y  point1.Y;
// denominator to solution of linear system
float denom = (a * b)  (c * d);
// if denominator is 0, then lines are parallel
if (!(denom >= floatTolerance && denom <= floatTolerance))
{
float e = point1.Y  point3.Y;
float f = point1.X  point3.X;
float oneOverDenom = 1.0f / denom;
// numerator of first equation
float ua = (c * e)  (a * f);
ua *= oneOverDenom;
// check if intersection point of the two lines is on line segment 1
if (!firstIsSegment  ua >= floatTolerance && ua <= 1.0f + floatTolerance)
{
// numerator of second equation
float ub = (b * e)  (d * f);
ub *= oneOverDenom;
// check if intersection point of the two lines is on line segment 2
// means the line segments intersect, since we know it is on
// segment 1 as well.
if (!secondIsSegment  ub >= floatTolerance && ub <= 1.0f + floatTolerance)
{
// check if they are coincident (no collision in this case)
if ((ua < floatTolerance  ua > floatTolerance) &&
(ub < floatTolerance  ub > floatTolerance))
{
//There is an intersection
point.X = point1.X + ua * b;
point.Y = point1.Y + ua * d;
return true;
}
}
}
}
return false;
}
Hope this helps anybody. Deflection code is working like a charm now :)



Another approach that should work, is by casting two rays, one at the side of the other with very little distance between them. This way, by the distance on the collision points you can get the angle of the collisioned vertice.

