Results 1 to 10 of 14

Thread: Ray and convex polygon intersection

Threaded View

Previous Post Previous Post   Next Post Next Post
  1. #8
    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;
    Last edited by User137; 21-01-2013 at 12:53 PM. Reason: Optimized code

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •