- this exposed a bizarre issue on Mac where dragging in <AGL/agl.h> in extensions.hxx was pulling in all of Carbon to the global namespace - very scary. As a result, I now need to explicitly include CoreFoundation in fg_init.cxx. - change SG_USING_STD(x) to using std::x Issues: - the logic for X11 and Win32 in RenderTexture and extensions is tortured, please see if you agree I got all the ifdefs correct.
600 lines
16 KiB
C++
600 lines
16 KiB
C++
/* $Id$ */
|
|
|
|
/*
|
|
* $Log$
|
|
* Revision 1.5 2008/07/27 16:10:37 ehofman
|
|
*
|
|
*
|
|
* - remove the SG_GLxxxx_H #defines, since OSG provides its own versions
|
|
* - this exposed a bizarre issue on Mac where dragging in <AGL/agl.h> in
|
|
* extensions.hxx was pulling in all of Carbon to the global namespace
|
|
* - very scary. As a result, I now need to explicitly include CoreFoundation
|
|
* in fg_init.cxx.
|
|
* - change SG_USING_STD(x) to using std::x
|
|
*
|
|
* Issues:
|
|
*
|
|
* - the logic for X11 and Win32 in RenderTexture and extensions is tortured,
|
|
* please see if you agree I got all the ifdefs correct.
|
|
*
|
|
* Revision 1.4 2006/10/29 19:27:11 frohlich
|
|
* Modified Files:
|
|
* configure.ac simgear/environment/visual_enviro.cxx
|
|
* simgear/ephemeris/ephemeris.cxx
|
|
* simgear/ephemeris/ephemeris.hxx simgear/ephemeris/stardata.cxx
|
|
* simgear/ephemeris/stardata.hxx simgear/math/SGMatrix.hxx
|
|
* simgear/math/SGQuat.hxx simgear/math/SGVec3.hxx
|
|
* simgear/math/SGVec4.hxx simgear/scene/Makefile.am
|
|
* simgear/scene/material/mat.cxx simgear/scene/material/mat.hxx
|
|
* simgear/scene/material/matlib.cxx
|
|
* simgear/scene/material/matlib.hxx
|
|
* simgear/scene/material/matmodel.cxx
|
|
* simgear/scene/material/matmodel.hxx
|
|
* simgear/scene/model/Makefile.am
|
|
* simgear/scene/model/animation.cxx
|
|
* simgear/scene/model/animation.hxx
|
|
* simgear/scene/model/custtrans.hxx
|
|
* simgear/scene/model/model.cxx simgear/scene/model/model.hxx
|
|
* simgear/scene/model/modellib.cxx
|
|
* simgear/scene/model/modellib.hxx
|
|
* simgear/scene/model/personality.cxx
|
|
* simgear/scene/model/personality.hxx
|
|
* simgear/scene/model/placement.cxx
|
|
* simgear/scene/model/placement.hxx
|
|
* simgear/scene/model/placementtrans.cxx
|
|
* simgear/scene/model/placementtrans.hxx
|
|
* simgear/scene/model/shadanim.cxx
|
|
* simgear/scene/model/shadowvolume.hxx
|
|
* simgear/scene/sky/cloud.cxx simgear/scene/sky/cloud.hxx
|
|
* simgear/scene/sky/cloudfield.cxx simgear/scene/sky/dome.cxx
|
|
* simgear/scene/sky/dome.hxx simgear/scene/sky/moon.cxx
|
|
* simgear/scene/sky/moon.hxx simgear/scene/sky/newcloud.cxx
|
|
* simgear/scene/sky/oursun.cxx simgear/scene/sky/oursun.hxx
|
|
* simgear/scene/sky/sky.cxx simgear/scene/sky/sky.hxx
|
|
* simgear/scene/sky/sphere.cxx simgear/scene/sky/sphere.hxx
|
|
* simgear/scene/sky/stars.cxx simgear/scene/sky/stars.hxx
|
|
* simgear/scene/tgdb/apt_signs.cxx
|
|
* simgear/scene/tgdb/apt_signs.hxx simgear/scene/tgdb/leaf.cxx
|
|
* simgear/scene/tgdb/leaf.hxx simgear/scene/tgdb/obj.cxx
|
|
* simgear/scene/tgdb/obj.hxx simgear/scene/tgdb/pt_lights.cxx
|
|
* simgear/scene/tgdb/pt_lights.hxx
|
|
* simgear/scene/tgdb/userdata.cxx
|
|
* simgear/scene/tgdb/userdata.hxx simgear/scene/tgdb/vasi.hxx
|
|
* simgear/screen/jpgfactory.cxx simgear/screen/tr.cxx
|
|
* simgear/structure/Makefile.am simgear/threads/SGThread.hxx
|
|
* Added Files:
|
|
* simgear/scene/util/Makefile.am
|
|
* simgear/scene/util/SGDebugDrawCallback.hxx
|
|
* simgear/scene/util/SGNodeMasks.hxx
|
|
* simgear/scene/util/SGStateAttributeVisitor.hxx
|
|
* simgear/scene/util/SGTextureStateAttributeVisitor.hxx
|
|
* simgear/scene/util/SGUpdateVisitor.hxx
|
|
* Removed Files:
|
|
* simgear/screen/ssgEntityArray.cxx
|
|
* simgear/screen/ssgEntityArray.hxx
|
|
* simgear/structure/ssgSharedPtr.hxx
|
|
* Big BLOB on the way to OSG.
|
|
*
|
|
* Revision 1.3 2006-02-21 10:47:21 ehofman
|
|
* Back out the previous patch.
|
|
*
|
|
* Revision 1.2 2004/11/18 19:10:34 curt
|
|
* Abstract out location of gl.h, glut.h, and glu.h includes so that we can
|
|
* make the Mac platform happy since they put these in a different place compared
|
|
* to the rest of the world.
|
|
*
|
|
* Revision 1.1.1.1 2002/09/07 02:58:19 curt
|
|
* Initial revsion of Simgear-0.3.0
|
|
*
|
|
* Revision 1.3 2001/07/30 20:34:21 curt
|
|
* Various MSVC fixes.
|
|
*
|
|
* Revision 1.2 2001/06/27 02:48:01 curt
|
|
* Fixed a type conversion bug that could trip up some of the pickier compilers
|
|
* out there.
|
|
*
|
|
* Revision 1.1 2001/06/26 15:19:39 curt
|
|
* Added tr.cxx / tr.h, Brian Paul's LGPL'd tiled rendering support libs for
|
|
* rendering ultra high res "tiled" screen shots.
|
|
*
|
|
* Revision 1.9 1998/01/29 16:56:54 brianp
|
|
* allow trOrtho() and trFrustum() to be called at any time, minor clean-up
|
|
*
|
|
* Revision 1.8 1998/01/28 19:47:39 brianp
|
|
* minor clean-up for C++
|
|
*
|
|
* Revision 1.7 1997/07/21 17:34:38 brianp
|
|
* added tile borders
|
|
*
|
|
* Revision 1.6 1997/07/21 15:47:35 brianp
|
|
* renamed all "near" and "far" variables
|
|
*
|
|
* Revision 1.5 1997/04/26 21:23:25 brianp
|
|
* added trRasterPos3f function
|
|
*
|
|
* Revision 1.4 1997/04/26 19:59:36 brianp
|
|
* set CurrentTile to -1 before first tile and after last tile
|
|
*
|
|
* Revision 1.3 1997/04/22 23:51:15 brianp
|
|
* added WIN32 header stuff, removed tabs
|
|
*
|
|
* Revision 1.2 1997/04/19 23:26:10 brianp
|
|
* many API changes
|
|
*
|
|
* Revision 1.1 1997/04/18 21:53:05 brianp
|
|
* Initial revision
|
|
*
|
|
*/
|
|
|
|
|
|
/*
|
|
* Tiled Rendering library
|
|
* Version 1.1
|
|
* Copyright (C) Brian Paul
|
|
*/
|
|
|
|
|
|
#include <simgear/compiler.h>
|
|
|
|
#include <assert.h>
|
|
#include <math.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#ifdef WIN32
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
#include <osg/GLU>
|
|
|
|
#include "tr.h"
|
|
|
|
|
|
#define DEFAULT_TILE_WIDTH 256
|
|
#define DEFAULT_TILE_HEIGHT 256
|
|
#define DEFAULT_TILE_BORDER 0
|
|
|
|
|
|
struct _TRctx {
|
|
/* Final image parameters */
|
|
GLint ImageWidth, ImageHeight;
|
|
GLenum ImageFormat, ImageType;
|
|
GLvoid *ImageBuffer;
|
|
|
|
/* Tile parameters */
|
|
GLint TileWidth, TileHeight;
|
|
GLint TileWidthNB, TileHeightNB;
|
|
GLint TileBorder;
|
|
GLenum TileFormat, TileType;
|
|
GLvoid *TileBuffer;
|
|
|
|
/* Projection parameters */
|
|
GLboolean Perspective;
|
|
GLdouble Left;
|
|
GLdouble Right;
|
|
GLdouble Bottom;
|
|
GLdouble Top;
|
|
GLdouble Near;
|
|
GLdouble Far;
|
|
|
|
/* Misc */
|
|
TRenum RowOrder;
|
|
GLint Rows, Columns;
|
|
GLint CurrentTile;
|
|
GLint CurrentTileWidth, CurrentTileHeight;
|
|
GLint CurrentRow, CurrentColumn;
|
|
|
|
GLint ViewportSave[4];
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
* Misc setup including computing number of tiles (rows and columns).
|
|
*/
|
|
static void Setup(TRcontext *tr)
|
|
{
|
|
if (!tr)
|
|
return;
|
|
|
|
tr->Columns = (tr->ImageWidth + tr->TileWidthNB - 1) / tr->TileWidthNB;
|
|
tr->Rows = (tr->ImageHeight + tr->TileHeightNB - 1) / tr->TileHeightNB;
|
|
tr->CurrentTile = 0;
|
|
|
|
assert(tr->Columns >= 0);
|
|
assert(tr->Rows >= 0);
|
|
}
|
|
|
|
|
|
|
|
TRcontext *trNew(void)
|
|
{
|
|
TRcontext *tr = (TRcontext *) calloc(1, sizeof(TRcontext));
|
|
if (tr) {
|
|
tr->TileWidth = DEFAULT_TILE_WIDTH;
|
|
tr->TileHeight = DEFAULT_TILE_HEIGHT;
|
|
tr->TileBorder = DEFAULT_TILE_BORDER;
|
|
tr->RowOrder = TR_BOTTOM_TO_TOP;
|
|
tr->CurrentTile = -1;
|
|
}
|
|
return (TRcontext *) tr;
|
|
}
|
|
|
|
|
|
void trDelete(TRcontext *tr)
|
|
{
|
|
if (tr)
|
|
free(tr);
|
|
}
|
|
|
|
|
|
|
|
void trTileSize(TRcontext *tr, GLint width, GLint height, GLint border)
|
|
{
|
|
if (!tr)
|
|
return;
|
|
|
|
assert(border >= 0);
|
|
assert(width >= 1);
|
|
assert(height >= 1);
|
|
assert(width >= 2*border);
|
|
assert(height >= 2*border);
|
|
|
|
tr->TileBorder = border;
|
|
tr->TileWidth = width;
|
|
tr->TileHeight = height;
|
|
tr->TileWidthNB = width - 2 * border;
|
|
tr->TileHeightNB = height - 2 * border;
|
|
Setup(tr);
|
|
}
|
|
|
|
|
|
|
|
void trTileBuffer(TRcontext *tr, GLenum format, GLenum type, GLvoid *image)
|
|
{
|
|
if (!tr)
|
|
return;
|
|
|
|
tr->TileFormat = format;
|
|
tr->TileType = type;
|
|
tr->TileBuffer = image;
|
|
}
|
|
|
|
|
|
|
|
void trImageSize(TRcontext *tr, GLint width, GLint height)
|
|
{
|
|
if (!tr)
|
|
return;
|
|
|
|
tr->ImageWidth = width;
|
|
tr->ImageHeight = height;
|
|
Setup(tr);
|
|
}
|
|
|
|
|
|
void trImageBuffer(TRcontext *tr, GLenum format, GLenum type, GLvoid *image)
|
|
{
|
|
if (!tr)
|
|
return;
|
|
|
|
tr->ImageFormat = format;
|
|
tr->ImageType = type;
|
|
tr->ImageBuffer = image;
|
|
}
|
|
|
|
|
|
GLint trGet(TRcontext *tr, TRenum param)
|
|
{
|
|
if (!tr)
|
|
return 0;
|
|
switch (param) {
|
|
case TR_TILE_WIDTH:
|
|
return tr->TileWidth;
|
|
case TR_TILE_HEIGHT:
|
|
return tr->TileHeight;
|
|
case TR_TILE_BORDER:
|
|
return tr->TileBorder;
|
|
case TR_IMAGE_WIDTH:
|
|
return tr->ImageWidth;
|
|
case TR_IMAGE_HEIGHT:
|
|
return tr->ImageHeight;
|
|
case TR_ROWS:
|
|
return tr->Rows;
|
|
case TR_COLUMNS:
|
|
return tr->Columns;
|
|
case TR_CURRENT_ROW:
|
|
if (tr->CurrentTile<0)
|
|
return -1;
|
|
else
|
|
return tr->CurrentRow;
|
|
case TR_CURRENT_COLUMN:
|
|
if (tr->CurrentTile<0)
|
|
return -1;
|
|
else
|
|
return tr->CurrentColumn;
|
|
case TR_CURRENT_TILE_WIDTH:
|
|
return tr->CurrentTileWidth;
|
|
case TR_CURRENT_TILE_HEIGHT:
|
|
return tr->CurrentTileHeight;
|
|
case TR_ROW_ORDER:
|
|
return (GLint) tr->RowOrder;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
GLdouble trGetD(TRcontext *tr, TRenum param)
|
|
{
|
|
if (!tr)
|
|
return 0.0;
|
|
switch (param) {
|
|
case TR_LEFT:
|
|
return tr->Left;
|
|
case TR_RIGHT:
|
|
return tr->Right;
|
|
case TR_BOTTOM:
|
|
return tr->Bottom;
|
|
case TR_TOP:
|
|
return tr->Top;
|
|
case TR_NEAR:
|
|
return tr->Near;
|
|
case TR_FAR:
|
|
return tr->Far;
|
|
default:
|
|
return 0.0;
|
|
}
|
|
}
|
|
|
|
void trRowOrder(TRcontext *tr, TRenum order)
|
|
{
|
|
if (!tr)
|
|
return;
|
|
|
|
if (order==TR_TOP_TO_BOTTOM || order==TR_BOTTOM_TO_TOP)
|
|
tr->RowOrder = order;
|
|
}
|
|
|
|
|
|
void trOrtho(TRcontext *tr,
|
|
GLdouble left, GLdouble right,
|
|
GLdouble bottom, GLdouble top,
|
|
GLdouble zNear, GLdouble zFar)
|
|
{
|
|
if (!tr)
|
|
return;
|
|
|
|
tr->Perspective = GL_FALSE;
|
|
tr->Left = left;
|
|
tr->Right = right;
|
|
tr->Bottom = bottom;
|
|
tr->Top = top;
|
|
tr->Near = zNear;
|
|
tr->Far = zFar;
|
|
}
|
|
|
|
|
|
void trFrustum(TRcontext *tr,
|
|
GLdouble left, GLdouble right,
|
|
GLdouble bottom, GLdouble top,
|
|
GLdouble zNear, GLdouble zFar)
|
|
{
|
|
if (!tr)
|
|
return;
|
|
|
|
tr->Perspective = GL_TRUE;
|
|
tr->Left = left;
|
|
tr->Right = right;
|
|
tr->Bottom = bottom;
|
|
tr->Top = top;
|
|
tr->Near = zNear;
|
|
tr->Far = zFar;
|
|
}
|
|
|
|
|
|
void trPerspective(TRcontext *tr,
|
|
GLdouble fovy, GLdouble aspect,
|
|
GLdouble zNear, GLdouble zFar )
|
|
{
|
|
GLdouble xmin, xmax, ymin, ymax;
|
|
ymax = zNear * tan(fovy * 3.14159265 / 360.0);
|
|
ymin = -ymax;
|
|
xmin = ymin * aspect;
|
|
xmax = ymax * aspect;
|
|
trFrustum(tr, xmin, xmax, ymin, ymax, zNear, zFar);
|
|
}
|
|
|
|
|
|
void trBeginTile(TRcontext *tr)
|
|
{
|
|
GLint matrixMode;
|
|
GLint tileWidth, tileHeight, border;
|
|
GLdouble left, right, bottom, top;
|
|
|
|
if (!tr)
|
|
return;
|
|
|
|
if (tr->CurrentTile <= 0) {
|
|
Setup(tr);
|
|
/* Save user's viewport, will be restored after last tile rendered */
|
|
glGetIntegerv(GL_VIEWPORT, tr->ViewportSave);
|
|
}
|
|
|
|
/* which tile (by row and column) we're about to render */
|
|
if (tr->RowOrder==TR_BOTTOM_TO_TOP) {
|
|
tr->CurrentRow = tr->CurrentTile / tr->Columns;
|
|
tr->CurrentColumn = tr->CurrentTile % tr->Columns;
|
|
}
|
|
else if (tr->RowOrder==TR_TOP_TO_BOTTOM) {
|
|
tr->CurrentRow = tr->Rows - (tr->CurrentTile / tr->Columns) - 1;
|
|
tr->CurrentColumn = tr->CurrentTile % tr->Columns;
|
|
}
|
|
else {
|
|
/* This should never happen */
|
|
abort();
|
|
}
|
|
assert(tr->CurrentRow < tr->Rows);
|
|
assert(tr->CurrentColumn < tr->Columns);
|
|
|
|
border = tr->TileBorder;
|
|
|
|
/* Compute actual size of this tile with border */
|
|
if (tr->CurrentRow < tr->Rows-1)
|
|
tileHeight = tr->TileHeight;
|
|
else
|
|
tileHeight = tr->ImageHeight - (tr->Rows-1) * (tr->TileHeightNB) + 2 * border;
|
|
|
|
if (tr->CurrentColumn < tr->Columns-1)
|
|
tileWidth = tr->TileWidth;
|
|
else
|
|
tileWidth = tr->ImageWidth - (tr->Columns-1) * (tr->TileWidthNB) + 2 * border;
|
|
|
|
/* Save tile size, with border */
|
|
tr->CurrentTileWidth = tileWidth;
|
|
tr->CurrentTileHeight = tileHeight;
|
|
|
|
glViewport(0, 0, tileWidth, tileHeight); /* tile size including border */
|
|
|
|
/* save current matrix mode */
|
|
glGetIntegerv(GL_MATRIX_MODE, &matrixMode);
|
|
glMatrixMode(GL_PROJECTION);
|
|
glLoadIdentity();
|
|
|
|
/* compute projection parameters */
|
|
left = tr->Left + (tr->Right - tr->Left)
|
|
* (tr->CurrentColumn * tr->TileWidthNB - border) / tr->ImageWidth;
|
|
right = left + (tr->Right - tr->Left) * tileWidth / tr->ImageWidth;
|
|
bottom = tr->Bottom + (tr->Top - tr->Bottom)
|
|
* (tr->CurrentRow * tr->TileHeightNB - border) / tr->ImageHeight;
|
|
top = bottom + (tr->Top - tr->Bottom) * tileHeight / tr->ImageHeight;
|
|
|
|
// OSGFIXME
|
|
// ssgSetFrustum ( left, right, bottom, top, tr->Near, tr->Far );
|
|
|
|
/* restore user's matrix mode */
|
|
glMatrixMode( (GLenum)matrixMode );
|
|
}
|
|
|
|
|
|
|
|
int trEndTile(TRcontext *tr)
|
|
{
|
|
GLint prevRowLength, prevSkipRows, prevSkipPixels /*, prevAlignment */;
|
|
|
|
if (!tr)
|
|
return 0;
|
|
|
|
assert(tr->CurrentTile>=0);
|
|
|
|
/* be sure OpenGL rendering is finished */
|
|
glFlush();
|
|
|
|
/* save current glPixelStore values */
|
|
glGetIntegerv(GL_PACK_ROW_LENGTH, &prevRowLength);
|
|
glGetIntegerv(GL_PACK_SKIP_ROWS, &prevSkipRows);
|
|
glGetIntegerv(GL_PACK_SKIP_PIXELS, &prevSkipPixels);
|
|
/*glGetIntegerv(GL_PACK_ALIGNMENT, &prevAlignment);*/
|
|
|
|
if (tr->TileBuffer) {
|
|
GLint srcX = tr->TileBorder;
|
|
GLint srcY = tr->TileBorder;
|
|
GLint srcWidth = tr->TileWidthNB;
|
|
GLint srcHeight = tr->TileHeightNB;
|
|
glReadPixels(srcX, srcY, srcWidth, srcHeight,
|
|
tr->TileFormat, tr->TileType, tr->TileBuffer);
|
|
}
|
|
|
|
if (tr->ImageBuffer) {
|
|
GLint srcX = tr->TileBorder;
|
|
GLint srcY = tr->TileBorder;
|
|
GLint srcWidth = tr->CurrentTileWidth - 2 * tr->TileBorder;
|
|
GLint srcHeight = tr->CurrentTileHeight - 2 * tr->TileBorder;
|
|
GLint destX = tr->TileWidthNB * tr->CurrentColumn;
|
|
GLint destY = tr->TileHeightNB * tr->CurrentRow;
|
|
|
|
/* setup pixel store for glReadPixels */
|
|
glPixelStorei(GL_PACK_ROW_LENGTH, tr->ImageWidth);
|
|
glPixelStorei(GL_PACK_SKIP_ROWS, destY);
|
|
glPixelStorei(GL_PACK_SKIP_PIXELS, destX);
|
|
/*glPixelStorei(GL_PACK_ALIGNMENT, 1);*/
|
|
|
|
/* read the tile into the final image */
|
|
glReadPixels(srcX, srcY, srcWidth, srcHeight,
|
|
tr->ImageFormat, tr->ImageType, tr->ImageBuffer);
|
|
}
|
|
|
|
/* restore previous glPixelStore values */
|
|
glPixelStorei(GL_PACK_ROW_LENGTH, prevRowLength);
|
|
glPixelStorei(GL_PACK_SKIP_ROWS, prevSkipRows);
|
|
glPixelStorei(GL_PACK_SKIP_PIXELS, prevSkipPixels);
|
|
/*glPixelStorei(GL_PACK_ALIGNMENT, prevAlignment);*/
|
|
|
|
/* increment tile counter, return 1 if more tiles left to render */
|
|
tr->CurrentTile++;
|
|
if (tr->CurrentTile >= tr->Rows * tr->Columns) {
|
|
/* restore user's viewport */
|
|
glViewport(tr->ViewportSave[0], tr->ViewportSave[1],
|
|
tr->ViewportSave[2], tr->ViewportSave[3]);
|
|
tr->CurrentTile = -1; /* all done */
|
|
return 0;
|
|
}
|
|
else
|
|
return 1;
|
|
}
|
|
|
|
|
|
/*
|
|
* Replacement for glRastePos3f() which avoids the problem with invalid
|
|
* raster pos.
|
|
*/
|
|
void trRasterPos3f(TRcontext *tr, GLfloat x, GLfloat y, GLfloat z)
|
|
{
|
|
if (tr->CurrentTile<0) {
|
|
/* not doing tile rendering right now. Let OpenGL do this. */
|
|
glRasterPos3f(x, y, z);
|
|
}
|
|
else {
|
|
GLdouble modelview[16], proj[16];
|
|
GLint viewport[4];
|
|
GLdouble winX, winY, winZ;
|
|
|
|
/* Get modelview, projection and viewport */
|
|
glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
|
|
glGetDoublev(GL_PROJECTION_MATRIX, proj);
|
|
viewport[0] = 0;
|
|
viewport[1] = 0;
|
|
viewport[2] = tr->CurrentTileWidth;
|
|
viewport[3] = tr->CurrentTileHeight;
|
|
|
|
/* Project object coord to window coordinate */
|
|
if (gluProject(x, y, z, modelview, proj, viewport, &winX, &winY, &winZ)){
|
|
|
|
/* set raster pos to window coord (0,0) */
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
glOrtho(0.0, tr->CurrentTileWidth,
|
|
0.0, tr->CurrentTileHeight, 0.0, 1.0);
|
|
glRasterPos3f(0.0, 0.0, -winZ);
|
|
|
|
/* Now use empty bitmap to adjust raster position to (winX,winY) */
|
|
{
|
|
GLubyte bitmap[1] = {0};
|
|
glBitmap(1, 1, 0.0, 0.0, winX, winY, bitmap);
|
|
}
|
|
|
|
/* restore original matrices */
|
|
glPopMatrix(); /*proj*/
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glPopMatrix();
|
|
}
|
|
#ifdef DEBUG
|
|
if (glGetError())
|
|
printf("GL error!\n");
|
|
#endif
|
|
}
|
|
}
|
|
|