ray
Owner: IIIlllIIIllI URL: git@github.com:nyangkosense/ray.git
binary search
Commit 3c349b8a25ebfdf50fabd5af30d5d6ab13619ed7 by SM <seb.michalk@gmail.com> on 2025-06-30 10:43:07 +0200
diff --git a/build/JTACCoords/win_x64/JTACCoords.xpl b/build/JTACCoords/win_x64/JTACCoords.xpl
index 2c1c17d..2edc039 100755
Binary files a/build/JTACCoords/win_x64/JTACCoords.xpl and b/build/JTACCoords/win_x64/JTACCoords.xpl differ
diff --git a/probe.cpp b/probe.cpp
index 1cf14e1..ca7dbc6 100644
--- a/probe.cpp
+++ b/probe.cpp
@@ -248,39 +248,68 @@ bool DesignateLaser(int screenX, int screenY, TargetCoords* target) {
return false;
}
- // Perform terrain intersection using ray marching
- const int maxSteps = 1000;
- const float stepSize = 10.0f; // 10 meters per step
+ // Perform terrain intersection using divide-and-conquer ray casting
+ // This is the proper way to do ray casting in X-Plane as discussed in forums
+
+ float minDistance = 1.0f; // 1 meter minimum
+ float maxDistance = 30000.0f; // 30km maximum range
+ float currentDistance = maxDistance;
XPLMProbeInfo_t probeInfo;
probeInfo.structSize = sizeof(XPLMProbeInfo_t);
- for (int i = 1; i <= maxSteps; i++) {
- float testX = rayStartX + rayDirX * stepSize * i;
- float testY = rayStartY + rayDirY * stepSize * i;
- float testZ = rayStartZ + rayDirZ * stepSize * i;
+ // Binary search for terrain intersection
+ int iterations = 0;
+ const int maxIterations = 50; // Should be enough for 1-meter precision
+
+ while ((maxDistance - minDistance) > 1.0f && iterations < maxIterations) {
+ currentDistance = (minDistance + maxDistance) * 0.5f;
+
+ // Calculate test point along ray
+ float testX = rayStartX + rayDirX * currentDistance;
+ float testY = rayStartY + rayDirY * currentDistance;
+ float testZ = rayStartZ + rayDirZ * currentDistance;
// Probe terrain at this point
XPLMProbeResult result = XPLMProbeTerrainXYZ(gTerrainProbe, testX, testY, testZ, &probeInfo);
if (result == xplm_ProbeHitTerrain) {
- // Found intersection - store target coordinates
- target->localX = probeInfo.locationX;
- target->localY = probeInfo.locationY;
- target->localZ = probeInfo.locationZ;
-
- // Convert back to world coordinates
- XPLMLocalToWorld(probeInfo.locationX, probeInfo.locationY, probeInfo.locationZ,
- &target->latitude, &target->longitude, &target->elevation);
-
- target->valid = true;
- return true;
+ // We're above terrain, check if we're below ground level
+ if (testY < probeInfo.locationY) {
+ // We're underground - intersection is closer
+ maxDistance = currentDistance;
+ } else {
+ // We're above ground - intersection is further
+ minDistance = currentDistance;
+ }
+ } else {
+ // No terrain data - probably too far out
+ maxDistance = currentDistance;
}
- // Check if we've gone too far (beyond reasonable range)
- if (stepSize * i > 50000.0f) { // 50km max range
- break;
- }
+ iterations++;
+ }
+
+ // Final probe at the refined distance
+ currentDistance = (minDistance + maxDistance) * 0.5f;
+ float finalX = rayStartX + rayDirX * currentDistance;
+ float finalY = rayStartY + rayDirY * currentDistance;
+ float finalZ = rayStartZ + rayDirZ * currentDistance;
+
+ XPLMProbeResult finalResult = XPLMProbeTerrainXYZ(gTerrainProbe, finalX, finalY, finalZ, &probeInfo);
+
+ if (finalResult == xplm_ProbeHitTerrain) {
+ // Store the terrain intersection point
+ target->localX = probeInfo.locationX;
+ target->localY = probeInfo.locationY;
+ target->localZ = probeInfo.locationZ;
+
+ // Convert back to world coordinates
+ XPLMLocalToWorld(probeInfo.locationX, probeInfo.locationY, probeInfo.locationZ,
+ &target->latitude, &target->longitude, &target->elevation);
+
+ target->valid = true;
+ return true;
}
target->valid = false;
diff --git a/probe.o b/probe.o
index 265befb..553d250 100644
Binary files a/probe.o and b/probe.o differ