Thanks, hope you don't mind if i include this in nxPascal? It works great, see:
https://docs.google.com/file/d/0B7FI...RwQVFMWDg/edit
I temporarily modified the model demo to use TPolyModel class, and this change will not remain in the actual demo. Not best example though, because the model consists only of triangles. But because that function treats triangles and polygons same way, i don't doubt that it wouldn't work.
I had to make a few changes to adapt the code to nxPascal and parameters. Also made sure it's compilable on fpc and delphi:
Code:
// Credits to Dan (PascalGameDev forums)
function TPolyModel.RayPolyIntersect(const rayStart,
rayDirection: TVector; const vi: PWordArray; Count: integer;
BothSided: boolean; intersect: PVector;
intersectNormal: PVector): Boolean;
var d: Single; i: Integer;
Hit, nn, vx, vy: TVector;
pi, pj: PVector;
Hit2, pi2, pj2: TVector2f;
begin
Result:=False;
if Count<3 then Exit; //no need to proceed if we have less than 3 points.
vx:=Norm(VectorSub(va[vi[1]], va[vi[0]]));
nn:=Norm(CrossProduct(vx, VectorSub(va[vi[2]], va[vi[0]])));
// Exit if ray is coming from behind the triangle
if (not BothSided) and (Dot(nn, rayDirection)>0) then exit;
d:=RayPlaneIntersect(rayStart, rayDirection, va[vi[0]], nn,
intersect);
if d>=0 then Hit:=VectorAdd(rayStart, nxMath3D.Scale(rayDirection, d))
else Exit; // the ray is parallel to the polygons plane. quit
vy:=CrossProduct(nn, vx); // Don't need to norm(), length is 1
// vx and vy are the 2d space projection vectors.
Hit2:=Vector2f(Dot(vx, Hit), -Dot(vy, Hit));
// and that's how you project a point to 2d space
// and finally we're checking if the intersection point is inside the polygon.
pj:=@va[vi[Count - 1]];
pj2:=Vector2f(Dot(vx, pj^), -Dot(vy, pj^));
for i := 0 to Count - 1 do begin
pi := @va[vi[i]];
pi2:=Vector2f(Dot(vx, pi^), -Dot(vy, pi^));
if ( ((pi2.y<=Hit2.y) and (Hit2.y<pj2.y)) or
((pj2.y<=Hit2.y) and (Hit2.y<pi2.y)) ) and (
Hit2.x < (pj2.x-pi2.x)*(Hit2.y-pi2.y)/(pj2.y-pi2.y)+pi2.x
) then
Result:=not Result;
pj:=pi;
pj2:=Vector2f(Dot(vx, pj^), -Dot(vy, pj^));
end;
if intersectNormal<>nil then intersectNormal^:=nn;
end;
Bookmarks