1 /* $Id: tr.c,v 1.9 1998/01/29 16:56:54 brianp Exp $ */
5 * Revision 1.9 1998/01/29 16:56:54 brianp
6 * allow trOrtho() and trFrustum() to be called at any time, minor clean-up
8 * Revision 1.8 1998/01/28 19:47:39 brianp
9 * minor clean-up for C++
11 * Revision 1.7 1997/07/21 17:34:38 brianp
14 * Revision 1.6 1997/07/21 15:47:35 brianp
15 * renamed all "near" and "far" variables
17 * Revision 1.5 1997/04/26 21:23:25 brianp
18 * added trRasterPos3f function
20 * Revision 1.4 1997/04/26 19:59:36 brianp
21 * set CurrentTile to -1 before first tile and after last tile
23 * Revision 1.3 1997/04/22 23:51:15 brianp
24 * added WIN32 header stuff, removed tabs
26 * Revision 1.2 1997/04/19 23:26:10 brianp
29 * Revision 1.1 1997/04/18 21:53:05 brianp
36 * Tiled Rendering library
38 * Copyright (C) Brian Paul
54 #define DEFAULT_TILE_WIDTH 256
55 #define DEFAULT_TILE_HEIGHT 256
56 #define DEFAULT_TILE_BORDER 0
60 /* Final image parameters */
61 GLint ImageWidth
, ImageHeight
;
62 GLenum ImageFormat
, ImageType
;
66 GLint TileWidth
, TileHeight
;
67 GLint TileWidthNB
, TileHeightNB
;
69 GLenum TileFormat
, TileType
;
72 /* Projection parameters */
73 GLboolean Perspective
;
85 GLint CurrentTileWidth
, CurrentTileHeight
;
86 GLint CurrentRow
, CurrentColumn
;
88 GLint ViewportSave
[4];
94 * Misc setup including computing number of tiles (rows and columns).
96 static void Setup(TRcontext
*tr
)
101 tr
->Columns
= (tr
->ImageWidth
+ tr
->TileWidthNB
- 1) / tr
->TileWidthNB
;
102 tr
->Rows
= (tr
->ImageHeight
+ tr
->TileHeightNB
- 1) / tr
->TileHeightNB
;
105 assert(tr
->Columns
>= 0);
106 assert(tr
->Rows
>= 0);
111 TRcontext
*trNew(void)
113 TRcontext
*tr
= (TRcontext
*) calloc(1, sizeof(TRcontext
));
115 tr
->TileWidth
= DEFAULT_TILE_WIDTH
;
116 tr
->TileHeight
= DEFAULT_TILE_HEIGHT
;
117 tr
->TileBorder
= DEFAULT_TILE_BORDER
;
118 tr
->RowOrder
= TR_BOTTOM_TO_TOP
;
119 tr
->CurrentTile
= -1;
121 return (TRcontext
*) tr
;
125 void trDelete(TRcontext
*tr
)
133 void trTileSize(TRcontext
*tr
, GLint width
, GLint height
, GLint border
)
141 assert(width
>= 2*border
);
142 assert(height
>= 2*border
);
144 tr
->TileBorder
= border
;
145 tr
->TileWidth
= width
;
146 tr
->TileHeight
= height
;
147 tr
->TileWidthNB
= width
- 2 * border
;
148 tr
->TileHeightNB
= height
- 2 * border
;
154 void trTileBuffer(TRcontext
*tr
, GLenum format
, GLenum type
, GLvoid
*image
)
159 tr
->TileFormat
= format
;
161 tr
->TileBuffer
= image
;
166 void trImageSize(TRcontext
*tr
, GLint width
, GLint height
)
171 tr
->ImageWidth
= width
;
172 tr
->ImageHeight
= height
;
177 void trImageBuffer(TRcontext
*tr
, GLenum format
, GLenum type
, GLvoid
*image
)
182 tr
->ImageFormat
= format
;
183 tr
->ImageType
= type
;
184 tr
->ImageBuffer
= image
;
188 GLint
trGet(TRcontext
*tr
, TRenum param
)
195 return tr
->TileWidth
;
197 return tr
->TileHeight
;
199 return tr
->TileBorder
;
201 return tr
->ImageWidth
;
202 case TR_IMAGE_HEIGHT
:
203 return tr
->ImageHeight
;
209 if (tr
->CurrentTile
<0)
212 return tr
->CurrentRow
;
213 case TR_CURRENT_COLUMN
:
214 if (tr
->CurrentTile
<0)
217 return tr
->CurrentColumn
;
218 case TR_CURRENT_TILE_WIDTH
:
219 return tr
->CurrentTileWidth
;
220 case TR_CURRENT_TILE_HEIGHT
:
221 return tr
->CurrentTileHeight
;
223 return (GLint
) tr
->RowOrder
;
230 void trRowOrder(TRcontext
*tr
, TRenum order
)
235 if (order
==TR_TOP_TO_BOTTOM
|| order
==TR_BOTTOM_TO_TOP
)
236 tr
->RowOrder
= order
;
240 void trOrtho(TRcontext
*tr
,
241 GLdouble left
, GLdouble right
,
242 GLdouble bottom
, GLdouble top
,
243 GLdouble zNear
, GLdouble zFar
)
248 tr
->Perspective
= GL_FALSE
;
258 void trFrustum(TRcontext
*tr
,
259 GLdouble left
, GLdouble right
,
260 GLdouble bottom
, GLdouble top
,
261 GLdouble zNear
, GLdouble zFar
)
266 tr
->Perspective
= GL_TRUE
;
276 void trPerspective(TRcontext
*tr
,
277 GLdouble fovy
, GLdouble aspect
,
278 GLdouble zNear
, GLdouble zFar
)
280 GLdouble xmin
, xmax
, ymin
, ymax
;
281 ymax
= zNear
* tan(fovy
* 3.14159265 / 360.0);
283 xmin
= ymin
* aspect
;
284 xmax
= ymax
* aspect
;
285 trFrustum(tr
, xmin
, xmax
, ymin
, ymax
, zNear
, zFar
);
289 void trBeginTile(TRcontext
*tr
)
292 GLint tileWidth
, tileHeight
, border
;
293 GLdouble left
, right
, bottom
, top
;
298 if (tr
->CurrentTile
<= 0) {
300 /* Save user's viewport, will be restored after last tile rendered */
301 glGetIntegerv(GL_VIEWPORT
, tr
->ViewportSave
);
304 /* which tile (by row and column) we're about to render */
305 if (tr
->RowOrder
==TR_BOTTOM_TO_TOP
) {
306 tr
->CurrentRow
= tr
->CurrentTile
/ tr
->Columns
;
307 tr
->CurrentColumn
= tr
->CurrentTile
% tr
->Columns
;
309 else if (tr
->RowOrder
==TR_TOP_TO_BOTTOM
) {
310 tr
->CurrentRow
= tr
->Rows
- (tr
->CurrentTile
/ tr
->Columns
) - 1;
311 tr
->CurrentColumn
= tr
->CurrentTile
% tr
->Columns
;
314 /* This should never happen */
317 assert(tr
->CurrentRow
< tr
->Rows
);
318 assert(tr
->CurrentColumn
< tr
->Columns
);
320 border
= tr
->TileBorder
;
322 /* Compute actual size of this tile with border */
323 if (tr
->CurrentRow
< tr
->Rows
-1)
324 tileHeight
= tr
->TileHeight
;
326 tileHeight
= tr
->ImageHeight
- (tr
->Rows
-1) * (tr
->TileHeightNB
) + 2 * border
;
328 if (tr
->CurrentColumn
< tr
->Columns
-1)
329 tileWidth
= tr
->TileWidth
;
331 tileWidth
= tr
->ImageWidth
- (tr
->Columns
-1) * (tr
->TileWidthNB
) + 2 * border
;
333 /* Save tile size, with border */
334 tr
->CurrentTileWidth
= tileWidth
;
335 tr
->CurrentTileHeight
= tileHeight
;
337 glViewport(0, 0, tileWidth
, tileHeight
); /* tile size including border */
339 /* save current matrix mode */
340 glGetIntegerv(GL_MATRIX_MODE
, &matrixMode
);
341 glMatrixMode(GL_PROJECTION
);
344 /* compute projection parameters */
345 left
= tr
->Left
+ (tr
->Right
- tr
->Left
)
346 * (tr
->CurrentColumn
* tr
->TileWidthNB
- border
) / tr
->ImageWidth
;
347 right
= left
+ (tr
->Right
- tr
->Left
) * tileWidth
/ tr
->ImageWidth
;
348 bottom
= tr
->Bottom
+ (tr
->Top
- tr
->Bottom
)
349 * (tr
->CurrentRow
* tr
->TileHeightNB
- border
) / tr
->ImageHeight
;
350 top
= bottom
+ (tr
->Top
- tr
->Bottom
) * tileHeight
/ tr
->ImageHeight
;
353 glFrustum(left
, right
, bottom
, top
, tr
->Near
, tr
->Far
);
355 glOrtho(left
, right
, bottom
, top
, tr
->Near
, tr
->Far
);
357 /* restore user's matrix mode */
358 glMatrixMode(matrixMode
);
363 int trEndTile(TRcontext
*tr
)
365 GLint prevRowLength
, prevSkipRows
, prevSkipPixels
, prevAlignment
;
370 assert(tr
->CurrentTile
>=0);
372 /* be sure OpenGL rendering is finished */
375 /* save current glPixelStore values */
376 glGetIntegerv(GL_PACK_ROW_LENGTH
, &prevRowLength
);
377 glGetIntegerv(GL_PACK_SKIP_ROWS
, &prevSkipRows
);
378 glGetIntegerv(GL_PACK_SKIP_PIXELS
, &prevSkipPixels
);
379 /*glGetIntegerv(GL_PACK_ALIGNMENT, &prevAlignment);*/
381 if (tr
->TileBuffer
) {
382 GLint srcX
= tr
->TileBorder
;
383 GLint srcY
= tr
->TileBorder
;
384 GLint srcWidth
= tr
->TileWidthNB
;
385 GLint srcHeight
= tr
->TileHeightNB
;
386 glReadPixels(srcX
, srcY
, srcWidth
, srcHeight
,
387 tr
->TileFormat
, tr
->TileType
, tr
->TileBuffer
);
390 if (tr
->ImageBuffer
) {
391 GLint srcX
= tr
->TileBorder
;
392 GLint srcY
= tr
->TileBorder
;
393 GLint srcWidth
= tr
->CurrentTileWidth
- 2 * tr
->TileBorder
;
394 GLint srcHeight
= tr
->CurrentTileHeight
- 2 * tr
->TileBorder
;
395 GLint destX
= tr
->TileWidthNB
* tr
->CurrentColumn
;
396 GLint destY
= tr
->TileHeightNB
* tr
->CurrentRow
;
398 /* setup pixel store for glReadPixels */
399 glPixelStorei(GL_PACK_ROW_LENGTH
, tr
->ImageWidth
);
400 glPixelStorei(GL_PACK_SKIP_ROWS
, destY
);
401 glPixelStorei(GL_PACK_SKIP_PIXELS
, destX
);
402 /*glPixelStorei(GL_PACK_ALIGNMENT, 1);*/
404 /* read the tile into the final image */
405 glReadPixels(srcX
, srcY
, srcWidth
, srcHeight
,
406 tr
->ImageFormat
, tr
->ImageType
, tr
->ImageBuffer
);
409 /* restore previous glPixelStore values */
410 glPixelStorei(GL_PACK_ROW_LENGTH
, prevRowLength
);
411 glPixelStorei(GL_PACK_SKIP_ROWS
, prevSkipRows
);
412 glPixelStorei(GL_PACK_SKIP_PIXELS
, prevSkipPixels
);
413 /*glPixelStorei(GL_PACK_ALIGNMENT, prevAlignment);*/
415 /* increment tile counter, return 1 if more tiles left to render */
417 if (tr
->CurrentTile
>= tr
->Rows
* tr
->Columns
) {
418 /* restore user's viewport */
419 glViewport(tr
->ViewportSave
[0], tr
->ViewportSave
[1],
420 tr
->ViewportSave
[2], tr
->ViewportSave
[3]);
421 tr
->CurrentTile
= -1; /* all done */
430 * Replacement for glRastePos3f() which avoids the problem with invalid
433 void trRasterPos3f(TRcontext
*tr
, GLfloat x
, GLfloat y
, GLfloat z
)
435 if (tr
->CurrentTile
<0) {
436 /* not doing tile rendering right now. Let OpenGL do this. */
437 glRasterPos3f(x
, y
, z
);
440 GLdouble modelview
[16], proj
[16];
442 GLdouble winX
, winY
, winZ
;
444 /* Get modelview, projection and viewport */
445 glGetDoublev(GL_MODELVIEW_MATRIX
, modelview
);
446 glGetDoublev(GL_PROJECTION_MATRIX
, proj
);
449 viewport
[2] = tr
->CurrentTileWidth
;
450 viewport
[3] = tr
->CurrentTileHeight
;
452 /* Project object coord to window coordinate */
453 if (gluProject(x
, y
, z
, modelview
, proj
, viewport
, &winX
, &winY
, &winZ
)){
455 /* set raster pos to window coord (0,0) */
456 glMatrixMode(GL_MODELVIEW
);
459 glMatrixMode(GL_PROJECTION
);
462 glOrtho(0.0, tr
->CurrentTileWidth
,
463 0.0, tr
->CurrentTileHeight
, 0.0, 1.0);
464 glRasterPos3f(0.0, 0.0, -winZ
);
466 /* Now use empty bitmap to adjust raster position to (winX,winY) */
468 GLubyte bitmap
[1] = {0};
469 glBitmap(1, 1, 0.0, 0.0, winX
, winY
, bitmap
);
472 /* restore original matrices */
473 glPopMatrix(); /*proj*/
474 glMatrixMode(GL_MODELVIEW
);
479 printf("GL error!\n");