]> git.mxchange.org Git - simgear.git/blob - simgear/screen/tr.cxx
Actually commit the code changes which impliment a "scale" animation type.
[simgear.git] / simgear / screen / tr.cxx
1 /* $Id$ */
2
3 /*
4  * $Log$
5  * Revision 1.1  2002/09/07 02:58:19  curt
6  * Initial revision
7  *
8  * Revision 1.3  2001/07/30 20:34:21  curt
9  * Various MSVC fixes.
10  *
11  * Revision 1.2  2001/06/27 02:48:01  curt
12  * Fixed a type conversion bug that could trip up some of the pickier compilers
13  * out there.
14  *
15  * Revision 1.1  2001/06/26 15:19:39  curt
16  * Added tr.cxx / tr.h, Brian Paul's LGPL'd tiled rendering support libs for
17  * rendering ultra high res "tiled" screen shots.
18  *
19  * Revision 1.9  1998/01/29  16:56:54  brianp
20  * allow trOrtho() and trFrustum() to be called at any time, minor clean-up
21  *
22  * Revision 1.8  1998/01/28  19:47:39  brianp
23  * minor clean-up for C++
24  *
25  * Revision 1.7  1997/07/21  17:34:38  brianp
26  * added tile borders
27  *
28  * Revision 1.6  1997/07/21  15:47:35  brianp
29  * renamed all "near" and "far" variables
30  *
31  * Revision 1.5  1997/04/26  21:23:25  brianp
32  * added trRasterPos3f function
33  *
34  * Revision 1.4  1997/04/26  19:59:36  brianp
35  * set CurrentTile to -1 before first tile and after last tile
36  *
37  * Revision 1.3  1997/04/22  23:51:15  brianp
38  * added WIN32 header stuff, removed tabs
39  *
40  * Revision 1.2  1997/04/19  23:26:10  brianp
41  * many API changes
42  *
43  * Revision 1.1  1997/04/18  21:53:05  brianp
44  * Initial revision
45  *
46  */
47
48
49 /*
50  * Tiled Rendering library
51  * Version 1.1
52  * Copyright (C) Brian Paul
53  */
54
55
56 #include <simgear/compiler.h>
57
58 #include <assert.h>
59 #include <math.h>
60 #include <stdlib.h>
61 #include <stdio.h>
62 #ifdef WIN32
63 #include <windows.h>
64 #endif
65 #include <GL/gl.h>
66 #include <GL/glu.h>
67 #include <plib/ssg.h>
68 #include "tr.h"
69
70
71 #define DEFAULT_TILE_WIDTH  256
72 #define DEFAULT_TILE_HEIGHT 256
73 #define DEFAULT_TILE_BORDER 0
74
75
76 struct _TRctx {
77    /* Final image parameters */
78    GLint ImageWidth, ImageHeight;
79    GLenum ImageFormat, ImageType;
80    GLvoid *ImageBuffer;
81
82    /* Tile parameters */
83    GLint TileWidth, TileHeight;
84    GLint TileWidthNB, TileHeightNB;
85    GLint TileBorder;
86    GLenum TileFormat, TileType;
87    GLvoid *TileBuffer;
88
89    /* Projection parameters */
90    GLboolean Perspective;
91    GLdouble Left;
92    GLdouble Right;
93    GLdouble Bottom;
94    GLdouble Top;
95    GLdouble Near;
96    GLdouble Far;
97
98    /* Misc */
99    TRenum RowOrder;
100    GLint Rows, Columns;
101    GLint CurrentTile;
102    GLint CurrentTileWidth, CurrentTileHeight;
103    GLint CurrentRow, CurrentColumn;
104
105    GLint ViewportSave[4];
106 };
107
108
109
110 /*
111  * Misc setup including computing number of tiles (rows and columns).
112  */
113 static void Setup(TRcontext *tr)
114 {
115    if (!tr)
116       return;
117
118    tr->Columns = (tr->ImageWidth + tr->TileWidthNB - 1) / tr->TileWidthNB;
119    tr->Rows = (tr->ImageHeight + tr->TileHeightNB - 1) / tr->TileHeightNB;
120    tr->CurrentTile = 0;
121
122    assert(tr->Columns >= 0);
123    assert(tr->Rows >= 0);
124 }
125
126
127
128 TRcontext *trNew(void)
129 {
130    TRcontext *tr = (TRcontext *) calloc(1, sizeof(TRcontext));
131    if (tr) {
132       tr->TileWidth = DEFAULT_TILE_WIDTH;
133       tr->TileHeight = DEFAULT_TILE_HEIGHT;
134       tr->TileBorder = DEFAULT_TILE_BORDER;
135       tr->RowOrder = TR_BOTTOM_TO_TOP;
136       tr->CurrentTile = -1;
137    }
138    return (TRcontext *) tr;
139 }
140
141
142 void trDelete(TRcontext *tr)
143 {
144    if (tr)
145       free(tr);
146 }
147
148
149
150 void trTileSize(TRcontext *tr, GLint width, GLint height, GLint border)
151 {
152    if (!tr)
153       return;
154
155    assert(border >= 0);
156    assert(width >= 1);
157    assert(height >= 1);
158    assert(width >= 2*border);
159    assert(height >= 2*border);
160
161    tr->TileBorder = border;
162    tr->TileWidth = width;
163    tr->TileHeight = height;
164    tr->TileWidthNB = width - 2 * border;
165    tr->TileHeightNB = height - 2 * border;
166    Setup(tr);
167 }
168
169
170
171 void trTileBuffer(TRcontext *tr, GLenum format, GLenum type, GLvoid *image)
172 {
173    if (!tr)
174       return;
175
176    tr->TileFormat = format;
177    tr->TileType = type;
178    tr->TileBuffer = image;
179 }
180
181
182
183 void trImageSize(TRcontext *tr, GLint width, GLint height)
184 {
185    if (!tr)
186       return;
187
188    tr->ImageWidth = width;
189    tr->ImageHeight = height;
190    Setup(tr);
191 }
192
193
194 void trImageBuffer(TRcontext *tr, GLenum format, GLenum type, GLvoid *image)
195 {
196    if (!tr)
197       return;
198
199    tr->ImageFormat = format;
200    tr->ImageType = type;
201    tr->ImageBuffer = image;
202 }
203
204
205 GLint trGet(TRcontext *tr, TRenum param)
206 {
207    if (!tr)
208       return 0;
209    switch (param) {
210       case TR_TILE_WIDTH:
211          return tr->TileWidth;
212       case TR_TILE_HEIGHT:
213          return tr->TileHeight;
214       case TR_TILE_BORDER:
215          return tr->TileBorder;
216       case TR_IMAGE_WIDTH:
217          return tr->ImageWidth;
218       case TR_IMAGE_HEIGHT:
219          return tr->ImageHeight;
220       case TR_ROWS:
221          return tr->Rows;
222       case TR_COLUMNS:
223          return tr->Columns;
224       case TR_CURRENT_ROW:
225          if (tr->CurrentTile<0)
226             return -1;
227          else
228             return tr->CurrentRow;
229       case TR_CURRENT_COLUMN:
230          if (tr->CurrentTile<0)
231             return -1;
232          else
233             return tr->CurrentColumn;
234       case TR_CURRENT_TILE_WIDTH:
235          return tr->CurrentTileWidth;
236       case TR_CURRENT_TILE_HEIGHT:
237          return tr->CurrentTileHeight;
238       case TR_ROW_ORDER:
239          return (GLint) tr->RowOrder;
240       default:
241          return 0;
242    }
243 }
244
245 GLdouble trGetD(TRcontext *tr, TRenum param)
246 {
247         if (!tr)
248                 return 0.0;
249         switch (param) {
250         case TR_LEFT:
251                 return tr->Left;
252         case TR_RIGHT:
253                 return tr->Right;
254         case TR_BOTTOM:
255                 return tr->Bottom;
256         case TR_TOP:
257                 return tr->Top;
258         case TR_NEAR:
259                 return tr->Near;
260         case TR_FAR:
261                 return tr->Far;
262         default:
263                 return 0.0;
264         }
265 }
266
267 void trRowOrder(TRcontext *tr, TRenum order)
268 {
269    if (!tr)
270       return;
271
272    if (order==TR_TOP_TO_BOTTOM || order==TR_BOTTOM_TO_TOP)
273       tr->RowOrder = order;
274 }
275
276
277 void trOrtho(TRcontext *tr,
278              GLdouble left, GLdouble right,
279              GLdouble bottom, GLdouble top,
280              GLdouble zNear, GLdouble zFar)
281 {
282    if (!tr)
283       return;
284
285    tr->Perspective = GL_FALSE;
286    tr->Left = left;
287    tr->Right = right;
288    tr->Bottom = bottom;
289    tr->Top = top;
290    tr->Near = zNear;
291    tr->Far = zFar;
292 }
293
294
295 void trFrustum(TRcontext *tr,
296                GLdouble left, GLdouble right,
297                GLdouble bottom, GLdouble top,
298                GLdouble zNear, GLdouble zFar)
299 {
300    if (!tr)
301       return;
302
303    tr->Perspective = GL_TRUE;
304    tr->Left = left;
305    tr->Right = right;
306    tr->Bottom = bottom;
307    tr->Top = top;
308    tr->Near = zNear;
309    tr->Far = zFar;
310 }
311
312
313 void trPerspective(TRcontext *tr,
314                    GLdouble fovy, GLdouble aspect,
315                    GLdouble zNear, GLdouble zFar )
316 {
317    GLdouble xmin, xmax, ymin, ymax;
318    ymax = zNear * tan(fovy * 3.14159265 / 360.0);
319    ymin = -ymax;
320    xmin = ymin * aspect;
321    xmax = ymax * aspect;
322    trFrustum(tr, xmin, xmax, ymin, ymax, zNear, zFar);
323 }
324
325
326 void trBeginTile(TRcontext *tr)
327 {
328    GLint matrixMode;
329    GLint tileWidth, tileHeight, border;
330    GLdouble left, right, bottom, top;
331
332    if (!tr)
333       return;
334
335    if (tr->CurrentTile <= 0) {
336       Setup(tr);
337       /* Save user's viewport, will be restored after last tile rendered */
338       glGetIntegerv(GL_VIEWPORT, tr->ViewportSave);
339    }
340
341    /* which tile (by row and column) we're about to render */
342    if (tr->RowOrder==TR_BOTTOM_TO_TOP) {
343       tr->CurrentRow = tr->CurrentTile / tr->Columns;
344       tr->CurrentColumn = tr->CurrentTile % tr->Columns;
345    }
346    else if (tr->RowOrder==TR_TOP_TO_BOTTOM) {
347       tr->CurrentRow = tr->Rows - (tr->CurrentTile / tr->Columns) - 1;
348       tr->CurrentColumn = tr->CurrentTile % tr->Columns;
349    }
350    else {
351       /* This should never happen */
352       abort();
353    }
354    assert(tr->CurrentRow < tr->Rows);
355    assert(tr->CurrentColumn < tr->Columns);
356
357    border = tr->TileBorder;
358
359    /* Compute actual size of this tile with border */
360    if (tr->CurrentRow < tr->Rows-1)
361       tileHeight = tr->TileHeight;
362    else
363       tileHeight = tr->ImageHeight - (tr->Rows-1) * (tr->TileHeightNB) + 2 * border;
364
365    if (tr->CurrentColumn < tr->Columns-1)
366       tileWidth = tr->TileWidth;
367    else
368       tileWidth = tr->ImageWidth - (tr->Columns-1) * (tr->TileWidthNB) + 2 * border;
369
370    /* Save tile size, with border */
371    tr->CurrentTileWidth = tileWidth;
372    tr->CurrentTileHeight = tileHeight;
373
374    glViewport(0, 0, tileWidth, tileHeight);  /* tile size including border */
375
376    /* save current matrix mode */
377    glGetIntegerv(GL_MATRIX_MODE, &matrixMode);
378    glMatrixMode(GL_PROJECTION);
379    glLoadIdentity();
380
381    /* compute projection parameters */
382    left = tr->Left + (tr->Right - tr->Left)
383         * (tr->CurrentColumn * tr->TileWidthNB - border) / tr->ImageWidth;
384    right = left + (tr->Right - tr->Left) * tileWidth / tr->ImageWidth;
385    bottom = tr->Bottom + (tr->Top - tr->Bottom)
386           * (tr->CurrentRow * tr->TileHeightNB - border) / tr->ImageHeight;
387    top = bottom + (tr->Top - tr->Bottom) * tileHeight / tr->ImageHeight;
388
389    ssgSetFrustum ( left, right, bottom, top, tr->Near, tr->Far );
390
391    /* restore user's matrix mode */
392    glMatrixMode( (GLenum)matrixMode );
393 }
394
395
396
397 int trEndTile(TRcontext *tr)
398 {
399    GLint prevRowLength, prevSkipRows, prevSkipPixels /*, prevAlignment */;
400
401    if (!tr)
402       return 0;
403
404    assert(tr->CurrentTile>=0);
405
406    /* be sure OpenGL rendering is finished */
407    glFlush();
408
409    /* save current glPixelStore values */
410    glGetIntegerv(GL_PACK_ROW_LENGTH, &prevRowLength);
411    glGetIntegerv(GL_PACK_SKIP_ROWS, &prevSkipRows);
412    glGetIntegerv(GL_PACK_SKIP_PIXELS, &prevSkipPixels);
413    /*glGetIntegerv(GL_PACK_ALIGNMENT, &prevAlignment);*/
414
415    if (tr->TileBuffer) {
416       GLint srcX = tr->TileBorder;
417       GLint srcY = tr->TileBorder;
418       GLint srcWidth = tr->TileWidthNB;
419       GLint srcHeight = tr->TileHeightNB;
420       glReadPixels(srcX, srcY, srcWidth, srcHeight,
421                    tr->TileFormat, tr->TileType, tr->TileBuffer);
422    }
423
424    if (tr->ImageBuffer) {
425       GLint srcX = tr->TileBorder;
426       GLint srcY = tr->TileBorder;
427       GLint srcWidth = tr->CurrentTileWidth - 2 * tr->TileBorder;
428       GLint srcHeight = tr->CurrentTileHeight - 2 * tr->TileBorder;
429       GLint destX = tr->TileWidthNB * tr->CurrentColumn;
430       GLint destY = tr->TileHeightNB * tr->CurrentRow;
431
432       /* setup pixel store for glReadPixels */
433       glPixelStorei(GL_PACK_ROW_LENGTH, tr->ImageWidth);
434       glPixelStorei(GL_PACK_SKIP_ROWS, destY);
435       glPixelStorei(GL_PACK_SKIP_PIXELS, destX);
436       /*glPixelStorei(GL_PACK_ALIGNMENT, 1);*/
437
438       /* read the tile into the final image */
439       glReadPixels(srcX, srcY, srcWidth, srcHeight,
440                    tr->ImageFormat, tr->ImageType, tr->ImageBuffer);
441    }
442
443    /* restore previous glPixelStore values */
444    glPixelStorei(GL_PACK_ROW_LENGTH, prevRowLength);
445    glPixelStorei(GL_PACK_SKIP_ROWS, prevSkipRows);
446    glPixelStorei(GL_PACK_SKIP_PIXELS, prevSkipPixels);
447    /*glPixelStorei(GL_PACK_ALIGNMENT, prevAlignment);*/
448
449    /* increment tile counter, return 1 if more tiles left to render */
450    tr->CurrentTile++;
451    if (tr->CurrentTile >= tr->Rows * tr->Columns) {
452       /* restore user's viewport */
453       glViewport(tr->ViewportSave[0], tr->ViewportSave[1],
454                  tr->ViewportSave[2], tr->ViewportSave[3]);
455       tr->CurrentTile = -1;  /* all done */
456       return 0;
457    }
458    else
459       return 1;
460 }
461
462
463 /*
464  * Replacement for glRastePos3f() which avoids the problem with invalid
465  * raster pos.
466  */
467 void trRasterPos3f(TRcontext *tr, GLfloat x, GLfloat y, GLfloat z)
468 {
469    if (tr->CurrentTile<0) {
470       /* not doing tile rendering right now.  Let OpenGL do this. */
471       glRasterPos3f(x, y, z);
472    }
473    else {
474       GLdouble modelview[16], proj[16];
475       GLint viewport[4];
476       GLdouble winX, winY, winZ;
477
478       /* Get modelview, projection and viewport */
479       glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
480       glGetDoublev(GL_PROJECTION_MATRIX, proj);
481       viewport[0] = 0;
482       viewport[1] = 0;
483       viewport[2] = tr->CurrentTileWidth;
484       viewport[3] = tr->CurrentTileHeight;
485
486       /* Project object coord to window coordinate */
487       if (gluProject(x, y, z, modelview, proj, viewport, &winX, &winY, &winZ)){
488
489          /* set raster pos to window coord (0,0) */
490          glMatrixMode(GL_MODELVIEW);
491          glPushMatrix();
492          glLoadIdentity();
493          glMatrixMode(GL_PROJECTION);
494          glPushMatrix();
495          glLoadIdentity();
496          glOrtho(0.0, tr->CurrentTileWidth,
497                  0.0, tr->CurrentTileHeight, 0.0, 1.0);
498          glRasterPos3f(0.0, 0.0, -winZ);
499
500          /* Now use empty bitmap to adjust raster position to (winX,winY) */
501          {
502             GLubyte bitmap[1] = {0};
503             glBitmap(1, 1, 0.0, 0.0, winX, winY, bitmap);
504          }
505
506          /* restore original matrices */
507          glPopMatrix(); /*proj*/
508          glMatrixMode(GL_MODELVIEW);
509          glPopMatrix();
510       }
511 #ifdef DEBUG
512       if (glGetError())
513          printf("GL error!\n");
514 #endif
515    }
516 }
517