Results 1 to 7 of 7

Thread: Screen to World Coordinates

  1. #1

    Screen to World Coordinates

    Hi.
    I have found code like this also under many C# C++ (and C-- ahh ahh)
    ---------------------------------------
    Code:
    function GetOpenGLPosFromMouse(X, Y: Integer): TGLVectord3;
    var
        viewport:   TGLVectori4;
        modelview:  TGLMatrixd4;
        projection: TGLMatrixd4;
        winZ,winY:  Single;
    begin
        glGetDoublev(GL_MODELVIEW_MATRIX, @modelview );   // Modelview
        glGetDoublev(GL_PROJECTION_MATRIX, @projection );    // Projection
        glGetIntegerv(GL_VIEWPORT, @viewport );                      // Viewport
    
      winY := viewport[3] - y;                                                 //Change from Win32 to OpenGL coordinate system
    
        glReadPixels(X, Round(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, @winZ );
        gluUnProject(X, winY, winZ,
                               modelview, projection, viewport,                             
                   @Result[0], @Result[1], @Result[2]);  
    end;
    ---------------------------------------
    But it doesn't work; in fact I tested with this
    ---------------------------------------------
    Code:
    OpenGLMousePosition:=GetOpenGLPosFromMouse(DelphiMousePosition.X,DelphiMousePosition.Y);
    
        glDisable(GL_DEPTH_TEST);
                 
        Main_Form.Caption:= 'Mouse Position is '+
                            'x..:'+IntToStr(DelphiMousePosition.X)+'  '+
                            'y..:'+IntToStr(DelphiMousePosition.y)+'  '+
                            '   OpenGl Mouse '+
                            'x..:'+FormatFloat('#,##0.0;-#,##0.0;0.0',OpenGLMousePosition[0])+'  '+
                            'y..:'+FormatFloat('#,##0.0;-#,##0.0;0.0',OpenGLMousePosition[1])+'  '+
                            'z..:'+FormatFloat('#,##0.0;-#,##0.0;0.0',OpenGLMousePosition[2])+'  ';
                            
        glColor3d(1.0,1.0,0.0);
        glLineWidth(3);
    
        glBegin(GL_LINES);
          glVertex3d( 0, 0, 0);
          glVertex3d( OpenGLMousePosition[0],OpenGLMousePosition[1],OpenGLMousePosition[2]);
        glEnd();
    ------------------------------------------------------------------------------------
    while moving the mouse the line goes somewhere else. Occasionally near (maybe about 40 pixels away) the mouse.

    Did someone already faced the headache ?

    JPG sample cannot be upload .... too large.
    I will be happy to send it.


    Giovanni.
    Italy.
    Last edited by WILL; 30-11-2010 at 04:29 PM. Reason: Please use code tags to post code...

  2. #2
    IIRC, the Red Book has an example about this. I'm sure it will be more useful as it explains "why".

    [edit] Didn't (re)read it but I think its in "Chapter 12 - Selection and Feedback"
    No signature provided yet.

  3. #3

    Thanks

    But, as far as I have read, this doesn't cope with my request.
    Else, please, be more precise.
    Thanks
    Giovanni

  4. #4
    Co-Founder / PGD Elder WILL's Avatar
    Join Date
    Apr 2003
    Location
    Canada
    Posts
    6,107
    Blog Entries
    25
    What is it that you are trying to do in plain language?

    For an interface, it's usually best to keep your mouse movement based on your screen's resolution while you World co-ordinates would be displayed using your own values multiplied by your 'zoom level' which would give you your world verses screen display calculation. You can then use this to calculate where your mouse is pointing in your world. This is of course easiest for a 2D world. If you want to know more about 3D worlds, then you'd have to consult someone else here who know more.
    Jason McMillen
    Pascal Game Development
    Co-Founder





  5. #5
    You didn't mention what you are trying to do, but when it comes to getting screen to world coordinates on various 3D objects or just 2D plane, this is what i do:
    1) Calculate mouse-ray that goes from mouse towards infinity. (You only need to do this once per frame tick)
    2) Calculate its collision point with a plane. Or calculate with each face of a 3D model.
    Good thing is that in the process you get information such as face normal in collision point and which face it hits.

    Then some code from Next3D:
    Code:
    procedure TNXGL.GetMouseRay(const mx, my: single; const p, normal: PVector;
      rayMove: single);
    var viewport: TGLVectori4;
        modelM,projM: TGLMatrixd4;
        x1,y1,z1,x2,y2,z2: double;
        n: TVector;
    begin
      glGetIntegerv(GL_VIEWPORT,@viewPort);
      glGetDoublev(GL_PROJECTION_MATRIX,@projM);
      glGetDoublev(GL_MODELVIEW_MATRIX,@modelM);
      {$HINTS OFF} // hints about x1..z2 not initialized
      gluUnProject(mx,my,modelM[2,3],modelM,projM,viewport,x1,y1,z1);
      gluUnProject(mx,my,modelM[2,3]-1,modelM,projM,viewport,x2,y2,z2);
      {$HINTS ON}
      n.x:=x1-x2; n.y:=y1-y2; n.z:=z1-z2; n:=Norm(n);
      if p<>nil then begin
        p^.x:=x1+n.x*rayMove;
        p^.y:=y1+n.y*rayMove;
        p^.z:=z1+n.z*rayMove;
      end;
      if normal<>nil then normal^:=n;
    end;
    
    // Result >= 0 if intersection happens
    function RayPlaneIntersect(const rayOrigin, rayDirection,
      planeOrigin, planeNormal: TVector; intersection: PVector): single;
    var d,numer,denom: single;
    begin
      d:=planeNormal.x*planeOrigin.x+planeNormal.y*planeOrigin.y+planeNormal.z*planeOrigin.z;
      numer:=-planeNormal.x*rayOrigin.x-planeNormal.y*rayOrigin.y-planeNormal.z*rayOrigin.z+d;
      denom:=planeNormal.x*rayDirection.x+planeNormal.y*rayDirection.y+planeNormal.z*rayDirection.z;
      if denom=0 then begin
        result:=-1; exit;
      end;
      result:=numer/denom;
      if intersection<>nil then begin
        intersection^.x:=rayOrigin.x+result*rayDirection.x;
        intersection^.y:=rayOrigin.y+result*rayDirection.y;
        intersection^.z:=rayOrigin.z+result*rayDirection.z;
      end;
    end;
    
    function TNXGL.MouseRayAtPlane(const mx,my: single; const planePos,planeNormal: TVector): TVector;
    var rayOrigin, rayDirection: TVector;
    begin
      GetMouseRay(mx,my,@rayOrigin,@rayDirection);
      rayPlaneIntersect(rayOrigin,rayDirection,planePos,planeNormal,@result);
    end;
    Last edited by User137; 30-11-2010 at 06:19 PM.

  6. #6

    Dear USER 137

    1st. Thank you very for sources. They are very hi tech. Your way to solve the problem is sure out of my (little) mind.

    2nd. I have a 3ds model of an airport. I have to send coords to planes in order to move themselves using mouse.
    Airport Y value is not request, because zero or very close.
    So, is there no a easyer way to have x,z (NO Y need) coordinates ?

    3rd. Please, if posibile, mail to info@brambo.it for a question.

    Thanks however.

    Giovanni

  7. #7
    You don't need to go private messaging because of this, what comes told may be useful to someone else later. So i'll answer here too...

    Firstly full source of my 3D engine and demos which include mouse-ray demo with 3D model are here: http://next3d.webs.com/

    The code itself is really copy-paste stuff. You don't need to deeply understand how it works, just what parameter are needed and result they give. This might explain a little more:
    Code:
    type
      TVector = record x,y,z: single; end;
      PVector = ^TVector;
    
    function vector(const x, y, z: single): TVector;
    begin
      result.x:=x; result.y:=y; result.z:=z;
    end;
    
    function TNXGL.MouseRayAtXZPlane(const mx, my: single): TVector;
    begin
       result:=MouseRayAtPlane(mx,my,Vector(0,0,0),Vector(0,1,0));
    end;
    So in order to get point (x,y,z) at airfield you need to call only
    pointAtAirfield:=MouseRayAtXZPlane(mouseX,mouseY);
    ...where pointAtAirfield is TVector type.

    Also notice that with OpenGL you may have to flip mouseY coordinate around because 0,0 is bottom left. DisplayHeight-mouseY.

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
  •