xp12camera
Owner: IIIlllIIIllI URL: git@github.com:nyangkosense/xp12camera.git
quasi final
Commit ff20a752777190164932cb027106dc5d669c6dfc by SM <seb.michalk@gmail.com> on 2025-06-26 10:31:04 +0200
diff --git a/FLIR_Camera.cpp b/FLIR_Camera.cpp
index 72d4867..44c7934 100644
--- a/FLIR_Camera.cpp
+++ b/FLIR_Camera.cpp
@@ -6,238 +6,154 @@
* - Real camera positioning under aircraft (belly-mounted)
* - True optical zoom with zoom parameter
* - Pan/tilt camera controls with mouse
- * - Arbitrary point lock-on system
* - Military-style targeting reticles
*
*/
- #include <string.h>
- #include <stdio.h>
- #include <stdlib.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 "FLIR_SimpleLock.h"
- #include "FLIR_VisualEffects.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <windows.h>
+#include <GL/gl.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;
+#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 "FLIR_SimpleLock.h"
+#include "FLIR_VisualEffects.h"
+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 XPLMDataRef gPlaneX = NULL;
+static XPLMDataRef gPlaneY = NULL;
+static XPLMDataRef gPlaneZ = NULL;
+static XPLMDataRef gPlaneHeading = NULL;
+static XPLMDataRef gPlanePitch = NULL;
+static XPLMDataRef gPlaneRoll = NULL;
+static XPLMDataRef gManipulatorDisabled = NULL;
+
+static int gCameraActive = 0;
+static int gDrawCallbackRegistered = 0;
+static float gZoomLevel = 1.0f;
+static float gCameraPan = 0.0f;
+static float gCameraTilt = -15.0f;
+static float gCameraHeight = -5.0f;
+static float gCameraDistance = 3.0f;
static int gLastMouseX = 0;
static int gLastMouseY = 0;
-static float gMouseSensitivity = 0.2f; // Mouse sensitivity multiplier
-
-// Thermal view settings are now handled by visual effects system
-
-// Dataref to control HUD visibility
-static XPLMDataRef gManipulatorDisabled = 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 float gMouseSensitivity = 0.2f;
+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 int FLIRCameraFunc(XPLMCameraPosition_t* outCameraPosition, int inIsLosingControl, void* inRefcon);
+static int DrawThermalOverlay(XPLMDrawingPhase inPhase, int inIsBefore, void* inRefcon);
static void DrawRealisticThermalOverlay(void);
- // 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");
-
- // Dataref for HUD control
- gManipulatorDisabled = XPLMFindDataRef("sim/operation/prefs/misc/manipulator_disabled");
-
- // Initialize simple lock system
- InitializeSimpleLock();
-
- // Initialize visual effects system
- InitializeVisualEffects();
+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");
- // 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);
+ 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");
+ gManipulatorDisabled = XPLMFindDataRef("sim/operation/prefs/misc/manipulator_disabled");
- gThermalToggleKey = XPLMRegisterHotKey(XPLM_VK_T, xplm_DownFlag,
- "FLIR Visual Effects Toggle",
- ThermalToggleCallback, NULL);
-
- gFocusLockKey = XPLMRegisterHotKey(XPLM_VK_SPACE, xplm_DownFlag,
- "FLIR Focus/Lock Target",
- FocusLockCallback, NULL);
+ InitializeSimpleLock();
+ InitializeVisualEffects();
+ 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);
+ gThermalToggleKey = XPLMRegisterHotKey(XPLM_VK_T, xplm_DownFlag, "FLIR Visual Effects Toggle", ThermalToggleCallback, NULL);
+ gFocusLockKey = XPLMRegisterHotKey(XPLM_VK_SPACE, xplm_DownFlag, "FLIR Focus/Lock Target", FocusLockCallback, NULL);
- 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 enhanced lock-on\n");
- XPLMDebugString("FLIR Camera System: Enhanced tracking uses X-Plane's algorithm for smooth target following\n");
-
- 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);
+ return 1;
+}
+PLUGIN_API void XPluginStop(void)
+{
+ 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) { }
+ if (gCameraActive) {
+ XPLMDontControlCamera();
+ gCameraActive = 0;
+ }
+}
+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");
-
- // Take camera control
- XPLMControlCamera(xplm_ControlCameraUntilViewChanges, FLIRCameraFunc, NULL);
- gCameraActive = 1;
+static void ActivateFLIRCallback(void* inRefcon)
+{
+ if (!gCameraActive) {
+ XPLMControlCamera(xplm_ControlCameraUntilViewChanges, FLIRCameraFunc, NULL);
+ gCameraActive = 1;
- // 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;
- 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;
-
- // Re-enable manipulator
- if (gManipulatorDisabled) {
- XPLMSetDatai(gManipulatorDisabled, 0);
- }
-
- // Disable lock when camera deactivated
- DisableSimpleLock();
-
- // Unregister drawing callback to save performance
+ } else {
+ XPLMDontControlCamera();
+ gCameraActive = 0;
+
+ if (gManipulatorDisabled) {
+ XPLMSetDatai(gManipulatorDisabled, 0);
+ }
+
+ DisableSimpleLock();
+
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
+static void ZoomInCallback(void* inRefcon)
+{
+ if (gCameraActive) {
if (gZoomLevel < 1.5f) gZoomLevel = 1.5f;
else if (gZoomLevel < 2.0f) gZoomLevel = 2.0f;
else if (gZoomLevel < 3.0f) gZoomLevel = 3.0f;
@@ -250,17 +166,13 @@ static void DrawRealisticThermalOverlay(void);
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);
- }
- }
+ else gZoomLevel = 64.0f;
+ }
+}
- static void ZoomOutCallback(void* inRefcon)
- {
- if (gCameraActive) {
- // Reverse zoom steps
+static void ZoomOutCallback(void* inRefcon)
+{
+ if (gCameraActive) {
if (gZoomLevel > 48.0f) gZoomLevel = 48.0f;
else if (gZoomLevel > 32.0f) gZoomLevel = 32.0f;
else if (gZoomLevel > 24.0f) gZoomLevel = 24.0f;
@@ -272,178 +184,136 @@ static void DrawRealisticThermalOverlay(void);
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);
- }
- }
+ else gZoomLevel = 1.0f;
+ }
+}
- static void PanLeftCallback(void* inRefcon)
- {
- if (gCameraActive && !IsSimpleLockActive()) { // Only when not locked
- 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 PanLeftCallback(void* inRefcon)
+{
+ if (gCameraActive && !IsSimpleLockActive()) {
+ gCameraPan -= 0.5f;
+ if (gCameraPan < -180.0f) gCameraPan += 360.0f;
+ }
+}
- static void PanRightCallback(void* inRefcon)
- {
- if (gCameraActive && !IsSimpleLockActive()) { // Only when not locked
- 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 && !IsSimpleLockActive()) {
+ gCameraPan += 0.5f;
+ if (gCameraPan > 180.0f) gCameraPan -= 360.0f;
+ }
+}
- static void TiltUpCallback(void* inRefcon)
- {
- if (gCameraActive && !IsSimpleLockActive()) { // 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);
- XPLMDebugString(msg);
- }
- }
+static void TiltUpCallback(void* inRefcon)
+{
+ if (gCameraActive && !IsSimpleLockActive()) {
+ gCameraTilt = fminf(gCameraTilt + 0.5f, 45.0f);
+ }
+}
- static void TiltDownCallback(void* inRefcon)
- {
- if (gCameraActive && !IsSimpleLockActive()) { // 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);
- XPLMDebugString(msg);
- }
- }
+static void TiltDownCallback(void* inRefcon)
+{
+ if (gCameraActive && !IsSimpleLockActive()) {
+ gCameraTilt = fmaxf(gCameraTilt - 0.5f, -90.0f);
+ }
+}
- static void ThermalToggleCallback(void* inRefcon)
- {
- if (gCameraActive) {
- // Cycle through visual effect modes
- CycleVisualModes();
- }
- }
+static void ThermalToggleCallback(void* inRefcon)
+{
+ if (gCameraActive) {
+ CycleVisualModes();
+ }
+}
static void FocusLockCallback(void* inRefcon)
{
if (gCameraActive) {
if (!IsSimpleLockActive()) {
- // Lock to current camera direction using enhanced tracking
LockCurrentDirection(gCameraPan, gCameraTilt);
- XPLMDebugString("FLIR Camera System: Enhanced tracking engaged\n");
} else {
- // Disable enhanced tracking
DisableSimpleLock();
- XPLMDebugString("FLIR Camera System: Enhanced tracking disabled\n");
}
}
}
- // Camera control function
- static int FLIRCameraFunc(XPLMCameraPosition_t* outCameraPosition,
- int inIsLosingControl,
- void* inRefcon)
- {
- if (inIsLosingControl) {
- // We're losing control, clean up
- gCameraActive = 0;
- if (gDrawCallbackRegistered) {
- XPLMUnregisterDrawCallback(DrawThermalOverlay, xplm_Phase_Window, 0, NULL);
- gDrawCallbackRegistered = 0;
- }
- // Re-enable manipulator
- if (gManipulatorDisabled) {
- XPLMSetDatai(gManipulatorDisabled, 0);
- }
- DisableSimpleLock();
- return 0;
- }
-
- if (!gPlaneX || !gPlaneY || !gPlaneZ || !gPlaneHeading || !gPlanePitch || !gPlaneRoll) {
- return 1; // Keep control but don't update position
- }
-
- // Get current aircraft position and orientation
- float planeX = XPLMGetDataf(gPlaneX);
- float planeY = XPLMGetDataf(gPlaneY);
- float planeZ = XPLMGetDataf(gPlaneZ);
- float planeHeading = XPLMGetDataf(gPlaneHeading);
-
- // Calculate camera position (belly-mounted) first
- float headingRad = planeHeading * M_PI / 180.0f;
-
- // Position camera below and slightly forward of aircraft center
- outCameraPosition->x = planeX + gCameraDistance * sin(headingRad);
- outCameraPosition->y = planeY + gCameraHeight;
- outCameraPosition->z = planeZ + gCameraDistance * cos(headingRad);
-
- // Camera orientation control (mouse or enhanced tracking)
- if (!IsSimpleLockActive()) {
- // Mouse control for camera movement
- int mouseX, mouseY;
- XPLMGetMouseLocation(&mouseX, &mouseY);
-
- if (gLastMouseX != 0 || gLastMouseY != 0) {
- float deltaX = (mouseX - gLastMouseX) * gMouseSensitivity;
- float deltaY = (mouseY - gLastMouseY) * gMouseSensitivity;
-
- gCameraPan += deltaX;
- gCameraTilt -= deltaY; // Invert Y for natural control
-
- // 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;
- }
-
- gLastMouseX = mouseX;
- gLastMouseY = mouseY;
- } else {
- // Use locked camera angles (camera movement frozen)
- GetLockedAngles(&gCameraPan, &gCameraTilt);
- }
-
- // Camera orientation (pan/tilt relative to aircraft heading)
- outCameraPosition->heading = planeHeading + gCameraPan;
- outCameraPosition->pitch = gCameraTilt;
- outCameraPosition->roll = 0.0f; // Keep camera level
-
- // Apply zoom
- outCameraPosition->zoom = gZoomLevel;
-
- return 1; // Keep controlling camera
- }
+static int FLIRCameraFunc(XPLMCameraPosition_t* outCameraPosition, int inIsLosingControl, void* inRefcon)
+{
+ if (inIsLosingControl) {
+ gCameraActive = 0;
+ if (gDrawCallbackRegistered) {
+ XPLMUnregisterDrawCallback(DrawThermalOverlay, xplm_Phase_Window, 0, NULL);
+ gDrawCallbackRegistered = 0;
+ }
+ if (gManipulatorDisabled) {
+ XPLMSetDatai(gManipulatorDisabled, 0);
+ }
+ DisableSimpleLock();
+ return 0;
+ }
+
+ if (!gPlaneX || !gPlaneY || !gPlaneZ || !gPlaneHeading || !gPlanePitch || !gPlaneRoll) {
+ return 1;
+ }
+
+ float planeX = XPLMGetDataf(gPlaneX);
+ float planeY = XPLMGetDataf(gPlaneY);
+ float planeZ = XPLMGetDataf(gPlaneZ);
+ float planeHeading = XPLMGetDataf(gPlaneHeading);
+
+ float headingRad = planeHeading * M_PI / 180.0f;
+
+ outCameraPosition->x = planeX + gCameraDistance * sin(headingRad);
+ outCameraPosition->y = planeY + gCameraHeight;
+ outCameraPosition->z = planeZ + gCameraDistance * cos(headingRad);
+
+ if (!IsSimpleLockActive()) {
+ int mouseX, mouseY;
+ XPLMGetMouseLocation(&mouseX, &mouseY);
+
+ if (gLastMouseX != 0 || gLastMouseY != 0) {
+ float deltaX = (mouseX - gLastMouseX) * gMouseSensitivity;
+ float deltaY = (mouseY - gLastMouseY) * gMouseSensitivity;
+
+ gCameraPan += deltaX;
+ gCameraTilt -= deltaY;
+
+ while (gCameraPan > 180.0f) gCameraPan -= 360.0f;
+ while (gCameraPan < -180.0f) gCameraPan += 360.0f;
+
+ if (gCameraTilt > 45.0f) gCameraTilt = 45.0f;
+ if (gCameraTilt < -90.0f) gCameraTilt = -90.0f;
+ }
+
+ gLastMouseX = mouseX;
+ gLastMouseY = mouseY;
+ } else {
+ GetLockedAngles(&gCameraPan, &gCameraTilt);
+ }
+
+ outCameraPosition->heading = planeHeading + gCameraPan;
+ outCameraPosition->pitch = gCameraTilt;
+ outCameraPosition->roll = 0.0f;
+ outCameraPosition->zoom = gZoomLevel;
+
+ return 1;
+}
- // Drawing callback for thermal overlay
- static int DrawThermalOverlay(XPLMDrawingPhase inPhase,
- int inIsBefore,
- void* inRefcon)
- {
- if (!gCameraActive) return 1;
-
- DrawRealisticThermalOverlay();
-
- return 1;
- }
+static int DrawThermalOverlay(XPLMDrawingPhase inPhase, int inIsBefore, void* inRefcon)
+{
+ if (!gCameraActive) return 1;
+
+ DrawRealisticThermalOverlay();
+
+ return 1;
+}
-// Enhanced thermal overlay with visual effects
static void DrawRealisticThermalOverlay(void)
{
int screenWidth, screenHeight;
XPLMGetScreenSize(&screenWidth, &screenHeight);
- // Apply visual effects (monochrome, thermal, noise, etc.)
RenderVisualEffects(screenWidth, screenHeight);
- // Set up OpenGL for crosshair drawing
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
@@ -453,73 +323,58 @@ static void DrawRealisticThermalOverlay(void)
glPushMatrix();
glLoadIdentity();
- // Disable depth testing for overlay
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- // Draw crosshair in center
float centerX = screenWidth / 2.0f;
float centerY = screenHeight / 2.0f;
- // Set color based on lock status
if (IsSimpleLockActive()) {
- glColor4f(1.0f, 0.0f, 0.0f, 0.9f); // Red when locked
+ glColor4f(1.0f, 0.0f, 0.0f, 0.9f);
} else {
- glColor4f(0.0f, 1.0f, 0.0f, 0.9f); // Bright green when scanning
+ glColor4f(0.0f, 1.0f, 0.0f, 0.9f);
}
glLineWidth(2.0f);
- // Central crosshair
glBegin(GL_LINES);
- // Horizontal line
glVertex2f(centerX - 20, centerY);
glVertex2f(centerX + 20, centerY);
- // Vertical line
glVertex2f(centerX, centerY - 20);
glVertex2f(centerX, centerY + 20);
glEnd();
- // Military-style targeting brackets [ ] - FIXED SIZE
- float bracketSize = 50.0f; // Fixed size - doesn't change with zoom
+ float bracketSize = 50.0f;
float bracketLength = 20.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(3.0f);
glBegin(GL_POINTS);
glVertex2f(centerX, centerY);
glEnd();
- // Restore OpenGL state
glEnable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
glLineWidth(1.0f);
diff --git a/FLIR_Camera.o b/FLIR_Camera.o
index 454cd12..e6a69be 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
deleted file mode 100644
index 9e9cca2..0000000
--- a/FLIR_Camera_OLD.cpp
+++ /dev/null
@@ -1,1308 +0,0 @@
-/*
- * 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 998f182..462b878 100644
--- a/FLIR_HUD.lua
+++ b/FLIR_HUD.lua
@@ -1,31 +1,29 @@
-- FLIR Camera HUD Display Script for FlyWithLua
-- Auto-toggles based on camera view with realistic military HUD
+-- Press F9 to toggle on/off
--- Global variables
flir_start_time = flir_start_time or os.time()
flir_hud_enabled = flir_hud_enabled or true
flir_last_view_type = 0
function draw_flir_hud()
- -- Auto-toggle based on camera view
local view_type = XPLMGetDatai(XPLMFindDataRef("sim/graphics/view/view_type"))
- -- Auto-enable when entering camera view, disable when leaving
if view_type == 1026 and flir_last_view_type ~= 1026 then
- flir_hud_enabled = true
- logMsg("FLIR HUD: Auto-enabled (Camera view active)")
+ if flir_hud_enabled then
+ logMsg("FLIR HUD: Camera view active")
+ end
elseif view_type ~= 1026 and flir_last_view_type == 1026 then
- flir_hud_enabled = false
- logMsg("FLIR HUD: Auto-disabled (Camera view inactive)")
+ if flir_hud_enabled then
+ logMsg("FLIR HUD: Camera view inactive")
+ end
end
flir_last_view_type = view_type
- -- Only draw if HUD is enabled and in camera view
if not flir_hud_enabled or view_type ~= 1026 then
return
end
- -- Get aircraft data
local zulu_time = XPLMGetDataf(XPLMFindDataRef("sim/time/zulu_time_sec"))
local latitude = XPLMGetDataf(XPLMFindDataRef("sim/flightmodel/position/latitude"))
local longitude = XPLMGetDataf(XPLMFindDataRef("sim/flightmodel/position/longitude"))
@@ -33,27 +31,22 @@ function draw_flir_hud()
local ground_speed = XPLMGetDataf(XPLMFindDataRef("sim/flightmodel/position/groundspeed"))
local heading = XPLMGetDataf(XPLMFindDataRef("sim/flightmodel/position/psi"))
- -- Convert values
local hours = math.floor(zulu_time / 3600) % 24
local minutes = math.floor((zulu_time % 3600) / 60)
local time_string = string.format("%02d:%02d Z", hours, minutes)
local alt_feet = math.floor(altitude_msl * 3.28084)
local speed_knots = math.floor(ground_speed * 1.94384)
- -- Set FLIR green color
graphics.set_color(0.0, 1.0, 0.0, 1.0)
- -- Top status bar - realistic military format
local status_line = string.format("▶ FLIR-25HD %s %.4f°N %.4f°W MSL:%dft",
time_string, latitude, longitude, alt_feet)
graphics.draw_string(20, SCREEN_HEIGHT - 25, status_line, "large")
- -- Navigation data
local nav_line = string.format("▲ HDG:%03d° SPD:%03d kts TRK:%03d° VSI:+0000 fpm",
math.floor(heading), speed_knots, math.floor(heading))
graphics.draw_string(20, SCREEN_HEIGHT - 50, nav_line, "large")
- -- Mission timer (top right)
local mission_time = os.time() - flir_start_time
local mission_hours = math.floor(mission_time / 3600)
local mission_mins = math.floor((mission_time % 3600) / 60)
@@ -61,31 +54,32 @@ function draw_flir_hud()
local mission_line = string.format("REC: %02d:%02d:%02d", mission_hours, mission_mins, mission_secs)
graphics.draw_string(SCREEN_WIDTH - 180, SCREEN_HEIGHT - 25, mission_line, "large")
- -- Target info (top right)
graphics.draw_string(SCREEN_WIDTH - 180, SCREEN_HEIGHT - 50, "TGT: SCANNING", "large")
- -- System status (bottom left)
graphics.draw_string(20, 80, "◆ SYS: NOMINAL STAB: ON IR: WHT", "large")
graphics.draw_string(20, 105, "● ZOOM: 1.0x FOV: WIDE FOCUS: AUTO", "large")
- -- Aircraft ID (bottom)
graphics.draw_string(20, SCREEN_HEIGHT - 75, "✈ MARITIME PATROL A319", "large")
end
--- Toggle function for manual override
function toggle_flir_hud()
flir_hud_enabled = not flir_hud_enabled
if flir_hud_enabled then
- logMsg("FLIR HUD: Manually enabled")
+ logMsg("FLIR HUD: Enabled")
else
- logMsg("FLIR HUD: Manually disabled")
+ logMsg("FLIR HUD: Disabled")
end
end
--- Register drawing function
do_every_draw("draw_flir_hud()")
-
--- Add macro for manual toggle (backup)
add_macro("FLIR: Toggle HUD", "toggle_flir_hud()", "", "activate")
-logMsg("FLIR HUD Script Loaded - Auto-toggles with camera view, manual toggle available")
+function flir_hud_key_handler()
+ if VKEY == 120 then
+ toggle_flir_hud()
+ end
+end
+
+do_on_keystroke("flir_hud_key_handler()")
+
+logMsg("FLIR HUD Script Loaded - Press F9 to toggle")
\ No newline at end of file
diff --git a/FLIR_HUD_Simple.lua b/FLIR_HUD_Simple.lua
deleted file mode 100644
index a989c55..0000000
--- a/FLIR_HUD_Simple.lua
+++ /dev/null
@@ -1,76 +0,0 @@
--- FLIR Camera HUD Display Script for FlyWithLua
--- Toggle with macro: FLIR Toggle HUD
-
--- Global variables
-flir_start_time = flir_start_time or os.time()
-flir_hud_enabled = flir_hud_enabled or true
-
-function draw_flir_hud()
- -- Only draw if HUD is enabled
- if not flir_hud_enabled then
- return
- end
- -- Simple check for external view
- local view_type = XPLMGetDatai(XPLMFindDataRef("sim/graphics/view/view_type"))
-
- if view_type == 1026 then -- External view
- -- Get basic data using direct dataref calls
- local zulu_time = XPLMGetDataf(XPLMFindDataRef("sim/time/zulu_time_sec"))
- local latitude = XPLMGetDataf(XPLMFindDataRef("sim/flightmodel/position/latitude"))
- local longitude = XPLMGetDataf(XPLMFindDataRef("sim/flightmodel/position/longitude"))
- local altitude_msl = XPLMGetDataf(XPLMFindDataRef("sim/flightmodel/position/elevation"))
- local ground_speed = XPLMGetDataf(XPLMFindDataRef("sim/flightmodel/position/groundspeed"))
- local heading = XPLMGetDataf(XPLMFindDataRef("sim/flightmodel/position/psi"))
-
- -- Convert zulu time to HH:MM format
- local hours = math.floor(zulu_time / 3600) % 24
- local minutes = math.floor((zulu_time % 3600) / 60)
- local time_string = string.format("%02d:%02d UTC", hours, minutes)
-
- -- Convert altitude to feet
- local alt_feet = math.floor(altitude_msl * 3.28084)
-
- -- Convert ground speed to knots
- local speed_knots = math.floor(ground_speed * 1.94384)
-
- -- Set text color to FLIR green
- graphics.set_color(0.0, 1.0, 0.0, 1.0)
-
- -- Draw HUD text
- local status_line = string.format("FLIR CAMERA %s LAT:%.4f LON:%.4f ALT:%dft",
- time_string, latitude, longitude, alt_feet)
- graphics.draw_string(30, SCREEN_HEIGHT - 40, status_line, "large")
-
- local nav_line = string.format("HDG:%03d SPD:%d kts GS:%.1f m/s",
- math.floor(heading), speed_knots, ground_speed)
- graphics.draw_string(30, SCREEN_HEIGHT - 70, nav_line, "large")
-
- local mission_time = os.time() - flir_start_time
- local mission_mins = math.floor(mission_time / 60)
- local mission_secs = mission_time % 60
- local mission_line = string.format("MISSION TIME: %02d:%02d", mission_mins, mission_secs)
- graphics.draw_string(SCREEN_WIDTH - 300, SCREEN_HEIGHT - 40, mission_line, "large")
-
- graphics.draw_string(SCREEN_WIDTH - 300, SCREEN_HEIGHT - 70, "TGT: SCANNING...", "large")
- graphics.draw_string(30, 90, "ZOOM: ACTIVE THERMAL: WHT", "large")
- graphics.draw_string(30, SCREEN_HEIGHT - 100, "A319 MTP AIRCRAFT", "large")
- end
-end
-
--- Toggle function
-function toggle_flir_hud()
- flir_hud_enabled = not flir_hud_enabled
- if flir_hud_enabled then
- logMsg("FLIR HUD: Enabled")
- else
- logMsg("FLIR HUD: Disabled")
- end
-end
-
--- Register drawing function
-do_every_draw("draw_flir_hud()")
-
--- Add macro for toggling HUD
-add_macro("FLIR: Toggle HUD", "toggle_flir_hud()", "", "activate")
-
-logMsg("FLIR HUD Simple Script Loaded - Use 'FLIR: Toggle HUD' macro to toggle")
diff --git a/FLIR_LockOn.cpp b/FLIR_LockOn.cpp
deleted file mode 100644
index 144cca1..0000000
--- a/FLIR_LockOn.cpp
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * FLIR_LockOn.cpp
- *
- * Real-world lock-on system for FLIR camera
- * Implements proper world-space target tracking using X-Plane's coordinate system
- */
-
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
-
-#include "XPLMDataAccess.h"
-#include "XPLMUtilities.h"
-#include "XPLMGraphics.h"
-#include "FLIR_LockOn.h"
-
-// Lock-on state - using OpenGL local coordinates for precision
-static int gLockOnActive = 0;
-static double gTargetX = 0.0; // Target X in OpenGL coordinates (East)
-static double gTargetY = 0.0; // Target Y in OpenGL coordinates (Up)
-static double gTargetZ = 0.0; // Target Z in OpenGL coordinates (South)
-static float gLockAcquisitionTime = 0.0f; // Time when lock was acquired
-
-// 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;
- }
-
- // SIMPLE APPROACH: Just store current pan/tilt as the target direction
- // This is what most military systems do - lock the current LOS (Line of Sight)
-
- // Get current aircraft position in OpenGL coordinates
- double planeX = XPLMGetDataf(gPlaneX);
- double planeY = XPLMGetDataf(gPlaneY);
- double planeZ = XPLMGetDataf(gPlaneZ);
- float planeHeading = XPLMGetDataf(gPlaneHeading);
-
- // Calculate camera position (belly-mounted, slightly forward)
- float headingRad = planeHeading * M_PI / 180.0f;
- double cameraX = planeX + 3.0 * sin(headingRad); // 3m forward (east)
- double cameraY = planeY - 5.0; // 5m below
- double cameraZ = planeZ - 3.0 * cos(headingRad); // 3m forward (north, Z+ is south)
-
- // Calculate absolute camera direction in world space
- float absoluteHeading = planeHeading + currentPan;
- float pitchRad = currentTilt * M_PI / 180.0f;
-
- // Project target point forward from camera
- double horizontalDistance = distance * cos(pitchRad);
- double headingRadAbs = absoluteHeading * M_PI / 180.0f;
-
- // Target calculation - positive angles go clockwise from north
- gTargetX = cameraX + horizontalDistance * sin(headingRadAbs); // East component
- gTargetY = cameraY + distance * sin(pitchRad); // Up component
- gTargetZ = cameraZ - horizontalDistance * cos(headingRadAbs); // North component (Z+ is south)
-
- gLockAcquisitionTime = XPLMGetDataf(XPLMFindDataRef("sim/time/total_running_time_sec"));
- gLockOnActive = 1;
-
- char msg[256];
- sprintf(msg, "FLIR Lock-On: Plane hdg=%.1f°, Pan=%.1f°, Abs=%.1f°, Target=(%.1f,%.1f,%.1f)\n",
- planeHeading, currentPan, absoluteHeading, gTargetX, gTargetY, gTargetZ);
- XPLMDebugString(msg);
-}
-
-void UpdateCameraToLockPoint(float* outPan, float* outTilt)
-{
- if (!gLockOnActive || !gPlaneX || !gPlaneY || !gPlaneZ || !gPlaneHeading) {
- return;
- }
-
- // Get current aircraft position and heading
- double planeX = XPLMGetDataf(gPlaneX);
- double planeY = XPLMGetDataf(gPlaneY);
- double planeZ = XPLMGetDataf(gPlaneZ);
- float planeHeading = XPLMGetDataf(gPlaneHeading);
-
- // Calculate current camera position (same as in SetArbitraryLockPoint)
- float headingRad = planeHeading * M_PI / 180.0f;
- double cameraX = planeX + 3.0 * sin(headingRad); // 3m forward (east)
- double cameraY = planeY - 5.0; // 5m below
- double cameraZ = planeZ - 3.0 * cos(headingRad); // 3m forward (north, Z+ is south)
-
- // Calculate vector from camera to target
- double dx = gTargetX - cameraX; // East component
- double dy = gTargetY - cameraY; // Up component
- double dz = gTargetZ - cameraZ; // South component
-
- // Calculate distance to target
- double horizontalDist = sqrt(dx * dx + dz * dz);
- double totalDist = sqrt(dx * dx + dy * dy + dz * dz);
-
- if (totalDist < 1.0) {
- // Target too close, maintain current angles
- return;
- }
-
- // Convert vector to spherical coordinates
- // X-Plane: Camera faces -Z initially (north), X=East, Z=South
- // For heading: 0° = north = -Z direction, 90° = east = +X direction
- float targetHeading = atan2(dx, -dz) * 180.0f / M_PI; // atan2(East, North)
- float targetPitch = atan2(dy, horizontalDist) * 180.0f / M_PI;
-
- // Debug coordinate system
- char coordMsg[256];
- sprintf(coordMsg, "FLIR Debug: dx=%.1f(E), dy=%.1f(U), dz=%.1f(S), camera facing %.1f°\n",
- dx, dy, dz, planeHeading);
- XPLMDebugString(coordMsg);
-
- // Convert absolute heading to relative camera pan
- *outPan = targetHeading - planeHeading;
- *outTilt = targetPitch;
-
- // Normalize pan angle to -180 to +180 degrees
- while (*outPan > 180.0f) *outPan -= 360.0f;
- while (*outPan < -180.0f) *outPan += 360.0f;
-
- // Clamp to camera physical limits
- if (*outPan > 180.0f) *outPan = 180.0f;
- if (*outPan < -180.0f) *outPan = -180.0f;
- if (*outTilt > 45.0f) *outTilt = 45.0f;
- if (*outTilt < -90.0f) *outTilt = -90.0f;
-
- // Debug output for testing
- char debugMsg[256];
- sprintf(debugMsg, "FLIR Track: Dist=%.1fm, TargetHdg=%.1f°, Pan=%.1f°, Pitch=%.1f°\n",
- totalDist, targetHeading, *outPan, *outTilt);
- XPLMDebugString(debugMsg);
-}
-
-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 current distance to target
- if (gPlaneX && gPlaneY && gPlaneZ) {
- double planeX = XPLMGetDataf(gPlaneX);
- double planeY = XPLMGetDataf(gPlaneY);
- double planeZ = XPLMGetDataf(gPlaneZ);
-
- // Calculate camera position
- float planeHeading = XPLMGetDataf(gPlaneHeading);
- float headingRad = planeHeading * M_PI / 180.0f;
- double cameraX = planeX + 3.0 * sin(headingRad);
- double cameraY = planeY - 5.0;
- double cameraZ = planeZ - 3.0 * cos(headingRad);
-
- // Calculate distance to target
- double dx = gTargetX - cameraX;
- double dy = gTargetY - cameraY;
- double dz = gTargetZ - cameraZ;
- double distance = sqrt(dx * dx + dy * dy + dz * dz);
-
- snprintf(statusBuffer, bufferSize, "LOCK: ON RNG %.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
deleted file mode 100644
index c1537ea..0000000
--- a/FLIR_LockOn.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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_SimpleLock.cpp b/FLIR_SimpleLock.cpp
index 9eb0568..9087632 100644
--- a/FLIR_SimpleLock.cpp
+++ b/FLIR_SimpleLock.cpp
@@ -1,9 +1,8 @@
/*
* FLIR_SimpleLock.cpp
*
- * Enhanced lock-on system using X-Plane's tracking algorithms
- * Implements sophisticated target following like X-Plane's built-in external view
- * Provides smooth tracking for ships, vehicles, and any visual targets
+ * Simple camera lock system for FLIR targeting
+ * Freezes camera movement when locked on target
*/
#include <string.h>
@@ -19,28 +18,20 @@
#include "XPLMUtilities.h"
#include "FLIR_SimpleLock.h"
-// Simple lock-on state
static int gLockActive = 0;
-static float gLockedPan = 0.0f; // Pan angle when locked (for display only)
-static float gLockedTilt = 0.0f; // Tilt angle when locked (for display only)
+static float gLockedPan = 0.0f;
+static float gLockedTilt = 0.0f;
void InitializeSimpleLock()
{
gLockActive = 0;
- XPLMDebugString("FLIR Simple Lock: Initialized\n");
}
void LockCurrentDirection(float currentPan, float currentTilt)
{
- // Simple lock - just store angles for display and freeze camera movement
gLockedPan = currentPan;
gLockedTilt = currentTilt;
gLockActive = 1;
-
- char msg[256];
- sprintf(msg, "FLIR Camera Lock: Engaged at Pan=%.1f°, Tilt=%.1f°\n",
- gLockedPan, gLockedTilt);
- XPLMDebugString(msg);
}
void GetLockedAngles(float* outPan, float* outTilt)
@@ -49,7 +40,6 @@ void GetLockedAngles(float* outPan, float* outTilt)
return;
}
- // Return stored angles - camera movement is frozen
*outPan = gLockedPan;
*outTilt = gLockedTilt;
}
@@ -57,7 +47,6 @@ void GetLockedAngles(float* outPan, float* outTilt)
void DisableSimpleLock()
{
gLockActive = 0;
- XPLMDebugString("FLIR Camera Lock: Disabled\n");
}
int IsSimpleLockActive()
diff --git a/FLIR_SimpleLock.h b/FLIR_SimpleLock.h
index 0d0e67b..1294ad2 100644
--- a/FLIR_SimpleLock.h
+++ b/FLIR_SimpleLock.h
@@ -1,8 +1,7 @@
/*
* FLIR_SimpleLock.h
*
- * Enhanced lock-on system using X-Plane's tracking algorithms
- * Provides smooth target following like X-Plane's built-in external view
+ * Simple camera lock system for FLIR targeting
*/
#ifndef FLIR_SIMPLELOCK_H
@@ -12,23 +11,11 @@
extern "C" {
#endif
-// Initialize the enhanced lock system
void InitializeSimpleLock();
-
-// Lock to current camera direction (enhanced algorithm)
void LockCurrentDirection(float currentPan, float currentTilt);
-
-
-// Get locked camera angles (legacy support)
void GetLockedAngles(float* outPan, float* outTilt);
-
-// Disable lock
void DisableSimpleLock();
-
-// Check if lock is active
int IsSimpleLockActive();
-
-// Get lock status string for display
void GetSimpleLockStatus(char* statusBuffer, int bufferSize);
#ifdef __cplusplus
diff --git a/FLIR_SimpleLock.o b/FLIR_SimpleLock.o
index acc523a..96d933e 100644
Binary files a/FLIR_SimpleLock.o and b/FLIR_SimpleLock.o differ
diff --git a/FLIR_VisualEffects.cpp b/FLIR_VisualEffects.cpp
index 4e6ec1b..000dbd6 100644
--- a/FLIR_VisualEffects.cpp
+++ b/FLIR_VisualEffects.cpp
@@ -25,7 +25,6 @@
#include <windows.h>
#include <GL/gl.h>
-// Visual effects state
static int gMonochromeEnabled = 0;
static int gThermalEnabled = 1;
static int gIREnabled = 0;
@@ -33,8 +32,6 @@ static int gNoiseEnabled = 1;
static int gScanLinesEnabled = 1;
static float gBrightness = 1.0f;
static float gContrast = 1.2f;
-
-// Effect parameters
static float gNoiseIntensity = 0.1f;
static float gScanLineOpacity = 0.05f;
static int gFrameCounter = 0;
@@ -42,47 +39,33 @@ static int gFrameCounter = 0;
void InitializeVisualEffects()
{
srand(time(NULL));
- XPLMDebugString("FLIR Visual Effects: Initialized\n");
}
void SetMonochromeFilter(int enabled)
{
gMonochromeEnabled = enabled;
- char msg[256];
- sprintf(msg, "FLIR Visual Effects: Monochrome %s\n", enabled ? "ON" : "OFF");
- XPLMDebugString(msg);
}
void SetThermalMode(int enabled)
{
gThermalEnabled = enabled;
- char msg[256];
- sprintf(msg, "FLIR Visual Effects: Thermal %s\n", enabled ? "ON" : "OFF");
- XPLMDebugString(msg);
}
void SetIRMode(int enabled)
{
gIREnabled = enabled;
- char msg[256];
- sprintf(msg, "FLIR Visual Effects: IR (B/W) %s\n", enabled ? "ON" : "OFF");
- XPLMDebugString(msg);
}
void SetImageEnhancement(float brightness, float contrast)
{
gBrightness = brightness;
gContrast = contrast;
- char msg[256];
- sprintf(msg, "FLIR Visual Effects: Brightness=%.1f, Contrast=%.1f\n", brightness, contrast);
- XPLMDebugString(msg);
}
void RenderVisualEffects(int screenWidth, int screenHeight)
{
gFrameCounter++;
- // Set up OpenGL for 2D screen-space effects
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
@@ -92,33 +75,25 @@ void RenderVisualEffects(int screenWidth, int screenHeight)
glPushMatrix();
glLoadIdentity();
- // Disable depth testing for screen overlays
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
- // Apply monochrome filter
if (gMonochromeEnabled) {
RenderMonochromeFilter(screenWidth, screenHeight);
}
- // Apply thermal vision effects
if (gThermalEnabled) {
RenderThermalEffects(screenWidth, screenHeight);
}
- // IR black/white filter removed - was not realistic
-
- // Add camera noise/grain
if (gNoiseEnabled) {
RenderCameraNoise(screenWidth, screenHeight);
}
- // Add scan lines for CRT-like effect
if (gScanLinesEnabled) {
RenderScanLines(screenWidth, screenHeight);
}
- // Restore OpenGL state
glEnable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
glPopMatrix();
@@ -129,10 +104,7 @@ void RenderVisualEffects(int screenWidth, int screenHeight)
void RenderMonochromeFilter(int screenWidth, int screenHeight)
{
- // Monochrome overlay using color blending
- glBlendFunc(GL_DST_COLOR, GL_ZERO); // Multiply blend mode
-
- // Create a subtle green monochrome tint (military night vision style)
+ glBlendFunc(GL_DST_COLOR, GL_ZERO);
glColor4f(0.3f, 1.0f, 0.3f, 1.0f);
glBegin(GL_QUADS);
@@ -142,7 +114,6 @@ void RenderMonochromeFilter(int screenWidth, int screenHeight)
glVertex2f(0, screenHeight);
glEnd();
- // Add brightness/contrast adjustment
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
float brightness_adj = (gBrightness - 1.0f) * 0.3f;
@@ -159,12 +130,10 @@ void RenderMonochromeFilter(int screenWidth, int screenHeight)
glVertex2f(0, screenHeight);
glEnd();
- // Add white temperature scale lines (like thermal mode)
glColor4f(1.0f, 1.0f, 1.0f, 0.8f);
glLineWidth(1.0f);
glBegin(GL_LINES);
- // Temperature scale on left
for (int i = 0; i < 10; i++) {
float y = 50 + i * (screenHeight - 100) / 10.0f;
glVertex2f(10, y);
@@ -176,9 +145,7 @@ void RenderMonochromeFilter(int screenWidth, int screenHeight)
void RenderThermalEffects(int screenWidth, int screenHeight)
{
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- // Thermal overlay with heat signature simulation
- glColor4f(1.0f, 0.4f, 0.0f, 0.15f); // Orange thermal tint
+ glColor4f(1.0f, 0.4f, 0.0f, 0.15f);
glBegin(GL_QUADS);
glVertex2f(0, 0);
@@ -187,21 +154,16 @@ void RenderThermalEffects(int screenWidth, int screenHeight)
glVertex2f(0, screenHeight);
glEnd();
- // Add thermal border indicators
glColor4f(1.0f, 1.0f, 1.0f, 0.8f);
glLineWidth(1.0f);
glBegin(GL_LINES);
- // Temperature scale on left
for (int i = 0; i < 10; i++) {
float y = 50 + i * (screenHeight - 100) / 10.0f;
glVertex2f(10, y);
glVertex2f(25, y);
}
glEnd();
-
- // Add "WHT HOT" indicator
- // (Text would be drawn here if we had font rendering)
}
void RenderCameraNoise(int screenWidth, int screenHeight)
@@ -314,43 +276,37 @@ void CycleVisualModes()
mode = (mode + 1) % 4; // Only 4 modes now
switch (mode) {
- case 0: // Standard
+ case 0:
SetMonochromeFilter(0);
SetThermalMode(0);
SetIRMode(0);
gNoiseEnabled = 0;
gScanLinesEnabled = 0;
- XPLMDebugString("FLIR Visual Effects: Standard Mode\n");
break;
- case 1: // Monochrome
+ case 1:
SetMonochromeFilter(1);
SetThermalMode(0);
SetIRMode(0);
gNoiseEnabled = 1;
gScanLinesEnabled = 1;
- XPLMDebugString("FLIR Visual Effects: Monochrome Mode\n");
break;
- case 2: // Thermal
+ case 2:
SetMonochromeFilter(0);
SetThermalMode(1);
SetIRMode(0);
gNoiseEnabled = 1;
gScanLinesEnabled = 0;
- XPLMDebugString("FLIR Visual Effects: Thermal Mode\n");
break;
- case 3: // Enhanced Monochrome
+ case 3:
SetMonochromeFilter(1);
SetThermalMode(0);
SetIRMode(0);
gNoiseEnabled = 1;
gScanLinesEnabled = 1;
- XPLMDebugString("FLIR Visual Effects: Enhanced Monochrome\n");
break;
-
- // case 4 removed - now case 3 is the last mode
}
}
diff --git a/FLIR_VisualEffects.h b/FLIR_VisualEffects.h
index 4ac76d8..cbdb2c2 100644
--- a/FLIR_VisualEffects.h
+++ b/FLIR_VisualEffects.h
@@ -11,29 +11,19 @@
extern "C" {
#endif
-// Initialize the visual effects system
void InitializeVisualEffects();
-
-// Main rendering function - call from drawing callback
void RenderVisualEffects(int screenWidth, int screenHeight);
-// Individual effect controls
void SetMonochromeFilter(int enabled);
void SetThermalMode(int enabled);
void SetIRMode(int enabled);
void SetImageEnhancement(float brightness, float contrast);
-
-// Individual effect renderers
void RenderMonochromeFilter(int screenWidth, int screenHeight);
void RenderThermalEffects(int screenWidth, int screenHeight);
void RenderIRFilter(int screenWidth, int screenHeight);
void RenderCameraNoise(int screenWidth, int screenHeight);
void RenderScanLines(int screenWidth, int screenHeight);
-
-// Quick mode switching
void CycleVisualModes();
-
-// Status display
void GetVisualEffectsStatus(char* statusBuffer, int bufferSize);
#ifdef __cplusplus
diff --git a/FLIR_VisualEffects.o b/FLIR_VisualEffects.o
index 9b5a39b..6fe768c 100644
Binary files a/FLIR_VisualEffects.o and b/FLIR_VisualEffects.o differ
diff --git a/build/FLIR_Camera/win_x64/FLIR_Camera.xpl b/build/FLIR_Camera/win_x64/FLIR_Camera.xpl
index 1d6799b..d1bd2b2 100755
Binary files a/build/FLIR_Camera/win_x64/FLIR_Camera.xpl and b/build/FLIR_Camera/win_x64/FLIR_Camera.xpl differ