Working on modeling more realistic VOR and ILS ranges.
This commit is contained in:
parent
6e0a10b757
commit
61c8cefcf2
7 changed files with 162 additions and 106 deletions
|
@ -63,65 +63,6 @@ static double kludgeRange ( double stationElev, double aircraftElev,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// model standard VOR/DME/TACAN service volumes as per AIM 1-1-8
|
|
||||||
static double adjustNavRange( double stationElev, double aircraftElev,
|
|
||||||
double nominalRange )
|
|
||||||
{
|
|
||||||
// assumptions we model the standard service volume, plus
|
|
||||||
// ... rather than specifying a cylinder, we model a cone that
|
|
||||||
// contains the cylinder. Then we put an upside down cone on top
|
|
||||||
// to model diminishing returns at too-high altitudes.
|
|
||||||
|
|
||||||
// altitude difference
|
|
||||||
double alt = ( aircraftElev - stationElev ) * METER_TO_FEET;
|
|
||||||
|
|
||||||
if ( nominalRange < 25.0 + FG_EPSILON ) {
|
|
||||||
// Standard Terminal Service Volume
|
|
||||||
if ( alt <= 1000.0 ) {
|
|
||||||
return nominalRange;
|
|
||||||
} else if ( alt <= 12000.0 ) {
|
|
||||||
return nominalRange + nominalRange * ( alt - 1000.0 ) / 11000.0;
|
|
||||||
} else if ( alt <= 18000.0 ) {
|
|
||||||
return nominalRange * 2 * ( 1 - ( alt - 12000.0 ) / 6000.0 );
|
|
||||||
} else {
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
} else if ( nominalRange < 50.0 + FG_EPSILON ) {
|
|
||||||
// Standard Low Altitude Service Volume
|
|
||||||
if ( alt <= 1000.0 ) {
|
|
||||||
return nominalRange;
|
|
||||||
} else if ( alt <= 18000.0 ) {
|
|
||||||
return nominalRange + nominalRange * ( alt - 1000.0 ) / 17000.0;
|
|
||||||
} else if ( alt <= 18000.0 ) {
|
|
||||||
return nominalRange * 2 * ( 1 - ( alt - 18000.0 ) / 9000.0 );
|
|
||||||
} else {
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Standard High Altitude Service Volume
|
|
||||||
double lc = nominalRange * 0.31;
|
|
||||||
double mc = nominalRange * 0.77;
|
|
||||||
double hc = nominalRange;
|
|
||||||
|
|
||||||
if ( alt <= 1000.0 ) {
|
|
||||||
return lc;
|
|
||||||
} else if ( alt <= 14500.0 ) {
|
|
||||||
return lc + (mc-lc) * ( alt - 1000.0 ) / 13500.0;
|
|
||||||
} else if ( alt <= 18000.0 ) {
|
|
||||||
return mc + (hc-mc) * ( alt - 14500.0 ) / 3500.0;
|
|
||||||
} else if ( alt <= 45000.0 ) {
|
|
||||||
return hc + hc * ( 1 - fabs(alt - 31500.0) / 13500.0 );
|
|
||||||
} else if ( alt <= 60000.0 ) {
|
|
||||||
return mc + (hc-mc) * (60000.0 - alt) / 15000.0;
|
|
||||||
} else if ( alt <= 75000.0 ) {
|
|
||||||
return mc * ( 75000.0 - alt ) / 15000.0;
|
|
||||||
} else {
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// periodic radio station search wrapper
|
// periodic radio station search wrapper
|
||||||
static void fgRadioSearch( void ) {
|
static void fgRadioSearch( void ) {
|
||||||
current_radiostack->search();
|
current_radiostack->search();
|
||||||
|
@ -155,6 +96,18 @@ FGRadioStack::init ()
|
||||||
search();
|
search();
|
||||||
update();
|
update();
|
||||||
|
|
||||||
|
FGPath path( globals->get_fg_root() );
|
||||||
|
FGPath term = path;
|
||||||
|
term.append( "Navaids/range.term" );
|
||||||
|
FGPath low = path;
|
||||||
|
low.append( "Navaids/range.low" );
|
||||||
|
FGPath high = path;
|
||||||
|
high.append( "Navaids/range.high" );
|
||||||
|
|
||||||
|
term_tbl = new SGInterpTable( term.str() );
|
||||||
|
low_tbl = new SGInterpTable( low.str() );
|
||||||
|
high_tbl = new SGInterpTable( high.str() );
|
||||||
|
|
||||||
// Search radio database once per second
|
// Search radio database once per second
|
||||||
global_events.Register( "fgRadioSearch()", fgRadioSearch,
|
global_events.Register( "fgRadioSearch()", fgRadioSearch,
|
||||||
fgEVENT::FG_EVENT_READY, 1000);
|
fgEVENT::FG_EVENT_READY, 1000);
|
||||||
|
@ -264,6 +217,58 @@ FGRadioStack::unbind ()
|
||||||
fgUntie("/radios/adf/rotation");
|
fgUntie("/radios/adf/rotation");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// model standard VOR/DME/TACAN service volumes as per AIM 1-1-8
|
||||||
|
double FGRadioStack::adjustNavRange( double stationElev, double aircraftElev,
|
||||||
|
double nominalRange )
|
||||||
|
{
|
||||||
|
// assumptions we model the standard service volume, plus
|
||||||
|
// ... rather than specifying a cylinder, we model a cone that
|
||||||
|
// contains the cylinder. Then we put an upside down cone on top
|
||||||
|
// to model diminishing returns at too-high altitudes.
|
||||||
|
|
||||||
|
// altitude difference
|
||||||
|
double alt = ( aircraftElev * METER_TO_FEET - stationElev );
|
||||||
|
// cout << "aircraft elev = " << aircraftElev * METER_TO_FEET
|
||||||
|
// << " station elev = " << stationElev << endl;
|
||||||
|
|
||||||
|
if ( nominalRange < 25.0 + FG_EPSILON ) {
|
||||||
|
// Standard Terminal Service Volume
|
||||||
|
return term_tbl->interpolate( alt );
|
||||||
|
} else if ( nominalRange < 50.0 + FG_EPSILON ) {
|
||||||
|
// Standard Low Altitude Service Volume
|
||||||
|
// table is based on range of 40, scale to actual range
|
||||||
|
return low_tbl->interpolate( alt ) * nominalRange / 40.0;
|
||||||
|
} else {
|
||||||
|
// Standard High Altitude Service Volume
|
||||||
|
// table is based on range of 130, scale to actual range
|
||||||
|
return high_tbl->interpolate( alt ) * nominalRange / 130.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// model standard ILS service volumes as per AIM 1-1-9
|
||||||
|
double FGRadioStack::adjustILSRange( double stationElev, double aircraftElev,
|
||||||
|
double offsetDegrees, double distance )
|
||||||
|
{
|
||||||
|
// assumptions we model the standard service volume, plus
|
||||||
|
|
||||||
|
// altitude difference
|
||||||
|
// double alt = ( aircraftElev * METER_TO_FEET - stationElev );
|
||||||
|
double offset = fabs( offsetDegrees );
|
||||||
|
|
||||||
|
if ( offset < 10 ) {
|
||||||
|
return FG_ILS_DEFAULT_RANGE;
|
||||||
|
} else if ( offset < 35 ) {
|
||||||
|
return 10 + (35 - offset) * (FG_ILS_DEFAULT_RANGE - 10) / 25;
|
||||||
|
} else if ( offset < 45 ) {
|
||||||
|
return (45 - offset);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Update the various nav values based on position and valid tuned in navs
|
// Update the various nav values based on position and valid tuned in navs
|
||||||
void
|
void
|
||||||
FGRadioStack::update()
|
FGRadioStack::update()
|
||||||
|
@ -297,26 +302,39 @@ FGRadioStack::update()
|
||||||
nav1_gs_dist = 0.0;
|
nav1_gs_dist = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
nav1_effective_range = kludgeRange(nav1_elev, elev, nav1_range);
|
// wgs84 heading
|
||||||
|
geo_inverse_wgs_84( elev, lat * RAD_TO_DEG, lon * RAD_TO_DEG,
|
||||||
|
nav1_loclat, nav1_loclon,
|
||||||
|
&az1, &az2, &s );
|
||||||
|
// cout << "az1 = " << az1 << " magvar = " << nav1_magvar << endl;
|
||||||
|
nav1_heading = az1 - nav1_magvar;
|
||||||
|
// cout << " heading = " << nav1_heading
|
||||||
|
// << " dist = " << nav1_dist << endl;
|
||||||
|
|
||||||
|
if ( nav1_loc ) {
|
||||||
|
double offset = nav1_heading - nav1_radial;
|
||||||
|
while ( offset < -180.0 ) { offset += 360.0; }
|
||||||
|
while ( offset > 180.0 ) { offset -= 360.0; }
|
||||||
|
cout << "ils offset = " << offset << endl;
|
||||||
|
nav1_effective_range = adjustILSRange(nav1_elev, elev, offset,
|
||||||
|
nav1_loc_dist * METER_TO_NM );
|
||||||
|
} else {
|
||||||
|
nav1_effective_range = adjustNavRange(nav1_elev, elev, nav1_range);
|
||||||
|
}
|
||||||
|
cout << "nav1 range = " << nav1_effective_range
|
||||||
|
<< " (" << nav1_range << ")" << endl;
|
||||||
|
|
||||||
if ( nav1_loc_dist < nav1_effective_range * NM_TO_METER ) {
|
if ( nav1_loc_dist < nav1_effective_range * NM_TO_METER ) {
|
||||||
nav1_inrange = true;
|
nav1_inrange = true;
|
||||||
|
} else if ( nav1_loc_dist < 2 * nav1_effective_range * NM_TO_METER ) {
|
||||||
// wgs84 heading
|
nav1_inrange = sg_random() <
|
||||||
geo_inverse_wgs_84( elev, lat * RAD_TO_DEG, lon * RAD_TO_DEG,
|
( 2 * nav1_effective_range * NM_TO_METER - nav1_loc_dist ) /
|
||||||
nav1_loclat, nav1_loclon,
|
(nav1_effective_range * NM_TO_METER);
|
||||||
&az1, &az2, &s );
|
|
||||||
// cout << "az1 = " << az1 << " magvar = " << nav1_magvar << endl;
|
|
||||||
nav1_heading = az1 - nav1_magvar;
|
|
||||||
// Alex: nav1_heading = - (az1 - FGBFI::getMagVar() / RAD_TO_DEG);
|
|
||||||
|
|
||||||
// cout << " heading = " << nav1_heading
|
|
||||||
// << " dist = " << nav1_dist << endl;
|
|
||||||
} else {
|
} else {
|
||||||
nav1_inrange = false;
|
nav1_inrange = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( nav1_loc ) {
|
if ( !nav1_loc ) {
|
||||||
} else {
|
|
||||||
nav1_radial = nav1_sel_radial;
|
nav1_radial = nav1_sel_radial;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -373,19 +391,33 @@ FGRadioStack::update()
|
||||||
nav2_gs_dist = 0.0;
|
nav2_gs_dist = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
nav2_effective_range = kludgeRange(nav2_elev, elev, nav2_range);
|
// wgs84 heading
|
||||||
|
geo_inverse_wgs_84( elev, lat * RAD_TO_DEG, lon * RAD_TO_DEG,
|
||||||
|
nav2_loclat, nav2_loclon,
|
||||||
|
&az1, &az2, &s );
|
||||||
|
nav2_heading = az1 - nav2_magvar;
|
||||||
|
// cout << " heading = " << nav2_heading
|
||||||
|
// << " dist = " << nav2_dist << endl;
|
||||||
|
|
||||||
|
if ( nav2_loc ) {
|
||||||
|
double offset = nav2_heading - nav2_radial;
|
||||||
|
while ( offset < -180.0 ) { offset += 360.0; }
|
||||||
|
while ( offset > 180.0 ) { offset -= 360.0; }
|
||||||
|
cout << "ils offset = " << offset << endl;
|
||||||
|
nav2_effective_range = adjustILSRange(nav2_elev, elev, offset,
|
||||||
|
nav2_loc_dist * METER_TO_NM );
|
||||||
|
} else {
|
||||||
|
nav2_effective_range = adjustNavRange(nav2_elev, elev, nav2_range);
|
||||||
|
}
|
||||||
|
cout << "nav2 range = " << nav2_effective_range
|
||||||
|
<< " (" << nav2_range << ")" << endl;
|
||||||
|
|
||||||
if ( nav2_loc_dist < nav2_effective_range * NM_TO_METER ) {
|
if ( nav2_loc_dist < nav2_effective_range * NM_TO_METER ) {
|
||||||
nav2_inrange = true;
|
nav2_inrange = true;
|
||||||
|
} else if ( nav2_loc_dist < 2 * nav2_effective_range * NM_TO_METER ) {
|
||||||
// wgs84 heading
|
nav2_inrange = sg_random() <
|
||||||
geo_inverse_wgs_84( elev, lat * RAD_TO_DEG, lon * RAD_TO_DEG,
|
( 2 * nav2_effective_range * NM_TO_METER - nav2_loc_dist ) /
|
||||||
nav2_loclat, nav2_loclon,
|
(nav2_effective_range * NM_TO_METER);
|
||||||
&az1, &az2, &s );
|
|
||||||
nav2_heading = az1 - nav2_magvar;
|
|
||||||
// Alex: nav2_heading = - (az1 - FGBFI::getMagVar() / RAD_TO_DEG);
|
|
||||||
|
|
||||||
// cout << " heading = " << nav2_heading
|
|
||||||
// << " dist = " << nav2_dist << endl;
|
|
||||||
} else {
|
} else {
|
||||||
nav2_inrange = false;
|
nav2_inrange = false;
|
||||||
}
|
}
|
||||||
|
@ -395,6 +427,7 @@ FGRadioStack::update()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
nav2_inrange = false;
|
nav2_inrange = false;
|
||||||
|
nav2_dme_dist = 0.0;
|
||||||
// cout << "not picking up vor. :-(" << endl;
|
// cout << "not picking up vor. :-(" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -404,18 +437,21 @@ FGRadioStack::update()
|
||||||
station = Point3D( adf_x, adf_y, adf_z );
|
station = Point3D( adf_x, adf_y, adf_z );
|
||||||
adf_dist = aircraft.distance3D( station );
|
adf_dist = aircraft.distance3D( station );
|
||||||
|
|
||||||
|
// wgs84 heading
|
||||||
|
geo_inverse_wgs_84( elev, lat * RAD_TO_DEG, lon * RAD_TO_DEG,
|
||||||
|
adf_lat, adf_lon,
|
||||||
|
&az1, &az2, &s );
|
||||||
|
adf_heading = az1;
|
||||||
|
// cout << " heading = " << nav2_heading
|
||||||
|
// << " dist = " << nav2_dist << endl;
|
||||||
|
|
||||||
adf_effective_range = kludgeRange(adf_elev, elev, adf_range);
|
adf_effective_range = kludgeRange(adf_elev, elev, adf_range);
|
||||||
if ( adf_dist < adf_effective_range * NM_TO_METER ) {
|
if ( adf_dist < adf_effective_range * NM_TO_METER ) {
|
||||||
adf_inrange = true;
|
adf_inrange = true;
|
||||||
|
} else if ( adf_dist < 2 * adf_effective_range * NM_TO_METER ) {
|
||||||
// wgs84 heading
|
adf_inrange = sg_random() <
|
||||||
geo_inverse_wgs_84( elev, lat * RAD_TO_DEG, lon * RAD_TO_DEG,
|
( 2 * adf_effective_range * NM_TO_METER - adf_dist ) /
|
||||||
adf_lat, adf_lon,
|
(adf_effective_range * NM_TO_METER);
|
||||||
&az1, &az2, &s );
|
|
||||||
adf_heading = az1;
|
|
||||||
|
|
||||||
// cout << " heading = " << nav2_heading
|
|
||||||
// << " dist = " << nav2_dist << endl;
|
|
||||||
} else {
|
} else {
|
||||||
adf_inrange = false;
|
adf_inrange = false;
|
||||||
}
|
}
|
||||||
|
@ -516,7 +552,7 @@ void FGRadioStack::search()
|
||||||
nav1_elev = nav.get_elev();
|
nav1_elev = nav.get_elev();
|
||||||
nav1_magvar = nav.get_magvar();
|
nav1_magvar = nav.get_magvar();
|
||||||
nav1_range = nav.get_range();
|
nav1_range = nav.get_range();
|
||||||
nav1_effective_range = kludgeRange(nav1_elev, elev, nav1_range);
|
nav1_effective_range = adjustNavRange(nav1_elev, elev, nav1_range);
|
||||||
nav1_target_gs = 0.0;
|
nav1_target_gs = 0.0;
|
||||||
nav1_radial = nav1_sel_radial;
|
nav1_radial = nav1_sel_radial;
|
||||||
nav1_x = nav1_dme_x = nav.get_x();
|
nav1_x = nav1_dme_x = nav.get_x();
|
||||||
|
@ -607,7 +643,7 @@ void FGRadioStack::search()
|
||||||
nav2_elev = nav.get_elev();
|
nav2_elev = nav.get_elev();
|
||||||
nav2_magvar = nav.get_magvar();
|
nav2_magvar = nav.get_magvar();
|
||||||
nav2_range = nav.get_range();
|
nav2_range = nav.get_range();
|
||||||
nav2_effective_range = kludgeRange(nav2_elev, elev, nav2_range);
|
nav2_effective_range = adjustNavRange(nav2_elev, elev, nav2_range);
|
||||||
nav2_target_gs = 0.0;
|
nav2_target_gs = 0.0;
|
||||||
nav2_radial = nav2_sel_radial;
|
nav2_radial = nav2_sel_radial;
|
||||||
nav2_x = nav2_dme_x = nav.get_x();
|
nav2_x = nav2_dme_x = nav.get_x();
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
|
|
||||||
#include <simgear/compiler.h>
|
#include <simgear/compiler.h>
|
||||||
|
|
||||||
|
#include <simgear/math/interpolater.hxx>
|
||||||
|
|
||||||
#include <Navaids/ilslist.hxx>
|
#include <Navaids/ilslist.hxx>
|
||||||
#include <Navaids/navlist.hxx>
|
#include <Navaids/navlist.hxx>
|
||||||
#include <Sound/morse.hxx>
|
#include <Sound/morse.hxx>
|
||||||
|
@ -39,6 +41,10 @@ class FGRadioStack : public FGSubsystem
|
||||||
{
|
{
|
||||||
FGMorse morse;
|
FGMorse morse;
|
||||||
|
|
||||||
|
SGInterpTable *term_tbl;
|
||||||
|
SGInterpTable *low_tbl;
|
||||||
|
SGInterpTable *high_tbl;
|
||||||
|
|
||||||
SGValue * latitudeVal;
|
SGValue * latitudeVal;
|
||||||
SGValue * longitudeVal;
|
SGValue * longitudeVal;
|
||||||
SGValue * altitudeVal;
|
SGValue * altitudeVal;
|
||||||
|
@ -137,6 +143,14 @@ class FGRadioStack : public FGSubsystem
|
||||||
double adf_y;
|
double adf_y;
|
||||||
double adf_z;
|
double adf_z;
|
||||||
|
|
||||||
|
// model standard VOR/DME/TACAN service volumes as per AIM 1-1-8
|
||||||
|
double adjustNavRange( double stationElev, double aircraftElev,
|
||||||
|
double nominalRange );
|
||||||
|
|
||||||
|
// model standard ILS service volumes as per AIM 1-1-9
|
||||||
|
double adjustILSRange( double stationElev, double aircraftElev,
|
||||||
|
double offsetDegrees, double distance );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
FGRadioStack();
|
FGRadioStack();
|
||||||
|
|
|
@ -44,7 +44,7 @@ FG_USING_STD(istream);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define FG_ILS_DEFAULT_RANGE 30
|
#define FG_ILS_DEFAULT_RANGE 18
|
||||||
|
|
||||||
class FGILS {
|
class FGILS {
|
||||||
|
|
||||||
|
|
|
@ -135,8 +135,11 @@ bool FGILSList::query( double lon, double lat, double elev, double freq,
|
||||||
// << ")" << endl;
|
// << ")" << endl;
|
||||||
|
|
||||||
// cout << " dist = " << s << endl;
|
// cout << " dist = " << s << endl;
|
||||||
if ( d < (FG_ILS_DEFAULT_RANGE * NM_TO_METER
|
|
||||||
* FG_ILS_DEFAULT_RANGE * NM_TO_METER) ) {
|
// match up to twice the published range so we can model
|
||||||
|
// reduced signal strength
|
||||||
|
if ( d < (2* FG_ILS_DEFAULT_RANGE * NM_TO_METER
|
||||||
|
* 2 * FG_ILS_DEFAULT_RANGE * NM_TO_METER) ) {
|
||||||
*ils = *current;
|
*ils = *current;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,8 +130,11 @@ bool FGNavList::query( double lon, double lat, double elev, double freq,
|
||||||
|
|
||||||
// cout << " dist = " << sqrt(d)
|
// cout << " dist = " << sqrt(d)
|
||||||
// << " range = " << current->get_range() * NM_TO_METER << endl;
|
// << " range = " << current->get_range() * NM_TO_METER << endl;
|
||||||
if ( d < (current->get_range() * NM_TO_METER
|
|
||||||
* current->get_range() * NM_TO_METER * 5.0) ) {
|
// match up to twice the published range so we can model
|
||||||
|
// reduced signal strength
|
||||||
|
if ( d < (2 * current->get_range() * NM_TO_METER
|
||||||
|
* 2 * current->get_range() * NM_TO_METER ) ) {
|
||||||
// cout << "matched = " << current->get_ident() << endl;
|
// cout << "matched = " << current->get_ident() << endl;
|
||||||
*n = *current;
|
*n = *current;
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -84,13 +84,13 @@ void fgLIGHT::Init( void ) {
|
||||||
sky.append( "Lighting/sky" );
|
sky.append( "Lighting/sky" );
|
||||||
|
|
||||||
// initialize ambient table
|
// initialize ambient table
|
||||||
ambient_tbl = new fgINTERPTABLE( ambient.str() );
|
ambient_tbl = new SGInterpTable( ambient.str() );
|
||||||
|
|
||||||
// initialize diffuse table
|
// initialize diffuse table
|
||||||
diffuse_tbl = new fgINTERPTABLE( diffuse.str() );
|
diffuse_tbl = new SGInterpTable( diffuse.str() );
|
||||||
|
|
||||||
// initialize sky table
|
// initialize sky table
|
||||||
sky_tbl = new fgINTERPTABLE( sky.str() );
|
sky_tbl = new SGInterpTable( sky.str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -51,9 +51,9 @@
|
||||||
class fgLIGHT {
|
class fgLIGHT {
|
||||||
|
|
||||||
// Lighting look up tables (based on sun angle with local horizon)
|
// Lighting look up tables (based on sun angle with local horizon)
|
||||||
fgINTERPTABLE *ambient_tbl;
|
SGInterpTable *ambient_tbl;
|
||||||
fgINTERPTABLE *diffuse_tbl;
|
SGInterpTable *diffuse_tbl;
|
||||||
fgINTERPTABLE *sky_tbl;
|
SGInterpTable *sky_tbl;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue