1
0
Fork 0

Patches contributed by Norman Vine to do ultra-hires tiled screen dumps.

This commit is contained in:
curt 2001-06-26 18:23:07 +00:00
parent 52848158ff
commit af2a0da64c
5 changed files with 313 additions and 19 deletions

View file

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

View file

@ -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();

View file

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

View file

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

View file

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