xp12camera

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

13

Commit 83d48f7366f60137edf6af2223d069116ec1286f by SM <seb.michalk@gmail.com> on 2025-06-25 19:14:53 +0200
diff --git a/FLIR_Camera.cpp b/FLIR_Camera.cpp
index 9e9cca2..b1d61bd 100644
--- a/FLIR_Camera.cpp
+++ b/FLIR_Camera.cpp
@@ -5,9 +5,9 @@
  * Features:
  * - Real camera positioning under aircraft (belly-mounted)
  * - True optical zoom with zoom parameter
- * - Pan/tilt camera controls
- * - Target acquisition and tracking
- * - Thermal overlay rendering
+ * - Pan/tilt camera controls with mouse
+ * - Arbitrary point lock-on system
+ * - Military-style targeting reticles
  * 
  */
 
@@ -24,11 +24,7 @@
  #include "XPLMGraphics.h"
  #include "XPLMProcessing.h"
  #include "XPLMMenus.h"
- #include "XPLMScenery.h"
- #include "XPLMPlanes.h"
-#include "XPLMNavigation.h"
-#include "XPLMInstance.h"
-#include "XPLMWeather.h"
+ #include "FLIR_LockOn.h"
 
  // OpenGL includes for MinGW
  #include <windows.h>
@@ -69,59 +65,9 @@ static float gMouseSensitivity = 0.2f; // Mouse sensitivity multiplier
 
 // Thermal view settings
 static int gThermalMode = 1;         // 0=Off, 1=White Hot, 2=Enhanced
- 
- // Target tracking and object detection
- static int gTargetLocked = 0;
-static float gFocusDistance = 1000.0f; // Distance to focused target
- static float gTargetX = 0.0f; // World position of locked target
- static float gTargetY = 0.0f;
- static float gTargetZ = 0.0f;
- static int gLockedTargetIndex = -1; // Index of locked target in heat sources
-
- // Aircraft tracking arrays (up to 20 aircraft)
- static float gAircraftPositions[20][3];  // x, y, z positions
- static float gAircraftEngineTemp[20];    // Engine temperatures
- static float gAircraftDistance[20];      // Distance from camera
-static int gAircraftVisible[20];         // Visibility in thermal
-static int gAircraftCount = 0;
-
-// Environmental factors
-static float gCurrentVisibility = 10000.0f;
-static float gCurrentTemp = 15.0f;
-static float gCurrentWindSpeed = 0.0f;
-static int gIsNight = 0;
-
-// Heat source simulation
-typedef struct {
-    float x, y, z;           // World position
-    float intensity;         // Heat intensity (0-1)
-    float size;             // Heat source size
-    int type;               // 0=aircraft, 1=ship, 2=vehicle, 3=building
-    float lastUpdate;       // Last update time
-} HeatSource;
 
-static HeatSource gHeatSources[50];
-static int gHeatSourceCount = 0;
-
- // Additional datarefs for enhanced detection
- static XPLMDataRef gEngineRunning = NULL;
- static XPLMDataRef gEngineN1 = NULL;
-static XPLMDataRef gEngineEGT = NULL;
-static XPLMDataRef gGroundTemperature = NULL;
-static XPLMDataRef gWeatherVisibility = NULL;
-static XPLMDataRef gCloudCoverage = NULL;
-static XPLMDataRef gAmbientTemperature = NULL;
-static XPLMDataRef gWindSpeed = NULL;
-static XPLMDataRef gTimeOfDay = NULL;
-static XPLMDataRef gAIAircraftX = NULL;
-static XPLMDataRef gAIAircraftY = NULL;
-static XPLMDataRef gAIAircraftZ = NULL;
-static XPLMDataRef gAIAircraftCount = NULL;
-static XPLMDataRef gLocalDate = NULL;
-static XPLMDataRef gZuluTime = NULL;
-static XPLMDataRef gLatitude = NULL;
-static XPLMDataRef gLongitude = NULL;
-static XPLMDataRef gAltitude = NULL;
+// Dataref to control HUD visibility
+static XPLMDataRef gManipulatorDisabled = NULL;
  
  // Function declarations
  static void ActivateFLIRCallback(void* inRefcon);
@@ -142,12 +88,7 @@ static void FocusLockCallback(void* inRefcon);
                               int inIsBefore,
                               void* inRefcon);
 
-static void UpdateEnvironmentalFactors(void);
-static void UpdateHeatSources(void);
-static void DetectAircraft(void);
-static float CalculateHeatIntensity(float engineTemp, float distance, int engineRunning);
 static void DrawRealisticThermalOverlay(void);
-static float GetDistanceToCamera(float x, float y, float z);
  
  // Plugin lifecycle functions
  PLUGIN_API int XPluginStart(char* outName, char* outSig, char* outDesc)
@@ -155,7 +96,7 @@ static float GetDistanceToCamera(float x, float y, float z);
      strcpy(outName, "FLIR Camera System");
      strcpy(outSig, "flir.camera.system");
      strcpy(outDesc, "Realistic FLIR camera with zoom and thermal overlay");
- 
+
      // Get aircraft position datarefs
      gPlaneX = XPLMFindDataRef("sim/flightmodel/position/local_x");
      gPlaneY = XPLMFindDataRef("sim/flightmodel/position/local_y");
@@ -163,29 +104,13 @@ static float GetDistanceToCamera(float x, float y, float z);
      gPlaneHeading = XPLMFindDataRef("sim/flightmodel/position/psi");
      gPlanePitch = XPLMFindDataRef("sim/flightmodel/position/theta");
      gPlaneRoll = XPLMFindDataRef("sim/flightmodel/position/phi");
- 
-     // Additional datarefs for thermal detection
-     gEngineRunning = XPLMFindDataRef("sim/flightmodel/engine/ENGN_running");
-     gEngineN1 = XPLMFindDataRef("sim/flightmodel/engine/ENGN_N1_");
-    gEngineEGT = XPLMFindDataRef("sim/flightmodel/engine/ENGN_EGT_c");
-    gGroundTemperature = XPLMFindDataRef("sim/weather/temperature_sealevel_c");
-    gWeatherVisibility = XPLMFindDataRef("sim/weather/visibility_reported_m");
-    gCloudCoverage = XPLMFindDataRef("sim/weather/cloud_coverage[0]");
-    gAmbientTemperature = XPLMFindDataRef("sim/weather/temperature_ambient_c");
-    gWindSpeed = XPLMFindDataRef("sim/weather/wind_speed_kt[0]");
-    gTimeOfDay = XPLMFindDataRef("sim/time/local_time_sec");
-    gAIAircraftX = XPLMFindDataRef("sim/multiplayer/position/plane1_x");
-    gAIAircraftY = XPLMFindDataRef("sim/multiplayer/position/plane1_y");
-    gAIAircraftZ = XPLMFindDataRef("sim/multiplayer/position/plane1_z");
-    gAIAircraftCount = XPLMFindDataRef("sim/operation/prefs/mult_max");
-    
-    // Additional datarefs for HUD display
-    gLocalDate = XPLMFindDataRef("sim/time/local_date_days");
-    gZuluTime = XPLMFindDataRef("sim/time/zulu_time_sec");
-    gLatitude = XPLMFindDataRef("sim/flightmodel/position/latitude");
-    gLongitude = XPLMFindDataRef("sim/flightmodel/position/longitude");
-    gAltitude = XPLMFindDataRef("sim/flightmodel/position/elevation");
- 
+
+     // Dataref for HUD control
+     gManipulatorDisabled = XPLMFindDataRef("sim/operation/prefs/misc/manipulator_disabled");
+
+     // Initialize lock-on system
+     InitializeLockOnSystem();
+
      // Register hotkeys
      gActivateKey = XPLMRegisterHotKey(XPLM_VK_F9, xplm_DownFlag,
                                        "Activate FLIR Camera",
@@ -214,16 +139,7 @@ static float GetDistanceToCamera(float x, float y, float z);
      gTiltDownKey = XPLMRegisterHotKey(XPLM_VK_DOWN, xplm_DownFlag,
                                        "FLIR Tilt Down",
                                        TiltDownCallback, NULL);
- 
-     // Register thermal overlay drawing callback - use objects phase for better integration
-     // Register 2D drawing callback for overlay - per SDK guidance for overlays/annotations  
-    // Only register when camera is active to minimize performance overhead
-    // Drawing callback will be registered dynamically when camera is activated
- 
-     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 target lock\n");
-     
+
      gThermalToggleKey = XPLMRegisterHotKey(XPLM_VK_T, xplm_DownFlag,
                                            "FLIR Thermal Toggle",
                                            ThermalToggleCallback, NULL);
@@ -231,9 +147,11 @@ static float GetDistanceToCamera(float x, float y, float z);
     gFocusLockKey = XPLMRegisterHotKey(XPLM_VK_SPACE, xplm_DownFlag,
                                       "FLIR Focus/Lock Target",
                                       FocusLockCallback, NULL);
-    
-    // Note: For text display, use FlyWithLua to read standard X-Plane datarefs
- 
+
+     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");
+     
      return 1;
  }
  
@@ -249,13 +167,13 @@ static float GetDistanceToCamera(float x, float y, float z);
      if (gTiltDownKey) XPLMUnregisterHotKey(gTiltDownKey);
     if (gThermalToggleKey) XPLMUnregisterHotKey(gThermalToggleKey);
     if (gFocusLockKey) XPLMUnregisterHotKey(gFocusLockKey);
- 
+
      // Stop camera control if active
      if (gCameraActive) {
          XPLMDontControlCamera();
          gCameraActive = 0;
      }
- 
+
      XPLMDebugString("FLIR Camera System: Plugin stopped\n");
  }
  
@@ -270,15 +188,16 @@ static float GetDistanceToCamera(float x, float y, float z);
          // Activate FLIR camera
          XPLMDebugString("FLIR Camera System: Activating camera\n");
          
-         // Switch to external view first
-         // XPLMCommandButtonPress(xplm_joy_v_fr1);
-         // XPLMCommandButtonRelease(xplm_joy_v_fr1);
-         
          // Take camera control
          XPLMControlCamera(xplm_ControlCameraUntilViewChanges, FLIRCameraFunc, NULL);
          gCameraActive = 1;
         
-        // Register 2D drawing callback for overlays (per SDK guidance)
+        // Set manipulator disabled for HUD control
+        if (gManipulatorDisabled) {
+            XPLMSetDatai(gManipulatorDisabled, 1);
+        }
+        
+        // Register 2D drawing callback for overlays
         if (!gDrawCallbackRegistered) {
             XPLMRegisterDrawCallback(DrawThermalOverlay, xplm_Phase_Window, 0, NULL);
             gDrawCallbackRegistered = 1;
@@ -290,6 +209,15 @@ static float GetDistanceToCamera(float x, float y, float z);
          // Deactivate camera
          XPLMDontControlCamera();
          gCameraActive = 0;
+         
+         // Re-enable manipulator
+         if (gManipulatorDisabled) {
+             XPLMSetDatai(gManipulatorDisabled, 0);
+         }
+         
+         // Disable lock-on when camera deactivated
+         DisableLockOn();
+         
          // Unregister drawing callback to save performance
         if (gDrawCallbackRegistered) {
             XPLMUnregisterDrawCallback(DrawThermalOverlay, xplm_Phase_Window, 0, NULL);
@@ -348,7 +276,7 @@ static float GetDistanceToCamera(float x, float y, float z);
  
  static void PanLeftCallback(void* inRefcon)
  {
-     if (gCameraActive) {
+     if (gCameraActive && !IsLockOnActive()) { // Only when not locked
          gCameraPan -= 0.5f; // Very sensitive control
          if (gCameraPan < -180.0f) gCameraPan += 360.0f;
          char msg[256];
@@ -359,7 +287,7 @@ static float GetDistanceToCamera(float x, float y, float z);
  
  static void PanRightCallback(void* inRefcon)
  {
-     if (gCameraActive) {
+     if (gCameraActive && !IsLockOnActive()) { // Only when not locked
          gCameraPan += 0.5f; // Very sensitive control
          if (gCameraPan > 180.0f) gCameraPan -= 360.0f;
          char msg[256];
@@ -370,7 +298,7 @@ static float GetDistanceToCamera(float x, float y, float z);
  
  static void TiltUpCallback(void* inRefcon)
  {
-     if (gCameraActive) {
+     if (gCameraActive && !IsLockOnActive()) { // Only when not locked
          gCameraTilt = fminf(gCameraTilt + 0.5f, 45.0f); // Very sensitive control
          char msg[256];
          sprintf(msg, "FLIR Camera System: Tilt %.1f degrees\n", gCameraTilt);
@@ -380,7 +308,7 @@ static float GetDistanceToCamera(float x, float y, float z);
  
  static void TiltDownCallback(void* inRefcon)
  {
-     if (gCameraActive) {
+     if (gCameraActive && !IsLockOnActive()) { // Only when not locked
          gCameraTilt = fmaxf(gCameraTilt - 0.5f, -90.0f); // Very sensitive control
          char msg[256];
          sprintf(msg, "FLIR Camera System: Tilt %.1f degrees\n", gCameraTilt);
@@ -398,911 +326,209 @@ static float GetDistanceToCamera(float x, float y, float z);
          XPLMDebugString(msg);
      }
  }
+
+static void FocusLockCallback(void* inRefcon)
+{
+    if (gCameraActive) {
+        if (!IsLockOnActive()) {
+            // Lock on to current camera direction at 1000m distance
+            SetArbitraryLockPoint(gCameraPan, gCameraTilt, 1000.0f);
+            XPLMDebugString("FLIR Camera System: Lock-on activated\n");
+        } else {
+            // Disable lock-on
+            DisableLockOn();
+            XPLMDebugString("FLIR Camera System: Lock-on disabled\n");
+        }
+    }
+}
  
- /*
-  * FLIRCameraFunc
-  * 
-  * The main camera control function - positions camera under aircraft
-  * like a real belly-mounted FLIR system
-  */
+ // Camera control function
  static int FLIRCameraFunc(XPLMCameraPosition_t* outCameraPosition,
                            int inIsLosingControl,
                            void* inRefcon)
  {
-     if (outCameraPosition && !inIsLosingControl) {
-         // Get current aircraft position and orientation
-         float planeX = XPLMGetDataf(gPlaneX);
-         float planeY = XPLMGetDataf(gPlaneY);
-         float planeZ = XPLMGetDataf(gPlaneZ);
-         float planeHeading = XPLMGetDataf(gPlaneHeading);
-         // float planePitch = XPLMGetDataf(gPlanePitch); // unused for now
-         float planeRoll = XPLMGetDataf(gPlaneRoll);
- 
-         // Convert to radians
-         float headingRad = planeHeading * M_PI / 180.0f;
-         // float pitchRad = planePitch * M_PI / 180.0f; // unused
-         float rollRad = planeRoll * M_PI / 180.0f;
-         // float panRad = gCameraPan * M_PI / 180.0f; // unused
-         // float tiltRad = gCameraTilt * M_PI / 180.0f; // unused
- 
-         // Calculate camera position relative to aircraft
-         // Position camera under the aircraft (belly-mounted)
-         float localX = gCameraDistance * cosf(headingRad);
-         float localZ = gCameraDistance * sinf(headingRad);
-         float localY = gCameraHeight; // Below aircraft
- 
-         // Apply aircraft roll and pitch to camera position
-         float rotatedX = localX * cosf(rollRad) - localY * sinf(rollRad);
-         float rotatedY = localX * sinf(rollRad) + localY * cosf(rollRad);
-         float rotatedZ = localZ;
- 
-         // Final camera position in world coordinates
-         outCameraPosition->x = planeX + rotatedX;
-         outCameraPosition->y = planeY + rotatedY;
-         outCameraPosition->z = planeZ + rotatedZ;
- 
-         // Camera orientation - if locked, track target; otherwise manual control
-         if (gTargetLocked && gLockedTargetIndex >= 0 && gLockedTargetIndex < gHeatSourceCount) {
-             // Update target position from heat sources
-             gTargetX = gHeatSources[gLockedTargetIndex].x;
-             gTargetY = gHeatSources[gLockedTargetIndex].y;
-             gTargetZ = gHeatSources[gLockedTargetIndex].z;
-             
-             // Calculate angle to target
-             float dx = gTargetX - outCameraPosition->x;
-             float dy = gTargetY - outCameraPosition->y;
-             float dz = gTargetZ - outCameraPosition->z;
-             
-             // Calculate heading and pitch to target
-             float targetHeading = atan2f(dz, dx) * 180.0f / M_PI;
-             float groundDistance = sqrtf(dx*dx + dz*dz);
-             float targetPitch = -atan2f(dy, groundDistance) * 180.0f / M_PI;
-             
-             // Track the target automatically
-             outCameraPosition->heading = targetHeading;
-             outCameraPosition->pitch = targetPitch;
-         } else {
-             // Manual camera control
-             outCameraPosition->heading = planeHeading + gCameraPan;
-             outCameraPosition->pitch = gCameraTilt;
-         }
-         outCameraPosition->roll = 0.0f; // Keep camera level
- 
-         // Apply zoom - this is the key for real magnification!
-         outCameraPosition->zoom = gZoomLevel;
- 
-         // Normalize heading
-         if (outCameraPosition->heading > 360.0f) outCameraPosition->heading -= 360.0f;
-         if (outCameraPosition->heading < 0.0f) outCameraPosition->heading += 360.0f;
-     }
- 
      if (inIsLosingControl) {
+         // We're losing control, clean up
          gCameraActive = 0;
-         XPLMDebugString("FLIR Camera System: Lost camera control\n");
+         if (gDrawCallbackRegistered) {
+             XPLMUnregisterDrawCallback(DrawThermalOverlay, xplm_Phase_Window, 0, NULL);
+             gDrawCallbackRegistered = 0;
+         }
+         // Re-enable manipulator
+         if (gManipulatorDisabled) {
+             XPLMSetDatai(gManipulatorDisabled, 0);
+         }
+         DisableLockOn();
+         return 0;
      }
- 
-     return gCameraActive;
- }
- 
- /*
-  * DrawThermalOverlay
-  * 
-  * Draws thermal/IR overlay effects on the camera view
-  */
- static int DrawThermalOverlay(XPLMDrawingPhase inPhase, int inIsBefore, void* inRefcon)
- {
-     if (!gCameraActive) return 1;
-    
-    // Debug output to verify callback is being called
-    static int callCount = 0;
-    if (callCount < 5) {
-        char debugMsg[256];
-        sprintf(debugMsg, "FLIR Camera System: DrawThermalOverlay called, thermal mode: %d\n", gThermalMode);
-        XPLMDebugString(debugMsg);
-        callCount++;
-    }
-    
-    // Update environmental factors and heat sources
-    UpdateEnvironmentalFactors();
-    UpdateHeatSources();
-    DetectAircraft();
- 
-     // Set up OpenGL for 2D drawing with proper error checking
-     // Get screen dimensions
-    int screenWidth, screenHeight;
-    XPLMGetScreenSize(&screenWidth, &screenHeight);
-    
-    if (screenWidth <= 0 || screenHeight <= 0) {
-        return 1; // Avoid drawing with invalid screen dimensions
-    }
-    
-    // Save OpenGL state to prevent crashes
-    glPushAttrib(GL_ALL_ATTRIB_BITS);
-    
-    // Set up 2D rendering state
-    XPLMSetGraphicsState(0, 0, 0, 1, 1, 0, 0);
      
-     // Window phase provides proper 2D setup - no manual matrix setup needed
- 
-     // For Window phase, coordinate system is already set up by X-Plane
- 
-     float centerX = screenWidth / 2.0f;
-     float centerY = screenHeight / 2.0f;
+     if (!gPlaneX || !gPlaneY || !gPlaneZ || !gPlaneHeading || !gPlanePitch || !gPlaneRoll) {
+         return 1; // Keep control but don't update position
+     }
      
-     // Mouse control for camera movement
-     if (gCameraActive && !gTargetLocked) { // Only when not locked
+     // Get current aircraft position and orientation
+     float planeX = XPLMGetDataf(gPlaneX);
+     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)
+     if (!IsLockOnActive()) {
          int mouseX, mouseY;
          XPLMGetMouseLocation(&mouseX, &mouseY);
          
-         static int mouseInitialized = 0;
-         if (!mouseInitialized) {
-             gLastMouseX = mouseX;
-             gLastMouseY = mouseY;
-             mouseInitialized = 1;
-         }
-         
-         // Calculate mouse delta
-         int deltaX = mouseX - gLastMouseX;
-         int deltaY = mouseY - gLastMouseY;
-         
-         // Apply mouse movement to camera (much more sensitive)
-         if (abs(deltaX) > 1 || abs(deltaY) > 1) { // Only if significant movement
-             gCameraPan += deltaX * gMouseSensitivity;
-             gCameraTilt += deltaY * gMouseSensitivity;
+         if (gLastMouseX != 0 || gLastMouseY != 0) {
+             float deltaX = (mouseX - gLastMouseX) * gMouseSensitivity;
+             float deltaY = (mouseY - gLastMouseY) * gMouseSensitivity;
              
-             // Clamp values
-             if (gCameraPan > 180.0f) gCameraPan -= 360.0f;
-             if (gCameraPan < -180.0f) gCameraPan += 360.0f;
-             gCameraTilt = fmaxf(-90.0f, fminf(45.0f, gCameraTilt));
+             gCameraPan += deltaX;
+             gCameraTilt -= deltaY; // Invert Y for natural control
              
-             gLastMouseX = mouseX;
-             gLastMouseY = mouseY;
-         }
-     }
- 
-     // Draw targeting reticle
-     if (callCount < 3) {
-         char debugMsg[256];
-         sprintf(debugMsg, "FLIR: Drawing crosshair at %.0f,%.0f (screen %dx%d)\n", centerX, centerY, screenWidth, screenHeight);
-         XPLMDebugString(debugMsg);
-     }
-     
-     glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
-     glLineWidth(3.0f);
- 
-     glBegin(GL_LINES);
-     // No crosshair - only brackets
-     
-     // Military-style targeting brackets [ ] - FIXED SIZE
-     float bracketSize = 50.0f;  // Fixed size - doesn't change with zoom
-     float bracketLength = 20.0f;
-     
-     // Top-left bracket [
-     glVertex2f(centerX - bracketSize, centerY + bracketSize);
-     glVertex2f(centerX - bracketSize + bracketLength, centerY + bracketSize);
-     glVertex2f(centerX - bracketSize, centerY + bracketSize);
-     glVertex2f(centerX - bracketSize, centerY + bracketSize - bracketLength);
-     
-     // Top-right bracket ]
-     glVertex2f(centerX + bracketSize, centerY + bracketSize);
-     glVertex2f(centerX + bracketSize - bracketLength, centerY + bracketSize);
-     glVertex2f(centerX + bracketSize, centerY + bracketSize);
-     glVertex2f(centerX + bracketSize, centerY + bracketSize - bracketLength);
-     
-     // Bottom-left bracket [
-     glVertex2f(centerX - bracketSize, centerY - bracketSize);
-     glVertex2f(centerX - bracketSize + bracketLength, centerY - bracketSize);
-     glVertex2f(centerX - bracketSize, centerY - bracketSize);
-     glVertex2f(centerX - bracketSize, centerY - bracketSize + bracketLength);
-     
-     // Bottom-right bracket ]
-     glVertex2f(centerX + bracketSize, centerY - bracketSize);
-     glVertex2f(centerX + bracketSize - bracketLength, centerY - bracketSize);
-     glVertex2f(centerX + bracketSize, centerY - bracketSize);
-     glVertex2f(centerX + bracketSize, centerY - bracketSize + bracketLength);
-     
-     // Small center dot for precise aiming
-     glVertex2f(centerX - 2, centerY);
-     glVertex2f(centerX + 2, centerY);
-     glVertex2f(centerX, centerY - 2);
-     glVertex2f(centerX, centerY + 2);
-     glEnd();
- 
-     // Draw thermal effects based on thermal mode - using same reliable approach as crosshair
-     if (gThermalMode > 0) {
-         if (callCount < 3) {
-            char debugMsg[256];
-            sprintf(debugMsg, "FLIR: Drawing thermal overlay mode %d\n", gThermalMode);
-            XPLMDebugString(debugMsg);
-         }
-         
-         // Full-screen thermal overlay using same drawing method as crosshair
-         glEnable(GL_BLEND);
-         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-         
-         // Draw thermal background overlay
-         if (gThermalMode == 1) {
-             // White Hot mode - dark blue/black background
-             glColor4f(0.05f, 0.1f, 0.2f, 0.7f); // More opaque for realistic IR view
-         } else {
-             // Enhanced mode - greenish IR background  
-             glColor4f(0.1f, 0.3f, 0.1f, 0.6f);
-         }
-         
-         glBegin(GL_QUADS);
-         glVertex2f(0, 0);
-         glVertex2f(screenWidth, 0);
-         glVertex2f(screenWidth, screenHeight);
-         glVertex2f(0, screenHeight);
-         glEnd();
-         
-         // Realistic IR scan lines only (no random noise)
-         glLineWidth(1.0f);
-         glColor4f(0.0f, 0.0f, 0.0f, 0.15f);
-         
-         // Horizontal scan lines like real IR cameras
-         for (int y = 0; y < screenHeight; y += 2) {
-             glBegin(GL_LINES);
-             glVertex2f(0, y);
-             glVertex2f(screenWidth, y);
-             glEnd();
+             // Normalize pan angle
+             while (gCameraPan > 180.0f) gCameraPan -= 360.0f;
+             while (gCameraPan < -180.0f) gCameraPan += 360.0f;
+             
+             // Clamp tilt
+             if (gCameraTilt > 45.0f) gCameraTilt = 45.0f;
+             if (gCameraTilt < -90.0f) gCameraTilt = -90.0f;
          }
          
-         // Only draw realistic heat sources from actual detection, no fake test rectangles
-        
-        // Draw realistic heat sources if we have any
-        if (gHeatSourceCount > 0) {
-            DrawRealisticThermalOverlay();
-        }
-         
-         // No background thermal noise - cleaner IR view
-         
-         glDisable(GL_BLEND);
-     }
- 
-     // Draw realistic military FLIR HUD overlay
-     glColor4f(0.0f, 1.0f, 0.0f, 0.8f);
-     glLineWidth(1.0f);
-     
-     // Minimal corner reticles only (like real FLIR systems)
-     float reticleSize = 15.0f;
-     glBegin(GL_LINES);
-     // Top-left reticle
-     glVertex2f(30, 30); glVertex2f(30 + reticleSize, 30);
-     glVertex2f(30, 30); glVertex2f(30, 30 + reticleSize);
-     // Top-right reticle
-     glVertex2f(screenWidth - 30 - reticleSize, 30); glVertex2f(screenWidth - 30, 30);
-     glVertex2f(screenWidth - 30, 30); glVertex2f(screenWidth - 30, 30 + reticleSize);
-     // Bottom-left reticle
-     glVertex2f(30, screenHeight - 30 - reticleSize); glVertex2f(30, screenHeight - 30);
-     glVertex2f(30, screenHeight - 30); glVertex2f(30 + reticleSize, screenHeight - 30);
-     // Bottom-right reticle
-     glVertex2f(screenWidth - 30 - reticleSize, screenHeight - 30); glVertex2f(screenWidth - 30, screenHeight - 30);
-     glVertex2f(screenWidth - 30, screenHeight - 30); glVertex2f(screenWidth - 30, screenHeight - 30 - reticleSize);
-     glEnd();
-     
-     // Data will be exported to shared datarefs for FlyWithLua display
-     // For now, minimal built-in display only
-     
-     // Use X-Plane's text rendering for professional look
-     glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
-     
-     // Minimal status indicators (no confusing abstract lines)
-     // Only show essential info
-     
-     // Zoom level indicator (bottom-left corner only)
-     glLineWidth(2.0f);
-     glColor4f(0.0f, 1.0f, 0.0f, 0.8f);
-     glBegin(GL_LINES);
-     float zoomBar = fminf(gZoomLevel * 5.0f, 100.0f); // Scale zoom to reasonable bar length
-     glVertex2f(30, 40);
-     glVertex2f(30 + zoomBar, 40);
-     glEnd();
-     
-     // TARGET LOCK INDICATOR - VERY VISIBLE
-     if (gTargetLocked) {
-         glColor4f(1.0f, 0.0f, 0.0f, 1.0f); // Bright red for locked
-         glLineWidth(4.0f);
-         
-         // Large red box around the entire targeting area
-         glBegin(GL_LINE_LOOP);
-         glVertex2f(centerX - 100, centerY - 100);
-         glVertex2f(centerX + 100, centerY - 100);
-         glVertex2f(centerX + 100, centerY + 100);
-         glVertex2f(centerX - 100, centerY + 100);
-         glEnd();
-         
-         // Flashing corner indicators
-         float time = XPLMGetElapsedTime();
-         float flash = (sinf(time * 4.0f) + 1.0f) * 0.5f; // 0-1 flashing
-         glColor4f(1.0f, 0.0f, 0.0f, 0.5f + flash * 0.5f);
-         
-         glBegin(GL_LINES);
-         float lockSize = 30.0f;
-         // Top-left corner
-         glVertex2f(centerX - 100, centerY + 100 - lockSize); glVertex2f(centerX - 100, centerY + 100);
-         glVertex2f(centerX - 100, centerY + 100); glVertex2f(centerX - 100 + lockSize, centerY + 100);
-         // Top-right corner
-         glVertex2f(centerX + 100 - lockSize, centerY + 100); glVertex2f(centerX + 100, centerY + 100);
-         glVertex2f(centerX + 100, centerY + 100); glVertex2f(centerX + 100, centerY + 100 - lockSize);
-         // Bottom-left corner
-         glVertex2f(centerX - 100, centerY - 100 + lockSize); glVertex2f(centerX - 100, centerY - 100);
-         glVertex2f(centerX - 100, centerY - 100); glVertex2f(centerX - 100 + lockSize, centerY - 100);
-         // Bottom-right corner
-         glVertex2f(centerX + 100 - lockSize, centerY - 100); glVertex2f(centerX + 100, centerY - 100);
-         glVertex2f(centerX + 100, centerY - 100); glVertex2f(centerX + 100, centerY - 100 + lockSize);
-         glEnd();
-         
-         // LOCKED text indicator (top of screen)
-         glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
-         glLineWidth(3.0f);
-         glBegin(GL_LINES);
-         // Simple "LOCKED" text using lines at top center
-         float textY = screenHeight - 100;
-         // L
-         glVertex2f(centerX - 80, textY); glVertex2f(centerX - 80, textY - 20);
-         glVertex2f(centerX - 80, textY - 20); glVertex2f(centerX - 65, textY - 20);
-         // O
-         glVertex2f(centerX - 60, textY); glVertex2f(centerX - 45, textY);
-         glVertex2f(centerX - 60, textY - 20); glVertex2f(centerX - 45, textY - 20);
-         glVertex2f(centerX - 60, textY); glVertex2f(centerX - 60, textY - 20);
-         glVertex2f(centerX - 45, textY); glVertex2f(centerX - 45, textY - 20);
-         // C
-         glVertex2f(centerX - 40, textY); glVertex2f(centerX - 25, textY);
-         glVertex2f(centerX - 40, textY - 20); glVertex2f(centerX - 25, textY - 20);
-         glVertex2f(centerX - 40, textY); glVertex2f(centerX - 40, textY - 20);
-         // K
-         glVertex2f(centerX - 20, textY); glVertex2f(centerX - 20, textY - 20);
-         glVertex2f(centerX - 20, textY - 10); glVertex2f(centerX - 5, textY);
-         glVertex2f(centerX - 20, textY - 10); glVertex2f(centerX - 5, textY - 20);
-         // E
-         glVertex2f(centerX, textY); glVertex2f(centerX, textY - 20);
-         glVertex2f(centerX, textY); glVertex2f(centerX + 15, textY);
-         glVertex2f(centerX, textY - 10); glVertex2f(centerX + 10, textY - 10);
-         glVertex2f(centerX, textY - 20); glVertex2f(centerX + 15, textY - 20);
-         // D
-         glVertex2f(centerX + 20, textY); glVertex2f(centerX + 20, textY - 20);
-         glVertex2f(centerX + 20, textY); glVertex2f(centerX + 30, textY - 5);
-         glVertex2f(centerX + 30, textY - 5); glVertex2f(centerX + 30, textY - 15);
-         glVertex2f(centerX + 30, textY - 15); glVertex2f(centerX + 20, textY - 20);
-         glEnd();
+         gLastMouseX = mouseX;
+         gLastMouseY = mouseY;
+     } else {
+         // Update camera angles based on lock-on point
+         UpdateCameraToLockPoint(&gCameraPan, &gCameraTilt);
      }
      
-     // No range circles - clean display
+     // Calculate camera position (belly-mounted)
+     float headingRad = planeHeading * M_PI / 180.0f;
+     float pitchRad = planePitch * M_PI / 180.0f;
+     float rollRad = planeRoll * M_PI / 180.0f;
      
-     // Heading indicator (top center)
-     glColor4f(0.0f, 1.0f, 0.0f, 0.9f);
-     glLineWidth(2.0f);
-     float headingX = centerX;
-     float headingY = screenHeight - 40;
-     float currentHeading = XPLMGetDataf(gPlaneHeading);
+     // 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);
      
-     glBegin(GL_LINES);
-     // Heading scale
-     for (int h = 0; h < 360; h += 30) {
-         float angle = (h - currentHeading - gCameraPan) * M_PI / 180.0f;
-         float x1 = headingX + 100 * sinf(angle);
-         float x2 = headingX + 110 * sinf(angle);
-         if (x1 > 50 && x1 < screenWidth - 50) {
-             glVertex2f(x1, headingY);
-             glVertex2f(x2, headingY);
-         }
-     }
-     glEnd();
+     // Camera orientation (pan/tilt relative to aircraft heading)
+     outCameraPosition->heading = planeHeading + gCameraPan;
+     outCameraPosition->pitch = gCameraTilt;
+     outCameraPosition->roll = 0.0f; // Keep camera level
      
-     // Center heading marker
-     glBegin(GL_LINES);
-     glVertex2f(headingX, headingY - 10);
-     glVertex2f(headingX, headingY + 10);
-     glEnd();
+     // Apply zoom
+     outCameraPosition->zoom = gZoomLevel;
      
-     // Restore OpenGL state to prevent crashes
-     glPopAttrib();
-     
-     return 1;
- }
- 
- /*
-  * Additional utility functions for future enhancements
-  */
- 
- // Function to detect and track actual X-Plane objects
- /*
-static void UpdateTargetTracking(void)
- {
-     // Future enhancement: Use X-Plane's object detection APIs
-     // to find and track actual aircraft, ships, vehicles in the sim
+     return 1; // Keep controlling camera
  }
  
- // Function to simulate different thermal/IR modes
- static void SetThermalMode(int mode)
+ // Drawing callback for thermal overlay
+ static int DrawThermalOverlay(XPLMDrawingPhase inPhase,
+                              int inIsBefore,
+                              void* inRefcon)
  {
-     // Future enhancement: Different thermal rendering modes
-     // 0 = White Hot, 1 = Black Hot, 2 = Rainbow, etc.
+     if (!gCameraActive) return 1;
+     
+     DrawRealisticThermalOverlay();
+     
+     return 1;
  }
-*/
-/*
- * Enhanced Functions for FLIR Camera Plugin
- * These functions provide realistic thermal detection and environmental factors
- */
-
-/*
- * UpdateEnvironmentalFactors
- * 
- * Updates environmental conditions that affect thermal visibility
- */
-static void UpdateEnvironmentalFactors(void)
-{
-    if (gWeatherVisibility != NULL) {
-        gCurrentVisibility = XPLMGetDataf(gWeatherVisibility);
-    }
-    
-    if (gAmbientTemperature != NULL) {
-        gCurrentTemp = XPLMGetDataf(gAmbientTemperature);
-    }
-    
-    if (gWindSpeed != NULL) {
-        gCurrentWindSpeed = XPLMGetDataf(gWindSpeed);
-    }
-    
-    if (gTimeOfDay != NULL) {
-        float timeOfDay = XPLMGetDataf(gTimeOfDay);
-        // Night is roughly 18:00 to 06:00 (18*3600 = 64800, 6*3600 = 21600)
-        gIsNight = (timeOfDay > 64800.0f || timeOfDay < 21600.0f) ? 1 : 0;
-    }
-}
-
-/*
- * GetDistanceToCamera
- * 
- * Calculate distance from world position to camera
- */
-static float GetDistanceToCamera(float x, float y, float z)
-{
-    float camX = XPLMGetDataf(gPlaneX);
-    float camY = XPLMGetDataf(gPlaneY);
-    float camZ = XPLMGetDataf(gPlaneZ);
-    
-    float dx = x - camX;
-    float dy = y - camY;
-    float dz = z - camZ;
-    
-    return sqrtf(dx*dx + dy*dy + dz*dz);
-}
-
-/*
- * CalculateHeatIntensity
- * 
- * Calculate thermal intensity based on engine temperature and distance
- */
-static float CalculateHeatIntensity(float engineTemp, float distance, int engineRunning)
-{
-    if (!engineRunning) return 0.1f; // Cold engine still slightly visible
-    
-    // Base intensity from engine temperature (EGT typically 400-900°C)
-    float baseIntensity = (engineTemp - 200.0f) / 700.0f;
-    baseIntensity = fmaxf(0.0f, fminf(1.0f, baseIntensity));
-    
-    // Distance attenuation (max detection ~10km for aircraft)
-    float distanceFactor = 1.0f - (distance / 10000.0f);
-    distanceFactor = fmaxf(0.0f, distanceFactor);
-    
-    // Weather effects
-    float weatherFactor = gCurrentVisibility / 10000.0f;
-    weatherFactor = fmaxf(0.2f, fminf(1.0f, weatherFactor));
-    
-    // Night enhances thermal contrast
-    float nightBonus = gIsNight ? 1.3f : 1.0f;
-    
-    return baseIntensity * distanceFactor * weatherFactor * nightBonus;
-}
-
-/*
- * DetectAircraft
- * 
- * Scan for AI aircraft and other heat sources in the simulation
- */
-static void DetectAircraft(void)
-{
-    gAircraftCount = 0;
-    
-    // Debug output for aircraft detection
-    static int detectCallCount = 0;
-    detectCallCount++;
-    if (detectCallCount % 300 == 1) { // Every ~5 seconds
-        XPLMDebugString("FLIR Camera System: Scanning for AI aircraft and ships...\n");
-    }
-    
-    // **1. Detect AI Aircraft (much more common than multiplayer)**
-    // X-Plane has up to 63 AI aircraft slots
-    for (int i = 0; i < 63 && gAircraftCount < 20; i++) {
-        char datarefName[256];
-        
-        // AI aircraft positions
-        sprintf(datarefName, "sim/multiplayer/position/plane%d_x", i + 1);
-        XPLMDataRef aircraftX = XPLMFindDataRef(datarefName);
-        sprintf(datarefName, "sim/multiplayer/position/plane%d_y", i + 1);
-        XPLMDataRef aircraftY = XPLMFindDataRef(datarefName);
-        sprintf(datarefName, "sim/multiplayer/position/plane%d_z", i + 1);
-        XPLMDataRef aircraftZ = XPLMFindDataRef(datarefName);
-        
-        if (aircraftX && aircraftY && aircraftZ) {
-            float x = XPLMGetDataf(aircraftX);
-            float y = XPLMGetDataf(aircraftY);
-            float z = XPLMGetDataf(aircraftZ);
-            
-            // Check if aircraft exists and is not our own plane
-            if ((x != 0.0f || y != 0.0f || z != 0.0f)) {
-                float distance = GetDistanceToCamera(x, y, z);
-                if (distance > 50.0f) { // Minimum distance to avoid locking on self
-                    gAircraftPositions[gAircraftCount][0] = x;
-                    gAircraftPositions[gAircraftCount][1] = y;
-                    gAircraftPositions[gAircraftCount][2] = z;
-                    gAircraftDistance[gAircraftCount] = distance;
-                    
-                    // Simulate engine temperature (realistic EGT values)
-                    gAircraftEngineTemp[gAircraftCount] = 450.0f + (rand() % 300);
-                    
-                    // Determine visibility based on distance and conditions
-                    gAircraftVisible[gAircraftCount] = (distance < gCurrentVisibility * 0.8f) ? 1 : 0;
-                    
-                    if (detectCallCount % 300 == 1) {
-                        char debugMsg[256];
-                        sprintf(debugMsg, "FLIR: Found AI aircraft %d at %.0fm\n", i+1, distance);
-                        XPLMDebugString(debugMsg);
-                    }
-                    
-                    gAircraftCount++;
-                }
-            }
-        }
-    }
-    
-    // **2. Detect Ships - try multiple ship/boat datarefs**
-    
-    // Method 1: Try ground vehicle datarefs that might be ships
-    XPLMDataRef shipX = XPLMFindDataRef("sim/flightmodel2/position/local_x");
-    XPLMDataRef shipY = XPLMFindDataRef("sim/flightmodel2/position/local_y"); 
-    XPLMDataRef shipZ = XPLMFindDataRef("sim/flightmodel2/position/local_z");
-    
-    if (shipX && shipY && shipZ && gAircraftCount < 20) {
-        float x = XPLMGetDataf(shipX);
-        float y = XPLMGetDataf(shipY);
-        float z = XPLMGetDataf(shipZ);
-        
-        if (x != 0.0f || y != 0.0f || z != 0.0f) {
-            float distance = GetDistanceToCamera(x, y, z);
-            if (distance > 50.0f) {
-                gAircraftPositions[gAircraftCount][0] = x;
-                gAircraftPositions[gAircraftCount][1] = y;
-                gAircraftPositions[gAircraftCount][2] = z;
-                gAircraftDistance[gAircraftCount] = distance;
-                gAircraftEngineTemp[gAircraftCount] = 250.0f + (rand() % 150); // Ships have lower heat
-                gAircraftVisible[gAircraftCount] = (distance < gCurrentVisibility) ? 1 : 0;
-                
-                if (detectCallCount % 300 == 1) {
-                    char debugMsg[256];
-                    sprintf(debugMsg, "FLIR: Found ship/vehicle at %.0fm\n", distance);
-                    XPLMDebugString(debugMsg);
-                }
-                gAircraftCount++;
-            }
-        }
-    }
-    
-    // Method 2: AI boat datarefs
-    for (int i = 0; i < 10 && gAircraftCount < 20; i++) {
-        char datarefName[256];
-        sprintf(datarefName, "sim/multiplayer/position/boat%d_x", i + 1);
-        XPLMDataRef boatX = XPLMFindDataRef(datarefName);
-        sprintf(datarefName, "sim/multiplayer/position/boat%d_y", i + 1);
-        XPLMDataRef boatY = XPLMFindDataRef(datarefName);
-        sprintf(datarefName, "sim/multiplayer/position/boat%d_z", i + 1);
-        XPLMDataRef boatZ = XPLMFindDataRef(datarefName);
-        
-        if (boatX && boatY && boatZ) {
-            float x = XPLMGetDataf(boatX);
-            float y = XPLMGetDataf(boatY);
-            float z = XPLMGetDataf(boatZ);
-            
-            if (x != 0.0f || y != 0.0f || z != 0.0f) {
-                float distance = GetDistanceToCamera(x, y, z);
-                if (distance > 50.0f) {
-                    gAircraftPositions[gAircraftCount][0] = x;
-                    gAircraftPositions[gAircraftCount][1] = y;
-                    gAircraftPositions[gAircraftCount][2] = z;
-                    gAircraftDistance[gAircraftCount] = distance;
-                    
-                    // Ships have engine heat too
-                    gAircraftEngineTemp[gAircraftCount] = 300.0f + (rand() % 200);
-                    gAircraftVisible[gAircraftCount] = (distance < gCurrentVisibility) ? 1 : 0;
-                    
-                    if (detectCallCount % 300 == 1) {
-                        char debugMsg[256];
-                        sprintf(debugMsg, "FLIR: Found ship %d at %.0fm\n", i+1, distance);
-                        XPLMDebugString(debugMsg);
-                    }
-                    
-                    gAircraftCount++;
-                }
-            }
-        }
-    }
-    
-    if (detectCallCount % 300 == 1) {
-        char debugMsg[256];
-        sprintf(debugMsg, "FLIR: Total targets found: %d\n", gAircraftCount);
-        XPLMDebugString(debugMsg);
-    }
-}
 
-/*
- * UpdateHeatSources
- * 
- * Update dynamic heat sources in the simulation
- */
-static void UpdateHeatSources(void)
-{
-    float currentTime = XPLMGetElapsedTime();
-    gHeatSourceCount = 0;
-    
-    // Add detected aircraft as heat sources
-    for (int i = 0; i < gAircraftCount && gHeatSourceCount < 50; i++) {
-        if (gAircraftVisible[i]) {
-            gHeatSources[gHeatSourceCount].x = gAircraftPositions[i][0];
-            gHeatSources[gHeatSourceCount].y = gAircraftPositions[i][1];
-            gHeatSources[gHeatSourceCount].z = gAircraftPositions[i][2];
-            gHeatSources[gHeatSourceCount].intensity = CalculateHeatIntensity(
-                gAircraftEngineTemp[i], gAircraftDistance[i], 1);
-            gHeatSources[gHeatSourceCount].size = 15.0f + (gHeatSources[gHeatSourceCount].intensity * 25.0f);
-            gHeatSources[gHeatSourceCount].type = 0; // Aircraft
-            gHeatSources[gHeatSourceCount].lastUpdate = currentTime;
-            gHeatSourceCount++;
-        }
-    }
-    
-    // Add simulated ground heat sources (buildings, vehicles, ships)
-    float planeX = XPLMGetDataf(gPlaneX);
-    float planeZ = XPLMGetDataf(gPlaneZ);
-    
-    // Simulate some heat sources around the area
-    for (int i = 0; i < 8 && gHeatSourceCount < 50; i++) {
-        float angle = (i * 45.0f) * M_PI / 180.0f;
-        float distance = 2000.0f + (i * 500.0f);
-        
-        float x = planeX + distance * cosf(angle);
-        float z = planeZ + distance * sinf(angle);
-        float y = XPLMGetDataf(gPlaneY) - 100.0f; // Ground level
-        
-        gHeatSources[gHeatSourceCount].x = x;
-        gHeatSources[gHeatSourceCount].y = y;
-        gHeatSources[gHeatSourceCount].z = z;
-        
-        // Vary intensity based on type and time
-        float baseIntensity = 0.3f;
-        if (gIsNight) baseIntensity += 0.2f; // More visible at night
-        
-        gHeatSources[gHeatSourceCount].intensity = baseIntensity + 
-            0.2f * sinf(currentTime * 0.1f + i);
-        gHeatSources[gHeatSourceCount].size = 8.0f + (gHeatSources[gHeatSourceCount].intensity * 12.0f);
-        gHeatSources[gHeatSourceCount].type = (i % 3) + 1; // Ships, vehicles, buildings
-        gHeatSources[gHeatSourceCount].lastUpdate = currentTime;
-        gHeatSourceCount++;
-    }
-}
-
-/*
- * DrawRealisticThermalOverlay
- * 
- * Render realistic thermal signatures for detected heat sources
- */
+// Realistic thermal overlay drawing
 static void DrawRealisticThermalOverlay(void)
 {
-    if (gHeatSourceCount == 0) return;
-    
-    // Get screen dimensions and camera info
     int screenWidth, screenHeight;
     XPLMGetScreenSize(&screenWidth, &screenHeight);
     
-    float camX = XPLMGetDataf(gPlaneX);
-    float camY = XPLMGetDataf(gPlaneY);
-    float camZ = XPLMGetDataf(gPlaneZ);
-    float camHeading = XPLMGetDataf(gPlaneHeading) + gCameraPan;
-    float camPitch = gCameraTilt;
-    
-    // Convert camera angles to radians
-    float headingRad = camHeading * M_PI / 180.0f;
-    float pitchRad = camPitch * M_PI / 180.0f;
-    
-    // Camera forward vector
-    float forwardX = cosf(headingRad) * cosf(pitchRad);
-    float forwardY = sinf(pitchRad);
-    float forwardZ = sinf(headingRad) * cosf(pitchRad);
+    // Set up OpenGL for 2D drawing
+    glMatrixMode(GL_PROJECTION);
+    glPushMatrix();
+    glLoadIdentity();
+    glOrtho(0, screenWidth, screenHeight, 0, -1, 1);
     
-    // Camera right vector (for screen mapping)
-    float rightX = -sinf(headingRad);
-    float rightZ = cosf(headingRad);
-    
-    // Camera up vector
-    float upX = -cosf(headingRad) * sinf(pitchRad);
-    float upY = cosf(pitchRad);
-    float upZ = -sinf(headingRad) * sinf(pitchRad);
-    
-    // Field of view factor (approximate)
-    float fovFactor = 60.0f / gZoomLevel; // Base FOV 60 degrees
+    glMatrixMode(GL_MODELVIEW);
+    glPushMatrix();
+    glLoadIdentity();
     
+    // Disable depth testing for overlay
+    glDisable(GL_DEPTH_TEST);
     glEnable(GL_BLEND);
     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
     
-    // Draw each heat source
-    for (int i = 0; i < gHeatSourceCount; i++) {
-        HeatSource* heat = &gHeatSources[i];
-        
-        // Vector from camera to heat source
-        float dx = heat->x - camX;
-        float dy = heat->y - camY;
-        float dz = heat->z - camZ;
-        float distance = sqrtf(dx*dx + dy*dy + dz*dz);
-        
-        if (distance < 50.0f) continue; // Too close, skip
-        
-        // Normalize direction vector
-        dx /= distance;
-        dy /= distance;
-        dz /= distance;
-        
-        // Check if heat source is in front of camera
-        float dotForward = dx * forwardX + dy * forwardY + dz * forwardZ;
-        if (dotForward <= 0.1f) continue; // Behind camera or too far to side
-        
-        // Project to screen coordinates
-        float rightDot = dx * rightX + dz * rightZ;
-        float upDot = dx * upX + dy * upY + dz * upZ;
-        
-        // Convert to screen space
-        float screenX = screenWidth * 0.5f + (rightDot * screenWidth * 0.5f / fovFactor);
-        float screenY = screenHeight * 0.5f + (upDot * screenHeight * 0.5f / fovFactor);
-        
-        // Check if on screen
-        if (screenX < 0 || screenX >= screenWidth || screenY < 0 || screenY >= screenHeight) {
-            continue;
-        }
-        
-        // Calculate apparent size based on distance and zoom
-        float apparentSize = heat->size * gZoomLevel / (distance * 0.01f);
-        apparentSize = fmaxf(3.0f, fminf(apparentSize, 50.0f));
-        
-        // Color based on heat source type and intensity
-        float r, g, b, a;
-        if (gThermalMode == 1) {
-            // White hot mode
-            r = g = b = heat->intensity;
-            a = heat->intensity * 0.8f;
-            
-            // Aircraft show as very bright white
-            if (heat->type == 0) {
-                r = g = b = 1.0f;
-                a = 0.9f;
-            }
-        } else {
-            // Enhanced mode - use color coding
-            switch (heat->type) {
-                case 0: // Aircraft - bright yellow/orange
-                    r = 1.0f;
-                    g = 0.8f;
-                    b = 0.2f;
-                    a = heat->intensity * 0.9f;
-                    break;
-                case 1: // Ships - cyan
-                    r = 0.2f;
-                    g = 0.8f;
-                    b = 1.0f;
-                    a = heat->intensity * 0.7f;
-                    break;
-                case 2: // Vehicles - red
-                    r = 1.0f;
-                    g = 0.3f;
-                    b = 0.1f;
-                    a = heat->intensity * 0.6f;
-                    break;
-                case 3: // Buildings - orange
-                    r = 1.0f;
-                    g = 0.5f;
-                    b = 0.0f;
-                    a = heat->intensity * 0.5f;
-                    break;
-                default:
-                    r = g = b = heat->intensity;
-                    a = heat->intensity * 0.6f;
-                    break;
-            }
-        }
-        
-        glColor4f(r, g, b, a);
-        
-        // Draw heat signature with gradient effect
+    // Draw thermal border effect if thermal mode is active
+    if (gThermalMode > 0) {
+        glColor4f(0.0f, 1.0f, 0.0f, 0.3f); // Subtle green tint
         glBegin(GL_QUADS);
-        glVertex2f(screenX - apparentSize, screenY - apparentSize);
-        glVertex2f(screenX + apparentSize, screenY - apparentSize);
-        glVertex2f(screenX + apparentSize, screenY + apparentSize);
-        glVertex2f(screenX - apparentSize, screenY + apparentSize);
+        // Top border
+        glVertex2f(0, 0);
+        glVertex2f(screenWidth, 0);
+        glVertex2f(screenWidth, 20);
+        glVertex2f(0, 20);
+        // Bottom border
+        glVertex2f(0, screenHeight - 20);
+        glVertex2f(screenWidth, screenHeight - 20);
+        glVertex2f(screenWidth, screenHeight);
+        glVertex2f(0, screenHeight);
         glEnd();
-        
-        // Add heat bloom effect for intense sources
-        if (heat->intensity > 0.7f) {
-            float bloomSize = apparentSize * 1.5f;
-            glColor4f(r, g, b, a * 0.3f);
-            glBegin(GL_QUADS);
-            glVertex2f(screenX - bloomSize, screenY - bloomSize);
-            glVertex2f(screenX + bloomSize, screenY - bloomSize);
-            glVertex2f(screenX + bloomSize, screenY + bloomSize);
-            glVertex2f(screenX - bloomSize, screenY + bloomSize);
-            glEnd();
-        }
-        
-        // Add targeting indicator for aircraft
-        if (heat->type == 0 && distance < 5000.0f) {
-            glColor4f(0.0f, 1.0f, 0.0f, 0.8f);
-            glLineWidth(2.0f);
-            
-            float targetSize = apparentSize + 10.0f;
-            glBegin(GL_LINE_LOOP);
-            glVertex2f(screenX - targetSize, screenY - targetSize);
-            glVertex2f(screenX + targetSize, screenY - targetSize);
-            glVertex2f(screenX + targetSize, screenY + targetSize);
-            glVertex2f(screenX - targetSize, screenY + targetSize);
-            glEnd();
-            
-            // Add distance indicator
-            char distText[32];
-            sprintf(distText, "%.0fm", distance);
-            // Note: Actual text rendering would need XPLMDrawString
-        }
     }
     
-    glDisable(GL_BLEND);
-}
-
-static void FocusLockCallback(void* inRefcon)
-{
-    if (gCameraActive) {
-        if (!gTargetLocked) {
-            // Find nearest target to focus on
-            float nearestDistance = 999999.0f;
-            int nearestTarget = -1;
-            
-            // Check heat sources for nearest aircraft
-            for (int i = 0; i < gHeatSourceCount; i++) {
-                if (gHeatSources[i].type == 0) { // Aircraft
-                    float distance = GetDistanceToCamera(gHeatSources[i].x, gHeatSources[i].y, gHeatSources[i].z);
-                    if (distance < nearestDistance && distance > 100.0f) { // Minimum 100m distance
-                        nearestDistance = distance;
-                        nearestTarget = i;
-                    }
-                }
-            }
-            
-            if (nearestTarget >= 0) {
-                gTargetLocked = 1;
-                gLockedTargetIndex = nearestTarget;
-                gFocusDistance = nearestDistance;
-                gTargetX = gHeatSources[nearestTarget].x;
-                gTargetY = gHeatSources[nearestTarget].y;
-                gTargetZ = gHeatSources[nearestTarget].z;
-                char msg[256];
-                sprintf(msg, "FLIR Camera System: Target LOCKED at %.0fm - Camera will track automatically\n", gFocusDistance);
-                XPLMDebugString(msg);
-            } else {
-                char debugMsg[256];
-                sprintf(debugMsg, "FLIR Camera System: No targets found - Heat sources: %d, Aircraft: %d\n", 
-                        gHeatSourceCount, gAircraftCount);
-                XPLMDebugString(debugMsg);
-            }
-        } else {
-            // Unlock target
-            gTargetLocked = 0;
-            gLockedTargetIndex = -1;
-            XPLMDebugString("FLIR Camera System: Target UNLOCKED - Manual control restored\n");
-        }
+    // Military-style targeting brackets [ ] - FIXED SIZE
+    float centerX = screenWidth / 2.0f;
+    float centerY = screenHeight / 2.0f;
+    float bracketSize = 50.0f;  // Fixed size - doesn't change with zoom
+    float bracketLength = 20.0f;
+    
+    // Set color based on lock status
+    if (IsLockOnActive()) {
+        glColor4f(1.0f, 0.0f, 0.0f, 0.8f); // Red when locked
+    } else {
+        glColor4f(0.0f, 1.0f, 0.0f, 0.8f); // Green when scanning
     }
+    
+    glLineWidth(2.0f);
+    glBegin(GL_LINES);
+    
+    // Top-left bracket [
+    glVertex2f(centerX - bracketSize, centerY - bracketSize);
+    glVertex2f(centerX - bracketSize + bracketLength, centerY - bracketSize);
+    glVertex2f(centerX - bracketSize, centerY - bracketSize);
+    glVertex2f(centerX - bracketSize, centerY - bracketSize + bracketLength);
+    
+    // Top-right bracket ]
+    glVertex2f(centerX + bracketSize, centerY - bracketSize);
+    glVertex2f(centerX + bracketSize - bracketLength, centerY - bracketSize);
+    glVertex2f(centerX + bracketSize, centerY - bracketSize);
+    glVertex2f(centerX + bracketSize, centerY - bracketSize + bracketLength);
+    
+    // Bottom-left bracket [
+    glVertex2f(centerX - bracketSize, centerY + bracketSize);
+    glVertex2f(centerX - bracketSize + bracketLength, centerY + bracketSize);
+    glVertex2f(centerX - bracketSize, centerY + bracketSize);
+    glVertex2f(centerX - bracketSize, centerY + bracketSize - bracketLength);
+    
+    // Bottom-right bracket ]
+    glVertex2f(centerX + bracketSize, centerY + bracketSize);
+    glVertex2f(centerX + bracketSize - bracketLength, centerY + bracketSize);
+    glVertex2f(centerX + bracketSize, centerY + bracketSize);
+    glVertex2f(centerX + bracketSize, centerY + bracketSize - bracketLength);
+    
+    glEnd();
+    
+    // Center dot
+    glPointSize(4.0f);
+    glBegin(GL_POINTS);
+    glVertex2f(centerX, centerY);
+    glEnd();
+    
+    // Restore OpenGL state
+    glEnable(GL_DEPTH_TEST);
+    glDisable(GL_BLEND);
+    glLineWidth(1.0f);
+    glPointSize(1.0f);
+    
+    glPopMatrix();
+    glMatrixMode(GL_PROJECTION);
+    glPopMatrix();
+    glMatrixMode(GL_MODELVIEW);
 }
\ No newline at end of file
diff --git a/FLIR_Camera.o b/FLIR_Camera.o
index 98a49b4..a527ffd 100644
Binary files a/FLIR_Camera.o and b/FLIR_Camera.o differ
diff --git a/FLIR_Camera_OLD.cpp b/FLIR_Camera_OLD.cpp
new file mode 100644
index 0000000..9e9cca2
--- /dev/null
+++ b/FLIR_Camera_OLD.cpp
@@ -0,0 +1,1308 @@
+/*
+ * FLIR_Camera.cpp
+ * 
+ * A realistic FLIR camera system plugin for X-Plane 12
+ * Features:
+ * - Real camera positioning under aircraft (belly-mounted)
+ * - True optical zoom with zoom parameter
+ * - Pan/tilt camera controls
+ * - Target acquisition and tracking
+ * - Thermal overlay rendering
+ * 
+ */
+
+ #include <string.h>
+ #include <stdio.h>
+ #include <math.h>
+ #ifndef M_PI
+ #define M_PI 3.14159265358979323846
+ #endif
+ #include "XPLMDisplay.h"
+ #include "XPLMUtilities.h"
+ #include "XPLMCamera.h"
+ #include "XPLMDataAccess.h"
+ #include "XPLMGraphics.h"
+ #include "XPLMProcessing.h"
+ #include "XPLMMenus.h"
+ #include "XPLMScenery.h"
+ #include "XPLMPlanes.h"
+#include "XPLMNavigation.h"
+#include "XPLMInstance.h"
+#include "XPLMWeather.h"
+
+ // OpenGL includes for MinGW
+ #include <windows.h>
+ #include <GL/gl.h>
+ 
+ // Plugin globals
+ static XPLMHotKeyID gActivateKey = NULL;
+ static XPLMHotKeyID gZoomInKey = NULL;
+ static XPLMHotKeyID gZoomOutKey = NULL;
+ static XPLMHotKeyID gPanLeftKey = NULL;
+ static XPLMHotKeyID gPanRightKey = NULL;
+ static XPLMHotKeyID gTiltUpKey = NULL;
+ static XPLMHotKeyID gTiltDownKey = NULL;
+static XPLMHotKeyID gThermalToggleKey = NULL;
+static XPLMHotKeyID gFocusLockKey = NULL;
+ 
+ // Aircraft position datarefs
+ static XPLMDataRef gPlaneX = NULL;
+ static XPLMDataRef gPlaneY = NULL;
+ static XPLMDataRef gPlaneZ = NULL;
+ static XPLMDataRef gPlaneHeading = NULL;
+ static XPLMDataRef gPlanePitch = NULL;
+ static XPLMDataRef gPlaneRoll = NULL;
+ 
+ // FLIR camera state
+ static int gCameraActive = 0;
+static int gDrawCallbackRegistered = 0;
+ static float gZoomLevel = 1.0f;
+ static float gCameraPan = 0.0f;      // Left/right rotation (degrees)
+ static float gCameraTilt = -15.0f;   // Up/down rotation (degrees)
+ static float gCameraHeight = -5.0f;  // Height below aircraft (meters)
+ static float gCameraDistance = 3.0f; // Forward/back from aircraft center
+
+// Mouse control for camera
+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
+ 
+ // Target tracking and object detection
+ static int gTargetLocked = 0;
+static float gFocusDistance = 1000.0f; // Distance to focused target
+ static float gTargetX = 0.0f; // World position of locked target
+ static float gTargetY = 0.0f;
+ static float gTargetZ = 0.0f;
+ static int gLockedTargetIndex = -1; // Index of locked target in heat sources
+
+ // Aircraft tracking arrays (up to 20 aircraft)
+ static float gAircraftPositions[20][3];  // x, y, z positions
+ static float gAircraftEngineTemp[20];    // Engine temperatures
+ static float gAircraftDistance[20];      // Distance from camera
+static int gAircraftVisible[20];         // Visibility in thermal
+static int gAircraftCount = 0;
+
+// Environmental factors
+static float gCurrentVisibility = 10000.0f;
+static float gCurrentTemp = 15.0f;
+static float gCurrentWindSpeed = 0.0f;
+static int gIsNight = 0;
+
+// Heat source simulation
+typedef struct {
+    float x, y, z;           // World position
+    float intensity;         // Heat intensity (0-1)
+    float size;             // Heat source size
+    int type;               // 0=aircraft, 1=ship, 2=vehicle, 3=building
+    float lastUpdate;       // Last update time
+} HeatSource;
+
+static HeatSource gHeatSources[50];
+static int gHeatSourceCount = 0;
+
+ // Additional datarefs for enhanced detection
+ static XPLMDataRef gEngineRunning = NULL;
+ static XPLMDataRef gEngineN1 = NULL;
+static XPLMDataRef gEngineEGT = NULL;
+static XPLMDataRef gGroundTemperature = NULL;
+static XPLMDataRef gWeatherVisibility = NULL;
+static XPLMDataRef gCloudCoverage = NULL;
+static XPLMDataRef gAmbientTemperature = NULL;
+static XPLMDataRef gWindSpeed = NULL;
+static XPLMDataRef gTimeOfDay = NULL;
+static XPLMDataRef gAIAircraftX = NULL;
+static XPLMDataRef gAIAircraftY = NULL;
+static XPLMDataRef gAIAircraftZ = NULL;
+static XPLMDataRef gAIAircraftCount = NULL;
+static XPLMDataRef gLocalDate = NULL;
+static XPLMDataRef gZuluTime = NULL;
+static XPLMDataRef gLatitude = NULL;
+static XPLMDataRef gLongitude = NULL;
+static XPLMDataRef gAltitude = NULL;
+ 
+ // Function declarations
+ static void ActivateFLIRCallback(void* inRefcon);
+ static void ZoomInCallback(void* inRefcon);
+ static void ZoomOutCallback(void* inRefcon);
+ static void PanLeftCallback(void* inRefcon);
+ static void PanRightCallback(void* inRefcon);
+ static void TiltUpCallback(void* inRefcon);
+ static void TiltDownCallback(void* inRefcon);
+static void ThermalToggleCallback(void* inRefcon);
+static void FocusLockCallback(void* inRefcon);
+ 
+ static int FLIRCameraFunc(XPLMCameraPosition_t* outCameraPosition, 
+                           int inIsLosingControl, 
+                           void* inRefcon);
+ 
+ static int DrawThermalOverlay(XPLMDrawingPhase inPhase,
+                              int inIsBefore,
+                              void* inRefcon);
+
+static void UpdateEnvironmentalFactors(void);
+static void UpdateHeatSources(void);
+static void DetectAircraft(void);
+static float CalculateHeatIntensity(float engineTemp, float distance, int engineRunning);
+static void DrawRealisticThermalOverlay(void);
+static float GetDistanceToCamera(float x, float y, float z);
+ 
+ // Plugin lifecycle functions
+ PLUGIN_API int XPluginStart(char* outName, char* outSig, char* outDesc)
+ {
+     strcpy(outName, "FLIR Camera System");
+     strcpy(outSig, "flir.camera.system");
+     strcpy(outDesc, "Realistic FLIR camera with zoom and thermal overlay");
+ 
+     // Get aircraft position datarefs
+     gPlaneX = XPLMFindDataRef("sim/flightmodel/position/local_x");
+     gPlaneY = XPLMFindDataRef("sim/flightmodel/position/local_y");
+     gPlaneZ = XPLMFindDataRef("sim/flightmodel/position/local_z");
+     gPlaneHeading = XPLMFindDataRef("sim/flightmodel/position/psi");
+     gPlanePitch = XPLMFindDataRef("sim/flightmodel/position/theta");
+     gPlaneRoll = XPLMFindDataRef("sim/flightmodel/position/phi");
+ 
+     // Additional datarefs for thermal detection
+     gEngineRunning = XPLMFindDataRef("sim/flightmodel/engine/ENGN_running");
+     gEngineN1 = XPLMFindDataRef("sim/flightmodel/engine/ENGN_N1_");
+    gEngineEGT = XPLMFindDataRef("sim/flightmodel/engine/ENGN_EGT_c");
+    gGroundTemperature = XPLMFindDataRef("sim/weather/temperature_sealevel_c");
+    gWeatherVisibility = XPLMFindDataRef("sim/weather/visibility_reported_m");
+    gCloudCoverage = XPLMFindDataRef("sim/weather/cloud_coverage[0]");
+    gAmbientTemperature = XPLMFindDataRef("sim/weather/temperature_ambient_c");
+    gWindSpeed = XPLMFindDataRef("sim/weather/wind_speed_kt[0]");
+    gTimeOfDay = XPLMFindDataRef("sim/time/local_time_sec");
+    gAIAircraftX = XPLMFindDataRef("sim/multiplayer/position/plane1_x");
+    gAIAircraftY = XPLMFindDataRef("sim/multiplayer/position/plane1_y");
+    gAIAircraftZ = XPLMFindDataRef("sim/multiplayer/position/plane1_z");
+    gAIAircraftCount = XPLMFindDataRef("sim/operation/prefs/mult_max");
+    
+    // Additional datarefs for HUD display
+    gLocalDate = XPLMFindDataRef("sim/time/local_date_days");
+    gZuluTime = XPLMFindDataRef("sim/time/zulu_time_sec");
+    gLatitude = XPLMFindDataRef("sim/flightmodel/position/latitude");
+    gLongitude = XPLMFindDataRef("sim/flightmodel/position/longitude");
+    gAltitude = XPLMFindDataRef("sim/flightmodel/position/elevation");
+ 
+     // Register hotkeys
+     gActivateKey = XPLMRegisterHotKey(XPLM_VK_F9, xplm_DownFlag,
+                                       "Activate FLIR Camera",
+                                       ActivateFLIRCallback, NULL);
+     
+     gZoomInKey = XPLMRegisterHotKey(XPLM_VK_EQUAL, xplm_DownFlag,
+                                     "FLIR Zoom In",
+                                     ZoomInCallback, NULL);
+     
+     gZoomOutKey = XPLMRegisterHotKey(XPLM_VK_MINUS, xplm_DownFlag,
+                                      "FLIR Zoom Out",
+                                      ZoomOutCallback, NULL);
+     
+     gPanLeftKey = XPLMRegisterHotKey(XPLM_VK_LEFT, xplm_DownFlag,
+                                      "FLIR Pan Left",
+                                      PanLeftCallback, NULL);
+     
+     gPanRightKey = XPLMRegisterHotKey(XPLM_VK_RIGHT, xplm_DownFlag,
+                                       "FLIR Pan Right",
+                                       PanRightCallback, NULL);
+     
+     gTiltUpKey = XPLMRegisterHotKey(XPLM_VK_UP, xplm_DownFlag,
+                                     "FLIR Tilt Up",
+                                     TiltUpCallback, NULL);
+     
+     gTiltDownKey = XPLMRegisterHotKey(XPLM_VK_DOWN, xplm_DownFlag,
+                                       "FLIR Tilt Down",
+                                       TiltDownCallback, NULL);
+ 
+     // Register thermal overlay drawing callback - use objects phase for better integration
+     // Register 2D drawing callback for overlay - per SDK guidance for overlays/annotations  
+    // Only register when camera is active to minimize performance overhead
+    // Drawing callback will be registered dynamically when camera is activated
+ 
+     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 target lock\n");
+     
+     gThermalToggleKey = XPLMRegisterHotKey(XPLM_VK_T, xplm_DownFlag,
+                                           "FLIR Thermal Toggle",
+                                           ThermalToggleCallback, NULL);
+    
+    gFocusLockKey = XPLMRegisterHotKey(XPLM_VK_SPACE, xplm_DownFlag,
+                                      "FLIR Focus/Lock Target",
+                                      FocusLockCallback, NULL);
+    
+    // Note: For text display, use FlyWithLua to read standard X-Plane datarefs
+ 
+     return 1;
+ }
+ 
+ PLUGIN_API void XPluginStop(void)
+ {
+     // Unregister hotkeys
+     if (gActivateKey) XPLMUnregisterHotKey(gActivateKey);
+     if (gZoomInKey) XPLMUnregisterHotKey(gZoomInKey);
+     if (gZoomOutKey) XPLMUnregisterHotKey(gZoomOutKey);
+     if (gPanLeftKey) XPLMUnregisterHotKey(gPanLeftKey);
+     if (gPanRightKey) XPLMUnregisterHotKey(gPanRightKey);
+     if (gTiltUpKey) XPLMUnregisterHotKey(gTiltUpKey);
+     if (gTiltDownKey) XPLMUnregisterHotKey(gTiltDownKey);
+    if (gThermalToggleKey) XPLMUnregisterHotKey(gThermalToggleKey);
+    if (gFocusLockKey) XPLMUnregisterHotKey(gFocusLockKey);
+ 
+     // Stop camera control if active
+     if (gCameraActive) {
+         XPLMDontControlCamera();
+         gCameraActive = 0;
+     }
+ 
+     XPLMDebugString("FLIR Camera System: Plugin stopped\n");
+ }
+ 
+ PLUGIN_API void XPluginDisable(void) { }
+ PLUGIN_API int XPluginEnable(void) { return 1; }
+ PLUGIN_API void XPluginReceiveMessage(XPLMPluginID inFromWho, int inMessage, void* inParam) { }
+ 
+ // Hotkey callbacks
+ static void ActivateFLIRCallback(void* inRefcon)
+ {
+     if (!gCameraActive) {
+         // Activate FLIR camera
+         XPLMDebugString("FLIR Camera System: Activating camera\n");
+         
+         // Switch to external view first
+         // XPLMCommandButtonPress(xplm_joy_v_fr1);
+         // XPLMCommandButtonRelease(xplm_joy_v_fr1);
+         
+         // Take camera control
+         XPLMControlCamera(xplm_ControlCameraUntilViewChanges, FLIRCameraFunc, NULL);
+         gCameraActive = 1;
+        
+        // Register 2D drawing callback for overlays (per SDK guidance)
+        if (!gDrawCallbackRegistered) {
+            XPLMRegisterDrawCallback(DrawThermalOverlay, xplm_Phase_Window, 0, NULL);
+            gDrawCallbackRegistered = 1;
+            XPLMDebugString("FLIR Camera System: 2D overlay callback registered\n");
+        }
+         
+         XPLMDebugString("FLIR Camera System: Camera active - mounted under aircraft\n");
+     } else {
+         // Deactivate camera
+         XPLMDontControlCamera();
+         gCameraActive = 0;
+         // Unregister drawing callback to save performance
+        if (gDrawCallbackRegistered) {
+            XPLMUnregisterDrawCallback(DrawThermalOverlay, xplm_Phase_Window, 0, NULL);
+            gDrawCallbackRegistered = 0;
+            XPLMDebugString("FLIR Camera System: 2D overlay callback unregistered\n");
+        }
+        
+        XPLMDebugString("FLIR Camera System: Camera deactivated\n");
+     }
+ }
+ 
+ static void ZoomInCallback(void* inRefcon)
+ {
+     if (gCameraActive) {
+         // More precise zoom steps: 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 8.0, 12.0, 16.0, 24.0, 32.0, 48.0, 64.0
+        if (gZoomLevel < 1.5f) gZoomLevel = 1.5f;
+        else if (gZoomLevel < 2.0f) gZoomLevel = 2.0f;
+        else if (gZoomLevel < 3.0f) gZoomLevel = 3.0f;
+        else if (gZoomLevel < 4.0f) gZoomLevel = 4.0f;
+        else if (gZoomLevel < 6.0f) gZoomLevel = 6.0f;
+        else if (gZoomLevel < 8.0f) gZoomLevel = 8.0f;
+        else if (gZoomLevel < 12.0f) gZoomLevel = 12.0f;
+        else if (gZoomLevel < 16.0f) gZoomLevel = 16.0f;
+        else if (gZoomLevel < 24.0f) gZoomLevel = 24.0f;
+        else if (gZoomLevel < 32.0f) gZoomLevel = 32.0f;
+        else if (gZoomLevel < 48.0f) gZoomLevel = 48.0f;
+        else if (gZoomLevel < 64.0f) gZoomLevel = 64.0f;
+        else gZoomLevel = 64.0f; // Maximum zoom
+         char msg[256];
+         sprintf(msg, "FLIR Camera System: Zoom %.1fx\n", gZoomLevel);
+         XPLMDebugString(msg);
+     }
+ }
+ 
+ static void ZoomOutCallback(void* inRefcon)
+ {
+     if (gCameraActive) {
+         // Reverse zoom steps
+        if (gZoomLevel > 48.0f) gZoomLevel = 48.0f;
+        else if (gZoomLevel > 32.0f) gZoomLevel = 32.0f;
+        else if (gZoomLevel > 24.0f) gZoomLevel = 24.0f;
+        else if (gZoomLevel > 16.0f) gZoomLevel = 16.0f;
+        else if (gZoomLevel > 12.0f) gZoomLevel = 12.0f;
+        else if (gZoomLevel > 8.0f) gZoomLevel = 8.0f;
+        else if (gZoomLevel > 6.0f) gZoomLevel = 6.0f;
+        else if (gZoomLevel > 4.0f) gZoomLevel = 4.0f;
+        else if (gZoomLevel > 3.0f) gZoomLevel = 3.0f;
+        else if (gZoomLevel > 2.0f) gZoomLevel = 2.0f;
+        else if (gZoomLevel > 1.5f) gZoomLevel = 1.5f;
+        else gZoomLevel = 1.0f; // Minimum zoom
+         char msg[256];
+         sprintf(msg, "FLIR Camera System: Zoom %.1fx\n", gZoomLevel);
+         XPLMDebugString(msg);
+     }
+ }
+ 
+ static void PanLeftCallback(void* inRefcon)
+ {
+     if (gCameraActive) {
+         gCameraPan -= 0.5f; // Very sensitive control
+         if (gCameraPan < -180.0f) gCameraPan += 360.0f;
+         char msg[256];
+         sprintf(msg, "FLIR Camera System: Pan %.1f degrees\n", gCameraPan);
+         XPLMDebugString(msg);
+     }
+ }
+ 
+ static void PanRightCallback(void* inRefcon)
+ {
+     if (gCameraActive) {
+         gCameraPan += 0.5f; // Very sensitive control
+         if (gCameraPan > 180.0f) gCameraPan -= 360.0f;
+         char msg[256];
+         sprintf(msg, "FLIR Camera System: Pan %.1f degrees\n", gCameraPan);
+         XPLMDebugString(msg);
+     }
+ }
+ 
+ static void TiltUpCallback(void* inRefcon)
+ {
+     if (gCameraActive) {
+         gCameraTilt = fminf(gCameraTilt + 0.5f, 45.0f); // Very sensitive control
+         char msg[256];
+         sprintf(msg, "FLIR Camera System: Tilt %.1f degrees\n", gCameraTilt);
+         XPLMDebugString(msg);
+     }
+ }
+ 
+ static void TiltDownCallback(void* inRefcon)
+ {
+     if (gCameraActive) {
+         gCameraTilt = fmaxf(gCameraTilt - 0.5f, -90.0f); // Very sensitive control
+         char msg[256];
+         sprintf(msg, "FLIR Camera System: Tilt %.1f degrees\n", gCameraTilt);
+         XPLMDebugString(msg);
+     }
+ }
+ 
+ static void ThermalToggleCallback(void* inRefcon)
+ {
+     if (gCameraActive) {
+         gThermalMode = (gThermalMode + 1) % 3;
+         char msg[256];
+         const char* modeNames[] = {"Off", "White Hot", "Enhanced"};
+         sprintf(msg, "FLIR Camera System: Thermal mode %s\n", modeNames[gThermalMode]);
+         XPLMDebugString(msg);
+     }
+ }
+ 
+ /*
+  * FLIRCameraFunc
+  * 
+  * The main camera control function - positions camera under aircraft
+  * like a real belly-mounted FLIR system
+  */
+ static int FLIRCameraFunc(XPLMCameraPosition_t* outCameraPosition,
+                           int inIsLosingControl,
+                           void* inRefcon)
+ {
+     if (outCameraPosition && !inIsLosingControl) {
+         // Get current aircraft position and orientation
+         float planeX = XPLMGetDataf(gPlaneX);
+         float planeY = XPLMGetDataf(gPlaneY);
+         float planeZ = XPLMGetDataf(gPlaneZ);
+         float planeHeading = XPLMGetDataf(gPlaneHeading);
+         // float planePitch = XPLMGetDataf(gPlanePitch); // unused for now
+         float planeRoll = XPLMGetDataf(gPlaneRoll);
+ 
+         // Convert to radians
+         float headingRad = planeHeading * M_PI / 180.0f;
+         // float pitchRad = planePitch * M_PI / 180.0f; // unused
+         float rollRad = planeRoll * M_PI / 180.0f;
+         // float panRad = gCameraPan * M_PI / 180.0f; // unused
+         // float tiltRad = gCameraTilt * M_PI / 180.0f; // unused
+ 
+         // Calculate camera position relative to aircraft
+         // Position camera under the aircraft (belly-mounted)
+         float localX = gCameraDistance * cosf(headingRad);
+         float localZ = gCameraDistance * sinf(headingRad);
+         float localY = gCameraHeight; // Below aircraft
+ 
+         // Apply aircraft roll and pitch to camera position
+         float rotatedX = localX * cosf(rollRad) - localY * sinf(rollRad);
+         float rotatedY = localX * sinf(rollRad) + localY * cosf(rollRad);
+         float rotatedZ = localZ;
+ 
+         // Final camera position in world coordinates
+         outCameraPosition->x = planeX + rotatedX;
+         outCameraPosition->y = planeY + rotatedY;
+         outCameraPosition->z = planeZ + rotatedZ;
+ 
+         // Camera orientation - if locked, track target; otherwise manual control
+         if (gTargetLocked && gLockedTargetIndex >= 0 && gLockedTargetIndex < gHeatSourceCount) {
+             // Update target position from heat sources
+             gTargetX = gHeatSources[gLockedTargetIndex].x;
+             gTargetY = gHeatSources[gLockedTargetIndex].y;
+             gTargetZ = gHeatSources[gLockedTargetIndex].z;
+             
+             // Calculate angle to target
+             float dx = gTargetX - outCameraPosition->x;
+             float dy = gTargetY - outCameraPosition->y;
+             float dz = gTargetZ - outCameraPosition->z;
+             
+             // Calculate heading and pitch to target
+             float targetHeading = atan2f(dz, dx) * 180.0f / M_PI;
+             float groundDistance = sqrtf(dx*dx + dz*dz);
+             float targetPitch = -atan2f(dy, groundDistance) * 180.0f / M_PI;
+             
+             // Track the target automatically
+             outCameraPosition->heading = targetHeading;
+             outCameraPosition->pitch = targetPitch;
+         } else {
+             // Manual camera control
+             outCameraPosition->heading = planeHeading + gCameraPan;
+             outCameraPosition->pitch = gCameraTilt;
+         }
+         outCameraPosition->roll = 0.0f; // Keep camera level
+ 
+         // Apply zoom - this is the key for real magnification!
+         outCameraPosition->zoom = gZoomLevel;
+ 
+         // Normalize heading
+         if (outCameraPosition->heading > 360.0f) outCameraPosition->heading -= 360.0f;
+         if (outCameraPosition->heading < 0.0f) outCameraPosition->heading += 360.0f;
+     }
+ 
+     if (inIsLosingControl) {
+         gCameraActive = 0;
+         XPLMDebugString("FLIR Camera System: Lost camera control\n");
+     }
+ 
+     return gCameraActive;
+ }
+ 
+ /*
+  * DrawThermalOverlay
+  * 
+  * Draws thermal/IR overlay effects on the camera view
+  */
+ static int DrawThermalOverlay(XPLMDrawingPhase inPhase, int inIsBefore, void* inRefcon)
+ {
+     if (!gCameraActive) return 1;
+    
+    // Debug output to verify callback is being called
+    static int callCount = 0;
+    if (callCount < 5) {
+        char debugMsg[256];
+        sprintf(debugMsg, "FLIR Camera System: DrawThermalOverlay called, thermal mode: %d\n", gThermalMode);
+        XPLMDebugString(debugMsg);
+        callCount++;
+    }
+    
+    // Update environmental factors and heat sources
+    UpdateEnvironmentalFactors();
+    UpdateHeatSources();
+    DetectAircraft();
+ 
+     // Set up OpenGL for 2D drawing with proper error checking
+     // Get screen dimensions
+    int screenWidth, screenHeight;
+    XPLMGetScreenSize(&screenWidth, &screenHeight);
+    
+    if (screenWidth <= 0 || screenHeight <= 0) {
+        return 1; // Avoid drawing with invalid screen dimensions
+    }
+    
+    // Save OpenGL state to prevent crashes
+    glPushAttrib(GL_ALL_ATTRIB_BITS);
+    
+    // Set up 2D rendering state
+    XPLMSetGraphicsState(0, 0, 0, 1, 1, 0, 0);
+     
+     // Window phase provides proper 2D setup - no manual matrix setup needed
+ 
+     // For Window phase, coordinate system is already set up by X-Plane
+ 
+     float centerX = screenWidth / 2.0f;
+     float centerY = screenHeight / 2.0f;
+     
+     // Mouse control for camera movement
+     if (gCameraActive && !gTargetLocked) { // Only when not locked
+         int mouseX, mouseY;
+         XPLMGetMouseLocation(&mouseX, &mouseY);
+         
+         static int mouseInitialized = 0;
+         if (!mouseInitialized) {
+             gLastMouseX = mouseX;
+             gLastMouseY = mouseY;
+             mouseInitialized = 1;
+         }
+         
+         // Calculate mouse delta
+         int deltaX = mouseX - gLastMouseX;
+         int deltaY = mouseY - gLastMouseY;
+         
+         // Apply mouse movement to camera (much more sensitive)
+         if (abs(deltaX) > 1 || abs(deltaY) > 1) { // Only if significant movement
+             gCameraPan += deltaX * gMouseSensitivity;
+             gCameraTilt += deltaY * gMouseSensitivity;
+             
+             // Clamp values
+             if (gCameraPan > 180.0f) gCameraPan -= 360.0f;
+             if (gCameraPan < -180.0f) gCameraPan += 360.0f;
+             gCameraTilt = fmaxf(-90.0f, fminf(45.0f, gCameraTilt));
+             
+             gLastMouseX = mouseX;
+             gLastMouseY = mouseY;
+         }
+     }
+ 
+     // Draw targeting reticle
+     if (callCount < 3) {
+         char debugMsg[256];
+         sprintf(debugMsg, "FLIR: Drawing crosshair at %.0f,%.0f (screen %dx%d)\n", centerX, centerY, screenWidth, screenHeight);
+         XPLMDebugString(debugMsg);
+     }
+     
+     glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
+     glLineWidth(3.0f);
+ 
+     glBegin(GL_LINES);
+     // No crosshair - only brackets
+     
+     // Military-style targeting brackets [ ] - FIXED SIZE
+     float bracketSize = 50.0f;  // Fixed size - doesn't change with zoom
+     float bracketLength = 20.0f;
+     
+     // Top-left bracket [
+     glVertex2f(centerX - bracketSize, centerY + bracketSize);
+     glVertex2f(centerX - bracketSize + bracketLength, centerY + bracketSize);
+     glVertex2f(centerX - bracketSize, centerY + bracketSize);
+     glVertex2f(centerX - bracketSize, centerY + bracketSize - bracketLength);
+     
+     // Top-right bracket ]
+     glVertex2f(centerX + bracketSize, centerY + bracketSize);
+     glVertex2f(centerX + bracketSize - bracketLength, centerY + bracketSize);
+     glVertex2f(centerX + bracketSize, centerY + bracketSize);
+     glVertex2f(centerX + bracketSize, centerY + bracketSize - bracketLength);
+     
+     // Bottom-left bracket [
+     glVertex2f(centerX - bracketSize, centerY - bracketSize);
+     glVertex2f(centerX - bracketSize + bracketLength, centerY - bracketSize);
+     glVertex2f(centerX - bracketSize, centerY - bracketSize);
+     glVertex2f(centerX - bracketSize, centerY - bracketSize + bracketLength);
+     
+     // Bottom-right bracket ]
+     glVertex2f(centerX + bracketSize, centerY - bracketSize);
+     glVertex2f(centerX + bracketSize - bracketLength, centerY - bracketSize);
+     glVertex2f(centerX + bracketSize, centerY - bracketSize);
+     glVertex2f(centerX + bracketSize, centerY - bracketSize + bracketLength);
+     
+     // Small center dot for precise aiming
+     glVertex2f(centerX - 2, centerY);
+     glVertex2f(centerX + 2, centerY);
+     glVertex2f(centerX, centerY - 2);
+     glVertex2f(centerX, centerY + 2);
+     glEnd();
+ 
+     // Draw thermal effects based on thermal mode - using same reliable approach as crosshair
+     if (gThermalMode > 0) {
+         if (callCount < 3) {
+            char debugMsg[256];
+            sprintf(debugMsg, "FLIR: Drawing thermal overlay mode %d\n", gThermalMode);
+            XPLMDebugString(debugMsg);
+         }
+         
+         // Full-screen thermal overlay using same drawing method as crosshair
+         glEnable(GL_BLEND);
+         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+         
+         // Draw thermal background overlay
+         if (gThermalMode == 1) {
+             // White Hot mode - dark blue/black background
+             glColor4f(0.05f, 0.1f, 0.2f, 0.7f); // More opaque for realistic IR view
+         } else {
+             // Enhanced mode - greenish IR background  
+             glColor4f(0.1f, 0.3f, 0.1f, 0.6f);
+         }
+         
+         glBegin(GL_QUADS);
+         glVertex2f(0, 0);
+         glVertex2f(screenWidth, 0);
+         glVertex2f(screenWidth, screenHeight);
+         glVertex2f(0, screenHeight);
+         glEnd();
+         
+         // Realistic IR scan lines only (no random noise)
+         glLineWidth(1.0f);
+         glColor4f(0.0f, 0.0f, 0.0f, 0.15f);
+         
+         // Horizontal scan lines like real IR cameras
+         for (int y = 0; y < screenHeight; y += 2) {
+             glBegin(GL_LINES);
+             glVertex2f(0, y);
+             glVertex2f(screenWidth, y);
+             glEnd();
+         }
+         
+         // Only draw realistic heat sources from actual detection, no fake test rectangles
+        
+        // Draw realistic heat sources if we have any
+        if (gHeatSourceCount > 0) {
+            DrawRealisticThermalOverlay();
+        }
+         
+         // No background thermal noise - cleaner IR view
+         
+         glDisable(GL_BLEND);
+     }
+ 
+     // Draw realistic military FLIR HUD overlay
+     glColor4f(0.0f, 1.0f, 0.0f, 0.8f);
+     glLineWidth(1.0f);
+     
+     // Minimal corner reticles only (like real FLIR systems)
+     float reticleSize = 15.0f;
+     glBegin(GL_LINES);
+     // Top-left reticle
+     glVertex2f(30, 30); glVertex2f(30 + reticleSize, 30);
+     glVertex2f(30, 30); glVertex2f(30, 30 + reticleSize);
+     // Top-right reticle
+     glVertex2f(screenWidth - 30 - reticleSize, 30); glVertex2f(screenWidth - 30, 30);
+     glVertex2f(screenWidth - 30, 30); glVertex2f(screenWidth - 30, 30 + reticleSize);
+     // Bottom-left reticle
+     glVertex2f(30, screenHeight - 30 - reticleSize); glVertex2f(30, screenHeight - 30);
+     glVertex2f(30, screenHeight - 30); glVertex2f(30 + reticleSize, screenHeight - 30);
+     // Bottom-right reticle
+     glVertex2f(screenWidth - 30 - reticleSize, screenHeight - 30); glVertex2f(screenWidth - 30, screenHeight - 30);
+     glVertex2f(screenWidth - 30, screenHeight - 30); glVertex2f(screenWidth - 30, screenHeight - 30 - reticleSize);
+     glEnd();
+     
+     // Data will be exported to shared datarefs for FlyWithLua display
+     // For now, minimal built-in display only
+     
+     // Use X-Plane's text rendering for professional look
+     glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
+     
+     // Minimal status indicators (no confusing abstract lines)
+     // Only show essential info
+     
+     // Zoom level indicator (bottom-left corner only)
+     glLineWidth(2.0f);
+     glColor4f(0.0f, 1.0f, 0.0f, 0.8f);
+     glBegin(GL_LINES);
+     float zoomBar = fminf(gZoomLevel * 5.0f, 100.0f); // Scale zoom to reasonable bar length
+     glVertex2f(30, 40);
+     glVertex2f(30 + zoomBar, 40);
+     glEnd();
+     
+     // TARGET LOCK INDICATOR - VERY VISIBLE
+     if (gTargetLocked) {
+         glColor4f(1.0f, 0.0f, 0.0f, 1.0f); // Bright red for locked
+         glLineWidth(4.0f);
+         
+         // Large red box around the entire targeting area
+         glBegin(GL_LINE_LOOP);
+         glVertex2f(centerX - 100, centerY - 100);
+         glVertex2f(centerX + 100, centerY - 100);
+         glVertex2f(centerX + 100, centerY + 100);
+         glVertex2f(centerX - 100, centerY + 100);
+         glEnd();
+         
+         // Flashing corner indicators
+         float time = XPLMGetElapsedTime();
+         float flash = (sinf(time * 4.0f) + 1.0f) * 0.5f; // 0-1 flashing
+         glColor4f(1.0f, 0.0f, 0.0f, 0.5f + flash * 0.5f);
+         
+         glBegin(GL_LINES);
+         float lockSize = 30.0f;
+         // Top-left corner
+         glVertex2f(centerX - 100, centerY + 100 - lockSize); glVertex2f(centerX - 100, centerY + 100);
+         glVertex2f(centerX - 100, centerY + 100); glVertex2f(centerX - 100 + lockSize, centerY + 100);
+         // Top-right corner
+         glVertex2f(centerX + 100 - lockSize, centerY + 100); glVertex2f(centerX + 100, centerY + 100);
+         glVertex2f(centerX + 100, centerY + 100); glVertex2f(centerX + 100, centerY + 100 - lockSize);
+         // Bottom-left corner
+         glVertex2f(centerX - 100, centerY - 100 + lockSize); glVertex2f(centerX - 100, centerY - 100);
+         glVertex2f(centerX - 100, centerY - 100); glVertex2f(centerX - 100 + lockSize, centerY - 100);
+         // Bottom-right corner
+         glVertex2f(centerX + 100 - lockSize, centerY - 100); glVertex2f(centerX + 100, centerY - 100);
+         glVertex2f(centerX + 100, centerY - 100); glVertex2f(centerX + 100, centerY - 100 + lockSize);
+         glEnd();
+         
+         // LOCKED text indicator (top of screen)
+         glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
+         glLineWidth(3.0f);
+         glBegin(GL_LINES);
+         // Simple "LOCKED" text using lines at top center
+         float textY = screenHeight - 100;
+         // L
+         glVertex2f(centerX - 80, textY); glVertex2f(centerX - 80, textY - 20);
+         glVertex2f(centerX - 80, textY - 20); glVertex2f(centerX - 65, textY - 20);
+         // O
+         glVertex2f(centerX - 60, textY); glVertex2f(centerX - 45, textY);
+         glVertex2f(centerX - 60, textY - 20); glVertex2f(centerX - 45, textY - 20);
+         glVertex2f(centerX - 60, textY); glVertex2f(centerX - 60, textY - 20);
+         glVertex2f(centerX - 45, textY); glVertex2f(centerX - 45, textY - 20);
+         // C
+         glVertex2f(centerX - 40, textY); glVertex2f(centerX - 25, textY);
+         glVertex2f(centerX - 40, textY - 20); glVertex2f(centerX - 25, textY - 20);
+         glVertex2f(centerX - 40, textY); glVertex2f(centerX - 40, textY - 20);
+         // K
+         glVertex2f(centerX - 20, textY); glVertex2f(centerX - 20, textY - 20);
+         glVertex2f(centerX - 20, textY - 10); glVertex2f(centerX - 5, textY);
+         glVertex2f(centerX - 20, textY - 10); glVertex2f(centerX - 5, textY - 20);
+         // E
+         glVertex2f(centerX, textY); glVertex2f(centerX, textY - 20);
+         glVertex2f(centerX, textY); glVertex2f(centerX + 15, textY);
+         glVertex2f(centerX, textY - 10); glVertex2f(centerX + 10, textY - 10);
+         glVertex2f(centerX, textY - 20); glVertex2f(centerX + 15, textY - 20);
+         // D
+         glVertex2f(centerX + 20, textY); glVertex2f(centerX + 20, textY - 20);
+         glVertex2f(centerX + 20, textY); glVertex2f(centerX + 30, textY - 5);
+         glVertex2f(centerX + 30, textY - 5); glVertex2f(centerX + 30, textY - 15);
+         glVertex2f(centerX + 30, textY - 15); glVertex2f(centerX + 20, textY - 20);
+         glEnd();
+     }
+     
+     // No range circles - clean display
+     
+     // Heading indicator (top center)
+     glColor4f(0.0f, 1.0f, 0.0f, 0.9f);
+     glLineWidth(2.0f);
+     float headingX = centerX;
+     float headingY = screenHeight - 40;
+     float currentHeading = XPLMGetDataf(gPlaneHeading);
+     
+     glBegin(GL_LINES);
+     // Heading scale
+     for (int h = 0; h < 360; h += 30) {
+         float angle = (h - currentHeading - gCameraPan) * M_PI / 180.0f;
+         float x1 = headingX + 100 * sinf(angle);
+         float x2 = headingX + 110 * sinf(angle);
+         if (x1 > 50 && x1 < screenWidth - 50) {
+             glVertex2f(x1, headingY);
+             glVertex2f(x2, headingY);
+         }
+     }
+     glEnd();
+     
+     // Center heading marker
+     glBegin(GL_LINES);
+     glVertex2f(headingX, headingY - 10);
+     glVertex2f(headingX, headingY + 10);
+     glEnd();
+     
+     // Restore OpenGL state to prevent crashes
+     glPopAttrib();
+     
+     return 1;
+ }
+ 
+ /*
+  * Additional utility functions for future enhancements
+  */
+ 
+ // Function to detect and track actual X-Plane objects
+ /*
+static void UpdateTargetTracking(void)
+ {
+     // Future enhancement: Use X-Plane's object detection APIs
+     // to find and track actual aircraft, ships, vehicles in the sim
+ }
+ 
+ // Function to simulate different thermal/IR modes
+ static void SetThermalMode(int mode)
+ {
+     // Future enhancement: Different thermal rendering modes
+     // 0 = White Hot, 1 = Black Hot, 2 = Rainbow, etc.
+ }
+*/
+/*
+ * Enhanced Functions for FLIR Camera Plugin
+ * These functions provide realistic thermal detection and environmental factors
+ */
+
+/*
+ * UpdateEnvironmentalFactors
+ * 
+ * Updates environmental conditions that affect thermal visibility
+ */
+static void UpdateEnvironmentalFactors(void)
+{
+    if (gWeatherVisibility != NULL) {
+        gCurrentVisibility = XPLMGetDataf(gWeatherVisibility);
+    }
+    
+    if (gAmbientTemperature != NULL) {
+        gCurrentTemp = XPLMGetDataf(gAmbientTemperature);
+    }
+    
+    if (gWindSpeed != NULL) {
+        gCurrentWindSpeed = XPLMGetDataf(gWindSpeed);
+    }
+    
+    if (gTimeOfDay != NULL) {
+        float timeOfDay = XPLMGetDataf(gTimeOfDay);
+        // Night is roughly 18:00 to 06:00 (18*3600 = 64800, 6*3600 = 21600)
+        gIsNight = (timeOfDay > 64800.0f || timeOfDay < 21600.0f) ? 1 : 0;
+    }
+}
+
+/*
+ * GetDistanceToCamera
+ * 
+ * Calculate distance from world position to camera
+ */
+static float GetDistanceToCamera(float x, float y, float z)
+{
+    float camX = XPLMGetDataf(gPlaneX);
+    float camY = XPLMGetDataf(gPlaneY);
+    float camZ = XPLMGetDataf(gPlaneZ);
+    
+    float dx = x - camX;
+    float dy = y - camY;
+    float dz = z - camZ;
+    
+    return sqrtf(dx*dx + dy*dy + dz*dz);
+}
+
+/*
+ * CalculateHeatIntensity
+ * 
+ * Calculate thermal intensity based on engine temperature and distance
+ */
+static float CalculateHeatIntensity(float engineTemp, float distance, int engineRunning)
+{
+    if (!engineRunning) return 0.1f; // Cold engine still slightly visible
+    
+    // Base intensity from engine temperature (EGT typically 400-900°C)
+    float baseIntensity = (engineTemp - 200.0f) / 700.0f;
+    baseIntensity = fmaxf(0.0f, fminf(1.0f, baseIntensity));
+    
+    // Distance attenuation (max detection ~10km for aircraft)
+    float distanceFactor = 1.0f - (distance / 10000.0f);
+    distanceFactor = fmaxf(0.0f, distanceFactor);
+    
+    // Weather effects
+    float weatherFactor = gCurrentVisibility / 10000.0f;
+    weatherFactor = fmaxf(0.2f, fminf(1.0f, weatherFactor));
+    
+    // Night enhances thermal contrast
+    float nightBonus = gIsNight ? 1.3f : 1.0f;
+    
+    return baseIntensity * distanceFactor * weatherFactor * nightBonus;
+}
+
+/*
+ * DetectAircraft
+ * 
+ * Scan for AI aircraft and other heat sources in the simulation
+ */
+static void DetectAircraft(void)
+{
+    gAircraftCount = 0;
+    
+    // Debug output for aircraft detection
+    static int detectCallCount = 0;
+    detectCallCount++;
+    if (detectCallCount % 300 == 1) { // Every ~5 seconds
+        XPLMDebugString("FLIR Camera System: Scanning for AI aircraft and ships...\n");
+    }
+    
+    // **1. Detect AI Aircraft (much more common than multiplayer)**
+    // X-Plane has up to 63 AI aircraft slots
+    for (int i = 0; i < 63 && gAircraftCount < 20; i++) {
+        char datarefName[256];
+        
+        // AI aircraft positions
+        sprintf(datarefName, "sim/multiplayer/position/plane%d_x", i + 1);
+        XPLMDataRef aircraftX = XPLMFindDataRef(datarefName);
+        sprintf(datarefName, "sim/multiplayer/position/plane%d_y", i + 1);
+        XPLMDataRef aircraftY = XPLMFindDataRef(datarefName);
+        sprintf(datarefName, "sim/multiplayer/position/plane%d_z", i + 1);
+        XPLMDataRef aircraftZ = XPLMFindDataRef(datarefName);
+        
+        if (aircraftX && aircraftY && aircraftZ) {
+            float x = XPLMGetDataf(aircraftX);
+            float y = XPLMGetDataf(aircraftY);
+            float z = XPLMGetDataf(aircraftZ);
+            
+            // Check if aircraft exists and is not our own plane
+            if ((x != 0.0f || y != 0.0f || z != 0.0f)) {
+                float distance = GetDistanceToCamera(x, y, z);
+                if (distance > 50.0f) { // Minimum distance to avoid locking on self
+                    gAircraftPositions[gAircraftCount][0] = x;
+                    gAircraftPositions[gAircraftCount][1] = y;
+                    gAircraftPositions[gAircraftCount][2] = z;
+                    gAircraftDistance[gAircraftCount] = distance;
+                    
+                    // Simulate engine temperature (realistic EGT values)
+                    gAircraftEngineTemp[gAircraftCount] = 450.0f + (rand() % 300);
+                    
+                    // Determine visibility based on distance and conditions
+                    gAircraftVisible[gAircraftCount] = (distance < gCurrentVisibility * 0.8f) ? 1 : 0;
+                    
+                    if (detectCallCount % 300 == 1) {
+                        char debugMsg[256];
+                        sprintf(debugMsg, "FLIR: Found AI aircraft %d at %.0fm\n", i+1, distance);
+                        XPLMDebugString(debugMsg);
+                    }
+                    
+                    gAircraftCount++;
+                }
+            }
+        }
+    }
+    
+    // **2. Detect Ships - try multiple ship/boat datarefs**
+    
+    // Method 1: Try ground vehicle datarefs that might be ships
+    XPLMDataRef shipX = XPLMFindDataRef("sim/flightmodel2/position/local_x");
+    XPLMDataRef shipY = XPLMFindDataRef("sim/flightmodel2/position/local_y"); 
+    XPLMDataRef shipZ = XPLMFindDataRef("sim/flightmodel2/position/local_z");
+    
+    if (shipX && shipY && shipZ && gAircraftCount < 20) {
+        float x = XPLMGetDataf(shipX);
+        float y = XPLMGetDataf(shipY);
+        float z = XPLMGetDataf(shipZ);
+        
+        if (x != 0.0f || y != 0.0f || z != 0.0f) {
+            float distance = GetDistanceToCamera(x, y, z);
+            if (distance > 50.0f) {
+                gAircraftPositions[gAircraftCount][0] = x;
+                gAircraftPositions[gAircraftCount][1] = y;
+                gAircraftPositions[gAircraftCount][2] = z;
+                gAircraftDistance[gAircraftCount] = distance;
+                gAircraftEngineTemp[gAircraftCount] = 250.0f + (rand() % 150); // Ships have lower heat
+                gAircraftVisible[gAircraftCount] = (distance < gCurrentVisibility) ? 1 : 0;
+                
+                if (detectCallCount % 300 == 1) {
+                    char debugMsg[256];
+                    sprintf(debugMsg, "FLIR: Found ship/vehicle at %.0fm\n", distance);
+                    XPLMDebugString(debugMsg);
+                }
+                gAircraftCount++;
+            }
+        }
+    }
+    
+    // Method 2: AI boat datarefs
+    for (int i = 0; i < 10 && gAircraftCount < 20; i++) {
+        char datarefName[256];
+        sprintf(datarefName, "sim/multiplayer/position/boat%d_x", i + 1);
+        XPLMDataRef boatX = XPLMFindDataRef(datarefName);
+        sprintf(datarefName, "sim/multiplayer/position/boat%d_y", i + 1);
+        XPLMDataRef boatY = XPLMFindDataRef(datarefName);
+        sprintf(datarefName, "sim/multiplayer/position/boat%d_z", i + 1);
+        XPLMDataRef boatZ = XPLMFindDataRef(datarefName);
+        
+        if (boatX && boatY && boatZ) {
+            float x = XPLMGetDataf(boatX);
+            float y = XPLMGetDataf(boatY);
+            float z = XPLMGetDataf(boatZ);
+            
+            if (x != 0.0f || y != 0.0f || z != 0.0f) {
+                float distance = GetDistanceToCamera(x, y, z);
+                if (distance > 50.0f) {
+                    gAircraftPositions[gAircraftCount][0] = x;
+                    gAircraftPositions[gAircraftCount][1] = y;
+                    gAircraftPositions[gAircraftCount][2] = z;
+                    gAircraftDistance[gAircraftCount] = distance;
+                    
+                    // Ships have engine heat too
+                    gAircraftEngineTemp[gAircraftCount] = 300.0f + (rand() % 200);
+                    gAircraftVisible[gAircraftCount] = (distance < gCurrentVisibility) ? 1 : 0;
+                    
+                    if (detectCallCount % 300 == 1) {
+                        char debugMsg[256];
+                        sprintf(debugMsg, "FLIR: Found ship %d at %.0fm\n", i+1, distance);
+                        XPLMDebugString(debugMsg);
+                    }
+                    
+                    gAircraftCount++;
+                }
+            }
+        }
+    }
+    
+    if (detectCallCount % 300 == 1) {
+        char debugMsg[256];
+        sprintf(debugMsg, "FLIR: Total targets found: %d\n", gAircraftCount);
+        XPLMDebugString(debugMsg);
+    }
+}
+
+/*
+ * UpdateHeatSources
+ * 
+ * Update dynamic heat sources in the simulation
+ */
+static void UpdateHeatSources(void)
+{
+    float currentTime = XPLMGetElapsedTime();
+    gHeatSourceCount = 0;
+    
+    // Add detected aircraft as heat sources
+    for (int i = 0; i < gAircraftCount && gHeatSourceCount < 50; i++) {
+        if (gAircraftVisible[i]) {
+            gHeatSources[gHeatSourceCount].x = gAircraftPositions[i][0];
+            gHeatSources[gHeatSourceCount].y = gAircraftPositions[i][1];
+            gHeatSources[gHeatSourceCount].z = gAircraftPositions[i][2];
+            gHeatSources[gHeatSourceCount].intensity = CalculateHeatIntensity(
+                gAircraftEngineTemp[i], gAircraftDistance[i], 1);
+            gHeatSources[gHeatSourceCount].size = 15.0f + (gHeatSources[gHeatSourceCount].intensity * 25.0f);
+            gHeatSources[gHeatSourceCount].type = 0; // Aircraft
+            gHeatSources[gHeatSourceCount].lastUpdate = currentTime;
+            gHeatSourceCount++;
+        }
+    }
+    
+    // Add simulated ground heat sources (buildings, vehicles, ships)
+    float planeX = XPLMGetDataf(gPlaneX);
+    float planeZ = XPLMGetDataf(gPlaneZ);
+    
+    // Simulate some heat sources around the area
+    for (int i = 0; i < 8 && gHeatSourceCount < 50; i++) {
+        float angle = (i * 45.0f) * M_PI / 180.0f;
+        float distance = 2000.0f + (i * 500.0f);
+        
+        float x = planeX + distance * cosf(angle);
+        float z = planeZ + distance * sinf(angle);
+        float y = XPLMGetDataf(gPlaneY) - 100.0f; // Ground level
+        
+        gHeatSources[gHeatSourceCount].x = x;
+        gHeatSources[gHeatSourceCount].y = y;
+        gHeatSources[gHeatSourceCount].z = z;
+        
+        // Vary intensity based on type and time
+        float baseIntensity = 0.3f;
+        if (gIsNight) baseIntensity += 0.2f; // More visible at night
+        
+        gHeatSources[gHeatSourceCount].intensity = baseIntensity + 
+            0.2f * sinf(currentTime * 0.1f + i);
+        gHeatSources[gHeatSourceCount].size = 8.0f + (gHeatSources[gHeatSourceCount].intensity * 12.0f);
+        gHeatSources[gHeatSourceCount].type = (i % 3) + 1; // Ships, vehicles, buildings
+        gHeatSources[gHeatSourceCount].lastUpdate = currentTime;
+        gHeatSourceCount++;
+    }
+}
+
+/*
+ * DrawRealisticThermalOverlay
+ * 
+ * Render realistic thermal signatures for detected heat sources
+ */
+static void DrawRealisticThermalOverlay(void)
+{
+    if (gHeatSourceCount == 0) return;
+    
+    // Get screen dimensions and camera info
+    int screenWidth, screenHeight;
+    XPLMGetScreenSize(&screenWidth, &screenHeight);
+    
+    float camX = XPLMGetDataf(gPlaneX);
+    float camY = XPLMGetDataf(gPlaneY);
+    float camZ = XPLMGetDataf(gPlaneZ);
+    float camHeading = XPLMGetDataf(gPlaneHeading) + gCameraPan;
+    float camPitch = gCameraTilt;
+    
+    // Convert camera angles to radians
+    float headingRad = camHeading * M_PI / 180.0f;
+    float pitchRad = camPitch * M_PI / 180.0f;
+    
+    // Camera forward vector
+    float forwardX = cosf(headingRad) * cosf(pitchRad);
+    float forwardY = sinf(pitchRad);
+    float forwardZ = sinf(headingRad) * cosf(pitchRad);
+    
+    // Camera right vector (for screen mapping)
+    float rightX = -sinf(headingRad);
+    float rightZ = cosf(headingRad);
+    
+    // Camera up vector
+    float upX = -cosf(headingRad) * sinf(pitchRad);
+    float upY = cosf(pitchRad);
+    float upZ = -sinf(headingRad) * sinf(pitchRad);
+    
+    // Field of view factor (approximate)
+    float fovFactor = 60.0f / gZoomLevel; // Base FOV 60 degrees
+    
+    glEnable(GL_BLEND);
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    
+    // Draw each heat source
+    for (int i = 0; i < gHeatSourceCount; i++) {
+        HeatSource* heat = &gHeatSources[i];
+        
+        // Vector from camera to heat source
+        float dx = heat->x - camX;
+        float dy = heat->y - camY;
+        float dz = heat->z - camZ;
+        float distance = sqrtf(dx*dx + dy*dy + dz*dz);
+        
+        if (distance < 50.0f) continue; // Too close, skip
+        
+        // Normalize direction vector
+        dx /= distance;
+        dy /= distance;
+        dz /= distance;
+        
+        // Check if heat source is in front of camera
+        float dotForward = dx * forwardX + dy * forwardY + dz * forwardZ;
+        if (dotForward <= 0.1f) continue; // Behind camera or too far to side
+        
+        // Project to screen coordinates
+        float rightDot = dx * rightX + dz * rightZ;
+        float upDot = dx * upX + dy * upY + dz * upZ;
+        
+        // Convert to screen space
+        float screenX = screenWidth * 0.5f + (rightDot * screenWidth * 0.5f / fovFactor);
+        float screenY = screenHeight * 0.5f + (upDot * screenHeight * 0.5f / fovFactor);
+        
+        // Check if on screen
+        if (screenX < 0 || screenX >= screenWidth || screenY < 0 || screenY >= screenHeight) {
+            continue;
+        }
+        
+        // Calculate apparent size based on distance and zoom
+        float apparentSize = heat->size * gZoomLevel / (distance * 0.01f);
+        apparentSize = fmaxf(3.0f, fminf(apparentSize, 50.0f));
+        
+        // Color based on heat source type and intensity
+        float r, g, b, a;
+        if (gThermalMode == 1) {
+            // White hot mode
+            r = g = b = heat->intensity;
+            a = heat->intensity * 0.8f;
+            
+            // Aircraft show as very bright white
+            if (heat->type == 0) {
+                r = g = b = 1.0f;
+                a = 0.9f;
+            }
+        } else {
+            // Enhanced mode - use color coding
+            switch (heat->type) {
+                case 0: // Aircraft - bright yellow/orange
+                    r = 1.0f;
+                    g = 0.8f;
+                    b = 0.2f;
+                    a = heat->intensity * 0.9f;
+                    break;
+                case 1: // Ships - cyan
+                    r = 0.2f;
+                    g = 0.8f;
+                    b = 1.0f;
+                    a = heat->intensity * 0.7f;
+                    break;
+                case 2: // Vehicles - red
+                    r = 1.0f;
+                    g = 0.3f;
+                    b = 0.1f;
+                    a = heat->intensity * 0.6f;
+                    break;
+                case 3: // Buildings - orange
+                    r = 1.0f;
+                    g = 0.5f;
+                    b = 0.0f;
+                    a = heat->intensity * 0.5f;
+                    break;
+                default:
+                    r = g = b = heat->intensity;
+                    a = heat->intensity * 0.6f;
+                    break;
+            }
+        }
+        
+        glColor4f(r, g, b, a);
+        
+        // Draw heat signature with gradient effect
+        glBegin(GL_QUADS);
+        glVertex2f(screenX - apparentSize, screenY - apparentSize);
+        glVertex2f(screenX + apparentSize, screenY - apparentSize);
+        glVertex2f(screenX + apparentSize, screenY + apparentSize);
+        glVertex2f(screenX - apparentSize, screenY + apparentSize);
+        glEnd();
+        
+        // Add heat bloom effect for intense sources
+        if (heat->intensity > 0.7f) {
+            float bloomSize = apparentSize * 1.5f;
+            glColor4f(r, g, b, a * 0.3f);
+            glBegin(GL_QUADS);
+            glVertex2f(screenX - bloomSize, screenY - bloomSize);
+            glVertex2f(screenX + bloomSize, screenY - bloomSize);
+            glVertex2f(screenX + bloomSize, screenY + bloomSize);
+            glVertex2f(screenX - bloomSize, screenY + bloomSize);
+            glEnd();
+        }
+        
+        // Add targeting indicator for aircraft
+        if (heat->type == 0 && distance < 5000.0f) {
+            glColor4f(0.0f, 1.0f, 0.0f, 0.8f);
+            glLineWidth(2.0f);
+            
+            float targetSize = apparentSize + 10.0f;
+            glBegin(GL_LINE_LOOP);
+            glVertex2f(screenX - targetSize, screenY - targetSize);
+            glVertex2f(screenX + targetSize, screenY - targetSize);
+            glVertex2f(screenX + targetSize, screenY + targetSize);
+            glVertex2f(screenX - targetSize, screenY + targetSize);
+            glEnd();
+            
+            // Add distance indicator
+            char distText[32];
+            sprintf(distText, "%.0fm", distance);
+            // Note: Actual text rendering would need XPLMDrawString
+        }
+    }
+    
+    glDisable(GL_BLEND);
+}
+
+static void FocusLockCallback(void* inRefcon)
+{
+    if (gCameraActive) {
+        if (!gTargetLocked) {
+            // Find nearest target to focus on
+            float nearestDistance = 999999.0f;
+            int nearestTarget = -1;
+            
+            // Check heat sources for nearest aircraft
+            for (int i = 0; i < gHeatSourceCount; i++) {
+                if (gHeatSources[i].type == 0) { // Aircraft
+                    float distance = GetDistanceToCamera(gHeatSources[i].x, gHeatSources[i].y, gHeatSources[i].z);
+                    if (distance < nearestDistance && distance > 100.0f) { // Minimum 100m distance
+                        nearestDistance = distance;
+                        nearestTarget = i;
+                    }
+                }
+            }
+            
+            if (nearestTarget >= 0) {
+                gTargetLocked = 1;
+                gLockedTargetIndex = nearestTarget;
+                gFocusDistance = nearestDistance;
+                gTargetX = gHeatSources[nearestTarget].x;
+                gTargetY = gHeatSources[nearestTarget].y;
+                gTargetZ = gHeatSources[nearestTarget].z;
+                char msg[256];
+                sprintf(msg, "FLIR Camera System: Target LOCKED at %.0fm - Camera will track automatically\n", gFocusDistance);
+                XPLMDebugString(msg);
+            } else {
+                char debugMsg[256];
+                sprintf(debugMsg, "FLIR Camera System: No targets found - Heat sources: %d, Aircraft: %d\n", 
+                        gHeatSourceCount, gAircraftCount);
+                XPLMDebugString(debugMsg);
+            }
+        } else {
+            // Unlock target
+            gTargetLocked = 0;
+            gLockedTargetIndex = -1;
+            XPLMDebugString("FLIR Camera System: Target UNLOCKED - Manual control restored\n");
+        }
+    }
+}
\ No newline at end of file
diff --git a/FLIR_HUD.lua b/FLIR_HUD.lua
index 33b6864..21f9351 100644
--- a/FLIR_HUD.lua
+++ b/FLIR_HUD.lua
@@ -1,15 +1,18 @@
 -- FLIR Camera HUD Display Script for FlyWithLua
 -- Place this file in X-Plane/Resources/plugins/FlyWithLua/Scripts/
--- Simple and safe version
+-- Only shows HUD when FLIR camera is actually active
 
 -- Global variables
 flir_start_time = flir_start_time or os.time()
 
 function draw_flir_hud()
-    -- Only draw when in external view (likely FLIR active)
+    -- Check if FLIR camera is active via shared dataref
+    local flir_active = dataref_table("sim/operation/prefs/misc/manipulator_disabled")
+    
+    -- Only draw HUD when FLIR camera is actually active (manipulator disabled indicates camera mode)
     local view_type = dataref_table("sim/graphics/view/view_type")
     
-    if view_type[0] == 1026 then  -- External view
+    if view_type[0] == 1026 and flir_active[0] == 1 then  -- External view AND camera active
         -- Get basic aircraft data safely
         local zulu_time = dataref_table("sim/time/zulu_time_sec")[0]
         local latitude = dataref_table("sim/flightmodel/position/latitude")[0]
diff --git a/FLIR_LockOn.cpp b/FLIR_LockOn.cpp
new file mode 100644
index 0000000..b8d2c90
--- /dev/null
+++ b/FLIR_LockOn.cpp
@@ -0,0 +1,164 @@
+/*
+ * FLIR_LockOn.cpp
+ * 
+ * Arbitrary point focus system for FLIR camera
+ * This module handles camera locking to specific world coordinates
+ * without AI target scanning - focuses on arbitrary points in space
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+#include "XPLMDataAccess.h"
+#include "XPLMUtilities.h"
+#include "FLIR_LockOn.h"
+
+// Lock-on state
+static int gLockOnActive = 0;
+static float gLockedWorldX = 0.0f;
+static float gLockedWorldY = 0.0f; 
+static float gLockedWorldZ = 0.0f;
+static float gLockOnPan = 0.0f;    // Camera pan when locked
+static float gLockOnTilt = 0.0f;   // Camera tilt when locked
+
+// Aircraft position datarefs
+static XPLMDataRef gPlaneX = NULL;
+static XPLMDataRef gPlaneY = NULL;
+static XPLMDataRef gPlaneZ = NULL;
+static XPLMDataRef gPlaneHeading = NULL;
+static XPLMDataRef gPlanePitch = NULL;
+static XPLMDataRef gPlaneRoll = NULL;
+
+void InitializeLockOnSystem()
+{
+    // Get aircraft position datarefs
+    gPlaneX = XPLMFindDataRef("sim/flightmodel/position/local_x");
+    gPlaneY = XPLMFindDataRef("sim/flightmodel/position/local_y");
+    gPlaneZ = XPLMFindDataRef("sim/flightmodel/position/local_z");
+    gPlaneHeading = XPLMFindDataRef("sim/flightmodel/position/psi");
+    gPlanePitch = XPLMFindDataRef("sim/flightmodel/position/theta");
+    gPlaneRoll = XPLMFindDataRef("sim/flightmodel/position/phi");
+    
+    XPLMDebugString("FLIR Lock-On System: Initialized\n");
+}
+
+void SetArbitraryLockPoint(float currentPan, float currentTilt, float distance)
+{
+    if (!gPlaneX || !gPlaneY || !gPlaneZ || !gPlaneHeading) {
+        XPLMDebugString("FLIR Lock-On: Aircraft datarefs not available\n");
+        return;
+    }
+    
+    // Get current aircraft position
+    float planeX = XPLMGetDataf(gPlaneX);
+    float planeY = XPLMGetDataf(gPlaneY);
+    float planeZ = XPLMGetDataf(gPlaneZ);
+    float planeHeading = XPLMGetDataf(gPlaneHeading);
+    
+    // Convert camera angles to radians
+    float panRad = (planeHeading + currentPan) * M_PI / 180.0f;
+    float tiltRad = currentTilt * M_PI / 180.0f;
+    
+    // Calculate world coordinates of the lock point
+    // Project forward from camera position based on current pan/tilt
+    gLockedWorldX = planeX + distance * sin(panRad) * cos(tiltRad);
+    gLockedWorldY = planeY + distance * sin(tiltRad);
+    gLockedWorldZ = planeZ + distance * cos(panRad) * cos(tiltRad);
+    
+    // Store the camera angles at lock time
+    gLockOnPan = currentPan;
+    gLockOnTilt = currentTilt;
+    
+    gLockOnActive = 1;
+    
+    char msg[256];
+    sprintf(msg, "FLIR Lock-On: Locked to point (%.1f, %.1f, %.1f)\n", 
+            gLockedWorldX, gLockedWorldY, gLockedWorldZ);
+    XPLMDebugString(msg);
+}
+
+void UpdateCameraToLockPoint(float* outPan, float* outTilt)
+{
+    if (!gLockOnActive || !gPlaneX || !gPlaneY || !gPlaneZ || !gPlaneHeading) {
+        return;
+    }
+    
+    // Get current aircraft position
+    float planeX = XPLMGetDataf(gPlaneX);
+    float planeY = XPLMGetDataf(gPlaneY);
+    float planeZ = XPLMGetDataf(gPlaneZ);
+    float planeHeading = XPLMGetDataf(gPlaneHeading);
+    
+    // Calculate vector from aircraft to locked point
+    float dx = gLockedWorldX - planeX;
+    float dy = gLockedWorldY - planeY;
+    float dz = gLockedWorldZ - planeZ;
+    
+    // Calculate distance to locked point
+    float horizontalDist = sqrt(dx * dx + dz * dz);
+    float totalDist = sqrt(dx * dx + dy * dy + dz * dz);
+    
+    if (totalDist < 1.0f) {
+        // Too close, maintain last known angles
+        *outPan = gLockOnPan;
+        *outTilt = gLockOnTilt;
+        return;
+    }
+    
+    // Calculate required camera angles
+    float targetHeading = atan2(dx, dz) * 180.0f / M_PI;
+    float targetTilt = atan2(dy, horizontalDist) * 180.0f / M_PI;
+    
+    // Convert to camera-relative angles
+    *outPan = targetHeading - planeHeading;
+    *outTilt = targetTilt;
+    
+    // Normalize pan angle to -180 to +180
+    while (*outPan > 180.0f) *outPan -= 360.0f;
+    while (*outPan < -180.0f) *outPan += 360.0f;
+    
+    // Clamp tilt to reasonable limits
+    if (*outTilt > 90.0f) *outTilt = 90.0f;
+    if (*outTilt < -90.0f) *outTilt = -90.0f;
+}
+
+void DisableLockOn()
+{
+    gLockOnActive = 0;
+    XPLMDebugString("FLIR Lock-On: Disabled\n");
+}
+
+int IsLockOnActive()
+{
+    return gLockOnActive;
+}
+
+void GetLockOnStatus(char* statusBuffer, int bufferSize)
+{
+    if (!gLockOnActive) {
+        strncpy(statusBuffer, "LOCK: OFF", bufferSize - 1);
+        statusBuffer[bufferSize - 1] = '\0';
+        return;
+    }
+    
+    // Calculate distance to locked point
+    if (gPlaneX && gPlaneY && gPlaneZ) {
+        float planeX = XPLMGetDataf(gPlaneX);
+        float planeY = XPLMGetDataf(gPlaneY);
+        float planeZ = XPLMGetDataf(gPlaneZ);
+        
+        float dx = gLockedWorldX - planeX;
+        float dy = gLockedWorldY - planeY;
+        float dz = gLockedWorldZ - planeZ;
+        float distance = sqrt(dx * dx + dy * dy + dz * dz);
+        
+        snprintf(statusBuffer, bufferSize, "LOCK: ON %.0fm", distance);
+    } else {
+        strncpy(statusBuffer, "LOCK: ON", bufferSize - 1);
+    }
+    statusBuffer[bufferSize - 1] = '\0';
+}
\ No newline at end of file
diff --git a/FLIR_LockOn.h b/FLIR_LockOn.h
new file mode 100644
index 0000000..c1537ea
--- /dev/null
+++ b/FLIR_LockOn.h
@@ -0,0 +1,36 @@
+/*
+ * FLIR_LockOn.h
+ * 
+ * Header file for FLIR camera arbitrary point lock-on system
+ */
+
+#ifndef FLIR_LOCKON_H
+#define FLIR_LOCKON_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Initialize the lock-on system
+void InitializeLockOnSystem();
+
+// Set lock-on point based on current camera direction and distance
+void SetArbitraryLockPoint(float currentPan, float currentTilt, float distance);
+
+// Update camera angles to maintain lock on point
+void UpdateCameraToLockPoint(float* outPan, float* outTilt);
+
+// Disable lock-on
+void DisableLockOn();
+
+// Check if lock-on is active
+int IsLockOnActive();
+
+// Get lock-on status string for display
+void GetLockOnStatus(char* statusBuffer, int bufferSize);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // FLIR_LOCKON_H
\ No newline at end of file
diff --git a/FLIR_LockOn.o b/FLIR_LockOn.o
new file mode 100644
index 0000000..34c3a2b
Binary files /dev/null and b/FLIR_LockOn.o differ
diff --git a/Makefile b/Makefile
index a1dc2e8..77a32a4 100644
--- a/Makefile
+++ b/Makefile
@@ -29,7 +29,7 @@ LDFLAGS += $(LIBS)
 LDFLAGS += -lopengl32 -lgdi32
 
 # Source files
-SOURCES = FLIR_Camera.cpp
+SOURCES = FLIR_Camera.cpp FLIR_LockOn.cpp
 
 # Object files
 OBJECTS = $(SOURCES:.cpp=.o)
diff --git a/build/FLIR_Camera/win_x64/FLIR_Camera.xpl b/build/FLIR_Camera/win_x64/FLIR_Camera.xpl
index cf8429b..604d4df 100755
Binary files a/build/FLIR_Camera/win_x64/FLIR_Camera.xpl and b/build/FLIR_Camera/win_x64/FLIR_Camera.xpl differ