From 41e217fb9a6fdbb6e14329ff5d0a40d7300423af Mon Sep 17 00:00:00 2001 From: curt Date: Wed, 6 Oct 2004 03:29:14 +0000 Subject: [PATCH] Continued work to clean up the hires screen shot code and move it back towards a working state. I still see an anomoly when taking a screen shot from inside a 3d cockpit, but external (chase/tower) views seem to work well. I also added a property to control how many screen-res tiles are generated in the output. Theoretically, you can now generate unlimited resolution screen shots, or limited only by your disk space and patience. Today I successfully generated a 20*1024 x 20*768 (20480x15360) resolution screen shot. If you rendered that at 100 dpi it would cover a poster of about 17 feet by 12.8 feet. Good luck trying to display something that big or convert it to anything useful on a typical PC. :-) --- src/GUI/gui.h | 4 +- src/GUI/gui_funcs.cxx | 42 ++++------ src/Main/renderer.cxx | 176 ++++++++---------------------------------- src/Main/renderer.hxx | 10 ++- 4 files changed, 57 insertions(+), 175 deletions(-) diff --git a/src/GUI/gui.h b/src/GUI/gui.h index 2ce8bd6a2..2920e48e8 100644 --- a/src/GUI/gui.h +++ b/src/GUI/gui.h @@ -57,9 +57,9 @@ extern int gui_menu_on; extern void saveFlight(puObject *); extern void loadFlight(puObject *); extern void reInit(puObject *); -extern void dumpSnapShot(puObject *); +extern void fgDumpSnapShotWrapper(puObject *); #ifdef TR_HIRES_SNAP -extern void dumpHiResSnapShot(puObject *); +extern void fgHiResDumpWrapper(puObject *); extern void fgHiResDump(); #endif #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined(__MINGW32__) diff --git a/src/GUI/gui_funcs.cxx b/src/GUI/gui_funcs.cxx index 4f51dcc7d..c44e69577 100644 --- a/src/GUI/gui_funcs.cxx +++ b/src/GUI/gui_funcs.cxx @@ -138,9 +138,9 @@ const __fg_gui_fn_t __fg_gui_fn[] = { {"loadFlight", loadFlight}, {"reInit", reInit}, #ifdef TR_HIRES_SNAP - {"dumpHiResSnapShot", dumpHiResSnapShot}, + {"dumpHiResSnapShot", fgHiResDumpWrapper}, #endif - {"dumpSnapShot", dumpSnapShot}, + {"dumpSnapShot", fgDumpSnapShotWrapper}, #if defined( WIN32 ) && !defined( __CYGWIN__) && !defined(__MINGW32__) {"printScreen", printScreen}, #endif @@ -528,9 +528,10 @@ void fgHiResDump() fgSetBool("/sim/freeze/master", true); } + TurnCursorOff(); if ( !puCursorIsHidden() ) { - show_pu_cursor = true; - puHideCursor(); + show_pu_cursor = true; + puHideCursor(); } FGRenderer *renderer = globals->get_renderer(); @@ -541,22 +542,9 @@ void fgHiResDump() // we need two render frames here to clear the menu and cursor // ... not sure why but doing an extra fgRenderFrame() shouldn't // hurt anything - renderer->update(); - renderer->update(); + renderer->update( true ); + renderer->update( true ); - // Make sure we have SSG projection primed for current view - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - ssgSetCamera( (sgVec4 *)globals->get_current_view()->get_VIEW() ); - ssgSetFOV( globals->get_current_view()->get_h_fov(), - globals->get_current_view()->get_v_fov() ); - cout << "FOV = " << globals->get_current_view()->get_h_fov() - << ", " << globals->get_current_view()->get_v_fov() << endl; - - // ssgSetNearFar( 10.0f, 120000.0f ); - ssgSetNearFar( 0.5f, 1200000.0f ); - - // This ImageSize stuff is a temporary hack // should probably use 128x128 tile size and // support any image size @@ -636,7 +624,7 @@ void fgHiResDump() trBeginTile(tr); int curColumn = trGet(tr, TR_CURRENT_COLUMN); int curRow = trGet(tr, TR_CURRENT_ROW); - renderer->screendump(); + renderer->update( false ); if ( do_hud ) fgUpdateHUD( curColumn*hud_col_step, curRow*hud_row_step, (curColumn+1)*hud_col_step, (curRow+1)*hud_row_step ); @@ -696,6 +684,8 @@ void fgHiResDump() puShowCursor(); } + TurnCursorOn(); + if ( !freeze ) { fgSetBool("/sim/freeze/master", false); } @@ -729,7 +719,7 @@ GLubyte *hiResScreenCapture( int multiplier ) 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) ); - globals->get_renderer()->update(); + globals->get_renderer()->update( false ); // restore view GlBitmap b2; b1->copyBitmap( &b2, cur_width*x, cur_height*y ); @@ -755,7 +745,7 @@ void printScreen ( puObject *obj ) { int cur_width = fgGetInt("/sim/startup/xsize"); int cur_height = fgGetInt("/sim/startup/ysize"); p.Begin( "FlightGear", cur_width*3, cur_height*3 ); - p.End( hiResScreenCapture(3) ); + p.End( hiResScreenCapture(3) ); // BusyCursor(1); if ( show_pu_cursor ) { @@ -766,12 +756,12 @@ void printScreen ( puObject *obj ) { #endif // #ifdef WIN32 -void dumpSnapShot ( puObject *obj ) { +void fgDumpSnapShotWrapper ( puObject *obj ) { fgDumpSnapShot(); } -void dumpHiResSnapShot ( puObject *obj ) { +void fgHiResDumpWrapper ( puObject *obj ) { fgHiResDump(); } @@ -805,8 +795,8 @@ void fgDumpSnapShot () { // we need two render frames here to clear the menu and cursor // ... not sure why but doing an extra fgRenderFrame() shouldn't // hurt anything - renderer->update(); - renderer->update(); + renderer->update( true ); + renderer->update( true ); while (count < 1000) { FILE *fp; diff --git a/src/Main/renderer.cxx b/src/Main/renderer.cxx index 7f1e76474..fa780f36c 100644 --- a/src/Main/renderer.cxx +++ b/src/Main/renderer.cxx @@ -212,132 +212,9 @@ FGRenderer::init( void ) { } -// For HiRes screen Dumps using Brian Pauls TR Library -void -FGRenderer::screendump( 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 -FGRenderer::update() { +FGRenderer::update( bool refresh_camera_settings ) { bool scenery_loaded = fgGetBool("sim/sceneryloaded") || fgGetBool("sim/sceneryloaded-override"); bool draw_otw = fgGetBool("/sim/rendering/draw-otw"); bool skyblend = fgGetBool("/sim/rendering/skyblend"); @@ -368,10 +245,12 @@ FGRenderer::update() { // update fog params double actual_visibility; - if (fgGetBool("/environment/clouds/status")) + if (fgGetBool("/environment/clouds/status")) { actual_visibility = thesky->get_visibility(); - else + } else { actual_visibility = fgGetDouble("/environment/visibility-m"); + } + if ( actual_visibility != last_visibility ) { last_visibility = actual_visibility; @@ -412,9 +291,16 @@ FGRenderer::update() { // calculate our current position in cartesian space globals->get_scenery()->set_center( globals->get_scenery()->get_next_center() ); - // update view port - resize( fgGetInt("/sim/startup/xsize"), - fgGetInt("/sim/startup/ysize") ); + if ( refresh_camera_settings ) { + // update view port + resize( fgGetInt("/sim/startup/xsize"), + fgGetInt("/sim/startup/ysize") ); + + // Tell GL we are switching to model view parameters + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + ssgSetCamera( (sgVec4 *)current__view->get_VIEW() ); + } if ( fgGetBool("/sim/rendering/clouds3d") ) { glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT ); @@ -460,16 +346,6 @@ FGRenderer::update() { } 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(); @@ -597,11 +473,6 @@ FGRenderer::update() { 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(); @@ -920,7 +791,23 @@ FGRenderer::resize( int width, int height ) { } + // For HiRes screen Dumps using Brian Pauls TR Library +// +// Curt writes: Unfortunately, if the jpeg image server code is +// compiled into simgear and flightgear, this function get's called +// from simgear which is not the direction we want our dependencies to +// go, but it's the way things are right now. +// +// If I had to guess, I would speculate that this code probably +// doesn't work, at least not 100% correctly, but I don't have time +// right now to sort this one out. Also the jpeg server was very +// experimental and was extremely limited in the resolution images it +// could serve out for some never debugged reason. It's a novel +// feature, but I wouldn't be entirely opposed to seeing it go away +// unless someone wants to fix it so it works right and robustly and +// can serve full resolution images without crashing ourselves. + void trRenderFrame( void ) { #ifdef FG_ENABLE_MULTIPASS_CLOUDS bool multi_pass_clouds = fgGetBool("/sim/rendering/multi-pass-clouds") && @@ -1041,4 +928,5 @@ void trRenderFrame( void ) { globals->get_aircraft_model()->draw(); } + // end of renderer.cxx diff --git a/src/Main/renderer.hxx b/src/Main/renderer.hxx index c8db96d5e..62f3f2053 100644 --- a/src/Main/renderer.hxx +++ b/src/Main/renderer.hxx @@ -22,11 +22,15 @@ public: ~FGRenderer() {} void init(); - static void update(); + + void build_states(); static void resize(int width, int height ); - void screendump(); - void build_states(); + // calling update( refresh_camera_settings = false ) will not + // touch window or camera settings. This is useful for the tiled + // renderer which needs to set the view frustum itself. + static void update( bool refresh_camera_settings ); + inline static void update() { update( true ); } }; #endif