ray

Owner: IIIlllIIIllI URL: git@github.com:nyangkosense/ray.git

3d ray

Commit 899afe29abf95a8ac77664d74b7074770ae0932d by SM <seb.michalk@gmail.com> on 2025-06-30 09:47:26 +0200
diff --git a/build/JTACCoords/win_x64/JTACCoords.xpl b/build/JTACCoords/win_x64/JTACCoords.xpl
index 5f4e504..bf1eacd 100755
Binary files a/build/JTACCoords/win_x64/JTACCoords.xpl and b/build/JTACCoords/win_x64/JTACCoords.xpl differ
diff --git a/probe.cpp b/probe.cpp
index 79d7b20..d7b8b9d 100644
--- a/probe.cpp
+++ b/probe.cpp
@@ -35,11 +35,11 @@ static XPLMDataRef gPlaneRoll = NULL;
 static XPLMDataRef gViewHeading = NULL;
 static XPLMDataRef gViewPitch = NULL;
 
-// Mouse tracking
-static XPLMDataRef gMouseX = NULL;
-static XPLMDataRef gMouseY = NULL;
-static XPLMDataRef gScreenWidth = NULL;
-static XPLMDataRef gScreenHeight = NULL;
+// Hotkey handling
+static XPLMHotKeyID gLaserHotkey = NULL;
+
+// Function declarations
+void LaserDesignationHotkey(void* refcon);
 
 // Terrain probe handle
 static XPLMProbeRef gTerrainProbe = NULL;
@@ -82,18 +82,19 @@ PLUGIN_API int XPluginStart(char* outName, char* outSig, char* outDesc) {
     gViewHeading = XPLMFindDataRef("sim/graphics/view/view_heading");
     gViewPitch = XPLMFindDataRef("sim/graphics/view/view_pitch");
     
-    gMouseX = XPLMFindDataRef("sim/graphics/view/click_3d_x");
-    gMouseY = XPLMFindDataRef("sim/graphics/view/click_3d_y");
-    gScreenWidth = XPLMFindDataRef("sim/graphics/view/window_width");
-    gScreenHeight = XPLMFindDataRef("sim/graphics/view/window_height");
-    
     // Create terrain probe
     gTerrainProbe = XPLMCreateProbe(xplm_ProbeY);
     
+    // Register hotkey for laser designation (Ctrl+L)
+    gLaserHotkey = XPLMRegisterHotKey(XPLM_VK_L, xplm_DownFlag | xplm_ControlFlag, "Laser Target Designation", LaserDesignationHotkey, NULL);
+    
     return 1;
 }
 
 PLUGIN_API void XPluginStop(void) {
+    if (gLaserHotkey) {
+        XPLMUnregisterHotKey(gLaserHotkey);
+    }
     if (gTerrainProbe) {
         XPLMDestroyProbe(gTerrainProbe);
     }
@@ -145,11 +146,27 @@ void InvertMatrix4x4(const float* m, float* invOut) {
     }
 }
 
