Patches contributed by Norman Vine to do ultra-hires tiled screen dumps.
This commit is contained in:
parent
52848158ff
commit
af2a0da64c
5 changed files with 313 additions and 19 deletions
|
@ -964,7 +964,19 @@ static void set_hud_color(float r, float g, float b) {
|
|||
// all C++.
|
||||
//
|
||||
void fgUpdateHUD( void ) {
|
||||
fgUpdateHUD( 0.0f, 0.0f, 640.0f, 480.0f );
|
||||
|
||||
static const float normal_aspect = float(640) / float(480);
|
||||
// note: win_ratio is Y/X
|
||||
float current_aspect = 1.0f/globals->get_current_view()->get_win_ratio();
|
||||
if( current_aspect > normal_aspect ) {
|
||||
float aspect_adjust = current_aspect / normal_aspect;
|
||||
float adjust = 320.0f*aspect_adjust - 320.0f;
|
||||
fgUpdateHUD( -adjust, 0.0f, 640.0f+adjust, 480.0f );
|
||||
} else {
|
||||
float aspect_adjust = normal_aspect / current_aspect;
|
||||
float adjust = 240.0f*aspect_adjust - 240.0f;
|
||||
fgUpdateHUD( 0.0f, -adjust, 640.0f, 480.0f+adjust );
|
||||
}
|
||||
}
|
||||
|
||||
void fgUpdateHUD( GLfloat x_start, GLfloat y_start,
|
||||
|
@ -1009,6 +1021,7 @@ void fgUpdateHUD( GLfloat x_start, GLfloat y_start,
|
|||
// glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
||||
glHint(GL_LINE_SMOOTH_HINT,GL_DONT_CARE);
|
||||
// glHint(GL_LINE_SMOOTH_HINT,GL_NICEST);
|
||||
glLineWidth(1.5);
|
||||
} else {
|
||||
glLineWidth(1.0);
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
/**
|
||||
* Calculate the aspect adjustment for the panel.
|
||||
*/
|
||||
float
|
||||
static float
|
||||
get_aspect_adjust (int xsize, int ysize)
|
||||
{
|
||||
float ideal_aspect = float(WIN_W) / float(WIN_H);
|
||||
|
@ -240,32 +240,36 @@ FGPanel::unbind ()
|
|||
void
|
||||
FGPanel::update ()
|
||||
{
|
||||
float aspect_adjust = get_aspect_adjust(_xsize_node->getIntValue(),
|
||||
_ysize_node->getIntValue());
|
||||
|
||||
// Do nothing if the panel isn't visible.
|
||||
if (!fgPanelVisible())
|
||||
return;
|
||||
if (!fgPanelVisible())
|
||||
return;
|
||||
|
||||
// If the mouse is down, do something
|
||||
if (_mouseDown) {
|
||||
_mouseDelay--;
|
||||
if (_mouseDelay < 0) {
|
||||
_mouseInstrument->doMouseAction(_mouseButton, _mouseX, _mouseY);
|
||||
_mouseDelay = 2;
|
||||
if (_mouseDown) {
|
||||
_mouseDelay--;
|
||||
if (_mouseDelay < 0) {
|
||||
_mouseInstrument->doMouseAction(_mouseButton, _mouseX, _mouseY);
|
||||
_mouseDelay = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now, draw the panel
|
||||
float aspect_adjust = get_aspect_adjust(_xsize_node->getIntValue(),
|
||||
_ysize_node->getIntValue());
|
||||
if (aspect_adjust <1.0)
|
||||
update(WIN_X, int(WIN_W * aspect_adjust), WIN_Y, WIN_H);
|
||||
else
|
||||
update(WIN_X, WIN_W, WIN_Y, int(WIN_H / aspect_adjust));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FGPanel::update (GLfloat winx, GLfloat winw, GLfloat winy, GLfloat winh)
|
||||
{
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
if (aspect_adjust <1.0)
|
||||
gluOrtho2D(WIN_X, WIN_X + int(WIN_W * aspect_adjust),
|
||||
WIN_Y, WIN_Y + WIN_H);
|
||||
else
|
||||
gluOrtho2D(WIN_X, WIN_X + WIN_W,
|
||||
WIN_Y, WIN_Y + int(WIN_H / aspect_adjust));
|
||||
gluOrtho2D(winx, winx + winw, winy, winy + winh);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
|
|
|
@ -133,6 +133,7 @@ public:
|
|||
virtual void bind ();
|
||||
virtual void unbind ();
|
||||
virtual void update ();
|
||||
virtual void update (GLfloat winx, GLfloat winw, GLfloat winy, GLfloat winh);
|
||||
|
||||
// transfer pointer ownership!!!
|
||||
virtual void addInstrument (FGPanelInstrument * instrument);
|
||||
|
|
203
src/GUI/gui.cxx
203
src/GUI/gui.cxx
|
@ -450,6 +450,202 @@ void helpCb (puObject *)
|
|||
//mkDialog (text.c_str());
|
||||
mkDialog ("Help started in netscape window.");
|
||||
}
|
||||
#define TR_HIRES_SNAP
|
||||
#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 );
|
||||
|
||||
void fgHiResDump()
|
||||
{
|
||||
FILE *f;
|
||||
string message;
|
||||
bool show_pu_cursor = false;
|
||||
bool show_menu = false;
|
||||
char *filename = new char [24];
|
||||
static int count = 1;
|
||||
|
||||
int freeze = globals->get_freeze();
|
||||
if(!freeze)
|
||||
globals->set_freeze( true );
|
||||
|
||||
if(gui_menu_on) {
|
||||
show_menu = true;
|
||||
guiToggleMenu();
|
||||
}
|
||||
|
||||
if ( !puCursorIsHidden() ) {
|
||||
show_pu_cursor = true;
|
||||
puHideCursor();
|
||||
}
|
||||
|
||||
fgInitVisuals();
|
||||
fgReshape( 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();
|
||||
|
||||
// Make sure we have SSG projection primed for current view
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
ssgSetCamera( (sgVec4 *)globals->get_current_view()->get_VIEW() );
|
||||
float fov = globals->get_current_view()->get_fov();
|
||||
ssgSetFOV(fov, fov * globals->get_current_view()->get_win_ratio());
|
||||
// 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
|
||||
|
||||
// This should be a requester to get multiplier from user
|
||||
int multiplier = 3;
|
||||
int width = fgGetInt("/sim/startup/xsize");
|
||||
int height = fgGetInt("/sim/startup/ysize");
|
||||
|
||||
/* allocate buffer large enough to store one tile */
|
||||
GLubyte *tile = (GLubyte *)malloc(width * height * 3 * sizeof(GLubyte));
|
||||
if (!tile) {
|
||||
printf("Malloc of tile buffer failed!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
int imageWidth = multiplier*width;
|
||||
int imageHeight = multiplier*height;
|
||||
|
||||
/* allocate buffer to hold a row of tiles */
|
||||
GLubyte *buffer
|
||||
= (GLubyte *)malloc(imageWidth * height * 3 * sizeof(GLubyte));
|
||||
if (!buffer) {
|
||||
free(tile);
|
||||
printf("Malloc of tile row buffer failed!\n");
|
||||
return;
|
||||
}
|
||||
TRcontext *tr = trNew();
|
||||
trTileSize(tr, width, height, 0);
|
||||
trTileBuffer(tr, GL_RGB, GL_UNSIGNED_BYTE, tile);
|
||||
trImageSize(tr, imageWidth, imageHeight);
|
||||
trRowOrder(tr, TR_TOP_TO_BOTTOM);
|
||||
sgFrustum *frustum = ssgGetFrustum();
|
||||
trFrustum(tr,
|
||||
frustum->getLeft(), frustum->getRight(),
|
||||
frustum->getBot(), frustum->getTop(),
|
||||
frustum->getNear(), frustum->getFar());
|
||||
|
||||
/* Prepare ppm output file */
|
||||
while (count < 1000) {
|
||||
snprintf(filename, 24, "fgfs-screen-%03d.ppm", count++);
|
||||
if ( (f = fopen(filename, "r")) == NULL )
|
||||
break;
|
||||
fclose(f);
|
||||
}
|
||||
f = fopen(filename, "wb");
|
||||
if (!f) {
|
||||
printf("Couldn't open image file: %s\n", filename);
|
||||
free(buffer);
|
||||
free(tile);
|
||||
return;
|
||||
}
|
||||
fprintf(f,"P6\n");
|
||||
fprintf(f,"# ppm-file created by %s\n", "trdemo2");
|
||||
fprintf(f,"%i %i\n", imageWidth, imageHeight);
|
||||
fprintf(f,"255\n");
|
||||
|
||||
/* just to be safe... */
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
|
||||
/* Because the HUD and Panel change the ViewPort we will
|
||||
* need to handle some lowlevel stuff ourselves */
|
||||
int ncols = trGet(tr, TR_COLUMNS);
|
||||
int nrows = trGet(tr, TR_ROWS);
|
||||
|
||||
bool do_hud = fgGetBool("/sim/hud/visibility");
|
||||
GLfloat hud_col_step = 640.0 / ncols;
|
||||
GLfloat hud_row_step = 480.0 / nrows;
|
||||
|
||||
bool do_panel = fgPanelVisible();
|
||||
GLfloat panel_col_step = current_panel->getWidth() / ncols;
|
||||
GLfloat panel_row_step = current_panel->getHeight() / nrows;
|
||||
|
||||
/* Draw tiles */
|
||||
int more = 1;
|
||||
while (more) {
|
||||
trBeginTile(tr);
|
||||
int curColumn = trGet(tr, TR_CURRENT_COLUMN);
|
||||
int curRow = trGet(tr, TR_CURRENT_ROW);
|
||||
trRenderFrame();
|
||||
if ( do_hud )
|
||||
fgUpdateHUD( curColumn*hud_col_step, curRow*hud_row_step,
|
||||
(curColumn+1)*hud_col_step, (curRow+1)*hud_row_step );
|
||||
if (do_panel)
|
||||
current_panel->update( curColumn*panel_col_step, panel_col_step,
|
||||
curRow*panel_row_step, panel_row_step );
|
||||
more = trEndTile(tr);
|
||||
|
||||
/* save tile into tile row buffer*/
|
||||
int curTileWidth = trGet(tr, TR_CURRENT_TILE_WIDTH);
|
||||
int bytesPerImageRow = imageWidth * 3*sizeof(GLubyte);
|
||||
int bytesPerTileRow = (width) * 3*sizeof(GLubyte);
|
||||
int xOffset = curColumn * bytesPerTileRow;
|
||||
int bytesPerCurrentTileRow = (curTileWidth) * 3*sizeof(GLubyte);
|
||||
int i;
|
||||
for (i=0;i<height;i++) {
|
||||
memcpy(buffer + i*bytesPerImageRow + xOffset, /* Dest */
|
||||
tile + i*bytesPerTileRow, /* Src */
|
||||
bytesPerCurrentTileRow); /* Byte count*/
|
||||
}
|
||||
|
||||
if (curColumn == trGet(tr, TR_COLUMNS)-1) {
|
||||
/* write this buffered row of tiles to the file */
|
||||
int curTileHeight = trGet(tr, TR_CURRENT_TILE_HEIGHT);
|
||||
int bytesPerImageRow = imageWidth * 3*sizeof(GLubyte);
|
||||
int i;
|
||||
for (i=0;i<curTileHeight;i++) {
|
||||
/* Remember, OpenGL images are bottom to top. Have to reverse. */
|
||||
GLubyte *rowPtr = buffer + (curTileHeight-1-i) * bytesPerImageRow;
|
||||
fwrite(rowPtr, 1, imageWidth*3, f);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fgReshape( width, height );
|
||||
|
||||
trDelete(tr);
|
||||
|
||||
fclose(f);
|
||||
|
||||
message = "Snap shot saved to ";
|
||||
message += filename;
|
||||
mkDialog (message.c_str());
|
||||
|
||||
free(tile);
|
||||
free(buffer);
|
||||
|
||||
// message = "Snap shot saved to ";
|
||||
// message += filename;
|
||||
// mkDialog (message.c_str());
|
||||
|
||||
delete [] filename;
|
||||
|
||||
if( show_menu )
|
||||
guiToggleMenu();
|
||||
|
||||
if ( show_pu_cursor ) {
|
||||
puShowCursor();
|
||||
}
|
||||
|
||||
if(!freeze)
|
||||
globals->set_freeze( false );
|
||||
}
|
||||
#endif // #if defined( TR_HIRES_SNAP)
|
||||
|
||||
|
||||
#if defined( WIN32 ) && !defined( __CYGWIN__)
|
||||
|
||||
|
@ -525,6 +721,11 @@ void dumpSnapShot ( puObject *obj ) {
|
|||
}
|
||||
|
||||
|
||||
void dumpHiResSnapShot ( puObject *obj ) {
|
||||
fgHiResDump();
|
||||
}
|
||||
|
||||
|
||||
// do a screen snap shot
|
||||
void fgDumpSnapShot () {
|
||||
bool show_pu_cursor = false;
|
||||
|
@ -621,6 +822,7 @@ char *fileSubmenu [] = {
|
|||
"Print",
|
||||
#endif
|
||||
"Snap Shot",
|
||||
"Hires Snap Shot",
|
||||
"---------",
|
||||
"Reset",
|
||||
"Load flight",
|
||||
|
@ -634,6 +836,7 @@ puCallback fileSubmenuCb [] = {
|
|||
#endif
|
||||
/* NULL, notCb, */
|
||||
dumpSnapShot,
|
||||
dumpHiResSnapShot,
|
||||
NULL,
|
||||
reInit,
|
||||
loadFlight,
|
||||
|
|
|
@ -311,6 +311,79 @@ void fgInitVisuals( void ) {
|
|||
}
|
||||
|
||||
|
||||
// For HiRes screen Dumps using Brian Pauls TR Library
|
||||
void trRenderFrame( void ) {
|
||||
|
||||
if ( fgPanelVisible() ) {
|
||||
GLfloat height = fgGetInt("/sim/startup/ysize");
|
||||
GLfloat view_h =
|
||||
(current_panel->getViewHeight() - current_panel->getYOffset())
|
||||
* (height / 768.0) + 1;
|
||||
glTranslatef( 0.0, view_h, 0.0 );
|
||||
}
|
||||
|
||||
static double m_log01 = -log( 0.01 );
|
||||
static double sqrt_m_log01 = sqrt( m_log01 );
|
||||
|
||||
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 = &cur_light_params;
|
||||
|
||||
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();
|
||||
|
||||
// update fog params
|
||||
double actual_visibility = thesky->get_visibility();
|
||||
// GLfloat fog_exp_density = m_log01 / actual_visibility;
|
||||
GLfloat fog_exp2_density = sqrt_m_log01 / actual_visibility;
|
||||
GLfloat fog_exp2_punch_through = sqrt_m_log01 / ( actual_visibility * 1.5 );
|
||||
|
||||
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 );
|
||||
|
||||
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();
|
||||
|
||||
// draw the ssg scene
|
||||
// return to the desired diffuse color
|
||||
ssgGetLight( 0 ) -> setColour( GL_DIFFUSE, l->scene_diffuse );
|
||||
glEnable( GL_DEPTH_TEST );
|
||||
ssgCullAndDraw( scene );
|
||||
|
||||
// draw the lights
|
||||
glFogf (GL_FOG_DENSITY, fog_exp2_punch_through);
|
||||
ssgCullAndDraw( lighting );
|
||||
|
||||
thesky->postDraw( cur_fdm_state->get_Altitude() * SG_FEET_TO_METER );
|
||||
|
||||
// need to do this here as hud_and_panel state is static to
|
||||
// main.cxx and HUD and Panel routines have to be called with
|
||||
// knowledge of the the TR struct < see gui.cxx::HighResDump()
|
||||
hud_and_panel->apply();
|
||||
}
|
||||
|
||||
|
||||
// Update all Visuals (redraws anything graphics related)
|
||||
void fgRenderFrame( void ) {
|
||||
// Update the default (kludged) properties.
|
||||
|
|
Loading…
Reference in a new issue