@@ -642,81 +642,103 @@ namespace XPC
642642 unsigned char aircraft = buffer[5 ];
643643 Log::FormatLine (LOG_TRACE, " GETT" , " Getting terrain information for aircraft %u" , aircraft);
644644
645- double loc[3 ];
646- double X;
647- double Y;
648- double Z;
649- memcpy (loc, buffer + 6 , 24 );
645+ double pos[3 ];
646+ memcpy (pos, buffer + 6 , 24 );
650647
651- if (loc [0 ] == -998 || loc [1 ] == -998 || loc [2 ] == -998 )
648+ if (pos [0 ] == -998 || pos [1 ] == -998 || pos [2 ] == -998 )
652649 {
653650 // get terrain properties at aircraft location
654- // probe needs to be below terrain to work...
655- X = DataManager::GetDouble (DREF_LocalX, aircraft);
656- Z = DataManager::GetDouble (DREF_LocalZ, aircraft);
657- Y = -100.0 ;
658- }
659- else
660- {
661- // terrain probe at specified location
662- XPLMWorldToLocal (loc[0 ], loc[1 ], loc[2 ], &X, &Y, &Z);
651+ pos[0 ] = DataManager::GetDouble (DREF_Latitude, aircraft);
652+ pos[1 ] = DataManager::GetDouble (DREF_Longitude, aircraft);
653+ pos[2 ] = 0.0 ;
663654 }
655+ MessageHandlers::SendTerr (pos, aircraft);
656+ }
657+
658+ void MessageHandlers::SendTerr (double pos[3 ], char aircraft)
659+ {
660+ double lat, lon, alt, X, Y, Z;
664661
665662 // Init terrain probe (if required) and probe data struct
666- XPLMProbeInfo_t probe_data;
663+ static XPLMProbeInfo_t probe_data;
667664 probe_data.structSize = sizeof (XPLMProbeInfo_t);
668665
669666 if (Terrain_probe == nullptr )
670667 {
671- Log::FormatLine (LOG_TRACE, " GETT " , " Create terrain probe for aircraft %u" , aircraft);
668+ Log::FormatLine (LOG_TRACE, " TERR " , " Create terrain probe for aircraft %u" , aircraft);
672669 Terrain_probe = XPLMCreateProbe (0 );
673670 }
674671
672+ // terrain probe at specified location
673+ // Follow the process in the following post to get accurate results
674+ // https://forums.x-plane.org/index.php?/forums/topic/38688-how-do-i-use-xplmprobeterrainxyz/&page=2
675+
676+ // transform probe location to local coordinates
677+ // Step 1. Convert initial lat/lon/alt to XYZ
678+ XPLMWorldToLocal (pos[0 ], pos[1 ], pos[2 ], &X, &Y, &Z);
679+
675680 // query probe
681+ // Step 2. Probe XYZ to get a new Y
676682 int rc = XPLMProbeTerrainXYZ (Terrain_probe, X, Y, Z, &probe_data);
677-
683+ if (rc > 0 )
684+ {
685+ Log::FormatLine (LOG_ERROR, " TERR" , " Probe failed. Return Value %u" , rc);
686+ XPLMDestroyProbe (Terrain_probe);
687+ return ;
688+ }
689+
678690 // transform probe location to world coordinates
679- double lat;
680- double lon;
681- double alt;
682-
691+ // Step 3. Convert that new XYZ back to LLE
692+ XPLMLocalToWorld (probe_data.locationX , probe_data.locationY , probe_data.locationZ , &lat, &lon, &alt);
693+ Log::FormatLine (LOG_TRACE, " TERR" , " Conv LLA=%f, %f, %f" , lat, lon, alt);
694+
695+ // transform probe location to local coordinates
696+ // Step 4. NOW convert your origina lat/lon with the elevation from step 3 to XYZ
697+ XPLMWorldToLocal (pos[0 ], pos[1 ], alt, &X, &Y, &Z);
698+
699+ // query probe
700+ // Step 5. Re-probe with the NEW XYZ
701+ rc = XPLMProbeTerrainXYZ (Terrain_probe, X, Y, Z, &probe_data);
683702 if (rc == 0 )
684703 {
704+ // transform probe location to world coordinates
705+ // Step 6. You now have a new Y, and your XYZ will be closer to correct for high elevations far from the origin.
685706 XPLMLocalToWorld (probe_data.locationX , probe_data.locationY , probe_data.locationZ , &lat, &lon, &alt);
686-
687- Log::FormatLine (LOG_TRACE, " GETT" , " Probe LLA %lf %lf %lf" , lat, lon, alt);
707+ Log::FormatLine (LOG_TRACE, " TERR" , " Probe LLA %lf %lf %lf" , lat, lon, alt);
688708 }
689709 else
690710 {
691711 lat = -998 ;
692712 lon = -998 ;
693713 alt = -998 ;
694-
695- Log::FormatLine (LOG_TRACE, " GETT" , " Probe failed. Return Value %u" , rc);
714+ Log::FormatLine (LOG_TRACE, " TERR" , " Probe failed. Return Value %u" , rc);
696715 }
697716
698717 // keep probe for next query
699- // XPLMDestroyProbe(probe );
718+ // XPLMDestroyProbe(Terrain_probe );
700719
701720 // Assemble response message
702- unsigned char response[50 ] = " TERR" ;
721+ unsigned char response[62 ] = " TERR" ;
703722 response[5 ] = aircraft;
704723 // terrain height over msl at lat/lon point
705724 memcpy (response + 6 , &lat, 8 );
706725 memcpy (response + 14 , &lon, 8 );
707726 memcpy (response + 22 , &alt, 8 );
708- // terrain incidence
727+ // terrain normal vector
709728 memcpy (response + 30 , &probe_data.normalX , 4 );
710729 memcpy (response + 34 , &probe_data.normalY , 4 );
711730 memcpy (response + 38 , &probe_data.normalZ , 4 );
731+ // terrain velocity
732+ memcpy (response + 42 , &probe_data.velocityX , 4 );
733+ memcpy (response + 46 , &probe_data.velocityY , 4 );
734+ memcpy (response + 50 , &probe_data.velocityZ , 4 );
712735 // terrain type
713- memcpy (response + 42 , &probe_data.is_wet , 4 );
736+ memcpy (response + 54 , &probe_data.is_wet , 4 );
714737 // probe status
715- memcpy (response + 46 , &rc, 4 );
716-
717- sock->SendTo (response, 50 , &connection.addr );
718- }
738+ memcpy (response + 58 , &rc, 4 );
719739
740+ sock->SendTo (response, 62 , &connection.addr );
741+ }
720742
721743 void MessageHandlers::HandleSimu (const Message& msg)
722744 {
0 commit comments