xp12camera

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

enhanced algorithm, implemented more filter

Commit bf0a4bfc03728f2c506b08ae6ffaba087d6212d3 by SM <seb.michalk@gmail.com> on 2025-06-26 09:23:48 +0200
diff --git a/FLIR_Camera.cpp b/FLIR_Camera.cpp
index bec1dd0..ab4a8e1 100644
--- a/FLIR_Camera.cpp
+++ b/FLIR_Camera.cpp
@@ -65,8 +65,7 @@ static int gLastMouseX = 0;
 static int gLastMouseY = 0;
 static float gMouseSensitivity = 0.2f; // Mouse sensitivity multiplier
 
-// Thermal view settings
-static int gThermalMode = 1;         // 0=Off, 1=White Hot, 2=Enhanced
+// Thermal view settings are now handled by visual effects system
 
 // Dataref to control HUD visibility
 static XPLMDataRef gManipulatorDisabled = NULL;
@@ -155,7 +154,8 @@ static void DrawRealisticThermalOverlay(void);
 
      XPLMDebugString("FLIR Camera System: Plugin loaded successfully\n");
      XPLMDebugString("FLIR Camera System: Press F9 to activate camera\n");
-     XPLMDebugString("FLIR Camera System: MOUSE for smooth pan/tilt, +/- for zoom, arrows for fine adjust, T for thermal, SPACE for lock-on\n");
+     XPLMDebugString("FLIR Camera System: MOUSE for smooth pan/tilt, +/- for zoom, arrows for fine adjust, T for thermal, SPACE for enhanced lock-on\n");
+     XPLMDebugString("FLIR Camera System: Enhanced tracking uses X-Plane's algorithm for smooth target following\n");
      
      return 1;
  }
@@ -333,13 +333,13 @@ static void FocusLockCallback(void* inRefcon)
 {
     if (gCameraActive) {
         if (!IsSimpleLockActive()) {
-            // Lock to current camera direction
+            // Lock to current camera direction using enhanced tracking
             LockCurrentDirection(gCameraPan, gCameraTilt);
-            XPLMDebugString("FLIR Camera System: Direction locked\n");
+            XPLMDebugString("FLIR Camera System: Enhanced tracking engaged\n");
         } else {
-            // Disable lock
+            // Disable enhanced tracking
             DisableSimpleLock();
-            XPLMDebugString("FLIR Camera System: Lock disabled\n");
+            XPLMDebugString("FLIR Camera System: Enhanced tracking disabled\n");
         }
     }
 }
@@ -373,11 +373,18 @@ static void FocusLockCallback(void* inRefcon)
      float planeY = XPLMGetDataf(gPlaneY);
      float planeZ = XPLMGetDataf(gPlaneZ);
      float planeHeading = XPLMGetDataf(gPlaneHeading);
-     float planePitch = XPLMGetDataf(gPlanePitch);
-     float planeRoll = XPLMGetDataf(gPlaneRoll);
      
-     // Mouse control for camera movement (only when not locked)
+     // Calculate camera position (belly-mounted) first
+     float headingRad = planeHeading * M_PI / 180.0f;
+     
+     // Position camera below and slightly forward of aircraft center
+     outCameraPosition->x = planeX + gCameraDistance * sin(headingRad);
+     outCameraPosition->y = planeY + gCameraHeight;
+     outCameraPosition->z = planeZ + gCameraDistance * cos(headingRad);
+     
+     // Camera orientation control (mouse or enhanced tracking)
      if (!IsSimpleLockActive()) {
+         // Mouse control for camera movement
          int mouseX, mouseY;
          XPLMGetMouseLocation(&mouseX, &mouseY);
          
@@ -400,18 +407,13 @@ static void FocusLockCallback(void* inRefcon)
          gLastMouseX = mouseX;
          gLastMouseY = mouseY;
      } else {
-         // Use locked camera angles
-         GetLockedAngles(&gCameraPan, &gCameraTilt);
+         // Use enhanced tracking algorithm like X-Plane's built-in system
+         CalculateEnhancedTrackingCamera(&gCameraPan, &gCameraTilt,
+                                       planeX, planeY, planeZ,
+                                       planeHeading,
+                                       outCameraPosition->x, outCameraPosition->y, outCameraPosition->z);
      }
      
-     // Calculate camera position (belly-mounted)
-     float headingRad = planeHeading * M_PI / 180.0f;
-     
-     // Position camera below and slightly forward of aircraft center
-     outCameraPosition->x = planeX + gCameraDistance * sin(headingRad);
-     outCameraPosition->y = planeY + gCameraHeight;
-     outCameraPosition->z = planeZ + gCameraDistance * cos(headingRad);
-     
      // Camera orientation (pan/tilt relative to aircraft heading)
      outCameraPosition->heading = planeHeading + gCameraPan;
      outCameraPosition->pitch = gCameraTilt;
diff --git a/FLIR_Camera.o b/FLIR_Camera.o
index 14c4d50..1d8af99 100644
Binary files a/FLIR_Camera.o and b/FLIR_Camera.o differ
diff --git a/FLIR_HUD_Simple.lua b/FLIR_HUD_Simple.lua
index 3df4db9..a989c55 100644
--- a/FLIR_HUD_Simple.lua
+++ b/FLIR_HUD_Simple.lua
@@ -1,5 +1,4 @@
 -- FLIR Camera HUD Display Script for FlyWithLua
--- Simplified version to prevent engine crashes
 -- Toggle with macro: FLIR Toggle HUD
 
 -- Global variables
@@ -54,7 +53,7 @@ function draw_flir_hud()
         
         graphics.draw_string(SCREEN_WIDTH - 300, SCREEN_HEIGHT - 70, "TGT: SCANNING...", "large")
         graphics.draw_string(30, 90, "ZOOM: ACTIVE  THERMAL: WHT", "large")
-        graphics.draw_string(30, SCREEN_HEIGHT - 100, "MARITIME PATROL AIRCRAFT", "large")
+        graphics.draw_string(30, SCREEN_HEIGHT - 100, "A319 MTP AIRCRAFT", "large")
     end
 end
 
@@ -74,4 +73,4 @@ do_every_draw("draw_flir_hud()")
 -- Add macro for toggling HUD
 add_macro("FLIR: Toggle HUD", "toggle_flir_hud()", "", "activate")
 
-logMsg("FLIR HUD Simple Script Loaded - Use 'FLIR: Toggle HUD' macro to toggle")
\ No newline at end of file
+logMsg("FLIR HUD Simple Script Loaded - Use 'FLIR: Toggle HUD' macro to toggle")
diff --git a/FLIR_SimpleLock.cpp b/FLIR_SimpleLock.cpp
index 6ff8edb..b441117 100644
--- a/FLIR_SimpleLock.cpp
+++ b/FLIR_SimpleLock.cpp
@@ -1,9 +1,9 @@
 /*
  * FLIR_SimpleLock.cpp
  * 
- * Simple arbitrary point lock-on system
- * Just locks the current camera direction relative to aircraft heading
- * Perfect for tracking moving ships, vehicles, or any visual target
+ * Enhanced lock-on system using X-Plane's tracking algorithms
+ * Implements sophisticated target following like X-Plane's built-in external view
+ * Provides smooth tracking for ships, vehicles, and any visual targets
  */
 
 #include <string.h>
@@ -11,41 +11,105 @@
 #include <stdlib.h>
 #include <math.h>
 
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
 #include "XPLMDataAccess.h"
 #include "XPLMUtilities.h"
 #include "FLIR_SimpleLock.h"
 
-// Lock-on state
+// Enhanced lock-on state
 static int gLockActive = 0;
 static float gLockedPan = 0.0f;     // Pan angle relative to aircraft when locked
 static float gLockedTilt = 0.0f;    // Tilt angle when locked
+static float gTargetX = 0.0f;       // World coordinates of locked target
+static float gTargetY = 0.0f;
+static float gTargetZ = 0.0f;
+static int gUseEnhancedTracking = 1; // Use X-Plane style tracking algorithm
 
 void InitializeSimpleLock()
 {
     gLockActive = 0;
-    XPLMDebugString("FLIR Simple Lock: Initialized\n");
+    gUseEnhancedTracking = 1;
+    XPLMDebugString("FLIR Enhanced Lock: Initialized with X-Plane tracking algorithms\n");
 }
 
 void LockCurrentDirection(float currentPan, float currentTilt)
 {
-    // Simply store the current camera angles
+    // Store the current camera angles for enhanced tracking
     gLockedPan = currentPan;
     gLockedTilt = currentTilt;
     gLockActive = 1;
     
+    // Calculate target position in world coordinates using X-Plane's algorithm
+    // This creates a stable target point that the camera will track
+    float headingRad = (currentPan) * M_PI / 180.0f;
+    float pitchRad = currentTilt * M_PI / 180.0f;
+    
+    // Project locked direction into world space at far distance
+    float targetDistance = 10000.0f; // Far target for stable tracking
+    gTargetX = targetDistance * sin(headingRad) * cos(pitchRad);
+    gTargetY = targetDistance * sin(pitchRad);
+    gTargetZ = targetDistance * cos(headingRad) * cos(pitchRad);
+    
     char msg[256];
-    sprintf(msg, "FLIR Simple Lock: Locked at Pan=%.1f°, Tilt=%.1f°\n", 
-            gLockedPan, gLockedTilt);
+    sprintf(msg, "FLIR Enhanced Lock: Locked at Pan=%.1f°, Tilt=%.1f° (Target: %.1f,%.1f,%.1f)\n", 
+            gLockedPan, gLockedTilt, gTargetX, gTargetY, gTargetZ);
     XPLMDebugString(msg);
 }
 
