tr.cxx

00001 /* $Id: tr_8cxx-source.html,v 1.15 2007-12-17 15:37:16 curt Exp $ */
00002 
00003 /*
00004  * $Log: tr.cxx,v $
00005  * Revision 1.3  2006-02-21 10:47:21  ehofman
00006  * Back out the previous patch.
00007  *
00008  * Revision 1.2  2004/11/18 19:10:34  curt
00009  * Abstract out location of gl.h, glut.h, and glu.h includes so that we can
00010  * make the Mac platform happy since they put these in a different place compared
00011  * to the rest of the world.
00012  *
00013  * Revision 1.1.1.1  2002/09/07 02:58:19  curt
00014  * Initial revsion of Simgear-0.3.0
00015  *
00016  * Revision 1.3  2001/07/30 20:34:21  curt
00017  * Various MSVC fixes.
00018  *
00019  * Revision 1.2  2001/06/27 02:48:01  curt
00020  * Fixed a type conversion bug that could trip up some of the pickier compilers
00021  * out there.
00022  *
00023  * Revision 1.1  2001/06/26 15:19:39  curt
00024  * Added tr.cxx / tr.h, Brian Paul's LGPL'd tiled rendering support libs for
00025  * rendering ultra high res "tiled" screen shots.
00026  *
00027  * Revision 1.9  1998/01/29  16:56:54  brianp
00028  * allow trOrtho() and trFrustum() to be called at any time, minor clean-up
00029  *
00030  * Revision 1.8  1998/01/28  19:47:39  brianp
00031  * minor clean-up for C++
00032  *
00033  * Revision 1.7  1997/07/21  17:34:38  brianp
00034  * added tile borders
00035  *
00036  * Revision 1.6  1997/07/21  15:47:35  brianp
00037  * renamed all "near" and "far" variables
00038  *
00039  * Revision 1.5  1997/04/26  21:23:25  brianp
00040  * added trRasterPos3f function
00041  *
00042  * Revision 1.4  1997/04/26  19:59:36  brianp
00043  * set CurrentTile to -1 before first tile and after last tile
00044  *
00045  * Revision 1.3  1997/04/22  23:51:15  brianp
00046  * added WIN32 header stuff, removed tabs
00047  *
00048  * Revision 1.2  1997/04/19  23:26:10  brianp
00049  * many API changes
00050  *
00051  * Revision 1.1  1997/04/18  21:53:05  brianp
00052  * Initial revision
00053  *
00054  */
00055 
00056 
00057 /*
00058  * Tiled Rendering library
00059  * Version 1.1
00060  * Copyright (C) Brian Paul
00061  */
00062 
00063 
00064 #include <simgear/compiler.h>
00065 
00066 #include <assert.h>
00067 #include <math.h>
00068 #include <stdlib.h>
00069 #include <stdio.h>
00070 #ifdef WIN32
00071 #include <windows.h>
00072 #endif
00073 
00074 #include SG_GLU_H
00075 
00076 #include <plib/ssg.h>
00077 #include "tr.h"
00078 
00079 
00080 #define DEFAULT_TILE_WIDTH  256
00081 #define DEFAULT_TILE_HEIGHT 256
00082 #define DEFAULT_TILE_BORDER 0
00083 
00084 
00085 struct _TRctx {
00086    /* Final image parameters */
00087    GLint ImageWidth, ImageHeight;
00088    GLenum ImageFormat, ImageType;
00089    GLvoid *ImageBuffer;
00090 
00091    /* Tile parameters */
00092    GLint TileWidth, TileHeight;
00093    GLint TileWidthNB, TileHeightNB;
00094    GLint TileBorder;
00095    GLenum TileFormat, TileType;
00096    GLvoid *TileBuffer;
00097 
00098    /* Projection parameters */
00099    GLboolean Perspective;
00100    GLdouble Left;
00101    GLdouble Right;
00102    GLdouble Bottom;
00103    GLdouble Top;
00104    GLdouble Near;
00105    GLdouble Far;
00106 
00107    /* Misc */
00108    TRenum RowOrder;
00109    GLint Rows, Columns;
00110    GLint CurrentTile;
00111    GLint CurrentTileWidth, CurrentTileHeight;
00112    GLint CurrentRow, CurrentColumn;
00113 
00114    GLint ViewportSave[4];
00115 };
00116 
00117 
00118 
00119 /*
00120  * Misc setup including computing number of tiles (rows and columns).
00121  */
00122 static void Setup(TRcontext *tr)
00123 {
00124    if (!tr)
00125       return;
00126 
00127    tr->Columns = (tr->ImageWidth + tr->TileWidthNB - 1) / tr->TileWidthNB;
00128    tr->Rows = (tr->ImageHeight + tr->TileHeightNB - 1) / tr->TileHeightNB;
00129    tr->CurrentTile = 0;
00130 
00131    assert(tr->Columns >= 0);
00132    assert(tr->Rows >= 0);
00133 }
00134 
00135 
00136 
00137 TRcontext *trNew(void)
00138 {
00139    TRcontext *tr = (TRcontext *) calloc(1, sizeof(TRcontext));
00140    if (tr) {
00141       tr->TileWidth = DEFAULT_TILE_WIDTH;
00142       tr->TileHeight = DEFAULT_TILE_HEIGHT;
00143       tr->TileBorder = DEFAULT_TILE_BORDER;
00144       tr->RowOrder = TR_BOTTOM_TO_TOP;
00145       tr->CurrentTile = -1;
00146    }
00147    return (TRcontext *) tr;
00148 }
00149 
00150 
00151 void trDelete(TRcontext *tr)
00152 {
00153    if (tr)
00154       free(tr);
00155 }
00156 
00157 
00158 
00159 void trTileSize(TRcontext *tr, GLint width, GLint height, GLint border)
00160 {
00161    if (!tr)
00162       return;
00163 
00164    assert(border >= 0);
00165    assert(width >= 1);
00166    assert(height >= 1);
00167    assert(width >= 2*border);
00168    assert(height >= 2*border);
00169 
00170    tr->TileBorder = border;
00171    tr->TileWidth = width;
00172    tr->TileHeight = height;
00173    tr->TileWidthNB = width - 2 * border;
00174    tr->TileHeightNB = height - 2 * border;
00175    Setup(tr);
00176 }
00177 
00178 
00179 
00180 void trTileBuffer(TRcontext *tr, GLenum format, GLenum type, GLvoid *image)
00181 {
00182    if (!tr)
00183       return;
00184 
00185    tr->TileFormat = format;
00186    tr->TileType = type;
00187    tr->TileBuffer = image;
00188 }
00189 
00190 
00191 
00192 void trImageSize(TRcontext *tr, GLint width, GLint height)
00193 {
00194    if (!tr)
00195       return;
00196 
00197    tr->ImageWidth = width;
00198    tr->ImageHeight = height;
00199    Setup(tr);
00200 }
00201 
00202 
00203 void trImageBuffer(TRcontext *tr, GLenum format, GLenum type, GLvoid *image)
00204 {
00205    if (!tr)
00206       return;
00207 
00208    tr->ImageFormat = format;
00209    tr->ImageType = type;
00210    tr->ImageBuffer = image;
00211 }
00212 
00213 
00214 GLint trGet(TRcontext *tr, TRenum param)
00215 {
00216    if (!tr)
00217       return 0;
00218    switch (param) {
00219       case TR_TILE_WIDTH:
00220          return tr->TileWidth;
00221       case TR_TILE_HEIGHT:
00222          return tr->TileHeight;
00223       case TR_TILE_BORDER:
00224          return tr->TileBorder;
00225       case TR_IMAGE_WIDTH:
00226          return tr->ImageWidth;
00227       case TR_IMAGE_HEIGHT:
00228          return tr->ImageHeight;
00229       case TR_ROWS:
00230          return tr->Rows;
00231       case TR_COLUMNS:
00232          return tr->Columns;
00233       case TR_CURRENT_ROW:
00234          if (tr->CurrentTile<0)
00235             return -1;
00236          else
00237             return tr->CurrentRow;
00238       case TR_CURRENT_COLUMN:
00239          if (tr->CurrentTile<0)
00240             return -1;
00241          else
00242             return tr->CurrentColumn;
00243       case TR_CURRENT_TILE_WIDTH:
00244          return tr->CurrentTileWidth;
00245       case TR_CURRENT_TILE_HEIGHT:
00246          return tr->CurrentTileHeight;
00247       case TR_ROW_ORDER:
00248          return (GLint) tr->RowOrder;
00249       default:
00250          return 0;
00251    }
00252 }
00253 
00254 GLdouble trGetD(TRcontext *tr, TRenum param)
00255 {
00256         if (!tr)
00257                 return 0.0;
00258         switch (param) {
00259         case TR_LEFT:
00260                 return tr->Left;
00261         case TR_RIGHT:
00262                 return tr->Right;
00263         case TR_BOTTOM:
00264                 return tr->Bottom;
00265         case TR_TOP:
00266                 return tr->Top;
00267         case TR_NEAR:
00268                 return tr->Near;
00269         case TR_FAR:
00270                 return tr->Far;
00271         default:
00272                 return 0.0;
00273         }
00274 }
00275 
00276 void trRowOrder(TRcontext *tr, TRenum order)
00277 {
00278    if (!tr)
00279       return;
00280 
00281    if (order==TR_TOP_TO_BOTTOM || order==TR_BOTTOM_TO_TOP)
00282       tr->RowOrder = order;
00283 }
00284 
00285 
00286 void trOrtho(TRcontext *tr,
00287              GLdouble left, GLdouble right,
00288              GLdouble bottom, GLdouble top,
00289              GLdouble zNear, GLdouble zFar)
00290 {
00291    if (!tr)
00292       return;
00293 
00294    tr->Perspective = GL_FALSE;
00295    tr->Left = left;
00296    tr->Right = right;
00297    tr->Bottom = bottom;
00298    tr->Top = top;
00299    tr->Near = zNear;
00300    tr->Far = zFar;
00301 }
00302 
00303 
00304 void trFrustum(TRcontext *tr,
00305                GLdouble left, GLdouble right,
00306                GLdouble bottom, GLdouble top,
00307                GLdouble zNear, GLdouble zFar)
00308 {
00309    if (!tr)
00310       return;
00311 
00312    tr->Perspective = GL_TRUE;
00313    tr->Left = left;
00314    tr->Right = right;
00315    tr->Bottom = bottom;
00316    tr->Top = top;
00317    tr->Near = zNear;
00318    tr->Far = zFar;
00319 }
00320 
00321 
00322 void trPerspective(TRcontext *tr,
00323                    GLdouble fovy, GLdouble aspect,
00324                    GLdouble zNear, GLdouble zFar )
00325 {
00326    GLdouble xmin, xmax, ymin, ymax;
00327    ymax = zNear * tan(fovy * 3.14159265 / 360.0);
00328    ymin = -ymax;
00329    xmin = ymin * aspect;
00330    xmax = ymax * aspect;
00331    trFrustum(tr, xmin, xmax, ymin, ymax, zNear, zFar);
00332 }
00333 
00334 
00335 void trBeginTile(TRcontext *tr)
00336 {
00337    GLint matrixMode;
00338    GLint tileWidth, tileHeight, border;
00339    GLdouble left, right, bottom, top;
00340 
00341    if (!tr)
00342       return;
00343 
00344    if (tr->CurrentTile <= 0) {
00345       Setup(tr);
00346       /* Save user's viewport, will be restored after last tile rendered */
00347       glGetIntegerv(GL_VIEWPORT, tr->ViewportSave);
00348    }
00349 
00350    /* which tile (by row and column) we're about to render */
00351    if (tr->RowOrder==TR_BOTTOM_TO_TOP) {
00352       tr->CurrentRow = tr->CurrentTile / tr->Columns;
00353       tr->CurrentColumn = tr->CurrentTile % tr->Columns;
00354    }
00355    else if (tr->RowOrder==TR_TOP_TO_BOTTOM) {
00356       tr->CurrentRow = tr->Rows - (tr->CurrentTile / tr->Columns) - 1;
00357       tr->CurrentColumn = tr->CurrentTile % tr->Columns;
00358    }
00359    else {
00360       /* This should never happen */
00361       abort();
00362    }
00363    assert(tr->CurrentRow < tr->Rows);
00364    assert(tr->CurrentColumn < tr->Columns);
00365 
00366    border = tr->TileBorder;
00367 
00368    /* Compute actual size of this tile with border */
00369    if (tr->CurrentRow < tr->Rows-1)
00370       tileHeight = tr->TileHeight;
00371    else
00372       tileHeight = tr->ImageHeight - (tr->Rows-1) * (tr->TileHeightNB) + 2 * border;
00373 
00374    if (tr->CurrentColumn < tr->Columns-1)
00375       tileWidth = tr->TileWidth;
00376    else
00377       tileWidth = tr->ImageWidth - (tr->Columns-1) * (tr->TileWidthNB) + 2 * border;
00378 
00379    /* Save tile size, with border */
00380    tr->CurrentTileWidth = tileWidth;
00381    tr->CurrentTileHeight = tileHeight;
00382 
00383    glViewport(0, 0, tileWidth, tileHeight);  /* tile size including border */
00384 
00385    /* save current matrix mode */
00386    glGetIntegerv(GL_MATRIX_MODE, &matrixMode);
00387    glMatrixMode(GL_PROJECTION);
00388    glLoadIdentity();
00389 
00390    /* compute projection parameters */
00391    left = tr->Left + (tr->Right - tr->Left)
00392         * (tr->CurrentColumn * tr->TileWidthNB - border) / tr->ImageWidth;
00393    right = left + (tr->Right - tr->Left) * tileWidth / tr->ImageWidth;
00394    bottom = tr->Bottom + (tr->Top - tr->Bottom)
00395           * (tr->CurrentRow * tr->TileHeightNB - border) / tr->ImageHeight;
00396    top = bottom + (tr->Top - tr->Bottom) * tileHeight / tr->ImageHeight;
00397 
00398    ssgSetFrustum ( left, right, bottom, top, tr->Near, tr->Far );
00399 
00400    /* restore user's matrix mode */
00401    glMatrixMode( (GLenum)matrixMode );
00402 }
00403 
00404 
00405 
00406 int trEndTile(TRcontext *tr)
00407 {
00408    GLint prevRowLength, prevSkipRows, prevSkipPixels /*, prevAlignment */;
00409 
00410    if (!tr)
00411       return 0;
00412 
00413    assert(tr->CurrentTile>=0);
00414 
00415    /* be sure OpenGL rendering is finished */
00416    glFlush();
00417 
00418    /* save current glPixelStore values */
00419    glGetIntegerv(GL_PACK_ROW_LENGTH, &prevRowLength);
00420    glGetIntegerv(GL_PACK_SKIP_ROWS, &prevSkipRows);
00421    glGetIntegerv(GL_PACK_SKIP_PIXELS, &prevSkipPixels);
00422    /*glGetIntegerv(GL_PACK_ALIGNMENT, &prevAlignment);*/
00423 
00424    if (tr->TileBuffer) {
00425       GLint srcX = tr->TileBorder;
00426       GLint srcY = tr->TileBorder;
00427       GLint srcWidth = tr->TileWidthNB;
00428       GLint srcHeight = tr->TileHeightNB;
00429       glReadPixels(srcX, srcY, srcWidth, srcHeight,
00430                    tr->TileFormat, tr->TileType, tr->TileBuffer);
00431    }
00432 
00433    if (tr->ImageBuffer) {
00434       GLint srcX = tr->TileBorder;
00435       GLint srcY = tr->TileBorder;
00436       GLint srcWidth = tr->CurrentTileWidth - 2 * tr->TileBorder;
00437       GLint srcHeight = tr->CurrentTileHeight - 2 * tr->TileBorder;
00438       GLint destX = tr->TileWidthNB * tr->CurrentColumn;
00439       GLint destY = tr->TileHeightNB * tr->CurrentRow;
00440 
00441       /* setup pixel store for glReadPixels */
00442       glPixelStorei(GL_PACK_ROW_LENGTH, tr->ImageWidth);
00443       glPixelStorei(GL_PACK_SKIP_ROWS, destY);
00444       glPixelStorei(GL_PACK_SKIP_PIXELS, destX);
00445       /*glPixelStorei(GL_PACK_ALIGNMENT, 1);*/
00446 
00447       /* read the tile into the final image */
00448       glReadPixels(srcX, srcY, srcWidth, srcHeight,
00449                    tr->ImageFormat, tr->ImageType, tr->ImageBuffer);
00450    }
00451 
00452    /* restore previous glPixelStore values */
00453    glPixelStorei(GL_PACK_ROW_LENGTH, prevRowLength);
00454    glPixelStorei(GL_PACK_SKIP_ROWS, prevSkipRows);
00455    glPixelStorei(GL_PACK_SKIP_PIXELS, prevSkipPixels);
00456    /*glPixelStorei(GL_PACK_ALIGNMENT, prevAlignment);*/
00457 
00458    /* increment tile counter, return 1 if more tiles left to render */
00459    tr->CurrentTile++;
00460    if (tr->CurrentTile >= tr->Rows * tr->Columns) {
00461       /* restore user's viewport */
00462       glViewport(tr->ViewportSave[0], tr->ViewportSave[1],
00463                  tr->ViewportSave[2], tr->ViewportSave[3]);
00464       tr->CurrentTile = -1;  /* all done */
00465       return 0;
00466    }
00467    else
00468       return 1;
00469 }
00470 
00471 
00472 /*
00473  * Replacement for glRastePos3f() which avoids the problem with invalid
00474  * raster pos.
00475  */
00476 void trRasterPos3f(TRcontext *tr, GLfloat x, GLfloat y, GLfloat z)
00477 {
00478    if (tr->CurrentTile<0) {
00479       /* not doing tile rendering right now.  Let OpenGL do this. */
00480       glRasterPos3f(x, y, z);
00481    }
00482    else {
00483       GLdouble modelview[16], proj[16];
00484       GLint viewport[4];
00485       GLdouble winX, winY, winZ;
00486 
00487       /* Get modelview, projection and viewport */
00488       glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
00489       glGetDoublev(GL_PROJECTION_MATRIX, proj);
00490       viewport[0] = 0;
00491       viewport[1] = 0;
00492       viewport[2] = tr->CurrentTileWidth;
00493       viewport[3] = tr->CurrentTileHeight;
00494 
00495       /* Project object coord to window coordinate */
00496       if (gluProject(x, y, z, modelview, proj, viewport, &winX, &winY, &winZ)){
00497 
00498          /* set raster pos to window coord (0,0) */
00499          glMatrixMode(GL_MODELVIEW);
00500          glPushMatrix();
00501          glLoadIdentity();
00502          glMatrixMode(GL_PROJECTION);
00503          glPushMatrix();
00504          glLoadIdentity();
00505          glOrtho(0.0, tr->CurrentTileWidth,
00506                  0.0, tr->CurrentTileHeight, 0.0, 1.0);
00507          glRasterPos3f(0.0, 0.0, -winZ);
00508 
00509          /* Now use empty bitmap to adjust raster position to (winX,winY) */
00510          {
00511             GLubyte bitmap[1] = {0};
00512             glBitmap(1, 1, 0.0, 0.0, winX, winY, bitmap);
00513          }
00514 
00515          /* restore original matrices */
00516          glPopMatrix(); /*proj*/
00517          glMatrixMode(GL_MODELVIEW);
00518          glPopMatrix();
00519       }
00520 #ifdef DEBUG
00521       if (glGetError())
00522          printf("GL error!\n");
00523 #endif
00524    }
00525 }
00526 

Generated on Mon Dec 17 09:30:56 2007 for SimGear by  doxygen 1.5.1