head 1.4; access; symbols; locks; strict; comment @# @; 1.4 date 2002.09.07.01.50.41; author curt; state Exp; branches; next 1.3; 1.3 date 2002.08.31.19.01.59; author curt; state Exp; branches; next 1.2; 1.2 date 2002.08.31.18.54.05; author curt; state Exp; branches; next 1.1; 1.1 date 2002.02.15.17.22.02; author curt; state Exp; branches; next ; desc @@ 1.4 log @Updated doxygen docs. @ text @
Main Page Class Hierarchy Compound List File List Compound Members File Members

# tr.cxx

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

@ 1.3 log @Oops, try again. @ text @d523 1 a523 1