+void CalculateEnhancedTrackingCamera(float* outPan, float* outTilt, 
+                                   float aircraftX, float aircraftY, float aircraftZ,
+                                   float aircraftHeading, float cameraX, float cameraY, float cameraZ)
+{
+    if (!gLockActive) {
+        return;
+    }
+    
+    if (!gUseEnhancedTracking) {
+        // Fallback to simple angle lock
+        *outPan = gLockedPan;
+        *outTilt = gLockedTilt;
+        return;
+    }
+    
+    // Enhanced tracking using X-Plane's algorithm
+    // Transform target from aircraft-relative to world coordinates
+    float headingRad = (aircraftHeading + gLockedPan) * M_PI / 180.0f;
+    float pitchRad = gLockedTilt * M_PI / 180.0f;
+    
+    // Calculate world target position relative to current aircraft position
+    float targetDistance = 10000.0f;
+    float worldTargetX = aircraftX + targetDistance * sin(headingRad) * cos(pitchRad);
+    float worldTargetY = aircraftY + targetDistance * sin(pitchRad);
+    float worldTargetZ = aircraftZ + targetDistance * cos(headingRad) * cos(pitchRad);
+    
+    // Calculate camera orientation to track target (X-Plane's method)
+    float deltaX = worldTargetX - cameraX;
+    float deltaY = worldTargetY - cameraY;
+    float deltaZ = worldTargetZ - cameraZ;
+    
+    // Convert to pan/tilt angles
+    float targetHeading = atan2(deltaX, deltaZ) * 180.0f / M_PI;
+    float targetPitch = atan2(deltaY, sqrt(deltaX*deltaX + deltaZ*deltaZ)) * 180.0f / M_PI;
+    
+    // Calculate relative to aircraft heading
+    *outPan = targetHeading - aircraftHeading;
+    *outTilt = targetPitch;
+    
+    // Normalize pan angle
+    while (*outPan > 180.0f) *outPan -= 360.0f;
+    while (*outPan < -180.0f) *outPan += 360.0f;
+}
+
 void GetLockedAngles(float* outPan, float* outTilt)
 {
     if (!gLockActive) {
         return;
     }
     
-    // Simply return the locked angles - camera stays fixed relative to aircraft
+    // Legacy support - return stored angles
     *outPan = gLockedPan;
     *outTilt = gLockedTilt;
 }
@@ -53,7 +117,7 @@ void GetLockedAngles(float* outPan, float* outTilt)
 void DisableSimpleLock()
 {
     gLockActive = 0;
-    XPLMDebugString("FLIR Simple Lock: Disabled\n");
+    XPLMDebugString("FLIR Enhanced Lock: Disabled\n");
 }
 
 int IsSimpleLockActive()
@@ -64,11 +128,12 @@ int IsSimpleLockActive()
 void GetSimpleLockStatus(char* statusBuffer, int bufferSize)
 {
     if (!gLockActive) {
-        strncpy(statusBuffer, "LOCK: OFF", bufferSize - 1);
+        strncpy(statusBuffer, "TRACK: OFF", bufferSize - 1);
         statusBuffer[bufferSize - 1] = '\0';
         return;
     }
     
-    snprintf(statusBuffer, bufferSize, "LOCK: ON %.1f°/%.1f°", gLockedPan, gLockedTilt);
+    const char* mode = gUseEnhancedTracking ? "ENH" : "SIM";
+    snprintf(statusBuffer, bufferSize, "TRACK: %s %.1f°/%.1f°", mode, gLockedPan, gLockedTilt);
     statusBuffer[bufferSize - 1] = '\0';
 }