-// Convert screen coordinates to local ray direction using OpenGL matrices
-bool ScreenToLocalRay(int screenX, int screenY, double aircraftLat, double aircraftLon, double aircraftElev,
-                      float* rayStartX, float* rayStartY, float* rayStartZ,
-                      float* rayDirX, float* rayDirY, float* rayDirZ) {
+// Convert screen coordinates to world ray using X-Plane's projection system
+bool ScreenToWorldRay(int screenX, int screenY, 
+                     float* rayStartX, float* rayStartY, float* rayStartZ,
+                     float* rayDirX, float* rayDirY, float* rayDirZ) {
     
+    // Get current aircraft position as ray start
+    double aircraftLat = XPLMGetDatad(gPlaneLatitude);
+    double aircraftLon = XPLMGetDatad(gPlaneLongitude);
+    double aircraftElev = XPLMGetDatad(gPlaneElevation);
+    
+    // Get current screen dimensions
+    XPLMDataRef screenWidthRef = XPLMFindDataRef("sim/graphics/view/window_width");
+    XPLMDataRef screenHeightRef = XPLMFindDataRef("sim/graphics/view/window_height");
+    int screenWidth = XPLMGetDatai(screenWidthRef);
+    int screenHeight = XPLMGetDatai(screenHeightRef);
+    
+    // Convert to normalized coordinates (-1 to 1)
+    float normalX = (2.0f * screenX / (float)screenWidth) - 1.0f;
+    float normalY = 1.0f - (2.0f * screenY / (float)screenHeight);
+    
+    // Use X-Plane's world coordinate system
     // Convert aircraft position to local coordinates for ray start
     double localX, localY, localZ;
     XPLMWorldToLocal(aircraftLat, aircraftLon, aircraftElev, &localX, &localY, &localZ);
@@ -158,75 +175,38 @@ bool ScreenToLocalRay(int screenX, int screenY, double aircraftLat, double aircr
     *rayStartY = (float)localY;
     *rayStartZ = (float)localZ;
     
-    // Get OpenGL matrices
-    GLfloat modelMatrix[16];
-    GLfloat projMatrix[16];
-    GLint viewport[4];
-    
-    glGetFloatv(GL_MODELVIEW_MATRIX, modelMatrix);
-    glGetFloatv(GL_PROJECTION_MATRIX, projMatrix);
-    glGetIntegerv(GL_VIEWPORT, viewport);
-    
-    // Calculate combined model-view-projection matrix
-    float mvpMatrix[16];
-    MultiplyMatrix4x4(projMatrix, modelMatrix, mvpMatrix);
-    
-    // Invert the MVP matrix
-    float invMvpMatrix[16];
-    InvertMatrix4x4(mvpMatrix, invMvpMatrix);
-    
-    // Convert screen coordinates to normalized device coordinates
-    float ndcX = (2.0f * (screenX - viewport[0])) / viewport[2] - 1.0f;
-    float ndcY = 1.0f - (2.0f * (screenY - viewport[1])) / viewport[3];
-    
-    // Create two points in NDC space (near and far)
-    float nearPoint[4] = {ndcX, ndcY, -1.0f, 1.0f}; // Near plane
-    float farPoint[4] = {ndcX, ndcY, 1.0f, 1.0f};   // Far plane
-    
-    // Transform to OpenGL world space
-    float worldNear[4], worldFar[4];
-    
-    // Transform near point
-    worldNear[0] = invMvpMatrix[0] * nearPoint[0] + invMvpMatrix[4] * nearPoint[1] + 
-                   invMvpMatrix[8] * nearPoint[2] + invMvpMatrix[12] * nearPoint[3];
-    worldNear[1] = invMvpMatrix[1] * nearPoint[0] + invMvpMatrix[5] * nearPoint[1] + 
-                   invMvpMatrix[9] * nearPoint[2] + invMvpMatrix[13] * nearPoint[3];
-    worldNear[2] = invMvpMatrix[2] * nearPoint[0] + invMvpMatrix[6] * nearPoint[1] + 
-                   invMvpMatrix[10] * nearPoint[2] + invMvpMatrix[14] * nearPoint[3];
-    worldNear[3] = invMvpMatrix[3] * nearPoint[0] + invMvpMatrix[7] * nearPoint[1] + 
-                   invMvpMatrix[11] * nearPoint[2] + invMvpMatrix[15] * nearPoint[3];
-    
-    // Transform far point
-    worldFar[0] = invMvpMatrix[0] * farPoint[0] + invMvpMatrix[4] * farPoint[1] + 
-                  invMvpMatrix[8] * farPoint[2] + invMvpMatrix[12] * farPoint[3];
-    worldFar[1] = invMvpMatrix[1] * farPoint[0] + invMvpMatrix[5] * farPoint[1] + 
-                  invMvpMatrix[9] * farPoint[2] + invMvpMatrix[13] * farPoint[3];
-    worldFar[2] = invMvpMatrix[2] * farPoint[0] + invMvpMatrix[6] * farPoint[1] + 
-                  invMvpMatrix[10] * farPoint[2] + invMvpMatrix[14] * farPoint[3];
-    worldFar[3] = invMvpMatrix[3] * farPoint[0] + invMvpMatrix[7] * farPoint[1] + 
-                  invMvpMatrix[11] * farPoint[2] + invMvpMatrix[15] * farPoint[3];
-    
-    // Perspective divide
-    if (worldNear[3] != 0.0f) {
-        worldNear[0] /= worldNear[3];
-        worldNear[1] /= worldNear[3];
-        worldNear[2] /= worldNear[3];
-    }
+    // Get view parameters
+    float heading = XPLMGetDataf(gViewHeading) * DEG_TO_RAD;
+    float pitch = XPLMGetDataf(gViewPitch) * DEG_TO_RAD;
     
-    if (worldFar[3] != 0.0f) {
-        worldFar[0] /= worldFar[3];
-        worldFar[1] /= worldFar[3];
-        worldFar[2] /= worldFar[3];
-    }
+    // Calculate FOV (approximate)
+    float fov = 45.0f * DEG_TO_RAD; // Default X-Plane FOV
+    float aspect = (float)screenWidth / (float)screenHeight;
+    
+    // Calculate ray direction based on screen position and view angles
+    float tanHalfFov = tan(fov * 0.5f);
+    
+    // Ray direction in view space
+    float viewX = normalX * tanHalfFov * aspect;
+    float viewY = normalY * tanHalfFov;
+    float viewZ = -1.0f; // Forward direction
     
-    // The OpenGL unprojection gives us OpenGL world coordinates
-    // We need to convert these to X-Plane local coordinates
-    // X-Plane's OpenGL coordinate system is already in local space relative to the world origin
+    // Transform ray direction by view rotation
+    float cosHeading = cos(heading);
+    float sinHeading = sin(heading);
+    float cosPitch = cos(pitch);
+    float sinPitch = sin(pitch);
     
-    // Calculate ray direction in local space
-    *rayDirX = worldFar[0] - worldNear[0];
-    *rayDirY = worldFar[1] - worldNear[1];
-    *rayDirZ = worldFar[2] - worldNear[2];
+    // Apply pitch rotation (around X axis)
+    float tempY = viewY * cosPitch - viewZ * sinPitch;
+    float tempZ = viewY * sinPitch + viewZ * cosPitch;
+    viewY = tempY;
+    viewZ = tempZ;
+    
+    // Apply heading rotation (around Y axis)
+    *rayDirX = viewX * cosHeading - viewZ * sinHeading;
+    *rayDirY = viewY;
+    *rayDirZ = viewX * sinHeading + viewZ * cosHeading;
     
     // Normalize direction vector
     float length = sqrt(*rayDirX * *rayDirX + *rayDirY * *rayDirY + *rayDirZ * *rayDirZ);
@@ -242,16 +222,16 @@ bool ScreenToLocalRay(int screenX, int screenY, double aircraftLat, double aircr
 
 // Perform laser designation at screen coordinates
 bool DesignateLaser(int screenX, int screenY, TargetCoords* target) {
-    // Get aircraft position in world coordinates
-    double aircraftLat = XPLMGetDatad(gPlaneLatitude);
-    double aircraftLon = XPLMGetDatad(gPlaneLongitude);
-    double aircraftElev = XPLMGetDatad(gPlaneElevation);
+    // Get ray start and direction
+    // double aircraftLat = XPLMGetDatad(gPlaneLatitude);
+    // double aircraftLon = XPLMGetDatad(gPlaneLongitude);
+    // double aircraftElev = XPLMGetDatad(gPlaneElevation);
     
     // Get ray start and direction using OpenGL matrices
     float rayStartX, rayStartY, rayStartZ;
     float rayDirX, rayDirY, rayDirZ;
     
-    if (!ScreenToLocalRay(screenX, screenY, aircraftLat, aircraftLon, aircraftElev,
+    if (!ScreenToWorldRay(screenX, screenY,
                          &rayStartX, &rayStartY, &rayStartZ,
                          &rayDirX, &rayDirY, &rayDirZ)) {
         return false;
@@ -338,25 +318,25 @@ void FormatMGRS(double latitude, double longitude, char* output, size_t outputSi
              abs(latDeg), latMin, latSec, abs(lonDeg), lonMin, lonSec);
 }
 
-// Mouse click handler
-int MouseClickHandler(XPLMWindowID inWindowID, int x, int y, int mouse, void* inRefcon) {
-    if (mouse == xplm_MouseDown) {
-        // Convert window coordinates to screen coordinates
-        int left, top, right, bottom;
-        XPLMGetWindowGeometry(inWindowID, &left, &top, &right, &bottom);
-        
-        int screenX = x;
-        int screenY = y;
+// Hotkey callback for laser designation (Ctrl+L)
+void LaserDesignationHotkey(void* refcon) {
+    // Get current mouse position from X-Plane
+    XPLMDataRef mouseXRef = XPLMFindDataRef("sim/graphics/view/mouse_x");
+    XPLMDataRef mouseYRef = XPLMFindDataRef("sim/graphics/view/mouse_y");
+    
+    if (mouseXRef && mouseYRef) {
+        int mouseX = XPLMGetDatai(mouseXRef);
+        int mouseY = XPLMGetDatai(mouseYRef);
         
-        // Perform laser designation
-        if (DesignateLaser(screenX, screenY, &gLastTarget)) {
-            XPLMDebugString("JTAC: Target designated successfully\n");
+        // Perform laser designation at mouse cursor location
+        if (DesignateLaser(mouseX, mouseY, &gLastTarget)) {
+            XPLMDebugString("JTAC: Target designated successfully at cursor location\n");
         } else {
-            XPLMDebugString("JTAC: No terrain intersection found\n");
+            XPLMDebugString("JTAC: No terrain intersection found at cursor location\n");
         }
+    } else {
+        XPLMDebugString("JTAC: Could not get mouse position\n");
     }
-    
-    return 1;
 }
 
 // Display window draw function
@@ -420,7 +400,7 @@ void DrawWindow(XPLMWindowID inWindowID, void* inRefcon) {
     
     // Instructions
     line++;
-    snprintf(buffer, sizeof(buffer), "Click to designate laser target");
+    snprintf(buffer, sizeof(buffer), "Press Ctrl+L to designate laser target at cursor");
     float gray[] = {0.78f, 0.78f, 0.78f};
     XPLMDrawString(gray, left + 10, top - 20 - (line++ * 15), buffer, NULL, xplmFont_Proportional);
 }
@@ -435,7 +415,7 @@ void CreateJTACWindow() {
     params.bottom = 400;
     params.visible = 1;
     params.drawWindowFunc = DrawWindow;
-    params.handleMouseClickFunc = MouseClickHandler;
+    params.handleMouseClickFunc = NULL;
     params.handleKeyFunc = NULL;
     params.handleCursorFunc = NULL;
     params.handleMouseWheelFunc = NULL;
diff --git a/probe.o b/probe.o
index 898d873..02db76f 100644
Binary files a/probe.o and b/probe.o differ