From bbb8b066eb295ba782cf1486f9db2f1d71d53f3e Mon Sep 17 00:00:00 2001
From: curt <curt>
Date: Mon, 12 Dec 2005 21:15:20 +0000
Subject: [PATCH] =?UTF-8?q?Mathias=20Fr=C3=B6hlich:?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Computes the pick direction and starting point.  This is code that translates
a screen coordinate into a vector in the FlightGear world (between the eye and
the on-screen coordinate.)  Armed with this vector in FG world coordinates,
you could call a scenery intersection routine and lookup the lon/lat/elev of
the point in the world that was clicked on.
---
 src/Main/renderer.cxx | 45 +++++++++++++++++++++++++++++++++++++++++++
 src/Main/renderer.hxx |  6 ++++++
 2 files changed, 51 insertions(+)

diff --git a/src/Main/renderer.cxx b/src/Main/renderer.cxx
index 5b704cc52..0e25a7169 100644
--- a/src/Main/renderer.cxx
+++ b/src/Main/renderer.cxx
@@ -920,5 +920,50 @@ void FGRenderer::setNearFar( float n, float f ) {
     fgHackFrustum();
 }
 
+bool FGRenderer::getPickInfo( sgdVec3 pt, sgdVec3 dir, unsigned x, unsigned y )
+{
+  // Get the matrices involved in the transform from global to screen
+  // coordinates.
+  sgMat4 pm;
+  ssgGetProjectionMatrix(pm);
+  sgMat4 mv;
+  ssgGetModelviewMatrix(mv);
+  
+  // Compose ...
+  sgMat4 m;
+  sgMultMat4(m, pm, mv);
+  // ... and invert
+  sgInvertMat4(m);
+  
+  // Get the width and height of the display to be able to normalize the
+  // mouse coordinate
+  float width = fgGetInt("/sim/startup/xsize");
+  float height = fgGetInt("/sim/startup/ysize");
+  
+  // Compute some coordinates of in the line from the eyepoint to the
+  // mouse click coodinates.
+  // First build the normalized projection coordinates
+  sgVec4 normPt;
+  sgSetVec4(normPt, (2*x - width)/width, -(2*y - height)/height, 1, 1);
+  // Transform them into the real world
+  sgVec4 worldPt;
+  sgXformPnt4(worldPt, normPt, m);
+  if (worldPt[3] == 0)
+    return false;
+  sgScaleVec3(worldPt, 1/worldPt[3]);
+
+  // Now build a direction from the point
+  FGViewer* view = globals->get_current_view();
+  sgVec4 fDir;
+  sgSubVec3(fDir, worldPt, view->get_view_pos());
+  sgdSetVec3(dir, fDir);
+  sgdNormalizeVec3(dir);
+
+  // Copy the start point
+  sgdCopyVec3(pt, view->get_absolute_view_pos());
+
+  return true;
+}
 
 // end of renderer.cxx
+    
diff --git a/src/Main/renderer.hxx b/src/Main/renderer.hxx
index ed9fe6df2..de33b114a 100644
--- a/src/Main/renderer.hxx
+++ b/src/Main/renderer.hxx
@@ -44,6 +44,12 @@ public:
      *  clip planes rather than calling the ssg routine directly
      */
     static void setNearFar( float n, float f );
+
+    /** Get the pick start point and direction in global coordinates.
+     *  The inputs are expected to be the x and y coordinates of the
+     *  screen point relative to the window.
+     */
+    static bool getPickInfo( sgdVec3 p, sgdVec3 d, unsigned x, unsigned y );
 };
 
 #endif