/* graphics.ogl */
/* Graphics functions for OpenGL */
/*
* Vis5D system for visualizing five dimensional gridded data sets.
* Copyright (C) 1990 - 2000 Bill Hibbard, Johan Kellum, Brian Paul,
* Dave Santek, and Andre Battaiola.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* As a special exception to the terms of the GNU General Public
* License, you are permitted to link Vis5D with (and distribute the
* resulting source and executables) the LUI library (copyright by
* Stellar Computer Inc. and licensed for distribution with Vis5D),
* the McIDAS library, and/or the NetCDF library, where those
* libraries are governed by the terms of their own licenses.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "../config.h"
#ifdef HAVE_OPENGL
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/cursorfont.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glx.h>
#ifdef HAVE_XMESAGETBACKBUFFER
#include <GL/xmesa.h>
#endif
#include "globals.h"
#include "graphics.h"
#include "matrix.h"
#include "misc.h"
#include "mwmborder.h"
#include <sys/stat.h>
#include "xdump.h"
GLuint v5d_glGenLists(GLsizei cnt);
extern int vis5d_verbose;
/*
* Private OpenGL variables:
*/
static int pretty_flag = 0;
#ifndef M_PI
#define M_PI 3.14159265
#endif
#define TMP_XWD "tmp.xwd"
#define TMP_RGB "tmp.rgb"
#define GLBEGINNOTE if(vis5d_verbose & VERBOSE_OPENGL) printf("calling glbegin at line %d\n",__LINE__);
/* Accumulation buffer antialiasing */
/* JPE: Not used anywhere - tell me if I am wrong: jedwards@inmet.gov.br
#define AA_INC 1.0
static float xoffsets[AA_PASSES] =
{ -AA_INC, 0.0, AA_INC, -AA_INC, 0.0, AA_INC, -AA_INC, 0.0, AA_INC };
static float yoffsets[AA_PASSES] =
{ -AA_INC, -AA_INC, -AA_INC, 0.0, 0.0, 0.0, AA_INC, AA_INC, AA_INC };
*/
/* "Screen door" transparency */
GLuint scalelist=0; /* a simple gllist for a common operation */
static GLuint stipple[3][32];
static Display_Context current_dtx = NULL;
#define DEFAULT_FONT "10x20"
struct Biggfx{
GLXContext gl_ctx;
XFontStruct *font;
GLuint fontbase;
};
struct Biggfx biggfx;
void check_gl_error( char *where )
{
GLenum error;
while ((error = glGetError()) != GL_NO_ERROR) {
fprintf(stderr, "vis5d: OpenGL error near %s: %s\n",
where, gluErrorString( error ) );
fprintf(stderr, "OpenGL: %s %s %s\n",
(char *) glGetString(GL_VENDOR),
(char *) glGetString(GL_RENDERER),
(char *) glGetString(GL_VERSION));
}
}
/*
* Do OpenGL-specific initializations. This is only called once.
*/
void init_graphics2( void )
{
int i;
HQR_available = 1;
Perspec_available = 1;
/* Setup stipples for screendoor transparency */
/* stipple[0] = 25% opaque */
for (i=0;i<32;i+=2) {
stipple[0][i+0] = 0x88888888;
stipple[0][i+1] = 0x22222222;
}
/* stipple[1] = 50% opaque */
for (i=0;i<32;i+=2) {
stipple[1][i+0] = 0xaaaaaaaa;
stipple[1][i+1] = 0x55555555;
}
/* stipple[2] = 75% opaque */
for (i=0;i<32;i+=2) {
stipple[2][i+0] = 0x77777777;
stipple[2][i+1] = 0xdddddddd;
}
}
/*
* Call this before exiting vis5d.
*/
void terminate_graphics( void )
{
}
/*
* Free the graphics resources attached to a display context.
*/
void free_graphics( Display_Context dtx )
{
if (dtx->gl_ctx) {
glXDestroyContext( GfxDpy, dtx->gl_ctx );
dtx->gl_ctx = 0;
}
if (dtx->GfxWindow) {
XDestroyWindow( GfxDpy, dtx->GfxWindow );
dtx->GfxWindow = 0;
}
}
void
context_init(
Context ctx,
long win_id,
int width,
int height
)
{
/* nothing for OpenGL */
}
int make_big_window( char *title, int xpos, int ypos, int width, int height)
{
int attrib_list[] = {
GLX_RGBA,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
GLX_DEPTH_SIZE, 1,
GLX_DOUBLEBUFFER,
None };
int size_attrib_list = sizeof(attrib_list)/sizeof(int);
int stereo_attrib_list[(sizeof(attrib_list)/sizeof(int))+1];
int i;
Window root;
XSetWindowAttributes win_attrib;
XSizeHints sizehints;
XVisualInfo *visualinfo=NULL;
unsigned long mask;
Screen *screen = DefaultScreenOfDisplay( GfxDpy );
root = DefaultRootWindow(GfxDpy);
/*********************/
/* Choose the visual */
/*********************/
for(i=0;i<size_attrib_list-1;i++)
stereo_attrib_list[i] = attrib_list[i];
stereo_attrib_list[size_attrib_list-1] = GLX_STEREO;
stereo_attrib_list[size_attrib_list] = None;
visualinfo = glXChooseVisual( GfxDpy, GfxScr, stereo_attrib_list );
if(visualinfo){
printf("Stereo Mode Enabled\n");
GfxStereoEnabled = 1;
}else
{
visualinfo = glXChooseVisual( GfxDpy, GfxScr, attrib_list );
if (!visualinfo) {
printf("Error: couldn't get RGB, Double-Buffered, Depth-Buffered GLX");
printf(" visual!\n");
exit(0);
}
}
/*******************/
/* Make the window */
/*******************/
win_attrib.background_pixmap = None;
win_attrib.background_pixel = 0;
win_attrib.border_pixel = 0;
if (MaxCmapsOfScreen(screen)==1
&& visualinfo->depth==DefaultDepth(GfxDpy,GfxScr)
&& visualinfo->visual==DefaultVisual(GfxDpy,GfxScr)) {
/* Share the root colormap on low-end displays */
win_attrib.colormap = DefaultColormap( GfxDpy, GfxScr );
}
else {
win_attrib.colormap = XCreateColormap( GfxDpy, root,
visualinfo->visual, AllocNone );
}
win_attrib.event_mask = ExposureMask | ButtonMotionMask | KeyReleaseMask
| KeyPressMask | ButtonPressMask | ButtonReleaseMask
| StructureNotifyMask | VisibilityChangeMask;
mask = CWBackPixmap | CWBackPixel | CWBorderPixel | CWEventMask
| CWColormap; /* | CWOverrideRedirect;*/
if (!BigWindow){
BigWindow = XCreateWindow( GfxDpy, root, xpos, ypos, width, height,
0, visualinfo->depth, InputOutput,
visualinfo->visual,
mask, &win_attrib );
BigWinWidth = width;
BigWinHeight = height;
XSelectInput( GfxDpy, BigWindow, ExposureMask | ButtonMotionMask | KeyReleaseMask
| KeyPressMask | ButtonPressMask | ButtonReleaseMask
| StructureNotifyMask | SubstructureNotifyMask
| VisibilityChangeMask );
sizehints.x = xpos;
sizehints.y = ypos;
sizehints.width = width;
sizehints.height = height;
sizehints.flags = USSize | USPosition;
XSetNormalHints( GfxDpy, BigWindow, &sizehints);
XSetStandardProperties( GfxDpy, BigWindow, title, title,
None, (char **)NULL, 0, &sizehints);
if (!BigWindow) {
printf("Error: XCreateWindow failed in making BigWindow!\n");
exit(0);
}
}
if (width==ScrWidth && height==ScrHeight) {
/* This is a hack for borderless windows! */
no_border( GfxDpy, BigWindow );
}
if (!off_screen_rendering){
XMapWindow( GfxDpy, BigWindow);
}
if (visualinfo->depth<8) {
/* This case occurs on 8-bit SGI Indys, etc because in double buffer
* mode the front and back buffers are only 4 bits deep.
* We do nothing, the GUI will use the GfxVisual, GfxColormap, etc
* which was found by find_best_visual previously.
*/
}
else {
/* Reassign GfxVisual, GfxColormap, etc to use what glxChooseVisual
* gave us. This is especially important on low-end systems using
* Mesa because we want to share colormaps, etc to prevent colormap
* "flashing".
*/
GfxVisual = visualinfo->visual;
GfxDepth = visualinfo->depth;
GfxColormap = win_attrib.colormap;
}
return 1;
}
int make_3d_window( Display_Context dtx, char *title, int xpos, int ypos,
int width, int height )
{
/* TODO: should query GL for best options available */
int attrib_list[] = {
GLX_RGBA,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
/* GLX_ALPHA_SIZE, 1, Leave out, some systems have no alpha bitplanes */
GLX_DEPTH_SIZE, 1,
GLX_DOUBLEBUFFER,
/*
GLX_ACCUM_RED_SIZE, 1,
GLX_ACCUM_GREEN_SIZE, 1,
GLX_ACCUM_BLUE_SIZE, 1,
GLX_ACCUM_ALPHA_SIZE, 1,
*/
None };
XSetWindowAttributes win_attrib;
XSizeHints sizehints;
XVisualInfo *visualinfo=NULL;
unsigned long mask;
if (!BigWindow){
printf("no BigWindow \n");
exit(0);
}
/* MJK 11.19.98 */
if (off_screen_rendering){
width = BigWinWidth/DisplayRows;
height = BigWinHeight/DisplayCols;
}
dtx->StereoEnabled = 0;
if(GfxStereoEnabled){
int size_attrib_list = sizeof(attrib_list)/sizeof(int);
int stereo_attrib_list[(sizeof(attrib_list)/sizeof(int))+1];
int i;
for(i=0;i<size_attrib_list-1;i++)
stereo_attrib_list[i] = attrib_list[i];
stereo_attrib_list[size_attrib_list-1] = GLX_STEREO;
stereo_attrib_list[size_attrib_list] = None;
visualinfo = glXChooseVisual( GfxDpy, GfxScr, stereo_attrib_list );
if(visualinfo){
dtx->StereoEnabled = 1;
}
}
if(! visualinfo)
{
visualinfo = glXChooseVisual( GfxDpy, GfxScr, attrib_list );
if (!visualinfo) {
printf("Error: couldn't get RGB, Double-Buffered,");
printf("Depth-Buffered GLX visual!\n");
exit(0);
}
}
/* Create the GL/X context. */
if (dtx->gl_ctx){
GLXContext prevctx;
prevctx = glXGetCurrentContext();
if(prevctx == dtx->gl_ctx)
glXMakeCurrent( GfxDpy, None, NULL);
glXDestroyContext( GfxDpy, dtx->gl_ctx);
}
dtx->gl_ctx = glXCreateContext( GfxDpy, visualinfo, NULL, True );
if (!dtx->gl_ctx) {
/* try (indirect context) */
dtx->gl_ctx = glXCreateContext( GfxDpy, visualinfo, NULL, False );
if (!dtx->gl_ctx) {
printf("Error: glXCreateContext failed!\n");
exit(0);
}
else {
printf("Warning: using indirect GL/X context, may be slow\n");
}
}
current_dtx = dtx;
if (!dtx->GfxWindow){
/* Make the window */
win_attrib.background_pixmap = None;
win_attrib.background_pixel = 0;
win_attrib.border_pixel = 0;
win_attrib.colormap = GfxColormap;
win_attrib.event_mask = ExposureMask | ButtonMotionMask | KeyReleaseMask
| KeyPressMask | ButtonPressMask | ButtonReleaseMask
| StructureNotifyMask | VisibilityChangeMask;
mask = CWBackPixmap | CWBackPixel | CWBorderPixel | CWEventMask
| CWColormap; /* | CWOverrideRedirect;*/
if (!dtx->GfxWindow){
dtx->GfxWindow = XCreateWindow( GfxDpy, BigWindow, xpos, ypos, width, height,
0, GfxDepth, InputOutput,
GfxVisual,
mask, &win_attrib );
XSelectInput( GfxDpy, dtx->GfxWindow, ExposureMask | ButtonMotionMask
| KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask
| StructureNotifyMask | SubstructureNotifyMask
| VisibilityChangeMask );
sizehints.x = xpos;
sizehints.y = ypos;
sizehints.width = width;
sizehints.height = height;
sizehints.flags = USSize | USPosition;
XSetNormalHints( GfxDpy, dtx->GfxWindow, &sizehints);
XSetStandardProperties( GfxDpy, dtx->GfxWindow,
"Vis5D " VERSION, "Vis5d " VERSION,
None, (char **)NULL, 0, &sizehints);
}
}
if (!dtx->GfxWindow) {
printf("Error: XCreateWindow failed in making GfxWindow!\n");
exit(0);
}
/* MJK 11.19.98 */
if (off_screen_rendering){
GLXPixmap yomap;
dtx->GfxPixmap = XCreatePixmap( GfxDpy, dtx->GfxWindow, width, height,visualinfo->depth);
dtx->WinHeight = height;
dtx->WinWidth = width;
yomap = glXCreateGLXPixmap( GfxDpy, visualinfo, dtx->GfxPixmap);
glXMakeCurrent( GfxDpy, yomap, dtx->gl_ctx );
printf(" The window id is 0x%x 0x%x\n",dtx->GfxWindow,dtx->GfxPixmap);
check_gl_error("make_3d_window:off_screen_rendering ");
}
if (width==ScrWidth && height==ScrHeight) {
/* This is a hack for borderless windows! */
no_border( GfxDpy, dtx->GfxWindow );
}
return finish_3d_window_setup(dtx,xpos,ypos,width,height);
}
int finish_3d_window_setup(Display_Context dtx,int xpos,int ypos,int width,int height)
{
GLXContext prevctx;
GLXDrawable prevdraw;
prevctx = glXGetCurrentContext();
prevdraw= glXGetCurrentDrawable();
/* MJK 11.19.98 */
if (!off_screen_rendering){
if (dtx->GfxWindow ){
if (!glXMakeCurrent( GfxDpy, dtx->GfxWindow, dtx->gl_ctx )) {
printf("Error: glXMakeCurrent failed!\n");
exit(0);
}
}
}
/*
* Need to make sure the correct draw buffer is initially selected - SGI bug?
* (It seems that the second time you bring up the application, the correct
* buffer is not selected. The default by the spec for a double-buffered
* visual is that the BACK buffer should be selected, but that doesn't
* seem to be the case.)
*/
glDrawBuffer(GL_BACK);
{
static GLfloat light0_pos[] = { 0.0, 0.0, 1000.0, 0.0 };
static GLfloat light1_pos[] = { 0.0, 0.0, -1000.0, 0.0 };
static GLfloat light_ambient[] = { 0.15, 0.15, 0.15, 1.0 };
static GLfloat light_diffuse[] = { 0.6, 0.6, 0.6, 1.0 };
static GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
static GLfloat model_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
/*static GLfloat mat_specular[] = { 0.5, 0.5, 0.5, 1.0 };*/
glLightfv( GL_LIGHT0, GL_AMBIENT, light_ambient );
glLightfv( GL_LIGHT0, GL_DIFFUSE, light_diffuse );
glLightfv( GL_LIGHT0, GL_SPECULAR, light_specular );
glLightfv( GL_LIGHT0, GL_POSITION, light0_pos );
glLightfv( GL_LIGHT1, GL_AMBIENT, light_ambient );
glLightfv( GL_LIGHT1, GL_DIFFUSE, light_diffuse );
glLightfv( GL_LIGHT1, GL_SPECULAR, light_specular );
glLightfv( GL_LIGHT1, GL_POSITION, light1_pos );
glLightModelfv( GL_LIGHT_MODEL_AMBIENT, model_ambient );
glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, 0 );
glLightModeli( GL_LIGHT_MODEL_LOCAL_VIEWER, 0 );
/*glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular );*/
/*glMaterialf( GL_FRONT_AND_BACK, GL_SHININESS, 100.0 );*/
glEnable( GL_LIGHT0 );
glEnable( GL_LIGHT1 );
glEnable( GL_NORMALIZE );
}
/* Setup fog/depthcue parameters */
{
static GLfloat fog_color[] = { 0.2, 0.2, 0.2, 1.0 };
glFogi( GL_FOG_MODE, GL_LINEAR );
glFogfv( GL_FOG_COLOR, fog_color );
}
scalelist = v5d_glGenLists(1);
glNewList(scalelist,GL_COMPILE);
glPushMatrix();
glScalef( 1.0/VERTEX_SCALE, 1.0/VERTEX_SCALE, 1.0/VERTEX_SCALE );
glEndList();
dtx->WinWidth = width;
dtx->WinHeight = height;
glViewport( 0, 0, dtx->WinWidth, dtx->WinHeight );
set_3d_font(dtx, DEFAULT_FONT,0);
if (prevctx && prevdraw){
if (!glXMakeCurrent( GfxDpy, prevdraw, prevctx )) {
printf("Error: glXMakeCurrent failed!\n");
exit(0);
}
}
check_gl_error("make_3d_window");
return 1;
}
/*
* Bind the given OpenGL window to a Vis5D context.
* Return: 1 = ok, 0 = error.
*/
int use_opengl_window( Display_Context dtx, Display *dpy, Window window,
GLXContext glctx, XFontStruct *xfont )
{
if (dpy!=GfxDpy) {
GfxDpy = dpy;
GfxScr = DefaultScreen( GfxDpy );
ScrWidth = DisplayWidth( GfxDpy, GfxScr );
ScrHeight = DisplayHeight( GfxDpy, GfxScr );
/* While some graphics libraries don't need this, others do and the
* X/GUI stuff always does.
*/
find_best_visual( GfxDpy, GfxScr, &GfxDepth, &GfxVisual, &GfxColormap );
}
dtx->gl_ctx = glctx;
dtx->GfxWindow = window;
/* Bind the GLX context to the window (make this window the current one) */
/* glXMakeCurrent( GfxDpy, dtx->GfxWindow, dtx->gl_ctx );
JPE replaced with: */
set_current_window( dtx );
/* Setup the font */
if (xfont) {
dtx->gfx[WINDOW_3D_FONT]->font = xfont;
set_3d_font(dtx,NULL,0);
}else{
set_3d_font(dtx,DEFAULT_FONT,0);
}
check_gl_error("use_opengl_window");
return 1;
}
/*
* Specify which display_context / 3D window is the current one for rendering.
*/
/*
#define SET_GFX_DISPLAY_CONTEXT( c ) \
if (c!=current_dtx) { \
glXMakeCurrent( GfxDpy, c->GfxWindow, c->gfx->gl_ctx ); \
current_dtx = c; \
}
*/
/*
* Set the current rendering context/window.
*/
void set_current_window( Display_Context dtx )
{
check_gl_error("b set_current_window");
if (dtx!=current_dtx) {
/* MJK 11.19.98 */
if (dtx->GfxPixmap){
if (off_screen_rendering){
glXMakeCurrent( GfxDpy, dtx->GfxPixmap, dtx->gl_ctx );
}
}
else if (dtx->GfxWindow) {
glXMakeCurrent( GfxDpy, dtx->GfxWindow, dtx->gl_ctx );
}
current_dtx = dtx;
}
check_gl_error("set_current_window");
}
void finish_rendering( void )
{
/* nothing */
/* used for PEX */
}
/* Specify a font to use in an OpenGL window */
int set_opengl_font(char *name, Window GfxWindow, GLXContext gl_ctx, Xgfx *gfx)
{
GLXContext prevctx;
if(prevctx!=gl_ctx)
glXMakeCurrent( GfxDpy, GfxWindow, gl_ctx);
/* JPE: if name is NULL it is assumed that the gfx structure is already
valid (as called from use_opengl_window) */
if(name){
gfx->FontName = strdup(name);
if(gfx->FontName == NULL){
printf("ERROR allocating FontName \n");
}
if (gfx->font && gfx->fontbase && gfx->font->max_char_or_byte2){
glDeleteLists(gfx->fontbase, gfx->font->max_char_or_byte2);
}
gfx->font = XLoadQueryFont( GfxDpy, gfx->FontName );
}
if (!gfx->font) {
fprintf( stderr, "Unable to load font: %s\n", gfx->FontName );
return 0;
}
gfx->fontbase = v5d_glGenLists( gfx->font->max_char_or_byte2 );
glXUseXFont( gfx->font->fid, 0,
gfx->font->max_char_or_byte2, gfx->fontbase );
gfx->FontHeight = gfx->font->ascent + gfx->font->descent;
gfx->FontDescent = gfx->font->descent;
check_gl_error("set_opengl_font");
return 0;
}
/*
* Specify the font to use in the 3-D window. Must be called before
* the window is created.
*/
int set_3d_font( Display_Context dtx, char *name, int size )
{
set_opengl_font(name, dtx->GfxWindow, dtx->gl_ctx, dtx->gfx[WINDOW_3D_FONT]);
check_gl_error("set_3d_font");
return 0;
}
int get_3d_font( Display_Context dtx, char *name, int *size)
{
strcpy( name, dtx->gfx[WINDOW_3D_FONT]->FontName);
return 0;
}
/*
* Set the window's background color.
*/
void clear_color( unsigned int bgcolor )
{
GLfloat r, g, b, a;
r = UNPACK_RED( bgcolor) / 255.0;
g = UNPACK_GREEN( bgcolor ) / 255.0;
b = UNPACK_BLUE( bgcolor ) / 255.0;
a = UNPACK_ALPHA( bgcolor ) / 255.0;
check_gl_error("b clear_color");
glClearColor( r, g, b, a );
check_gl_error("clear_color");
}
/*
* Clear the graphics window. This is called prior to rendering a frame.
*/
void clear_3d_window( void )
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
check_gl_error("clear_3d_window");
}
/*
* Called when window size changes.
*/
void resize_3d_window( int width, int height )
{
current_dtx->WinWidth = width;
current_dtx->WinHeight = height;
glViewport( 0, 0, width, height );
check_gl_error("resize_3d_window");
}
void resize_BIG_window( int width, int height )
{
glFinish();
XResizeWindow(GfxDpy, BigWindow, (unsigned int)width,(unsigned int)height);
glXWaitX();
check_gl_error("resize_BIG_window");
}
void swap_3d_window( void )
{
if (off_screen_rendering){
printf("0x%x 0x%x 0x%x\n",GfxDpy, current_dtx->GfxPixmap , current_dtx->GfxWindow);
/* glXSwapBuffers( GfxDpy, current_dtx->GfxPixmap ); */
}
else{
glXSwapBuffers( GfxDpy, current_dtx->GfxWindow );
}
}
void set_2d( void )
{
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho( 0.0, (GLfloat) current_dtx->WinWidth,
0.0, (GLfloat) current_dtx->WinHeight, -1.0, 1.0 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glDisable( GL_DEPTH_TEST );
check_gl_error("set_2d");
}
/*
* A "magic" number which describes the default size of the view volume.
* The view volume extends from -MAGIC to MAGIC along X, Y, and Z.
*/
#define MAGIC 1.5F
#define ZMAGIC 1.8F
/*
* Distance from eye to center of 3-D box when in perspective mode:
*/
#define EYE_DIST 4.0F
void clipping_on( void )
{
if (!current_dtx->CurvedBox){
glEnable(GL_CLIP_PLANE0);
glEnable(GL_CLIP_PLANE1);
glEnable(GL_CLIP_PLANE2);
glEnable(GL_CLIP_PLANE3);
glEnable(GL_CLIP_PLANE4);
glEnable(GL_CLIP_PLANE5);
glFinish();
}
check_gl_error("clipping_on");
}
void clipping_off( void )
{
if (!current_dtx->CurvedBox){
glDisable(GL_CLIP_PLANE0);
glDisable(GL_CLIP_PLANE1);
glDisable(GL_CLIP_PLANE2);
glDisable(GL_CLIP_PLANE3);
glDisable(GL_CLIP_PLANE4);
glDisable(GL_CLIP_PLANE5);
}
check_gl_error("clipping_off");
}
void set_3d( int perspective, float frontclip, float zoom, float *modelmat)
{
int width = current_dtx->WinWidth;
int height = current_dtx->WinHeight;
GLdouble eqnleft[4];
GLdouble eqnright[4];
GLdouble eqntop[4];
GLdouble eqnbottom[4];
GLdouble eqnback[4];
GLdouble eqnfront[4];
eqntop[0] = -1 * current_dtx->VClipTable[0].eqn[0];
eqntop[1] = -1 * current_dtx->VClipTable[0].eqn[1];
eqntop[2] = -1 * current_dtx->VClipTable[0].eqn[2];
eqntop[3] = -1 * current_dtx->VClipTable[0].eqn[3] + 0.01;
eqnbottom[0] = current_dtx->VClipTable[1].eqn[0];
eqnbottom[1] = current_dtx->VClipTable[1].eqn[1];
eqnbottom[2] =current_dtx->VClipTable[1].eqn[2];
eqnbottom[3] =current_dtx->VClipTable[1].eqn[3] + 0.01;
eqnleft[0] = current_dtx->VClipTable[2].eqn[0];
eqnleft[1] = current_dtx->VClipTable[2].eqn[1];
eqnleft[2] = current_dtx->VClipTable[2].eqn[2];
eqnleft[3] = current_dtx->VClipTable[2].eqn[3] + 0.01;
eqnright[0] = -1 * current_dtx->VClipTable[3].eqn[0];
eqnright[1] = -1 * current_dtx->VClipTable[3].eqn[1];
eqnright[2] = -1 * current_dtx->VClipTable[3].eqn[2];
eqnright[3] = -1 * current_dtx->VClipTable[3].eqn[3] + 0.01;
eqnfront[0] = -1 *current_dtx->HClipTable[0].eqn[0];
eqnfront[1] = -1 *current_dtx->HClipTable[0].eqn[1];
eqnfront[2] = -1 *current_dtx->HClipTable[0].eqn[2];
eqnfront[3] = current_dtx->HClipTable[0].eqn[3] + 0.01;
eqnback[0] = current_dtx->HClipTable[1].eqn[0];
eqnback[1] =current_dtx->HClipTable[1].eqn[1];
eqnback[2] =current_dtx->HClipTable[1].eqn[2];
eqnback[3] = -1 * current_dtx->HClipTable[1].eqn[3] + 0.01;
check_gl_error("set_3d");
if (frontclip<0.0F) {
frontclip = 0.0F;
}
else if (frontclip>=1.0F) {
frontclip = 0.99F;
}
else {
frontclip = frontclip;
}
if (perspective) {
float x, y, near, far;
near = EYE_DIST - ZMAGIC + (2.0F*MAGIC*frontclip);
far = EYE_DIST + ZMAGIC;
if (width>height) {
x = MAGIC / EYE_DIST * near;
y = MAGIC / EYE_DIST * near * height / width;
}
else {
x = MAGIC / EYE_DIST * near * width / height;
y = MAGIC / EYE_DIST * near;
}
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glFrustum( -x, x, -y, y, near, far );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glTranslatef( 0.0, 0.0, -EYE_DIST );
glScalef( zoom, zoom, 1.0 );
glMultMatrixf( modelmat );
glClipPlane(GL_CLIP_PLANE0, eqnleft);
glClipPlane(GL_CLIP_PLANE1, eqnright);
glClipPlane(GL_CLIP_PLANE2, eqntop);
glClipPlane(GL_CLIP_PLANE3, eqnbottom);
glClipPlane(GL_CLIP_PLANE4, eqnback);
glClipPlane(GL_CLIP_PLANE5, eqnfront);
glFogf( GL_FOG_START, EYE_DIST - ZMAGIC );
glFogf( GL_FOG_END, far );
}
else {
/* orthographic */
float x, y, near, far;
if (width>height) {
x = MAGIC / zoom;
y = MAGIC / zoom * height / width;
}
else {
x = MAGIC / zoom * width / height;
y = MAGIC / zoom;
}
near = 2.0F*ZMAGIC*frontclip;
far = 2.0*ZMAGIC;
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
check_gl_error("1end set_3d");
glOrtho( -x, x, -y, y, near, far );
check_gl_error("2end set_3d");
glMatrixMode( GL_MODELVIEW );
glTranslatef( 0.0, 0.0, -ZMAGIC );
glMultMatrixf( modelmat );
glClipPlane(GL_CLIP_PLANE0, eqnleft);
glClipPlane(GL_CLIP_PLANE1, eqnright);
glClipPlane(GL_CLIP_PLANE2, eqntop);
glClipPlane(GL_CLIP_PLANE3, eqnbottom);
glClipPlane(GL_CLIP_PLANE4, eqnback);
glClipPlane(GL_CLIP_PLANE5, eqnfront);
glFogf( GL_FOG_START, 0.0 );
glFogf( GL_FOG_END, far );
}
glEnable( GL_DEPTH_TEST );
check_gl_error("3 set_3d");
glGetDoublev( GL_MODELVIEW_MATRIX, current_dtx->ModelMat );
glGetDoublev( GL_PROJECTION_MATRIX, current_dtx->ProjMat );
current_dtx->Perspective = perspective;
check_gl_error("end set_3d");
glViewport(0, 0,width,height);
}
void stereo_set_3d_perspective(int whicheye, float frontclip)
{
int width = current_dtx->WinWidth;
int height = current_dtx->WinHeight;
GLint mm;
float near, far, eye;
float left, right, top, bottom;
check_gl_error("stereo_set_3d_perspective");
if(!current_dtx->Perspective){
(void) fprintf(stderr, "Error: Stereo requires Perspective mode\n");
return;
}
switch(whicheye){
case VIS5D_STEREO_LEFT:
eye = -VIS5D_EYE_SEP;
break;
case VIS5D_STEREO_RIGHT:
eye = VIS5D_EYE_SEP;
break;
default:
(void) fprintf(stderr, "Error: stereo_set_3d_perspective bad eye\n");
return;
}
near = EYE_DIST - ZMAGIC + (2.0F*MAGIC*frontclip);
far = EYE_DIST + ZMAGIC;
if (width>height) {
left = -MAGIC / EYE_DIST * near - eye/EYE_DIST*near;
right = MAGIC / EYE_DIST * near - eye/EYE_DIST*near;
top = MAGIC / EYE_DIST * near * height /width;
bottom = -top;
}
else {
left = -MAGIC / EYE_DIST * near * width / height - eye/EYE_DIST*near;
right = MAGIC / EYE_DIST * near * width / height - eye/EYE_DIST*near;
top = MAGIC / EYE_DIST * near;
bottom = -top;
}
glGetIntegerv(GL_MATRIX_MODE, &mm);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(left, right, bottom, top, near, far);
glTranslatef(-eye, 0.0, 0.0);
glMatrixMode(mm);
check_gl_error("end stereo_set_3d_perspective");
}
void stereo_set_buff(int whichbuf)
{
GLint buf;
switch(whichbuf){
case VIS5D_STEREO_LEFT:
buf = GL_BACK_LEFT;
break;
case VIS5D_STEREO_RIGHT:
buf = GL_BACK_RIGHT;
break;
case VIS5D_STEREO_BOTH:
buf = GL_BACK;
break;
default:
(void) fprintf(stderr, "Error: stereo_set_buf bad buffer\n");
return;
}
glDrawBuffer(buf);
}
void project( float p[3], float *x, float *y )
{
GLint viewport[4];
GLdouble winx, winy, winz;
/*glGetIntegerv( GL_VIEWPORT, viewport );*/
viewport[0] = 0;
viewport[1] = 0;
viewport[2] = current_dtx->WinWidth;
viewport[3] = current_dtx->WinHeight;
gluProject( (GLdouble) p[0], (GLdouble) p[1], (GLdouble) p[2],
current_dtx->ModelMat, current_dtx->ProjMat, viewport,
&winx, &winy, &winz );
check_gl_error("project");
*x = winx;
*y = current_dtx->WinHeight - winy;
}
void unproject( float x, float y, float p[3], float d[3] )
{
GLint viewport[4];
GLdouble x0, y0, z0;
GLdouble x1, y1, z1;
GLdouble len;
/*glGetIntegerv( GL_VIEWPORT, viewport );*/
viewport[0] = 0;
viewport[1] = 0;
viewport[2] = current_dtx->WinWidth;
viewport[3] = current_dtx->WinHeight;
/* Unproject */
if (!gluUnProject( (GLdouble) x, (GLdouble) (current_dtx->WinHeight-y),
(GLdouble) 0.0,
current_dtx->ModelMat, current_dtx->ProjMat, viewport,
&x0, &y0, &z0 )) {
printf("unproject1 failed\n");
}
if (!gluUnProject( (GLdouble) x, (GLdouble) (current_dtx->WinHeight-y),
(GLdouble) 1.0,
current_dtx->ModelMat, current_dtx->ProjMat, viewport,
&x1, &y1, &z1 )) {
printf("unproject2 failed\n");
}
p[0] = x0;
p[1] = y0;
p[2] = z0;
d[0] = x1-x0;
d[1] = y1-y0;
d[2] = z1-z0;
len = sqrt( d[0]*d[0] + d[1]*d[1] + d[2]*d[2] );
d[0] /= len;
d[1] /= len;
d[2] /= len;
check_gl_error("unproject");
}
void transparency_mode( Display_Context dtx, int mode )
{
if (mode==1) {
dtx->AlphaBlend = 1;
}
else {
dtx->AlphaBlend = 0;
}
}
void set_color( unsigned int c )
{
GLfloat material_color[4];
material_color[0] = UNPACK_RED( c ) / 255.0;
material_color[1] = UNPACK_GREEN( c ) / 255.0;
material_color[2] = UNPACK_BLUE( c ) / 255.0;
material_color[3] = UNPACK_ALPHA( c ) / 255.0;
glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, material_color );
glColor4ubv( (GLubyte *) &c );
check_gl_error("set_color");
}
void set_depthcue( int onoff )
{
if (onoff) {
glEnable( GL_FOG );
}
else {
glDisable( GL_FOG );
}
check_gl_error("set_depthcue");
}
void set_line_width( double w )
{
glLineWidth( (GLfloat) w );
check_gl_error("set_line_width");
}
void set_pointer( int p )
{
if (p) {
/* make busy cursor */
XDefineCursor( GfxDpy, current_dtx->GfxWindow,
XCreateFontCursor(GfxDpy,XC_watch) );
}
else {
XDefineCursor( GfxDpy, current_dtx->GfxWindow,
XCreateFontCursor(GfxDpy,XC_top_left_arrow) );
}
check_gl_error("set_pointer");
}
void set_pretty( int onoff )
{
if (onoff) {
/* turn on */
set_pointer(1);
pretty_flag = 1;
}
else {
/* turn off */
set_pointer(0);
pretty_flag = 0;
}
}
/*** These functions are taken from the OpenGL Programming Guide, ch. 10 ***/
static void accFrustum( GLdouble left, GLdouble right,
GLdouble bottom, GLdouble top,
GLdouble near, GLdouble far,
GLdouble pixdx, GLdouble pixdy,
GLdouble eyedx, GLdouble eyedy,
GLdouble focus )
{
GLdouble xwsize, ywsize;
GLdouble dx, dy;
GLint viewport[4];
glGetIntegerv (GL_VIEWPORT, viewport);
xwsize = right - left;
ywsize = top - bottom;
dx = -(pixdx*xwsize/(GLdouble) viewport[2] + eyedx*near/focus);
dy = -(pixdy*ywsize/(GLdouble) viewport[3] + eyedy*near/focus);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum (left + dx, right + dx, bottom + dy, top + dy, near, far);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(-eyedx, -eyedy, 0.0);
check_gl_error("accFrustum");
}
#ifdef LEAVEOUT
static void accPerspective( GLdouble fovy, GLdouble aspect,
GLdouble near, GLdouble far,
GLdouble pixdx, GLdouble pixdy,
GLdouble eyedx, GLdouble eyedy, GLdouble focus )
{
GLdouble fov2,left,right,bottom,top;
fov2 = ((fovy*M_PI) / 180.0) / 2.0;
top = near / (cos(fov2) / sin(fov2));
bottom = -top;
right = top * aspect;
left = -right;
accFrustum( left, right, bottom, top, near, far,
pixdx, pixdy, eyedx, eyedy, focus );
}
#endif
void start_aa_pass( int n )
{
#define EYEDIST 3.0
#define FOV 400
#ifdef JUNK
float w, h, front, rear;
if (pretty_flag) {
if (n==0) {
/* clear ACC buffer */
glClear( GL_ACCUM_BUFFER_BIT );
}
if (current_dtx->Perspective) {
float front, rear;
front = EYEDIST - current_dtx->Scale * 1.75 * current_dtx->FrntClip;
if (front<0.01) front = 0.01;
rear = EYEDIST + current_dtx->Scale * 1.75;
accPerspective( FOV, current_dtx->AspectRatio, front, rear,
xoffsets[n]/2.0, yoffsets[n]/2.0,
0.0, 0.0, 1.0 );
}
else {
w = xoffsets[n] / current_dtx->WinWidth;
h = yoffsets[n] / current_dtx->WinHeight;
front = current_dtx->Scale * 1.75 * current_dtx->FrntClip;
rear = -current_dtx->Scale * 1.75;
accFrustum( -current_dtx->AspectRatio, current_dtx->AspectRatio,
-1.0, 1.0, front, rear, w, h,
0.0, 0.0, 0.0 );
}
}
#endif
}
void end_aa_pass( int n )
{
if (pretty_flag) {
glAccum( GL_ACCUM, 1.0/AA_PASSES );
if (n==AA_PASSES-1) {
glAccum( GL_RETURN, 1.0 );
}
}
check_gl_error("end_aa_pass");
}
/*
* The original image saving was completely done in X - which does not
* work if you are using stereo visuals. So, I have completely changed
* this portion.
*
* boote@ncar.ucar.edu
*/
static int VIS5DInitializedFormats = 0;
int save_formats( void )
{
int formats;
char s[1000];
struct stat buf;
FILE *f;
#ifdef WORDS_BIGENDIAN
formats = VIS5D_RGB;
#endif
VIS5DInitializedFormats = 1;
#ifdef IMCONVERT
/* found ImageMagick convert program so use it!! */
formats |= VIS5D_PPM;
formats |= VIS5D_GIF;
formats |= VIS5D_PS;
formats |= VIS5D_COLOR_PS;
formats |= VIS5D_XWD;
formats |= VIS5D_TGA;
#else
if (installed("toppm")) formats |= VIS5D_PPM;
if (installed("togif")) formats |= VIS5D_GIF;
if (installed("tops")){
formats |= VIS5D_COLOR_PS;
formats |= VIS5D_PS;
}
#endif
return formats;
}
int save_3d_window_from_oglbuf( char *filename, int format , GLenum oglbuf)
{
char rgbname[100];
char cmd[1000];
FILE *f;
set_pointer(1);
XRaiseWindow( GfxDpy, BigWindow);
XSync( GfxDpy, 0 );
if(!VIS5DInitializedFormats) (void)save_formats();
if(off_screen_rendering){
int x = 0;
int y = 0;
int i;
Display_Context dtx;
if (format==VIS5D_PPM ) {
strcpy( rgbname, filename );
}
else {
strcpy( rgbname, TMP_RGB );
}
for (i = 0; i < DisplayCols; i++){
dtx = vis5d_get_dtx(i);
x += dtx->WinWidth;
}
for (i = 0; i < DisplayRows; i++){
dtx = vis5d_get_dtx(i*DisplayCols);
y += dtx->WinHeight;
}
if (!open_ppm_file( rgbname, x, y)){
return VIS5D_FAIL;
}
for (i = 0; i < DisplayRows*DisplayCols; i++){
dtx = vis5d_get_dtx(i);
if (!add_display_to_ppm_file( dtx, i)){
return VIS5D_FAIL;
}
}
if (!close_ppm_file()){
return VIS5D_FAIL;
}
}else{
if (format==VIS5D_RGB ) {
strcpy( rgbname, filename );
}
else {
strcpy( rgbname, TMP_RGB );
}
/* Make an rgb dump file (.rgb) */
f = fopen(rgbname,"w");
if (!f) {
printf("Error unable to open %s for writing\n", filename);
set_pointer(0);
return 0;
}
#ifdef WORDS_BIGENDIAN
/* TODO: the SGI_Dump code currently only works on BIGENDIAN hardware */
SGI_Dump( GfxDpy, GfxScr, BigWindow, f, oglbuf);
#else
Window_Dump( GfxDpy, GfxScr, BigWindow, f );
#endif
fclose(f);
}
if ((off_screen_rendering && format != VIS5D_PPM) ||
(!off_screen_rendering && format != VIS5D_RGB)){
#ifdef IMCONVERT
if (format==VIS5D_XWD){
sprintf( cmd, "%s %s xwd:%s",IMCONVERT, rgbname, filename );
}
else if (format==VIS5D_GIF){
sprintf( cmd, "%s %s gif:%s", IMCONVERT,rgbname, filename );
}
else if (format==VIS5D_PS || format == VIS5D_COLOR_PS){
sprintf( cmd, "%s %s ps:%s", IMCONVERT,rgbname, filename );
}
else if (format==VIS5D_PPM){
sprintf( cmd, "%s %s ppm:%s", IMCONVERT,rgbname, filename );
}
else if (format==VIS5D_TGA){
sprintf( cmd, "%s %s tga:%s", IMCONVERT,rgbname, filename );
}
#else
if (format==VIS5D_GIF) {
/* convert rgb to gif */
sprintf( cmd, "togif %s %s", rgbname, filename );
}
else if (format==VIS5D_PPM) {
sprintf(cmd,"toppm %s > %s", rgbname, filename );
}
else if (format==VIS5D_PS) {
sprintf(cmd,"tops %s > %s", rgbname, filename );
}
else if (format==VIS5D_COLOR_PS) {
/* convert rgb to color PS */
sprintf(cmd,"tops %s -rgb > %s", rgbname, filename );
}
#endif
else{
fprintf(stderr,"Could not convert image to %d format",format);
return 0;
}
printf("Executing: %s\n", cmd );
system( cmd );
unlink( rgbname );
}
printf("Done writing image file.\n");
set_pointer(0);
return 1;
}
int save_3d_window( char *filename, int format )
{
if(current_dtx->StereoOn)
return save_3d_window_from_oglbuf(filename,format,GL_BACK_LEFT);
return save_3d_window_from_oglbuf(filename,format,GL_BACK);
}
int save_3d_right_window( char *filename, int format )
{
if(current_dtx->StereoOn)
return save_3d_window_from_oglbuf(filename,format,GL_BACK_RIGHT);
(void)fprintf(stderr,
"Stereo *right* window save not supported when not in stereo mode.\n");
(void)fprintf(stderr,
"Hopefully this is not a big suprise for you ;-)\n");
return 0;
}
int save_snd_window(Display_Context dtx, char *filename, int format )
{
char xwdname[100];
char cmd[1000];
char s[1000];
struct stat buf;
FILE *f;
set_pointer(1);
XRaiseWindow(GfxDpy, dtx->Sound.SoundCtrlWindow);
XSync( GfxDpy, 0 );
vis5d_draw_frame(dtx->dpy_context_index, 0);
vis5d_swap_frame(dtx->dpy_context_index);
XSync( GfxDpy, 0 );
vis5d_draw_frame(dtx->dpy_context_index, 0);
vis5d_swap_frame(dtx->dpy_context_index);
XSync( GfxDpy, 0 );
if (format==VIS5D_XWD) {
strcpy( xwdname, filename );
}
else {
strcpy( xwdname, TMP_XWD );
}
/* Make an X window dump file (.xwd) */
f = fopen(xwdname,"w");
if (!f) {
printf("Error unable to open %s for writing\n", filename);
set_pointer(0);
return 0;
}
if (dtx->Sound.soundwin){
Window_Dump( GfxDpy, GfxScr, dtx->Sound.soundwin, f );
fclose(f);
}
else{
return 0;
}
#ifdef IMCONVERT
if (format != VIS5D_XWD){
if (format==VIS5D_RGB){
sprintf( cmd, "%s %s sgi:%s", IMCONVERT,xwdname, filename );
printf("Executing: %s\n", cmd );
system (cmd);
unlink( xwdname );
}
if (format==VIS5D_GIF){
sprintf( cmd, "%s %s gif:%s", IMCONVERT,xwdname, filename );
printf("Executing: %s\n", cmd );
system (cmd);
unlink( xwdname );
}
if (format==VIS5D_PS || format == VIS5D_COLOR_PS){
sprintf( cmd, "%s %s ps:%s", IMCONVERT,xwdname, filename );
printf("Executing: %s\n", cmd );
system (cmd);
unlink( xwdname );
}
if (format==VIS5D_PPM){
sprintf( cmd, "%s %s ppm:%s",IMCONVERT, xwdname, filename );
printf("Executing: %s\n", cmd );
system (cmd);
unlink( xwdname );
}
if (format==VIS5D_TGA){
sprintf( cmd, "%s %s tga:%s",IMCONVERT, xwdname, filename );
printf("Executing: %s\n", cmd );
system (cmd);
unlink( xwdname );
}
}
else
#endif
{
if (format==VIS5D_RGB) {
sprintf( cmd, "fromxwd %s %s", xwdname, filename );
printf("Executing: %s\n", cmd );
system( cmd );
unlink( xwdname );
}
else if (format==VIS5D_GIF) {
/* convert xwd to rgb */
sprintf( cmd, "fromxwd %s %s", xwdname, TMP_RGB );
printf("Executing: %s\n", cmd );
system( cmd );
/* convert rgb to gif */
sprintf( cmd, "togif %s %s", TMP_RGB, filename );
printf("Executing: %s\n", cmd );
system( cmd );
unlink( xwdname );
unlink( TMP_RGB );
}
else if (format==VIS5D_PS) {
sprintf( cmd, "xpr -device ps -gray 4 %s >%s", xwdname, filename );
printf("Executing: %s\n", cmd );
system( cmd );
unlink( xwdname );
}
else if (format==VIS5D_COLOR_PS) {
/* convert xwd to rgb */
sprintf( cmd, "fromxwd %s %s", xwdname, TMP_RGB );
printf("Executing: %s\n", cmd );
system( cmd );
/* convert rgb to color PS */
sprintf(cmd,"tops %s -rgb > %s", TMP_RGB, filename );
printf("Executing: %s\n", cmd );
system( cmd );
unlink( xwdname );
unlink( TMP_RGB );
}
}
printf("Done writing image file.\n");
set_pointer(0);
return 1;
}
int print_3d_window( void )
{
static char ps_file[] = "/usr/tmp/Vis5D_image.ps";
char cmd[1000];
if (!save_3d_window( ps_file, VIS5D_PS )) return 0;
/* We now have a PostScript file */
if (installed("lpr")) {
/* Send ps_file to default printer */
sprintf(cmd,"lpr %s\n", ps_file );
printf("Executing: %s\n", cmd );
system(cmd);
}
/* delete .ps file */
unlink( ps_file );
return 1;
}
int print_snd_window( Display_Context dtx )
{
static char ps_file[] = "/usr/tmp/Vis5D_image.ps";
char cmd[1000];
if (!save_snd_window( dtx, ps_file, VIS5D_PS )) return 0;
/* We now have a PostScript file */
if (installed("lpr")) {
/* Send ps_file to default printer */
sprintf(cmd,"lpr %s\n", ps_file );
printf("Executing: %s\n", cmd );
system(cmd);
}
/* delete .ps file */
unlink( ps_file );
return 1;
}
void set_transparency( int alpha )
{
if (alpha==255) {
/* disable */
glDisable( GL_BLEND );
glDisable( GL_POLYGON_STIPPLE );
}
else {
/* enable */
if (current_dtx->AlphaBlend) {
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glEnable( GL_BLEND );
}
else {
int s = alpha / 64; /* s is in [0,3] */
if (s<3) {
glPolygonStipple( (GLubyte *) stipple[s] );
glEnable( GL_POLYGON_STIPPLE );
}
}
}
check_gl_error("set_transparency");
}
/**********************************************************************/
/*** Drawing Functions ***/
/**********************************************************************/
void generate_isosurface( int n,
uint_index *index,
int_2 verts[][3],
int_1 norms[][3],
int draw_triangles,
GLuint *list )
{
int i;
if(*list<=0){
*list = v5d_glGenLists(1);
if(*list==0)
check_gl_error("generate_isosurface");
}
glNewList(*list,GL_COMPILE);
glEnable( GL_LIGHTING );
if (draw_triangles) {
/* Render the triangles */
glBegin(GL_TRIANGLES);
for (i=0;i<n;i++) {
glNormal3bv( (GLbyte *) norms[i] );
glVertex3sv( verts[i] );
}
glEnd();
}
else
{
/* Render the triangle strip */
GLBEGINNOTE glBegin( GL_TRIANGLE_STRIP );
for (i=0;i<n;i++) {
int j = index[i];
glNormal3bv( (GLbyte *) norms[j] );
glVertex3sv( verts[j] );
}
glEnd();
}
set_transparency(255);
glDisable( GL_LIGHTING );
glEndList();
check_gl_error("draw_isosurface");
}
void draw_isosurface( int n,
uint_index *index,
int_2 verts[][3],
int_1 norms[][3],
int draw_triangles,
unsigned int color, GLuint *list, int listtype )
{
int i;
if(list==NULL){
GLfloat mat_color[4];
mat_color[0] = UNPACK_RED( color ) / 255.0;
mat_color[1] = UNPACK_GREEN( color ) / 255.0;
mat_color[2] = UNPACK_BLUE( color ) / 255.0;
mat_color[3] = UNPACK_ALPHA( color ) / 255.0;
glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_color );
set_transparency( UNPACK_ALPHA(color) );
}else{
if(*list<=0){
*list = v5d_glGenLists(1);
if(*list==0)
check_gl_error("draw_color_quadmesh");
}
glNewList(*list, listtype);
}
glEnable( GL_LIGHTING );
glPushMatrix();
glScalef( 1.0/VERTEX_SCALE, 1.0/VERTEX_SCALE, 1.0/VERTEX_SCALE );
if (draw_triangles) {
/* Render the triangles */
glBegin(GL_TRIANGLES);
for (i=0;i<n;i++) {
glNormal3bv( (GLbyte *) norms[i] );
glVertex3sv( verts[i] );
}
glEnd();
}
else
{
/* Render the triangle strip */
GLBEGINNOTE glBegin( GL_TRIANGLE_STRIP );
for (i=0;i<n;i++) {
int j = index[i];
glNormal3bv( (GLbyte *) norms[j] );
glVertex3sv( verts[j] );
}
glEnd();
}
glPopMatrix();
glDisable( GL_LIGHTING );
if(list)
glEndList();
else
set_transparency(255);
check_gl_error("draw_isosurface");
}
void draw_colored_isosurface( int n,
uint_index *index,
int_2 verts[][3],
int_1 norms[][3],
int draw_triangles,
uint_1 color_indexes[],
unsigned int color_table[],
int alpha )
{
int i;
glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );
glEnable( GL_COLOR_MATERIAL );
glEnable( GL_LIGHTING );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glEnable( GL_BLEND );
glAlphaFunc( GL_GREATER, 0.05 );
glEnable( GL_ALPHA_TEST );
set_transparency( alpha );
glPushMatrix();
glScalef( 1.0/VERTEX_SCALE, 1.0/VERTEX_SCALE, 1.0/VERTEX_SCALE );
if (draw_triangles) {
/* Render the triangles */
glBegin(GL_TRIANGLES);
for (i=0;i<n;i++) {
glColor4ubv( (GLubyte *) &color_table[color_indexes[i]] );
glNormal3bv( (GLbyte *) norms[i] );
glVertex3sv( verts[i] );
}
glEnd();
}else
{
/* Render the triangle strip */
GLBEGINNOTE glBegin( GL_TRIANGLE_STRIP );
for (i=0;i<n;i++) {
int j = index[i];
unsigned int k = color_indexes[j];
glColor4ubv( (GLubyte *) &color_table[k] );
glNormal3bv( (GLbyte *) norms[j] );
glVertex3sv( verts[j] );
}
glEnd();
}
glPopMatrix();
glDisable( GL_LIGHTING );
glDisable( GL_COLOR_MATERIAL );
glDisable( GL_BLEND );
glDisable( GL_POLYGON_STIPPLE );
glDisable( GL_ALPHA_TEST );
check_gl_error("draw_colored_isosurface");
}
void draw_triangle_strip( int n, int_2 verts[][3], int_1 norms[][3],
unsigned int color )
{
int i;
GLfloat material_color[4];
material_color[0] = UNPACK_RED( color ) / 255.0;
material_color[1] = UNPACK_GREEN( color ) / 255.0;
material_color[2] = UNPACK_BLUE( color ) / 255.0;
material_color[3] = UNPACK_ALPHA( color ) / 255.0;
glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, material_color );
set_transparency( UNPACK_ALPHA(color) );
glEnable( GL_LIGHTING );
glPushMatrix();
glScalef( 1.0/VERTEX_SCALE, 1.0/VERTEX_SCALE, 1.0/VERTEX_SCALE );
/* Render the triangle strip */
GLBEGINNOTE glBegin( GL_TRIANGLE_STRIP );
for (i=0;i<n;i++) {
glNormal3bv( (GLbyte *) norms[i] );
glVertex3sv( verts[i] );
}
glEnd();
glPopMatrix();
glDisable( GL_LIGHTING );
check_gl_error("draw_triangle_strip");
set_transparency(255);
}
void draw_colored_triangle_strip( int n,
int_2 verts[][3], int_1 norms[][3],
uint_1 color_indexes[],
unsigned int color_table[], int alpha )
{
int i;
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glEnable( GL_BLEND );
glAlphaFunc( GL_GREATER, 0.05 );
glEnable( GL_ALPHA_TEST );
/* MJK 12.04.98 begin */
glShadeModel(GL_SMOOTH);
glEnable( GL_LIGHTING );
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
glEnable( GL_COLOR_MATERIAL );
/* MJK 12.04.98 end */
check_gl_error("draw_colored_triangle_strip1");
if (alpha==-1) {
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glEnable( GL_BLEND );
glAlphaFunc( GL_GREATER, 0.05 );
glEnable( GL_ALPHA_TEST );
}
else {
/* constant alpha */
set_transparency( alpha );
}
glPushMatrix();
glScalef( 1.0/VERTEX_SCALE, 1.0/VERTEX_SCALE, 1.0/VERTEX_SCALE );
/* Render the triangle strip */
GLBEGINNOTE glBegin( GL_TRIANGLE_STRIP );
for (i=0;i<n;i++) {
glColor4ubv( (GLubyte *) &color_table[color_indexes[i]] );
/* MJK 12.4.98 */
glNormal3bv( norms[i]);
glVertex3sv( verts[i] );
}
glEnd();
glPopMatrix();
glDisable( GL_BLEND );
glDisable( GL_POLYGON_STIPPLE );
glDisable( GL_ALPHA_TEST );
/* MJK 12.04.98 begin */
glDisable( GL_LIGHTING );
glDisable(GL_COLOR_MATERIAL);
/* MJK 12.04.98 end */
check_gl_error("draw_colored_triangle_strip2");
}
void color_quadmesh_texture_object(GLuint *texture, GLubyte *color_table )
{
if(*texture<=0)
glGenTextures(1, texture);
glBindTexture(GL_TEXTURE_1D, *texture );
glTexImage1D( GL_TEXTURE_1D, 0, 4, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE,
color_table );
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
}
void draw_color_quadmesh( int rows, int columns, int_2 verts[][3],
uint_1 color_indexes[], unsigned int color_table[],
int texture_method, GLuint *list, int listtype )
{
register int i, j, base1, base2;
if(list!=NULL){
if(list[0]<=0){
list[0] = v5d_glGenLists(1);
if(list[0]==0)
check_gl_error("draw_color_quadmesh");
}
glNewList(list[0], listtype);
}
if(texture_method){
glBindTexture(GL_TEXTURE_1D, list[1] );
glEnable( GL_TEXTURE_1D );
glMatrixMode( GL_TEXTURE );
glLoadIdentity();
glScalef( 1.0/255.0, 1.0/255.0, 1.0/255.0 );
glMatrixMode( GL_MODELVIEW );
glPushMatrix();
glScalef( 1.0/VERTEX_SCALE, 1.0/VERTEX_SCALE, 1.0/VERTEX_SCALE );
/* variable alpha in the mesh */
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glEnable( GL_BLEND );
glAlphaFunc( GL_GREATER, 0.05 );
glEnable( GL_ALPHA_TEST );
glColor4f( 1.0, 1.0, 1.0, 1.0 );
/* render mesh as a sequence of quad strips */
for (i=0;i<rows-1;i++) {
base1 = i * columns;
base2 = (i+1) * columns;
GLBEGINNOTE glBegin( GL_QUAD_STRIP );
for (j=0;j<columns;j++) {
glTexCoord1i( (GLint) color_indexes[base1+j] );
glVertex3sv( verts[base1+j] );
glTexCoord1i( (GLint) color_indexes[base2+j] );
glVertex3sv( verts[base2+j] );
}
glEnd();
}
}else{
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(4,GL_UNSIGNED_BYTE,0,(GLvoid *) color_table);
/* variable alpha in the mesh */
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glEnable( GL_BLEND );
glAlphaFunc( GL_GREATER, 0.05 );
glEnable( GL_ALPHA_TEST );
glPushMatrix();
glScalef( 1.0/VERTEX_SCALE, 1.0/VERTEX_SCALE, 1.0/VERTEX_SCALE );
/* render mesh as a sequence of quad strips */
for (i=0;i<rows-1;i++) {
base1 = i * columns;
base2 = (i+1) * columns;
GLBEGINNOTE glBegin( GL_QUAD_STRIP );
for (j=0;j<columns;j++) {
glArrayElement(color_indexes[base1+j]);
glVertex3sv( verts[base1+j] );
glArrayElement(color_indexes[base2+j]);
glVertex3sv( verts[base2+j] );
}
glEnd();
}
}
glDisable( GL_BLEND );
glDisable( GL_POLYGON_STIPPLE );
glDisable( GL_ALPHA_TEST );
glDisable( GL_TEXTURE_1D );
glPopMatrix();
if(list!=NULL){
glEndList();
}
check_gl_error("draw_color_quadmesh");
}
void draw_lit_color_quadmesh( int rows, int columns,
float verts[][3],
float norms[][3],
uint_1 color_indexes[],
unsigned int color_table[] )
{
register int i, j, base1, base2;
unsigned int color_row1[1000];
unsigned int color_row2[1000];
unsigned int *row1ptr, *row2ptr, *tmp;
#ifdef FOO
if (alphavalue==-1) {
/* variable alpha in the mesh */
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glEnable( GL_BLEND );
glAlphaFunc( GL_GREATER, 0.05 );
glEnable( GL_ALPHA_TEST );
}
else {
/* constant alpha */
set_transparency( alphavalue );
}
#endif
glEnable( GL_LIGHTING );
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
glEnable( GL_COLOR_MATERIAL );
/* get first row of colors */
for (j=0;j<columns;j++) {
color_row1[j] = color_table[color_indexes[j]];
}
row1ptr = color_row1;
row2ptr = color_row2;
/* render mesh as a sequence of quad strips */
for (i=0;i<rows-1;i++) {
base1 = i * columns;
base2 = (i+1) * columns;
/* second row of colors */
for (j=0;j<columns;j++) {
row2ptr[j] = color_table[color_indexes[base2+j]];
}
GLBEGINNOTE glBegin( GL_QUAD_STRIP );
for (j=0;j<columns;j++) {
glColor4ubv( (GLubyte *) &row1ptr[j] );
glNormal3fv( norms[base1+j] );
glVertex3fv( verts[base1+j] );
glColor4ubv( (GLubyte *) &row2ptr[j] );
glNormal3fv( norms[base2+j] );
glVertex3fv( verts[base2+j] );
}
glEnd();
/* swap row1ptr and row2ptr */
tmp = row1ptr;
row1ptr = row2ptr;
row2ptr = tmp;
}
glDisable( GL_LIGHTING );
glDisable( GL_COLOR_MATERIAL );
/*FOO
glDisable( GL_BLEND );
glDisable( GL_POLYGON_STIPPLE );
glDisable( GL_ALPHA_TEST );
*/
check_gl_error("draw_lit_color_quadmesh");
}
void draw_wind_lines( int nvectors, int_2 verts[][3], unsigned int color )
{
int i, j;
glShadeModel( GL_FLAT );
glDisable( GL_DITHER );
glColor4ubv( (GLubyte *) &color );
glPushMatrix();
glScalef( 1.0/VERTEX_SCALE, 1.0/VERTEX_SCALE, 1.0/VERTEX_SCALE );
GLBEGINNOTE glBegin( GL_LINES );
for (i=0;i<nvectors;i++) {
j = i * 4;
/* main vector */
glVertex3sv( verts[j] );
glVertex3sv( verts[j+1] );
/* head vectors */
glVertex3sv( verts[j+1] );
glVertex3sv( verts[j+2] );
glVertex3sv( verts[j+1] );
glVertex3sv( verts[j+3] );
}
glEnd();
glShadeModel( GL_SMOOTH );
glEnable( GL_DITHER );
glPopMatrix();
check_gl_error("draw_wind_lines");
}
void generate_labels(int n, char *str, int_2 verts[][3], GLuint *list)
{
int i, len;
if(*list<=0){
*list = v5d_glGenLists(1);
if(*list==0)
check_gl_error("generate_disjoint_lines");
}
glNewList(*list,GL_COMPILE);
glPushMatrix();
glScalef( 1.0/VERTEX_SCALE, 1.0/VERTEX_SCALE, 1.0/VERTEX_SCALE );
glPushAttrib(GL_LIST_BIT);
for(i=0;i<n;i++){
len = strlen(str);
glRasterPos3sv(verts[i]);
glCallLists(len, GL_UNSIGNED_BYTE, (GLubyte *) str);
str+=(len+1);
}
glPopAttrib();
glPopMatrix();
glEndList();
}
void plot_strings( int n, char *str, int_2 verts[][3], unsigned int color, GLuint fontbase )
{
int i;
int len;
/* TODO: How to make the area behind the string opaque? */
if(str==NULL)
return;
glColor4ubv( (GLubyte *) &color );
glPushMatrix();
glScalef( 1.0/VERTEX_SCALE, 1.0/VERTEX_SCALE, 1.0/VERTEX_SCALE );
glPushAttrib(GL_LIST_BIT);
glListBase(fontbase);
for(i=0;i<n;i++){
len = strlen(str);
glRasterPos3sv(verts[i]);
glCallLists(len, GL_UNSIGNED_BYTE, (GLubyte *) str);
str+=(len+1);
}
glPopAttrib();
glPopMatrix();
}
void generate_disjoint_lines(int n, int_2 verts[][3], GLuint *list )
{
int i;
if(*list<=0){
*list = v5d_glGenLists(1);
if(*list==0)
check_gl_error("generate_disjoint_lines");
}
glNewList(*list,GL_COMPILE);
GLBEGINNOTE glBegin( GL_LINES );
for(i=0;i<n;i++) glVertex3sv(verts[i]);
glEnd();
glEndList();
}
void draw_disjoint_lines( int n, int_2 verts[][3], unsigned int color,
GLuint *list, int listtype )
{
int i;
/* JPE: leave color out of list, this allows colors to be changed without */
/* regenerating graphics - color must be set when list is called */
if(list==NULL){
glColor4ubv( (GLubyte *) &color );
}else{
if(*list<=0){
*list = v5d_glGenLists(1);
if(*list==0)
check_gl_error("generate_disjoint_lines");
}
glNewList(*list, listtype);
}
glPushMatrix();
glScalef( 1.0/VERTEX_SCALE, 1.0/VERTEX_SCALE, 1.0/VERTEX_SCALE );
glShadeModel( GL_FLAT );
glDisable( GL_DITHER );
if(vis5d_verbose & VERBOSE_OPENGL) printf("draw_disjoint_lines %d\n",n);
GLBEGINNOTE glBegin( GL_LINES );
for(i=0;i<n;i++) glVertex3sv(verts[i]);
glEnd();
glShadeModel( GL_SMOOTH );
glEnable( GL_DITHER );
glPopMatrix();
if(list!=NULL)
glEndList();
}
void draw_colored_disjoint_lines( int n, int_2 verts[][3],
uint_1 color_indexes[],
unsigned int color_table[] )
{
int i;
glPushMatrix();
glScalef( 1.0/VERTEX_SCALE, 1.0/VERTEX_SCALE, 1.0/VERTEX_SCALE );
GLBEGINNOTE glBegin( GL_LINES );
for (i=0;i<n;i+=2 ) {
glColor4ubv( (GLubyte *) &color_table[color_indexes[i/2]] );
glVertex3sv( verts[i] );
glVertex3sv( verts[i+1] );
}
glEnd();
glPopMatrix();
check_gl_error("draw_colored_disjoint_lines");
}
void draw_polylines( int n, int_2 verts[][3], unsigned int color )
{
int i;
glColor4ubv( (GLubyte *) &color );
glShadeModel( GL_FLAT );
glDisable( GL_DITHER );
glPushMatrix();
glScalef( 1.0/VERTEX_SCALE, 1.0/VERTEX_SCALE, 1.0/VERTEX_SCALE );
GLBEGINNOTE glBegin( GL_LINE_STRIP );
for (i=0;i<n;i++ ) {
glVertex3sv( verts[i] );
}
glEnd();
glPopMatrix();
glShadeModel( GL_SMOOTH );
glEnable( GL_DITHER );
check_gl_error("draw_polylines");
}
void draw_colored_polylines( int n, int_2 verts[][3],
uint_1 color_indexes[],
unsigned int color_table[] )
{
int i;
glPushMatrix();
glScalef( 1.0/VERTEX_SCALE, 1.0/VERTEX_SCALE, 1.0/VERTEX_SCALE );
GLBEGINNOTE glBegin( GL_LINE_STRIP );
for (i=0;i<n;i++ ) {
glColor4ubv( (GLubyte *) &color_table[color_indexes[i]] );
glVertex3sv( verts[i] );
}
glEnd();
glPopMatrix();
check_gl_error("draw_colored_polylines");
}
void draw_multi_lines( int n, float verts[][3], unsigned int color )
{
int i;
glColor4ubv( (GLubyte *) &color );
GLBEGINNOTE glBegin( GL_LINE_STRIP );
for (i=0;i<n;i++ ) {
if (verts[i][0]==-999.0) {
/* start new line */
glEnd();
GLBEGINNOTE glBegin( GL_LINE_STRIP );
}
else {
glVertex3fv( verts[i] );
}
}
glEnd();
check_gl_error("draw_multi_lines");
}
void draw_cursor( Display_Context dtx, int style, float x, float y, float z, unsigned int color )
/*** Style 0: Line Cursor
Style 1: Polygon Cursor
Style 2: Sounding Cursor
***/
{
static GLuint line_cursor;
static GLuint polygon_cursor;
static GLuint sounding_cursor;
if (dtx->init_cursor_flag) {
/* do one-time initialization */
/* Make Sounding_cursor vertical line */
sounding_cursor = v5d_glGenLists(1);
glNewList( sounding_cursor, GL_COMPILE );
glLineWidth(3.0);
GLBEGINNOTE glBegin( GL_LINES );
glVertex3f( 0.0, 0.0, dtx->Zmin);
glVertex3f( 0.0, 0.0, dtx->Zmax );
glEnd();
glLineWidth(1.0);
GLBEGINNOTE glBegin( GL_LINES );
glVertex3f( -0.05, 0.0, dtx->Zmax);
glVertex3f( 0.05, 0.0, dtx->Zmax);
glVertex3f( 0.0, -0.05, dtx->Zmax);
glVertex3f( 0.0, 0.05, dtx->Zmax);
glEnd();
glEndList();
/* Make line-segment cursor object */
line_cursor = v5d_glGenLists(1);
glNewList( line_cursor, GL_COMPILE );
GLBEGINNOTE glBegin( GL_LINES );
glVertex3f( -0.05, 0.0, 0.0 );
glVertex3f( 0.05, 0.0, 0.0 );
glVertex3f( 0.0, -0.05, 0.0 );
glVertex3f( 0.0, 0.05, 0.0 );
glVertex3f( 0.0, 0.0, -0.05 );
glVertex3f( 0.0, 0.0, 0.05 );
glEnd();
glEndList();
/* Makt polygona cursor object */
polygon_cursor = v5d_glGenLists(1);
glNewList( polygon_cursor, GL_COMPILE );
GLBEGINNOTE glBegin( GL_QUADS );
/* X axis */
glVertex3f( -0.05, -0.005, 0.005 );
glVertex3f( -0.05, 0.005, -0.005 );
glVertex3f( 0.05, 0.005, -0.005 );
glVertex3f( 0.05, -0.005, 0.005 );
glVertex3f( -0.05, -0.005, -0.005 );
glVertex3f( -0.05, 0.005, 0.005 );
glVertex3f( 0.05, 0.005, 0.005 );
glVertex3f( 0.05, -0.005, -0.005 );
/* Y-axis */
glVertex3f( -0.005, -0.05, 0.005 );
glVertex3f( 0.005, -0.05, -0.005 );
glVertex3f( 0.005, 0.05, -0.005 );
glVertex3f( -0.005, 0.05, 0.005 );
glVertex3f( -0.005, -0.05, -0.005 );
glVertex3f( 0.005, -0.05, 0.005 );
glVertex3f( 0.005, 0.05, 0.005 );
glVertex3f( -0.005, 0.05, -0.005 );
/* Z-axis */
glVertex3f( -0.005, -0.005, 0.05 );
glVertex3f( 0.005, 0.005, 0.05 );
glVertex3f( 0.005, 0.005, -0.05 );
glVertex3f( -0.005, -0.005, -0.05 );
glVertex3f( -0.005, 0.005, 0.05 );
glVertex3f( 0.005, -0.005, 0.05 );
glVertex3f( 0.005, -0.005, -0.05 );
glVertex3f( -0.005, 0.005, -0.05 );
glEnd();
glEndList();
dtx->init_cursor_flag = 0;
}
glColor4ubv( (GLubyte *) &color );
glPushMatrix();
if (style == 2) z = 0 ;
glTranslatef( x, y, z );
if (style == 1) {
glCallList( polygon_cursor );
}
if (style == 2) {
glCallList( sounding_cursor );
}
else {
glCallList( line_cursor );
}
glPopMatrix();
check_gl_error("draw_cursor");
}
GLuint v5d_glGenLists(GLsizei cnt)
{
GLuint listbase;
/* do not allow a list value of 1 - in this way we can signal
that a graphic is requested but has not been drawn */
listbase = glGenLists(cnt);
if(listbase == 1){
listbase = glGenLists(cnt);
glDeleteLists(1,cnt);
}
if(listbase==0){
check_gl_error("v5d_glGenLists");
}
return listbase;
}
void generate_polyline( int n, float vert[][3], GLuint *list )
{
register int i;
if(*list<=0){
*list = v5d_glGenLists(1);
if(*list==0)
check_gl_error("generate_polyline");
}
glNewList(*list,GL_COMPILE);
GLBEGINNOTE glBegin( GL_LINE_STRIP );
for (i=0;i<n;i++) {
glVertex3fv( vert[i] );
}
glEnd();
glEndList();
check_gl_error("generate polyline");
}
/**** OLD primitives ***/
void polyline( float vert[][3], int n )
{
register int i;
GLBEGINNOTE glBegin( GL_LINE_STRIP );
for (i=0;i<n;i++) {
glVertex3fv( vert[i] );
}
glEnd();
check_gl_error("polyline");
}
void disjointpolyline( float vert[][3], int n )
{
register int i;
glShadeModel( GL_FLAT ); /* faster */
glDisable( GL_DITHER );
GLBEGINNOTE glBegin( GL_LINES );
for (i=0;i<n;i+=2) {
glVertex3fv( vert[i] );
glVertex3fv( vert[i+1] );
}
glEnd();
glShadeModel( GL_SMOOTH );
glEnable( GL_DITHER );
check_gl_error("disjointpolyline");
}
#ifdef JUNK
void quadmeshnorm( float vert[][3], float norm[][3], unsigned int color[],
int rows, int cols )
{
register int i, j, base1, base2;
glEnable( GL_LIGHTING );
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
glEnable( GL_COLOR_MATERIAL );
/* break mesh into strips */
for (i=0;i<rows-1;i++) {
base1 = i * cols;
base2 = (i+1) * cols;
GLBEGINNOTE glBegin( GL_QUAD_STRIP );
for (j=0;j<cols;j++) {
glColor4ubv( (GLubyte *) &color[base1+j] );
glNormal3fv( norm[base1+j] );
glVertex3fv( vert[base1+j] );
glColor4ubv( (GLubyte *) &color[base2+j] );
glNormal3fv( norm[base2+j] );
glVertex3fv( vert[base2+j] );
}
glEnd();
}
glDisable( GL_COLOR_MATERIAL );
glDisable( GL_LIGHTING );
}
#endif
void polyline2d( short vert[][2], int n )
{
int i;
glShadeModel( GL_FLAT );
glDisable( GL_DITHER );
GLBEGINNOTE glBegin( GL_LINE_STRIP );
for (i=0;i<n;i++) {
glVertex2i( vert[i][0], current_dtx->WinHeight-vert[i][1] );
}
glEnd();
glShadeModel( GL_SMOOTH );
glEnable( GL_DITHER );
check_gl_error("polyline2d");
}
void draw_text( int xpos, int ypos, char *str )
{
int len = strlen(str);
glRasterPos2i( xpos, current_dtx->WinHeight-ypos );
glListBase( current_dtx->gfx[WINDOW_3D_FONT]->fontbase );
glCallLists( len, GL_UNSIGNED_BYTE, str );
check_gl_error("draw_text");
}
int text_width( XFontStruct *font, char *str)
{
int dir, ascent, descent;
XCharStruct overall;
XTextExtents( font, str, strlen(str),
&dir, &ascent, &descent, &overall);
return overall.width;
}
/*
* Return a copy of Mesa's back buffer image.
*/
XImage *mesa_read_image( void )
{
#ifdef HAVE_XMESAGETBACKBUFFER
unsigned int w = current_dtx->WinWidth;
unsigned int h = current_dtx->WinHeight;
XImage *backimage;
XMesaGetBackBuffer( XMesaGetCurrentBuffer(), NULL, &backimage );
return XSubImage( backimage, 0, 0, w, h );
#else
return NULL;
#endif
}
/*
* Write an XImage into the Mesa window.
*/
void mesa_draw_image( XImage *image )
{
#ifdef HAVE_XMESAGETBACKBUFFER
XImage *backimage;
unsigned int n;
XMesaGetBackBuffer( XMesaGetCurrentBuffer(), NULL, &backimage );
n = backimage->bytes_per_line * backimage->height;
memcpy( backimage->data, image->data, n );
#endif
}
#endif /* HAVE_OPENGL */
syntax highlighted by Code2HTML, v. 0.9.1