Menu ▾ ▴

TGLPipe.RayCastIntersect not implemented

lnebel
2022-05-10
2022-05-11
  • lnebel

    lnebel - 2022-05-10

    Hi all,

    I have been trying to do a raycastintersect on TGLPipe objects, but just realized that RayCastIntersect has not been implemented for TGLPipe. From what I can see in implementations for other objects, implementing RayCastIntersect is not trivial. So, is there another way to do this?

    TGLFeedback could possibly be used to extract the triangles for the pipe object, and then do the ray cast as in TGLBaseMesh.RayCastIntersect. However, TGLFeedback renders all visible objects in the whole scene, whereas I only want the triangles for a single pipe.

    Any ideas?

    Lars Nebel

     
  • Pavel Vassiliev

    Pavel Vassiliev - 2022-05-10

    Hi Lars,
    Hm, the TGLPipe is inherited from ..TGLBaseSceneObject and RayCastIntersect method implemented there in public section and should work, but may be you need to override it for TGLPolygonBase class in GLS.Objects unit as for TGLSphere e.g.
    Pavel Vassiliev

     

    Last edit: Pavel Vassiliev 2022-05-10
    • lnebel

      lnebel - 2022-05-11

      Hi Pavel,

      Yes, RayCastIntersect is implemented in TGLBaseSceneObject and is called, but it does not work for TGLPipe because the BoundingSphereRadius is only a default one unit radius which does not reflect the shape of the actual pipe. As I understand it, RayCastIntersect must be implemented for each object class so that all the triangles in the object can be tested for intersect, similar to TGLCylinder.RayCastIntersect. This seems to be a really complicated task for TGLPipe and over my head at this point, but you can note it as something missing in the code.

      This topic from 2019 is related, although it is about bounding extents and not actual intersect:

      https://sourceforge.net/p/glscene/discussion/Help/thread/c450cf02a9/?limit=25#9e9d

      For now, I have made a simple workaround method which uses the line segment positions and radii instead of the actual triangles. This is of course not accurate, but good enough for me at this point.

      //Approximated RayCastIntersect method for TGLipe

      //Becomes obsolete if TGLPipe.RayCastIntersect is implemented properly

      function RayCastIntersectPipe(AX, AY: Integer; AHeight: Integer; APipe: TGLPipe): Boolean;

      var

      RayStart     : TGLVector;
      
      RayVector    : TGLVector;
      
      PointVector  : TGLVector;
      
      NormalVector : TGLVector;
      
      I            : Integer;
      
      Node0              : TGLPipeNode;
      
      Node1        : TGLPipeNode;
      
      S0Start      : TVector3f;
      
      S0Stop       : TVector3f;
      
      S1Start      : TVector3f;
      
      S1Stop       : TVector3f;
      
      Closest0     : TVector3f;
      
      Closest1     : TVector3f;
      
      Radius       : Double;
      
      Dist        : Double;
      

      begin

      Result := False;
      
      
      
      //RayCast vector
      
      SetVector(Raystart,  Glsceneviewer.Camera.Absoluteposition);
      
      SetVector(Rayvector, Glsceneviewer.Buffer.ScreenToVector(AffineVectorMake(AX, AHeight - AX, 0)));
      
      NormalizeVector(RayVector);
      
      ScaleVector(RayVector, 100000);
      
      
      
      //Ray cast segment, S0 (long segment from screen into scene)
      
      S0Start.X := RayStart.X;
      
      S0Start.Y := RayStart.Y;
      
      S0Start.Z := RayStart.Z;
      
      S0Stop.X  := RayStart.X + RayVector.X;
      
      S0Stop.Y  := RayStart.Y + RayVector.Y;
      
      S0Stop.Z  := RayStart.Z + RayVector.Z;
      
      
      
      //Loop pipe segments
      
      for I := 0 to APipe.Nodes.Count - 2 do begin
      
        Node0  := TGLPipeNode(APipe.Nodes[I    ]);
      
        Node1  := TGLPipeNode(APipe.Nodes[I + 1]);
      
        Radius := (Node0.RadiusFactor + Node1.RadiusFactor) / 2;
      
      
      
        //Line segment between two nodes, S0
      
        S1Start.X := Node0.X;
      
        S1Start.Y := Node0.Y;
      
        S1Start.Z := Node0.Z;
      
        S1Stop.X  := Node1.X;
      
        S1Stop.Y  := Node1.Y;
      
        S1Stop.Z  := Node1.Z;
      
      
      
        //Test distance between ray cast vector and line segment
      
        Dist := SegmentSegmentDistance(S0Start, S0Stop, S1Start, S1Stop);
      
        if Dist < Radius then begin
      
          SegmentSegmentClosestPoint(S0Start, S0Stop, S1Start, S1Stop, Closest0, Closest1);
      
          GLX    := Closest0.X;
      
          GLY    := Closest0.Y;
      
          GLZ    := Closest0.Z;
      
          Result := True;
      
          Exit;
      
        end;
      
      
      
      end;
      

      end;

      \Lars

      From: Pavel Vassiliev vassiliev@users.sourceforge.net
      Sent: Tuesday, 10 May 2022 17.10
      To: [glscene:discussion] General@discussion.glscene.p.re.sourceforge.net
      Subject: [glscene:discussion] TGLPipe.RayCastIntersect not implemented

      Hi Lars,
      Hm, the TGLPipe is inherited from ..TGLBaseSceneObject and RayCastIntersect method implemented there in public section and should work, but may be you need to override it for TGLPolygonBase class in GLS.Object unit as for TGLSphere e.g.
      Pavel Vassiliev


      TGLPipe.RayCastIntersect not implemented https://sourceforge.net/p/glscene/discussion/General/thread/d4f985499f/?limit=25#a3e9


      Sent from sourceforge.net because you indicated interest in https://sourceforge.net/p/glscene/discussion/General/

      To unsubscribe from further messages, please visit https://sourceforge.net/auth/subscriptions/

       

Log in to post a comment.