\ No newline at end of file
diff --git a/FLIR_SimpleLock.h b/FLIR_SimpleLock.h
index 6a7216f..9e748da 100644
--- a/FLIR_SimpleLock.h
+++ b/FLIR_SimpleLock.h
@@ -1,7 +1,8 @@
 /*
  * FLIR_SimpleLock.h
  * 
- * Header file for simple arbitrary point lock-on system
+ * Enhanced lock-on system using X-Plane's tracking algorithms
+ * Provides smooth target following like X-Plane's built-in external view
  */
 
 #ifndef FLIR_SIMPLELOCK_H
@@ -11,13 +12,18 @@
 extern "C" {
 #endif
 
-// Initialize the simple lock system
+// Initialize the enhanced lock system
 void InitializeSimpleLock();
 
-// Lock to current camera direction
+// Lock to current camera direction (enhanced algorithm)
 void LockCurrentDirection(float currentPan, float currentTilt);
 
-// Get locked camera angles
+// Calculate enhanced tracking camera position
+void CalculateEnhancedTrackingCamera(float* outPan, float* outTilt, 
+                                   float aircraftX, float aircraftY, float aircraftZ,
+                                   float aircraftHeading, float cameraX, float cameraY, float cameraZ);
+
+// Get locked camera angles (legacy support)
 void GetLockedAngles(float* outPan, float* outTilt);
 
 // Disable lock
diff --git a/FLIR_SimpleLock.o b/FLIR_SimpleLock.o
index 349f49e..6699040 100644
Binary files a/FLIR_SimpleLock.o and b/FLIR_SimpleLock.o differ
diff --git a/FLIR_VisualEffects.cpp b/FLIR_VisualEffects.cpp
index 2c050d0..c9243ed 100644
--- a/FLIR_VisualEffects.cpp
+++ b/FLIR_VisualEffects.cpp
@@ -28,6 +28,7 @@
 // Visual effects state
 static int gMonochromeEnabled = 0;
 static int gThermalEnabled = 1;
+static int gIREnabled = 0;
 static int gNoiseEnabled = 1;
 static int gScanLinesEnabled = 1;
 static float gBrightness = 1.0f;
@@ -60,6 +61,14 @@ void SetThermalMode(int enabled)
     XPLMDebugString(msg);
 }
 
+void SetIRMode(int enabled)
+{
+    gIREnabled = enabled;
+    char msg[256];
+    sprintf(msg, "FLIR Visual Effects: IR (B/W) %s\n", enabled ? "ON" : "OFF");
+    XPLMDebugString(msg);
+}
+
 void SetImageEnhancement(float brightness, float contrast)
 {
     gBrightness = brightness;
@@ -97,6 +106,11 @@ void RenderVisualEffects(int screenWidth, int screenHeight)
         RenderThermalEffects(screenWidth, screenHeight);
     }
     
+    // Apply IR black/white filter
+    if (gIREnabled) {
+        RenderIRFilter(screenWidth, screenHeight);
+    }
+    
     // Add camera noise/grain
     if (gNoiseEnabled) {
         RenderCameraNoise(screenWidth, screenHeight);
@@ -238,15 +252,62 @@ void RenderScanLines(int screenWidth, int screenHeight)
     glEnd();
 }
 
