source: git/src/tr.c @ a72ed95

RELEASE/1.2debug-cidebug-ci-sanitisersstereowalls-data
Last change on this file since a72ed95 was 46acc71, checked in by Olly Betts <olly@…>, 12 years ago

src/tr.c,src/tr.h: Committing original versions of tr tiled
rendering code.

git-svn-id: file:///home/survex-svn/survex/trunk@3891 4b37db11-9a0c-4f06-9ece-9ab7cdaee568

  • Property mode set to 100644
File size: 11.7 KB
Line 
1/* $Id: tr.c,v 1.9 1998/01/29 16:56:54 brianp Exp $ */
2
3/*
4 * $Log: tr.c,v $
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
7 *
8 * Revision 1.8  1998/01/28  19:47:39  brianp
9 * minor clean-up for C++
10 *
11 * Revision 1.7  1997/07/21  17:34:38  brianp
12 * added tile borders
13 *
14 * Revision 1.6  1997/07/21  15:47:35  brianp
15 * renamed all "near" and "far" variables
16 *
17 * Revision 1.5  1997/04/26  21:23:25  brianp
18 * added trRasterPos3f function
19 *
20 * Revision 1.4  1997/04/26  19:59:36  brianp
21 * set CurrentTile to -1 before first tile and after last tile
22 *
23 * Revision 1.3  1997/04/22  23:51:15  brianp
24 * added WIN32 header stuff, removed tabs
25 *
26 * Revision 1.2  1997/04/19  23:26:10  brianp
27 * many API changes
28 *
29 * Revision 1.1  1997/04/18  21:53:05  brianp
30 * Initial revision
31 *
32 */
33
34
35/*
36 * Tiled Rendering library
37 * Version 1.1
38 * Copyright (C) Brian Paul
39 */
40
41
42#include <assert.h>
43#include <math.h>
44#include <stdlib.h>
45#include <stdio.h>
46#ifdef WIN32
47#include <windows.h>
48#endif
49#include <GL/gl.h>
50#include <GL/glu.h>
51#include "tr.h"
52
53
54#define DEFAULT_TILE_WIDTH  256
55#define DEFAULT_TILE_HEIGHT 256
56#define DEFAULT_TILE_BORDER 0
57
58
59struct _TRctx {
60   /* Final image parameters */
61   GLint ImageWidth, ImageHeight;
62   GLenum ImageFormat, ImageType;
63   GLvoid *ImageBuffer;
64
65   /* Tile parameters */
66   GLint TileWidth, TileHeight;
67   GLint TileWidthNB, TileHeightNB;
68   GLint TileBorder;
69   GLenum TileFormat, TileType;
70   GLvoid *TileBuffer;
71
72   /* Projection parameters */
73   GLboolean Perspective;
74   GLdouble Left;
75   GLdouble Right;
76   GLdouble Bottom;
77   GLdouble Top;
78   GLdouble Near;
79   GLdouble Far;
80
81   /* Misc */
82   TRenum RowOrder;
83   GLint Rows, Columns;
84   GLint CurrentTile;
85   GLint CurrentTileWidth, CurrentTileHeight;
86   GLint CurrentRow, CurrentColumn;
87
88   GLint ViewportSave[4];
89};
90
91
92
93/*
94 * Misc setup including computing number of tiles (rows and columns).
95 */
96static void Setup(TRcontext *tr)
97{
98   if (!tr)
99      return;
100
101   tr->Columns = (tr->ImageWidth + tr->TileWidthNB - 1) / tr->TileWidthNB;
102   tr->Rows = (tr->ImageHeight + tr->TileHeightNB - 1) / tr->TileHeightNB;
103   tr->CurrentTile = 0;
104
105   assert(tr->Columns >= 0);
106   assert(tr->Rows >= 0);
107}
108
109
110
111TRcontext *trNew(void)
112{
113   TRcontext *tr = (TRcontext *) calloc(1, sizeof(TRcontext));
114   if (tr) {
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;
120   }
121   return (TRcontext *) tr;
122}
123
124
125void trDelete(TRcontext *tr)
126{
127   if (tr)
128      free(tr);
129}
130
131
132
133void trTileSize(TRcontext *tr, GLint width, GLint height, GLint border)
134{
135   if (!tr)
136      return;
137
138   assert(border >= 0);
139   assert(width >= 1);
140   assert(height >= 1);
141   assert(width >= 2*border);
142   assert(height >= 2*border);
143
144   tr->TileBorder = border;
145   tr->TileWidth = width;
146   tr->TileHeight = height;
147   tr->TileWidthNB = width - 2 * border;
148   tr->TileHeightNB = height - 2 * border;
149   Setup(tr);
150}
151
152
153
154void trTileBuffer(TRcontext *tr, GLenum format, GLenum type, GLvoid *image)
155{
156   if (!tr)
157      return;
158
159   tr->TileFormat = format;
160   tr->TileType = type;
161   tr->TileBuffer = image;
162}
163
164
165
166void trImageSize(TRcontext *tr, GLint width, GLint height)
167{
168   if (!tr)
169      return;
170
171   tr->ImageWidth = width;
172   tr->ImageHeight = height;
173   Setup(tr);
174}
175
176
177void trImageBuffer(TRcontext *tr, GLenum format, GLenum type, GLvoid *image)
178{
179   if (!tr)
180      return;
181
182   tr->ImageFormat = format;
183   tr->ImageType = type;
184   tr->ImageBuffer = image;
185}
186
187
188GLint trGet(TRcontext *tr, TRenum param)
189{
190   if (!tr)
191      return 0;
192
193   switch (param) {
194      case TR_TILE_WIDTH:
195         return tr->TileWidth;
196      case TR_TILE_HEIGHT:
197         return tr->TileHeight;
198      case TR_TILE_BORDER:
199         return tr->TileBorder;
200      case TR_IMAGE_WIDTH:
201         return tr->ImageWidth;
202      case TR_IMAGE_HEIGHT:
203         return tr->ImageHeight;
204      case TR_ROWS:
205         return tr->Rows;
206      case TR_COLUMNS:
207         return tr->Columns;
208      case TR_CURRENT_ROW:
209         if (tr->CurrentTile<0)
210            return -1;
211         else
212            return tr->CurrentRow;
213      case TR_CURRENT_COLUMN:
214         if (tr->CurrentTile<0)
215            return -1;
216         else
217            return tr->CurrentColumn;
218      case TR_CURRENT_TILE_WIDTH:
219         return tr->CurrentTileWidth;
220      case TR_CURRENT_TILE_HEIGHT:
221         return tr->CurrentTileHeight;
222      case TR_ROW_ORDER:
223         return (GLint) tr->RowOrder;
224      default:
225         return 0;
226   }
227}
228
229
230void trRowOrder(TRcontext *tr, TRenum order)
231{
232   if (!tr)
233      return;
234
235   if (order==TR_TOP_TO_BOTTOM || order==TR_BOTTOM_TO_TOP)
236      tr->RowOrder = order;
237}
238
239
240void trOrtho(TRcontext *tr,
241             GLdouble left, GLdouble right,
242             GLdouble bottom, GLdouble top,
243             GLdouble zNear, GLdouble zFar)
244{
245   if (!tr)
246      return;
247
248   tr->Perspective = GL_FALSE;
249   tr->Left = left;
250   tr->Right = right;
251   tr->Bottom = bottom;
252   tr->Top = top;
253   tr->Near = zNear;
254   tr->Far = zFar;
255}
256
257
258void trFrustum(TRcontext *tr,
259               GLdouble left, GLdouble right,
260               GLdouble bottom, GLdouble top,
261               GLdouble zNear, GLdouble zFar)
262{
263   if (!tr)
264      return;
265
266   tr->Perspective = GL_TRUE;
267   tr->Left = left;
268   tr->Right = right;
269   tr->Bottom = bottom;
270   tr->Top = top;
271   tr->Near = zNear;
272   tr->Far = zFar;
273}
274
275
276void trPerspective(TRcontext *tr,
277                   GLdouble fovy, GLdouble aspect,
278                   GLdouble zNear, GLdouble zFar )
279{
280   GLdouble xmin, xmax, ymin, ymax;
281   ymax = zNear * tan(fovy * 3.14159265 / 360.0);
282   ymin = -ymax;
283   xmin = ymin * aspect;
284   xmax = ymax * aspect;
285   trFrustum(tr, xmin, xmax, ymin, ymax, zNear, zFar);
286}
287
288
289void trBeginTile(TRcontext *tr)
290{
291   GLint matrixMode;
292   GLint tileWidth, tileHeight, border;
293   GLdouble left, right, bottom, top;
294
295   if (!tr)
296      return;
297
298   if (tr->CurrentTile <= 0) {
299      Setup(tr);
300      /* Save user's viewport, will be restored after last tile rendered */
301      glGetIntegerv(GL_VIEWPORT, tr->ViewportSave);
302   }
303
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;
308   }
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;
312   }
313   else {
314      /* This should never happen */
315      abort();
316   }
317   assert(tr->CurrentRow < tr->Rows);
318   assert(tr->CurrentColumn < tr->Columns);
319
320   border = tr->TileBorder;
321
322   /* Compute actual size of this tile with border */
323   if (tr->CurrentRow < tr->Rows-1)
324      tileHeight = tr->TileHeight;
325   else
326      tileHeight = tr->ImageHeight - (tr->Rows-1) * (tr->TileHeightNB) + 2 * border;
327
328   if (tr->CurrentColumn < tr->Columns-1)
329      tileWidth = tr->TileWidth;
330   else
331      tileWidth = tr->ImageWidth - (tr->Columns-1) * (tr->TileWidthNB) + 2 * border;
332
333   /* Save tile size, with border */
334   tr->CurrentTileWidth = tileWidth;
335   tr->CurrentTileHeight = tileHeight;
336
337   glViewport(0, 0, tileWidth, tileHeight);  /* tile size including border */
338
339   /* save current matrix mode */
340   glGetIntegerv(GL_MATRIX_MODE, &matrixMode);
341   glMatrixMode(GL_PROJECTION);
342   glLoadIdentity();
343
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;
351
352   if (tr->Perspective)
353      glFrustum(left, right, bottom, top, tr->Near, tr->Far);
354   else
355      glOrtho(left, right, bottom, top, tr->Near, tr->Far);
356
357   /* restore user's matrix mode */
358   glMatrixMode(matrixMode);
359}
360
361
362
363int trEndTile(TRcontext *tr)
364{
365   GLint prevRowLength, prevSkipRows, prevSkipPixels, prevAlignment;
366
367   if (!tr)
368      return 0;
369
370   assert(tr->CurrentTile>=0);
371
372   /* be sure OpenGL rendering is finished */
373   glFlush();
374
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);*/
380
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);
388   }
389
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;
397
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);*/
403
404      /* read the tile into the final image */
405      glReadPixels(srcX, srcY, srcWidth, srcHeight,
406                   tr->ImageFormat, tr->ImageType, tr->ImageBuffer);
407   }
408
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);*/
414
415   /* increment tile counter, return 1 if more tiles left to render */
416   tr->CurrentTile++;
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 */
422      return 0;
423   }
424   else
425      return 1;
426}
427
428
429/*
430 * Replacement for glRastePos3f() which avoids the problem with invalid
431 * raster pos.
432 */
433void trRasterPos3f(TRcontext *tr, GLfloat x, GLfloat y, GLfloat z)
434{
435   if (tr->CurrentTile<0) {
436      /* not doing tile rendering right now.  Let OpenGL do this. */
437      glRasterPos3f(x, y, z);
438   }
439   else {
440      GLdouble modelview[16], proj[16];
441      GLint viewport[4];
442      GLdouble winX, winY, winZ;
443
444      /* Get modelview, projection and viewport */
445      glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
446      glGetDoublev(GL_PROJECTION_MATRIX, proj);
447      viewport[0] = 0;
448      viewport[1] = 0;
449      viewport[2] = tr->CurrentTileWidth;
450      viewport[3] = tr->CurrentTileHeight;
451
452      /* Project object coord to window coordinate */
453      if (gluProject(x, y, z, modelview, proj, viewport, &winX, &winY, &winZ)){
454
455         /* set raster pos to window coord (0,0) */
456         glMatrixMode(GL_MODELVIEW);
457         glPushMatrix();
458         glLoadIdentity();
459         glMatrixMode(GL_PROJECTION);
460         glPushMatrix();
461         glLoadIdentity();
462         glOrtho(0.0, tr->CurrentTileWidth,
463                 0.0, tr->CurrentTileHeight, 0.0, 1.0);
464         glRasterPos3f(0.0, 0.0, -winZ);
465
466         /* Now use empty bitmap to adjust raster position to (winX,winY) */
467         {
468            GLubyte bitmap[1] = {0};
469            glBitmap(1, 1, 0.0, 0.0, winX, winY, bitmap);
470         }
471
472         /* restore original matrices */
473         glPopMatrix(); /*proj*/
474         glMatrixMode(GL_MODELVIEW);
475         glPopMatrix();
476      }
477#ifdef DEBUG
478      if (glGetError())
479         printf("GL error!\n");
480#endif
481   }
482}
483
Note: See TracBrowser for help on using the repository browser.