1
0
Fork 0

Finish what was committed in a broken state yesterday.

Split up main.cxx into a program manegement part (which remains in
main.cxx) and a render part (the new renderer.?xx files). Also turn
the renderer into a small class of it's own. At this time not really
exctining because most of the stuff is still global, but it allows us
to slowly migrate some of the global definitions into the new class.

The FGRenderer class is now managed by globals, so to get the renderer
just call gloabals->get_renderer()

At some pijt it might be a good idea to also turn the remaining code in
main into a class of it's own. With a bit of luck we end up with a more
robust, and better maintainable code.
This commit is contained in:
ehofman 2004-09-20 13:21:51 +00:00
parent 3b3600fd21
commit 986492d72d
15 changed files with 76 additions and 934 deletions

View file

@ -102,7 +102,6 @@ extern void fgLatLonFormatToggle( puObject *);
#if defined( TR_HIRES_SNAP)
#include <simgear/screen/tr.h>
extern void trRenderFrame( void );
extern void fgUpdateHUD( GLfloat x_start, GLfloat y_start,
GLfloat x_end, GLfloat y_end );
#endif
@ -376,8 +375,8 @@ void guiTogglePanel(puObject *cb)
else
fgSetBool("/sim/panel/visibility", true);
fgReshape(fgGetInt("/sim/startup/xsize"),
fgGetInt("/sim/startup/ysize"));
globals->get_renderer()->resize(fgGetInt("/sim/startup/xsize"),
fgGetInt("/sim/startup/ysize"));
}
void goodBye(puObject *)
@ -534,15 +533,16 @@ void fgHiResDump()
puHideCursor();
}
fgInitVisuals();
fgReshape( fgGetInt("/sim/startup/xsize"),
fgGetInt("/sim/startup/ysize") );
FGRenderer *renderer = globals->get_renderer();
renderer->init();
renderer->resize( fgGetInt("/sim/startup/xsize"),
fgGetInt("/sim/startup/ysize") );
// we need two render frames here to clear the menu and cursor
// ... not sure why but doing an extra fgRenderFrame() shouldn't
// hurt anything
fgRenderFrame();
fgRenderFrame();
renderer->update();
renderer->update();
// Make sure we have SSG projection primed for current view
glMatrixMode(GL_MODELVIEW);
@ -633,7 +633,7 @@ void fgHiResDump()
trBeginTile(tr);
int curColumn = trGet(tr, TR_CURRENT_COLUMN);
int curRow = trGet(tr, TR_CURRENT_ROW);
trRenderFrame();
globals->get_renderer()->screendump();
if ( do_hud )
fgUpdateHUD( curColumn*hud_col_step, curRow*hud_row_step,
(curColumn+1)*hud_col_step, (curRow+1)*hud_row_step );
@ -670,7 +670,7 @@ void fgHiResDump()
}
fgReshape( width, height );
globals->get_renderer()->resize( width, height );
trDelete(tr);
@ -714,7 +714,7 @@ GLubyte *hiResScreenCapture( int multiplier )
float fov = oldfov / multiplier;
FGViewer *v = globals->get_current_view();
fgSetDouble("/sim/current-view/field-of-view", fov);
fgInitVisuals();
globals->get_renderer()->init();
int cur_width = fgGetInt("/sim/startup/xsize");
int cur_height = fgGetInt("/sim/startup/ysize");
if (b1) delete( b1 );
@ -723,10 +723,10 @@ GLubyte *hiResScreenCapture( int multiplier )
int x,y;
for ( y = 0; y < multiplier; y++ ) {
for ( x = 0; x < multiplier; x++ ) {
fgReshape( cur_width, cur_height );
globals->get_renderer()->resize( cur_width, cur_height );
// pan to tile
rotateView( 0, (y*fov)-((multiplier-1)*fov/2), (x*fov)-((multiplier-1)*fov/2) );
fgRenderFrame();
globals->get_renderer()->update();
// restore view
GlBitmap b2;
b1->copyBitmap( &b2, cur_width*x, cur_height*y );
@ -794,15 +794,15 @@ void fgDumpSnapShot () {
puHideCursor();
}
fgInitVisuals();
fgReshape( fgGetInt("/sim/startup/xsize"),
fgGetInt("/sim/startup/ysize") );
globals->get_renderer()->init();
globals->get_renderer()->resize( fgGetInt("/sim/startup/xsize"),
fgGetInt("/sim/startup/ysize") );
// we need two render frames here to clear the menu and cursor
// ... not sure why but doing an extra fgRenderFrame() shouldn't
// hurt anything
fgRenderFrame();
fgRenderFrame();
globals->get_renderer()->update();
globals->get_renderer()->update();
while (count < 1000) {
FILE *fp;

View file

@ -81,7 +81,7 @@ void reInit(puObject *cb)
globals->get_tile_mgr()->update( fgGetDouble("/environment/visibility-m") );
fgReshape( xsize, ysize );
globals->get_renderer()->resize( xsize, ysize );
// BusyCursor(1);

View file

@ -37,6 +37,7 @@ noinst_LIBRARIES = libMain.a
libMain_a_SOURCES = \
main.cxx main.hxx \
renderer.cxx renderer.hxx \
fg_commands.cxx fg_commands.hxx \
fg_init.cxx fg_init.hxx \
fg_io.cxx fg_io.hxx \

View file

@ -42,6 +42,7 @@ FGGlobals *globals;
// Constructor
FGGlobals::FGGlobals() :
renderer( new FGRenderer ),
subsystem_mgr( new SGSubsystemMgr ),
event_mgr( new SGEventMgr ),
sim_time_sec( 0.0 ),
@ -95,6 +96,7 @@ FGGlobals::~FGGlobals()
delete props;
delete commands;
delete io;
delete renderer;
// make sure only to delete the initial waypoints list if it acually
// still exists.
@ -157,6 +159,12 @@ void FGGlobals::set_fg_scenery (const string &scenery) {
}
FGRenderer *
FGGlobals::get_renderer () const
{
return renderer;
}
SGSubsystemMgr *
FGGlobals::get_subsystem_mgr () const
{

View file

@ -42,6 +42,8 @@ SG_USING_STD( string );
typedef vector<string> string_list;
#include "renderer.hxx"
// Forward declarations
// This file is included, directly or indirectly, almost everywhere in
@ -97,6 +99,7 @@ class FGGlobals
private:
FGRenderer *renderer;
SGSubsystemMgr *subsystem_mgr;
SGEventMgr *event_mgr;
@ -217,6 +220,8 @@ public:
FGGlobals();
virtual ~FGGlobals();
virtual FGRenderer *get_renderer () const;
virtual SGSubsystemMgr *get_subsystem_mgr () const;
virtual SGSubsystem *get_subsystem (const char * name);

View file

@ -41,31 +41,23 @@
# include <float.h>
#endif
#include <plib/ssg.h>
#include <plib/netSocket.h>
#include <simgear/screen/extensions.hxx>
#include <simgear/scene/material/matlib.hxx>
#include <simgear/props/props.hxx>
#include <simgear/scene/sky/sky.hxx>
#include <simgear/timing/sg_time.hxx>
#include <simgear/scene/model/animation.hxx>
#include <simgear/ephemeris/ephemeris.hxx>
#include <simgear/scene/model/placement.hxx>
#include <simgear/math/sg_random.h>
#include <simgear/scene/model/modellib.hxx>
#ifdef FG_USE_CLOUDS_3D
# include <simgear/scene/sky/clouds3d/SkySceneLoader.hpp>
# include <simgear/scene/sky/clouds3d/SkyUtil.hpp>
#endif
// Class refferences
#include <simgear/ephemeris/ephemeris.hxx>
#include <simgear/scene/model/modellib.hxx>
#include <simgear/scene/material/matlib.hxx>
#include <simgear/scene/model/animation.hxx>
#include <simgear/scene/sky/sky.hxx>
#include <Time/light.hxx>
#include <Include/general.hxx>
#include <Scenery/tileentry.hxx>
#include <Time/light.hxx>
#include <Time/light.hxx>
#include <Aircraft/aircraft.hxx>
#include <Cockpit/panel.hxx>
#include <Cockpit/cockpit.hxx>
#include <Cockpit/radiostack.hxx>
#include <Cockpit/hud.hxx>
@ -91,32 +83,18 @@
#include <MultiPlayer/multiplayrxmgr.hxx>
#endif
#include "splash.hxx"
#include "fg_commands.hxx"
#include "fg_io.hxx"
#include "renderer.hxx"
#include "splash.hxx"
#include "main.hxx"
float default_attenuation[3] = {1.0, 0.0, 0.0};
ssgSelector *ship_sel=NULL;
// upto 32 instances of a same object can be loaded.
ssgTransform *ship_pos[32];
double obj_lat[32],obj_lon[32],obj_alt[32],obj_pitch[32],obj_roll[32];
int objc=0;
ssgSelector *lightpoints_brightness = new ssgSelector;
ssgTransform *lightpoints_transform = new ssgTransform;
FGTileEntry *dummy_tile;
sgVec3 rway_ols;
// ADA
// Clip plane settings...
float scene_nearplane = 0.5f;
float scene_farplane = 120000.0f;
static double real_delta_time_sec = 0.0;
static double delta_time_sec = 0.0;
glPointParameterfProc glPointParameterfPtr = 0;
glPointParameterfvProc glPointParameterfvPtr = 0;
bool glPointParameterIsSupported = false;
double delta_time_sec = 0.0;
#ifdef macintosh
@ -129,40 +107,9 @@ FGGeneral general;
// Specify our current idle function state. This is used to run all
// our initializations out of the idle callback so that we can get a
// splash screen up and running right away.
static int idle_state = 0;
static long global_multi_loop;
int idle_state = 0;
long global_multi_loop;
// fog constants. I'm a little nervous about putting actual code out
// here but it seems to work (?)
static const double m_log01 = -log( 0.01 );
static const double sqrt_m_log01 = sqrt( m_log01 );
static GLfloat fog_exp_density;
static GLfloat fog_exp2_density;
static GLfloat rwy_exp2_punch_through;
static GLfloat taxi_exp2_punch_through;
static GLfloat ground_exp2_punch_through;
// Sky structures
SGSky *thesky;
#ifdef FG_USE_CLOUDS_3D
SkySceneLoader *sgClouds3d;
bool _bcloud_orig = true;
#endif
// hack
sgMat4 copy_of_ssgOpenGLAxisSwapMatrix =
{
{ 1.0f, 0.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, -1.0f, 0.0f },
{ 0.0f, 1.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f, 1.0f }
};
ssgSimpleState *cloud3d_imposter_state;
ssgSimpleState *default_state;
ssgSimpleState *hud_and_panel;
ssgSimpleState *menus;
SGTimeStamp last_time_stamp;
SGTimeStamp current_time_stamp;
@ -172,762 +119,6 @@ SGTimeStamp current_time_stamp;
extern int _bootstrap_OSInit;
void fgBuildRenderStates( void ) {
default_state = new ssgSimpleState;
default_state->ref();
default_state->disable( GL_TEXTURE_2D );
default_state->enable( GL_CULL_FACE );
default_state->enable( GL_COLOR_MATERIAL );
default_state->setColourMaterial( GL_AMBIENT_AND_DIFFUSE );
default_state->setMaterial( GL_EMISSION, 0, 0, 0, 1 );
default_state->setMaterial( GL_SPECULAR, 0, 0, 0, 1 );
default_state->disable( GL_BLEND );
default_state->disable( GL_ALPHA_TEST );
default_state->disable( GL_LIGHTING );
cloud3d_imposter_state = new ssgSimpleState;
cloud3d_imposter_state->ref();
cloud3d_imposter_state->enable( GL_TEXTURE_2D );
cloud3d_imposter_state->enable( GL_CULL_FACE );
cloud3d_imposter_state->enable( GL_COLOR_MATERIAL );
cloud3d_imposter_state->setColourMaterial( GL_AMBIENT_AND_DIFFUSE );
cloud3d_imposter_state->setMaterial( GL_DIFFUSE, 1, 1, 1, 1 );
cloud3d_imposter_state->setMaterial( GL_AMBIENT, 1, 1, 1, 1 );
cloud3d_imposter_state->setMaterial( GL_EMISSION, 0, 0, 0, 1 );
cloud3d_imposter_state->setMaterial( GL_SPECULAR, 0, 0, 0, 1 );
cloud3d_imposter_state->enable( GL_BLEND );
cloud3d_imposter_state->enable( GL_ALPHA_TEST );
cloud3d_imposter_state->disable( GL_LIGHTING );
hud_and_panel = new ssgSimpleState;
hud_and_panel->ref();
hud_and_panel->disable( GL_CULL_FACE );
hud_and_panel->disable( GL_TEXTURE_2D );
hud_and_panel->disable( GL_LIGHTING );
hud_and_panel->enable( GL_BLEND );
menus = new ssgSimpleState;
menus->ref();
menus->disable( GL_CULL_FACE );
menus->disable( GL_TEXTURE_2D );
menus->enable( GL_BLEND );
}
// fgInitVisuals() -- Initialize various GL/view parameters
void fgInitVisuals( void ) {
FGLight *l = (FGLight *)(globals->get_subsystem("lighting"));
// Go full screen if requested ...
if ( fgGetBool("/sim/startup/fullscreen") ) {
fgOSFullScreen();
}
// If enabled, normal vectors specified with glNormal are scaled
// to unit length after transformation. Enabling this has
// performance implications. See the docs for glNormal.
// glEnable( GL_NORMALIZE );
glEnable( GL_LIGHTING );
glEnable( GL_LIGHT0 );
// glLightfv( GL_LIGHT0, GL_POSITION, l->sun_vec ); // done later with ssg
sgVec3 sunpos;
sgSetVec3( sunpos, l->sun_vec()[0], l->sun_vec()[1], l->sun_vec()[2] );
ssgGetLight( 0 ) -> setPosition( sunpos );
glFogi (GL_FOG_MODE, GL_EXP2);
if ( (!strcmp(fgGetString("/sim/rendering/fog"), "disabled")) ||
(!fgGetBool("/sim/rendering/shading"))) {
// if fastest fog requested, or if flat shading force fastest
glHint ( GL_FOG_HINT, GL_FASTEST );
} else if ( !strcmp(fgGetString("/sim/rendering/fog"), "nicest") ) {
glHint ( GL_FOG_HINT, GL_NICEST );
}
if ( fgGetBool("/sim/rendering/wireframe") ) {
// draw wire frame
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
}
// This is the default anyways, but it can't hurt
glFrontFace ( GL_CCW );
// Just testing ...
// glEnable(GL_POINT_SMOOTH);
// glEnable(GL_LINE_SMOOTH);
// glEnable(GL_POLYGON_SMOOTH);
}
// For HiRes screen Dumps using Brian Pauls TR Library
void trRenderFrame( void ) {
#ifdef FG_ENABLE_MULTIPASS_CLOUDS
bool multi_pass_clouds = fgGetBool("/sim/rendering/multi-pass-clouds") &&
!SGCloudLayer::enable_bump_mapping; // ugly artefact now
#else
bool multi_pass_clouds = false;
#endif
bool draw_clouds = fgGetBool("/environment/clouds/status");
if ( fgPanelVisible() ) {
GLfloat height = fgGetInt("/sim/startup/ysize");
GLfloat view_h =
(globals->get_current_panel()->getViewHeight() - globals->get_current_panel()->getYOffset())
* (height / 768.0) + 1;
glTranslatef( 0.0, view_h, 0.0 );
}
static GLfloat black[4] = { 0.0, 0.0, 0.0, 1.0 };
static GLfloat white[4] = { 1.0, 1.0, 1.0, 1.0 };
FGLight *l = (FGLight *)(globals->get_subsystem("lighting"));
glClearColor(l->adj_fog_color()[0], l->adj_fog_color()[1],
l->adj_fog_color()[2], l->adj_fog_color()[3]);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
// set the opengl state to known default values
default_state->force();
glEnable( GL_FOG );
glFogf ( GL_FOG_DENSITY, fog_exp2_density);
glFogi ( GL_FOG_MODE, GL_EXP2 );
glFogfv ( GL_FOG_COLOR, l->adj_fog_color() );
// GL_LIGHT_MODEL_AMBIENT has a default non-zero value so if
// we only update GL_AMBIENT for our lights we will never get
// a completely dark scene. So, we set GL_LIGHT_MODEL_AMBIENT
// explicitely to black.
glLightModelfv( GL_LIGHT_MODEL_AMBIENT, black );
glLightModeli( GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE );
ssgGetLight( 0 ) -> setColour( GL_AMBIENT, l->scene_ambient() );
// texture parameters
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ) ;
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST ) ;
// we need a white diffuse light for the phase of the moon
ssgGetLight( 0 ) -> setColour( GL_DIFFUSE, white );
thesky->preDraw( cur_fdm_state->get_Altitude() * SG_FEET_TO_METER,
fog_exp2_density );
// draw the ssg scene
// return to the desired diffuse color
ssgGetLight( 0 ) -> setColour( GL_DIFFUSE, l->scene_diffuse() );
glEnable( GL_DEPTH_TEST );
ssgSetNearFar( scene_nearplane, scene_farplane );
if ( draw_clouds ) {
// Draw the terrain
FGTileMgr::set_tile_filter( true );
sgSetModelFilter( false );
globals->get_aircraft_model()->select( false );
ssgCullAndDraw( globals->get_scenery()->get_scene_graph() );
// Disable depth buffer update, draw the clouds
glDepthMask( GL_FALSE );
thesky->drawUpperClouds();
if ( multi_pass_clouds ) {
thesky->drawLowerClouds();
}
glDepthMask( GL_TRUE );
if ( multi_pass_clouds ) {
// Draw the objects except the aircraft
// and update the stencil buffer with 1
glEnable( GL_STENCIL_TEST );
glStencilFunc( GL_ALWAYS, 1, 1 );
glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );
}
FGTileMgr::set_tile_filter( false );
sgSetModelFilter( true );
ssgCullAndDraw( globals->get_scenery()->get_scene_graph() );
} else {
FGTileMgr::set_tile_filter( true );
sgSetModelFilter( true );
globals->get_aircraft_model()->select( false );
ssgCullAndDraw( globals->get_scenery()->get_scene_graph() );
}
// draw the lights
glFogf (GL_FOG_DENSITY, rwy_exp2_punch_through);
ssgSetNearFar( scene_nearplane, scene_farplane );
ssgCullAndDraw( globals->get_scenery()->get_vasi_lights_root() );
ssgCullAndDraw( globals->get_scenery()->get_rwy_lights_root() );
ssgCullAndDraw( globals->get_scenery()->get_gnd_lights_root() );
if ( draw_clouds ) {
if ( multi_pass_clouds ) {
// Disable depth buffer update, draw the clouds where the
// objects overwrite the already drawn clouds, by testing
// the stencil buffer against 1
glDepthMask( GL_FALSE );
glStencilFunc( GL_EQUAL, 1, 1 );
glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
thesky->drawUpperClouds();
thesky->drawLowerClouds();
glDepthMask( GL_TRUE );
glDisable( GL_STENCIL_TEST );
} else {
glDepthMask( GL_FALSE );
thesky->drawLowerClouds();
glDepthMask( GL_TRUE );
}
}
globals->get_aircraft_model()->select( true );
globals->get_model_mgr()->draw();
globals->get_aircraft_model()->draw();
}
// Update all Visuals (redraws anything graphics related)
void fgRenderFrame() {
bool scenery_loaded = fgGetBool("sim/sceneryloaded") || fgGetBool("sim/sceneryloaded-override");
bool draw_otw = fgGetBool("/sim/rendering/draw-otw");
bool skyblend = fgGetBool("/sim/rendering/skyblend");
bool enhanced_lighting = fgGetBool("/sim/rendering/enhanced-lighting");
bool distance_attenuation = fgGetBool("/sim/rendering/distance-attenuation");
#ifdef FG_ENABLE_MULTIPASS_CLOUDS
bool multi_pass_clouds = fgGetBool("/sim/rendering/multi-pass-clouds") &&
!SGCloudLayer::enable_bump_mapping; // ugly artefact now
#else
bool multi_pass_clouds = false;
#endif
bool draw_clouds = fgGetBool("/environment/clouds/status");
GLfloat black[4] = { 0.0, 0.0, 0.0, 1.0 };
GLfloat white[4] = { 1.0, 1.0, 1.0, 1.0 };
// static const SGPropertyNode *longitude
// = fgGetNode("/position/longitude-deg");
// static const SGPropertyNode *latitude
// = fgGetNode("/position/latitude-deg");
// static const SGPropertyNode *altitude
// = fgGetNode("/position/altitude-ft");
static const SGPropertyNode *groundlevel_nearplane
= fgGetNode("/sim/current-view/ground-level-nearplane-m");
FGLight *l = (FGLight *)(globals->get_subsystem("lighting"));
static double last_visibility = -9999;
// update fog params
double actual_visibility;
if (fgGetBool("/environment/clouds/status"))
actual_visibility = thesky->get_visibility();
else
actual_visibility = fgGetDouble("/environment/visibility-m");
if ( actual_visibility != last_visibility ) {
last_visibility = actual_visibility;
fog_exp_density = m_log01 / actual_visibility;
fog_exp2_density = sqrt_m_log01 / actual_visibility;
ground_exp2_punch_through = sqrt_m_log01 / (actual_visibility * 1.5);
if ( actual_visibility < 8000 ) {
rwy_exp2_punch_through = sqrt_m_log01 / (actual_visibility * 2.5);
taxi_exp2_punch_through = sqrt_m_log01 / (actual_visibility * 1.5);
} else {
rwy_exp2_punch_through = sqrt_m_log01 / ( 8000 * 2.5 );
taxi_exp2_punch_through = sqrt_m_log01 / ( 8000 * 1.5 );
}
}
// double angle;
// GLfloat black[4] = { 0.0, 0.0, 0.0, 1.0 };
// GLfloat white[4] = { 1.0, 1.0, 1.0, 1.0 };
// GLfloat terrain_color[4] = { 0.54, 0.44, 0.29, 1.0 };
// GLfloat mat_shininess[] = { 10.0 };
GLbitfield clear_mask;
if ( idle_state != 1000 || !scenery_loaded ) {
// still initializing, draw the splash screen
if ( fgGetBool("/sim/startup/splash-screen") ) {
fgSplashUpdate(0.0, 1.0);
}
// Keep resetting sim time while the sim is initializing
globals->set_sim_time_sec( 0.0 );
SGAnimation::set_sim_time_sec( 0.0 );
} else {
// idle_state is now 1000 meaning we've finished all our
// initializations and are running the main loop, so this will
// now work without seg faulting the system.
FGViewer *current__view = globals->get_current_view();
// calculate our current position in cartesian space
globals->get_scenery()->set_center( globals->get_scenery()->get_next_center() );
// update view port
fgReshape( fgGetInt("/sim/startup/xsize"),
fgGetInt("/sim/startup/ysize") );
if ( fgGetBool("/sim/rendering/clouds3d") ) {
glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );
cloud3d_imposter_state->force();
glDisable( GL_FOG );
glColor4f( 1.0, 1.0, 1.0, 1.0 );
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA ) ;
#ifdef FG_USE_CLOUDS_3D
if ( _bcloud_orig ) {
Point3D c = globals->get_scenery()->get_center();
sgClouds3d->Set_Cloud_Orig( &c );
_bcloud_orig = false;
}
sgClouds3d->Update( current__view->get_absolute_view_pos() );
#endif
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ;
glDisable(GL_DEPTH_TEST);
}
clear_mask = GL_DEPTH_BUFFER_BIT;
if ( fgGetBool("/sim/rendering/wireframe") ) {
clear_mask |= GL_COLOR_BUFFER_BIT;
}
if ( skyblend ) {
if ( fgGetBool("/sim/rendering/textures") ) {
// glClearColor(black[0], black[1], black[2], black[3]);
glClearColor(l->adj_fog_color()[0], l->adj_fog_color()[1],
l->adj_fog_color()[2], l->adj_fog_color()[3]);
clear_mask |= GL_COLOR_BUFFER_BIT;
}
} else {
glClearColor(l->sky_color()[0], l->sky_color()[1],
l->sky_color()[2], l->sky_color()[3]);
clear_mask |= GL_COLOR_BUFFER_BIT;
}
if ( multi_pass_clouds && draw_clouds ) {
glClearStencil( 0 );
clear_mask |= GL_STENCIL_BUFFER_BIT;
}
glClear( clear_mask );
// Tell GL we are switching to model view parameters
// I really should create a derived ssg node or use a call
// back or something so that I can draw the sky within the
// ssgCullAndDraw() function, but for now I just mimic what
// ssg does to set up the model view matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
ssgSetCamera( (sgVec4 *)current__view->get_VIEW() );
// set the opengl state to known default values
default_state->force();
// update fog params if visibility has changed
double visibility_meters = fgGetDouble("/environment/visibility-m");
thesky->set_visibility(visibility_meters);
thesky->modify_vis( cur_fdm_state->get_Altitude() * SG_FEET_TO_METER,
( global_multi_loop * fgGetInt("/sim/speed-up") )
/ (double)fgGetInt("/sim/model-hz") );
// Set correct opengl fog density
glFogf (GL_FOG_DENSITY, fog_exp2_density);
// update the sky dome
if ( skyblend ) {
/*
SG_LOG( SG_GENERAL, SG_BULK, "thesky->repaint() sky_color = "
<< l->sky_color()[0] << " "
<< l->sky_color()[1] << " "
<< l->sky_color()[2] << " "
<< l->sky_color()[3] );
SG_LOG( SG_GENERAL, SG_BULK, " fog = "
<< l->fog_color()[0] << " "
<< l->fog_color()[1] << " "
<< l->fog_color()[2] << " "
<< l->fog_color()[3] );
SG_LOG( SG_GENERAL, SG_BULK,
" sun_angle = " << l->sun_angle
<< " moon_angle = " << l->moon_angle );
*/
static SGSkyColor scolor;
FGLight *l = (FGLight *)(globals->get_subsystem("lighting"));
scolor.sky_color = l->sky_color();
scolor.fog_color = l->adj_fog_color();
scolor.cloud_color = l->cloud_color();
scolor.sun_angle = l->get_sun_angle();
scolor.moon_angle = l->get_moon_angle();
scolor.nplanets = globals->get_ephem()->getNumPlanets();
scolor.nstars = globals->get_ephem()->getNumStars();
scolor.planet_data = globals->get_ephem()->getPlanets();
scolor.star_data = globals->get_ephem()->getStars();
thesky->repaint( scolor );
/*
SG_LOG( SG_GENERAL, SG_BULK,
"thesky->reposition( view_pos = " << view_pos[0] << " "
<< view_pos[1] << " " << view_pos[2] );
SG_LOG( SG_GENERAL, SG_BULK,
" zero_elev = " << zero_elev[0] << " "
<< zero_elev[1] << " " << zero_elev[2]
<< " lon = " << cur_fdm_state->get_Longitude()
<< " lat = " << cur_fdm_state->get_Latitude() );
SG_LOG( SG_GENERAL, SG_BULK,
" sun_rot = " << l->get_sun_rotation
<< " gst = " << SGTime::cur_time_params->getGst() );
SG_LOG( SG_GENERAL, SG_BULK,
" sun ra = " << globals->get_ephem()->getSunRightAscension()
<< " sun dec = " << globals->get_ephem()->getSunDeclination()
<< " moon ra = " << globals->get_ephem()->getMoonRightAscension()
<< " moon dec = " << globals->get_ephem()->getMoonDeclination() );
*/
// The sun and moon distances are scaled down versions
// of the actual distance to get both the moon and the sun
// within the range of the far clip plane.
// Moon distance: 384,467 kilometers
// Sun distance: 150,000,000 kilometers
double sun_horiz_eff, moon_horiz_eff;
if (fgGetBool("/sim/rendering/horizon-effect")) {
sun_horiz_eff = 0.67+pow(0.5+cos(l->get_sun_angle())*2/2, 0.33)/3;
moon_horiz_eff = 0.67+pow(0.5+cos(l->get_moon_angle())*2/2, 0.33)/3;
} else {
sun_horiz_eff = moon_horiz_eff = 1.0;
}
static SGSkyState sstate;
sstate.view_pos = current__view->get_view_pos();
sstate.zero_elev = current__view->get_zero_elev();
sstate.view_up = current__view->get_world_up();
sstate.lon = current__view->getLongitude_deg()
* SGD_DEGREES_TO_RADIANS;
sstate.lat = current__view->getLatitude_deg()
* SGD_DEGREES_TO_RADIANS;
sstate.alt = current__view->getAltitudeASL_ft()
* SG_FEET_TO_METER;
sstate.spin = l->get_sun_rotation();
sstate.gst = globals->get_time_params()->getGst();
sstate.sun_ra = globals->get_ephem()->getSunRightAscension();
sstate.sun_dec = globals->get_ephem()->getSunDeclination();
sstate.sun_dist = 50000.0 * sun_horiz_eff;
sstate.moon_ra = globals->get_ephem()->getMoonRightAscension();
sstate.moon_dec = globals->get_ephem()->getMoonDeclination();
sstate.moon_dist = 40000.0 * moon_horiz_eff;
thesky->reposition( sstate, delta_time_sec );
}
glEnable( GL_DEPTH_TEST );
if ( strcmp(fgGetString("/sim/rendering/fog"), "disabled") ) {
glEnable( GL_FOG );
glFogi( GL_FOG_MODE, GL_EXP2 );
glFogfv( GL_FOG_COLOR, l->adj_fog_color() );
}
// set sun/lighting parameters
ssgGetLight( 0 ) -> setPosition( l->sun_vec() );
// GL_LIGHT_MODEL_AMBIENT has a default non-zero value so if
// we only update GL_AMBIENT for our lights we will never get
// a completely dark scene. So, we set GL_LIGHT_MODEL_AMBIENT
// explicitely to black.
glLightModelfv( GL_LIGHT_MODEL_AMBIENT, black );
ssgGetLight( 0 ) -> setColour( GL_AMBIENT, l->scene_ambient() );
ssgGetLight( 0 ) -> setColour( GL_DIFFUSE, l->scene_diffuse() );
ssgGetLight( 0 ) -> setColour( GL_SPECULAR, l->scene_specular() );
// texture parameters
// glEnable( GL_TEXTURE_2D );
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ) ;
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST ) ;
// glMatrixMode( GL_PROJECTION );
// glLoadIdentity();
ssgSetFOV( current__view->get_h_fov(),
current__view->get_v_fov() );
double agl =
current_aircraft.fdm_state->get_Altitude() * SG_FEET_TO_METER
- globals->get_scenery()->get_cur_elev();
if ( agl > 10.0 ) {
scene_nearplane = 10.0f;
scene_farplane = 120000.0f;
} else {
scene_nearplane = groundlevel_nearplane->getDoubleValue();
scene_farplane = 120000.0f;
}
ssgSetNearFar( scene_nearplane, scene_farplane );
#ifdef FG_MPLAYER_AS
// Update any multiplayer models
globals->get_multiplayer_rx_mgr()->Update();
#endif
if ( draw_otw && skyblend ) {
// draw the sky backdrop
// we need a white diffuse light for the phase of the moon
ssgGetLight( 0 ) -> setColour( GL_DIFFUSE, white );
thesky->preDraw( cur_fdm_state->get_Altitude() * SG_FEET_TO_METER,
fog_exp2_density );
// return to the desired diffuse color
ssgGetLight( 0 ) -> setColour( GL_DIFFUSE, l->scene_diffuse() );
}
// draw the ssg scene
glEnable( GL_DEPTH_TEST );
ssgSetNearFar( scene_nearplane, scene_farplane );
if ( fgGetBool("/sim/rendering/wireframe") ) {
// draw wire frame
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
}
if ( draw_otw ) {
if ( draw_clouds ) {
// Draw the terrain
FGTileMgr::set_tile_filter( true );
sgSetModelFilter( false );
globals->get_aircraft_model()->select( false );
ssgCullAndDraw( globals->get_scenery()->get_scene_graph() );
// Disable depth buffer update, draw the clouds
glDepthMask( GL_FALSE );
thesky->drawUpperClouds();
if ( multi_pass_clouds ) {
thesky->drawLowerClouds();
}
glDepthMask( GL_TRUE );
if ( multi_pass_clouds ) {
// Draw the objects except the aircraft
// and update the stencil buffer with 1
glEnable( GL_STENCIL_TEST );
glStencilFunc( GL_ALWAYS, 1, 1 );
glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );
}
FGTileMgr::set_tile_filter( false );
sgSetModelFilter( true );
ssgCullAndDraw( globals->get_scenery()->get_scene_graph() );
} else {
FGTileMgr::set_tile_filter( true );
sgSetModelFilter( true );
globals->get_aircraft_model()->select( false );
ssgCullAndDraw( globals->get_scenery()->get_scene_graph() );
}
}
// This is a bit kludgy. Every 200 frames, do an extra
// traversal of the scene graph without drawing anything, but
// with the field-of-view set to 360x360 degrees. This
// ensures that out-of-range random objects that are not in
// the current view frustum will still be freed properly.
static int counter = 0;
counter++;
if (counter == 200) {
sgFrustum f;
f.setFOV(360, 360);
// No need to put the near plane too close;
// this way, at least the aircraft can be
// culled.
f.setNearFar(1000, 1000000);
sgMat4 m;
ssgGetModelviewMatrix(m);
FGTileMgr::set_tile_filter( true );
sgSetModelFilter( true );
globals->get_scenery()->get_scene_graph()->cull(&f, m, true);
counter = 0;
}
// change state for lighting here
// draw runway lighting
glFogf (GL_FOG_DENSITY, rwy_exp2_punch_through);
ssgSetNearFar( scene_nearplane, scene_farplane );
if ( enhanced_lighting ) {
// Enable states for drawing points with GL_extension
glEnable(GL_POINT_SMOOTH);
if ( distance_attenuation && glPointParameterIsSupported )
{
// Enable states for drawing points with GL_extension
glEnable(GL_POINT_SMOOTH);
float quadratic[3] = {1.0, 0.001, 0.0000001};
// makes the points fade as they move away
glPointParameterfvPtr(GL_DISTANCE_ATTENUATION_EXT, quadratic);
glPointParameterfPtr(GL_POINT_SIZE_MIN_EXT, 1.0);
}
glPointSize(4.0);
// blending function for runway lights
glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ;
}
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glPolygonMode(GL_FRONT, GL_POINT);
// draw runway lighting
if ( draw_otw ) {
ssgCullAndDraw( globals->get_scenery()->get_vasi_lights_root() );
ssgCullAndDraw( globals->get_scenery()->get_rwy_lights_root() );
}
// change punch through and then draw taxi lighting
glFogf ( GL_FOG_DENSITY, fog_exp2_density );
// sgVec3 taxi_fog;
// sgSetVec3( taxi_fog, 0.0, 0.0, 0.0 );
// glFogfv ( GL_FOG_COLOR, taxi_fog );
if ( draw_otw ) {
ssgCullAndDraw( globals->get_scenery()->get_taxi_lights_root() );
}
// clean up lighting
glPolygonMode(GL_FRONT, GL_FILL);
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
//static int _frame_count = 0;
//if (_frame_count % 30 == 0) {
// printf("SSG: %s\n", ssgShowStats());
//}
//else {
// ssgShowStats();
//}
//_frame_count++;
if ( enhanced_lighting ) {
if ( distance_attenuation && glPointParameterIsSupported ) {
glPointParameterfvPtr(GL_DISTANCE_ATTENUATION_EXT,
default_attenuation);
}
glPointSize(1.0);
glDisable(GL_POINT_SMOOTH);
}
// draw ground lighting
glFogf (GL_FOG_DENSITY, ground_exp2_punch_through);
if ( draw_otw ) {
ssgCullAndDraw( globals->get_scenery()->get_gnd_lights_root() );
}
if ( draw_otw && fgGetBool("/sim/rendering/clouds3d") ) {
glDisable( GL_FOG );
glDisable( GL_LIGHTING );
// cout << "drawing new clouds" << endl;
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA ) ;
/*
glEnable( GL_TEXTURE_2D );
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
*/
#ifdef FG_USE_CLOUDS_3D
sgClouds3d->Draw((sgVec4 *)current__view->get_VIEW());
#endif
glEnable( GL_FOG );
glEnable( GL_LIGHTING );
glEnable( GL_DEPTH_TEST );
glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ;
}
if ( draw_otw && draw_clouds ) {
if ( multi_pass_clouds ) {
// Disable depth buffer update, draw the clouds where the
// objects overwrite the already drawn clouds, by testing
// the stencil buffer against 1
glDepthMask( GL_FALSE );
glStencilFunc( GL_EQUAL, 1, 1 );
glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
thesky->drawUpperClouds();
thesky->drawLowerClouds();
glDepthMask( GL_TRUE );
glDisable( GL_STENCIL_TEST );
} else {
glDepthMask( GL_FALSE );
thesky->drawLowerClouds();
glDepthMask( GL_TRUE );
}
}
if ( draw_otw ) {
FGTileMgr::set_tile_filter( false );
sgSetModelFilter( false );
globals->get_aircraft_model()->select( true );
globals->get_model_mgr()->draw();
globals->get_aircraft_model()->draw();
// If the view is internal, the previous line draw the
// cockpit with modified near/far clip planes and deselect
// the aircraft in the global scenegraph
// Otherwise, it just enables the aircraft: The scenegraph
// must be drawn again to see the plane.
ssgCullAndDraw( globals->get_scenery()->get_scene_graph() );
FGTileMgr::set_tile_filter( true );
sgSetModelFilter( true );
globals->get_aircraft_model()->select( true );
}
// display HUD && Panel
glDisable( GL_FOG );
glDisable( GL_DEPTH_TEST );
// glDisable( GL_CULL_FACE );
// glDisable( GL_TEXTURE_2D );
// update the controls subsystem
globals->get_controls()->update(delta_time_sec);
hud_and_panel->apply();
fgCockpitUpdate();
// Use the hud_and_panel ssgSimpleState for rendering the ATC output
// This only works properly if called before the panel call
if((fgGetBool("/sim/ATC/enabled")) || (fgGetBool("/sim/ai-traffic/enabled")))
globals->get_ATC_display()->update(delta_time_sec);
// update the panel subsystem
if ( globals->get_current_panel() != NULL ) {
globals->get_current_panel()->update(delta_time_sec);
}
fgUpdate3DPanels();
// We can do translucent menus, so why not. :-)
menus->apply();
glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ;
puDisplay();
// glDisable ( GL_BLEND ) ;
glEnable( GL_DEPTH_TEST );
glEnable( GL_FOG );
// Fade out the splash screen over the first three seconds.
double t = globals->get_sim_time_sec();
if ( t <= 1.0 ) {
fgSplashUpdate(0.0, 1.0);
} else if ( t <= 3.0) {
fgSplashUpdate(0.0, (3.0 - t) / 2.0);
}
}
}
// Update internal time dependent calculations (i.e. flight model)
// FIXME: this distinction is obsolete; all subsystems now get delta
@ -1192,6 +383,11 @@ static void fgMainLoop( void ) {
if (fgGetBool("/sim/ai-traffic/enabled"))
globals->get_AI_mgr()->update(delta_time_sec);
#ifdef FG_MPLAYER_AS
// Update any multiplayer models
globals->get_multiplayer_rx_mgr()->Update();
#endif
// Run flight model
// Calculate model iterations needed for next frame
@ -1433,7 +629,7 @@ static void fgIdleFunction ( void ) {
fgInitTimeOffset();
// setup OpenGL view parameters
fgInitVisuals();
globals->get_renderer()->init();
// Read the list of available aircrafts
fgReadAircraft();
@ -1448,8 +644,8 @@ static void fgIdleFunction ( void ) {
idle_state = 1000;
SG_LOG( SG_GENERAL, SG_INFO, "Panel visible = " << fgPanelVisible() );
fgReshape( fgGetInt("/sim/startup/xsize"),
fgGetInt("/sim/startup/ysize") );
globals->get_renderer()->resize( fgGetInt("/sim/startup/xsize"),
fgGetInt("/sim/startup/ysize") );
}
@ -1467,46 +663,6 @@ static void fgIdleFunction ( void ) {
}
}
// options.cxx needs to see this for toggle_panel()
// Handle new window size or exposure
void fgReshape( int width, int height ) {
int view_h;
if ( (!fgGetBool("/sim/virtual-cockpit"))
&& fgPanelVisible() && idle_state == 1000 ) {
view_h = (int)(height * (globals->get_current_panel()->getViewHeight() -
globals->get_current_panel()->getYOffset()) / 768.0);
} else {
view_h = height;
}
glViewport( 0, (GLint)(height - view_h), (GLint)(width), (GLint)(view_h) );
fgSetInt("/sim/startup/xsize", width);
fgSetInt("/sim/startup/ysize", height);
guiInitMouse(width, height);
// for all views
FGViewMgr *viewmgr = globals->get_viewmgr();
if (viewmgr) {
for ( int i = 0; i < viewmgr->size(); ++i ) {
viewmgr->get_view(i)->
set_aspect_ratio((float)view_h / (float)width);
}
ssgSetFOV( viewmgr->get_current_view()->get_h_fov(),
viewmgr->get_current_view()->get_v_fov() );
#ifdef FG_USE_CLOUDS_3D
sgClouds3d->Resize( viewmgr->get_current_view()->get_h_fov(),
viewmgr->get_current_view()->get_v_fov() );
#endif
}
fgHUDReshape();
}
// Main top level initialization
bool fgMainInit( int argc, char **argv ) {
@ -1586,9 +742,9 @@ bool fgMainInit( int argc, char **argv ) {
_bootstrap_OSInit++;
#endif
fgRegisterWindowResizeHandler( fgReshape );
fgRegisterWindowResizeHandler( FGRenderer::resize );
fgRegisterIdleHandler( fgIdleFunction );
fgRegisterDrawHandler( fgRenderFrame );
fgRegisterDrawHandler( FGRenderer::update );
#ifdef FG_ENABLE_MULTIPASS_CLOUDS
bool get_stencil_buffer = true;
@ -1780,7 +936,7 @@ bool fgMainInit( int argc, char **argv ) {
// lighting->addKid( airport );
// build our custom render states
fgBuildRenderStates();
globals->get_renderer()->build_states();
try {
// pass control off to the master event handler

View file

@ -2,27 +2,16 @@
#ifndef __FG_MAIN_HXX
#define __FG_MAIN_HXX 1
#include <simgear/screen/extensions.hxx>
class SGSky;
extern SGSky *thesky;
#define FG_ENABLE_MULTIPASS_CLOUDS 1
extern glPointParameterfProc glPointParameterfPtr;
extern glPointParameterfvProc glPointParameterfvPtr;
extern bool glPointParameterIsSupported;
void fgLoadDCS (void);
void fgUpdateDCS (void);
void fgBuildRenderStates( void );
void fgInitVisuals( void );
void fgRenderFrame();
void fgUpdateTimeDepCalcs();
void fgInitTimeDepCalcs( void );
void fgReshape( int width, int height );
bool fgMainInit( int argc, char **argv );
extern int idle_state;
extern long global_multi_loop;
extern double delta_time_sec;
#endif

View file

@ -68,11 +68,6 @@
#include <Replay/replay.hxx>
#include <GUI/new_gui.hxx>
#ifdef FG_MPLAYER_AS
#include <MultiPlayer/multiplaytxmgr.hxx>
#include <MultiPlayer/multiplayrxmgr.hxx>
#endif
#include "splash.hxx"
#include "renderer.hxx"
#include "main.hxx"
@ -127,18 +122,6 @@ ssgSimpleState *hud_and_panel;
ssgSimpleState *menus;
void fgRenderFrame() {
#ifdef FG_MPLAYER_AS
// Update any multiplayer models
globals->get_multiplayer_rx_mgr()->Update();
#endif
globals->get_renderer()->update(delta_time_sec);
}
void fgReshape(int width, int height) {
globals->get_renderer()->resize(width,height);
}
void
FGRenderer::build_states( void ) {
default_state = new ssgSimpleState;
@ -354,7 +337,7 @@ FGRenderer::screendump( void ) {
// Update all Visuals (redraws anything graphics related)
void
FGRenderer::update(double dt) {
FGRenderer::update() {
bool scenery_loaded = fgGetBool("sim/sceneryloaded") || fgGetBool("sim/sceneryloaded-override");
bool draw_otw = fgGetBool("/sim/rendering/draw-otw");
bool skyblend = fgGetBool("/sim/rendering/skyblend");
@ -430,7 +413,7 @@ FGRenderer::update(double dt) {
globals->get_scenery()->set_center( globals->get_scenery()->get_next_center() );
// update view port
fgReshape( fgGetInt("/sim/startup/xsize"),
resize( fgGetInt("/sim/startup/xsize"),
fgGetInt("/sim/startup/ysize") );
if ( fgGetBool("/sim/rendering/clouds3d") ) {

View file

@ -14,8 +14,6 @@ extern glPointParameterfProc glPointParameterfPtr;
extern glPointParameterfvProc glPointParameterfvPtr;
extern bool glPointParameterIsSupported;
void fgRenderFrame();
void fgReshape(int width, int height);
class FGRenderer {
@ -24,8 +22,8 @@ public:
~FGRenderer() {}
void init();
void update(double dt);
void resize(int width, int height );
static void update();
static void resize(int width, int height );
void screendump();
void build_states();

View file

@ -12,8 +12,6 @@
#include <vector>
#include <plib/ssg.h>
SG_USING_STD(string);
SG_USING_STD(vector);

View file

@ -52,6 +52,7 @@ SG_USING_STD(string);
// Number of seconds before a player is consider to be lost
#define TIME_TO_LIVE 10
class ssgEntity;
class ssgTransform;

View file

@ -16,6 +16,7 @@
SG_USING_STD(vector);
class ssgEntity;
class ssgBranch;
class FGHitRec {

View file

@ -29,6 +29,7 @@
# error This library requires C++
#endif
#include <plib/sg.h>
#include <simgear/structure/subsystem_mgr.hxx>
@ -38,6 +39,7 @@
class ssgRoot;
class ssgBranch;
// Define a structure containing global scenery parameters
class FGScenery : public SGSubsystem {
// center of current scenery chunk

View file

@ -54,13 +54,13 @@ typedef vector < Point3D > point_list;
typedef point_list::iterator point_list_iterator;
typedef point_list::const_iterator const_point_list_iterator;
class ssgLeaf;
class ssgBranch;
class ssgTransform;
class ssgSelector;
class ssgRangeSelector;
class ssgVertexArray;
class FGTileEntry;

View file

@ -35,8 +35,6 @@
#include <queue>
#include <plib/ssg.h>
#include <simgear/bucket/newbucket.hxx>
#if defined(ENABLE_THREADS) && ENABLE_THREADS
# include <simgear/threads/SGQueue.hxx>
@ -56,6 +54,8 @@ SG_USING_STD( queue );
// forward declaration
class ssgBranch;
class ssgEntity;
class FGTileEntry;
class FGDeferredModel;