1
0
Fork 0

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. :-)
This commit is contained in:
curt 2004-10-06 03:29:14 +00:00
parent 600384d5c7
commit 41e217fb9a
4 changed files with 57 additions and 175 deletions

View file

@ -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__)

View file

@ -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,6 +528,7 @@ void fgHiResDump()
fgSetBool("/sim/freeze/master", true);
}
TurnCursorOff();
if ( !puCursorIsHidden() ) {
show_pu_cursor = true;
puHideCursor();
@ -541,21 +542,8 @@ 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();
// 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 );
renderer->update( true );
renderer->update( true );
// This ImageSize stuff is a temporary hack
// should probably use 128x128 tile size and
@ -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 );
@ -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;

View file

@ -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,10 +291,17 @@ FGRenderer::update() {
// calculate our current position in cartesian space
globals->get_scenery()->set_center( globals->get_scenery()->get_next_center() );
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 );
cloud3d_imposter_state->force();
@ -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

View file

@ -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