+void RenderIRFilter(int screenWidth, int screenHeight)
+{
+    // IR Black/White high contrast filter
+    glBlendFunc(GL_DST_COLOR, GL_ZERO); // Multiply blend for desaturation
+    
+    // Create strong black/white contrast effect
+    glColor4f(0.4f, 0.4f, 0.4f, 1.0f); // Desaturate and darken
+    
+    glBegin(GL_QUADS);
+    glVertex2f(0, 0);
+    glVertex2f(screenWidth, 0);
+    glVertex2f(screenWidth, screenHeight);
+    glVertex2f(0, screenHeight);
+    glEnd();
+    
+    // Add high contrast overlay
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    
+    // Boost contrast for IR effect
+    float contrast = gContrast * 1.5f;
+    glColor4f(contrast, contrast, contrast, 0.3f);
+    
+    glBegin(GL_QUADS);
+    glVertex2f(0, 0);
+    glVertex2f(screenWidth, 0);
+    glVertex2f(screenWidth, screenHeight);
+    glVertex2f(0, screenHeight);
+    glEnd();
+    
+    // Add IR-style edge enhancement
+    glColor4f(1.0f, 1.0f, 1.0f, 0.1f);
+    glLineWidth(1.0f);
+    
+    // Subtle grid pattern for IR sensor simulation
+    glBegin(GL_LINES);
+    for (int x = 0; x < screenWidth; x += 8) {
+        glVertex2f(x, 0);
+        glVertex2f(x, screenHeight);
+    }
+    for (int y = 0; y < screenHeight; y += 8) {
+        glVertex2f(0, y);
+        glVertex2f(screenWidth, y);
+    }
+    glEnd();
+}
+
 void CycleVisualModes()
 {
     static int mode = 0;
-    mode = (mode + 1) % 4;
+    mode = (mode + 1) % 5;
     
     switch (mode) {
         case 0: // Standard
             SetMonochromeFilter(0);
             SetThermalMode(0);
+            SetIRMode(0);
             gNoiseEnabled = 0;
             gScanLinesEnabled = 0;
             XPLMDebugString("FLIR Visual Effects: Standard Mode\n");
@@ -255,6 +316,7 @@ void CycleVisualModes()
         case 1: // Monochrome
             SetMonochromeFilter(1);
             SetThermalMode(0);
+            SetIRMode(0);
             gNoiseEnabled = 1;
             gScanLinesEnabled = 1;
             XPLMDebugString("FLIR Visual Effects: Monochrome Mode\n");
@@ -263,14 +325,25 @@ void CycleVisualModes()
         case 2: // Thermal
             SetMonochromeFilter(0);
             SetThermalMode(1);
+            SetIRMode(0);
             gNoiseEnabled = 1;
             gScanLinesEnabled = 0;
             XPLMDebugString("FLIR Visual Effects: Thermal Mode\n");
             break;
             
-        case 3: // Enhanced
+        case 3: // IR Black/White
+            SetMonochromeFilter(0);
+            SetThermalMode(0);
+            SetIRMode(1);
+            gNoiseEnabled = 1;
+            gScanLinesEnabled = 1;
+            XPLMDebugString("FLIR Visual Effects: IR Mode\n");
+            break;
+            
+        case 4: // Enhanced
             SetMonochromeFilter(1);
             SetThermalMode(1);
+            SetIRMode(0);
             gNoiseEnabled = 1;
             gScanLinesEnabled = 1;
             XPLMDebugString("FLIR Visual Effects: Enhanced Mode\n");
@@ -284,6 +357,7 @@ void GetVisualEffectsStatus(char* statusBuffer, int bufferSize)
     if (gMonochromeEnabled && gThermalEnabled) mode = "ENHANCED";
     else if (gThermalEnabled) mode = "THERMAL";
     else if (gMonochromeEnabled) mode = "MONO";
+    else if (gIREnabled) mode = "IR B/W";
     
     snprintf(statusBuffer, bufferSize, "VFX: %s", mode);
     statusBuffer[bufferSize - 1] = '\0';
diff --git a/FLIR_VisualEffects.h b/FLIR_VisualEffects.h
index 8994e8b..4ac76d8 100644
--- a/FLIR_VisualEffects.h
+++ b/FLIR_VisualEffects.h
@@ -20,11 +20,13 @@ void RenderVisualEffects(int screenWidth, int screenHeight);
 // Individual effect controls
 void SetMonochromeFilter(int enabled);
 void SetThermalMode(int enabled);
+void SetIRMode(int enabled);
 void SetImageEnhancement(float brightness, float contrast);
 
 // Individual effect renderers
 void RenderMonochromeFilter(int screenWidth, int screenHeight);
 void RenderThermalEffects(int screenWidth, int screenHeight);
+void RenderIRFilter(int screenWidth, int screenHeight);
 void RenderCameraNoise(int screenWidth, int screenHeight);
 void RenderScanLines(int screenWidth, int screenHeight);
 
diff --git a/FLIR_VisualEffects.o b/FLIR_VisualEffects.o
index 7237a02..ec43597 100644
Binary files a/FLIR_VisualEffects.o and b/FLIR_VisualEffects.o differ
diff --git a/build/FLIR_Camera/win_x64/FLIR_Camera.xpl b/build/FLIR_Camera/win_x64/FLIR_Camera.xpl
index 605aa99..c6c1850 100755
Binary files a/build/FLIR_Camera/win_x64/FLIR_Camera.xpl and b/build/FLIR_Camera/win_x64/FLIR_Camera.xpl differ