]> git.mxchange.org Git - flightgear.git/commitdiff
Patches contributed by Norman Vine to do ultra-hires tiled screen dumps.
authorcurt <curt>
Tue, 26 Jun 2001 18:23:07 +0000 (18:23 +0000)
committercurt <curt>
Tue, 26 Jun 2001 18:23:07 +0000 (18:23 +0000)
src/Cockpit/hud.cxx
src/Cockpit/panel.cxx
src/Cockpit/panel.hxx
src/GUI/gui.cxx
src/Main/main.cxx

index 15e4837ab06a49e64ab697b539cf58a6ed0d0c59..fbaec9b14e3f8b0bf6012c82e91f190cc82b03b0 100644 (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);
index ff32eb27b1f5830ad33301d89d8373937fd5055d..95215723b88978566389a5009a70b094fd543803 100644 (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();
index 54276f62fceeb7f39fb5af093f302269aa00711b..1aa28d6952f8320375114603d1dd7b74bb1a8127 100644 (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);
index de332ea95bd1ee01d91cd1171be0fff418f50375..97dc8f3094e7d75167fb7c9147c14c5d97edf146 100644 (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,
index cfb2a382b8ee87951004f1eec5a9192f3df702d8..ac6cff902d502ecf81bedf0645fba3158159de2e 100644 (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.