Menu

Draw wire between two invisible objects

Help
M.a.
2021-05-10
2021-05-11
  • M.a.

    M.a. - 2021-05-10

    Hi,
    I have several invisible object ( such as TGLsphere) as connection points and I want to pick these objects and draw wires ( such as wire example )
    How can I do that?

     
  • shine world

    shine world - 2021-05-10

    To draw wires (lines) just Show object at runtime and change object material polygon mode with what you want (TGLPolygonMode = (pmFill, pmLines, pmPoints))

            OBJ.Material.Material.PolygonMode := <polygon_mode>;
    
     
  • M.a.

    M.a. - 2021-05-10

    hi shine , I have 2 freeform such as electrical device , I defined 2 point by two sphere for connection point but these spheres are invisible , I want to connect line (as wire) between two free form connection point at runtime bye mouse. how detect the position of that sphere for add line node?

     
  • shine world

    shine world - 2021-05-11

    Actually there are two ways, that I know, to detect a picked object:

    • Picked Object By Raycast
    • GLSceneViewer.Buffer.GetPicketObject (use a mask on surfaces draw to detect object).

    In below code I'm looking for TFreeForm object in pick search but you can change to other types.

    procedure TGLSceneFrame.GLSceneViewerMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    var
      PickedObject: TGLBaseSceneObject;
    
    // TODO: To complete, seem inacurate and slow!!!
    {$IFDEF EXPERIMENAL_RAY_CAST}
      function GetPickedObjectRayCast(const Root: TGLBaseSceneObject; X, Y: Integer): TGLBaseSceneObject;
      var
        T: Integer;
        Dist: Single;
        IPoint: TVector;
        INormal: TVector;
        RayStart: TVector;
        RayVector: TVector;
        HasRayCast: Boolean;
      begin
        Result := nil;
        SetVector(RayStart, GLSceneViewer.Camera.AbsolutePosition);
        SetVector(RayVector, GLSceneViewer.Buffer.ScreenToVector(AffineVectorMake(X, GLSceneViewer.Height - Y, 0)));
        NormalizeVector(RayVector);
        for T := 0 to Root.Count - 1 do
        begin
          if not (Root[T] is TGLFreeForm) then Continue;
          if Root[T].Visible then
          begin
            HasRayCast := Root[T].RayCastIntersect(RayStart, RayVector, @IPoint, @INormal);
            if HasRayCast and (VectorDotProduct(RayVector, INormal) < 0) then
            begin
              Dist := VectorLength(VectorSubtract(IPoint, RayStart));
              Result := Root[T];
              Exit;
            end;
          end;
        end;
      end;
    {$ENDIF}
    
    begin
      // stores mouse coordinates when a button went down
      FMDX := X;
      FMDY := Y;
    
      // checks if left mouse and control key pressed
      if Shift = [ssCtrl, ssLeft] then
      begin
        PickedObject := GLSceneViewer.Buffer.GetPickedObject(X, Y);
        if PickedObject is TGLFreeForm then
        begin
    {$IFDEF EXPERIMENAL_RAY_CAST}
          // define selected object in the virtual machine manager
          FVMManager.PickedPart := TGLFreeForm(GetPickedObjectRayCast(VMManager.MachineFParts, X, Y));
    {$ELSE}
          // define selected object in the virtual machine manager
          FVMManager.PickedPart := TGLFreeForm(PickedObject);
    {$ENDIF}
        end
        else
          FVMManager.PickedPart := nil;
      end;
    
      // sets screen cursor to meet active operation
      if ssRight in Shift then
        Screen.Cursor := crOpacityPan
      else if (ssLeft in Shift) and not (ssCtrl in Shift) then
        Screen.Cursor := crOpacityOrbit;
    end;
    

    I don't know if this can work for you.
    It required a visible object to detect if picked.

    A little video about how works:
    https://youtu.be/fmwr5SVt__Q

     

    Last edit: shine world 2021-05-11

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.