00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
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
00087 GLint ImageWidth, ImageHeight;
00088 GLenum ImageFormat, ImageType;
00089 GLvoid *ImageBuffer;
00090
00091
00092 GLint TileWidth, TileHeight;
00093 GLint TileWidthNB, TileHeightNB;
00094 GLint TileBorder;
00095 GLenum TileFormat, TileType;
00096 GLvoid *TileBuffer;
00097
00098
00099 GLboolean Perspective;
00100 GLdouble Left;
00101 GLdouble Right;
00102 GLdouble Bottom;
00103 GLdouble Top;
00104 GLdouble Near;
00105 GLdouble Far;
00106
00107
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
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
00347 glGetIntegerv(GL_VIEWPORT, tr->ViewportSave);
00348 }
00349
00350
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
00361 abort();
00362 }
00363 assert(tr->CurrentRow < tr->Rows);
00364 assert(tr->CurrentColumn < tr->Columns);
00365
00366 border = tr->TileBorder;
00367
00368
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
00380 tr->CurrentTileWidth = tileWidth;
00381 tr->CurrentTileHeight = tileHeight;
00382
00383 glViewport(0, 0, tileWidth, tileHeight);
00384
00385
00386 glGetIntegerv(GL_MATRIX_MODE, &matrixMode);
00387 glMatrixMode(GL_PROJECTION);
00388 glLoadIdentity();
00389
00390
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
00401 glMatrixMode( (GLenum)matrixMode );
00402 }
00403
00404
00405
00406 int trEndTile(TRcontext *tr)
00407 {
00408 GLint prevRowLength, prevSkipRows, prevSkipPixels ;
00409
00410 if (!tr)
00411 return 0;
00412
00413 assert(tr->CurrentTile>=0);
00414
00415
00416 glFlush();
00417
00418
00419 glGetIntegerv(GL_PACK_ROW_LENGTH, &prevRowLength);
00420 glGetIntegerv(GL_PACK_SKIP_ROWS, &prevSkipRows);
00421 glGetIntegerv(GL_PACK_SKIP_PIXELS, &prevSkipPixels);
00422
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
00442 glPixelStorei(GL_PACK_ROW_LENGTH, tr->ImageWidth);
00443 glPixelStorei(GL_PACK_SKIP_ROWS, destY);
00444 glPixelStorei(GL_PACK_SKIP_PIXELS, destX);
00445
00446
00447
00448 glReadPixels(srcX, srcY, srcWidth, srcHeight,
00449 tr->ImageFormat, tr->ImageType, tr->ImageBuffer);
00450 }
00451
00452
00453 glPixelStorei(GL_PACK_ROW_LENGTH, prevRowLength);
00454 glPixelStorei(GL_PACK_SKIP_ROWS, prevSkipRows);
00455 glPixelStorei(GL_PACK_SKIP_PIXELS, prevSkipPixels);
00456
00457
00458
00459 tr->CurrentTile++;
00460 if (tr->CurrentTile >= tr->Rows * tr->Columns) {
00461
00462 glViewport(tr->ViewportSave[0], tr->ViewportSave[1],
00463 tr->ViewportSave[2], tr->ViewportSave[3]);
00464 tr->CurrentTile = -1;
00465 return 0;
00466 }
00467 else
00468 return 1;
00469 }
00470
00471
00472
00473
00474
00475
00476 void trRasterPos3f(TRcontext *tr, GLfloat x, GLfloat y, GLfloat z)
00477 {
00478 if (tr->CurrentTile<0) {
00479
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
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
00496 if (gluProject(x, y, z, modelview, proj, viewport, &winX, &winY, &winZ)){
00497
00498
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
00510 {
00511 GLubyte bitmap[1] = {0};
00512 glBitmap(1, 1, 0.0, 0.0, winX, winY, bitmap);
00513 }
00514
00515
00516 glPopMatrix();
00517 glMatrixMode(GL_MODELVIEW);
00518 glPopMatrix();
00519 }
00520 #ifdef DEBUG
00521 if (glGetError())
00522 printf("GL error!\n");
00523 #endif
00524 }
00525 }
00526