yorick-gl-1.1+cvs20070922+dfsg.orig/0000755000175000017500000000000011062435103016423 5ustar thibautthibautyorick-gl-1.1+cvs20070922+dfsg.orig/tristruct.i0000640000175000017500000000472110313362503020641 0ustar thibautthibaut/* * $Id: tristruct.i,v 1.1.1.1 2005/09/18 22:08:03 dhmunro Exp $ */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ /* NOTE: these should not be exposed to interpreted interface */ /* data structures for triangle arrays and triangle strips */ func ASSERT(cond, msg) { if(!cond) error(msg); } struct OctSpan { double xmin, xmax, ymin, ymax, zmin, zmax; } struct OctSTree { long maxdepth; pointer start; pointer chunk; pointer size; pointer trsiz; pointer offsets; pointer ranges; pointer next; } struct OctRange { double lo, hi; } struct OctTree { long maxdepth; pointer start; pointer chunk; pointer size; pointer trsiz; pointer offsets; pointer ranges; OctTree *next; } struct TriArray{ long numTri; pointer cellIDs; pointer xyzverts; pointer normals; long nxti; long nxtj; long nxtk; TriArray *next; } struct TriArrayGrp { long numTri; pointer cellIDs; pointer xyzverts; pointer normals; pointer var2; pointer colors; pointer triEdg; pointer triStart; pointer nTris; TriArrayGrp *next; } struct PolyArrayGrp { long numPoly; pointer edges; pointer cellIDs; pointer xyzverts; pointer normals; pointer var2; pointer colors; pointer triEdg; pointer triStart; pointer nVerts; PolyArrayGrp *next; } struct TriStrip { long nVert; long nStrip; pointer cellIDs; pointer xyzverts; pointer normals; pointer triLen; long nxti; long nxtj; long nxtk; TriStrip *next; } struct TriStripGrp { long nVert; long nStrip; pointer cellIDs; pointer xyzverts; pointer normals; pointer colors; pointer triLen; TriStripGrp *next; } struct TriStripNdx { long nVert; long nStrip; pointer cellIDs; pointer ptndx; pointer triLen; } struct TriStripNdxGrp { long nVert; long nStrip; long numEdg; long numTri; pointer cellIDs; pointer ptndx; pointer xyzverts; pointer normals; pointer colors; pointer triLen; TriStripNdxGrp *next; } struct TriVertexGrp { long numTri; long numEdg; pointer cellIDs; pointer xyzverts; pointer normals; pointer colors; pointer var2; pointer ptndx; pointer triEdg; pointer triStart; pointer nTris; TriVertexGrp *next; } struct IsoTriStrip { long nvert; long edges(12); } struct IsoTriStripArray { long nStrip; IsoTriStrip the_tris(6); } yorick-gl-1.1+cvs20070922+dfsg.orig/Makefile0000640000175000017500000000571610313362473020077 0ustar thibautthibaut# Makefile for yorick-gl, the yorgl OpenGL package # $Id: Makefile,v 1.1.1.1 2005/09/18 22:07:55 dhmunro Exp $ Y_MAKEDIR= Y_EXE= Y_EXE_PKGS= Y_EXE_HOME= Y_EXE_SITE= # ----------------------------------------------------- optimization flags COPT=$(COPT_DEFAULT) TGT=$(DEFAULT_TGT) # ------------------------------------------------ macros for this package PKG_NAME=yorgl PKG_EXENAME=yorgl YISO_PKG_I=cntrfunc.i YGL_PKG_I=glfunc.i YISO_I=contour.i tristruct.i YGL_I=dlist3d.i slicenew.i glcompat.i glprofile.i testgl.i testisotree.i YISO_OBJS=ContourTets3D.o Gradient3D.o isotree.o slicetree.o YGL_OBJS=glPolys.o glStrips.o gltexture.o glcode.o glfunc.o glMouse.o \ glx11view.o glx11setup.o TriUtil.o dlist3d.o glTarray.o gltexsubs.o \ glustub.o glGlyph.o $(OGLXW) include ./Makegl # list of additional package names you want in PKG_EXENAME # (typically Y_EXE_PKGS should be first here) EXTRA_PKGS=$(Y_EXE_PKGS) # list of additional files for clean PKG_CLEAN= # -------------------------------- standard targets and rules (in Makepkg) # set macros Makepkg uses in target and dependency names # DLL_TARGETS, LIB_TARGETS, EXE_TARGETS # are any additional targets (defined below) prerequisite to # the plugin library, archive library, and executable, respectively PKG_I_DEPS=$(PKG_I) Y_DISTMAKE=distmake include $(Y_MAKEDIR)/Make.cfg include $(Y_MAKEDIR)/Makepkg include $(Y_MAKEDIR)/Make$(TGT) # override macros Makepkg sets for rules and other macros # Y_HOME and Y_SITE in Make.cfg may not be correct (e.g.- relocatable) Y_HOME=$(Y_EXE_HOME) Y_SITE=$(Y_EXE_SITE) # reduce chance of yorick-1.5 corrupting this Makefile MAKE_TEMPLATE = protect-against-1.5 # ------------------------------------- targets and rules for this package GLCODE=glcode.h dlist3d.h playgl.h GLFUNC=glfunc.h $(GLCODE) GLWRAP=glWrappers.h TriStruct.h TriUtil.o: $(GLWRAP) $(GLFUNC) dlist3d.o: glBasic.h glStrips.h $(GLWRAP) $(GLFUNC) glGlyph.o: TriStruct.h $(GLFUNC) glInfo.o: glInfo.h playgl.h glMouse.o: glMouse.h $(GLWRAP) $(GLFUNC) glPolys.o: glPolys.h $(GLFUNC) glStrips.o: glStrips.h $(GLWRAP) $(GLFUNC) glTarray.o: glStrips.h $(GLWRAP) $(GLFUNC) glcode.o: $(GLFUNC) glfunc.o: glBasic.h glMouse.h glStrips.h $(GLWRAP) $(GLFUNC) gltexpal.o: Contour3D.h gl3dtex.h glMouse.h glcubetex.h glviewpoint.h $(GLFUNC) gltexsubs.o: gl3dtex.h glBasic.h glcubetex.h $(GLFUNC) gltexture.o: Contour3D.h gl3dtex.h glBasic.h glMouse.h glcubetex.h $(GLFUNC) glustub.o: $(GLCODE) glx11setup.o: glBasic.h glMouse.h $(GLFUNC) glx11view.o: glBasic.h glMouse.h $(GLFUNC) glxWinUtils.o: glxWinUtils.h ContourTets3D.o: Contour3D.h Gradient3D.o: Contour3D.h isotree.o: Contour3D.h isotree.h slicetree.o: Contour3D.h slicetree.h oglx.o: playgl.h oglx.c $(CC) $(CPPFLAGS) $(CFLAGS) $(D_MESA_PIXMAPS) -o $@ -c oglx.c oglw.o: playgl.h install:: $(YNSTALL) $(PKG_I_EXTRA) "$(Y_SITE)/i" uninstall:: cd "$(Y_SITE)/i"; rm -f $(PKG_I_EXTRA) distclean:: ./configure --distclean # -------------------------------------------------------- end of Makefile yorick-gl-1.1+cvs20070922+dfsg.orig/glcode.c0000640000175000017500000006757710515710063020051 0ustar thibautthibaut/* * $Id: glcode.c,v 1.2 2006/10/19 14:48:19 dhmunro Exp $ */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #include "glcode.h" #include "glfunc.h" #include #include #define USE_TRI /* #define CHEK_ERROR(x) gl_chek_error(x) */ #define CHEK_ERROR(x) extern void (*g_on_idle)(void); extern void ygl_update_3d(void); void yglChekError(char *x) { GLenum val; char msg[120]; /* check for any OpenGl errors and clear the error flag */ val= glGetError(); if(val == GL_NO_ERROR) { return; } else if(val == GL_INVALID_ENUM) { sprintf(msg, "OpenGL error GL_INVALID_ENUM in %s\n", x); } else if(val == GL_INVALID_VALUE) { sprintf(msg, "OpenGL error GL_INVALID_VALUE in %s\n", x); } else if(val == GL_INVALID_OPERATION) { sprintf(msg, "OpenGL error GL_INVALID_OPERATION in %s\n", x); } else if(val == GL_STACK_OVERFLOW) { sprintf(msg, "OpenGL error GL_STACK_OVERFLOW in %s\n", x); } else if(val == GL_STACK_UNDERFLOW) { sprintf(msg, "OpenGL error GL_STACK_UNDERFLOW in %s\n", x); } else if(val == GL_OUT_OF_MEMORY) { sprintf(msg, "OpenGL error GL_OUT_OF_MEMORY in %s\n", x); } else { sprintf(msg, "GLU error in %s\n", x); } p_stderr(msg); } /* ////////////////////////////////////////////////////////////// Do any initialization of the rendering context here, such as setting background colors, setting up lighting, or performing preliminary calculations. */ void yglInitRC(void *pData) { glEnable(GL_DEPTH_TEST); /* Hidden surface removal */ /* The following should be GL defaults, but set them anyway */ /* don't use alpha to decide whether to draw */ glDisable(GL_ALPHA_TEST); glDisable(GL_STENCIL_TEST); /* disable stencil buffer */ glDisable(GL_BLEND); /* disable blending of incoming colors and the color buffer */ glDisable(GL_DITHER); /* diasble dithering */ glClearColor(glCurrWin3d->back_red, glCurrWin3d->back_green, glCurrWin3d->back_blue, glCurrWin3d->back_alpha); CHEK_ERROR("GLInitRC after setting clear color"); glEnable(GL_LIGHTING); yglForceUpdateLight(); glEnable(GL_LIGHT0); CHEK_ERROR("GLInitRC after enabling light"); glEnable(GL_COLOR_MATERIAL); yglForceUpdateProperties(); /* set pixel storage alignment for definiteness */ glPixelStorei(GL_UNPACK_ALIGNMENT, 1); /* Draw in green */ yglRGB(0, 255, 0); /* install the function that draws "dirty" 3D windows if one has not already been set */ if(!g_on_idle) { g_on_idle= ygl_update_3d; } CHEK_ERROR("GLInitRC"); } extern void p_glresize(p_glwin *w, int width, int height, int x, int y); /* ////////////////////////////////////////////////////////////// Called by Windows when it receives the WM_SIZE message. Put any code needed here to recalc the viewing volume and viewport info. */ void yglResize(glWinProp *theWin3d, GLsizei w, GLsizei h) { #define USE_PERSPECTIVE #ifdef USE_PERSPECTIVE GLdouble theAspectRatio; #endif /* Prevent a divide by zero */ if(h <= 20) h = 20; if(w <= 20) w = 20; theWin3d->width= w; theWin3d->hite= h; /* update the size of the "inner window" (someday the outer 2D window might be larger than the 3D window to provide room for buttons. */ p_glresize(theWin3d->gl_win, w, h, 0, 0); /* Set Viewport to window dimensions */ glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); /* Reset coordinate system */ glLoadIdentity(); /* Establish clipping volume (left, right, bottom, top, near, far) */ theAspectRatio= (GLdouble)theWin3d->width/(GLdouble)theWin3d->hite; /* Use perspective viewing with the requested field-of-view and an aspect ratio matching the window. Set the near and far clipping planes in z. Use the full opening angle instead of the half opening angle used internally in this package. */ gluPerspective (2.0*theWin3d->fov, theAspectRatio, theWin3d->viewdist/25.0, 16.0*theWin3d->viewdist); /* Set up transformation. */ glMatrixMode (GL_MODELVIEW); gluLookAt(theWin3d->eye[0], theWin3d->eye[1], theWin3d->eye[2], theWin3d->center[0], theWin3d->center[1], theWin3d->center[2], theWin3d->up[0], theWin3d->up[1], theWin3d->up[2]); CHEK_ERROR("GLResize"); } void draw_plane(float pt1[3], float pt2[3], float pt3[3], int num1, int num2) { int i; float rgb[3], norm[3], lin1[3], lin2[3], pt4[3]; float dx1, dy1, dz1, dx2, dy2, dz2; float ambi[]= {1.0f, 1.0f, 1.0f, 1.0f}; double val; /* The three points are the first three corners of a rectangle. Draw the rectangle, num1 lines along the first edge, and num2 lines along the second edge. */ if(alpha_pass) return; /* use smooth shading */ yglSetShade(1); yglUpdateProperties(); rgb[0]= glCurrWin3d->cage_red; rgb[1]= glCurrWin3d->cage_green; rgb[2]= glCurrWin3d->cage_blue; /* the normal is the cross product of the first two edges */ dx1= pt2[0]-pt1[0]; dy1= pt2[1]-pt1[1]; dz1= pt2[2]-pt1[2]; dx2= pt3[0]-pt2[0]; dy2= pt3[1]-pt2[1]; dz2= pt3[2]-pt2[2]; pt4[0]= pt1[0]+dx2; pt4[1]= pt1[1]+dy2; pt4[2]= pt1[2]+dz2; norm[0]= dy1*dz2-dz1*dy2; norm[1]= dz1*dx2-dx1*dz2; norm[2]= dx1*dy2-dy1*dx2; val= 1.0/sqrt(norm[0]*norm[0]+norm[1]*norm[1]+norm[2]*norm[2]); norm[0] *= (float)val; norm[1] *= (float)val; norm[2] *= (float)val; glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(1.0, 1.0); glBegin(GL_POLYGON); glColor3fv(rgb); glNormal3fv(norm); glVertex3fv(pt1); glVertex3fv(pt2); glVertex3fv(pt3); glVertex3fv(pt4); glEnd(); glDisable(GL_POLYGON_OFFSET_FILL); /* draw the grid lines */ rgb[0]= glCurrWin3d->grid_red; rgb[1]= glCurrWin3d->grid_green; rgb[2]= glCurrWin3d->grid_blue; lin1[0]= pt1[0]; lin1[1]= pt1[1]; lin1[2]= pt1[2]; lin2[0]= pt4[0]; lin2[1]= pt4[1]; lin2[2]= pt4[2]; /* this creates diffuse light not connected to any light source */ glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambi); /* turn off all light associated with the light source */ glDisable(GL_LIGHT0); glBegin(GL_LINES); glColor3fv(rgb); for(i= 0; i <= num1+1; i++) { glVertex3fv(lin1); glVertex3fv(lin2); lin1[0] += dx1/(num1+1); lin1[1] += dy1/(num1+1); lin1[2] += dz1/(num1+1); lin2[0] += dx1/(num1+1); lin2[1] += dy1/(num1+1); lin2[2] += dz1/(num1+1); } glEnd(); lin1[0]= pt1[0]; lin1[1]= pt1[1]; lin1[2]= pt1[2]; lin2[0]= pt2[0]; lin2[1]= pt2[1]; lin2[2]= pt2[2]; glBegin(GL_LINES); glColor3fv(rgb); for(i= 0; i <= num2+1; i++) { glVertex3fv(lin1); glVertex3fv(lin2); lin1[0] += dx2/(num2+1); lin1[1] += dy2/(num2+1); lin1[2] += dz2/(num2+1); lin2[0] += dx2/(num2+1); lin2[1] += dy2/(num2+1); lin2[2] += dz2/(num2+1); } glEnd(); /* restore prior diffuse light not connected to any light source */ glLightModelfv(GL_LIGHT_MODEL_AMBIENT, glCurrWin3d->curr_ambient); glEnable(GL_LIGHT0); } void yglCells(long nx, long ny, float xyz[3][3], float *norm, float *colr, long do_alpha) { /* draw a cell array in 3D. The data is a grid of nx by ny cells. xyz is a 3 by 3 array. The first 3 is for x, y, and z. The second three is for the three corners of the cell array */ long i, j, base, colrsiz; float x0, y0, z0, dx0, dy0, dz0, dx1, dy1, dz1; float xa, ya, za, xb, yb, zb, oldSpec; float blackvec[]= {0.0f, 0.0f, 0.0f, 0.0f}; if(do_alpha && !alpha_pass) return; if(!do_alpha && alpha_pass) return; /* there are nx by ny cells to be drawn. the first two corners are along an "x-edge" and the 2nd and 3rd are along a "y-edge". */ x0= xyz[0][0]; y0= xyz[0][1]; z0= xyz[0][2]; dx0= ((xyz[1][0]-xyz[0][0])/nx); dy0= ((xyz[1][1]-xyz[0][1])/nx); dz0= ((xyz[1][2]-xyz[0][2])/nx); dx1= ((xyz[2][0]-xyz[1][0])/ny); dy1= ((xyz[2][1]-xyz[1][1])/ny); dz1= ((xyz[2][2]-xyz[1][2])/ny); oldSpec= yglGetMatSpec(); yglSetMatSpec(0.0); /* turn off specular highlights */ yglUpdateProperties(); /* set ambient and diffuse colors to black (they are tracking glColor) */ glColor3f(0.0,0.0,0.0); if(do_alpha) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); colrsiz= 4; } else { glDisable(GL_BLEND); colrsiz= 3; } /* There are ny quad strips (one for each column). */ for(j= 0; j < ny; j++) { xa= x0+j*dx1; xb= xa+dx1; ya= y0+j*dy1; yb= ya+dy1; za= z0+j*dz1; zb= za+dz1; glBegin(GL_QUAD_STRIP); glNormal3fv(norm); if(do_alpha) { /* there are nx quads in the strip. set nx coords in the looop and the last one after the loop */ for(i= 0, base= colrsiz*j*nx; i < nx; i++) { /* NOTE: It makes no difference in local performance if the coords are converted to floats before being stored in the display list */ glVertex3f(xa, ya, za); glVertex3f(xb, yb, zb); xa += dx0; xb += dx0; ya += dy0; yb += dy0; za += dz0; zb += dz0; glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,colr+colrsiz*i+base); } } else { /* there are nx quads in the strip. set nx coords in the looop and the last one after the loop */ for(i= 0, base= colrsiz*j*nx; i < nx; i++) { /* NOTE: It makes no difference in local performance if the coords are converted to floats before being stored in the display list */ glVertex3f(xa, ya, za); glVertex3f(xb, yb, zb); xa += dx0; xb += dx0; ya += dy0; yb += dy0; za += dz0; zb += dz0; glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,colr+colrsiz*i+base); } } glVertex3f(xa, ya, za); glVertex3f(xb, yb, zb); glEnd(); } if(do_alpha) { glDisable(GL_BLEND); } yglSetMatSpec(oldSpec); /* turn emission color off */ glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,blackvec); yglForceUpdateProperties(); } void yglPlm(long nx, long ny, float *xyz, float *colr) { long i, j; /* draw a logically 2D mesh in one color */ if(nx <= 0 || ny <= 0) return; if(alpha_pass) return; /* NOTE: It makes no difference in local performance if the coords are converted to floats before being stored in the display list */ /* bump the line thickness up so that it will show through the plane */ for(i= 0; i < nx; i++) { glBegin(GL_LINE_STRIP); glColor3fv(colr); for(j= 0; j < ny; j++) { glVertex3fv(xyz+3*i+3*j*nx); } glEnd(); } for(j= 0; j < ny; j++) { glBegin(GL_LINE_STRIP); glColor3fv(colr); for(i= 0; i < nx; i++) { glVertex3fv(xyz+3*i+3*j*nx); } glEnd(); } CHEK_ERROR("yglPlm3d"); } void yglPlf(long nx, long ny, float *xyz, float *colr) { long i, j; float oldSpec; float blackvec[]= {0.0f, 0.0f, 0.0f, 0.0f}; /* fill a logically 2D mesh */ if(nx <= 0 || ny <= 0) return; if(alpha_pass) return; /* NOTE: It makes no difference in local performance if the coords are converted to floats before being stored in the display list */ /* set ambient and diffuse colors to black (they are tracking glColor) */ oldSpec= yglGetMatSpec(); yglSetMatSpec(0.0); /* turn off specular highlights */ yglUpdateProperties(); glColor4f(0.0,0.0,0.0, 0.0); for(j= 0; j < ny-1; j++) { for(i= 0; i < nx-1; i++) { glBegin(GL_POLYGON); glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,colr+4*i+4*j*(nx-1)); glVertex3fv(xyz+3*i+3*j*nx); glVertex3fv(xyz+3*(i+1)+3*j*nx); glVertex3fv(xyz+3*(i+1)+3*(j+1)*nx); glVertex3fv(xyz+3*i+3*(j+1)*nx); glEnd(); } } yglSetMatSpec(oldSpec); /* turn emission color off */ glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,blackvec); yglForceUpdateProperties(); CHEK_ERROR("yglPlf3d"); } void yglSurf(long do_alpha, long nx, long ny, float *xyz, float *norm, float *colr) { long i, j, base; /* fill a logically 2D mesh */ if(nx <= 0 || ny <= 0) return; if(do_alpha && !alpha_pass) return; if(!do_alpha && alpha_pass) return; /* NOTE: It makes no difference in local performance if the coords are converted to floats before being stored in the display list */ yglSetPolyMode(0); /* use smooth shading */ yglSetShade(1); yglSetColorType(1); yglUpdateProperties(); /* set ambient and diffuse colors to desired value */ if(do_alpha) { glColor4fv(colr); } else { glColor3fv(colr); } for(j= 0; j < ny-1; j++) { glBegin(GL_QUAD_STRIP); for(i= 0; i < nx; i++) { base= 3*i+3*j*nx; glNormal3fv(norm+base); glVertex3fv(xyz +base); glNormal3fv(norm+base+3*nx); glVertex3fv(xyz +base+3*nx); } glEnd(); } CHEK_ERROR("yglSurf3d"); } void yglColrSurf(long do_alpha, long nx, long ny, float *xyz, float *norm, float *colr) { long i, j, base; /* fill a logically 2D mesh with a color per vertex */ if(nx <= 0 || ny <= 0) return; if(do_alpha && !alpha_pass) return; if(!do_alpha && alpha_pass) return; /* NOTE: It makes no difference in local performance if the coords are converted to floats before being stored in the display list */ yglSetPolyMode(0); /* use smooth shading */ yglSetShade(1); /* yglSetColorType(1); */ yglUpdateProperties(); /* set ambient and diffuse colors to desired value */ if(do_alpha) { for(j= 0; j < ny-1; j++) { glBegin(GL_QUAD_STRIP); for(i= 0; i < nx; i++) { base= 3*i+3*j*nx; glColor4fv(colr+4*i+4*j*nx); glNormal3fv(norm+base); glVertex3fv(xyz +base); glColor4fv(colr+4*i+4*(j+1)*nx); glNormal3fv(norm+base+3*nx); glVertex3fv(xyz +base+3*nx); } glEnd(); } } else { for(j= 0; j < ny-1; j++) { glBegin(GL_QUAD_STRIP); for(i= 0; i < nx; i++) { base= 3*i+3*j*nx; glColor3fv(colr+base); glNormal3fv(norm+base); glVertex3fv(xyz +base); glColor3fv(colr+base+3*nx); glNormal3fv(norm+base+3*nx); glVertex3fv(xyz +base+3*nx); } glEnd(); } } CHEK_ERROR("yglColrSurf3d"); } void yglLineWidth(double width) { glLineWidth((float)width); } void yglLines(long nvert, float *xyz, float *colr) { long i; float ambi[]= {1.0f, 1.0f, 1.0f, 1.0f}; /* draw the polyline */ if(nvert <= 1) return; if(alpha_pass) return; /* this creates diffuse light not connected to any light source */ glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambi); /* turn off all light associated with the light source */ glDisable(GL_LIGHT0); glBegin(GL_LINE_STRIP); glColor3fv(colr); for(i= 0; i < nvert; i++) { glVertex3fv(xyz+3*i); } glEnd(); /* restore prior diffuse light not connected to any light source */ glLightModelfv(GL_LIGHT_MODEL_AMBIENT, glCurrWin3d->curr_ambient); glEnable(GL_LIGHT0); } void yglPoints(long nvert, float *xyz, float *colr) { long i; float ambi[]= {1.0f, 1.0f, 1.0f, 1.0f}; /* draw the points */ if(nvert <= 1) return; if(alpha_pass) return; /* glPointSize(3.5); */ /* this creates diffuse light not connected to any light source */ glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambi); /* turn off all light associated with the light source */ glDisable(GL_LIGHT0); glBegin(GL_POINTS); for(i= 0; i < nvert; i++) { glColor3fv(colr+3*i); glVertex3fv(xyz+3*i); } glEnd(); /* restore prior diffuse light not connected to any light source */ glLightModelfv(GL_LIGHT_MODEL_AMBIENT, glCurrWin3d->curr_ambient); glEnable(GL_LIGHT0); } void yglFrontFace3d(long dir) { if(dir) glFrontFace(GL_CCW); else glFrontFace(GL_CW); } void yglGetCenter3d(double *center) { center[0]= glCurrWin3d->center[0]; center[1]= glCurrWin3d->center[1]; center[2]= glCurrWin3d->center[2]; } void yglGetEye3d(double *eye) { eye[0]= glCurrWin3d->eye[0]; eye[1]= glCurrWin3d->eye[1]; eye[2]= glCurrWin3d->eye[2]; } void yglGetUp3d(double *up) { up[0]= glCurrWin3d->up[0]; up[1]= glCurrWin3d->up[1]; up[2]= glCurrWin3d->up[2]; } void yglSetLight3d(double ambient, double diffuse, double spec, double spower, double *sdir) { if(glCurrWin3d->ambientLight[0] != (float)ambient) { glCurrWin3d->ambientLight[0] = (float)ambient; glCurrWin3d->ambientLight[1] = (float)ambient; glCurrWin3d->ambientLight[2] = (float)ambient; } if(glCurrWin3d->diffuseLight[0] != (float)diffuse) { glCurrWin3d->diffuseLight[0] = (float)diffuse; glCurrWin3d->diffuseLight[1] = (float)diffuse; glCurrWin3d->diffuseLight[2] = (float)diffuse; } if(glCurrWin3d->specularLight[0] != (float)spec) { glCurrWin3d->specularLight[0] = (float)spec; glCurrWin3d->specularLight[1] = (float)spec; glCurrWin3d->specularLight[2] = (float)spec; } glCurrWin3d->positionLight[0] = (float)sdir[0]; glCurrWin3d->positionLight[1] = (float)sdir[1]; glCurrWin3d->positionLight[2] = (float)sdir[2]; CHEK_ERROR("set_gl_light"); } void yglPrepContext(void) { GLdouble theAspectRatio; glMatrixMode (GL_MODELVIEW); glLoadIdentity(); /* The light should be set immediately after loading the identity transform. All properties should be set because this is the start of a plot. */ yglForceUpdateLight(); /* Reset coordinate system */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); /* Establish clipping volume (left, right, bottom, top, near, far) */ theAspectRatio= (GLdouble)glCurrWin3d->width/(GLdouble)glCurrWin3d->hite; /* Use perspective viewing with the requested field-of-view and an aspect ratio matching the window. Set the near and far clipping planes in z. Use the full opening angle instead of he half opening angle used internally in this package. */ gluPerspective (2.0*glCurrWin3d->fov, theAspectRatio, glCurrWin3d->viewdist/25.0, 16.0*glCurrWin3d->viewdist); /* Set up transformation. */ glMatrixMode (GL_MODELVIEW); gluLookAt(glCurrWin3d->eye[0], glCurrWin3d->eye[1], glCurrWin3d->eye[2], glCurrWin3d->center[0], glCurrWin3d->center[1], glCurrWin3d->center[2], glCurrWin3d->up[0], glCurrWin3d->up[1], glCurrWin3d->up[2]); CHEK_ERROR("yglPrepContext"); yglForceUpdateProperties(); } void yglForceUpdateLight(void) { glCurrWin3d->curr_ambient[0]= glCurrWin3d->ambientLight[0]; glCurrWin3d->curr_ambient[1]= glCurrWin3d->ambientLight[1]; glCurrWin3d->curr_ambient[2]= glCurrWin3d->ambientLight[2]; glCurrWin3d->curr_diffuse[0]= glCurrWin3d->diffuseLight[0]; glCurrWin3d->curr_diffuse[1]= glCurrWin3d->diffuseLight[1]; glCurrWin3d->curr_diffuse[2]= glCurrWin3d->diffuseLight[2]; glCurrWin3d->curr_specular[0]= glCurrWin3d->specularLight[0]; glCurrWin3d->curr_specular[1]= glCurrWin3d->specularLight[1]; glCurrWin3d->curr_specular[2]= glCurrWin3d->specularLight[2]; glCurrWin3d->curr_position[0]= glCurrWin3d->positionLight[0]; glCurrWin3d->curr_position[1]= glCurrWin3d->positionLight[1]; glCurrWin3d->curr_position[2]= glCurrWin3d->positionLight[2]; glCurrWin3d->curr_position[3]= glCurrWin3d->positionLight[3]; glCurrWin3d->curr_light_model= glCurrWin3d->light_model; glLightfv(GL_LIGHT0,GL_AMBIENT,glCurrWin3d->curr_ambient); glLightfv(GL_LIGHT0,GL_DIFFUSE,glCurrWin3d->curr_diffuse); glLightfv(GL_LIGHT0,GL_SPECULAR,glCurrWin3d->curr_specular); glLightfv(GL_LIGHT0,GL_POSITION,glCurrWin3d->curr_position); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, glCurrWin3d->curr_light_model); CHEK_ERROR("ForceUpdateLight"); } void yglUpdateLight(void) { if(glCurrWin3d->curr_ambient[0] != glCurrWin3d->ambientLight[0] || glCurrWin3d->curr_ambient[1] != glCurrWin3d->ambientLight[1] || glCurrWin3d->curr_ambient[2] != glCurrWin3d->ambientLight[2]) { glCurrWin3d->curr_ambient[0]= glCurrWin3d->ambientLight[0]; glCurrWin3d->curr_ambient[1]= glCurrWin3d->ambientLight[1]; glCurrWin3d->curr_ambient[2]= glCurrWin3d->ambientLight[2]; glLightfv(GL_LIGHT0,GL_AMBIENT,glCurrWin3d->curr_ambient); } if(glCurrWin3d->curr_diffuse[0] != glCurrWin3d->diffuseLight[0] || glCurrWin3d->curr_diffuse[1] != glCurrWin3d->diffuseLight[1] || glCurrWin3d->curr_diffuse[2] != glCurrWin3d->diffuseLight[2]) { glCurrWin3d->curr_diffuse[0]= glCurrWin3d->diffuseLight[0]; glCurrWin3d->curr_diffuse[1]= glCurrWin3d->diffuseLight[1]; glCurrWin3d->curr_diffuse[2]= glCurrWin3d->diffuseLight[2]; glLightfv(GL_LIGHT0,GL_DIFFUSE,glCurrWin3d->curr_diffuse); } if(glCurrWin3d->curr_specular[0] != glCurrWin3d->specularLight[0] || glCurrWin3d->curr_specular[1] != glCurrWin3d->specularLight[1] || glCurrWin3d->curr_specular[2] != glCurrWin3d->specularLight[2]) { glCurrWin3d->curr_specular[0]= glCurrWin3d->specularLight[0]; glCurrWin3d->curr_specular[1]= glCurrWin3d->specularLight[1]; glCurrWin3d->curr_specular[2]= glCurrWin3d->specularLight[2]; glLightfv(GL_LIGHT0,GL_SPECULAR,glCurrWin3d->curr_specular); } /* not changing fourth element, so it remains "directional" or "positional" as initially set. */ if(glCurrWin3d->curr_position[0] != glCurrWin3d->positionLight[0] || glCurrWin3d->curr_position[1] != glCurrWin3d->positionLight[1] || glCurrWin3d->curr_position[2] != glCurrWin3d->positionLight[2] || glCurrWin3d->curr_position[3] != glCurrWin3d->positionLight[3]) { glCurrWin3d->curr_position[0]= glCurrWin3d->positionLight[0]; glCurrWin3d->curr_position[1]= glCurrWin3d->positionLight[1]; glCurrWin3d->curr_position[2]= glCurrWin3d->positionLight[2]; glCurrWin3d->curr_position[3]= glCurrWin3d->positionLight[3]; glLightfv(GL_LIGHT0,GL_POSITION,glCurrWin3d->curr_position); } if(glCurrWin3d->curr_light_model != glCurrWin3d->light_model) { glCurrWin3d->curr_light_model= glCurrWin3d->light_model; glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, glCurrWin3d->curr_light_model); } CHEK_ERROR("UpdateLight"); } void yglSetPolyMode(int mode) { if(!mode) glCurrWin3d->poly_mode= GL_FILL; else glCurrWin3d->poly_mode= GL_LINE; } void yglSetPolySides(int sides) { if(sides) glCurrWin3d->poly_sides= GL_FRONT_AND_BACK; else glCurrWin3d->poly_sides= GL_FRONT; } void yglSetMatSpec(float spec) { if(spec >= 0.0 && spec <= 1.0) glCurrWin3d->mat_spec= spec; } float yglGetMatSpec(void) { return glCurrWin3d->mat_spec; } void yglSetShade(int smooth) { if(smooth) glCurrWin3d->shade_model= GL_SMOOTH; else glCurrWin3d->shade_model= GL_FLAT; } void yglSetColorType(int colorType) { /* specifies which sort of color is set by glColorMaterial */ if(colorType) glCurrWin3d->mat_color= GL_AMBIENT_AND_DIFFUSE; else glCurrWin3d->mat_color= GL_EMISSION; } void yglUpdateProperties(void) { int chg_sides; if(glCurrWin3d->curr_poly_sides != glCurrWin3d->poly_sides) { chg_sides= 1; glCurrWin3d->curr_poly_sides= glCurrWin3d->poly_sides; } else { chg_sides= 0; } if(chg_sides || glCurrWin3d->curr_poly_mode != glCurrWin3d->poly_mode) { glCurrWin3d->curr_poly_mode= glCurrWin3d->poly_mode; glPolygonMode(glCurrWin3d->curr_poly_sides, glCurrWin3d->curr_poly_mode); } if(chg_sides || glCurrWin3d->curr_mat_spec[0] != glCurrWin3d->mat_spec) { glCurrWin3d->curr_mat_spec[0]= glCurrWin3d->mat_spec; glCurrWin3d->curr_mat_spec[1]= glCurrWin3d->mat_spec; glCurrWin3d->curr_mat_spec[2]= glCurrWin3d->mat_spec; glMaterialfv(glCurrWin3d->curr_poly_sides, GL_SPECULAR, glCurrWin3d->curr_mat_spec); } if(glCurrWin3d->curr_cull_mode != glCurrWin3d->cull_mode) { glCurrWin3d->curr_cull_mode= glCurrWin3d->cull_mode; if(glCurrWin3d->curr_cull_mode) { glEnable(GL_CULL_FACE); } else { glDisable(GL_CULL_FACE); } } if(chg_sides || glCurrWin3d->curr_mat_color != glCurrWin3d->mat_color) { glCurrWin3d->curr_mat_color= glCurrWin3d->mat_color; glColorMaterial(glCurrWin3d->curr_poly_sides, glCurrWin3d->curr_mat_color); glEnable(GL_COLOR_MATERIAL); } if(chg_sides) { glMateriali(glCurrWin3d->curr_poly_sides, GL_SHININESS, 100); } if(glCurrWin3d->curr_shade_model != glCurrWin3d->shade_model) { glCurrWin3d->curr_shade_model= glCurrWin3d->shade_model; glShadeModel(glCurrWin3d->curr_shade_model); } } void yglForceUpdateProperties(void) { glPolygonMode(glCurrWin3d->curr_poly_sides, glCurrWin3d->curr_poly_mode); glMaterialfv(glCurrWin3d->curr_poly_sides, GL_SPECULAR, glCurrWin3d->curr_mat_spec); if(glCurrWin3d->curr_cull_mode) { glEnable(GL_CULL_FACE); } else { glDisable(GL_CULL_FACE); } glMateriali(glCurrWin3d->curr_poly_sides, GL_SHININESS, 100); glColorMaterial(glCurrWin3d->curr_poly_sides, glCurrWin3d->curr_mat_color); /* glColorMaterial(curr_poly_sides, GL_AMBIENT_AND_DIFFUSE); */ glEnable(GL_COLOR_MATERIAL); glShadeModel(glCurrWin3d->curr_shade_model); } void yglWireSphere(int list_num, double radius) { /* draw a wire frame sphere with radius 1.0 centered at the origin. Draw lines every 30 degrees in latitude and longitude. Put a marker at the north pole. longitude lines in the western hemisphere are green and in the eastern hemisphere cyan. */ int i, j, numi, numj, numli, numlj, num2i; double lat, lon, x, y, z, csth, snth, csph, snph, pi; if(alpha_pass) return; #define ang_step 30 #define lin_step 5 pi= 4.0*atan(1.0); numi= (int)(360.0/ang_step); numj= (int)(180.0/ang_step); numli= (int)(360.0/lin_step); numlj= (int)(180.0/lin_step); glNewList(list_num, GL_COMPILE); CHEK_ERROR("yglWireSphere glNewList"); /* draw latitude lines */ for(j= 1; j < numj; j++) { lat= j*pi/numj; csth= cos(lat); snth= sqrt(1.0-csth*csth); glBegin(GL_LINE_STRIP); glColor3d(1.0,1.0,1.0); for(i= 0; i <= numli; i++) { lon= i*2.0*pi/numli; csph= cos(lon); snph= sin(lon); x= radius*csph*snth; y= radius*snph*snth; z= radius*csth; glVertex3d(x,y,z); } glEnd(); } CHEK_ERROR("yglWireSphere after latitude"); /* draw longitude lines */ num2i= numi/2; for(i= 0; i < numi; i++) { lon= i*2.0*pi/numi; csph= cos(lon); snph= sin(lon); glBegin(GL_LINE_STRIP); if(i < num2i) glColor3d(0.0, 0.0, 0.0); else glColor3d(0.0, 1.0, 0.0); for(j= 0; j <= numlj; j++) { lat= j*pi/numlj; csth= cos(lat); snth= sqrt(1.0-csth*csth); x= radius*csph*snth; y= radius*snph*snth; z= radius*csth; glVertex3d(x,y,z); } glEnd(); } CHEK_ERROR("yglWireSphere after longitude"); /* draw polar cap */ glBegin(GL_POLYGON); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glColor3d(1.0,1.0,1.0); for(i= 0; i <= numi; i++) { lon= i*2.0*pi/numi; csph= cos(lon); snph= sin(lon); csth= cos(pi/18.0); snth= sqrt(1.0-csth*csth); x= radius*csph*snth; y= radius*snph*snth; z= radius*csth; glVertex3d(x,y,z); } glEnd(); CHEK_ERROR("yglWireSphere after polar cap"); glEndList(); CHEK_ERROR("yglWireSphere"); } int yglNewList(void) { int num; /* create one new OpenGL display list */ num= glGenLists(1); glNewList(num, GL_COMPILE); return num; } int yglCloseList(void) { /* closes the current OpenGL display list (only one can be open at a time) */ glEndList(); return 0; } int yglDrawList(int num) { /* draw the specified OpenGL display list */ glCallList(num); return 0; } int yglDeleteList(int num) { /* free the specified OpenGL display list */ /* !!! WARNING !! FIX FIX FIX !! OpenGL display lists are destroyed when their OpenGL context is destroyed. Yorick must thus manage the list of active display lists. This should be per window information */ return 0; } int yglArrlim3d(long nvert, double *arr, double *lims) { long base; double xmin, xmax, ymin, ymax, zmin, zmax; double xval, yval, zval; xmin= 1.0e100; xmax= -1.0e100; ymin= 1.0e100; ymax= -1.0e100; zmin= 1.0e100; zmax= -1.0e100; /* the x-array is 3-by-nvert */ for(base= 0; base < nvert; base += 3) { xval= arr[base]; yval= arr[base+1]; zval= arr[base+2]; if(xmin > xval) xmin= xval; if(xmax < xval) xmax= xval; if(ymin > yval) ymin= yval; if(ymax < yval) ymax= yval; if(zmin > zval) zmin= zval; if(zmax < zval) zmax= zval; } lims[0]= xmin; lims[1]= xmax; lims[2]= ymin; lims[3]= ymax; lims[4]= zmin; lims[5]= zmax; return 0; } yorick-gl-1.1+cvs20070922+dfsg.orig/isotree.c0000640000175000017500000013075510313362502020250 0ustar thibautthibaut/* * $Id: isotree.c,v 1.1.1.1 2005/09/18 22:08:02 dhmunro Exp $ */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #include "Contour3D.h" #include "isotree.h" #include static long *t_sizes; static long *t_start; static long *t_chunk; static double *t_deltas; static double *t_origin; static double t_level; static double *t_var; static double *t_vcen; static double *t_var2; static yPoint3D *t_xyz; static TriArrayGrp *t_triangles; #ifdef OLD_ISO_STUFF static OctTree *t_tree; static long t_maxdepth; #endif static long *t_trsiz; static long *t_offsets; static OctRange *t_ranges; static long make_strip= 0; static long *t_ptndx; static long v_edg_offset[12]; #define DO_STATS #ifdef DO_STATS long numscan, numcross; #endif #ifdef OLD_ISO_STUFF static long edges[12][2] = { {0,1}, {1,2}, {2,3}, {3,0}, {4,5}, {5,6}, {6,7}, {7,4}, {0,4}, {1,5}, {3,7}, {2,6}}; static int CASE_MASK[8] = {1,2,4,8,16,32,64,128}; #endif static void extract_tris(int index, long idxvg, long *numTri, double lev, double s[8], yPoint3D pts[8], yPoint3D gradients[8], double vars[8], long *cellIDs, yPoint3D *xyzverts, yPoint3D *normals, double *var2); int ycMakeContourTree(double *var, OctTree *tree) { long maxdepth= tree->maxdepth; long *chk= tree->chunk; long *trsiz= tree->trsiz; long *offsets= tree->offsets; OctRange *ranges= tree->ranges; long nx= chk[0]; long ny= chk[1]; long nz= chk[2]; long i; OctRange *oldr, *newr; /* This function builds an octree from the input data values. The caller has pre-allocated enough space for the tree. The caller must free the storage. tree->size is the number of points in each direction in the global (whole) array. The global array has a layer of guard cells around it. The guard cells don't have a large effect in this routine because the algorithm must already deal with the difference between chunk indices and global indices. NOTE: the chunk specifies points surrounding cells to be contoured. The chunk will never include the first or last points in the global array. tree->chunk is the number of points in this chunk (one more than the number of cells). tree->start is the point in the larger grid where this chunk starts. tree->trsiz contains the number of "cells" in the various levels of the octree. The first three elements are the same as chunk. var contains the point-centered data values. */ if (!var || nx < 4 || ny < 4 || nz < 4) { return 0; } /* build an octree containing the data range for sub-blocks of the input array */ firstblk(var, tree->start, tree->size, trsiz, ranges); for(i= 1; i < maxdepth; i++) { /* NOTE: nextblk needs both the size of the tree level it is filling in and the size of the parent level. It also needs both the parent ranges and space to fill in the ranges for this level. */ oldr= ranges+offsets[i-1]; newr= ranges+offsets[i]; nextblk(trsiz+3*(i-1), oldr, newr); } return 1; } void firstblk(double *data, long *start, long *sizes, long *trsiz, OctRange *rng) { /* number of "cells" in this chunk */ long nx= trsiz[0]; long ny= trsiz[1]; long nz= trsiz[2]; /* number of vertices in the full array */ long ngx= sizes[0]; long ngy= sizes[1]; /* starting point of this chunk in the full array */ long stx= start[0]; long sty= start[1]; long stz= start[2]; long i, j, k, base, nbase; double lo, hi, val; /* NOTE: nx, ny, and nz are numbers of cells. The number of vertices is one more. start gives the starting point of this chunk in the larger array. sizes is the number of vertices of the larger array. The range array is the same size as an array of vertices (for this chunk). The uppermost element of the range is never used. */ for(k= 0; k < nz; k++) { for(j= 0; j < ny; j++) { for(i= 0; i < nx; i++) { base= i+stx+(j+sty)*ngx+(k+stz)*ngx*ngy; lo= data[base]; hi= lo; val= data[base+1]; if(val < lo) lo= val; if(val > hi) hi= val; val= data[base+ngx]; if(val < lo) lo= val; if(val > hi) hi= val; val= data[base+1+ngx]; if(val < lo) lo= val; if(val > hi) hi= val; val= data[base+ngx*ngy]; if(val < lo) lo= val; if(val > hi) hi= val; val= data[base+1+ngx*ngy]; if(val < lo) lo= val; if(val > hi) hi= val; val= data[base+ngx+ngx*ngy]; if(val < lo) lo= val; if(val > hi) hi= val; val= data[base+1+ngx+ngx*ngy]; if(val < lo) lo= val; if(val > hi) hi= val; nbase= i+j*nx+k*nx*ny; rng[nbase].lo= lo; rng[nbase].hi= hi; } } } } void nextblk(long *trsiz, OctRange *oldr, OctRange *nrng) { long oldnx= trsiz[0]; long oldny= trsiz[1]; long oldnz= trsiz[2]; long newnx= trsiz[3]; long newny= trsiz[4]; long i, j, k, base, nbase; double lo, hi, loval, hival; /* NOTE: nx, ny, and nz are numbers of cells. The number of vertices is one more. The range array is the same size as an array of cells. The uppermost element of the range is never used. */ /* Run through all 2x2x2 groups of cells. NOTE: The loops must check for cases where the block being collapsed isn't a full 2x2x2. */ for(k= 0; k < oldnz-1; k+= 2) { for(j= 0; j < oldny-1; j += 2) { for(i= 0; i < oldnx-1; i += 2) { base= i+j*oldnx+k*oldnx*oldny; lo= oldr[base].lo; hi= oldr[base].hi; loval= oldr[base+1].lo; hival= oldr[base+1].hi; if(loval < lo) lo= loval; if(hival > hi) hi= hival; loval= oldr[base+oldnx].lo; hival= oldr[base+oldnx].hi; if(loval < lo) lo= loval; if(hival > hi) hi= hival; loval= oldr[base+1+oldnx].lo; hival= oldr[base+1+oldnx].hi; if(loval < lo) lo= loval; if(hival > hi) hi= hival; loval= oldr[base+oldnx*oldny].lo; hival= oldr[base+oldnx*oldny].hi; if(loval < lo) lo= loval; if(hival > hi) hi= hival; loval= oldr[base+1+oldnx*oldny].lo; hival= oldr[base+1+oldnx*oldny].hi; if(loval < lo) lo= loval; if(hival > hi) hi= hival; loval= oldr[base+oldnx+oldnx*oldny].lo; hival= oldr[base+oldnx+oldnx*oldny].hi; if(loval < lo) lo= loval; if(hival > hi) hi= hival; loval= oldr[base+1+oldnx+oldnx*oldny].lo; hival= oldr[base+1+oldnx+oldnx*oldny].hi; if(loval < lo) lo= loval; if(hival > hi) hi= hival; nbase= i/2+(j/2)*newnx+(k/2)*newnx*newny; nrng[nbase].lo= lo; nrng[nbase].hi= hi; } if(oldnx & 1) { i= oldnx-1; base= i+j*oldnx+k*oldnx*oldny; lo= oldr[base].lo; hi= oldr[base].hi; loval= oldr[base+oldnx].lo; hival= oldr[base+oldnx].hi; if(loval < lo) lo= loval; if(hival > hi) hi= hival; loval= oldr[base+oldnx*oldny].lo; hival= oldr[base+oldnx*oldny].hi; if(loval < lo) lo= loval; if(hival > hi) hi= hival; loval= oldr[base+oldnx+oldnx*oldny].lo; hival= oldr[base+oldnx+oldnx*oldny].hi; if(loval < lo) lo= loval; if(hival > hi) hi= hival; nbase= i/2+(j/2)*newnx+(k/2)*newnx*newny; nrng[nbase].lo= lo; nrng[nbase].hi= hi; } } if(oldny & 1) { j= oldny-1; for(i= 0; i < oldnx-1; i += 2) { base= i+j*oldnx+k*oldnx*oldny; lo= oldr[base].lo; hi= oldr[base].hi; loval= oldr[base+1].lo; hival= oldr[base+1].hi; if(loval < lo) lo= loval; if(hival > hi) hi= hival; loval= oldr[base+oldnx*oldny].lo; hival= oldr[base+oldnx*oldny].hi; if(loval < lo) lo= loval; if(hival > hi) hi= hival; loval= oldr[base+1+oldnx*oldny].lo; hival= oldr[base+1+oldnx*oldny].hi; if(loval < lo) lo= loval; if(hival > hi) hi= hival; nbase= i/2+(j/2)*newnx+(k/2)*newnx*newny; nrng[nbase].lo= lo; nrng[nbase].hi= hi; } if(oldnx & 1) { i= oldnx-1; base= i+j*oldnx+k*oldnx*oldny; lo= oldr[base].lo; hi= oldr[base].hi; loval= oldr[base+oldnx*oldny].lo; hival= oldr[base+oldnx*oldny].hi; if(loval < lo) lo= loval; if(hival > hi) hi= hival; nbase= i/2+(j/2)*newnx+(k/2)*newnx*newny; nrng[nbase].lo= lo; nrng[nbase].hi= hi; } } } if(oldnz & 1) { k= oldnz-1; for(j= 0; j < oldny-1; j += 2) { for(i= 0; i < oldnx-1; i += 2) { base= i+j*oldnx+k*oldnx*oldny; lo= oldr[base].lo; hi= oldr[base].hi; loval= oldr[base+1].lo; hival= oldr[base+1].hi; if(loval < lo) lo= loval; if(hival > hi) hi= hival; loval= oldr[base+oldnx].lo; hival= oldr[base+oldnx].hi; if(loval < lo) lo= loval; if(hival > hi) hi= hival; loval= oldr[base+1+oldnx].lo; hival= oldr[base+1+oldnx].hi; if(loval < lo) lo= loval; if(hival > hi) hi= hival; nbase= i/2+(j/2)*newnx+(k/2)*newnx*newny; nrng[nbase].lo= lo; nrng[nbase].hi= hi; } if(oldnx & 1) { i= oldnx-1; base= i+j*oldnx+k*oldnx*oldny; lo= oldr[base].lo; hi= oldr[base].hi; loval= oldr[base+oldnx].lo; hival= oldr[base+oldnx].hi; if(loval < lo) lo= loval; if(hival > hi) hi= hival; nbase= i/2+(j/2)*newnx+(k/2)*newnx*newny; nrng[nbase].lo= lo; nrng[nbase].hi= hi; } } if(oldny & 1) { j= oldny-1; for(i= 0; i < oldnx-1; i += 2) { base= i+j*oldnx+k*oldnx*oldny; lo= oldr[base].lo; hi= oldr[base].hi; loval= oldr[base+1].lo; hival= oldr[base+1].hi; if(loval < lo) lo= loval; if(hival > hi) hi= hival; nbase= i/2+(j/2)*newnx+(k/2)*newnx*newny; nrng[nbase].lo= lo; nrng[nbase].hi= hi; } if(oldnx & 1) { i= oldnx-1; base= i+j*oldnx+k*oldnx*oldny; lo= oldr[base].lo; hi= oldr[base].hi; nbase= i/2+(j/2)*newnx+(k/2)*newnx*newny; nrng[nbase].lo= lo; nrng[nbase].hi= hi; } } } } int ycContourTree(double deltas[3], double origin[3], double level, double *var, TriArrayGrp *triangles, OctTree *tree) { long depth; /* prepare the case table for the iso-surfaces, if not already done */ if(!have_iso_cases) ycPrepIsoTet(); /* This function draws an iso-surface using a pre-computed octree. */ t_sizes= tree->size; t_chunk= tree->chunk; t_start= tree->start; t_deltas= deltas; t_origin= origin; t_level= level; t_var= var; t_vcen= 0; t_var2= 0; t_triangles= triangles; #ifdef OLD_ISO_STUFF t_tree= tree; t_maxdepth= tree->maxdepth; #endif t_trsiz= tree->trsiz; t_offsets= tree->offsets; t_ranges= tree->ranges; t_ptndx= 0; #ifdef DO_STATS numscan= 0; numcross= 0; #endif /* NOTE: a chunk does not include any guard cells */ if (!var || t_chunk[0] < 2 || t_chunk[1] < 2 || t_chunk[2] < 2) { return 0; } triangles->numTri= 0; depth= tree->maxdepth-1; /* depth as a C-style index */ do_blk(0, 0, 0, depth); if(triangles->numTri) return 1; else return 0; } int ycContourTree2(double deltas[3], double origin[3], double level, double *var, double *var2, TriArrayGrp *triangles, OctTree *tree) { long depth; /* prepare the case table for the iso-surfaces, if not already done */ if(!have_iso_cases) ycPrepIsoTet(); /* This function draws an iso-surface using a pre-computed octree. */ t_sizes= tree->size; t_chunk= tree->chunk; t_start= tree->start; t_deltas= deltas; t_origin= origin; t_level= level; t_var= var; t_vcen= 0; t_var2= var2; t_triangles= triangles; #ifdef OLD_ISO_STUFF t_tree= tree; t_maxdepth= tree->maxdepth; #endif t_trsiz= tree->trsiz; t_offsets= tree->offsets; t_ranges= tree->ranges; t_ptndx= 0; #ifdef DO_STATS numscan= 0; numcross= 0; #endif /* NOTE: a chunk does not include any guard cells */ if (!var || t_chunk[0] < 2 || t_chunk[1] < 2 || t_chunk[2] < 2) { return 0; } triangles->numTri= 0; depth= tree->maxdepth-1; /* depth as a C-style index */ do_blk(0, 0, 0, depth); if(triangles->numTri) return 1; else return 0; } int ycContourTreeCrv(double level, yPoint3D *xyz, double *var, TriArrayGrp *triangles, OctTree *tree) { long depth; /* prepare the case table for the iso-surfaces, if not already done */ if(!have_iso_cases) ycPrepIsoTet(); /* This function draws an iso-surface using a pre-computed octree. */ t_sizes= tree->size; t_chunk= tree->chunk; t_start= tree->start; t_deltas= 0; t_origin= 0; t_level= level; t_var= var; t_vcen= 0; t_var2= 0; t_xyz= xyz; t_triangles= triangles; #ifdef OLD_ISO_STUFF t_tree= tree; t_maxdepth= tree->maxdepth; #endif t_trsiz= tree->trsiz; t_offsets= tree->offsets; t_ranges= tree->ranges; t_ptndx= 0; #ifdef DO_STATS numscan= 0; numcross= 0; #endif /* NOTE: a chunk does not include any guard cells */ if (!var || t_chunk[0] < 2 || t_chunk[1] < 2 || t_chunk[2] < 2) { return 0; } triangles->numTri= 0; depth= tree->maxdepth-1; /* depth as a C-style index */ do_blk(0, 0, 0, depth); if(triangles->numTri) return 1; else return 0; } int ycContourTreeCrv2(double level, yPoint3D *xyz, double *var, double *var2, TriArrayGrp *triangles, OctTree *tree) { long depth; /* prepare the case table for the iso-surfaces, if not already done */ if(!have_iso_cases) ycPrepIsoTet(); /* This function draws an iso-surface using a pre-computed octree. */ t_sizes= tree->size; t_chunk= tree->chunk; t_start= tree->start; t_deltas= 0; t_origin= 0; t_level= level; t_var= var; t_vcen= 0; t_var2= var2; t_xyz= xyz; t_triangles= triangles; #ifdef OLD_ISO_STUFF t_tree= tree; t_maxdepth= tree->maxdepth; #endif t_trsiz= tree->trsiz; t_offsets= tree->offsets; t_ranges= tree->ranges; t_ptndx= 0; #ifdef DO_STATS numscan= 0; numcross= 0; #endif /* NOTE: a chunk does not include any guard cells */ if (!var || t_chunk[0] < 2 || t_chunk[1] < 2 || t_chunk[2] < 2) { return 0; } triangles->numTri= 0; depth= tree->maxdepth-1; /* depth as a C-style index */ do_blk(0, 0, 0, depth); if(triangles->numTri) return 1; else return 0; } int ycContourTreeZcen(double deltas[3], double origin[3], double level, double *var, double *vcen, TriArrayGrp *triangles, OctTree *tree) { long depth; /* prepare the case table for the iso-surfaces, if not already done */ if(!have_iso_cases) ycPrepIsoTet(); /* This function draws an iso-surface using a pre-computed octree. */ t_sizes= tree->size; t_chunk= tree->chunk; t_start= tree->start; t_deltas= deltas; t_origin= origin; t_level= level; t_var= var; t_vcen= vcen; t_var2= 0; t_triangles= triangles; #ifdef OLD_ISO_STUFF t_tree= tree; t_maxdepth= tree->maxdepth; #endif t_trsiz= tree->trsiz; t_offsets= tree->offsets; t_ranges= tree->ranges; t_ptndx= 0; #ifdef DO_STATS numscan= 0; numcross= 0; #endif /* NOTE: a chunk does not include any guard cells */ if (!var || t_chunk[0] < 2 || t_chunk[1] < 2 || t_chunk[2] < 2) { return 0; } triangles->numTri= 0; depth= tree->maxdepth-1; /* depth as a C-style index */ do_blk(0, 0, 0, depth); if(triangles->numTri) return 1; else return 0; } int ycContourTreeZcen2(double deltas[3], double origin[3], double level, double *var, double *vcen, double *var2, TriArrayGrp *triangles, OctTree *tree) { long depth; /* prepare the case table for the iso-surfaces, if not already done */ if(!have_iso_cases) ycPrepIsoTet(); /* This function draws an iso-surface using a pre-computed octree. */ t_sizes= tree->size; t_chunk= tree->chunk; t_start= tree->start; t_deltas= deltas; t_origin= origin; t_level= level; t_var= var; t_vcen= vcen; t_var2= var2; t_triangles= triangles; #ifdef OLD_ISO_STUFF t_tree= tree; t_maxdepth= tree->maxdepth; #endif t_trsiz= tree->trsiz; t_offsets= tree->offsets; t_ranges= tree->ranges; t_ptndx= 0; #ifdef DO_STATS numscan= 0; numcross= 0; #endif /* NOTE: a chunk does not include any guard cells */ if (!var || t_chunk[0] < 2 || t_chunk[1] < 2 || t_chunk[2] < 2) { return 0; } triangles->numTri= 0; depth= tree->maxdepth-1; /* depth as a C-style index */ do_blk(0, 0, 0, depth); if(triangles->numTri) return 1; else return 0; } int ycContourTreeCrvZcen(double level, yPoint3D *xyz, double *var, double *vcen, TriArrayGrp *triangles, OctTree *tree) { long depth; /* prepare the case table for the iso-surfaces, if not already done */ if(!have_iso_cases) ycPrepIsoTet(); /* This function draws an iso-surface using a pre-computed octree. */ t_sizes= tree->size; t_chunk= tree->chunk; t_start= tree->start; t_deltas= 0; t_origin= 0; t_level= level; t_var= var; t_vcen= vcen; t_var2= 0; t_xyz= xyz; t_triangles= triangles; #ifdef OLD_ISO_STUFF t_tree= tree; t_maxdepth= tree->maxdepth; #endif t_trsiz= tree->trsiz; t_offsets= tree->offsets; t_ranges= tree->ranges; t_ptndx= 0; #ifdef DO_STATS numscan= 0; numcross= 0; #endif /* NOTE: a chunk does not include any guard cells */ if (!var || t_chunk[0] < 2 || t_chunk[1] < 2 || t_chunk[2] < 2) { return 0; } triangles->numTri= 0; depth= tree->maxdepth-1; /* depth as a C-style index */ do_blk(0, 0, 0, depth); if(triangles->numTri) return 1; else return 0; } int ycContourTreeCrvZcen2(double level, yPoint3D *xyz, double *var, double *vcen, double *var2, TriArrayGrp *triangles, OctTree *tree) { long depth; /* prepare the case table for the iso-surfaces, if not already done */ if(!have_iso_cases) ycPrepIsoTet(); /* This function draws an iso-surface using a pre-computed octree. */ t_sizes= tree->size; t_chunk= tree->chunk; t_start= tree->start; t_deltas= 0; t_origin= 0; t_level= level; t_var= var; t_vcen= vcen; t_var2= var2; t_xyz= xyz; t_triangles= triangles; #ifdef OLD_ISO_STUFF t_tree= tree; t_maxdepth= tree->maxdepth; #endif t_trsiz= tree->trsiz; t_offsets= tree->offsets; t_ranges= tree->ranges; t_ptndx= 0; #ifdef DO_STATS numscan= 0; numcross= 0; #endif /* NOTE: a chunk does not include any guard cells */ if (!var || t_chunk[0] < 2 || t_chunk[1] < 2 || t_chunk[2] < 2) { return 0; } triangles->numTri= 0; depth= tree->maxdepth-1; /* depth as a C-style index */ do_blk(0, 0, 0, depth); if(triangles->numTri) return 1; else return 0; } int ycContourTreeVarr(double deltas[3], double origin[3], double level, double *var, TriVertexGrp *triangles, OctTree *tree, long *edgndx) { long i, nedg, depth, nx, ny, xy_siz; /* prepare the case table for the iso-surfaces, if not already done */ if(!have_iso_cases) ycPrepIsoTet(); /* This function draws an iso-surface using a pre-computed octree. */ t_sizes= tree->size; t_chunk= tree->chunk; t_start= tree->start; t_deltas= deltas; t_origin= origin; t_level= level; t_var= var; t_vcen= 0; t_var2= 0; t_triangles= (TriArrayGrp *) triangles; #ifdef OLD_ISO_STUFF t_tree= tree; t_maxdepth= tree->maxdepth; #endif t_trsiz= tree->trsiz; t_offsets= tree->offsets; t_ranges= tree->ranges; t_ptndx= edgndx; nx= t_chunk[0]; ny= t_chunk[1]; xy_siz= nx*ny; v_edg_offset[0]= 0; v_edg_offset[1]= 4; v_edg_offset[2]= 3*nx; v_edg_offset[3]= 1; v_edg_offset[4]= 3*xy_siz; v_edg_offset[5]= 3*xy_siz+4; v_edg_offset[6]= 3*xy_siz+3*nx; v_edg_offset[7]= 3*xy_siz+1; v_edg_offset[8]= 2; v_edg_offset[9]= 5; v_edg_offset[10]= 3*nx+5; v_edg_offset[11]= 3*nx+2; #ifdef DO_STATS numscan= 0; numcross= 0; #endif /* NOTE: a chunk does not include any guard cells */ if (!var || t_chunk[0] < 2 || t_chunk[1] < 2 || t_chunk[2] < 2) { return 0; } /* MUST clear both the number of triangles and the number of edges cut here */ triangles->numTri= 0; triangles->numEdg= 0; /* adjust so that the array indicates no vertices have yet been found */ nedg= 3*t_chunk[0]*t_chunk[1]*t_chunk[2]; for(i= 0; i <= nedg; i++) edgndx[i]= -1; depth= tree->maxdepth-1; /* depth as a C-style index */ do_blk(0, 0, 0, depth); if(triangles->numTri) return 1; else return 0; } int ycContourTreeVarr2(double deltas[3], double origin[3], double level, double *var, double *var2, TriVertexGrp *triangles, OctTree *tree, long *edgndx) { long i, nedg, depth, nx, ny, xy_siz; /* prepare the case table for the iso-surfaces, if not already done */ if(!have_iso_cases) ycPrepIsoTet(); /* This function draws an iso-surface using a pre-computed octree. */ t_sizes= tree->size; t_chunk= tree->chunk; t_start= tree->start; t_deltas= deltas; t_origin= origin; t_level= level; t_var= var; t_vcen= 0; t_var2= var2; t_triangles= (TriArrayGrp *) triangles; #ifdef OLD_ISO_STUFF t_tree= tree; t_maxdepth= tree->maxdepth; #endif t_trsiz= tree->trsiz; t_offsets= tree->offsets; t_ranges= tree->ranges; t_ptndx= edgndx; nx= t_chunk[0]; ny= t_chunk[1]; xy_siz= nx*ny; v_edg_offset[0]= 0; v_edg_offset[1]= 4; v_edg_offset[2]= 3*nx; v_edg_offset[3]= 1; v_edg_offset[4]= 3*xy_siz; v_edg_offset[5]= 3*xy_siz+4; v_edg_offset[6]= 3*xy_siz+3*nx; v_edg_offset[7]= 3*xy_siz+1; v_edg_offset[8]= 2; v_edg_offset[9]= 5; v_edg_offset[10]= 3*nx+5; v_edg_offset[11]= 3*nx+2; #ifdef DO_STATS numscan= 0; numcross= 0; #endif /* NOTE: a chunk does not include any guard cells */ if (!var || t_chunk[0] < 2 || t_chunk[1] < 2 || t_chunk[2] < 2) { return 0; } /* MUST clear both the number of triangles and the number of edges cut here */ triangles->numTri= 0; triangles->numEdg= 0; /* adjust so that the array indicates no vertices have yet been found */ nedg= 3*t_chunk[0]*t_chunk[1]*t_chunk[2]; for(i= 0; i <= nedg; i++) edgndx[i]= -1; depth= tree->maxdepth-1; /* depth as a C-style index */ do_blk(0, 0, 0, depth); if(triangles->numTri) return 1; else return 0; } int ycContourTreeVarrStr(double deltas[3], double origin[3], double level, double *var, TriVertexGrp *triangles, OctTree *tree, long *edgndx) { long i, nedg, depth; /* prepare the case table for the iso-surfaces, if not already done */ if(!have_iso_cases) ycPrepIsoTet(); /* This function draws an iso-surface using a pre-computed octree. */ t_sizes= tree->size; t_chunk= tree->chunk; t_start= tree->start; t_deltas= deltas; t_origin= origin; t_level= level; t_var= var; t_vcen= 0; t_var2= 0; t_triangles= (TriArrayGrp *) triangles; #ifdef OLD_ISO_STUFF t_tree= tree; t_maxdepth= tree->maxdepth; #endif t_trsiz= tree->trsiz; t_offsets= tree->offsets; t_ranges= tree->ranges; t_ptndx= edgndx; #ifdef DO_STATS numscan= 0; numcross= 0; #endif /* NOTE: a chunk does not include any guard cells */ if (!var || t_chunk[0] < 2 || t_chunk[1] < 2 || t_chunk[2] < 2) { return 0; } triangles->numTri= 0; triangles->numEdg= 0; /* adjust so that the array indicates no vertices have yet been found */ nedg= 3*t_chunk[0]*t_chunk[1]*t_chunk[2]; for(i= 0; i <= nedg; i++) edgndx[i]= -1; depth= tree->maxdepth-1; /* depth as a C-style index */ do_blk(0, 0, 0, depth); if(triangles->numTri) return 1; else return 0; } long do_blk(long i, long j, long k, long depth) { long child_depth, nx, ny, nz, ndx, newi, newj, newk; long ilo, ihi, jlo, jhi, klo, khi; OctRange *the_rng; /* Search the octree for sub-blocks spanning the iso-level. Immediately reject sub-blocks that are not cut. Descend sub-blocks that are cut until reaching a leaf. */ #ifdef DO_STATS numscan++; #endif nx= t_trsiz[3*depth]; ny= t_trsiz[3*depth+1]; nz= t_trsiz[3*depth+2]; ndx= i+j*nx+k*nx*ny; the_rng= t_ranges+t_offsets[depth]+ndx; if(t_level <= the_rng->lo || t_level >= the_rng->hi) { return 0; } if(depth == 0) { /* Have reached a leaf of the tree that is cut by the iso-surface, so generate triangles. */ grab_tris(i, j, k); return 1; } /* The contour level cuts this block. Recursively call this function for all sub-blocks. */ child_depth= depth-1; /* yorick style depth of the child blocks */ nx= t_trsiz[3*child_depth]; ny= t_trsiz[3*child_depth+1]; nz= t_trsiz[3*child_depth+2]; klo= 2*k; khi= klo+1; if(khi > nz-1) khi= nz-1; jlo= 2*j; jhi= jlo+1; if(jhi > ny-1) jhi= ny-1; ilo= 2*i; ihi= ilo+1; if(ihi > nx-1) ihi= nx-1; for(newk= klo; newk <= khi; newk++) { for(newj= jlo; newj <= jhi; newj++) { for(newi= ilo; newi <= ihi; newi++) { do_blk(newi, newj, newk, child_depth); } } } return 1; } long grab_tris(long i, long j, long k) { long iSize= t_sizes[0]; long jSize= t_sizes[1]; long kSize= t_sizes[2]; int res; /* NOTE: on input i,j,k are indices into the chunk that is currently being processed. Convert into indices into the full grid. */ i += t_start[0]; j += t_start[1]; k += t_start[2]; if(k <= 0 || k >= kSize-2) { /* k is bad - it must be in the interior of the array because there are guard cells */ } if(j <= 0 || j >= jSize-2) { /* j is bad - it must be in the interior of the array because there are guard cells */ } if(i <= 0 || i >= iSize-2) { /* i is bad - it must be in the interior of the array because there are guard cells */ } /* call the appropriate routine for this grid etc. */ if(t_ptndx) { /* call the routine for point centered data and vertex arrays */ res= grab_tris_varr(i, j, k); return res; } if(t_vcen) { /* call the routine for cell centered data */ res= grab_tris_zcen(i, j, k); return res; } if(t_xyz) { /* call the routine for curvilinear grids */ res= grab_tris_crv(i, j, k); return res; } /* the default is point centered data on a regular Cartesian grid */ res= grab_tris_ijk(i, j, k); return res; } long grab_tris_ijk(long i, long j, long k) { long iSize= t_sizes[0]; long jSize= t_sizes[1]; long kSize= t_sizes[2]; double dx, dy, dz, x0, y0, z0; double s[8], vars[8], *var2; long ijSize, numTri, *cellIDs; int idxvg, idxv, ii, index, mask; yPoint3D *xyzverts, *normals, pts[8], gradients[8]; /* This cell spans the iso-level. Generate the proper triangles using MarchingCubes style case tables. */ /* NOTE: on input i,j,k are indices into the full grid. */ ijSize = iSize * jSize; dx= t_deltas[0]; dy= t_deltas[1]; dz= t_deltas[2]; x0= t_origin[0]; y0= t_origin[1]; z0= t_origin[2]; cellIDs = t_triangles->cellIDs; xyzverts = t_triangles->xyzverts; var2 = t_triangles->var2; normals = t_triangles->normals; numTri= t_triangles->numTri; #ifdef DO_STATS numcross++; #endif /* get data values at the corners */ idxvg = i + j*iSize + k*ijSize; idxv = i-t_start[0] + (j-t_start[1])*t_chunk[0] + (k-t_start[2])*t_chunk[0]*t_chunk[1]; s[0] = t_var[idxvg]; s[1] = t_var[idxvg+1]; s[2] = t_var[idxvg+1 + iSize]; s[3] = t_var[idxvg + iSize]; s[4] = t_var[idxvg + ijSize]; s[5] = t_var[idxvg+1 + ijSize]; s[6] = t_var[idxvg+1 + iSize + ijSize]; s[7] = t_var[idxvg + iSize + ijSize]; /* Build the case table */ for ( ii=0, index = 0, mask= 1; ii < 8; ii++, mask += mask) { if ( s[ii] >= t_level ) index |= mask; } if(t_var2) { vars[0] = t_var2[idxvg]; vars[1] = t_var2[idxvg+1]; vars[2] = t_var2[idxvg+1 + iSize]; vars[3] = t_var2[idxvg + iSize]; vars[4] = t_var2[idxvg + ijSize]; vars[5] = t_var2[idxvg+1 + ijSize]; vars[6] = t_var2[idxvg+1 + iSize + ijSize]; vars[7] = t_var2[idxvg + iSize + ijSize]; } /* set coordinates for the corners of the cell */ pts[0].z = z0 + k*dz; pts[0].y = y0 + j*dy; pts[0].x = x0 + i*dx; pts[1].x = pts[0].x + dx; pts[1].y = pts[0].y; pts[1].z = pts[0].z; pts[2].x = pts[0].x + dx; pts[2].y = pts[0].y + dy; pts[2].z = pts[0].z; pts[3].x = pts[0].x; pts[3].y = pts[0].y + dy; pts[3].z = pts[0].z; pts[4].x = pts[0].x; pts[4].y = pts[0].y; pts[4].z = pts[0].z + dz; pts[5].x = pts[0].x + dx; pts[5].y = pts[0].y; pts[5].z = pts[0].z + dz; pts[6].x = pts[0].x + dx; pts[6].y = pts[0].y + dy; pts[6].z = pts[0].z + dz; pts[7].x = pts[0].x; pts[7].y = pts[0].y + dy; pts[7].z = pts[0].z + dz; /* create gradients (i,j,k are global indices) */ ycPointGradientAll(i, j, k, iSize, jSize, kSize, t_var, dx, dy, dz, gradients); extract_tris_tet(index, idxvg, t_var2, &numTri, t_level, s, pts, gradients, vars, cellIDs, xyzverts, normals, var2); /* WARNING: caller must be sure triangle array doesn't overflow. */ t_triangles->numTri= numTri; return 0; } long grab_tris_crv(long i, long j, long k) { long iSize= t_sizes[0]; long jSize= t_sizes[1]; long kSize= t_sizes[2]; double s[8], vars[8], *var2; long ijSize, numTri, *cellIDs; int idxv, idxvg, ii, index, mask; yPoint3D *xyzverts, *normals, pts[8], gradients[8]; cellIDs = t_triangles->cellIDs; xyzverts = t_triangles->xyzverts; var2 = t_triangles->var2; normals = t_triangles->normals; numTri= t_triangles->numTri; #ifdef DO_STATS numcross++; #endif /* This cell spans the iso-level. Generate the proper triangles using MarchingCubes style case tables. */ /* NOTE: on input i,j,k are indices into the full grid. */ ijSize = iSize * jSize; /* get data values at the corners */ idxvg = i + j*iSize + k*ijSize; s[0] = t_var[idxvg]; s[1] = t_var[idxvg+1]; s[2] = t_var[idxvg+1 + iSize]; s[3] = t_var[idxvg + iSize]; s[4] = t_var[idxvg + ijSize]; s[5] = t_var[idxvg+1 + ijSize]; s[6] = t_var[idxvg+1 + iSize + ijSize]; s[7] = t_var[idxvg + iSize + ijSize]; /* Build the case table */ for ( ii=0, index = 0, mask= 1; ii < 8; ii++, mask += mask) { if ( s[ii] >= t_level ) index |= mask; } if(t_var2) { vars[0] = t_var2[idxvg]; vars[1] = t_var2[idxvg+1]; vars[2] = t_var2[idxvg+1 + iSize]; vars[3] = t_var2[idxvg + iSize]; vars[4] = t_var2[idxvg + ijSize]; vars[5] = t_var2[idxvg+1 + ijSize]; vars[6] = t_var2[idxvg+1 + iSize + ijSize]; vars[7] = t_var2[idxvg + iSize + ijSize]; } /* set coordinates for the corners of the cell */ pts[0] = t_xyz[idxvg]; pts[1] = t_xyz[idxvg+1]; pts[2] = t_xyz[idxvg+1+iSize]; pts[3] = t_xyz[idxvg +iSize]; pts[4] = t_xyz[idxvg +ijSize]; pts[5] = t_xyz[idxvg+1 +ijSize]; pts[6] = t_xyz[idxvg+1+iSize+ijSize]; pts[7] = t_xyz[idxvg +iSize+ijSize]; /* create gradients */ ycPointGradientCrv(i, j, k, iSize, jSize, kSize, t_xyz, t_var, gradients ); ycPointGradientCrv(i+1, j, k, iSize, jSize, kSize, t_xyz, t_var, gradients+1); ycPointGradientCrv(i+1, j+1, k, iSize, jSize, kSize, t_xyz, t_var, gradients+2); ycPointGradientCrv(i, j+1, k, iSize, jSize, kSize, t_xyz, t_var, gradients+3); ycPointGradientCrv(i, j, k+1, iSize, jSize, kSize, t_xyz, t_var, gradients+4); ycPointGradientCrv(i+1, j, k+1, iSize, jSize, kSize, t_xyz, t_var, gradients+5); ycPointGradientCrv(i+1, j+1, k+1, iSize, jSize, kSize, t_xyz, t_var, gradients+6); ycPointGradientCrv(i, j+1, k+1, iSize, jSize, kSize, t_xyz, t_var, gradients+7); idxv = i-t_start[0] + (j-t_start[1])*t_chunk[0] + (k-t_start[2])*t_chunk[0]*t_chunk[1]; extract_tris_tet(index, idxvg, t_var2, &numTri, t_level, s, pts, gradients, vars, cellIDs, xyzverts, normals, var2); /* WARNING: caller must be sure triangle array doesn't overflow. */ t_triangles->numTri= numTri; return 0; } long grab_tris_zcen(long i, long j, long k) { long iSize= t_sizes[0]; long jSize= t_sizes[1]; double dx, dy, dz, x0, y0, z0; double s[8], vars[8], *var2; long ijSize, numTri, *cellIDs; int res; int idxv, idxvg, ii, index, mask; yPoint3D *xyzverts, *normals, pts[8], gradients[8]; if(t_xyz) { /* call the routine for curvilinear grids with cell centered data */ res= grab_tris_zcen_crv(i, j, k); return res; } dx= t_deltas[0]; dy= t_deltas[1]; dz= t_deltas[2]; x0= t_origin[0]; y0= t_origin[1]; z0= t_origin[2]; cellIDs = t_triangles->cellIDs; xyzverts = t_triangles->xyzverts; var2 = t_triangles->var2; normals = t_triangles->normals; numTri= t_triangles->numTri; #ifdef DO_STATS numcross++; #endif /* This cell spans the iso-level. Generate the proper triangles using MarchingCubes style case tables. */ /* NOTE: on input i,j,k are indices into the full grid. */ ijSize = iSize * jSize; /* get data values at the corners */ idxvg = i + j*iSize + k*ijSize; s[0] = t_vcen[idxvg]; s[1] = t_vcen[idxvg+1]; s[2] = t_vcen[idxvg+1 + iSize]; s[3] = t_vcen[idxvg + iSize]; s[4] = t_vcen[idxvg + ijSize]; s[5] = t_vcen[idxvg+1 + ijSize]; s[6] = t_vcen[idxvg+1 + iSize + ijSize]; s[7] = t_vcen[idxvg + iSize + ijSize]; /* Build the case table */ for ( ii=0, index = 0, mask= 1; ii < 8; ii++, mask += mask) { if ( s[ii] >= t_level ) index |= mask; } if(t_var2) { /* NOTE: var2 must be point centered by the caller */ vars[0] = t_var2[idxvg]; vars[1] = t_var2[idxvg+1]; vars[2] = t_var2[idxvg+1 + iSize]; vars[3] = t_var2[idxvg + iSize]; vars[4] = t_var2[idxvg + ijSize]; vars[5] = t_var2[idxvg+1 + ijSize]; vars[6] = t_var2[idxvg+1 + iSize + ijSize]; vars[7] = t_var2[idxvg + iSize + ijSize]; } /* set coordinates for the corners of the cell */ pts[0].z = z0 + k*dz; pts[0].y = y0 + j*dy; pts[0].x = x0 + i*dx; pts[1].x = pts[0].x + dx; pts[1].y = pts[0].y; pts[1].z = pts[0].z; pts[2].x = pts[0].x + dx; pts[2].y = pts[0].y + dy; pts[2].z = pts[0].z; pts[3].x = pts[0].x; pts[3].y = pts[0].y + dy; pts[3].z = pts[0].z; pts[4].x = pts[0].x; pts[4].y = pts[0].y; pts[4].z = pts[0].z + dz; pts[5].x = pts[0].x + dx; pts[5].y = pts[0].y; pts[5].z = pts[0].z + dz; pts[6].x = pts[0].x + dx; pts[6].y = pts[0].y + dy; pts[6].z = pts[0].z + dz; pts[7].x = pts[0].x; pts[7].y = pts[0].y + dy; pts[7].z = pts[0].z + dz; /* create gradients */ ycPointGradientIntGrdAllZcen(i, j, k, iSize, jSize, dx, dy, dz, t_vcen, gradients); idxv = i-t_start[0] + (j-t_start[1])*t_chunk[0] + (k-t_start[2])*t_chunk[0]*t_chunk[1]; extract_tris_tet(index, idxvg, t_var2, &numTri, t_level, s, pts, gradients, vars, cellIDs, xyzverts, normals, var2); /* WARNING: caller must be sure triangle array doesn't overflow. */ t_triangles->numTri= numTri; return 0; } long grab_tris_zcen_crv(long i, long j, long k) { long iSize= t_sizes[0]; long jSize= t_sizes[1]; double s[8], vars[8]; long ijSize, numTri, *cellIDs; int idxv, idxvg, ii, index, mask; double *var2; yPoint3D *xyzverts, *normals, pts[8], gradients[8]; cellIDs = t_triangles->cellIDs; xyzverts = t_triangles->xyzverts; var2 = t_triangles->var2; normals = t_triangles->normals; numTri= t_triangles->numTri; #ifdef DO_STATS numcross++; #endif /* This cell spans the iso-level. Generate the proper triangles using MarchingCubes style case tables. */ /* NOTE: on input i,j,k are indices into the full grid. */ ijSize = iSize * jSize; /* get data values at the corners */ idxvg = i + j*iSize + k*ijSize; s[0] = t_vcen[idxvg]; s[1] = t_vcen[idxvg+1]; s[2] = t_vcen[idxvg+1 + iSize]; s[3] = t_vcen[idxvg + iSize]; s[4] = t_vcen[idxvg + ijSize]; s[5] = t_vcen[idxvg+1 + ijSize]; s[6] = t_vcen[idxvg+1 + iSize + ijSize]; s[7] = t_vcen[idxvg + iSize + ijSize]; /* Build the case table */ for ( ii=0, index = 0, mask= 1; ii < 8; ii++, mask += mask) { if ( s[ii] >= t_level ) index |= mask; } if(t_var2) { /* NOTE: var2 must be point centered by the caller */ vars[0] = t_var2[idxvg]; vars[1] = t_var2[idxvg+1]; vars[2] = t_var2[idxvg+1 + iSize]; vars[3] = t_var2[idxvg + iSize]; vars[4] = t_var2[idxvg + ijSize]; vars[5] = t_var2[idxvg+1 + ijSize]; vars[6] = t_var2[idxvg+1 + iSize + ijSize]; vars[7] = t_var2[idxvg + iSize + ijSize]; } /* set coordinates for the corners of the cell */ pts[0] = t_xyz[idxvg]; pts[1] = t_xyz[idxvg+1]; pts[2] = t_xyz[idxvg+1+iSize]; pts[3] = t_xyz[idxvg +iSize]; pts[4] = t_xyz[idxvg +ijSize]; pts[5] = t_xyz[idxvg+1 +ijSize]; pts[6] = t_xyz[idxvg+1+iSize+ijSize]; pts[7] = t_xyz[idxvg +iSize+ijSize]; /* create gradients */ ycPointGradientCrvgAllZcen(idxvg, iSize, jSize, t_xyz+idxvg, t_vcen, gradients); idxv = i-t_start[0] + (j-t_start[1])*t_chunk[0] + (k-t_start[2])*t_chunk[0]*t_chunk[1]; extract_tris_tet(index, idxvg, t_var2, &numTri, t_level, s, pts, gradients, vars, cellIDs, xyzverts, normals, var2); /* WARNING: caller must be sure triangle array doesn't overflow. */ t_triangles->numTri= numTri; return 0; } void ycPointGradientIntGrdAllZcen(long i, long j, long k, long iSize, long jSize, double dx, double dy, double dz, double *var, yPoint3D gradient[8]) { long ijSize= iSize*jSize; long ibase; long ii, jj, kk, pp; long ioff[]= {0,1,1,0,0,1,1,0}; long joff[]= {0,0,1,1,0,0,1,1}; long koff[]= {0,0,0,0,1,1,1,1}; double v15, v35, v55, v75; /* Approximate the gradient at the vertex from the data at the surrounding zone centers. Guaranteed that the vertex is in the interior of the mesh. On entry, (i,j,k) is the index of the point. Convert to the index of the cell to the lower left bottom from this point before accessing var. */ for(pp= 0; pp < 8; pp++) { ii= i+ioff[pp]; jj= j+joff[pp]; kk= k+koff[pp]; ibase= ii + jj*iSize + kk*ijSize; v15= var[ibase]+var[ibase-1]; v35= var[ibase-iSize]+var[ibase-1-iSize]; v55= var[ibase-ijSize]+var[ibase-1-ijSize]; v75= var[ibase-iSize-ijSize]+var[ibase-1-iSize-ijSize]; /* x-direction */ gradient[pp].x = 0.25/dx*(var[ibase]-var[ibase-1]+var[ibase-iSize]-var[ibase-1-iSize] +var[ibase-ijSize]-var[ibase-1-ijSize] +var[ibase-iSize-ijSize]-var[ibase-1-iSize-ijSize]) ; /* y-direction */ gradient[pp].y = 0.25/dy*(v55-v75+v15-v35); /* z-direction */ gradient[pp].z = 0.25/dz*(v15-v55+v35-v75); } } void ycPointGradientCrvgAllZcen(long idxvg, long iSize, long jSize, yPoint3D *x, double *var, yPoint3D gradient[8]) { double dvar, del2; long ijSize= iSize*jSize; long gbase, pp; yPoint3D delta; long voff[8]; voff[0]= 0; voff[1]= 1; voff[2]= 1+iSize; voff[3]= iSize; voff[4]= ijSize; voff[5]= 1+ijSize; voff[6]= 1+iSize+ijSize; voff[7]= iSize+ijSize; /* idxvg is the index of the point at the "lower" corner of the cell. */ for(pp= 0; pp < 8; pp++) { gbase= idxvg+voff[pp]; /* i-direction */ dvar = var[gbase+1] - var[gbase-1]; delta.x= x[gbase+1].x-x[gbase-1].x; delta.y= x[gbase+1].y-x[gbase-1].y; delta.z= x[gbase+1].z-x[gbase-1].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; gradient[pp].x = dvar*delta.x / del2; gradient[pp].y = dvar*delta.y / del2; gradient[pp].z = dvar*delta.z / del2; /* j-direction */ dvar = var[gbase+iSize] - var[gbase-iSize]; delta.x= x[gbase+iSize].x-x[gbase-iSize].x; delta.y= x[gbase+iSize].y-x[gbase-iSize].y; delta.z= x[gbase+iSize].z-x[gbase-iSize].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; gradient[pp].x += dvar*delta.x / del2; gradient[pp].y += dvar*delta.y / del2; gradient[pp].z += dvar*delta.z / del2; /* k-direction */ dvar = var[gbase+ijSize] - var[gbase-ijSize]; delta.x= x[gbase+ijSize].x-x[gbase-ijSize].x; delta.y= x[gbase+ijSize].y-x[gbase-ijSize].y; delta.z= x[gbase+ijSize].z-x[gbase-ijSize].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; gradient[pp].x += dvar*delta.x / del2; gradient[pp].y += dvar*delta.y / del2; gradient[pp].z += dvar*delta.z / del2; } } /* Extract an iso-surface from data on a regular 3D grid. ndx is an edge centered scratch array. All elements are initially -1. Each time an edge is cut by the iso-surface, ndx is checked for that edge. If it is -1, the vertex and gradient are appended to the output lists and the position in the list is stored in ndx. This means that the vertices and gradients are only stored once, even though they are ordinarily shared by at least 4 triangles. Each triangle in the output list is described via three indices into the vertex and gradient lists. */ long grab_tris_varr(long i, long j, long k) { TriVertexGrp *v_triangles= (TriVertexGrp *) t_triangles; long iSize= t_sizes[0]; long jSize= t_sizes[1]; long kSize= t_sizes[2]; long ijSize= iSize*jSize; double dx, dy, dz, x0, y0, z0; double s[8], vars[8], *var2; long numEdg, *triStart, *ptndx; long numTri, *cellIDs, iOrigin, jOrigin, kOrigin, *nTris, *ndx; int idxc, idxv, idxcg, idxvg, ii, case_index, mask; yPoint3D *xyzverts, *normals, pts[8], gradients[8]; iOrigin= t_start[0]; jOrigin= t_start[1]; kOrigin= t_start[2]; dx= t_deltas[0]; dy= t_deltas[1]; dz= t_deltas[2]; x0= t_origin[0]; y0= t_origin[1]; z0= t_origin[2]; cellIDs = v_triangles->cellIDs; xyzverts = v_triangles->xyzverts; normals = v_triangles->normals; ptndx= v_triangles->ptndx; var2 = v_triangles->var2; numTri= v_triangles->numTri; numEdg= v_triangles->numEdg; triStart= v_triangles->triStart; nTris= v_triangles->nTris; ndx= t_ptndx; #ifdef DO_STATS numcross++; #endif /* This cell spans the iso-level. Generate the proper triangles using MarchingCubes style case tables. */ /* NOTE: on input i,j,k are indices into the full grid. */ ijSize = iSize * jSize; /* get data values at the corners. adjust (i,j,k) to find the location within the chunk. */ idxv = i-iOrigin + (j-jOrigin)*t_chunk[0] + (k-kOrigin)*t_chunk[0]*t_chunk[1]; /* idxvg is the zero-based index of this vertex within the global array. */ idxvg= i+iSize*j+ijSize*k; idxcg= i+(iSize-1)*j+(iSize-1)*(jSize-1)*k; if(make_strip) { /* record the first triangle for this cell */ triStart[idxv]= numTri; nTris[idxv]= 0; } s[0] = t_var[idxvg]; s[1] = t_var[idxvg+1]; s[2] = t_var[idxvg+1 + iSize]; s[3] = t_var[idxvg + iSize]; s[4] = t_var[idxvg + ijSize]; s[5] = t_var[idxvg+1 + ijSize]; s[6] = t_var[idxvg+1 + iSize + ijSize]; s[7] = t_var[idxvg + iSize + ijSize]; /* Build the case table */ for ( ii=0, case_index = 0, mask= 1; ii < 8; ii++, mask += mask) { if ( s[ii] >= t_level ) case_index |= mask; } if(t_var2) { vars[0] = t_var2[idxvg]; vars[1] = t_var2[idxvg+1]; vars[2] = t_var2[idxvg+1 + iSize]; vars[3] = t_var2[idxvg + iSize]; vars[4] = t_var2[idxvg + ijSize]; vars[5] = t_var2[idxvg+1 + ijSize]; vars[6] = t_var2[idxvg+1 + iSize + ijSize]; vars[7] = t_var2[idxvg + iSize + ijSize]; } /* set coordinates for the corners of the cell */ pts[0].z = z0 + k*dz; pts[0].y = y0 + j*dy; pts[0].x = x0 + i*dx; pts[1].x = pts[0].x + dx; pts[1].y = pts[0].y; pts[1].z = pts[0].z; pts[2].x = pts[0].x + dx; pts[2].y = pts[0].y + dy; pts[2].z = pts[0].z; pts[3].x = pts[0].x; pts[3].y = pts[0].y + dy; pts[3].z = pts[0].z; pts[4].x = pts[0].x; pts[4].y = pts[0].y; pts[4].z = pts[0].z + dz; pts[5].x = pts[0].x + dx; pts[5].y = pts[0].y; pts[5].z = pts[0].z + dz; pts[6].x = pts[0].x + dx; pts[6].y = pts[0].y + dy; pts[6].z = pts[0].z + dz; pts[7].x = pts[0].x; pts[7].y = pts[0].y + dy; pts[7].z = pts[0].z + dz; /* create gradients (i,j,k are global indices) */ ycPointGradientAll(i, j, k, iSize, jSize, kSize, t_var, dx, dy, dz, gradients); extract_tris_tet_ndx(case_index, idxv, idxcg, t_var2, &numTri, &numEdg, t_level, s, pts, gradients, vars, v_edg_offset, cellIDs, ptndx, ndx, xyzverts, normals, var2); /* WARNING: caller must be sure triangle array doesn't overflow. */ v_triangles->numTri= numTri; v_triangles->numEdg= numEdg; if(numTri > 0) return 1; else return 0; } yorick-gl-1.1+cvs20070922+dfsg.orig/glPolys.c0000640000175000017500000004040710515710063020224 0ustar thibautthibaut/* * $Id: glPolys.c,v 1.3 2006/10/19 14:48:19 dhmunro Exp $ */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #include "glcode.h" #include "glfunc.h" #include "glPolys.h" #include "pstdlib.h" #include #include static void yglPolysArrNoLite(long npoly, long *nverts, float *xyz, float *colr); static void yglPolysNoArrNoLite(long npoly, long *nverts, float *xyz, float *colr); static void yglPolysSmArr(long npoly, long *nverts, float *xyz, float *norm, float *colr); static void yglPolysSmNoArr(long npoly, long *nverts, float *xyz, float *norm, float *colr); static void yglPolysArr(long npoly, long *nverts, float *xyz, float *norm, float *colr); static void yglPolysNoArr(long npoly, long *nverts, float *xyz, float *norm, float *colr); /* #define CHEK_ERROR(x) gl_chek_error(x) */ #define CHEK_ERROR(x) void yglPolys(long npolys, long *len, float *xyz, float *norm, float *colr, long edge, long smooth, long do_light) { /* The input is a list of polygons. There is one color per polygon. There is one normal per vertex or one normal per polygon (depending on smooth), or none for no lighting. */ float oldSpec; if(alpha_pass) return; yglSetPolyMode(edge); oldSpec= yglGetMatSpec(); if(!do_light) { yglSetMatSpec(0.0); /* turn off specular highlights */ /* polys are not lit */ yglSetColorType(0); if(glCurrWin3d->use_array) { yglPolysArrNoLite(npolys, len, xyz, colr); } else { yglPolysNoArrNoLite(npolys, len, xyz, colr); } } else if(smooth) { /* smooth shading */ yglSetColorType(1); if(glCurrWin3d->use_array) { yglPolysSmArr(npolys, len, xyz, norm, colr); } else { yglPolysSmNoArr(npolys, len, xyz, norm, colr); } yglSetMatSpec(oldSpec); } else { /* flat shading */ yglSetColorType(1); if(glCurrWin3d->use_array) { yglPolysArr(npolys, len, xyz, norm, colr); } else { yglPolysNoArr(npolys, len, xyz, norm, colr); } } } void yglPolysArr(long npoly, long *nverts, float *xyz, float *norm, float *colr) { /* This function expands each polygon out into a series of triangles and will INCREASE the amount of data sent to the server. */ long i, j; float *arr_colr, *arr_norm, *arr_vert; long ntri, ind, vrt; #ifdef USE_ALPHA long indc; #endif /* draw the polygon list now */ if(npoly <= 0) return; #ifdef USE_ALPHA if(!alpha_pass) return; #else if(alpha_pass) return; #endif #ifdef USE_ALPHA glEnable(GL_BLEND); #endif /* use flat shading (no per-vertex normals supplied) */ yglSetShade(0); yglUpdateProperties(); /* NOTE: cannot use an index list, because the indices must be the same for all active arrays. This means that I could only do one polygon at a time, and that does not seem worthwhile. */ /* compute the number of triangles in the set */ for(i= 0, ntri= 0; i < npoly; i++) { ntri += nverts[i]-2; } /* make an array big enough to hold all the colors, normals, and vertices for the polygon list */ #ifdef USE_ALPHA arr_colr= (float *)p_malloc(12*ntri*sizeof(float)); #else arr_colr= (float *)p_malloc(9*ntri*sizeof(float)); #endif arr_norm= (float *)p_malloc(9*ntri*sizeof(float)); arr_vert= (float *)p_malloc(9*ntri*sizeof(float)); ind= 0; #ifdef USE_ALPHA indc= 0; #endif vrt= 0; for(i= 0; i < npoly; i++) { long nv= nverts[i]; long i3= 3*i; /* loop through all triangles for this polygon */ for(j= 1; j < nv-1; j++) { #ifdef USE_ALPHA arr_colr[indc]= colr[i3]; arr_colr[indc+1]= colr[i3+1]; arr_colr[indc+2]= colr[i3+2]; arr_colr[indc+3]= curr_alpha; arr_colr[indc+4]= colr[i3]; arr_colr[indc+5]= colr[i3+1]; arr_colr[indc+6]= colr[i3+2]; arr_colr[indc+7]= curr_alpha; arr_colr[indc+8]= colr[i3]; arr_colr[indc+9]= colr[i3+1]; arr_colr[indc+10]= colr[i3+2]; arr_colr[indc+11]= curr_alpha; indc += 12; #else arr_colr[ind]= colr[i3]; arr_colr[ind+1]= colr[i3+1]; arr_colr[ind+2]= colr[i3+2]; arr_colr[ind+3]= colr[i3]; arr_colr[ind+4]= colr[i3+1]; arr_colr[ind+5]= colr[i3+2]; arr_colr[ind+6]= colr[i3]; arr_colr[ind+7]= colr[i3+1]; arr_colr[ind+8]= colr[i3+2]; #endif arr_norm[ind]= norm[i3]; arr_norm[ind+1]= norm[i3+1]; arr_norm[ind+2]= norm[i3+2]; arr_norm[ind+3]= norm[i3]; arr_norm[ind+4]= norm[i3+1]; arr_norm[ind+5]= norm[i3+2]; arr_norm[ind+6]= norm[i3]; arr_norm[ind+7]= norm[i3+1]; arr_norm[ind+8]= norm[i3+2]; arr_vert[ind]= xyz[vrt]; arr_vert[ind+1]= xyz[vrt+1]; arr_vert[ind+2]= xyz[vrt+2]; arr_vert[ind+3]= xyz[vrt+3*j]; arr_vert[ind+4]= xyz[vrt+3*j+1]; arr_vert[ind+5]= xyz[vrt+3*j+2]; arr_vert[ind+6]= xyz[vrt+3*j+3]; arr_vert[ind+7]= xyz[vrt+3*j+4]; arr_vert[ind+8]= xyz[vrt+3*j+5]; ind += 9; } vrt += 3*nv; } /* NOTE: for each enabled array, a corresponding array must be defined and have data filled in before a call to glDrawArrays, because that call will use data from each enabled array */ glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_COLOR_ARRAY); #ifdef USE_ALPHA glColorPointer(4, GL_FLOAT, 0, arr_colr); #else glColorPointer(3, GL_FLOAT, 0, arr_colr); #endif glNormalPointer(GL_FLOAT, 0, arr_norm); glVertexPointer(3, GL_FLOAT, 0, arr_vert); /* draw all triangles using previously specified colors, vertices, and normals */ glDrawArrays(GL_TRIANGLES, 0, 3*ntri); /* free up the storage */ glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_COLOR_ARRAY); p_free(arr_colr); p_free(arr_norm); p_free(arr_vert); #ifdef USE_ALPHA glDisable(GL_BLEND); #endif CHEK_ERROR("gl_polys_arr"); } void yglPolysArrNoLite(long npoly, long *nverts, float *xyz, float *colr) { /* This function expands each polygon out into a series of triangles and will INCREASE the amount of data sent to the server. */ long i, j; float *arr_colr, *arr_vert; long ntri, ind, vrt; #ifdef USE_ALPHA long indc; #endif /* draw the polygon list now */ if(npoly <= 0) return; #ifdef USE_ALPHA if(!alpha_pass) return; #else if(alpha_pass) return; #endif #ifdef USE_ALPHA glEnable(GL_BLEND); #endif /* use flat shading (no per-vertex normals supplied) */ yglSetShade(0); yglUpdateProperties(); /* NOTE: cannot use an index list, because the indices must be the same for all active arrays. This means that I could only do one polygon at a time, and that does not seem worthwhile. */ /* compute the number of triangles in the set */ for(i= 0, ntri= 0; i < npoly; i++) { ntri += nverts[i]-2; } /* make an array big enough to hold all the colors, normals, and vertices for the polygon list */ #ifdef USE_ALPHA arr_colr= (float *)p_malloc(12*ntri*sizeof(float)); #else arr_colr= (float *)p_malloc(9*ntri*sizeof(float)); #endif arr_vert= (float *)p_malloc(9*ntri*sizeof(float)); ind= 0; #ifdef USE_ALPHA indc= 0; #endif vrt= 0; for(i= 0; i < npoly; i++) { long nv= nverts[i]; long i3= 3*i; /* loop through all triangles for this polygon */ for(j= 1; j < nv-1; j++) { #ifdef USE_ALPHA arr_colr[indc]= colr[i3]; arr_colr[indc+1]= colr[i3+1]; arr_colr[indc+2]= colr[i3+2]; arr_colr[indc+3]= curr_alpha; arr_colr[indc+4]= colr[i3]; arr_colr[indc+5]= colr[i3+1]; arr_colr[indc+6]= colr[i3+2]; arr_colr[indc+7]= curr_alpha; arr_colr[indc+8]= colr[i3]; arr_colr[indc+9]= colr[i3+1]; arr_colr[indc+10]= colr[i3+2]; arr_colr[indc+11]= curr_alpha; indc += 12; #else arr_colr[ind]= colr[i3]; arr_colr[ind+1]= colr[i3+1]; arr_colr[ind+2]= colr[i3+2]; arr_colr[ind+3]= colr[i3]; arr_colr[ind+4]= colr[i3+1]; arr_colr[ind+5]= colr[i3+2]; arr_colr[ind+6]= colr[i3]; arr_colr[ind+7]= colr[i3+1]; arr_colr[ind+8]= colr[i3+2]; #endif arr_vert[ind]= xyz[vrt]; arr_vert[ind+1]= xyz[vrt+1]; arr_vert[ind+2]= xyz[vrt+2]; arr_vert[ind+3]= xyz[vrt+3*j]; arr_vert[ind+4]= xyz[vrt+3*j+1]; arr_vert[ind+5]= xyz[vrt+3*j+2]; arr_vert[ind+6]= xyz[vrt+3*j+3]; arr_vert[ind+7]= xyz[vrt+3*j+4]; arr_vert[ind+8]= xyz[vrt+3*j+5]; ind += 9; } vrt += 3*nv; } /* NOTE: for each enabled array, a corresponding array must be defined and have data filled in before a call to glDrawArrays, because that call will use data from each enabled array */ glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); #ifdef USE_ALPHA glColorPointer(4, GL_FLOAT, 0, arr_colr); #else glColorPointer(3, GL_FLOAT, 0, arr_colr); #endif glVertexPointer(3, GL_FLOAT, 0, arr_vert); /* draw all triangles using previously specified colors, vertices, and normals */ glDrawArrays(GL_TRIANGLES, 0, 3*ntri); /* free up the storage */ glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); p_free(arr_colr); p_free(arr_vert); #ifdef USE_ALPHA glDisable(GL_BLEND); #endif CHEK_ERROR("gl_polys_arr"); } void yglPolysNoArr(long npoly, long *nverts, float *xyz, float *norm, float *colr) { long i, j, base; /* draw the polygon list now */ if(npoly <= 0) return; #ifdef USE_ALPHA if(!alpha_pass) return; #else if(alpha_pass) return; #endif #ifdef USE_ALPHA glEnable(GL_BLEND); #endif /* use flat shading (no per-vertex normals supplied) */ yglSetShade(0); yglUpdateProperties(); base= 0; for(i= 0; i < npoly; i++) { #ifdef USE_TRI glBegin(GL_TRIANGLE_FAN); #else glBegin(GL_POLYGON); #endif #ifdef USE_ALPHA glColor4f(*(colr+3*i), *(colr+3*i+1), *(colr+3*i+2), curr_alpha); #else glColor3fv(colr+3*i); #endif glNormal3fv(norm+3*i); for(j= 0; j < nverts[i]; j++) { /* NOTE: It makes no difference in local performance if the coords are converted to floats before being stored in the display list */ glVertex3fv(xyz+base); base += 3; } glEnd(); } #ifdef USE_ALPHA glDisable(GL_BLEND); #endif CHEK_ERROR("gl_polys_no_arr"); } void yglPolysNoArrNoLite(long npoly, long *nverts, float *xyz, float *colr) { long i, j, base; /* draw the polygon list now */ if(npoly <= 0) return; #ifdef USE_ALPHA if(!alpha_pass) return; #else if(alpha_pass) return; #endif #ifdef USE_ALPHA glEnable(GL_BLEND); #endif /* use flat shading */ yglSetShade(0); yglUpdateProperties(); base= 0; for(i= 0; i < npoly; i++) { #ifdef USE_TRI glBegin(GL_TRIANGLE_FAN); #else glBegin(GL_POLYGON); #endif #ifdef USE_ALPHA glColor4f(*(colr+3*i), *(colr+3*i+1), *(colr+3*i+2), curr_alpha); #else glColor3fv(colr+3*i); #endif for(j= 0; j < nverts[i]; j++) { /* NOTE: It makes no difference in local performance if the coords are converted to floats before being stored in the display list */ glVertex3fv(xyz+base); base += 3; } glEnd(); } #ifdef USE_ALPHA glDisable(GL_BLEND); #endif CHEK_ERROR("gl_polys_no_arr"); } void yglPolysSmArr(long npoly, long *nverts, float *xyz, float *norm, float *colr) { /* This function expands each polygon out into a series of triangles and will INCREASE the amount of data sent to the server. */ long i, j; float *arr_colr, *arr_norm, *arr_vert; long ntri, ind, vrt; #ifdef USE_ALPHA long indc; #endif /* draw the polygon list, with a normal per vertex */ if(npoly <= 0) return; #ifdef USE_ALPHA if(!alpha_pass) return; #else if(alpha_pass) return; #endif #ifdef USE_ALPHA glEnable(GL_BLEND); #endif /* use smooth shading */ yglSetShade(1); yglUpdateProperties(); /* NOTE: cannot use an index list, because the indices must be the same for all active arrays. This means that I could only do one polygon at a time, and that does not seem worthwhile. */ /* compute the number of triangles in the set */ for(i= 0, ntri= 0; i < npoly; i++) { ntri += nverts[i]-2; } /* make an array big enough to hold all the colors, normals, and vertices for the polygon list */ #ifdef USE_ALPHA arr_colr= (float *)p_malloc(12*ntri*sizeof(float)); #else arr_colr= (float *)p_malloc(9*ntri*sizeof(float)); #endif arr_norm= (float *)p_malloc(9*ntri*sizeof(float)); arr_vert= (float *)p_malloc(9*ntri*sizeof(float)); ind= 0; #ifdef USE_ALPHA indc= 0; #endif vrt= 0; for(i= 0; i < npoly; i++) { long nv= nverts[i]; long i3= 3*i; /* loop through all triangles for this polygon */ for(j= 1; j < nv-1; j++) { #ifdef USE_ALPHA arr_colr[indc]= colr[i3]; arr_colr[indc+1]= colr[i3+1]; arr_colr[indc+2]= colr[i3+2]; arr_colr[indc+3]= curr_alpha; arr_colr[indc+4]= colr[i3]; arr_colr[indc+5]= colr[i3+1]; arr_colr[indc+6]= colr[i3+2]; arr_colr[indc+7]= curr_alpha; arr_colr[indc+8]= colr[i3]; arr_colr[indc+9]= colr[i3+1]; arr_colr[indc+10]= colr[i3+2]; arr_colr[indc+11]= curr_alpha; indc += 12; #else arr_colr[ind]= colr[i3]; arr_colr[ind+1]= colr[i3+1]; arr_colr[ind+2]= colr[i3+2]; arr_colr[ind+3]= colr[i3]; arr_colr[ind+4]= colr[i3+1]; arr_colr[ind+5]= colr[i3+2]; arr_colr[ind+6]= colr[i3]; arr_colr[ind+7]= colr[i3+1]; arr_colr[ind+8]= colr[i3+2]; #endif arr_norm[ind]= norm[vrt]; arr_norm[ind+1]= norm[vrt+1]; arr_norm[ind+2]= norm[vrt+2]; arr_norm[ind+3]= norm[vrt+3*j]; arr_norm[ind+4]= norm[vrt+3*j+1]; arr_norm[ind+5]= norm[vrt+3*j+2]; arr_norm[ind+6]= norm[vrt+3*j+3]; arr_norm[ind+7]= norm[vrt+3*j+4]; arr_norm[ind+8]= norm[vrt+3*j+5]; arr_vert[ind]= xyz[vrt]; arr_vert[ind+1]= xyz[vrt+1]; arr_vert[ind+2]= xyz[vrt+2]; arr_vert[ind+3]= xyz[vrt+3*j]; arr_vert[ind+4]= xyz[vrt+3*j+1]; arr_vert[ind+5]= xyz[vrt+3*j+2]; arr_vert[ind+6]= xyz[vrt+3*j+3]; arr_vert[ind+7]= xyz[vrt+3*j+4]; arr_vert[ind+8]= xyz[vrt+3*j+5]; ind += 9; } vrt += 3*nv; } /* NOTE: for each enabled array, a corresponding array must be defined and have data filled in before a call to glDrawArrays, because that call will use data from each enabled array */ glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_COLOR_ARRAY); #ifdef USE_ALPHA glColorPointer(4, GL_FLOAT, 0, arr_colr); #else glColorPointer(3, GL_FLOAT, 0, arr_colr); #endif glNormalPointer(GL_FLOAT, 0, arr_norm); glVertexPointer(3, GL_FLOAT, 0, arr_vert); /* draw all triangles using previously specified colors, vertices, and normals */ glDrawArrays(GL_TRIANGLES, 0, 3*ntri); /* free up the storage */ glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_COLOR_ARRAY); p_free(arr_colr); p_free(arr_norm); p_free(arr_vert); #ifdef USE_ALPHA glDisable(GL_BLEND); #endif CHEK_ERROR("gl_polys_sm_arr"); } void yglPolysSmNoArr(long npoly, long *nverts, float *xyz, float *norm, float *colr) { long i, j, base; /* draw the polygon list, with a normal per vertex */ if(npoly <= 0) return; #ifdef USE_ALPHA if(!alpha_pass) return; #else if(alpha_pass) return; #endif #ifdef USE_ALPHA glEnable(GL_BLEND); #endif /* use smooth shading */ yglSetShade(1); yglUpdateProperties(); base= 0; for(i= 0; i < npoly; i++) { #ifdef USE_TRI glBegin(GL_TRIANGLE_FAN); #else glBegin(GL_POLYGON); #endif #ifdef USE_ALPHA glColor4f(*(colr+3*i), *(colr+3*i+1), *(colr+3*i+2), curr_alpha); #else glColor3fv(colr+3*i); #endif for(j= 0; j < nverts[i]; j++) { glNormal3fv(norm+base); /* NOTE: It makes no difference in local performance if the coords are converted to floats before being stored in the display list */ glVertex3fv(xyz+base); base += 3; } glEnd(); } #ifdef USE_ALPHA glDisable(GL_BLEND); #endif CHEK_ERROR("gl_polys_sm_no_arr"); } yorick-gl-1.1+cvs20070922+dfsg.orig/dlist3d.c0000640000175000017500000014700010515710063020136 0ustar thibautthibaut/* * $Id: dlist3d.c,v 1.3 2006/10/19 14:48:19 dhmunro Exp $ * Implement functions used for manipulating 3D display lists. * The functions in this file maintains the display list for the 3D graphics * package in Yorick. * The display routines MUST all be thread safe to permit this package to work * on Power Walls and other "multi-graphics-card" displays. */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #include "glcode.h" #include "glBasic.h" #include "dlist3d.h" #include "glfunc.h" #include "glStrips.h" #include "glWrappers.h" #include "ydata.h" #include "pstdlib.h" #include #include extern long yglGetBoundsList3d(yBox3D *box, yList3d_Elem *elem); yList3d_Elem *yListDirectHead= 0; yList3d_Elem *yListCachedHead= 0; int yDrawBBox3d= 0; int alpha_pass= 0; void yglDrawCurr3d(void) { yglDraw3d(glCurrWin3d); } void yglDraw3d(glWinProp *theWin3d) { glWinProp *oldWin3d= glCurrWin3d; /* prepare to draw, draw both cached and direct display lists, and finish drawing. */ if(!theWin3d) return; glCurrWin3d= theWin3d; yglPrepDraw(theWin3d); yglUpdateLight(); yglPrepContext(); /* draw all items in the "cached" display list */ yglDrawListCache3d(); /* draw all items in the "direct" display list */ yglDrawListDirect3d(); yglDrawCage(); yglDrawGnomon(); yglFinFrame(); theWin3d->dirty= 0; glCurrWin3d= oldWin3d; } void yglClearList3d(void) { yglClearCachedList3d(); yglClearDirectList3d(); } void yglClearCachedList3d(void) { yList3d_Elem *elem; /* empty the display list and free all storage associated with it */ while(yListCachedHead) { elem= yListCachedHead; yListCachedHead= yListCachedHead->next; p_free(elem->data); p_free(elem); } /* the OpenGL display list is now out-of-date */ if(glCurrWin3d && (glCurrWin3d->seq_num <= glCurrWin3d->list_num) ) { glCurrWin3d->seq_num++; } } void yglClearDirectList3d(void) { yList3d_Elem *elem; /* empty the display list and free all storage associated with it */ while(yListDirectHead) { elem= yListDirectHead; yListDirectHead= yListDirectHead->next; p_free(elem->data); p_free(elem); } } void yglDrawList3d(void) { /* draw all items in the "cached" display list */ yglDrawListCache3d(); /* draw all items in the "direct" display list */ yglDrawListDirect3d(); } void yglDrawListCache3d(void) { yList3d_Elem *elem; if(glCurrWin3d && (glCurrWin3d->seq_num > glCurrWin3d->list_num) ) { /* need a new display list */ /* draw all items in the "cached" display list */ yglPrepList(); /* in the first pass draw all opaque objects */ alpha_pass= 0; elem= yListCachedHead; while(elem) { (*(elem->func))(0, elem->data); elem= elem->next; } /* In the second pass draw all translucent objects. NOTE: objects with an alpha of 1.0 are still "translucent" and need not produce the same effect as an opaque object. */ alpha_pass= 1; elem= yListCachedHead; while(elem) { (*(elem->func))(0, elem->data); elem= elem->next; } alpha_pass= 0; } /* if necessary, finish the display list, then draw it */ yglFinCache(); } void yglDrawListDirect3d(void) { yList3d_Elem *elem; /* draw all items in the "direct" display list */ elem= yListDirectHead; while(elem) { (*(elem->func))(0, elem->data); elem= elem->next; } } long yglGetBounds3d(yBox3D *box) { yBox3D boxCached, boxDirect; long hasDirect, hasCached; /* if the bounding box for this scene has already been computed, return it. */ if(!glCurrWin3d) return 0; /* indicate failure */ if((glCurrWin3d->BoxSeqNum >= glCurrWin3d->seq_num) && (glCurrWin3d->cage_seq_num <= glCurrWin3d->cage_state) ) { *box= glCurrWin3d->boxAll; return 1; } /* Get the bounds of the objects in the scene */ hasCached= yglGetBoundsCachedList3d(&boxCached); hasDirect= yglGetBoundsDirectList3d(&boxDirect); if(hasCached) { if(hasDirect) { /* merge the two bounding boxes */ glCurrWin3d->boxAll= boxCached; if(glCurrWin3d->boxAll.xmin > boxDirect.xmin) glCurrWin3d->boxAll.xmin= boxDirect.xmin; if(glCurrWin3d->boxAll.xmax < boxDirect.xmax) glCurrWin3d->boxAll.xmax= boxDirect.xmax; if(glCurrWin3d->boxAll.ymin > boxDirect.ymin) glCurrWin3d->boxAll.ymin= boxDirect.ymin; if(glCurrWin3d->boxAll.ymax < boxDirect.ymax) glCurrWin3d->boxAll.ymax= boxDirect.ymax; if(glCurrWin3d->boxAll.zmin > boxDirect.zmin) glCurrWin3d->boxAll.zmin= boxDirect.zmin; if(glCurrWin3d->boxAll.zmax < boxDirect.zmax) glCurrWin3d->boxAll.zmax= boxDirect.zmax; } else { /* only cached objects */ glCurrWin3d->boxAll= boxCached; } } else { if(hasDirect) { /* only direct objects */ glCurrWin3d->boxAll= boxDirect; } else { /* no objects, so return "failure" and an empty box */ glCurrWin3d->boxAll.xmin= 0.0; glCurrWin3d->boxAll.xmax= 0.0; glCurrWin3d->boxAll.ymin= 0.0; glCurrWin3d->boxAll.ymax= 0.0; glCurrWin3d->boxAll.zmin= 0.0; glCurrWin3d->boxAll.zmax= 0.0; *box= glCurrWin3d->boxAll; return 0; } } if(glCurrWin3d->cage_style > 0) { /* modify the box to include the "cage" set by the user */ if(glCurrWin3d->boxAll.xmin > glCurrWin3d->cage_xmin) glCurrWin3d->boxAll.xmin= glCurrWin3d->cage_xmin; if(glCurrWin3d->boxAll.xmax < glCurrWin3d->cage_xmax) glCurrWin3d->boxAll.xmax= glCurrWin3d->cage_xmax; if(glCurrWin3d->boxAll.ymin > glCurrWin3d->cage_ymin) glCurrWin3d->boxAll.ymin= glCurrWin3d->cage_ymin; if(glCurrWin3d->boxAll.ymax < glCurrWin3d->cage_ymax) glCurrWin3d->boxAll.ymax= glCurrWin3d->cage_ymax; if(glCurrWin3d->boxAll.zmin > glCurrWin3d->cage_zmin) glCurrWin3d->boxAll.zmin= glCurrWin3d->cage_zmin; if(glCurrWin3d->boxAll.zmax < glCurrWin3d->cage_zmax) glCurrWin3d->boxAll.zmax= glCurrWin3d->cage_zmax; } *box= glCurrWin3d->boxAll; glCurrWin3d->BoxSeqNum= glCurrWin3d->seq_num; glCurrWin3d->cage_state= glCurrWin3d->cage_seq_num; return 1; } long yglGetBoundsDirectList3d(yBox3D *box) { return yglGetBoundsList3d(box, yListDirectHead); } long yglGetBoundsCachedList3d(yBox3D *box) { return yglGetBoundsList3d(box, yListCachedHead); } long yglGetBoundsList3d(yBox3D *box, yList3d_Elem *elem) { double xmin, xmax, ymin, ymax, zmin, zmax; /* find the bounding box containing all items in the specified display list */ if(elem) { xmin= (elem->box).xmin; xmax= (elem->box).xmax; ymin= (elem->box).ymin; ymax= (elem->box).ymax; zmin= (elem->box).zmin; zmax= (elem->box).zmax; elem= elem->next; while(elem) { if(xmin > (elem->box).xmin) xmin= (elem->box).xmin; if(xmax < (elem->box).xmax) xmax= (elem->box).xmax; if(ymin > (elem->box).ymin) ymin= (elem->box).ymin; if(ymax < (elem->box).ymax) ymax= (elem->box).ymax; if(zmin > (elem->box).zmin) zmin= (elem->box).zmin; if(zmax < (elem->box).zmax) zmax= (elem->box).zmax; elem= elem->next; } box->xmin= xmin; box->xmax= xmax; box->ymin= ymin; box->ymax= ymax; box->zmin= zmin; box->zmax= zmax; return 1; } else { box->xmin= 0.0; box->xmax= 0.0; box->ymin= 0.0; box->ymax= 0.0; box->zmin= 0.0; box->zmax= 0.0; return 0; } } yList3d_Elem *yglNewCachedList3dElem(void) { yList3d_Elem *elem; /* add another element at the head of the display list (it is a linked list) */ elem= (yList3d_Elem *) p_malloc(sizeof(yList3d_Elem)); elem->next= yListCachedHead; yListCachedHead= elem; return elem; } yList3d_Elem *yglNewDirectList3dElem(void) { yList3d_Elem *elem; /* add another element at the head of the display list (it is a linked list) */ elem= (yList3d_Elem *) p_malloc(sizeof(yList3d_Elem)); elem->next= yListDirectHead; yListDirectHead= elem; return elem; } void yglSetLims3d(yList3d_Elem *elem, long nvert, float *xyz) { long i; float xmin, xmax, ymin, ymax, zmin, zmax; float xx, yy, zz; if(nvert <= 0) return; xmin= xmax= xyz[0]; ymin= ymax= xyz[1]; zmin= zmax= xyz[2]; for(i= 1; i < nvert; i++) { xx= xyz[3*i]; yy= xyz[3*i+1]; zz= xyz[3*i+2]; if(xx < xmin) xmin= xx; if(xx > xmax) xmax= xx; if(yy < ymin) ymin= yy; if(yy > ymax) ymax= yy; if(zz < zmin) zmin= zz; if(zz > zmax) zmax= zz; } elem->box.xmin= xmin; elem->box.xmax= xmax; elem->box.ymin= ymin; elem->box.ymax= ymax; elem->box.zmin= zmin; elem->box.zmax= zmax; } void yglDrawGnomon(void) { /* draw an indicator of axis orientation */ } void yglDrawCage(void) { float pt1[3], pt2[3], pt3[3]; yBox3D boxAll; /* Determine the three furthest planes, given the current viewpoint. Draw them. If the "cage" uses the data bounds, put them in place now. */ if(!glCurrWin3d) return; if(!glCurrWin3d->cage_style) { /* do not draw a cage */ return; } if(glCurrWin3d->cage_style < 0) { /* Use the bounds of the objects in the scene. If no objects, just return */ if(!yglGetBounds3d(&boxAll)) { return; } glCurrWin3d->cage_xmin= (float)boxAll.xmin; glCurrWin3d->cage_xmax= (float)boxAll.xmax; glCurrWin3d->cage_ymin= (float)boxAll.ymin; glCurrWin3d->cage_ymax= (float)boxAll.ymax; glCurrWin3d->cage_zmin= (float)boxAll.zmin; glCurrWin3d->cage_zmax= (float)boxAll.zmax; } if(glCurrWin3d->view[0] >= 0.0) { /* draw the plane at cage_xmin because the eye is at a larger x than the center */ pt1[0]= glCurrWin3d->cage_xmin; pt1[1]= glCurrWin3d->cage_ymin; pt1[2]= glCurrWin3d->cage_zmin; pt2[0]= glCurrWin3d->cage_xmin; pt2[1]= glCurrWin3d->cage_ymin; pt2[2]= glCurrWin3d->cage_zmax; pt3[0]= glCurrWin3d->cage_xmin; pt3[1]= glCurrWin3d->cage_ymax; pt3[2]= glCurrWin3d->cage_zmax; } else { pt1[0]= glCurrWin3d->cage_xmax; pt1[1]= glCurrWin3d->cage_ymin; pt1[2]= glCurrWin3d->cage_zmin; pt2[0]= glCurrWin3d->cage_xmax; pt2[1]= glCurrWin3d->cage_ymin; pt2[2]= glCurrWin3d->cage_zmax; pt3[0]= glCurrWin3d->cage_xmax; pt3[1]= glCurrWin3d->cage_ymax; pt3[2]= glCurrWin3d->cage_zmax; } draw_plane(pt1, pt2, pt3, glCurrWin3d->num_zgrid, glCurrWin3d->num_ygrid); if(glCurrWin3d->view[1] >= 0.0) { /* draw the plane at cage_ymin because the eye is at a larger y than the center */ pt1[0]= glCurrWin3d->cage_xmin; pt1[1]= glCurrWin3d->cage_ymin; pt1[2]= glCurrWin3d->cage_zmin; pt2[0]= glCurrWin3d->cage_xmin; pt2[1]= glCurrWin3d->cage_ymin; pt2[2]= glCurrWin3d->cage_zmax; pt3[0]= glCurrWin3d->cage_xmax; pt3[1]= glCurrWin3d->cage_ymin; pt3[2]= glCurrWin3d->cage_zmax; } else { pt1[0]= glCurrWin3d->cage_xmin; pt1[1]= glCurrWin3d->cage_ymax; pt1[2]= glCurrWin3d->cage_zmin; pt2[0]= glCurrWin3d->cage_xmin; pt2[1]= glCurrWin3d->cage_ymax; pt2[2]= glCurrWin3d->cage_zmax; pt3[0]= glCurrWin3d->cage_xmax; pt3[1]= glCurrWin3d->cage_ymax; pt3[2]= glCurrWin3d->cage_zmax; } draw_plane(pt1, pt2, pt3, glCurrWin3d->num_zgrid, glCurrWin3d->num_xgrid); if(glCurrWin3d->view[2] >= 0.0) { /* draw the plane at cage_zmin because the eye is at a larger z than the center */ pt1[0]= glCurrWin3d->cage_xmin; pt1[1]= glCurrWin3d->cage_ymin; pt1[2]= glCurrWin3d->cage_zmin; pt2[0]= glCurrWin3d->cage_xmin; pt2[1]= glCurrWin3d->cage_ymax; pt2[2]= glCurrWin3d->cage_zmin; pt3[0]= glCurrWin3d->cage_xmax; pt3[1]= glCurrWin3d->cage_ymax; pt3[2]= glCurrWin3d->cage_zmin; } else { pt1[0]= glCurrWin3d->cage_xmin; pt1[1]= glCurrWin3d->cage_ymin; pt1[2]= glCurrWin3d->cage_zmax; pt2[0]= glCurrWin3d->cage_xmin; pt2[1]= glCurrWin3d->cage_ymax; pt2[2]= glCurrWin3d->cage_zmax; pt3[0]= glCurrWin3d->cage_xmax; pt3[1]= glCurrWin3d->cage_ymax; pt3[2]= glCurrWin3d->cage_zmax; } draw_plane(pt1, pt2, pt3, glCurrWin3d->num_ygrid, glCurrWin3d->num_xgrid); } void yglPolys3d(long npolys, long *len, double *xyz, double *norm, double *colr, long edge, long smooth, long do_light) { /* variables for the display list */ yList3d_Elem *elem; yPoly3dData *data; long size, nvert, i, nval; float *dxyz, *dnorm, *dcolr; /* There is one color per polygon (i.e. npolys colors) The number of polygon vertices is the sum of the npolys elements of len[]. There is one coordinate and one normal ???????????????? per vertex */ /* add a new entry to the 3D display list (it will be in the list when it is returned). */ if(!glCurrWin3d) return; if(glCurrWin3d->use_list) { elem= yglNewCachedList3dElem(); } else { elem= yglNewDirectList3dElem(); } elem->func= yglDrawPolys3d; /* compute the size of the data structure plus all data */ nvert= 0; for(i= 0; i < npolys; i++) { nvert += len[i]; } size= sizeof(yPoly3dData)+sizeof(long)*npolys+sizeof(float)*(2*3*nvert+3*npolys); data= (yPoly3dData *) p_malloc(size); elem->data= data; /* set all elements of the data structure, including pointers into the data block */ data->npolys= npolys; data->edge= edge; data->smooth= smooth; data->do_light= do_light; data->len= (long *) ((char *)data+sizeof(yPoly3dData)); data->xyz= dxyz= (float *) (data->len+npolys); data->norm= dnorm= data->xyz+3*nvert; data->colr= dcolr= data->norm+3*nvert; /* copy data into the new storage space */ memcpy(data->len, len, sizeof(long)*npolys); /* copy data into the new storage space */ nval= 3*nvert; for(i= 0; i < nval; i++) { dxyz[i]= (float) xyz[i]; dnorm[i]= (float) norm[i]; } nval= 3*npolys; for(i= 0; i < nval; i++) { dcolr[i]= (float) colr[i]; } /* compute and save the bounding box */ yglSetLims3d(elem, nvert, data->xyz); } void yglGlyphs3d(long nglyph, double *origin, double *scal, double *theta, double *phi, double *colr) { /* variables for the display list */ yList3d_Elem *elem; yGlyph3dData *data; float *dorigin, *dscal, *dtheta, *dphi, *dcolr; long i, size, nval; /* There is an origin, radius, ellipticity, color, and direction (theta and phi) per glyph */ /* add a new entry to the 3D display list (it will be in the list when it is returned). */ if(!glCurrWin3d) return; if(glCurrWin3d->use_list) { elem= yglNewCachedList3dElem(); } else { elem= yglNewDirectList3dElem(); } elem->func= yglDrawGlyphs3d; /* compute the size of the data structure plus all data */ size= sizeof(yGlyph3dData)+sizeof(float)*nglyph*(3+1+1+1+3); data= (yGlyph3dData *) p_malloc(size); elem->data= data; /* set all elements of the data structure, including pointers into the data block */ data->nglyph= nglyph; data->origin= dorigin= (float *) ((char *)data+sizeof(yGlyph3dData)); data->scal= dscal= data->origin+3*nglyph; data->theta= dtheta= data->scal+nglyph; data->phi= dphi= data->theta+nglyph; data->colr= dcolr= data->phi+nglyph; /* copy data into the new storage space with type conversion */ for(i= 0; i < nglyph; i++) { dscal[i]= (float) scal[i]; dtheta[i]= (float) theta[i]; dphi[i]= (float) phi[i]; } nval= 3*nglyph; for(i= 0; i < nval; i++) { dorigin[i]= (float) origin[i]; dcolr[i]= (float) colr[i]; } /* compute and save the bounding box */ yglSetLims3d(elem, nglyph, data->origin); } void yglCells3d(long nx, long ny, double *corners, double *norm, double *colr, long do_alpha) { /* variables for the display list */ yList3d_Elem *elem; yCell3dData *data; long i, size, nval; float *dxyz, *dnorm, *dcolr; /* there are nx-by-ny colors, three 3D coordinates and one 3D normal. NOTE: given three coordinates, the normal is redundant. !!!!!! shouldn't use a normal, just "emissive" color !!!! */ /* add a new entry to the 3D display list (it will be in the list when it is returned). */ if(!glCurrWin3d) return; if(glCurrWin3d->use_list) { elem= yglNewCachedList3dElem(); } else { elem= yglNewDirectList3dElem(); } elem->func= yglDrawCells3d; /* compute the size of the data structure plus all data */ size= sizeof(yCell3dData)+sizeof(float)*3*nx*ny+sizeof(float)*(3*3+3); data= (yCell3dData *) p_malloc(size); elem->data= data; /* set all elements of the data structure, including pointers into the data block */ data->nx= nx; data->ny= ny; data->do_alpha= do_alpha; data->xyz= dxyz= (float *) ((char *)data+sizeof(yCell3dData)); data->norm= dnorm= data->xyz+3*3; data->colr= dcolr= data->norm+3; /* copy data into the new storage space */ nval= 3; for(i= 0; i < nval; i++) { dnorm[i]= (float) norm[i]; } nval= 3*3; for(i= 0; i < nval; i++) { dxyz[i]= (float) corners[i]; } nval= 3*nx*ny; for(i= 0; i < nval; i++) { dcolr[i]= (float) colr[i]; } /* compute and save the bounding box */ yglSetLims3d(elem, 2, data->xyz); } void yglPlm3d(long nx, long ny, double *xyz, double *colr) { /* variables for the display list */ yList3d_Elem *elem; yPlm3dData *data; long i, size, nval; float *dxyz, *dcolr; /* there are nx-by-ny coordinates and one color */ /* add a new entry to the 3D display list (it will be in the list when it is returned). */ if(!glCurrWin3d) return; if(glCurrWin3d->use_list) { elem= yglNewCachedList3dElem(); } else { elem= yglNewDirectList3dElem(); } elem->func= yglDrawPlm3d; /* compute the size of the data structure plus all data */ size= sizeof(yPlm3dData)+sizeof(float)*3*nx*ny+sizeof(float)*3; data= (yPlm3dData *) p_malloc(size); elem->data= data; /* set all elements of the data structure, including pointers into the data block */ data->nx= nx; data->ny= ny; data->xyz= dxyz= (float *) ((char *)data+sizeof(yPlm3dData)); data->colr= dcolr= data->xyz+3*nx*ny; /* copy data into the new storage space */ nval= 3; for(i= 0; i < nval; i++) { dcolr[i]= (float) colr[i]; } nval= 3*nx*ny; for(i= 0; i < nval; i++) { dxyz[i]= (float) xyz[i]; } /* compute and save the bounding box */ yglSetLims3d(elem, nx*ny, data->xyz); } void yglPlf3d(long nx, long ny, double *xyz, double *colr) { /* variables for the display list */ yList3d_Elem *elem; yPlf3dData *data; long i, size, nval; float *dxyz, *dcolr; /* there are nx-by-ny coordinates and (nx-1)*(ny-1) colors ???????? */ /* add a new entry to the 3D display list (it will be in the list when it is returned). */ if(!glCurrWin3d) return; if(glCurrWin3d->use_list) { elem= yglNewCachedList3dElem(); } else { elem= yglNewDirectList3dElem(); } elem->func= yglDrawPlf3d; /* compute the size of the data structure plus all data */ size= sizeof(yPlf3dData)+sizeof(float)*3*nx*ny+sizeof(float)*3*(nx-1)*(ny-1); data= (yPlf3dData *) p_malloc(size); elem->data= data; /* set all elements of the data structure, including pointers into the data block */ data->nx= nx; data->ny= ny; data->xyz= dxyz= (float *) ((char *)data+sizeof(yPlf3dData)); data->colr= dcolr= data->xyz+3*nx*ny; /* copy data into the new storage space */ nval= 4*(nx-1)*(ny-1); for(i= 0; i < nval; i++) { dcolr[i]= (float) colr[i]; } nval= 3*nx*ny; for(i= 0; i < nval; i++) { dxyz[i]= (float) xyz[i]; } /* compute and save the bounding box */ yglSetLims3d(elem, nx*ny, data->xyz); } void yglSurf3d(long do_alpha, long nx, long ny, double *xyz, double *norm, double *colr) { /* variables for the display list */ yList3d_Elem *elem; ySurf3dData *data; long i, size, nval; float *dxyz, *dnorm, *dcolr; /* there are nx-by-ny coordinates and normals and one color ????????? */ /* add a new entry to the 3D display list (it will be in the list when it is returned). */ if(!glCurrWin3d) return; if(glCurrWin3d->use_list) { elem= yglNewCachedList3dElem(); } else { elem= yglNewDirectList3dElem(); } elem->func= yglDrawSurf3d; /* compute the size of the data structure plus all data */ size= sizeof(ySurf3dData)+sizeof(float)*2*3*nx*ny+sizeof(float)*3; data= (ySurf3dData *) p_malloc(size); elem->data= data; /* set all elements of the data structure, including pointers into the data block */ data->do_alpha= do_alpha; data->nx= nx; data->ny= ny; data->xyz= dxyz= (float *) ((char *)data+sizeof(ySurf3dData)); data->norm= dnorm= data->xyz+3*nx*ny; data->colr= dcolr= data->norm+3*nx*ny; /* copy data into the new storage space */ nval= 3*nx*ny; for(i= 0; i < nval; i++) { dxyz[i]= (float) xyz[i]; dnorm[i]= (float) norm[i]; } dcolr[0]= (float) colr[0]; dcolr[1]= (float) colr[1]; dcolr[2]= (float) colr[2]; /* compute and save the bounding box */ yglSetLims3d(elem, nx*ny, data->xyz); } void yglColrsurf3d(long do_alpha, long nx, long ny, double *xyz, double *norm, double *colr) { /* variables for the display list */ yList3d_Elem *elem; ySurf3dData *data; long i, size, nval; float *dxyz, *dnorm, *dcolr; /* there are nx-by-ny coordinates and normals and one color ????????? */ /* add a new entry to the 3D display list (it will be in the list when it is returned). */ if(!glCurrWin3d) return; if(glCurrWin3d->use_list) { elem= yglNewCachedList3dElem(); } else { elem= yglNewDirectList3dElem(); } elem->func= yglDrawColrSurf3d; /* compute the size of the data structure plus all data */ size= sizeof(ySurf3dData)+sizeof(float)*2*3*nx*ny+sizeof(float)*3*nx*ny; data= (ySurf3dData *) p_malloc(size); elem->data= data; /* set all elements of the data structure, including pointers into the data block */ data->do_alpha= do_alpha; data->nx= nx; data->ny= ny; data->xyz= dxyz= (float *) ((char *)data+sizeof(ySurf3dData)); data->norm= dnorm= data->xyz+3*nx*ny; data->colr= dcolr= data->norm+3*nx*ny; /* copy data into the new storage space */ nval= 3*nx*ny; for(i= 0; i < nval; i++) { dxyz[i]= (float) xyz[i]; dnorm[i]= (float) norm[i]; } if(do_alpha) nval= 4*nx*ny; else nval= 3*nx*ny; for(i= 0; i < nval; i++) { dcolr[i]= (float) colr[i]; } /* compute and save the bounding box */ yglSetLims3d(elem, nx*ny, data->xyz); } void yglLines3d(long nvert, double *xyz, double *colr) { /* variables for the display list */ yList3d_Elem *elem; yLines3dData *data; long i, size, nval; float *dxyz, *dcolr; /* there are nvert coordinates and one color */ /* add a new entry to the 3D display list (it will be in the list when it is returned). */ if(!glCurrWin3d) return; if(glCurrWin3d->use_list) { elem= yglNewCachedList3dElem(); } else { elem= yglNewDirectList3dElem(); } elem->func= yglDrawLines3d; /* compute the size of the data structure plus all data */ size= sizeof(yLines3dData)+sizeof(float)*3*nvert+sizeof(float)*3; data= (yLines3dData *) p_malloc(size); elem->data= data; /* set all elements of the data structure, including pointers into the data block */ data->nvert= nvert; data->xyz= dxyz= (float *) ((char *)data+sizeof(yLines3dData)); data->colr= dcolr= data->xyz+3*nvert; /* copy data into the new storage space */ nval= 3; for(i= 0; i < nval; i++) { dcolr[i]= (float) colr[i]; } nval= 3*nvert; for(i= 0; i < nval; i++) { dxyz[i]= (float) xyz[i]; } /* compute and save the bounding box */ yglSetLims3d(elem, nvert, data->xyz); } void yglPoints3d(long nvert, double *xyz, double *colr) { /* variables for the display list */ yList3d_Elem *elem; yPoints3dData *data; long i, size, nval; float *dxyz, *dcolr; /* there are nvert coordinates and nvert colors */ /* add a new entry to the 3D display list (it will be in the list when it is returned). */ if(!glCurrWin3d) return; if(glCurrWin3d->use_list) { elem= yglNewCachedList3dElem(); } else { elem= yglNewDirectList3dElem(); } elem->func= yglDrawPoints3d; /* compute the size of the data structure plus all data */ size= sizeof(yPoints3dData)+sizeof(float)*3*nvert+sizeof(float)*3*nvert; data= (yPoints3dData *) p_malloc(size); elem->data= data; /* set all elements of the data structure, including pointers into the data block */ data->nvert= nvert; data->xyz= dxyz= (float *) ((char *)data+sizeof(yPoints3dData)); data->colr= dcolr= data->xyz+3*nvert; /* copy data into the new storage space */ nval= 3*nvert; for(i= 0; i < nval; i++) { dcolr[i]= (float) colr[i]; } nval= 3*nvert; for(i= 0; i < nval; i++) { dxyz[i]= (float) xyz[i]; } /* compute and save the bounding box */ yglSetLims3d(elem, nvert, data->xyz); } void yglTstrips3d(long nstrips, long *len, double *xyz, double *norm, double *colr, long edge, long smooth, long do_light, long do_alpha) { /* variables for the display list */ yList3d_Elem *elem; yTstrips3dData *data; long size, i, ntri, nvert, colrsiz, nval, nrmsiz, *dlen; float *dxyz, *dnorm, *dcolr; /* The number of triangles is the sum of the nstrips elements of len[]. There is one color per triangle. ?????? There are ntri+2*nstrips vertices and normals. ??????? edge non-zero means outline the polygon, not fill it. smooth non-zero means normals have been provided and smooth shading should be used. ?????? smooth only ??????? do_light means enable lighting ????? maybe means emissive lighting if zero ????? do_alpha means colors contain an alpha component */ /* add a new entry to the 3D display list (it will be in the list when it is returned). */ if(!glCurrWin3d) return; if(glCurrWin3d->use_list) { elem= yglNewCachedList3dElem(); } else { elem= yglNewDirectList3dElem(); } elem->func= yglDrawTstrips3d; if(do_alpha) { colrsiz= 4; } else { colrsiz= 3; } nvert= 0; for(i= 0; i < nstrips; i++) { nvert += len[i]; } ntri= nvert-2*nstrips; /* compute the size of the data structure plus all data */ size= sizeof(yTstrips3dData)+sizeof(float)*3*nvert+sizeof(float)*colrsiz*ntri; size += sizeof(long)*nstrips; if(smooth) { nrmsiz= 3*nvert; } else { if(do_light) { nrmsiz= 3*ntri; } else { /* no normals supplied, so don't allocate storage for them. */ nrmsiz= 0; } } size += sizeof(float)*nrmsiz; data= (yTstrips3dData *) p_malloc(size); elem->data= data; /* set all elements of the data structure, including pointers into the data block */ data->nstrips= nstrips; data->edge= edge; data->smooth= smooth; data->do_light= do_light; data->do_alpha= do_alpha; data->len= dlen= (long *) ((char *)data+sizeof(yTstrips3dData)); data->xyz= dxyz= (float *) (data->len+nstrips); data->norm= dnorm= data->xyz+3*nvert; data->colr= dcolr= data->norm+nrmsiz; /* copy data into the new storage space */ for(i= 0; i < nstrips; i++) { dlen[i]= len[i]; } nval= colrsiz*ntri; for(i= 0; i < nval; i++) { dcolr[i]= (float) colr[i]; } if(smooth) { nval= 3*nvert; for(i= 0; i < nval; i++) { dxyz[i]= (float) xyz[i]; dnorm[i]= (float) norm[i]; } } else { nval= 3*nvert; for(i= 0; i < nval; i++) { dxyz[i]= (float) xyz[i]; } if(do_light) { nval= 3*ntri; for(i= 0; i < nval; i++) { dnorm[i]= (float) norm[i]; } } } /* compute and save the bounding box */ yglSetLims3d(elem, nvert, data->xyz); } void yglQstrips3d(long nstrips, long *len, double *xyz, double *norm, double *colr, long edge, long smooth, long do_light, long do_alpha) { /* variables for the display list */ yList3d_Elem *elem; yQstrips3dData *data; long size, i, nquad, nvert, ncoord, colrsiz, nval, nrmsiz, *dlen; float *dxyz, *dnorm, *dcolr; /* The number of quads is the sum of the nstrips elements of len[]. There is one color per quad. ?????? There are 2*nquad+2*nstrips vertices and normals. ??????? edge non-zero means outline the polygon, not fill it. smooth non-zero means normals have been provided and smooth shading should be used. ?????? smooth only ??????? do_light means enable lighting ????? maybe means emissive lighting if zero ????? do_alpha means colors contain an alpha component */ /* add a new entry to the 3D display list (it will be in the list when it is returned). */ if(!glCurrWin3d) return; if(glCurrWin3d->use_list) { elem= yglNewCachedList3dElem(); } else { elem= yglNewDirectList3dElem(); } elem->func= yglDrawQstrips3d; if(do_alpha) { colrsiz= 4; } else { colrsiz= 3; } /* first compute the number of vertices down one edge of the strip */ nvert= 0; for(i= 0; i < nstrips; i++) { nvert += len[i]; } nquad= nvert-nstrips; /* compute the number of vertices in the strip on both edges */ ncoord= 2*nvert; /* compute the size of the data structure plus all data */ size= sizeof(yQstrips3dData)+sizeof(float)*3*ncoord+sizeof(float)*colrsiz*nquad; size += sizeof(long)*nstrips; if(smooth) { nrmsiz= 3*ncoord; } else { if(do_light) { nrmsiz= 3*nquad; } else { nrmsiz= 0; } } size += sizeof(float)*nrmsiz; data= (yQstrips3dData *) p_malloc(size); elem->data= data; /* set all elements of the data structure, including pointers into the data block */ data->nstrips= nstrips; data->edge= edge; data->smooth= smooth; data->do_light= do_light; data->do_alpha= do_alpha; data->len= dlen= (long *) ((char *)data+sizeof(yQstrips3dData)); data->xyz= dxyz= (float *) (data->len+nstrips); data->norm= dnorm= data->xyz+3*ncoord; data->colr= dcolr= data->norm+nrmsiz; /* copy data into the new storage space */ for(i= 0; i < nstrips; i++) { dlen[i]= len[i]; } nval= colrsiz*nquad; for(i= 0; i < nval; i++) { dcolr[i]= (float) colr[i]; } if(smooth) { nval= 3*ncoord; for(i= 0; i < nval; i++) { dxyz[i]= (float) xyz[i]; dnorm[i]= (float) norm[i]; } } else { nval= 3*ncoord; for(i= 0; i < nval; i++) { dxyz[i]= (float) xyz[i]; } if(do_light) { for(i= 0; i < nrmsiz; i++) { dnorm[i]= (float) norm[i]; } } } /* compute and save the bounding box */ yglSetLims3d(elem, ncoord, data->xyz); } void yglTstripsndx3d(long nstrips, long numedg, long ntri, long *len, long *ndx, double *xyz, double *norm, double *colr, long edge, long do_alpha) { /* variables for the display list */ yList3d_Elem *elem; yTstripsNdx3dData *data; long size, i, nvert, colrsiz, nval, *dlen, *dndx; float *dxyz, *dnorm, *dcolr; /* The number of triangles is the sum of the nstrips elements of len[]. There is one color per triangle. ?????? There are ntri+2*nstrips vertices and normals. ??????? edge non-zero means outline the polygon, not fill it. do_alpha means colors contain an alpha component */ /* add a new entry to the 3D display list (it will be in the list when it is returned). */ if(!glCurrWin3d) return; if(glCurrWin3d->use_list) { elem= yglNewCachedList3dElem(); } else { elem= yglNewDirectList3dElem(); } elem->func= yglDrawTstripsNdx3d; if(do_alpha) { colrsiz= 4; } else { colrsiz= 3; } nvert= 0; for(i= 0; i < nstrips; i++) { nvert += len[i]; } ntri= nvert-2*nstrips; /* compute the size of the data structure plus all data */ size= sizeof(yTstripsNdx3dData)+sizeof(float)*2*3*numedg+sizeof(float)*colrsiz*ntri; size += sizeof(long)*nvert+sizeof(long)*nstrips; data= (yTstripsNdx3dData *) p_malloc(size); elem->data= data; /* set all elements of the data structure, including pointers into the data block */ data->nstrips= nstrips; data->numedg= numedg; data->nvert= nvert; data->ntri= ntri; data->edge= edge; data->do_alpha= do_alpha; data->len= dlen= (long *) ((char *)data+sizeof(yTstripsNdx3dData)); data->ndx= dndx= data->len+nstrips; data->xyz= dxyz= (float *) (data->ndx+nvert); data->norm= dnorm= data->xyz+3*numedg; data->colr= dcolr= data->norm+3*numedg; /* copy data into the new storage space */ for(i= 0; i < nstrips; i++) { dlen[i]= len[i]; } for(i= 0; i < nvert; i++) { dndx[i]= ndx[i]; } for(i= 0; i < 3*numedg; i++) { dxyz[i]= (float) xyz[i]; dnorm[i]= (float) norm[i]; } nval= colrsiz*ntri; for(i= 0; i < nval; i++) { dcolr[i]= (float) colr[i]; } /* compute and save the bounding box (NOTE: asumes everything in xyz is actually used) */ yglSetLims3d(elem, numedg, data->xyz); } void yglTarray3d(long ntri, double *xyz, double *norm, double *colr, long edge, long smooth, long do_light, long do_alpha, long cpervrt, long cubemap, long emit) { /* variables for the display list */ yList3d_Elem *elem; yTarray3dData *data; long size, colrsiz, ncolr, i, nval; float *dxyz, *dnorm, *dcolr; /* There are ntri triangles. There is one color per triangle or one color per triangle vertex. There are 3*ntri vertices and normals. edge non-zero means outline the polygon, not fill it. smooth non-zero means normals have been provided and smooth shading should be used. ?????? smooth only ??????? do_light means enable lighting ????? maybe means emissive lighting if zero ????? do_alpha means colors contain an alpha component colr_per_vert non-zero means one color per vertex */ /* add a new entry to the 3D display list (it will be in the list when it is returned). */ if(!glCurrWin3d) return; if(glCurrWin3d->use_list) { elem= yglNewCachedList3dElem(); } else { elem= yglNewDirectList3dElem(); } elem->func= yglDrawTarray3d; if(do_alpha) { colrsiz= 4; } else { colrsiz= 3; } if(cpervrt) { ncolr= 3*ntri; } else { ncolr= ntri; } /* compute the size of the data structure plus all data */ size= sizeof(yTarray3dData)+sizeof(float)*9*2*ntri+sizeof(float)*colrsiz*ncolr; data= (yTarray3dData *) p_malloc(size); elem->data= data; /* set all elements of the data structure, including pointers into the data block */ data->ntri= ntri; data->edge= edge; data->smooth= smooth; data->do_light= do_light; data->do_alpha= do_alpha; data->cpervrt= cpervrt; data->cubemap= cubemap; data->emit= emit; data->xyz= dxyz= (float *) ((char *)data+sizeof(yTarray3dData)); data->norm= dnorm= data->xyz+9*ntri; data->colr= dcolr= data->norm+9*ntri; /* copy data into the new storage space */ nval= colrsiz*ncolr; for(i= 0; i < nval; i++) { dcolr[i]= (float) colr[i]; } nval= 3*3*ntri; for(i= 0; i < nval; i++) { dxyz[i]= (float) xyz[i]; dnorm[i]= (float) norm[i]; } /* compute and save the bounding box */ yglSetLims3d(elem, 3*ntri, data->xyz); } void yglQarray3d(long nquad, double *xyz, double *norm, double *colr, long edge, long smooth, long do_light, long do_alpha, long cpervrt) { /* variables for the display list */ yList3d_Elem *elem; yQarray3dData *data; long size, colrsiz, ncolr, i, nval; float *dxyz, *dnorm, *dcolr; /* There are nquad quadrangless. There is one color per quad or one color per quad vertex. There are 4*nquad vertices and normals. edge non-zero means outline the polygon, not fill it. smooth non-zero means normals have been provided and smooth shading should be used. ?????? smooth only ??????? do_light means enable lighting ????? maybe means emissive lighting if zero ????? do_alpha means colors contain an alpha component colr_per_vert non-zero means one color per vertex */ /* add a new entry to the 3D display list (it will be in the list when it is returned). */ if(!glCurrWin3d) return; if(glCurrWin3d->use_list) { elem= yglNewCachedList3dElem(); } else { elem= yglNewDirectList3dElem(); } elem->func= yglDrawQarray3d; if(do_alpha) { colrsiz= 4; } else { colrsiz= 3; } if(cpervrt) { ncolr= 4*nquad; } else { ncolr= nquad; } /* compute the size of the data structure plus all data */ size= sizeof(yQarray3dData)+sizeof(float)*12*2*nquad+sizeof(float)*colrsiz*ncolr; data= (yQarray3dData *) p_malloc(size); elem->data= data; /* set all elements of the data structure, including pointers into the data block */ data->nquad= nquad; data->edge= edge; data->smooth= smooth; data->do_light= do_light; data->do_alpha= do_alpha; data->cpervrt= cpervrt; data->xyz= dxyz= (float *) ((char *)data+sizeof(yQarray3dData)); data->norm= dnorm= data->xyz+12*nquad; data->colr= dcolr= data->norm+12*nquad; /* copy data into the new storage space */ nval= colrsiz*ncolr; for(i= 0; i < nval; i++) { dcolr[i]= (float) colr[i]; } nval= 3*4*nquad; for(i= 0; i < nval; i++) { dxyz[i]= (float) xyz[i]; dnorm[i]= (float) norm[i]; } /* compute and save the bounding box */ yglSetLims3d(elem, 4*nquad, data->xyz); } void yglTivarray3d(long ntri, long nvert, long *ptndx, double *xyz, double *norm, double *colr) { /* variables for the display list */ yList3d_Elem *elem; yTivarray3dData *data; long size, i, numndx; unsigned int *dptndx; float *dileave; double xmin, xmax, ymin, ymax, zmin, zmax; /* There are ntri triangles and nvert vertices. Each triangle is specified by three indices into the xyz, norm, and colr arrays. The colors are RGBA. */ /* add a new entry to the 3D display list (it will be in the list when it is returned). */ if(!glCurrWin3d) return; if(glCurrWin3d->use_list) { elem= yglNewCachedList3dElem(); } else { elem= yglNewDirectList3dElem(); } elem->func= yglDrawTivarray3d; numndx= 3*ntri; /* compute the size of the data structure plus all data */ size= sizeof(yTivarray3dData)+sizeof(float)*(3+3+4)*nvert+sizeof(dptndx[0])*numndx; data= (yTivarray3dData *) p_malloc(size); elem->data= data; /* set all elements of the data structure, including pointers into the data block */ data->ntri= ntri; data->nvert= nvert; data->ptndx= dptndx= (unsigned int *) ((char *)data+sizeof(yTivarray3dData)); data->ileave= dileave= (float *) (data->ptndx+numndx); /* copy data into the new storage space */ for(i= 0; i < numndx; i++) { dptndx[i]= (unsigned int) ptndx[i]; } for(i= 0; i < nvert; i++) { dileave[10*i ]= (float) colr[4*i]; dileave[10*i+1]= (float) colr[4*i+1]; dileave[10*i+2]= (float) colr[4*i+2]; dileave[10*i+3]= (float) colr[4*i+3]; dileave[10*i+4]= (float) norm[3*i]; dileave[10*i+5]= (float) norm[3*i+1]; dileave[10*i+6]= (float) norm[3*i+2]; dileave[10*i+7]= (float) xyz[3*i]; dileave[10*i+8]= (float) xyz[3*i+1]; dileave[10*i+9]= (float) xyz[3*i+2]; } /* Compute and save the bounding box. WARNING: this could be WRONG if there are points in the arrays that are never referenced. */ if(nvert <= 0) return; xmin= xmax= xyz[0]; ymin= ymax= xyz[1]; zmin= zmax= xyz[2]; for(i= 1; i < nvert; i++) { if(xyz[3*i] < xmin) xmin= xyz[3*i]; if(xyz[3*i] > xmax) xmax= xyz[3*i]; if(xyz[3*i+1] < ymin) ymin= xyz[3*i+1]; if(xyz[3*i+1] > ymax) ymax= xyz[3*i+1]; if(xyz[3*i+2] < zmin) zmin= xyz[3*i+2]; if(xyz[3*i+2] > zmax) zmax= xyz[3*i+2]; } elem->box.xmin= (float) xmin; elem->box.xmax= (float) xmax; elem->box.ymin= (float) ymin; elem->box.ymax= (float) ymax; elem->box.zmin= (float) zmin; elem->box.zmax= (float) zmax; } void yglTvarray3d(long ntri, long nvert, long do_alpha, long cpervrt, long *ptndx, double *xyz, double *norm, double *colr) { /* variables for the display list */ yList3d_Elem *elem; yTvarray3dData *data; long size, i, ncopy, clrsiz; unsigned int *dptndx; float *dxyz, *dnorm, *dcolr; double xmin, xmax, ymin, ymax, zmin, zmax; #undef TVDBG #ifdef TVDBG long ndmin=2000000000, ndmax=-2000000000; double nrmin=1.0e150, nrmax=-1.0e150, ntmp; double nrmin2=1.0e150, nrmax2=-1.0e150; xmin=1.0e150; xmax=-1.0e150; #endif /* There are ntri triangles and nvert vertices. Each triangle is specified by three indices into the xyz, norm, and colr arrays. An option is also provided to use a single color for all triangles. The colors are RGB or RGBA. This is like yglTivarray3d except it uses three separate arrays instead of one interleaved array. */ /* add a new entry to the 3D display list (it will be in the list when it is returned). */ if(!glCurrWin3d) return; if(glCurrWin3d->use_list) { elem= yglNewCachedList3dElem(); } else { elem= yglNewDirectList3dElem(); } elem->func= yglDrawTvarray3d; /* compute the size of the data structure plus all data */ size= sizeof(yTvarray3dData)+sizeof(float)*(3+3)*nvert+sizeof(dptndx[0])*3*ntri; if(do_alpha) clrsiz= 4; else clrsiz= 3; if(cpervrt) { size += sizeof(float)*clrsiz*nvert; } else { size += sizeof(float)*clrsiz; } data= (yTvarray3dData *) p_malloc(size); elem->data= data; /* set all elements of the data structure, including pointers into the data block */ data->ntri= ntri; data->nvert= nvert; data->cpervrt= cpervrt; data->do_alpha= do_alpha; data->ptndx= dptndx= (unsigned int *) ((char *)data+sizeof(yTvarray3dData)); data->xyz= dxyz= (float *) (data->ptndx+3*ntri); data->norm= dnorm= data->xyz+3*nvert; data->colr= dcolr= data->norm+3*nvert; #ifdef TVDBG printf("xyz pointer is %x, norm pointer is %x, colr pointer is %x\n", data->xyz, data->norm, data->colr); #endif /* copy data into the new storage space */ for(i= 0; i < 3*ntri; i++) { #ifdef TVDBG if(ptndx[i] < ndmin) ndmin= ptndx[i]; if(ptndx[i] > ndmax) ndmax= ptndx[i]; #endif dptndx[i]= (unsigned int) ptndx[i]; } #ifdef TVDBG /* printf("elements for xyz is %ld\n", data->norm-data->xyz); printf("elements for norm is %ld\n", data->colr-data->norm); printf("struct uses %ld bytes, %ld bytes allocated\n", (char *)(data->colr+clrsiz*nvert)-(char *)data, size); */ printf("minimum index is %ld and max is %ld, nvert is %ld\n", ndmin, ndmax, nvert); #endif /* there are the same number of coords and normals in all cases */ for(i= 0; i < nvert; i++) { #ifdef TVDBG if(xyz[3*i] < xmin) xmin= xyz[3*i]; if(xyz[3*i] > xmax) xmax= xyz[3*i]; if(xyz[3*i+1] < xmin) xmin= xyz[3*i+1]; if(xyz[3*i+1] > xmax) xmax= xyz[3*i+1]; if(xyz[3*i+2] < xmin) xmin= xyz[3*i+2]; if(xyz[3*i+2] > xmax) xmax= xyz[3*i+2]; ntmp= norm[3*i]*norm[3*i]+norm[3*i+1]*norm[3*i+1]+norm[3*i+2]*norm[3*i+2]; if(ntmp < nrmin) nrmin= ntmp; if(ntmp > nrmax) nrmax= ntmp; #endif dxyz[3*i ]= (float) xyz[3*i]; dxyz[3*i+1]= (float) xyz[3*i+1]; dxyz[3*i+2]= (float) xyz[3*i+2]; dnorm[3*i ]= (float) norm[3*i]; dnorm[3*i+1]= (float) norm[3*i+1]; dnorm[3*i+2]= (float) norm[3*i+2]; #ifdef TVDBG ntmp= dnorm[3*i]*dnorm[3*i]+dnorm[3*i+1]*dnorm[3*i+1]+dnorm[3*i+2]*dnorm[3*i+2]; if(ntmp < nrmin2) nrmin2= ntmp; if(ntmp > nrmax2) nrmax2= ntmp; #endif } #ifdef TVDBG printf("minimum x is %e and max is %e\n", xmin, xmax); printf("minimum norm is %e and max is %e\n", nrmin, nrmax); printf("minimum norm in struct is %e and max is %e\n", nrmin2, nrmax2); #endif if(cpervrt) { if(do_alpha) { ncopy= 4*nvert; } else { ncopy= 3*nvert; } } else { if(do_alpha) { ncopy= 4; } else { ncopy= 3; } } for(i= 0; i < ncopy; i++) { dcolr[i]= (float) colr[i]; } /* Compute and save the bounding box. WARNING: this could be WRONG if there are points in the arrays that are never referenced. */ if(nvert <= 0) return; xmin= xmax= xyz[0]; ymin= ymax= xyz[1]; zmin= zmax= xyz[2]; for(i= 1; i < nvert; i++) { if(xyz[3*i] < xmin) xmin= xyz[3*i]; if(xyz[3*i] > xmax) xmax= xyz[3*i]; if(xyz[3*i+1] < ymin) ymin= xyz[3*i+1]; if(xyz[3*i+1] > ymax) ymax= xyz[3*i+1]; if(xyz[3*i+2] < zmin) zmin= xyz[3*i+2]; if(xyz[3*i+2] > zmax) zmax= xyz[3*i+2]; } elem->box.xmin= (float) xmin; elem->box.xmax= (float) xmax; elem->box.ymin= (float) ymin; elem->box.ymax= (float) ymax; elem->box.zmin= (float) zmin; elem->box.zmax= (float) zmax; } void yglTex3d(float ds, double *origin, double *boxsiz) { /* variables for the display list */ yList3d_Elem *elem; yTex3dData *data; long i, size, nval; double *dorigin, *dboxsiz; /* there are nx-by-ny coordinates and normals and one color ????????? */ /* add a new entry to the 3D display list (it will be in the list when it is returned). */ elem= yglNewDirectList3dElem(); elem->func= yglDrawTex3d; /* compute the size of the data structure plus all data */ size= sizeof(yTex3dData)+sizeof(double)*2*3; data= (yTex3dData *) p_malloc(size); elem->data= data; /* set all elements of the data structure, including pointers into the data block */ data->ds= ds; data->origin= dorigin= (double *) ((char *)data+sizeof(yTex3dData)); data->boxsiz= dboxsiz= data->origin+3; /* copy data into the new storage space */ nval= 3; for(i= 0; i < nval; i++) { dorigin[i]= origin[i]; dboxsiz[i]= boxsiz[i]; } /* compute and save the bounding box */ elem->box.xmin= origin[0]; elem->box.xmax= origin[0]+boxsiz[0]; elem->box.ymin= origin[1]; elem->box.ymax= origin[1]+boxsiz[1]; elem->box.zmin= origin[2]; elem->box.zmax= origin[2]+boxsiz[2]; } void yglTexcell2d(long nx, long ny, long nz, double *znsiz, char *texval) { /* variables for the display list */ yList3d_Elem *elem; yTexcell2dData *data; long i, size, nval; unsigned char *dtexval; double *dznsiz; /* there are nx-by-ny coordinates and normals and one color ????????? */ /* add a new entry to the 3D display list (it will be in the list when it is returned). */ if(!glCurrWin3d) return; if(glCurrWin3d->use_list) { elem= yglNewCachedList3dElem(); } else { elem= yglNewDirectList3dElem(); } elem->func= yglDrawTexcell2d; /* compute the size of the data structure plus all data */ size= sizeof(yTexcell2dData)+sizeof(double)*3+sizeof(char)*4*nx*ny*nz; data= (yTexcell2dData *) p_malloc(size); elem->data= data; /* set all elements of the data structure, including pointers into the data block */ data->nx= nx; data->ny= ny; data->nz= nz; data->znsiz= dznsiz= (double *) ((char *)data+sizeof(yTexcell2dData)); data->texval= dtexval= (unsigned char *) (data->znsiz+3); /* copy data into the new storage space */ nval= 3; for(i= 0; i < nval; i++) { dznsiz[i]= znsiz[i]; } nval= 4*nx*ny*nz; for(i= 0; i < nval; i++) { dtexval[i]= (unsigned char) texval[i]; } /* compute and save the bounding box */ elem->box.xmin= 0.0; elem->box.xmax= (nx-1)*znsiz[0]; elem->box.ymin= 0.0; elem->box.ymax= (ny-1)*znsiz[1]; elem->box.zmin= 0.0; elem->box.zmax= (nz-1)*znsiz[2]; } void yglPlpix3d(long nx, long ny, char *pix) { /* variables for the display list */ yList3d_Elem *elem; yPix3dData *data; long i, size, nval; unsigned char *dpix; /* there are nx-by-ny pixels */ /* add a new entry to the 3D display list (it will be in the list when it is returned). */ if(!glCurrWin3d) return; if(glCurrWin3d->use_list) { elem= yglNewCachedList3dElem(); } else { elem= yglNewDirectList3dElem(); } elem->func= yglDrawPix3d; /* compute the size of the data structure plus all data */ size= sizeof(yPix3dData)+sizeof(char)*3*nx*ny; data= (yPix3dData *) p_malloc(size); elem->data= data; /* set all elements of the data structure, including pointers into the data block */ data->nx= nx; data->ny= ny; data->pix= dpix= (unsigned char *)data+sizeof(yPix3dData); /* copy data into the new storage space */ nval= 3*nx*ny; for(i= 0; i < nval; i++) { dpix[i]= (char) pix[i]; } /* A bounding box doesn't make sense for this function because it uses pixel coords. */ } void yglDrawPolys3d(int mode, void *vdata) { yPoly3dData *data= (yPoly3dData *)vdata; yglPolys(data->npolys, data->len, data->xyz, data->norm, data->colr, data->edge, data->smooth, data->do_light); } void yglDrawGlyphs3d(int mode, void *vdata) { yGlyph3dData *data= (yGlyph3dData *)vdata; yglGlyphs(data->nglyph, data->origin, data->scal, data->theta, data->phi, data->colr); } void yglDrawCells3d(int mode, void *vdata) { yCell3dData *data= (yCell3dData *)vdata; yglCells(data->nx, data->ny, (float (*)[3])(data->xyz), data->norm, data->colr, data->do_alpha); } void yglDrawPlm3d(int mode, void *vdata) { yPlm3dData *data= (yPlm3dData *)vdata; yglPlm(data->nx, data->ny, data->xyz, data->colr); } void yglDrawPlf3d(int mode, void *vdata) { yPlf3dData *data= (yPlf3dData *)vdata; yglPlf(data->nx, data->ny, data->xyz, data->colr); } void yglDrawSurf3d(int mode, void *vdata) { ySurf3dData *data= (ySurf3dData *)vdata; yglSurf(data->do_alpha, data->nx, data->ny, data->xyz, data->norm, data->colr); } void yglDrawColrSurf3d(int mode, void *vdata) { yColrSurf3dData *data= (yColrSurf3dData *)vdata; yglColrSurf(data->do_alpha, data->nx, data->ny, data->xyz, data->norm, data->colr); } void yglDrawLines3d(int mode, void *vdata) { yLines3dData *data= (yLines3dData *)vdata; yglLines(data->nvert, data->xyz, data->colr); } void yglDrawPoints3d(int mode, void *vdata) { yPoints3dData *data= (yPoints3dData *)vdata; yglPoints(data->nvert, data->xyz, data->colr); } void yglDrawTstrips3d(int mode, void *vdata) { yTstrips3dData *data= (yTstrips3dData *)vdata; if(data->do_alpha) { yglTstripsAlpha(data->nstrips, data->len, data->xyz, data->norm, data->colr, data->edge, data->smooth, data->do_light); } else { yglTstrips(data->nstrips, data->len, data->xyz, data->norm, data->colr, data->edge, data->smooth, data->do_light); } } void yglDrawTstripsNdx3d(int mode, void *vdata) { yTstripsNdx3dData *data= (yTstripsNdx3dData *)vdata; if(data->do_alpha) { yglTstripsAlphaNdx(data->nstrips, data->numedg, data->ntri, data->len, data->ndx, data->xyz, data->norm, data->colr, data->edge); } else { yglTstripsNdx(data->nstrips, data->numedg, data->ntri, data->len, data->ndx, data->xyz, data->norm, data->colr, data->edge); } } void yglDrawQstrips3d(int mode, void *vdata) { yQstrips3dData *data= (yQstrips3dData *)vdata; if(data->do_alpha) { yglQstripsAlpha(data->nstrips, data->len, data->xyz, data->norm, data->colr, data->edge, data->smooth, data->do_light); } else { yglQstrips(data->nstrips, data->len, data->xyz, data->norm, data->colr, data->edge, data->smooth, data->do_light); } } void yglDrawTarray3d(int mode, void *vdata) { yTarray3dData *data= (yTarray3dData *)vdata; if(data->do_alpha) { yglTarrayAlpha(data->smooth, data->ntri, data->xyz, data->norm, data->colr, data->edge, data->cpervrt, data->emit); } else { yglTarray(data->smooth, data->ntri, data->xyz, data->norm, data->colr, data->edge, data->cpervrt, data->emit); } } void yglDrawQarray3d(int mode, void *vdata) { yQarray3dData *data= (yQarray3dData *)vdata; if(data->do_alpha) { yglQarrayAlpha(data->smooth, data->nquad, data->xyz, data->norm, data->colr, data->edge, data->cpervrt); } else { yglQarray(data->smooth, data->nquad, data->xyz, data->norm, data->colr, data->edge, data->cpervrt); } } void yglDrawTivarray3d(int mode, void *vdata) { yTivarray3dData *data= (yTivarray3dData *)vdata; yglTivarray(data->ntri, data->ptndx, data->ileave); } void yglDrawTvarray3d(int mode, void *vdata) { yTvarray3dData *data= (yTvarray3dData *)vdata; yglTvarray(data->do_alpha, data->cpervrt, data->ntri, data->ptndx, data->xyz, data->norm, data->colr); } void yglDrawTex3d(int mode, void *vdata) { yTex3dData *data= (yTex3dData *)vdata; yglTex3dbox(data->ds, data->origin, data->boxsiz); } void yglDrawTexcell2d(int mode, void *vdata) { yTexcell2dData *data= (yTexcell2dData *)vdata; yglTexcell2(data->nx, data->ny, data->nz, data->znsiz, data->texval); } void yglDrawPix3d(int mode, void *vdata) { yPix3dData *data= (yPix3dData *)vdata; yglPutPixels(data->nx, data->ny, data->pix); } yorick-gl-1.1+cvs20070922+dfsg.orig/glInfo.c0000640000175000017500000003642610313362462020021 0ustar thibautthibaut/* * $Id: glInfo.c,v 1.1.1.1 2005/09/18 22:07:46 dhmunro Exp $ * GL visual enquiry functions for X11, using GLX */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #include "config.h" #include "pstdlib.h" #include "play.h" #include "playgl.h" /* #include "playx.h" */ #include #include #include "glInfo.h" #include /* The code that displays information about the visuals was taken from the glxinfo.c file from Brain Paul's mesa-xdemos. */ #include /* #include */ #include extern void print_visual_attribs_verbose(const struct visual_attribs *attribs); extern void print_visual_attribs_short_header(void); extern void print_visual_attribs_short(const struct visual_attribs *attribs); extern void print_visual_attribs_long_header(void); extern void print_visual_attribs_long(const struct visual_attribs *attribs); extern void print_visual_info(Display *dpy, int scrnum, InfoMode mode); extern void get_visual_attribs(Display *dpy, XVisualInfo *vInfo, struct visual_attribs *attribs); /* $Id: glInfo.c,v 1.1.1.1 2005/09/18 22:07:46 dhmunro Exp $ */ /* * Copyright (C) 1999 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* * This program is a work-alike of the IRIX glxinfo program. * Command line options: * -t print wide table * -v print verbose information * -display DisplayName specify the X display to interogate * * Brian Paul 26 January 2000 */ /* * Print a list of extensions, with word-wrapping. */ void print_extension_list(const char *ext) { const char *indentString = " "; const int indent = 4; const int max = 79; int width, i, j; if (!ext || !ext[0]) return; width = indent; printf(indentString); i = j = 0; while (1) { if (ext[j] == ' ' || ext[j] == 0) { /* found end of an extension name */ const int len = j - i; if (width + len > max) { /* start a new line */ printf("\n"); width = indent; printf(indentString); } /* print the extension name between ext[i] and ext[j] */ while (i < j) { printf("%c", ext[i]); i++; } /* either we're all done, or we'll continue with next extension */ width += len + 1; if (ext[j] == 0) { break; } else { i++; j++; if (ext[j] == 0) break; printf(", "); width += 2; } } j++; } printf("\n"); } void print_screen_info(Display *dpy, int scrnum) { Window win; int attribSingle[] = { GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, None }; int attribDouble[] = { GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_DOUBLEBUFFER, None }; XSetWindowAttributes attr; unsigned long mask; Window root; GLXContext ctx; XVisualInfo *visinfo; int width = 100, height = 100; root = RootWindow(dpy, scrnum); visinfo = glXChooseVisual(dpy, scrnum, attribSingle); if (!visinfo) { visinfo = glXChooseVisual(dpy, scrnum, attribDouble); if (!visinfo) { fprintf(stderr, "Error: couldn't find RGB GLX visual\n"); return; } } attr.background_pixel = 0; attr.border_pixel = 0; attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone); attr.event_mask = StructureNotifyMask | ExposureMask; mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; win = XCreateWindow(dpy, root, 0, 0, width, height, 0, visinfo->depth, InputOutput, visinfo->visual, mask, &attr); ctx = glXCreateContext( dpy, visinfo, NULL, True ); if (!ctx) { fprintf(stderr, "Error: glXCreateContext failed\n"); XDestroyWindow(dpy, win); return; } if (glXMakeCurrent(dpy, win, ctx)) { const char *serverVendor = glXQueryServerString(dpy, scrnum, GLX_VENDOR); const char *serverVersion = glXQueryServerString(dpy, scrnum, GLX_VERSION); const char *serverExtensions = glXQueryServerString(dpy, scrnum, GLX_EXTENSIONS); const char *clientVendor = glXGetClientString(dpy, GLX_VENDOR); const char *clientVersion = glXGetClientString(dpy, GLX_VERSION); const char *clientExtensions = glXGetClientString(dpy, GLX_EXTENSIONS); const char *glxExtensions = glXQueryExtensionsString(dpy, scrnum); const char *glVendor = (const char *) glGetString(GL_VENDOR); const char *glRenderer = (const char *) glGetString(GL_RENDERER); const char *glVersion = (const char *) glGetString(GL_VERSION); const char *glExtensions = (const char *) glGetString(GL_EXTENSIONS); printf("display: %s screen:%d\n", DisplayString(dpy), scrnum); printf("direct rendering: %s\n", glXIsDirect(dpy, ctx) ? "Yes" : "No"); printf("server glx vendor string: %s\n", serverVendor); printf("server glx version string: %s\n", serverVersion); printf("server glx extensions:\n"); print_extension_list(serverExtensions); printf("client glx vendor string: %s\n", clientVendor); printf("client glx version string: %s\n", clientVersion); printf("client glx extensions:\n"); print_extension_list(clientExtensions); printf("GLX extensions:\n"); print_extension_list(glxExtensions); printf("OpenGL vendor string: %s\n", glVendor); printf("OpenGL renderer string: %s\n", glRenderer); printf("OpenGL version string: %s\n", glVersion); printf("OpenGL extensions:\n"); print_extension_list(glExtensions); } else { fprintf(stderr, "Error: glXMakeCurrent failed\n"); } glXDestroyContext(dpy, ctx); XDestroyWindow(dpy, win); } const char *visual_class_name(int cls) { switch (cls) { case StaticColor: return "StaticColor"; case PseudoColor: return "PseudoColor"; case StaticGray: return "StaticGray"; case GrayScale: return "GrayScale"; case TrueColor: return "TrueColor"; case DirectColor: return "DirectColor"; default: return ""; } } const char *visual_class_abbrev(int cls) { switch (cls) { case StaticColor: return "sc"; case PseudoColor: return "pc"; case StaticGray: return "sg"; case GrayScale: return "gs"; case TrueColor: return "tc"; case DirectColor: return "dc"; default: return ""; } } void get_visual_attribs(Display *dpy, XVisualInfo *vInfo, struct visual_attribs *attribs) { const char *ext = glXQueryExtensionsString(dpy, vInfo->screen); memset(attribs, 0, sizeof(struct visual_attribs)); attribs->id = vInfo->visualid; #if defined(__cplusplus) || defined(c_plusplus) attribs->klass = vInfo->c_class; #else attribs->klass = vInfo->class; #endif attribs->depth = vInfo->depth; attribs->redMask = vInfo->red_mask; attribs->greenMask = vInfo->green_mask; attribs->blueMask = vInfo->blue_mask; attribs->colormapSize = vInfo->colormap_size; attribs->bitsPerRGB = vInfo->bits_per_rgb; if (glXGetConfig(dpy, vInfo, GLX_USE_GL, &attribs->supportsGL) != 0) return; glXGetConfig(dpy, vInfo, GLX_BUFFER_SIZE, &attribs->bufferSize); glXGetConfig(dpy, vInfo, GLX_LEVEL, &attribs->level); glXGetConfig(dpy, vInfo, GLX_RGBA, &attribs->rgba); glXGetConfig(dpy, vInfo, GLX_DOUBLEBUFFER, &attribs->doubleBuffer); glXGetConfig(dpy, vInfo, GLX_STEREO, &attribs->stereo); glXGetConfig(dpy, vInfo, GLX_AUX_BUFFERS, &attribs->auxBuffers); glXGetConfig(dpy, vInfo, GLX_RED_SIZE, &attribs->redSize); glXGetConfig(dpy, vInfo, GLX_GREEN_SIZE, &attribs->greenSize); glXGetConfig(dpy, vInfo, GLX_BLUE_SIZE, &attribs->blueSize); glXGetConfig(dpy, vInfo, GLX_ALPHA_SIZE, &attribs->alphaSize); glXGetConfig(dpy, vInfo, GLX_DEPTH_SIZE, &attribs->depthSize); glXGetConfig(dpy, vInfo, GLX_STENCIL_SIZE, &attribs->stencilSize); glXGetConfig(dpy, vInfo, GLX_ACCUM_RED_SIZE, &attribs->accumRedSize); glXGetConfig(dpy, vInfo, GLX_ACCUM_GREEN_SIZE, &attribs->accumGreenSize); glXGetConfig(dpy, vInfo, GLX_ACCUM_BLUE_SIZE, &attribs->accumBlueSize); glXGetConfig(dpy, vInfo, GLX_ACCUM_ALPHA_SIZE, &attribs->accumAlphaSize); /* transparent pixel value not implemented yet */ attribs->transparent = 0; /* multisample tests not implemented yet */ attribs->numSamples = 0; attribs->numMultisample = 0; #if defined(GLX_EXT_visual_rating) if (ext && strstr(ext, "GLX_EXT_visual_rating")) { glXGetConfig(dpy, vInfo, GLX_VISUAL_CAVEAT_EXT, &attribs->visualCaveat); } else { attribs->visualCaveat = GLX_NONE_EXT; } #else attribs->visualCaveat = 0; #endif } void print_visual_attribs_verbose(const struct visual_attribs *attribs) { printf("Visual ID: %x depth=%d class=%s\n", attribs->id, attribs->depth, visual_class_name(attribs->klass)); printf(" bufferSize=%d level=%d renderType=%s doubleBuffer=%d stereo=%d\n", attribs->bufferSize, attribs->level, attribs->rgba ? "rgba" : "ci", attribs->doubleBuffer, attribs->stereo); printf(" rgba: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n", attribs->redSize, attribs->greenSize, attribs->blueSize, attribs->alphaSize); printf(" auxBuffers=%d depthSize=%d stencilSize=%d\n", attribs->auxBuffers, attribs->depthSize, attribs->stencilSize); printf(" accum: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n", attribs->accumRedSize, attribs->accumGreenSize, attribs->accumBlueSize, attribs->accumAlphaSize); printf(" multiSample=%d multiSampleBuffers=%d\n", attribs->numSamples, attribs->numMultisample); #ifdef GLX_EXT_visual_rating if (attribs->visualCaveat == GLX_NONE_EXT || attribs->visualCaveat == 0) printf(" visualCaveat=None\n"); else if (attribs->visualCaveat == GLX_SLOW_VISUAL_EXT) printf(" visualCaveat=Slow\n"); else if (attribs->visualCaveat == GLX_NON_CONFORMANT_VISUAL_EXT) printf(" visualCaveat=Nonconformant\n"); #endif printf(" %s\n", attribs->transparent ? "Transparent." : "Opaque."); } void print_visual_attribs_short_header(void) { printf(" visual x bf lv rg d st colorbuffer ax dp st accumbuffer ms cav\n"); printf(" id dep cl sp sz l ci b ro r g b a bf th cl r g b a ns b eat\n"); printf("----------------------------------------------------------------------\n"); } void print_visual_attribs_short(const struct visual_attribs *attribs) { char *caveat; #ifdef GLX_EXT_visual_rating if (attribs->visualCaveat == GLX_NONE_EXT || attribs->visualCaveat == 0) caveat = "None"; else if (attribs->visualCaveat == GLX_SLOW_VISUAL_EXT) caveat = "Slow"; else if (attribs->visualCaveat == GLX_NON_CONFORMANT_VISUAL_EXT) caveat = "Ncon"; #else caveat = "None"; #endif printf("0x%2x %2d %2s %2d %2d %2d %1s %2s %2s %2d %2d %2d %2d %2d %2d %2d", attribs->id, attribs->depth, visual_class_abbrev(attribs->klass), attribs->transparent, attribs->bufferSize, attribs->level, attribs->rgba ? "r" : "c", attribs->doubleBuffer ? "y" : ".", attribs->stereo ? "y" : ".", attribs->redSize, attribs->greenSize, attribs->blueSize, attribs->alphaSize, attribs->auxBuffers, attribs->depthSize, attribs->stencilSize ); printf(" %2d %2d %2d %2d %2d %1d %s\n", attribs->accumRedSize, attribs->accumGreenSize, attribs->accumBlueSize, attribs->accumAlphaSize, attribs->numSamples, attribs->numMultisample, caveat ); } void print_visual_attribs_long_header(void) { printf("Vis Vis Visual Trans buff lev render DB ste r g b a aux dep ste accum buffers MS MS\n"); printf(" ID Depth Type parent size el type reo sz sz sz sz buf th ncl r g b a num bufs\n"); printf("----------------------------------------------------------------------------------------------------\n"); } void print_visual_attribs_long(const struct visual_attribs *attribs) { printf("0x%2x %2d %-11s %2d %2d %2d %4s %3d %3d %3d %3d %3d %3d", attribs->id, attribs->depth, visual_class_name(attribs->klass), attribs->transparent, attribs->bufferSize, attribs->level, attribs->rgba ? "rgba" : "ci ", attribs->doubleBuffer, attribs->stereo, attribs->redSize, attribs->greenSize, attribs->blueSize, attribs->alphaSize ); printf(" %3d %4d %2d %3d %3d %3d %3d %2d %2d\n", attribs->auxBuffers, attribs->depthSize, attribs->stencilSize, attribs->accumRedSize, attribs->accumGreenSize, attribs->accumBlueSize, attribs->accumAlphaSize, attribs->numSamples, attribs->numMultisample ); } void print_visual_info(Display *dpy, int scrnum, InfoMode mode) { XVisualInfo template; XVisualInfo *visuals; int numVisuals; long mask; int i; /* get list of all visuals on this screen */ template.screen = scrnum; mask = VisualScreenMask; visuals = XGetVisualInfo(dpy, mask, &template, &numVisuals); if (mode == Verbose) { for (i = 0; i < numVisuals; i++) { struct visual_attribs attribs; get_visual_attribs(dpy, &visuals[i], &attribs); print_visual_attribs_verbose(&attribs); } } else if (mode == Normal) { print_visual_attribs_short_header(); for (i = 0; i < numVisuals; i++) { struct visual_attribs attribs; get_visual_attribs(dpy, &visuals[i], &attribs); print_visual_attribs_short(&attribs); } } else if (mode == Wide) { print_visual_attribs_long_header(); for (i = 0; i < numVisuals; i++) { struct visual_attribs attribs; get_visual_attribs(dpy, &visuals[i], &attribs); print_visual_attribs_long(&attribs); } } XFree(visuals); } yorick-gl-1.1+cvs20070922+dfsg.orig/glMouse.c0000640000175000017500000003506110313362462020210 0ustar thibautthibaut/* * $Id: glMouse.c,v 1.1.1.1 2005/09/18 22:07:46 dhmunro Exp $ * The functions in this file respond to mouse movements in * an OpenGL window. */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #include "ydata.h" #include "glMouse.h" #include "glcode.h" #include "glfunc.h" #include "glWrappers.h" /* #include */ #include #define SMALL_RADIUS 1.0e-2 static MsPoint ms_down, ms_last; int ygl_use_mouse_move= 1; double ygl_ms_mov_val= 4; static double ygl_view0[3], ygl_eye0[3], ygl_up0[3], ygl_center0[3], ygl_viewdist0; /* ----------- TEST ----------- */ #undef DBG_MOUSE #ifdef DBG_MOUSE #include "play.h" #include static char msg_buf[120]; #endif /* ----------- TEST ----------- */ void DoLButtonDown(int flags, int x, int y) { ms_down.x= x; ms_down.y= y; ms_last= ms_down; ygl_view0[0]= glCurrWin3d->view[0]; ygl_view0[1]= glCurrWin3d->view[1]; ygl_view0[2]= glCurrWin3d->view[2]; ygl_eye0[0]= glCurrWin3d->eye[0]; ygl_eye0[1]= glCurrWin3d->eye[1]; ygl_eye0[2]= glCurrWin3d->eye[2]; ygl_up0[0]= glCurrWin3d->up[0]; ygl_up0[1]= glCurrWin3d->up[1]; ygl_up0[2]= glCurrWin3d->up[2]; ygl_center0[0]= glCurrWin3d->center[0]; ygl_center0[1]= glCurrWin3d->center[1]; ygl_center0[2]= glCurrWin3d->center[2]; ygl_viewdist0= glCurrWin3d->viewdist; } void DoLButtonUp(int flags, int x, int y, glWinProp *theWin3d) { /* carry out rotation, even for a small motion */ new_mouse_pos(flags, x, y, 1, theWin3d); } static void ygl_set_idler(void); /* flags=1 for left 2 for middle, 3 for right button */ void new_mouse_pos(int flags, int x, int y, int force, glWinProp *theWin3d) { double distsq; int difx, dify; int action = glCurrWin3d->cursor_action; if (flags != 1) { /* for non-left button, do alternate action * glCurrWin3d->cursor_action == ACTION_ROTATE means * ROTATE left, ZOOM right, PAN middle * (also right is shift-left, middle is control-left) * left button always does glCurrWin3d->cursor_action * this is swapped with ACTION_ROTATE for other buttons */ if (action == ACTION_ROTATE) { if (flags == 3) action = ACTION_ZOOM; else action = ACTION_PAN; } else if (action == ACTION_ZOOM) { if (flags == 3) action = ACTION_ROTATE; else action = ACTION_PAN; } else { if (flags == 3) action = ACTION_ZOOM; else action = ACTION_ROTATE; } } /* has the mouse moved far enough to do something? */ difx= x-ms_last.x; dify= y-ms_last.y; distsq= difx*difx+dify*dify; /* No need to do anything if the mouse hasn't moved since last time */ if(distsq <= 0.0) return; /* Handle small residual mouse motion on button up (i.e. when force is turned on) */ if(!force && (distsq < ygl_ms_mov_val*ygl_ms_mov_val) ) return; #ifdef DBG_MOUSE sprintf(msg_buf, "distance moved squared is %e\n", distsq); p_stdout(msg_buf); sprintf(msg_buf, "x=%d, y=%d, ms_last.x=%d, ms_last.y=%d\n", x, y, ms_last.x, ms_last.y); p_stdout(msg_buf); #endif /* The mouse has moved significantly since the last point or the transform must be updated even for a small move. Call the proper action depending on the current effect of mouse motions. */ if (action == ACTION_ZOOM) { yglMouseZoom(x, y); } else if (action == ACTION_ROTATE) { yglMouseRot(x, y); } else { /* action == ACTION_PAN */ yglMousePan(x, y); } ms_last.x= x; ms_last.y= y; if (ygl_use_mouse_move) { /* indicate that this window needs to be redrawn */ theWin3d->dirty= 1; #if 0 #ifdef IMMEDIATE_REDRAW yglDraw3d(theWin3d); #else static long i_draw3_changes = -1; if (i_draw3_changes < 0) i_draw3_changes = Globalize("_draw3_changes", 0L); if (globTab[i_draw3_changes].ops == &dataBlockSym) { DataBlock *db = globTab[i_draw3_changes].value.db; globTab[i_draw3_changes].ops = &intScalar; Unref(db); } else if (globTab[i_draw3_changes].ops != &intScalar) { globTab[i_draw3_changes].ops = &intScalar; } globTab[i_draw3_changes].value.i = 1; ygl_set_idler(); #endif #endif } } static void ygl_set_idler(void) { extern Function *y_idler_function; Function *idler; static long i_draw3_idler = -1; if (i_draw3_idler < 0) i_draw3_idler = Globalize("_draw3_idler", 0L); ASSERT( (globTab[i_draw3_idler].ops == &dataBlockSym && globTab[i_draw3_idler].value.db->ops == &functionOps), "_draw3_idler is not a function") idler = (Function *)globTab[i_draw3_idler].value.db; y_idler_function = Ref(idler); } void yglMouseRot(int x, int y) { double rad, xx, yy; double r, csph, snph, snth, csth, r2, csph2, snph2, snth2, csth2; double p1[3], p2[3], b[3], aa[3], a[3], w[3]; double amag, dot12, dotb2, dotu1, dotua, dotub, dotv1, dotva, dotvb; double xcen, ycen, dotuv, len, p10, p11, p12, p20, p21, p22, normv; /* Compute a new rotation angle based on the offset from the original point. The assumption is that the mouse grabs the surface of a virtual trackball and drags it around. NOTE: the trackball is the size of the window, not the size of the object being displayed. A (theta,phi) on the sphere is computed from the (x,y) of the mouse click. The first step is to get a cylindrical coord pair, moving the radius in so that it is no more than the shortest half-axis of the window. The value of theta must lie between zero and pi/2 because the mouse can only grab the front of the trackball. */ /* Treat a return to the point where the button went down as a special case and just restore the original viewing transform. */ if(x == ms_down.x && y == ms_down.y) { glCurrWin3d->view[0]= ygl_view0[0]; glCurrWin3d->view[1]= ygl_view0[1]; glCurrWin3d->view[2]= ygl_view0[2]; glCurrWin3d->up[0]= ygl_up0[0]; glCurrWin3d->up[1]= ygl_up0[1]; glCurrWin3d->up[2]= ygl_up0[2]; glCurrWin3d->eye[0]= ygl_eye0[0]; glCurrWin3d->eye[1]= ygl_eye0[1]; glCurrWin3d->eye[2]= ygl_eye0[2]; /* NOTE: the center and viewing distance don't change for rotations */ return; } xcen= glCurrWin3d->width/2.0; ycen= glCurrWin3d->hite/2.0; rad= xcen; if(ycen < xcen) rad= ycen; xx= ms_down.x-xcen; yy= ms_down.y-ycen; r= sqrt(xx*xx+yy*yy); if(r < SMALL_RADIUS) { csph= 1.0; snph= 0.0; } else { csph= xx/r; snph= yy/r; } if(r > rad) r= rad; snth= r/rad; csth= sqrt(1.0-snth*snth); xx= x-xcen; yy= y-ycen; r2= sqrt(xx*xx+yy*yy); if(r2 < SMALL_RADIUS) { csph2= 1.0; snph2= 0.0; } else { csph2= xx/r2; snph2= yy/r2; } if(r2 > rad) r2= rad; snth2= r2/rad; csth2= sqrt(1.0-snth2*snth2); /* Let P1 be a unit vector pointing to (theta,phi) and P2 be a unit vector pointing to (theta2,phi2). Let A be a vector pointing along the rotation axis. The axis is in the direction of P1-cross-P2. Let B be the cross product of A and P1. The rotation takes P! into P2 and does not alter A. In a coordinate system with P1, B, and A as axes, the rotation takes a vector S into S' = S.P1 P2 + S.B (P1.P2 B - B.P2 P1) + S.A A P2, B, and A are known in terms of world coords P1 = sin(theta1)*cos(phi1) W + sin(theta1)*sin(phi1) U + cos(theta1) V where V is the viewing direction, U is the up vector, and W is U-cross-V. There is a similar expression for P2 and A and B can be computed from P1 and P2. */ p10= csph*snth; p11= snph*snth; p12= csth; p20= csph2*snth2; p21= snph2*snth2; p22= csth2; /* the vectors given above are in a coordinate system where U is the y-axis, V is the z-axis, and W is the x-axis. transform to global coordinates */ w[0]= ygl_view0[1]*ygl_up0[2]-ygl_view0[2]*ygl_up0[1]; w[1]= ygl_view0[2]*ygl_up0[0]-ygl_view0[0]*ygl_up0[2]; w[2]= ygl_view0[0]*ygl_up0[1]-ygl_view0[1]*ygl_up0[0]; p1[0]= p10*w[0]+p11*ygl_up0[0]+p12*ygl_view0[0]; p1[1]= p10*w[1]+p11*ygl_up0[1]+p12*ygl_view0[1]; p1[2]= p10*w[2]+p11*ygl_up0[2]+p12*ygl_view0[2]; p2[0]= p20*w[0]+p21*ygl_up0[0]+p22*ygl_view0[0]; p2[1]= p20*w[1]+p21*ygl_up0[1]+p22*ygl_view0[1]; p2[2]= p20*w[2]+p21*ygl_up0[2]+p22*ygl_view0[2]; aa[0]= p1[1]*p2[2]-p1[2]*p2[1]; aa[1]= p1[2]*p2[0]-p1[0]*p2[2]; aa[2]= p1[0]*p2[1]-p1[1]*p2[0]; amag= sqrt(aa[0]*aa[0]+aa[1]*aa[1]+aa[2]*aa[2]+1.0e-20); a[0]= aa[0]/amag; a[1]= aa[1]/amag; a[2]= aa[2]/amag; b[0]= a[1]*p1[2]-a[2]*p1[1]; b[1]= a[2]*p1[0]-a[0]*p1[2]; b[2]= a[0]*p1[1]-a[1]*p1[0]; dot12= p1[0]*p2[0]+p1[1]*p2[1]+p1[2]*p2[2]; dotb2= b[0]*p2[0]+b[1]*p2[1]+b[2]*p2[2]; if(dot12 < -1.0) dot12= -1.0; if(dot12 > 1.0) dot12= 1.0; if(dotb2 < -1.0) dotb2= -1.0; if(dotb2 > 1.0) dotb2= 1.0; /* compute the rotated view vector */ dotv1= (ygl_view0[0]*p1[0]+ygl_view0[1]*p1[1]+ygl_view0[2]*p1[2]); dotvb= (ygl_view0[0]*b[0] +ygl_view0[1]*b[1] +ygl_view0[2]*b[2]); dotva= (ygl_view0[0]*a[0] +ygl_view0[1]*a[1] +ygl_view0[2]*a[2]); if(dotv1 < -1.0) dotv1= -1.0; if(dotv1 > 1.0) dotv1= 1.0; if(dotvb < -1.0) dotvb= -1.0; if(dotvb > 1.0) dotvb= 1.0; if(dotva < -1.0) dotva= -1.0; if(dotva > 1.0) dotva= 1.0; glCurrWin3d->view[0]= dotv1*p2[0]+dotvb*(dot12*b[0]-dotb2*p1[0])+dotva*a[0]; glCurrWin3d->view[1]= dotv1*p2[1]+dotvb*(dot12*b[1]-dotb2*p1[1])+dotva*a[1]; glCurrWin3d->view[2]= dotv1*p2[2]+dotvb*(dot12*b[2]-dotb2*p1[2])+dotva*a[2]; normv= sqrt(glCurrWin3d->view[0]*glCurrWin3d->view[0]+glCurrWin3d->view[1]*glCurrWin3d->view[1] +glCurrWin3d->view[2]*glCurrWin3d->view[2]+1.0e-20); if(normv < 0.99 || normv > 1.01) { glCurrWin3d->view[0] /= normv; glCurrWin3d->view[1] /= normv; glCurrWin3d->view[2] /= normv; } /* compute the rotated up vector */ dotu1= (ygl_up0[0]*p1[0]+ygl_up0[1]*p1[1]+ygl_up0[2]*p1[2]); dotub= (ygl_up0[0]*b[0] +ygl_up0[1]*b[1] +ygl_up0[2]*b[2]); dotua= (ygl_up0[0]*a[0] +ygl_up0[1]*a[1] +ygl_up0[2]*a[2]); if(dotu1 < -1.0) dotu1= -1.0; if(dotu1 > 1.0) dotu1= 1.0; if(dotub < -1.0) dotub= -1.0; if(dotub > 1.0) dotub= 1.0; if(dotua < -1.0) dotua= -1.0; if(dotua > 1.0) dotua= 1.0; glCurrWin3d->up[0]= dotu1*p2[0]+dotub*(dot12*b[0]-dotb2*p1[0])+dotua*a[0]; glCurrWin3d->up[1]= dotu1*p2[1]+dotub*(dot12*b[1]-dotb2*p1[1])+dotua*a[1]; glCurrWin3d->up[2]= dotu1*p2[2]+dotub*(dot12*b[2]-dotb2*p1[2])+dotua*a[2]; /* make the up vector normal to the new viewing direction */ dotuv= glCurrWin3d->up[0]*glCurrWin3d->view[0]+glCurrWin3d->up[1]*glCurrWin3d->view[1] +glCurrWin3d->up[2]*glCurrWin3d->view[2]; glCurrWin3d->up[0] -= glCurrWin3d->view[0]*dotuv; glCurrWin3d->up[1] -= glCurrWin3d->view[1]*dotuv; glCurrWin3d->up[2] -= glCurrWin3d->view[2]*dotuv; len= sqrt(glCurrWin3d->up[0]*glCurrWin3d->up[0]+glCurrWin3d->up[1]*glCurrWin3d->up[1]+glCurrWin3d->up[2]*glCurrWin3d->up[2]+1.0e-20); glCurrWin3d->up[0] /= len; glCurrWin3d->up[1] /= len; glCurrWin3d->up[2] /= len; /* update the viewing position */ glCurrWin3d->eye[0]= glCurrWin3d->center[0]+glCurrWin3d->viewdist*glCurrWin3d->view[0]; glCurrWin3d->eye[1]= glCurrWin3d->center[1]+glCurrWin3d->viewdist*glCurrWin3d->view[1]; glCurrWin3d->eye[2]= glCurrWin3d->center[2]+glCurrWin3d->viewdist*glCurrWin3d->view[2]; } void yglMousePan(int x, int y) { double xx, yy, right0, right1, right2, xcen, ycen, imsize; /* Translate the viewpoint perpendicular to the viewing direction. The extent of the window at the viewing distance can be determined from the field-of-view. The distance the mouse has moved can then be used to change the eye position and center of attention. xcen and ycen are the half-widths of the screen in pixels and imsize is the half-size of the window at the viewing distance in world coords. */ xcen= glCurrWin3d->width/2.0; ycen= glCurrWin3d->hite/2.0; /* put a fudge factor into the image size to get the right motion on the screen */ imsize= 0.42*glCurrWin3d->viewdist*tan(glCurrWin3d->fov*atan(1.0)/45.0); /* set the distance moved since the mouse down in pixels */ xx= x-ms_down.x; yy= y-ms_down.y; /* ygl_view0 is the unit normal from the center of attention to the viewer. it does not change as the mouse is moved. ygl_up0 is the unit vector that points up in the window. form the unit vector that points right in the window. */ right0= ygl_up0[1]*ygl_view0[2]-ygl_up0[2]*ygl_view0[1]; right1= ygl_up0[2]*ygl_view0[0]-ygl_up0[0]*ygl_view0[2]; right2= ygl_up0[0]*ygl_view0[1]-ygl_up0[1]*ygl_view0[0]; /* move the center of attention by the fractions of the window represented by the mouse motions in the x and y windows (corresponding to right and ygl_up0) If xx is positive (moved right on the screen), the origin needs to move left. If yy is positive, the mouse moved down and the origin needs to move up. */ glCurrWin3d->center[0]= ygl_center0[0]+(-right0*xx/xcen+ygl_up0[0]*yy/ycen)*imsize; glCurrWin3d->center[1]= ygl_center0[1]+(-right1*xx/xcen+ygl_up0[1]*yy/ycen)*imsize; glCurrWin3d->center[2]= ygl_center0[2]+(-right2*xx/xcen+ygl_up0[2]*yy/ycen)*imsize; /* update the viewing position */ glCurrWin3d->eye[0]= glCurrWin3d->center[0]+glCurrWin3d->viewdist*glCurrWin3d->view[0]; glCurrWin3d->eye[1]= glCurrWin3d->center[1]+glCurrWin3d->viewdist*glCurrWin3d->view[1]; glCurrWin3d->eye[2]= glCurrWin3d->center[2]+glCurrWin3d->viewdist*glCurrWin3d->view[2]; } void yglMouseZoom(int x, int y) { double yy, ycen, frac, zm; /* zooming only considers the up/down mouse motion. moving from the bottom of the screen to the top zooms in by a factor of 4. moving the other direction zooms out by a factor of 4. */ ycen= glCurrWin3d->hite/2.0; yy= y-ms_down.y; /* scale to a fraction of the full screen */ frac= yy/ycen; /* this fractions is the base 2 log of the zoom factor */ zm= pow(2.0, frac); /* modify the lookat args */ glCurrWin3d->eye[0]= glCurrWin3d->center[0]+zm*ygl_viewdist0*glCurrWin3d->view[0]; glCurrWin3d->eye[1]= glCurrWin3d->center[1]+zm*ygl_viewdist0*glCurrWin3d->view[1]; glCurrWin3d->eye[2]= glCurrWin3d->center[2]+zm*ygl_viewdist0*glCurrWin3d->view[2]; glCurrWin3d->viewdist= zm*ygl_viewdist0; } void yglMouseMove(int flags, int x, int y, glWinProp *theWin3d) { #ifdef DBG_MOUSE p_stdout("mouse moved\n"); #endif new_mouse_pos(flags, x, y, 0, theWin3d); } void yglMouseFunc3d(long val) { /* Set the effect of mouse motions in the OpenGL window. */ if (val == 1) glCurrWin3d->cursor_action = ACTION_ROTATE; else if (val == 2) glCurrWin3d->cursor_action = ACTION_ZOOM; else if (val == 3) glCurrWin3d->cursor_action = ACTION_PAN; /* Ignore if value is bad */ } yorick-gl-1.1+cvs20070922+dfsg.orig/glcubetex.h0000640000175000017500000000231210313362465020560 0ustar thibautthibaut/* * $Id: glcubetex.h,v 1.1.1.1 2005/09/18 22:07:49 dhmunro Exp $ */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #ifndef __H_3DCUBETEX__ #define __H_3DCUBETEX__ #ifdef __cplusplus extern "C" { #endif /* In case your does not advertise EXT_texture_cube_map... NOTE: there are no new functions needed for cube maps */ #ifndef GL_EXT_texture_cube_map # define GL_NORMAL_MAP_EXT 0x8511 # define GL_REFLECTION_MAP_EXT 0x8512 # define GL_TEXTURE_CUBE_MAP_EXT 0x8513 # define GL_TEXTURE_BINDING_CUBE_MAP_EXT 0x8514 # define GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT 0x8515 # define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT 0x8516 # define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT 0x8517 # define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT 0x8518 # define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT 0x8519 # define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT 0x851A # define GL_PROXY_TEXTURE_CUBE_MAP_EXT 0x851B # define GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT 0x851C #endif #ifdef __cplusplus } #endif #endif /* __H_3DCUBETEX__ */ yorick-gl-1.1+cvs20070922+dfsg.orig/glx11setup.h0000640000175000017500000000073710313362471020621 0ustar thibautthibaut/* * $Id: glx11setup.h,v 1.1.1.1 2005/09/18 22:07:53 dhmunro Exp $ */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #ifndef GL_X11SETUP_H #define GL_X11SETUP_H #include /* XVisualInfo declared in Xutil.h */ #include typedef void (*GxHandler)(Engine *, Drawing *, XEvent *); #endif yorick-gl-1.1+cvs20070922+dfsg.orig/glfunc.h0000640000175000017500000000733410313362465020065 0ustar thibautthibaut/* * $Id: glfunc.h,v 1.1.1.1 2005/09/18 22:07:49 dhmunro Exp $ * Header file for GL related functions made known to yorick */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #ifndef __GLFUNC__ #define __GLFUNC__ #ifdef __cplusplus extern "C" { #endif /* need glcode.h for a typedef etc. */ #include "glcode.h" extern void YError(const char *msg); extern int (*YputsErr)(char *s); /* \n appended, like puts */ #ifdef _DEBUG #define ASSERT(cond, msg) if(!(cond)) YError(msg); #else #define ASSERT(cond, msg) #endif #define DEMAND(cond, msg) if(!(cond)) YError(msg); extern void yglDraw3d(glWinProp *theWin3d); extern void yglGetCenter(double *center); extern void yglGetEye(double *eye); extern void yglGetUp(double *up); extern void yglGetPixels(long nx, long ny, unsigned char *pix); extern void yglPutPixels(long nx, long ny, unsigned char *pix); extern void yglSetGLsize(long w, long h); extern void yglPolys(long npolys, long *len, float *xyz, float *norm, float *colr, long edge, long smooth, long do_light); extern void yglGlyphs(long nglyph, float *origin, float *scal, float *theta, float *phi, float *colr); extern void yglCells(long nx, long ny, float xyz[3][3], float *norm, float *colr, long do_alpha); extern void yglMap2ColorRaw3d(long ncolr, unsigned char *red, unsigned char *green, unsigned char *blue, double vmin, double vmax, double *var, long ntri, long *cellids, float *colr); extern double yglGetVers3d(void); extern int yglQueryTex3d(glWinProp *theWin3d); extern void yglPrepTex2d(void); extern void yglEndTex2d(void); extern void yglPrepTex3d(void); extern void yglEndTex3d(void); extern void yglPrepCubeTex(void); extern void yglEndCubeTex(void); extern void yglLdCubeTex(void); extern int yglQueryTexCube(void); extern void yglTexPoly(long nvert, float *verts, float *texverts); extern void yglLdTex3d(long nx, long ny, long nz, unsigned char *tex); extern void yglSetTexPalette(unsigned char *texpal); extern void yglTexTris(long ntri, float *verts, float *texverts); extern void yglTexcells(long nx, long ny, long nz, double delta[3], unsigned char *data, unsigned char *ctab); extern void yglTexcell2(long nx, long ny, long nz, double delta[3], unsigned char *texdata); extern void yglTex3dbox(double ds, double *origin, double *len); extern void yglPlm(long nx, long ny, float *xyz, float *colr); extern void yglPlf(long nx, long ny, float *xyz, float *colr); extern void yglSurf(long do_alpha, long nx, long ny, float *xyz, float *norm, float *colr); extern void yglColrSurf(long do_alpha, long nx, long ny, float *xyz, float *norm, float *colr); extern void yglLines(long nvert, float *xyz, float *colr); extern void yglPoints(long nvert, float *xyz, float *colr); extern void yglLineWidth(double width); extern void yglPrepContext(void); extern void yglSetPolyMode(int mode); extern void yglSetPolySides(int sides); extern float yglGetMatSpec(void); extern void yglSetMatSpec(float spec); extern void yglSetShade(int smooth); extern void yglSetColorType(int colorType); extern void yglSetLight(double ambient, double diffuse, double specular, double spower, double *sdir); extern void yglFrontFace3d(long dir); extern void yglTivarray(long ntri, unsigned int *ptndx, void *ileave); extern void yglTvarray(long do_alpha, long cpervrt, long ntri, unsigned int *ptndx, float *xyz, float *norm, float *colr); #ifdef __cplusplus } #endif #endif /* Include/Define */ yorick-gl-1.1+cvs20070922+dfsg.orig/glMouse.h0000640000175000017500000000212210313362462020205 0ustar thibautthibaut/* * $Id: glMouse.h,v 1.1.1.1 2005/09/18 22:07:46 dhmunro Exp $ * Header file for the routines that handle mouse motion * in OpenGL windows. */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #ifndef __GLMOUSE__ #define __GLMOUSE__ #include "glcode.h" #ifdef __cplusplus extern "C" { #endif typedef struct mspoint { int x; int y; } MsPoint; #define ACTION_ROTATE 1 #define ACTION_ZOOM 2 #define ACTION_PAN 3 extern void DoLButtonDown(int flags, int x, int y); extern void DoLButtonUp(int flags, int x, int y, glWinProp *theWin3d); extern void new_mouse_pos(int flags, int x, int y, int force, glWinProp *theWin3d); extern void yglMouseRot(int x, int y); extern void yglMousePan(int x, int y); extern void yglMouseZoom(int x, int y); extern void yglMouseMove(int flags, int x, int y, glWinProp *theWin3d); extern int ygl_use_mouse_move; extern double ygl_ms_mov_val; #ifdef __cplusplus } #endif #endif /* Include/Define */ yorick-gl-1.1+cvs20070922+dfsg.orig/glTarray.c0000640000175000017500000007037610515710063020370 0ustar thibautthibaut/* * $Id: glTarray.c,v 1.2 2006/10/19 14:48:19 dhmunro Exp $ */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #include "glcode.h" #include "glfunc.h" #include "glStrips.h" #include "glWrappers.h" #include #include /* #define CHEK_ERROR(x) yygl_chek_error(x) */ #define CHEK_ERROR(x) void yglTarray(long smooth, long ntri, float *xyz, float *norm, float *colr, long edge, long cpervrt, long emit) { long i, base; float oldRGBA[4]= {-1.0, -1.0, -1.0, 1.0}; float ambi[]= {1.0f, 1.0f, 1.0f, 1.0f}; /* draw an array of triangles */ if(ntri <= 0) return; if(alpha_pass) return; if(emit) { /* this creates diffuse light not connected to any light source */ glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambi); /* turn off all light associated with the light source */ glDisable(GL_LIGHT0); } else { if(smooth) { /* use smooth shading */ yglSetShade(1); } else { /* use flat shading */ yglSetShade(0); } } yglUpdateProperties(); base= 0; glBegin(GL_TRIANGLES); if(emit) { /* NOTE: no normals are supplied when using emissive colors */ if(cpervrt) { for(i= 0; i < ntri; i++) { glColor3fv(colr); colr += 3; glVertex3fv(xyz+base); glColor3fv(colr); colr += 3; glVertex3fv(xyz+base+3); glColor3fv(colr); colr += 3; glVertex3fv(xyz+base+6); base += 9; } } else { for(i= 0; i < ntri; i++) { if(colr[0] != oldRGBA[0] || colr[1] != oldRGBA[1] || colr[2] != oldRGBA[2]) { oldRGBA[0]= colr[0]; oldRGBA[1]= colr[1]; oldRGBA[2]= colr[2]; glColor3fv(oldRGBA); } colr += 3; /* NOTE: It makes no difference in local performance if the coords are converted to floats before being stored in the display list */ glVertex3fv(xyz+base); glVertex3fv(xyz+base+3); glVertex3fv(xyz+base+6); base += 9; } } } else { if(cpervrt) { for(i= 0; i < ntri; i++) { if(smooth) { glColor3fv(colr); colr += 3; glNormal3fv(norm+base); glVertex3fv(xyz+base); glColor3fv(colr); colr += 3; glNormal3fv(norm+base+3); glVertex3fv(xyz+base+3); glColor3fv(colr); colr += 3; glNormal3fv(norm+base+6); glVertex3fv(xyz+base+6); } else { glColor3fv(colr); colr += 3; glNormal3fv(norm+3*i); glVertex3fv(xyz+base); glColor3fv(colr); colr += 3; glVertex3fv(xyz+base+3); glColor3fv(colr); colr += 3; glVertex3fv(xyz+base+6); } base += 9; } } else { for(i= 0; i < ntri; i++) { if(colr[0] != oldRGBA[0] || colr[1] != oldRGBA[1] || colr[2] != oldRGBA[2]) { oldRGBA[0]= colr[0]; oldRGBA[1]= colr[1]; oldRGBA[2]= colr[2]; glColor3fv(oldRGBA); } colr += 3; /* NOTE: It makes no difference in local performance if the coords are converted to floats before being stored in the display list */ if(smooth) { glNormal3fv(norm+base); glVertex3fv(xyz+base); glNormal3fv(norm+base+3); glVertex3fv(xyz+base+3); glNormal3fv(norm+base+6); glVertex3fv(xyz+base+6); } else { glNormal3fv(norm+3*i); glVertex3fv(xyz+base); glVertex3fv(xyz+base+3); glVertex3fv(xyz+base+6); } base += 9; } } } glEnd(); if(emit) { /* restore prior diffuse light not connected to any light source */ glLightModelfv(GL_LIGHT_MODEL_AMBIENT, glCurrWin3d->curr_ambient); glEnable(GL_LIGHT0); } CHEK_ERROR("yglTarray"); } void yglTarrayAlpha(long smooth, long ntri, float *xyz, float *norm, float *colr, long edge, long cpervrt, long emit) { long i, base; float oldRGBA[4]= {-1.0, -1.0, -1.0, 1.0}; float ambi[]= {1.0f, 1.0f, 1.0f, 1.0f}; /* draw an array of triangles */ if(ntri <= 0) return; { char msg[120]; sprintf(msg, "in yglTarrayAlpha, alpha_pass is %d\n", alpha_pass); puts(msg); } if(!alpha_pass) return; { puts("drawing alpha tarray"); } if(emit) { /* this creates diffuse light not connected to any light source */ glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambi); /* turn off all light associated with the light source */ glDisable(GL_LIGHT0); } else { if(smooth) { /* use smooth shading */ yglSetShade(1); } else { /* use flat shading */ yglSetShade(0); } } glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDepthMask(GL_FALSE); yglUpdateProperties(); base= 0; glBegin(GL_TRIANGLES); if(emit) { /* NOTE: no normals are supplied when using emissive colors */ if(cpervrt) { for(i= 0; i < ntri; i++) { glColor4fv(colr); colr += 4; glVertex3fv(xyz+base); glColor4fv(colr); colr += 4; glVertex3fv(xyz+base+3); glColor4fv(colr); colr += 4; glVertex3fv(xyz+base+6); base += 9; } } else { for(i= 0; i < ntri; i++) { if(colr[0] != oldRGBA[0] || colr[1] != oldRGBA[1] || colr[2] != oldRGBA[2] || colr[3] != oldRGBA[3]) { oldRGBA[0]= colr[0]; oldRGBA[1]= colr[1]; oldRGBA[2]= colr[2]; oldRGBA[3]= colr[3]; glColor4fv(oldRGBA); } colr += 4; /* NOTE: It makes no difference in local performance if the coords are converted to floats before being stored in the display list */ glVertex3fv(xyz+base); glVertex3fv(xyz+base+3); glVertex3fv(xyz+base+6); base += 9; } } } else { if(cpervrt) { for(i= 0; i < ntri; i++) { if(smooth) { glColor4fv(colr); colr += 4; glNormal3fv(norm+base); glVertex3fv(xyz+base); glColor4fv(colr); colr += 4; glNormal3fv(norm+base+3); glVertex3fv(xyz+base+3); glColor4fv(colr); colr += 4; glNormal3fv(norm+base+6); glVertex3fv(xyz+base+6); } else { glColor4fv(colr); colr += 4; glNormal3fv(norm+3*i); glVertex3fv(xyz+base); glColor4fv(colr); colr += 4; glVertex3fv(xyz+base+3); glColor4fv(colr); colr += 4; glVertex3fv(xyz+base+6); } base += 9; } } else { for(i= 0; i < ntri; i++) { if(colr[0] != oldRGBA[0] || colr[1] != oldRGBA[1] || colr[2] != oldRGBA[2] || colr[3] != oldRGBA[3]) { oldRGBA[0]= colr[0]; oldRGBA[1]= colr[1]; oldRGBA[2]= colr[2]; oldRGBA[3]= colr[3]; glColor4fv(oldRGBA); } colr += 4; /* NOTE: It makes no difference in local performance if the coords are converted to floats before being stored in the display list */ if(smooth) { glNormal3fv(norm+base); glVertex3fv(xyz+base); glNormal3fv(norm+base+3); glVertex3fv(xyz+base+3); glNormal3fv(norm+base+6); glVertex3fv(xyz+base+6); } else { glNormal3fv(norm+3*i); glVertex3fv(xyz+base); glVertex3fv(xyz+base+3); glVertex3fv(xyz+base+6); } base += 9; } } } glEnd(); if(emit) { /* restore prior diffuse light not connected to any light source */ glLightModelfv(GL_LIGHT_MODEL_AMBIENT, glCurrWin3d->curr_ambient); glEnable(GL_LIGHT0); } glDepthMask(GL_TRUE); glDisable(GL_BLEND); CHEK_ERROR("yglTarrayNoArrAlpha"); } void yglTarrayCubeMapAlpha(long ntri, float *xyz, float *norm, float *colr, long cpervrt) { long i, base; float old_red= -1.0; float old_green= -1.0; float old_blue= -1.0; float old_alpha= -1.0; /* Draw an array of triangles using a cube map texture for lighting. Assumes the cube map texture has already been loaded and that cube map textures have been enabled. */ if(ntri <= 0) return; if(!alpha_pass) return; if( !yglQueryTex3d(glCurrWin3d) ) return; if( !glCurrWin3d->hascubetex) return; base= 0; glBegin(GL_TRIANGLES); if(cpervrt) { /* one color per vertex */ for(i= 0; i < ntri; i++) { glColor4fv(colr); colr += 4; glNormal3fv(norm+base); glVertex3fv(xyz+base); glColor4fv(colr); colr += 4; glNormal3fv(norm+base+3); glVertex3fv(xyz+base+3); glColor4fv(colr); colr += 4; glNormal3fv(norm+base+6); glVertex3fv(xyz+base+6); base += 9; } } else { /* one color per triangle */ for(i= 0; i < ntri; i++) { if(colr[0] != old_red || colr[1] != old_green || colr[2] != old_blue || colr[3] != old_alpha) { glColor4fv(colr); old_red= colr[0]; old_green= colr[1]; old_blue= colr[2]; old_alpha= colr[3]; } colr += 4; /* NOTE: It makes no difference in local performance if the coords are converted to floats before being stored in the display list */ glNormal3fv(norm+base); glVertex3fv(xyz+base); glNormal3fv(norm+base+3); glVertex3fv(xyz+base+3); glNormal3fv(norm+base+6); glVertex3fv(xyz+base+6); base += 9; } } glEnd(); CHEK_ERROR("yglTarrayCubeMapAlpha"); } void yglTarrayCubeMap(long ntri, float *xyz, float *norm, float *colr, long cpervrt) { long i, base; float old_colr[]= {-1.0, -1.0, -1.0, 1.0}; /* Draw an array of triangles using a cube map texture for lighting. Assumes the cube map texture has already been loaded and that cube map textures have been enabled. */ if(ntri <= 0) return; if(alpha_pass) return; if( !yglQueryTexCube() ) return; yglLdCubeTex(); yglPrepCubeTex(); base= 0; glBegin(GL_TRIANGLES); if(cpervrt) { for(i= 0; i < ntri; i++) { glColor3fv(colr); colr += 3; glNormal3fv(norm+base); glVertex3fv(xyz+base); glColor3fv(colr); colr += 3; glNormal3fv(norm+base+3); glVertex3fv(xyz+base+3); glColor3fv(colr); colr += 3; glNormal3fv(norm+base+6); glVertex3fv(xyz+base+6); base += 9; } } else { for(i= 0; i < ntri; i++) { if(colr[0] != old_colr[0] || colr[1] != old_colr[1] || colr[2] != old_colr[2]) { glColor4fv(old_colr); old_colr[0]= colr[0]; old_colr[1]= colr[1]; old_colr[2]= colr[2]; } colr += 3; /* NOTE: It makes no difference in local performance if the coords are converted to floats before being stored in the display list */ glNormal3fv(norm+base); glVertex3fv(xyz+base); glNormal3fv(norm+base+3); glVertex3fv(xyz+base+3); glNormal3fv(norm+base+6); glVertex3fv(xyz+base+6); base += 9; } } glEnd(); yglEndCubeTex(); CHEK_ERROR("yglTarrayCubeMapAlpha"); } void yglTarrayEmit(long do_alpha, long ntri, float *xyz, float *colr, long cpervrt) { long i, base, colrsiz; float oldRGBA[4]= {-1.0, -1.0, -1.0, 1.0}; float ambi[]= {1.0f, 1.0f, 1.0f, 1.0f}; float def_ambi[]= {0.2f, 0.2f, 0.2f, 1.0f}; /* draw an array of triangles */ if(ntri <= 0) return; /* this creates diffuse light not connected to any light */ glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambi); /* turn off all light associated with the light source */ glDisable(GL_LIGHT0); if(do_alpha) { if(!alpha_pass) return; glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); colrsiz= 4; } else { if(alpha_pass) return; glDisable(GL_BLEND); colrsiz= 3; } base= 0; glBegin(GL_TRIANGLES); if(do_alpha) { if(cpervrt) { for(i= 0; i < ntri; i++) { glColor4fv(colr); colr += colrsiz; glVertex3fv(xyz+base); glColor4fv(colr); colr += colrsiz; glVertex3fv(xyz+base+3); glColor4fv(colr); colr += colrsiz; glVertex3fv(xyz+base+6); base += 9; } } else { for(i= 0; i < ntri; i++) { if(colr[0] != oldRGBA[0] || colr[1] != oldRGBA[1] || colr[2] != oldRGBA[2] || colr[3] != oldRGBA[3]) { oldRGBA[0]= colr[0]; oldRGBA[1]= colr[1]; oldRGBA[2]= colr[2]; oldRGBA[3]= colr[3]; glColor4fv(oldRGBA); } colr += colrsiz; /* NOTE: It makes no difference in local performance if the coords are converted to floats before being stored in the display list */ glVertex3fv(xyz+base); glVertex3fv(xyz+base+3); glVertex3fv(xyz+base+6); base += 9; } } } else { if(cpervrt) { /* no alpha component */ for(i= 0; i < ntri; i++) { glColor3fv(colr); colr += colrsiz; glVertex3fv(xyz+base); glColor3fv(colr); colr += colrsiz; glVertex3fv(xyz+base+3); glColor3fv(colr); colr += colrsiz; glVertex3fv(xyz+base+6); base += 9; } } else { /* no alpha component */ for(i= 0; i < ntri; i++) { if(colr[0] != oldRGBA[0] || colr[1] != oldRGBA[1] || colr[2] != oldRGBA[2]) { oldRGBA[0]= colr[0]; oldRGBA[1]= colr[1]; oldRGBA[2]= colr[2]; glColor3fv(oldRGBA); } colr += colrsiz; /* NOTE: It makes no difference in local performance if the coords are converted to floats before being stored in the display list */ glVertex3fv(xyz+base); glVertex3fv(xyz+base+3); glVertex3fv(xyz+base+6); base += 9; } } } glEnd(); /* turn off diffuse light not connected to any light source */ glLightModelfv(GL_LIGHT_MODEL_AMBIENT, def_ambi); glEnable(GL_LIGHT0); if(do_alpha) { glDisable(GL_BLEND); } CHEK_ERROR("yglTarrayEmit"); } #undef USE_ELEMENTS #undef TVDBG #undef TVDBG_BASE #ifndef USE_ELEMENTS void yglTvarray(long do_alpha, long cpervrt, long ntri, unsigned int *ptndx, float *xyz, float *norm, float *colr) { long i, ndx; #ifdef TVDBG_BASE long ndmin=2000000000, ndmax=0; double nrmin=1.0e150, nrmax=-1.0e150, ntmp; double xmin=1.0e150, xmax=-1.0e150; puts("--- entering yglTvarray"); #endif if(do_alpha && !alpha_pass) return; if(!do_alpha && alpha_pass) return; yglUpdateProperties(); #ifdef TVDBG_BASE printf("Expanding arrays\nxyz pointer is %x, norm pointer is %x, colr pointer is %x\n", xyz, norm, colr); #endif /* NOTE: there either must be a color per vertex or a single color for all triangles. There is NO support for a color per triangle. NOTE: for each enabled "array", a corresponding data vector must be defined and have data filled in before a call to glDrawArrays, glDrawElements, etc. because that call will use data from each enabled array. */ if(!cpervrt) { if(do_alpha) { #ifdef TVDBG_BASE printf("alpha, single color\n"); #endif glColor4fv(colr); } else { #ifdef TVDBG_BASE printf("NO alpha, single color\n"); #endif glColor3fv(colr); } glBegin(GL_TRIANGLES); for(i= 0; i < 3*ntri; i++) { glNormal3fv(norm+3*ptndx[i]); glVertex3fv(xyz+3*ptndx[i]); } glEnd(); } else { if(do_alpha) { #ifdef TVDBG_BASE printf("alpha, color per vertex\n"); for(i= 0; i < 3*ntri; i++) { ndx= ptndx[i]; if(xyz[3*ndx] != xyz[3*ndx]) printf("xyz is a NAN for i=%d\n", i); if(xyz[3*ndx+1] != xyz[3*ndx+1]) printf("xyz is a NAN for i=%d\n", i); if(xyz[3*ndx+2] != xyz[3*ndx+2]) printf("xyz is a NAN for i=%d\n", i); if(norm[3*ndx] != norm[3*ndx]) printf("norm is a NAN for i=%d\n", i); if(norm[3*ndx+1] != norm[3*ndx+1]) printf("norm is a NAN for i=%d\n", i); if(norm[3*ndx+2] != norm[3*ndx+2]) printf("norm is a NAN for i=%d\n", i); if(colr[4*ndx] != colr[4*ndx]) printf("colr is a NAN for i=%d\n", i); if(colr[4*ndx+1] != colr[4*ndx+1]) printf("colr is a NAN for i=%d\n", i); if(colr[4*ndx+2] != colr[4*ndx+2]) printf("colr is a NAN for i=%d\n", i); if(colr[4*ndx+3] != colr[4*ndx+3]) printf("colr is a NAN for i=%d\n", i); if(xyz[3*ndx]*xyz[3*ndx] > 1.0e30) printf("xyz is too big for i=%d\n", i); if(xyz[3*ndx+1]*xyz[3*ndx+1] > 1.0e30) printf("xyz is too big for i=%d\n", i); if(xyz[3*ndx+2]*xyz[3*ndx+2] > 1.0e30) printf("xyz is too big for i=%d\n", i); if(colr[4*ndx]*colr[4*ndx] > 1.0e30) printf("colr is too big for i=%d\n", i); if(colr[4*ndx+1]*colr[4*ndx+1] > 1.0e30) printf("colr is too big for i=%d\n", i); if(colr[4*ndx+2]*colr[4*ndx+2] > 1.0e30) printf("colr is too big for i=%d\n", i); if(colr[4*ndx+3]*colr[4*ndx+3] > 1.0e30) printf("colr is too big for i=%d\n", i); nrmin= norm[3*ndx]*norm[3*ndx] + norm[3*ndx+1]*norm[3*ndx+1] + norm[3*ndx+2]*norm[3*ndx+2]; if(nrmin > 1.0e3) printf("norm is too big for i=%d\n", i); if(nrmin < 1.0e-3) printf("norm is too small for i=%d\n", i); } #endif glBegin(GL_TRIANGLES); for(i= 0; i < 3*ntri; i++) { ndx= ptndx[i]; #ifdef TVDBG if(ndx < ndmin) ndmin= ndx; if(ndx > ndmax) ndmax= ndx; if(xyz[3*ndx] < xmin) xmin= xyz[3*ndx]; if(xyz[3*ndx] > xmax) xmax= xyz[3*ndx]; if(xyz[3*ndx+1] < xmin) xmin= xyz[3*ndx+1]; if(xyz[3*ndx+1] > xmax) xmax= xyz[3*ndx+1]; if(xyz[3*ndx+2] < xmin) xmin= xyz[3*ndx+2]; if(xyz[3*ndx+2] > xmax) xmax= xyz[3*ndx+2]; ntmp= norm[3*ndx]*norm[3*ndx]+norm[3*ndx+1]*norm[3*ndx+1]+norm[3*ndx+2]*norm[3*ndx+2]; if(ntmp < nrmin) nrmin= ntmp; if(ntmp > nrmax) nrmax= ntmp; #endif glColor4fv(colr+4*ndx); glNormal3fv(norm+3*ndx); glVertex3fv(xyz+3*ndx); } glEnd(); #ifdef TVDBG printf("minimum index is %ld and max is %ld\n", ndmin, ndmax); printf("minimum x is %e and max is %e\n", xmin, xmax); printf("minimum norm is %e and max is %e\n", nrmin, nrmax); #endif } else { #ifdef TVDBG_BASE printf("NO alpha, color per vertex\n"); for(i= 0; i < 3*ntri; i++) { ndx= ptndx[i]; if(xyz[3*ndx] != xyz[3*ndx]) printf("xyz is a NAN for i=%d\n", i); if(xyz[3*ndx+1] != xyz[3*ndx+1]) printf("xyz is a NAN for i=%d\n", i); if(xyz[3*ndx+2] != xyz[3*ndx+2]) printf("xyz is a NAN for i=%d\n", i); if(norm[3*ndx] != norm[3*ndx]) printf("norm is a NAN for i=%d\n", i); if(norm[3*ndx+1] != norm[3*ndx+1]) printf("norm is a NAN for i=%d\n", i); if(norm[3*ndx+2] != norm[3*ndx+2]) printf("norm is a NAN for i=%d\n", i); if(colr[3*ndx] != colr[3*ndx]) printf("colr is a NAN for i=%d\n", i); if(colr[3*ndx+1] != colr[3*ndx+1]) printf("colr is a NAN for i=%d\n", i); if(colr[3*ndx+2] != colr[3*ndx+2]) printf("colr is a NAN for i=%d\n", i); if(xyz[3*ndx]*xyz[3*ndx] > 1.0e30) printf("xyz is too big for i=%d\n", i); if(xyz[3*ndx+1]*xyz[3*ndx+1] > 1.0e30) printf("xyz is too big for i=%d\n", i); if(xyz[3*ndx+2]*xyz[3*ndx+2] > 1.0e30) printf("xyz is too big for i=%d\n", i); if(norm[3*ndx]*norm[3*ndx] > 1.0e30) printf("norm is too big for i=%d\n", i); if(norm[3*ndx+1]*norm[3*ndx+1] > 1.0e30) printf("norm is too big for i=%d\n", i); if(norm[3*ndx+2]*norm[3*ndx+2] > 1.0e30) printf("norm is too big for i=%d\n", i); if(colr[3*ndx]*colr[3*ndx] > 1.0e30) printf("colr is too big for i=%d\n", i); if(colr[3*ndx+1]*colr[3*ndx+1] > 1.0e30) printf("colr is too big for i=%d\n", i); if(colr[3*ndx+2]*colr[3*ndx+2] > 1.0e30) printf("colr is too big for i=%d\n", i); if(norm[3*ndx]*norm[3*ndx] < 1.0e-3) printf("norm is too small for i=%d\n", i); if(norm[3*ndx+1]*norm[3*ndx+1] < 1.0e-3) printf("norm is too small for i=%d\n", i); if(norm[3*ndx+2]*norm[3*ndx+2] < 1.0e-3) printf("norm is too small for i=%d\n", i); } #endif glBegin(GL_TRIANGLES); for(i= 0; i < 3*ntri; i++) { ndx= ptndx[i]; #ifdef TVDBG if(ndx < ndmin) ndmin= ndx; if(ndx > ndmax) ndmax= ndx; if(xyz[3*ndx] < xmin) xmin= xyz[3*ndx]; if(xyz[3*ndx] > xmax) xmax= xyz[3*ndx]; if(xyz[3*ndx+1] < xmin) xmin= xyz[3*ndx+1]; if(xyz[3*ndx+1] > xmax) xmax= xyz[3*ndx+1]; if(xyz[3*ndx+2] < xmin) xmin= xyz[3*ndx+2]; if(xyz[3*ndx+2] > xmax) xmax= xyz[3*ndx+2]; ntmp= norm[3*ndx]*norm[3*ndx]+norm[3*ndx+1]*norm[3*ndx+1]+norm[3*ndx+2]*norm[3*ndx+2]; if(ntmp < nrmin) nrmin= ntmp; if(ntmp > nrmax) nrmax= ntmp; #endif glColor3fv(colr+3*ndx); glNormal3fv(norm+3*ndx); glVertex3fv(xyz+3*ndx); } glEnd(); #ifdef TVDBG printf("minimum index is %ld and max is %ld\n", ndmin, ndmax); printf("minimum x is %e and max is %e\n", xmin, xmax); printf("minimum norm is %e and max is %e\n", nrmin, nrmax); #endif } } CHEK_ERROR("yglTvarray"); } #else void yglTvarray(long do_alpha, long cpervrt, long ntri, unsigned int *ptndx, float *xyz, float *norm, float *colr) { long i, ndx; #ifdef TVDBG long ndmin=2000000000, ndmax=0; double nrmin=1.0e150, nrmax=-1.0e150, ntmp; double xmin=1.0e150, xmax=-1.0e150; puts("--- entering yglTvarray"); #endif if(do_alpha && !alpha_pass) return; if(!do_alpha && alpha_pass) return; yglUpdateProperties(); #ifdef TVDBG printf("Using EnableClientState\nxyz pointer is %x, norm pointer is %x, colr pointer is %x\n", xyz, norm, colr); #endif /* NOTE: there either must be a color per vertex or a single color for all triangles. There is NO support for a color per triangle. NOTE: for each enabled "array", a corresponding data vector must be defined and have data filled in before a call to glDrawArrays, glDrawElements, etc. because that call will use data from each enabled array. */ glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); glNormalPointer(GL_FLOAT, 0, norm); glVertexPointer(3, GL_FLOAT, 0, xyz); if(cpervrt) { glEnableClientState(GL_COLOR_ARRAY); if(do_alpha) { glColorPointer(4, GL_FLOAT, 0, colr); } else { glColorPointer(3, GL_FLOAT, 0, colr); } } else { if(do_alpha) { glColor4fv(colr); } else { glColor3fv(colr); } } glDrawElements(GL_TRIANGLES, 3*ntri, GL_UNSIGNED_INT, ptndx); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_COLOR_ARRAY); CHEK_ERROR("yglTvarray"); } #endif void yglTivarray(long ntri, unsigned int *ptndx, void *ileave) { /* draw an array of triangles */ if(ntri <= 0) return; if(alpha_pass) return; /* use smooth shading */ yglSetShade(1); yglUpdateProperties(); /* NOTE: This function uses an interleaved vertex array. All of the data must have been stored into the array before this function is called. NOTE: there isn't a mode with 3 color components, normals, and vertices. */ #undef USE_INTERLEAVE #ifdef USE_INTERLEAVE glInterleavedArrays(GL_C4F_N3F_V3F, 0, ileave); glDrawElements(GL_TRIANGLES, 3*ntri, GL_UNSIGNED_INT, ptndx); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_EDGE_FLAG_ARRAY); glDisableClientState(GL_INDEX_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); #else { float *now= (float *)ileave; long i; glBegin(GL_TRIANGLES); for(i= 0; i < ntri; i++) { glColor4fv(now); glNormal3fv(now+4); glVertex3fv(now+7); glColor4fv(now+10); glNormal3fv(now+14); glVertex3fv(now+17); glColor4fv(now+20); glNormal3fv(now+24); glVertex3fv(now+27); now += 30; } glEnd(); } #endif CHEK_ERROR("yglTivarray"); } void yglQarray(long smooth, long nquad, float *xyz, float *norm, float *colr, long edge, long cpervrt) { long i, base; float old_red= -1.0; float old_green= -1.0; float old_blue= -1.0; /* draw an array of quadrilaterals */ if(nquad <= 0) return; if(alpha_pass) return; if(smooth) { /* use smooth shading */ yglSetShade(1); } else { /* use flat shading */ yglSetShade(0); } yglUpdateProperties(); base= 0; glBegin(GL_QUADS); if(cpervrt) { for(i= 0; i < nquad; i++) { if(smooth) { glColor3fv(colr+12*i); glNormal3fv(norm+base); glVertex3fv(xyz+base); glColor3fv(colr+12*i+3); glNormal3fv(norm+base+3); glVertex3fv(xyz+base+3); glColor3fv(colr+12*i+6); glNormal3fv(norm+base+6); glVertex3fv(xyz+base+6); glColor3fv(colr+12*i+9); glNormal3fv(norm+base+9); glVertex3fv(xyz+base+9); } else { glColor3fv(colr+12*i); glNormal3fv(norm+3*i); glVertex3fv(xyz+base); glColor3fv(colr+12*i+3); glVertex3fv(xyz+base+3); glColor3fv(colr+12*i+6); glVertex3fv(xyz+base+6); glColor3fv(colr+12*i+9); glVertex3fv(xyz+base+9); } base += 12; } } else { for(i= 0; i < nquad; i++) { if(colr[3*i] != old_red || colr[3*i+1] != old_green || colr[3*i+2] != old_blue) { glColor3fv(colr+3*i); old_red= colr[3*i]; old_green= colr[3*i+1]; old_blue= colr[3*i+2]; } /* NOTE: It makes no difference in local performance if the coords are converted to floats before being stored in the display list */ if(smooth) { glNormal3fv(norm+base); glVertex3fv(xyz+base); glNormal3fv(norm+base+3); glVertex3fv(xyz+base+3); glNormal3fv(norm+base+6); glVertex3fv(xyz+base+6); glNormal3fv(norm+base+9); glVertex3fv(xyz+base+9); } else { glNormal3fv(norm+3*i); glVertex3fv(xyz+base); glVertex3fv(xyz+base+3); glVertex3fv(xyz+base+6); glVertex3fv(xyz+base+9); } base += 12; } } glEnd(); CHEK_ERROR("yglQarrayNoArr"); } void yglQarrayAlpha(long smooth, long nquad, float *xyz, float *norm, float *colr, long edge, long cpervrt) { long i, base; float old_red= -1.0; float old_green= -1.0; float old_blue= -1.0; float old_alpha= -1.0; long colrsiz= 4; /* draw an array of quadrilaterals */ if(nquad <= 0) return; if(!alpha_pass) return; if(smooth) { /* use smooth shading */ yglSetShade(1); } else { /* use flat shading */ yglSetShade(0); } glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDepthMask(GL_FALSE); yglUpdateProperties(); base= 0; glBegin(GL_QUADS); if(cpervrt) { for(i= 0; i < nquad; i++) { if(smooth) { glColor3fv(colr+12*i); glNormal3fv(norm+base); glVertex3fv(xyz+base); glColor3fv(colr+12*i+3); glNormal3fv(norm+base+3); glVertex3fv(xyz+base+3); glColor3fv(colr+12*i+6); glNormal3fv(norm+base+6); glVertex3fv(xyz+base+6); glColor3fv(colr+12*i+9); glNormal3fv(norm+base+9); glVertex3fv(xyz+base+9); } else { glColor3fv(colr+12*i); glNormal3fv(norm+3*i); glVertex3fv(xyz+base); glColor3fv(colr+12*i+3); glVertex3fv(xyz+base+3); glColor3fv(colr+12*i+6); glVertex3fv(xyz+base+6); glColor3fv(colr+12*i+9); glVertex3fv(xyz+base+9); } base += 12; } } else { for(i= 0; i < nquad; i++) { if(colr[colrsiz*i] != old_red || colr[colrsiz*i+1] != old_green || colr[colrsiz*i+2] != old_blue || colr[colrsiz*i+2] != old_alpha) { glColor3fv(colr+colrsiz*i); old_red= colr[colrsiz*i]; old_green= colr[colrsiz*i+1]; old_blue= colr[colrsiz*i+2]; old_alpha= colr[colrsiz*i+2]; } /* NOTE: It makes no difference in local performance if the coords are converted to floats before being stored in the display list */ if(smooth) { glNormal3fv(norm+base); glVertex3fv(xyz+base); glNormal3fv(norm+base+3); glVertex3fv(xyz+base+3); glNormal3fv(norm+base+6); glVertex3fv(xyz+base+6); glNormal3fv(norm+base+9); glVertex3fv(xyz+base+9); } else { glNormal3fv(norm+3*i); glVertex3fv(xyz+base); glVertex3fv(xyz+base+3); glVertex3fv(xyz+base+6); glVertex3fv(xyz+base+9); } base += 12; } } glEnd(); glDepthMask(GL_TRUE); glDisable(GL_BLEND); CHEK_ERROR("yglQarrayNoArr"); } yorick-gl-1.1+cvs20070922+dfsg.orig/glustub.c0000640000175000017500000000504310313362471020257 0ustar thibautthibaut/* * $Id: glustub.c,v 1.1.1.1 2005/09/18 22:07:53 dhmunro Exp $ * GLU is not always present alongside GL (e.g.- Windows) * here are the three GLU routines yorgl needs * -- these are loosely based on Mesa-4.0.1 sources */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #include "glcode.h" #include static void gs_normalize(GLdouble x[]); void gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez, GLdouble centerx, GLdouble centery, GLdouble centerz, GLdouble upx, GLdouble upy, GLdouble upz) { GLdouble m[16]; GLdouble *x = &m[0]; GLdouble *y = &m[1]; GLdouble *z = &m[2]; z[0] = eyex - centerx; z[4] = eyey - centery; z[8] = eyez - centerz; gs_normalize(z); x[0] = upy*z[8] - upz*z[4]; x[4] = upz*z[0] - upx*z[8]; x[8] = upx*z[4] - upy*z[0]; gs_normalize(x); y[0] = z[4]*x[8] - z[8]*x[4]; y[4] = z[8]*x[0] - z[0]*x[8]; y[8] = z[0]*x[4] - z[4]*x[0]; gs_normalize(y); m[3] = m[7] = m[11] = m[12] = m[13] = m[14] = 0.0; m[15] = 1.0; glMultMatrixd(m); glTranslated(-eyex, -eyey, -eyez); } static void gs_normalize(GLdouble x[]) { double len = x[0]*x[0] + x[4]*x[4] + x[8]*x[8]; if (len) { len = 1./sqrt(len); x[0] *= len; x[4] *= len; x[8] *= len; } } void gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble near_, GLdouble far_) { GLdouble m[16], rdz; fovy = tan(fovy*3.14159265358979324/360.0); rdz = 1. / (far_ - near_); m[0] = 1. / (fovy*aspect); m[1] = m[2] = m[3] = m[4] = 0.0; m[5] = 1. / fovy; m[6] = m[7] = m[8] = m[9] = 0.0; m[10] = -(far_ + near_) * rdz; m[11] = -1.0; m[12] = m[13] = 0.0; m[14] = -2.0 * far_ * near_ * rdz; m[15] = 0.0; glMultMatrixd(m); } const GLubyte * gluErrorString(GLenum code) { if (code == GL_NO_ERROR) return (GLubyte *) "no error"; else if (code == GL_INVALID_ENUM) return (GLubyte *) "GLenum argument out of range"; else if (code == GL_INVALID_VALUE) return (GLubyte *) "numeric argument out of range"; else if (code == GL_INVALID_OPERATION) return (GLubyte *) "operation illegal in current state"; else if (code == GL_STACK_OVERFLOW) return (GLubyte *) "command would cause a stack overflow"; else if (code == GL_STACK_UNDERFLOW) return (GLubyte *) "command would cause a stack underflow"; else if (code == GL_OUT_OF_MEMORY) return (GLubyte *) "not enough memory to execute command"; else return 0; } yorick-gl-1.1+cvs20070922+dfsg.orig/configure0000750000175000017500000001476110313362503020337 0ustar thibautthibaut#!/bin/sh # $Id: configure,v 1.1.1.1 2005/09/18 22:08:03 dhmunro Exp $ debug=no have_gl=no skip_gl=no distclean=no yorick=yorick prefix= glinc= gllib= if test "$#" -gt 0; then for opt in "$@"; do case "$opt" in --yorick=*) yorick=`echo $opt | sed -e s/--yorick=//` ;; --prefix=*) prefix=`echo $opt | sed -e s/--prefix=//` ;; --glinc=*) glinc=`echo $opt | sed -e s/--glinc//` ;; --gllib=*) gllib=`echo $opt | sed -e s/--gllib=//` ;; --no-opengl) skip_gl=yes ;; --distclean) distclean=yes ;; --debug) debug=yes ;; *) echo configure: unrecognized option echo options: echo '--yorick=/path/to/yorick' echo '--prefix=/path/to/opengl/include_and_lib_dirs' echo '--glinc=/path/to/opengl/headers (for -I)' echo '--gllib=/path/to/opengl/libs (for -L)' echo '--no-opengl (skip OpenGL, build yiso3d only)' exit 1 ;; esac done fi if test -n "$prefix"; then if test -z "$glinc"; then glinc="$prefix/include"; fi if test -z "$gllib"; then gllib="$prefix/lib"; fi fi rm -f cfg* ycode.* yinit.* ywrap.* rm -f core a.out *.o *.a *.so *.sl *.dylib *.dll *~ '#'* rm -f yorgl Makegl if test $distclean = yes; then rm -f Makefile.tmp mv Makefile Makefile.tmp sed Makefile -e 's/^Y_MAKEDIR=.*/Y_MAKEDIR=/' -e 's/^Y_EXE=.*/Y_EXE=/' -e 's/^Y_EXE_PKGS=.*/Y_EXE_PKGS=/' -e 's/^Y_EXE_HOME=.*/Y_EXE_HOME=/' -e 's/^Y_EXE_SITE=.*/Y_EXE_SITE=/' rm -f Makefile.tmp exit 0 fi echo "" echo " ============= begin OpenGL for GLX configuration ==============" echo "" # update Makefile to point to the currect yorick "$yorick" -batch make.i # read assorted build flags from Y_HOME/Make.cfg # Y_MAKEDIR=`grep '^Y_MAKEDIR=' ./Makefile | sed -e s/Y_MAKEDIR=//` # try to handle escaped blanks in Y_MAKEDIR Y_MAKEDIR=`echo $Y_MAKEDIR | sed -e 's/\\\\ / /g'` make_cfg="$Y_MAKEDIR/Make.cfg" CC=`grep '^CC=' "$make_cfg" | sed -e s/CC=//` CFLAGS=`grep '^Y_CFLAGS=' "$make_cfg" | sed -e s/Y_CFLAGS=//` LDFLAGS=`grep '^Y_LDFLAGS=' "$make_cfg" | sed -e s/Y_LDFLAGS=//` MATHLIB=`grep '^MATHLIB=' "$make_cfg" | sed -e s/MATHLIB=//` xinc=`grep '^XINC=' "$make_cfg" | sed -e s/XINC=//` xlib=`grep '^XLIB=' "$make_cfg" | sed -e s/XLIB=//` OGLXW=`grep '^PLAY_DIRS=.*win' "$make_cfg"` if test -n "$OGLXW"; then OGLXW=oglw.o glibs="-lopengl32 -lgdi32" gincs= have_gl=yes skip_gl=yes else OGLXW=oglx.o fi # search for a usable OpenGL gmesapix= if test $skip_gl != yes; then gllist=" \ /usr/X11R6/include \ /usr/local/include" cat >cfg.c < #include #ifndef USE_MESA_PIXMAPS # undef glXCreateGLXPixmapMESA # define glXCreateGLXPixmapMESA(d, v, p, c) glXCreateGLXPixmap(d, v, p) #endif static int attr[] = { GLX_RGBA, GLX_DOUBLEBUFFER, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, None }; int main(int argc, char *argv[]) { Display *dpy = XOpenDisplay("nosuchserver:0.0"); XVisualInfo *vi = glXChooseVisual(dpy, DefaultScreen(dpy), attr); GLXContext cx = glXCreateContext(dpy, vi, 0, GL_TRUE); Window win = XCreateSimpleWindow(dpy, RootWindow(dpy, vi->screen), 0,0, 100,100, 4, 0, 0); Drawable d = glXCreateGLXPixmapMESA(dpy, vi, win, DefaultColormap(dpy, vi->screen)); glXDestroyGLXPixmap(dpy, d); glXMakeCurrent(dpy, win, cx); glClearColor(1,1,0,1); glClear(GL_COLOR_BUFFER_BIT); glFlush(); XCloseDisplay(dpy); return 0; } EOF xfound=no if $CC $CFLAGS $glinc $xinc -c cfg.c >cfg.1a 2>&1; then xfound=yes else for d in $gllist; do if test -r $d/GL/glx.h; then glinc=-I$d if $CC $CFLAGS $glinc $xinc -c cfg.c >cfg.1b 2>&1; then xfound=yes gllib=`echo -L$d | sed s/include/lib/` if test $debug = no; then rm -f cfg.1a; fi fi break fi done fi if test -z "$xinc"; then gincs="$glinc" else gincs="$glinc $xinc" fi if test $xfound = yes; then args="$CFLAGS $gincs $LDFLAGS -o cfg cfg.c" xlibs="$xlib -lXext -lX11" xlibm="$xlibs $MATHLIB" for gll in -lGL -lMesaGL; do glibs="$xlib $gll -lXext -lX11" if $CC $args $glibs $MATHLIB >cfg.1c 2>&1; then xfound=both elif test -n "$gllib" && \ $CC $args $gllib $gll $xlibm >cfg.1c 2>&1; then glibs="$gllib $gll $xlibs" xfound=both else glibs="$xlib -lX11" gllist=`echo $gllist | sed s/include/lib/g` for d in $gllist; do xall=`echo $d/libX11*` if test "$xall" != $d/'libX11*'; then gllib=-L$d if $CC $args $gllib $gll $xlibm >cfg.1d 2>&1; then glibs="$gllib $gll $xlibs" xfound=both if test $debug = no; then rm -f cfg.1c; fi fi break fi done fi if test $xfound = both; then break fi done if test $xfound = both; then have_gl=yes echo "found OpenGL, GL headers and GL+GLX libraries" echo " - using GL+X11 header switch ${gincs:-[none]}" echo " - using GL+X11 loader switch ${glibs:-[none]}" if $CC -DUSE_MESA_PIXMAPS $args $glibs $MATHLIB >/dev/null 2>&1; then gmesapix=-DUSE_MESA_PIXMAPS echo " - using glXCreateGLXPixmapMESA" fi fi fi if test $have_gl != yes; then echo "" echo "***********WARNING*********** GLX not found" echo "" fi rm -f cfg cfg.c cfg.o for f in cfg.[0-9]*; do if grep ... $f >/dev/null 2>&1; then # or use test -s $f ? echo "WARNING - check compiler message in $f" else # remove empty files rm -f $f fi done fi if test $have_gl = yes; then PKG_I='$(YISO_PKG_I) $(YGL_PKG_I)' OBJS='$(YISO_OBJS) $(YGL_OBJS)' PKG_DEPLIBS="$glibs" PKG_CFLAGS="$gincs" PKG_I_START="yiso3d.i yorgl.i" PKG_I_EXTRA='$(YISO_I) $(YGL_I)' else PKG_I='$(YISO_PKG_I)' OBJS='$(YISO_OBJS)' PKG_DEPLIBS= PKG_CFLAGS= PKG_I_START=yiso3d.i PKG_I_EXTRA='$(YISO_I)' fi curdate=`date` cursystem=`uname -a` cat >Makegl < /* #include "ydata.h" */ static int t_octant; static long *t_sizes; static long *t_start; static long *t_chunk; static double *t_deltas; static double *t_origin; static double *t_point; static double *t_normal; static double *t_xyz; static TriArrayGrp *t_triangles; #ifdef OLD_ISO_STUFF static OctSTree *t_tree; static long t_maxdepth; #endif static long *t_trsiz; static long *t_offsets; static OctSpan *t_ranges; static double *t_var2; #define DO_STATS #ifdef DO_STATS extern long numscan, numcross; #endif #ifdef OLD_ISO_STUFF static long edges[12][2] = { {0,1}, {1,2}, {2,3}, {3,0}, {4,5}, {5,6}, {6,7}, {7,4}, {0,4}, {1,5}, {3,7}, {2,6}}; static int CASE_MASK[8] = {1,2,4,8,16,32,64,128}; #endif int ycMakeSliceTreeCrv(double *xyz, OctSTree *tree) { long maxdepth= tree->maxdepth; long *trsiz= tree->trsiz; long *offsets= tree->offsets; OctSpan *ranges= tree->ranges; long i; OctSpan *oldr, *newr; /* This function builds an octree from the input data values. The caller has pre-allocated enough space for the tree. The caller must free the storage. tree->size is the number of points in each direction in the whole array. tree->chunk is the number of points in this chunk (one more than the number of cells). tree->start is the point in the larger grid where this chunk starts. tree->trsiz contains the number of "cells" in the various levels of the octree. The first three elements are the same as chunk. */ /* prepare the case table for the iso-surfaces, if not already done */ if(!have_iso_cases) ycPrepIsoTet(); /* build an octree containing the data range for sub-blocks of the input array */ firstSblk(tree->start, tree->size, trsiz, xyz, ranges); for(i= 1; i < maxdepth; i++) { /* NOTE: nextblk needs both the size of the tree level it is filling in and the size of the parent level. It also needs both the parent ranges and space to fill in the ranges for this level. */ oldr= ranges+offsets[i-1]; newr= ranges+offsets[i]; nextSblk(trsiz+3*(i-1), oldr, newr); } return 1; } void firstSblk(long *start, long *sizes, long *trsiz, double *xyz, OctSpan *rng) { /* number of vertices in the full array (including guard cells) */ long ngx= sizes[0]; long ngy= sizes[1]; /* starting point of this chunk in the full array */ long stx= start[0]; long sty= start[1]; long stz= start[2]; /* number of "cells" in this chunk (all are real cells) */ long nx= trsiz[0]; long ny= trsiz[1]; long nz= trsiz[2]; long rowsiz= 3*ngx; long plnsiz= 3*ngx*ngy; long i, j, k, base, nbase; double xmin, xmax, ymin, ymax, zmin, zmax, val; /* NOTE: nx, ny, and nz are numbers of cells. The number of vertices is one more. start gives the starting point of this chunk in the larger array. sizes is the number of vertices of the larger array. The range array is the same size as an array of cells (for this chunk). */ /* the following loop is over all cells */ for(k= 0; k < nz; k++) { for(j= 0; j < ny; j++) { for(i= 0; i < nx; i++) { /* base is a point index into the full input array */ base= (i+stx)*3+(j+sty)*rowsiz+(k+stz)*plnsiz; xmin= xmax= xyz[base]; ymin= ymax= xyz[base+1]; zmin= zmax= xyz[base+2]; val= xyz[base+3]; if(val < xmin) xmin= val; if(val > xmax) xmax= val; val= xyz[base+4]; if(val < ymin) ymin= val; if(val > ymax) ymax= val; val= xyz[base+5]; if(val < zmin) zmin= val; if(val > zmax) zmax= val; val= xyz[base+ rowsiz]; if(val < xmin) xmin= val; if(val > xmax) xmax= val; val= xyz[base+1+rowsiz]; if(val < ymin) ymin= val; if(val > ymax) ymax= val; val= xyz[base+2+rowsiz]; if(val < zmin) zmin= val; if(val > zmax) zmax= val; val= xyz[base+3+rowsiz]; if(val < xmin) xmin= val; if(val > xmax) xmax= val; val= xyz[base+4+rowsiz]; if(val < ymin) ymin= val; if(val > ymax) ymax= val; val= xyz[base+5+rowsiz]; if(val < zmin) zmin= val; if(val > zmax) zmax= val; val= xyz[base +plnsiz]; if(val < xmin) xmin= val; if(val > xmax) xmax= val; val= xyz[base+1 +plnsiz]; if(val < ymin) ymin= val; if(val > ymax) ymax= val; val= xyz[base+2 +plnsiz]; if(val < zmin) zmin= val; if(val > zmax) zmax= val; val= xyz[base+3 +plnsiz]; if(val < xmin) xmin= val; if(val > xmax) xmax= val; val= xyz[base+4 +plnsiz]; if(val < ymin) ymin= val; if(val > ymax) ymax= val; val= xyz[base+5 +plnsiz]; if(val < zmin) zmin= val; if(val > zmax) zmax= val; val= xyz[base +rowsiz+plnsiz]; if(val < xmin) xmin= val; if(val > xmax) xmax= val; val= xyz[base+1+rowsiz+plnsiz]; if(val < ymin) ymin= val; if(val > ymax) ymax= val; val= xyz[base+2+rowsiz+plnsiz]; if(val < zmin) zmin= val; if(val > zmax) zmax= val; val= xyz[base+3+rowsiz+plnsiz]; if(val < xmin) xmin= val; if(val > xmax) xmax= val; val= xyz[base+4+rowsiz+plnsiz]; if(val < ymin) ymin= val; if(val > ymax) ymax= val; val= xyz[base+5+rowsiz+plnsiz]; if(val < zmin) zmin= val; if(val > zmax) zmax= val; /* nbase is an index into this chunk of cells */ nbase= i+j*nx+k*nx*ny; rng[nbase].xmin= xmin; rng[nbase].xmax= xmax; rng[nbase].ymin= ymin; rng[nbase].ymax= ymax; rng[nbase].zmin= zmin; rng[nbase].zmax= zmax; } } } } void nextSblk(long *trsiz, OctSpan *oldr, OctSpan *nrng) { long oldnx= trsiz[0]; long oldny= trsiz[1]; long oldnz= trsiz[2]; long newnx= trsiz[3]; long newny= trsiz[4]; long i, j, k, base, nbase; double xmin, xmax, ymin, ymax, zmin, zmax; OctSpan span; /* NOTE: nx, ny, and nz are numbers of cells. The number of vertices is one more. The range array is the same size as an array of cells. */ /* Run through all 2x2x2 groups of cells. NOTE: The loops must check for cases where the block being collapsed isn't a full 2x2x2. */ for(k= 0; k < oldnz-1; k+= 2) { for(j= 0; j < oldny-1; j += 2) { for(i= 0; i < oldnx-1; i += 2) { /* "cell cluster" index for parent level */ base= i+j*oldnx+k*oldnx*oldny; xmin= oldr[base].xmin; xmax= oldr[base].xmax; ymin= oldr[base].ymin; ymax= oldr[base].ymax; zmin= oldr[base].zmin; zmax= oldr[base].zmax; span= oldr[base+1]; if(xmin > span.xmin) xmin= span.xmin; if(xmax < span.xmax) xmax= span.xmax; if(ymin > span.ymin) ymin= span.ymin; if(ymax < span.ymax) ymax= span.ymax; if(zmin > span.zmin) zmin= span.zmin; if(zmax < span.zmax) zmax= span.zmax; span= oldr[base+oldnx]; if(xmin > span.xmin) xmin= span.xmin; if(xmax < span.xmax) xmax= span.xmax; if(ymin > span.ymin) ymin= span.ymin; if(ymax < span.ymax) ymax= span.ymax; if(zmin > span.zmin) zmin= span.zmin; if(zmax < span.zmax) zmax= span.zmax; span= oldr[base+1+oldnx]; if(xmin > span.xmin) xmin= span.xmin; if(xmax < span.xmax) xmax= span.xmax; if(ymin > span.ymin) ymin= span.ymin; if(ymax < span.ymax) ymax= span.ymax; if(zmin > span.zmin) zmin= span.zmin; if(zmax < span.zmax) zmax= span.zmax; span= oldr[base+oldnx*oldny]; if(xmin > span.xmin) xmin= span.xmin; if(xmax < span.xmax) xmax= span.xmax; if(ymin > span.ymin) ymin= span.ymin; if(ymax < span.ymax) ymax= span.ymax; if(zmin > span.zmin) zmin= span.zmin; if(zmax < span.zmax) zmax= span.zmax; span= oldr[base+1+oldnx*oldny]; if(xmin > span.xmin) xmin= span.xmin; if(xmax < span.xmax) xmax= span.xmax; if(ymin > span.ymin) ymin= span.ymin; if(ymax < span.ymax) ymax= span.ymax; if(zmin > span.zmin) zmin= span.zmin; if(zmax < span.zmax) zmax= span.zmax; span= oldr[base+oldnx+oldnx*oldny]; if(xmin > span.xmin) xmin= span.xmin; if(xmax < span.xmax) xmax= span.xmax; if(ymin > span.ymin) ymin= span.ymin; if(ymax < span.ymax) ymax= span.ymax; if(zmin > span.zmin) zmin= span.zmin; if(zmax < span.zmax) zmax= span.zmax; span= oldr[base+1+oldnx+oldnx*oldny]; if(xmin > span.xmin) xmin= span.xmin; if(xmax < span.xmax) xmax= span.xmax; if(ymin > span.ymin) ymin= span.ymin; if(ymax < span.ymax) ymax= span.ymax; if(zmin > span.zmin) zmin= span.zmin; if(zmax < span.zmax) zmax= span.zmax; /* "cell cluster" index for child level */ nbase= i/2+(j/2)*newnx+(k/2)*newnx*newny; nrng[nbase].xmin= xmin; nrng[nbase].xmax= xmax; nrng[nbase].ymin= ymin; nrng[nbase].ymax= ymax; nrng[nbase].zmin= zmin; nrng[nbase].zmax= zmax; } if(oldnx & 1) { i= oldnx-1; base= i+j*oldnx+k*oldnx*oldny; xmin= oldr[base].xmin; xmax= oldr[base].xmax; ymin= oldr[base].ymin; ymax= oldr[base].ymax; zmin= oldr[base].zmin; zmax= oldr[base].zmax; span= oldr[base+oldnx]; if(xmin > span.xmin) xmin= span.xmin; if(xmax < span.xmax) xmax= span.xmax; if(ymin > span.ymin) ymin= span.ymin; if(ymax < span.ymax) ymax= span.ymax; if(zmin > span.zmin) zmin= span.zmin; if(zmax < span.zmax) zmax= span.zmax; span= oldr[base+oldnx*oldny]; if(xmin > span.xmin) xmin= span.xmin; if(xmax < span.xmax) xmax= span.xmax; if(ymin > span.ymin) ymin= span.ymin; if(ymax < span.ymax) ymax= span.ymax; if(zmin > span.zmin) zmin= span.zmin; if(zmax < span.zmax) zmax= span.zmax; span= oldr[base+oldnx+oldnx*oldny]; if(xmin > span.xmin) xmin= span.xmin; if(xmax < span.xmax) xmax= span.xmax; if(ymin > span.ymin) ymin= span.ymin; if(ymax < span.ymax) ymax= span.ymax; if(zmin > span.zmin) zmin= span.zmin; if(zmax < span.zmax) zmax= span.zmax; nbase= i/2+(j/2)*newnx+(k/2)*newnx*newny; nrng[nbase].xmin= xmin; nrng[nbase].xmax= xmax; nrng[nbase].ymin= ymin; nrng[nbase].ymax= ymax; nrng[nbase].zmin= zmin; nrng[nbase].zmax= zmax; } } if(oldny & 1) { j= oldny-1; for(i= 0; i < oldnx-1; i += 2) { base= i+j*oldnx+k*oldnx*oldny; xmin= oldr[base].xmin; xmax= oldr[base].xmax; ymin= oldr[base].ymin; ymax= oldr[base].ymax; zmin= oldr[base].zmin; zmax= oldr[base].zmax; span= oldr[base+1]; if(xmin > span.xmin) xmin= span.xmin; if(xmax < span.xmax) xmax= span.xmax; if(ymin > span.ymin) ymin= span.ymin; if(ymax < span.ymax) ymax= span.ymax; if(zmin > span.zmin) zmin= span.zmin; if(zmax < span.zmax) zmax= span.zmax; span= oldr[base+oldnx*oldny]; if(xmin > span.xmin) xmin= span.xmin; if(xmax < span.xmax) xmax= span.xmax; if(ymin > span.ymin) ymin= span.ymin; if(ymax < span.ymax) ymax= span.ymax; if(zmin > span.zmin) zmin= span.zmin; if(zmax < span.zmax) zmax= span.zmax; span= oldr[base+1+oldnx*oldny]; if(xmin > span.xmin) xmin= span.xmin; if(xmax < span.xmax) xmax= span.xmax; if(ymin > span.ymin) ymin= span.ymin; if(ymax < span.ymax) ymax= span.ymax; if(zmin > span.zmin) zmin= span.zmin; if(zmax < span.zmax) zmax= span.zmax; nbase= i/2+(j/2)*newnx+(k/2)*newnx*newny; nrng[nbase].xmin= xmin; nrng[nbase].xmax= xmax; nrng[nbase].ymin= ymin; nrng[nbase].ymax= ymax; nrng[nbase].zmin= zmin; nrng[nbase].zmax= zmax; } if(oldnx & 1) { i= oldnx-1; base= i+j*oldnx+k*oldnx*oldny; xmin= oldr[base].xmin; xmax= oldr[base].xmax; ymin= oldr[base].ymin; ymax= oldr[base].ymax; zmin= oldr[base].zmin; zmax= oldr[base].zmax; span= oldr[base+oldnx*oldny]; if(xmin > span.xmin) xmin= span.xmin; if(xmax < span.xmax) xmax= span.xmax; if(ymin > span.ymin) ymin= span.ymin; if(ymax < span.ymax) ymax= span.ymax; if(zmin > span.zmin) zmin= span.zmin; if(zmax < span.zmax) zmax= span.zmax; nbase= i/2+(j/2)*newnx+(k/2)*newnx*newny; nrng[nbase].xmin= xmin; nrng[nbase].xmax= xmax; nrng[nbase].ymin= ymin; nrng[nbase].ymax= ymax; nrng[nbase].zmin= zmin; nrng[nbase].zmax= zmax; } } } if(oldnz & 1) { k= oldnz-1; for(j= 0; j < oldny-1; j += 2) { for(i= 0; i < oldnx-1; i += 2) { base= i+j*oldnx+k*oldnx*oldny; xmin= oldr[base].xmin; xmax= oldr[base].xmax; ymin= oldr[base].ymin; ymax= oldr[base].ymax; zmin= oldr[base].zmin; zmax= oldr[base].zmax; span= oldr[base+1]; if(xmin > span.xmin) xmin= span.xmin; if(xmax < span.xmax) xmax= span.xmax; if(ymin > span.ymin) ymin= span.ymin; if(ymax < span.ymax) ymax= span.ymax; if(zmin > span.zmin) zmin= span.zmin; if(zmax < span.zmax) zmax= span.zmax; span= oldr[base+oldnx]; if(xmin > span.xmin) xmin= span.xmin; if(xmax < span.xmax) xmax= span.xmax; if(ymin > span.ymin) ymin= span.ymin; if(ymax < span.ymax) ymax= span.ymax; if(zmin > span.zmin) zmin= span.zmin; if(zmax < span.zmax) zmax= span.zmax; span= oldr[base+1+oldnx]; if(xmin > span.xmin) xmin= span.xmin; if(xmax < span.xmax) xmax= span.xmax; if(ymin > span.ymin) ymin= span.ymin; if(ymax < span.ymax) ymax= span.ymax; if(zmin > span.zmin) zmin= span.zmin; if(zmax < span.zmax) zmax= span.zmax; nbase= i/2+(j/2)*newnx+(k/2)*newnx*newny; nrng[nbase].xmin= xmin; nrng[nbase].xmax= xmax; nrng[nbase].ymin= ymin; nrng[nbase].ymax= ymax; nrng[nbase].zmin= zmin; nrng[nbase].zmax= zmax; } if(oldnx & 1) { i= oldnx-1; base= i+j*oldnx+k*oldnx*oldny; xmin= oldr[base].xmin; xmax= oldr[base].xmax; ymin= oldr[base].ymin; ymax= oldr[base].ymax; zmin= oldr[base].zmin; zmax= oldr[base].zmax; span= oldr[base+oldnx]; if(xmin > span.xmin) xmin= span.xmin; if(xmax < span.xmax) xmax= span.xmax; if(ymin > span.ymin) ymin= span.ymin; if(ymax < span.ymax) ymax= span.ymax; if(zmin > span.zmin) zmin= span.zmin; if(zmax < span.zmax) zmax= span.zmax; nbase= i/2+(j/2)*newnx+(k/2)*newnx*newny; nrng[nbase].xmin= xmin; nrng[nbase].xmax= xmax; nrng[nbase].ymin= ymin; nrng[nbase].ymax= ymax; nrng[nbase].zmin= zmin; nrng[nbase].zmax= zmax; } } if(oldny & 1) { j= oldny-1; for(i= 0; i < oldnx-1; i += 2) { base= i+j*oldnx+k*oldnx*oldny; xmin= oldr[base].xmin; xmax= oldr[base].xmax; ymin= oldr[base].ymin; ymax= oldr[base].ymax; zmin= oldr[base].zmin; zmax= oldr[base].zmax; span= oldr[base+1]; if(xmin > span.xmin) xmin= span.xmin; if(xmax < span.xmax) xmax= span.xmax; if(ymin > span.ymin) ymin= span.ymin; if(ymax < span.ymax) ymax= span.ymax; if(zmin > span.zmin) zmin= span.zmin; if(zmax < span.zmax) zmax= span.zmax; nbase= i/2+(j/2)*newnx+(k/2)*newnx*newny; nrng[nbase].xmin= xmin; nrng[nbase].xmax= xmax; nrng[nbase].ymin= ymin; nrng[nbase].ymax= ymax; nrng[nbase].zmin= zmin; nrng[nbase].zmax= zmax; } if(oldnx & 1) { i= oldnx-1; base= i+j*oldnx+k*oldnx*oldny; nbase= i/2+(j/2)*newnx+(k/2)*newnx*newny; nrng[nbase].xmin= oldr[base].xmin; nrng[nbase].xmax= oldr[base].xmax; nrng[nbase].ymin= oldr[base].ymin; nrng[nbase].ymax= oldr[base].ymax; nrng[nbase].zmin= oldr[base].zmin; nrng[nbase].zmax= oldr[base].zmax; } } } } int ycSliceTreeCrv(double point[3], double normal[3], double *xyz, double *var, TriArrayGrp *triangles, OctSTree *tree) { long depth; /* This function finds the triangles making up a slicing plane using a pre-computed octree. If var2 is non-zero, it will be interpolated to the vertices on the slicing plane. */ t_sizes= tree->size; t_chunk= tree->chunk; t_start= tree->start; t_xyz= xyz; t_var2= var; t_point= point; t_normal= normal; t_triangles= triangles; #ifdef OLD_ISO_STUFF t_tree= tree; t_maxdepth= tree->maxdepth; #endif t_trsiz= tree->trsiz; t_offsets= tree->offsets; t_ranges= tree->ranges; #ifdef DO_STATS numscan= 0; numcross= 0; #endif if(t_chunk[0] < 2 || t_chunk[1] < 2 || t_chunk[2] < 2) { return 0; } /* prepare the case table for the iso-surfaces, if not already done */ if(!have_iso_cases) ycPrepIsoTet(); t_octant= 0; if(t_normal[0] >= 0) t_octant |= 1; if(t_normal[1] >= 0) t_octant |= 2; if(t_normal[2] >= 0) t_octant |= 4; t_triangles->numTri= 0; depth= tree->maxdepth-1; /* depth as a C-style index */ do_SblkCrv(0, 0, 0, depth); if(t_triangles->numTri) return 1; else return 0; } long do_SblkCrv(long i, long j, long k, long depth) { long child_depth, nx, ny, nz, ndx, newi, newj, newk; long ilo, ihi, jlo, jhi, klo, khi; double s0, s1; OctSpan *the_rng; /* Check to see if the slicing plane passes through the chunk of grid between xmin, xmax, ymin, ymax, zmin, zmax. This can be done by testing the two corners that are most nearly along the direction of the plane's normal. Immediately reject sub-blocks that are not cut. Descend sub-blocks that are cut until reaching a leaf. */ #ifdef DO_STATS numscan++; #endif nx= t_trsiz[3*depth]; ny= t_trsiz[3*depth+1]; nz= t_trsiz[3*depth+2]; ndx= i+j*nx+k*nx*ny; the_rng= t_ranges+t_offsets[depth]+ndx; switch(t_octant) { case 0: /* the normal is in the neg-x, neg-y, neg-z quadrant */ s0= (the_rng->xmax-t_point[0])*t_normal[0] +(the_rng->ymax-t_point[1])*t_normal[1] +(the_rng->zmax-t_point[2])*t_normal[2]; s1= (the_rng->xmin-t_point[0])*t_normal[0] +(the_rng->ymin-t_point[1])*t_normal[1] +(the_rng->zmin-t_point[2])*t_normal[2]; break; case 1: /* the normal is in the plus-x, neg-y, neg-z quadrant */ s0= (the_rng->xmin-t_point[0])*t_normal[0] +(the_rng->ymax-t_point[1])*t_normal[1] +(the_rng->zmax-t_point[2])*t_normal[2]; s1= (the_rng->xmax-t_point[0])*t_normal[0] +(the_rng->ymin-t_point[1])*t_normal[1] +(the_rng->zmin-t_point[2])*t_normal[2]; break; case 2: /* the normal is in the neg-x, plus-y, neg-z quadrant */ s0= (the_rng->xmax-t_point[0])*t_normal[0] +(the_rng->ymin-t_point[1])*t_normal[1] +(the_rng->zmax-t_point[2])*t_normal[2]; s1= (the_rng->xmin-t_point[0])*t_normal[0] +(the_rng->ymax-t_point[1])*t_normal[1] +(the_rng->zmin-t_point[2])*t_normal[2]; break; case 3: /* the normal is in the plus-x, plus-y, neg-z quadrant */ s0= (the_rng->xmin-t_point[0])*t_normal[0] +(the_rng->ymin-t_point[1])*t_normal[1] +(the_rng->zmax-t_point[2])*t_normal[2]; s1= (the_rng->xmax-t_point[0])*t_normal[0] +(the_rng->ymax-t_point[1])*t_normal[1] +(the_rng->zmin-t_point[2])*t_normal[2]; break; case 4: /* the normal is in the neg-x, neg-y, plus-z quadrant */ s0= (the_rng->xmax-t_point[0])*t_normal[0] +(the_rng->ymax-t_point[1])*t_normal[1] +(the_rng->zmin-t_point[2])*t_normal[2]; s1= (the_rng->xmin-t_point[0])*t_normal[0] +(the_rng->ymin-t_point[1])*t_normal[1] +(the_rng->zmax-t_point[2])*t_normal[2]; break; case 5: /* the normal is in the plus-x, neg-y, plus-z quadrant */ s0= (the_rng->xmin-t_point[0])*t_normal[0] +(the_rng->ymax-t_point[1])*t_normal[1] +(the_rng->zmin-t_point[2])*t_normal[2]; s1= (the_rng->xmax-t_point[0])*t_normal[0] +(the_rng->ymin-t_point[1])*t_normal[1] +(the_rng->zmax-t_point[2])*t_normal[2]; break; case 6: /* the normal is in the neg-x, plus-y, plus-z quadrant */ s0= (the_rng->xmax-t_point[0])*t_normal[0] +(the_rng->ymin-t_point[1])*t_normal[1] +(the_rng->zmin-t_point[2])*t_normal[2]; s1= (the_rng->xmin-t_point[0])*t_normal[0] +(the_rng->ymax-t_point[1])*t_normal[1] +(the_rng->zmax-t_point[2])*t_normal[2]; break; case 7: /* the normal is in the plus-x, plus-y, plus-z quadrant */ s0= (the_rng->xmin-t_point[0])*t_normal[0] +(the_rng->ymin-t_point[1])*t_normal[1] +(the_rng->zmin-t_point[2])*t_normal[2]; s1= (the_rng->xmax-t_point[0])*t_normal[0] +(the_rng->ymax-t_point[1])*t_normal[1] +(the_rng->zmax-t_point[2])*t_normal[2]; break; } /* If the corners are on the same side of the plane, the block is not cut. No need to sub-divide. Treat the case with s0 == 0 a not cut and the case with s1 == 0 as cut. */ if(s0 >= 0.0 || s1 < 0.0) return 0; if(depth == 0) { /* Have reached a leaf of the tree that is cut by the slice plane, so generate triangles. */ grab_StrisCrv(i, j, k); return 1; } /* The slicing plane cuts this block. Recursively call this function for all sub-blocks. */ child_depth= depth-1; /* yorick style depth of the child blocks */ nx= t_trsiz[3*child_depth]; ny= t_trsiz[3*child_depth+1]; nz= t_trsiz[3*child_depth+2]; klo= 2*k; khi= klo+1; if(khi > nz-1) khi= nz-1; jlo= 2*j; jhi= jlo+1; if(jhi > ny-1) jhi= ny-1; ilo= 2*i; ihi= ilo+1; if(ihi > nx-1) ihi= nx-1; for(newk= klo; newk <= khi; newk++) { for(newj= jlo; newj <= jhi; newj++) { for(newi= ilo; newi <= ihi; newi++) { do_SblkCrv(newi, newj, newk, child_depth); } } } return 1; } long grab_StrisCrv(long i, long j, long k) { long nx= t_sizes[0]; long ny= t_sizes[1]; double s[8], vars[8], *var2; int rowsiz, plnsiz, sliceSize; int idxvg, idxcg, idv, ii, index, mask; long numTri, *cellIDs; yPoint3D *xyzverts, pts[8]; cellIDs = t_triangles->cellIDs; xyzverts = t_triangles->xyzverts; var2= t_triangles->var2; numTri= t_triangles->numTri; #ifdef DO_STATS numcross++; #endif /* This cell is (probably) cut by the slicing plane. Generate the proper triangles using MarchingCubes style case tables. */ /* NOTE: on input i,j,k are indices into the chunk that is currently being processed. Convert into indices into the full grid. */ i += t_start[0]; j += t_start[1]; k += t_start[2]; sliceSize = nx*ny; rowsiz= 3*nx; plnsiz= 3*nx*ny; /* idxvg is a vertex index into the global array */ idxvg = 3*(i + j*nx + k*sliceSize); /* compute the distance to the plane at the 8 corners */ s[0] = (t_xyz[idxvg ]-t_point[0])*t_normal[0] +(t_xyz[idxvg+1]-t_point[1])*t_normal[1] +(t_xyz[idxvg+2]-t_point[2])*t_normal[2]; s[1] = (t_xyz[idxvg+3]-t_point[0])*t_normal[0] +(t_xyz[idxvg+4]-t_point[1])*t_normal[1] +(t_xyz[idxvg+5]-t_point[2])*t_normal[2]; s[2] = (t_xyz[idxvg+3+rowsiz]-t_point[0])*t_normal[0] +(t_xyz[idxvg+4+rowsiz]-t_point[1])*t_normal[1] +(t_xyz[idxvg+5+rowsiz]-t_point[2])*t_normal[2]; s[3] = (t_xyz[idxvg +rowsiz]-t_point[0])*t_normal[0] +(t_xyz[idxvg+1+rowsiz]-t_point[1])*t_normal[1] +(t_xyz[idxvg+2+rowsiz]-t_point[2])*t_normal[2]; s[4] = (t_xyz[idxvg +plnsiz]-t_point[0])*t_normal[0] +(t_xyz[idxvg+1 +plnsiz]-t_point[1])*t_normal[1] +(t_xyz[idxvg+2 +plnsiz]-t_point[2])*t_normal[2]; s[5] = (t_xyz[idxvg+3 +plnsiz]-t_point[0])*t_normal[0] +(t_xyz[idxvg+4 +plnsiz]-t_point[1])*t_normal[1] +(t_xyz[idxvg+5 +plnsiz]-t_point[2])*t_normal[2]; s[6] = (t_xyz[idxvg+3+rowsiz+plnsiz]-t_point[0])*t_normal[0] +(t_xyz[idxvg+4+rowsiz+plnsiz]-t_point[1])*t_normal[1] +(t_xyz[idxvg+5+rowsiz+plnsiz]-t_point[2])*t_normal[2]; s[7] = (t_xyz[idxvg+ rowsiz+plnsiz]-t_point[0])*t_normal[0] +(t_xyz[idxvg+1+rowsiz+plnsiz]-t_point[1])*t_normal[1] +(t_xyz[idxvg+2+rowsiz+plnsiz]-t_point[2])*t_normal[2]; /* Build the case table */ for ( ii=0, index = 0, mask= 1; ii < 8; ii++, mask += mask) { if ( s[ii] >= 0.0 ) index |= mask; } #define DEBUG_ISO #ifdef DEBUG_ISO if(index == 0 || index == 255) { /* because the test in the outer loop was against the bounding box, this cell may not be cut. */ return 0; } #endif /* set coordinates for the corners of the cell */ pts[0].x= t_xyz[idxvg ]; pts[0].y= t_xyz[idxvg+1]; pts[0].z= t_xyz[idxvg+2]; pts[1].x= t_xyz[idxvg+3]; pts[1].y= t_xyz[idxvg+4]; pts[1].z= t_xyz[idxvg+5]; pts[2].x= t_xyz[idxvg+3+rowsiz]; pts[2].y= t_xyz[idxvg+4+rowsiz]; pts[2].z= t_xyz[idxvg+5+rowsiz]; pts[3].x= t_xyz[idxvg +rowsiz]; pts[3].y= t_xyz[idxvg+1+rowsiz]; pts[3].z= t_xyz[idxvg+2+rowsiz]; pts[4].x= t_xyz[idxvg +plnsiz]; pts[4].y= t_xyz[idxvg+1 +plnsiz]; pts[4].z= t_xyz[idxvg+2 +plnsiz]; pts[5].x= t_xyz[idxvg+3 +plnsiz]; pts[5].y= t_xyz[idxvg+4 +plnsiz]; pts[5].z= t_xyz[idxvg+5 +plnsiz]; pts[6].x= t_xyz[idxvg+3+rowsiz+plnsiz]; pts[6].y= t_xyz[idxvg+4+rowsiz+plnsiz]; pts[6].z= t_xyz[idxvg+5+rowsiz+plnsiz]; pts[7].x= t_xyz[idxvg+ rowsiz+plnsiz]; pts[7].y= t_xyz[idxvg+1+rowsiz+plnsiz]; pts[7].z= t_xyz[idxvg+2+rowsiz+plnsiz]; /* set variable at corners of cell if provided */ idv = i + j*nx + k*sliceSize; if(t_var2) { vars[0]= t_var2[idv]; vars[1]= t_var2[idv+1]; vars[2]= t_var2[idv+1+nx]; vars[3]= t_var2[idv +nx]; vars[4]= t_var2[idv +sliceSize]; vars[5]= t_var2[idv+1 +sliceSize]; vars[6]= t_var2[idv+1+nx+sliceSize]; vars[7]= t_var2[idv +nx+sliceSize]; } idxcg= i+j*(nx-1)+k*(nx-1)*(ny-1); extract_slicetris_tet(index, idxcg, t_var2, &numTri, s, pts, vars, cellIDs, xyzverts, var2); /* WARNING: caller must be sure triangle array doesn't overflow. */ t_triangles->numTri= numTri; return 0; } int ycSliceTree(long maxdepth, long sizes[3], long chunk[3], long start[3], double deltas[3], double origin[3], double point[3], double normal[3], double *var, TriArrayGrp *triangles) { long depth; long ilo, ihi, jlo, jhi, klo, khi; /* This function draws a slicing plane through a regular orthogonal grid. It uses a binary search for grid chunks that are cut by the plane. No Octree is needed because the grid is completely regular. The first step is to find the octant in which the normal lies. This determines the two corners that extends furthest along the normal, and only those two must be tested to see if the plane cuts a chunk. */ t_sizes= sizes; t_chunk= chunk; t_start= start; t_deltas= deltas; t_origin= origin; t_point= point; t_normal= normal; t_var2= var; t_triangles= triangles; #ifdef OLD_ISO_STUFF t_maxdepth= maxdepth; #endif #ifdef DO_STATS numscan= 0; numcross= 0; #endif if(t_chunk[0] < 2 || t_chunk[1] < 2 || t_chunk[2] < 2) { return 0; } t_octant= 0; if(t_normal[0] >= 0) t_octant |= 1; if(t_normal[1] >= 0) t_octant |= 2; if(t_normal[2] >= 0) t_octant |= 4; t_triangles->numTri= 0; depth= maxdepth-1; /* depth as a C-style index */ /* The initial block includes the whole chunk */ ilo= t_start[0]; ihi= t_start[0]+t_chunk[0]-1; jlo= t_start[1]; jhi= t_start[1]+t_chunk[1]-1; klo= t_start[2]; khi= t_start[2]+t_chunk[2]-1; do_Sblk(ilo, ihi, jlo, jhi, klo, khi, depth); if(t_triangles->numTri) return 1; else return 0; } long do_Sblk(long ilo, long ihi, long jlo, long jhi, long klo, long khi, long depth) { long child_depth, imid, jmid, kmid; double s0, s1, s[8]; double delx= t_deltas[0]; double dely= t_deltas[1]; double delz= t_deltas[2]; double offx= t_origin[0]-t_point[0]; double offy= t_origin[1]-t_point[1]; double offz= t_origin[2]-t_point[2]; /* Check to see if the slicing plane passes through the chunk of grid between ilo and ihi, jlo and jhi, and klo and khi. This can be done by testing at the two corners that are most nearly along the direction of the plane's normal. Immediately reject sub-blocks that are not cut. Descend sub-blocks that are cut until reaching a leaf. */ if(ilo >= ihi || jlo >= jhi || klo >= khi) return 0; #ifdef DO_STATS numscan++; #endif /* NOTE: with a Cartesian grid, intersection of the slice plane and the zone can be checked for by evaluating the distance to the plane at only 2 vertices. s0 is the distance to the "entrance" vertex and s1 is the distance to the "exit" vertex. The plane cuts the "cell cluster" if s0 < 0 and s1 > 0. A simpler test is that s0 and s1 have different signs. */ switch(t_octant) { case 0: /* the normal is in the neg-x, neg-y, neg-z quadrant */ s0= (ihi*delx+offx)*t_normal[0]+(jhi*dely+offy)*t_normal[1] +(khi*delz+offz)*t_normal[2]; s1= (ilo*delx+offx)*t_normal[0]+(jlo*dely+offy)*t_normal[1] +(klo*delz+offz)*t_normal[2]; break; case 1: /* the normal is in the plus-x, neg-y, neg-z quadrant */ s0= (ilo*delx+offx)*t_normal[0]+(jhi*dely+offy)*t_normal[1] +(khi*delz+offz)*t_normal[2]; s1= (ihi*delx+offx)*t_normal[0]+(jlo*dely+offy)*t_normal[1] +(klo*delz+offz)*t_normal[2]; break; case 2: /* the normal is in the neg-x, plus-y, neg-z quadrant */ s0= (ihi*delx+offx)*t_normal[0]+(jlo*dely+offy)*t_normal[1] +(khi*delz+offz)*t_normal[2]; s1= (ilo*delx+offx)*t_normal[0]+(jhi*dely+offy)*t_normal[1] +(klo*delz+offz)*t_normal[2]; break; case 3: /* the normal is in the plus-x, plus-y, neg-z quadrant */ s0= (ilo*delx+offx)*t_normal[0]+(jlo*dely+offy)*t_normal[1] +(khi*delz+offz)*t_normal[2]; s1= (ihi*delx+offx)*t_normal[0]+(jhi*dely+offy)*t_normal[1] +(klo*delz+offz)*t_normal[2]; break; case 4: /* the normal is in the neg-x, neg-y, plus-z quadrant */ s0= (ihi*delx+offx)*t_normal[0]+(jhi*dely+offy)*t_normal[1] +(klo*delz+offz)*t_normal[2]; s1= (ilo*delx+offx)*t_normal[0] +(jlo*dely+offy)*t_normal[1]+(khi*delz+offz)*t_normal[2]; break; case 5: /* the normal is in the plus-x, neg-y, plus-z quadrant */ s0= (ilo*delx+offx)*t_normal[0]+(jhi*dely+offy)*t_normal[1] +(klo*delz+offz)*t_normal[2]; s1= (ihi*delx+offx)*t_normal[0]+(jlo*dely+offy)*t_normal[1] +(khi*delz+offz)*t_normal[2]; break; case 6: /* the normal is in the neg-x, plus-y, plus-z quadrant */ s0= (ihi*delx+offx)*t_normal[0]+(jlo*dely+offy)*t_normal[1] +(klo*delz+offz)*t_normal[2]; s1= (ilo*delx+offx)*t_normal[0]+(jhi*dely+offy)*t_normal[1] +(khi*delz+offz)*t_normal[2]; break; case 7: /* the normal is in the plus-x, plus-y, plus-z quadrant */ s0= (ilo*delx+offx)*t_normal[0]+(jlo*dely+offy)*t_normal[1] +(klo*delz+offz)*t_normal[2]; s1= (ihi*delx+offx)*t_normal[0]+(jhi*dely+offy)*t_normal[1] +(khi*delz+offz)*t_normal[2]; break; } #define DBG_S0_S1 #ifdef DBG_S0_S1 if(s0 > s1) { /* impossible error */ return 0; } #endif /* If the corners are on the same side of the plane, the block is not cut. No need to sub-divide. Treat the case with s0 == 0 as not cut and the case with s1 == 0 as cut. */ if(s0 >= 0.0 || s1 < 0.0) return 0; if(ihi-ilo == 1 && jhi-jlo == 1 && khi-klo == 1) { /* Have reached a leaf of the tree that is cut by the slice plane, so generate triangles. Be sure to do this in exactly the same way as the computation of s0 and s1 above. */ s[0]= (ilo*delx+offx)*t_normal[0]+(jlo*dely+offy)*t_normal[1] +(klo*delz+offz)*t_normal[2]; s[1]= (ihi*delx+offx)*t_normal[0]+(jlo*dely+offy)*t_normal[1] +(klo*delz+offz)*t_normal[2]; s[2]= (ihi*delx+offx)*t_normal[0]+(jhi*dely+offy)*t_normal[1] +(klo*delz+offz)*t_normal[2]; s[3]= (ilo*delx+offx)*t_normal[0]+(jhi*dely+offy)*t_normal[1] +(klo*delz+offz)*t_normal[2]; s[4]= (ilo*delx+offx)*t_normal[0]+(jlo*dely+offy)*t_normal[1] +(khi*delz+offz)*t_normal[2]; s[5]= (ihi*delx+offx)*t_normal[0]+(jlo*dely+offy)*t_normal[1] +(khi*delz+offz)*t_normal[2]; s[6]= (ihi*delx+offx)*t_normal[0]+(jhi*dely+offy)*t_normal[1] +(khi*delz+offz)*t_normal[2]; s[7]= (ilo*delx+offx)*t_normal[0]+(jhi*dely+offy)*t_normal[1] +(khi*delz+offz)*t_normal[2]; grab_Stris(ilo, jlo, klo, s); return 1; } /* The slicing plane cuts this block. Recursively call this function for all sub-blocks. */ child_depth= depth-1; /* yorick style depth of the child blocks */ imid= (ilo+ihi+1)/2; jmid= (jlo+jhi+1)/2; kmid= (klo+khi+1)/2; /* Call do_Sblk with a range of cells to handle. Empty ranges are rejected at the top of do_Sblk. */ do_Sblk(ilo, imid, jlo, jmid, klo, kmid, child_depth); do_Sblk(imid, ihi, jlo, jmid, klo, kmid, child_depth); do_Sblk(ilo, imid, jmid, jhi, klo, kmid, child_depth); do_Sblk(imid, ihi, jmid, jhi, klo, kmid, child_depth); do_Sblk(ilo, imid, jlo, jmid, kmid, khi, child_depth); do_Sblk(imid, ihi, jlo, jmid, kmid, khi, child_depth); do_Sblk(ilo, imid, jmid, jhi, kmid, khi, child_depth); do_Sblk(imid, ihi, jmid, jhi, kmid, khi, child_depth); return 1; } long grab_Stris(long i, long j, long k, double s[8]) { /* nx, ny, nz are the number of vertices in the global array */ long nx= t_sizes[0]; long ny= t_sizes[1]; double dx= t_deltas[0]; double dy= t_deltas[1]; double dz= t_deltas[2]; double x0= t_origin[0]; double y0= t_origin[1]; double z0= t_origin[2]; double vars[8]; int idxcg, idxvg, ii, index, mask; double *var2; long numTri, sliceSize, *cellIDs; yPoint3D *xyzverts, pts[8]; cellIDs = t_triangles->cellIDs; xyzverts = t_triangles->xyzverts; var2= t_triangles->var2; numTri= t_triangles->numTri; #ifdef DO_STATS numcross++; #endif /* This cell is cut by the slicing plane. Generate the proper triangles using MarchingCubes style case tables. */ /* Build the case table */ for ( ii=0, index = 0, mask= 1; ii < 8; ii++, mask += mask) { if ( s[ii] >= 0.0 ) index |= mask; } #define DEBUG_ISO #ifdef DEBUG_ISO if(index == 0 || index == 255) { YError("contouring a zone that should have been rejected"); } #endif /* set coordinates for the corners of the cell */ pts[0].z = z0 + k*dz; pts[0].y = y0 + j*dy; pts[0].x = x0 + i*dx; pts[1].x = pts[0].x + dx; pts[1].y = pts[0].y; pts[1].z = pts[0].z; pts[2].x = pts[0].x + dx; pts[2].y = pts[0].y + dy; pts[2].z = pts[0].z; pts[3].x = pts[0].x; pts[3].y = pts[0].y + dy; pts[3].z = pts[0].z; pts[4].x = pts[0].x; pts[4].y = pts[0].y; pts[4].z = pts[0].z + dz; pts[5].x = pts[0].x + dx; pts[5].y = pts[0].y; pts[5].z = pts[0].z + dz; pts[6].x = pts[0].x + dx; pts[6].y = pts[0].y + dy; pts[6].z = pts[0].z + dz; pts[7].x = pts[0].x; pts[7].y = pts[0].y + dy; pts[7].z = pts[0].z + dz; /* set variable at corners of cell if provided */ sliceSize = nx*ny; idxvg = i + j*nx + k*sliceSize; if(t_var2) { vars[0]= t_var2[idxvg]; vars[1]= t_var2[idxvg+1]; vars[2]= t_var2[idxvg+1+nx]; vars[3]= t_var2[idxvg +nx]; vars[4]= t_var2[idxvg +sliceSize]; vars[5]= t_var2[idxvg+1 +sliceSize]; vars[6]= t_var2[idxvg+1+nx+sliceSize]; vars[7]= t_var2[idxvg +nx+sliceSize]; } idxcg= i+j*(nx-1)+k*(nx-1)*(ny-1); extract_slicetris_tet(index, idxcg, t_var2, &numTri, s, pts, vars, cellIDs, xyzverts, var2); /* WARNING: caller must be sure triangle array doesn't overflow. */ t_triangles->numTri= numTri; return 0; } yorick-gl-1.1+cvs20070922+dfsg.orig/gltexture.c0000640000175000017500000012201510515710063020612 0ustar thibautthibaut/* * $Id: gltexture.c,v 1.3 2006/10/19 14:48:19 dhmunro Exp $ * This file contains functions that use OpenGL texture capabilities. * A significant application is interactive volume visualization * using either 2D or 3D textures (prefereable 3D). */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #include "glcode.h" #include "glfunc.h" #include "glMouse.h" #include "glBasic.h" #include "gl3dtex.h" #include "glcubetex.h" #include "Contour3D.h" #include "pstdlib.h" #include #include #include #ifdef DEBUG_PRINT #include "play.h" #include #endif extern int ycInitCartPcen(long sizes[3], long offsets[6], double deltas[3], double origin[3], double *var, double *var2); extern int ycContourTet_array(long make_strip, long sizes[3], double level, double *var, double *var2, yPoint3D *xyz, yPoint3D *grd, unsigned char *flag, TriArrayGrp *triangles); extern int isExtensionSupported(const char *extension); extern void *LookupFunction(const char *funcName); extern int TexExtSetup(void); static void slice_box(double s, double sbox[8], double *origin, double *len, TriArrayGrp *tris); extern int yglTexExtSetup(void); static void yglGenCubeTex(void); static GLuint texName= 0; static GLuint texName3d= 0; static unsigned char *texImage3d= 0; static TriArrayGrp *tris_tex3d= 0; static float fracx3d, fracy3d, fracz3d; static long nx3d, ny3d, nz3d; static GLuint texNameCube= 0; #define ygl_cubemap_size 64 /* 6 square faces of RGBA texels */ static unsigned char cubeMaps[6][ygl_cubemap_size][ygl_cubemap_size][4]; static GLenum faceTarget[6] = { GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT, GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT }; /* J. F. Blinn and M. E. Newell. Texture and reflection in computer generated images. Communications of the ACM, 19(10):542-547, 1976. */ int yglQueryTexCube(void) { int res; if(glCurrWin3d->hascubetex >= 0) return glCurrWin3d->hascubetex; /* Make sure the OpenGL context is current */ yglMakeCurrent(glCurrWin3d); res = isExtensionSupported("GL_EXT_texture_cube_map"); if(res) { glCurrWin3d->hascubetex= 1; /* has cube-map texture support */ } else { glCurrWin3d->hascubetex= 0; /* not supported */ } return glCurrWin3d->hascubetex; } double yglGetVers3d(void) { /* Return the OpenGL version number. */ char *version; double glver; yglMakeCurrent(glCurrWin3d); version = (char*) glGetString(GL_VERSION); glver= atof(version); return glver; } int yglTexExtSetup(void) { int res; yglMakeCurrent(glCurrWin3d); if(glCurrWin3d->hasTexExt >= 0) return glCurrWin3d->hasTexExt; res = isExtensionSupported("GL_EXT_texture"); res= 1; if(res) { glCurrWin3d->hasTexExt= 1; glCurrWin3d->myglBindTexture3D = (glBindTextureProc) LookupFunction("glBindTexture3DEXT"); } else { glCurrWin3d->hasTexExt= 0; glCurrWin3d->myglBindTexture3D = NULL; } return glCurrWin3d->hasTexExt; } int isExtensionSupported(const char *extension) { /* This function is based on the example in Mark Kilgard's article about openGL extensions. WARNING!!! an OpenGL context must be established before calling this function!!! */ const GLubyte *extensions= NULL; const GLubyte *start; GLubyte *where, *terminator; const GLubyte *errstr; GLenum err; /* Extension names should not have spaces, so return "not supported" if the name is malformed. */ where= (GLubyte *) strchr(extension, ' '); if(where || *extension == '\0') return 0; extensions= glGetString(GL_EXTENSIONS); err= glGetError(); errstr= gluErrorString(err); if(!extensions) return 0; /* Parsing OpenGL extension strings is tricky. handle sub-strings etc. */ start= extensions; for( ; ; ) { where= (GLubyte *) strstr((const char *) start, extension); if(!where) break; terminator= where+strlen(extension); if(where == start || *(where-1) == ' ') { if(*terminator == ' ' || *terminator == '\0') { return 1; } } start= terminator; } return 0; } #define USE_DATA void yglTexcells(long nx, long ny, long nz, double delta[3], unsigned char *data, unsigned char *ctab) { /* The input is a 3D array of characters, two corners, and a table that maps a character to RGBA. */ long i, j, k, n, nnx, nny, nnz, nh, nv, nhs, nvs, indt, dt, dir; float fracx, fracy, fracz; float x0, y0, z0, x1, y1, z1, dx, dy, dz; float x, y, z; double absx, absy, absz; unsigned char *newTexImage, *subImage; #ifdef DO_TEX_TEST GLint format, redSize, greenSize, blueSize, alphaSize; GLint texWidth, texHeight; #endif if(alpha_pass) return; yglPrepTex2d(); /* Textures must be a power of 2 in size. Find the smallest power of 2 that will hold the input array */ n= nx-1; nnx= 1; if(n) { do { nnx *= 2; } while(n= n/2); } fracx= (float)nx/(float)nnx; n= ny-1; nny= 1; if(n) { do { nny *= 2; } while(n= n/2); } fracy= (float)ny/(float)nny; n= nz-1; nnz= 1; if(n) { do { nnz *= 2; } while(n= n/2); } fracz= (float)nz/(float)nnz; /* There are nx by ny by nz cells to be volume rendered. FOR NOW, assume that the cells are aligned with the axes. */ dx= (float) delta[0]; dy= (float) delta[1]; dz= (float) delta[2]; #ifdef USE_DATA /* find the axis most closely matching the viewing direction */ absx= glCurrWin3d->view[0] < 0 ? -glCurrWin3d->view[0] : glCurrWin3d->view[0]; absy= glCurrWin3d->view[1] < 0 ? -glCurrWin3d->view[1] : glCurrWin3d->view[1]; absz= glCurrWin3d->view[2] < 0 ? -glCurrWin3d->view[2] : glCurrWin3d->view[2]; if(absx < absy) { if(absy < absz) { /* the view direction is most nearly along z */ dir= 3; if(glCurrWin3d->view[2] < 0) dir= -3; nh= nnx; nv= nny; nhs= nx; nvs= ny; } else { /* the view direction is most nearly along y */ dir= 2; if(glCurrWin3d->view[1] < 0) dir= -2; nh= nnz; nv= nnx; nhs= nz; nvs= nx; } } else { if(absx < absz) { /* the view direction is most nearly along z */ dir= 3; if(glCurrWin3d->view[2] < 0) dir= -3; nh= nnx; nv= nny; nhs= nx; nvs= ny; } else { /* the view direction is most nearly along x */ dir= 1; if(glCurrWin3d->view[0] < 0) dir= -1; nh= nny; nv= nnz; nhs= ny; nvs= nz; } } #else nh= nnx; nv= nny; #endif newTexImage= (unsigned char *)p_malloc(sizeof(unsigned char)*4*nh*nv); subImage= (unsigned char *)p_malloc(sizeof(unsigned char)*4*nhs*nvs); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, nh, nv, 0, GL_RGBA, GL_UNSIGNED_BYTE, newTexImage); #ifdef DO_TEX_TEST glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA, nnx, nny, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_RED_SIZE, &redSize); glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_GREEN_SIZE, &greenSize); glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_BLUE_SIZE, &blueSize); glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_ALPHA_SIZE, &alphaSize); glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &texWidth); glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &texHeight); #endif glGenTextures(1, &texName); glBindTexture(GL_TEXTURE_2D, texName); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); /* glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); */ glEnable(GL_TEXTURE_2D); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); #ifdef USE_DATA x0= 0.0; x1= x0+(nx-1)*dx; y0= 0.0; y1= y0+(ny-1)*dy; z0= 0.0; z1= z0+(nz-1)*dz; switch(dir) { case 1: /* the view direction is most nearly along x */ x= x0; /* draw planes in back to front order */ for(i= 0; i < nx; i++) { /* load the proper texture plane */ for(k= 0; k < nz; k++) { for(j= 0; j < ny; j++) { indt= 4*(j+k*ny); dt= 4*data[i+j*nx+k*nx*ny]; subImage[indt ]= ctab[dt]; subImage[indt+1]= ctab[dt+1]; subImage[indt+2]= ctab[dt+2]; subImage[indt+3]= ctab[dt+3]; } } /* replace the portion of the texture for which there is data */ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, ny, nz, GL_RGBA, GL_UNSIGNED_BYTE, subImage); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex3f(x, y0, z0); glTexCoord2f(fracy, 0.0f); glVertex3f(x, y1, z0); glTexCoord2f(fracy, fracz); glVertex3f(x, y1, z1); glTexCoord2f(0.0f, fracz); glVertex3f(x, y0, z1); glEnd(); x += dx; } break; case -1: /* the view direction is most nearly along negative x */ x= x1; /* draw planes in back to front order */ for(i= nx-1; i >= 0; i--) { /* load the proper texture plane */ for(k= 0; k < nz; k++) { for(j= 0; j < ny; j++) { indt= 4*(j+k*ny); dt= 4*data[i+j*nx+k*nx*ny]; subImage[indt ]= ctab[dt]; subImage[indt+1]= ctab[dt+1]; subImage[indt+2]= ctab[dt+2]; subImage[indt+3]= ctab[dt+3]; } } /* replace the portion of the texture for which there is data */ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, ny, nz, GL_RGBA, GL_UNSIGNED_BYTE, subImage); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex3f(x, y0, z0); glTexCoord2f(fracy, 0.0f); glVertex3f(x, y1, z0); glTexCoord2f(fracy, fracz); glVertex3f(x, y1, z1); glTexCoord2f(0.0f, fracz); glVertex3f(x, y0, z1); glEnd(); x -= dx; } break; case 2: /* the view direction is most nearly along y */ y= y0; /* draw planes in back to front order */ for(j= 0; j < ny; j++) { /* load the poper texture plane */ for(i= 0; i < nx; i++) { for(k= 0; k < nz; k++) { indt= 4*(k+i*nz); dt= 4*data[i+j*nx+k*nx*ny]; subImage[indt ]= ctab[dt]; subImage[indt+1]= ctab[dt+1]; subImage[indt+2]= ctab[dt+2]; subImage[indt+3]= ctab[dt+3]; } } /* replace the portion of the texture for which there is data */ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, nz, nx, GL_RGBA, GL_UNSIGNED_BYTE, subImage); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex3f(x0, y, z0); glTexCoord2f(0.0f, fracz); glVertex3f(x0, y, z1); glTexCoord2f(fracx, fracz); glVertex3f(x1, y, z1); glTexCoord2f(fracx, 0.0f); glVertex3f(x1, y, z0); glEnd(); y += dy; } break; case -2: /* the view direction is most nearly along negative y */ y= y1; /* draw planes in back to front order */ for(j= ny-1; j >=0; j--) { /* load the poper texture plane */ for(i= 0; i < nx; i++) { for(k= 0; k < nz; k++) { indt= 4*(k+i*nz); dt= 4*data[i+j*nx+k*nx*ny]; subImage[indt ]= ctab[dt]; subImage[indt+1]= ctab[dt+1]; subImage[indt+2]= ctab[dt+2]; subImage[indt+3]= ctab[dt+3]; } } /* replace the portion of the texture for which there is data */ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, nz, nx, GL_RGBA, GL_UNSIGNED_BYTE, subImage); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex3f(x0, y, z0); glTexCoord2f(0.0f, fracz); glVertex3f(x0, y, z1); glTexCoord2f(fracx, fracz); glVertex3f(x1, y, z1); glTexCoord2f(fracx, 0.0f); glVertex3f(x1, y, z0); glEnd(); y -= dy; } break; case 3: /* the view direction is most nearly along z */ z= z0; /* draw planes in back to front order */ for(k= 0; k < nz; k++) { /* load the poper texture plane */ for(j= 0; j < ny; j++) { for(i= 0; i < nx; i++) { indt= 4*(i+j*nx); dt= 4*data[i+j*nx+k*nx*ny]; subImage[indt ]= ctab[dt]; subImage[indt+1]= ctab[dt+1]; subImage[indt+2]= ctab[dt+2]; subImage[indt+3]= ctab[dt+3]; } } /* replace the portion of the texture for which there is data */ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, nx, ny, GL_RGBA, GL_UNSIGNED_BYTE, subImage); glBindTexture(GL_TEXTURE_2D, texName); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex3f(x0, y0, z); glTexCoord2f(0.0f, fracy); glVertex3f(x0, y1, z); glTexCoord2f(fracx, fracy); glVertex3f(x1, y1, z); glTexCoord2f(fracx, 0.0f); glVertex3f(x1, y0, z); glEnd(); z += dz; } break; case -3: /* the view direction is most nearly along negative z */ z= z1; /* draw planes in back to front order */ for(k= nz-1; k >= 0; k--) { /* load the poper texture plane */ for(j= 0; j < ny; j++) { for(i= 0; i < nx; i++) { indt= 4*(i+j*nx); dt= 4*data[i+j*nx+k*nx*ny]; subImage[indt ]= ctab[dt]; subImage[indt+1]= ctab[dt+1]; subImage[indt+2]= ctab[dt+2]; subImage[indt+3]= ctab[dt+3]; } } /* replace the portion of the texture for which there is data */ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, nx, ny, GL_RGBA, GL_UNSIGNED_BYTE, subImage); glBindTexture(GL_TEXTURE_2D, texName); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex3f(x0, y0, z); glTexCoord2f(0.0f, fracy); glVertex3f(x0, y1, z); glTexCoord2f(fracx, fracy); glVertex3f(x1, y1, z); glTexCoord2f(fracx, 0.0f); glVertex3f(x1, y0, z); glEnd(); z -= dz; } break; } #else /* the view direction is most nearly along z */ z= 0.0; y0= 0.0; x0= 0.0; y1= y0+(ny-1)*dy; x1= x0+(nx-1)*dx; /* draw planes in back to front order */ for(k= 0; k < nz; k++) { /* load the poper texture plane */ for(j= 0; j < ny; j++) { for(i= 0; i < nx; i++) { subImage[4*(i+j*nnx)]= (int)((i+j+k)*255.0/((nx-1.0)+(ny-1.0))) %255; subImage[4*(i+j*nnx)+1]= (int)((i+j+k)*255.0/((nx-1.0)+(ny-1.0))+80) %255; subImage[4*(i+j*nnx)+2]= (int)((i+j+k)*255.0/((nx-1.0)+(ny-1.0))+160) %255; subImage[4*(i+j*nnx)+3]= 50; } } /* replace the portion of the texture for which there is data */ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, nnx, nny, GL_RGBA, GL_UNSIGNED_BYTE, subImage); glBindTexture(GL_TEXTURE_2D, texName); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex3f(x0, y0, z); glTexCoord2f(0.0f, fracy); glVertex3f(x0, y1, z); glTexCoord2f(fracx, fracy); glVertex3f(x1, y1, z); glTexCoord2f(fracx, 0.0f); glVertex3f(x1, y0, z); glEnd(); z += dz; } #endif glDeleteTextures(1, &texName); p_free(newTexImage); p_free(subImage); yglEndTex2d(); } void yglTexcell2(long nx, long ny, long nz, double delta[3], unsigned char *tex) { /* The input is a 3D array of RGBA's and a vector of zone sizes. */ long i, j, k, n, nnx, nny, nnz, nh, nv, nhs, nvs, indt, dt, dir; float fracx, fracy, fracz; float x0, y0, z0, x1, y1, z1, dx, dy, dz; float x, y, z; double absx, absy, absz; unsigned char *newTexImage, *subImage; #ifdef DO_TEX_TEST GLint format, redSize, greenSize, blueSize, alphaSize; GLint texWidth, texHeight; #endif if(alpha_pass) return; yglPrepTex2d(); /* Textures must be a power of 2 in size. Find the smallest power of 2 that will hold the input array */ n= nx-1; nnx= 1; if(n) { do { nnx *= 2; } while(n= n/2); } fracx= (float)nx/(float)nnx; n= ny-1; nny= 1; if(n) { do { nny *= 2; } while(n= n/2); } fracy= (float)ny/(float)nny; n= nz-1; nnz= 1; if(n) { do { nnz *= 2; } while(n= n/2); } fracz= (float)nz/(float)nnz; /* There are nx by ny by nz cells to be volume rendered. FOR NOW, assume that the cells are aligned with the axes. */ dx= (float) delta[0]; dy= (float) delta[1]; dz= (float) delta[2]; #ifdef USE_DATA /* find the axis most closely matching the viewing direction */ absx= glCurrWin3d->view[0] < 0 ? -glCurrWin3d->view[0] : glCurrWin3d->view[0]; absy= glCurrWin3d->view[1] < 0 ? -glCurrWin3d->view[1] : glCurrWin3d->view[1]; absz= glCurrWin3d->view[2] < 0 ? -glCurrWin3d->view[2] : glCurrWin3d->view[2]; if(absx < absy) { if(absy < absz) { /* the view direction is most nearly along z */ dir= 3; if(glCurrWin3d->view[2] < 0) dir= -3; nh= nnx; nv= nny; nhs= nx; nvs= ny; } else { /* the view direction is most nearly along y */ dir= 2; if(glCurrWin3d->view[1] < 0) dir= -2; nh= nnz; nv= nnx; nhs= nz; nvs= nx; } } else { if(absx < absz) { /* the view direction is most nearly along z */ dir= 3; if(glCurrWin3d->view[2] < 0) dir= -3; nh= nnx; nv= nny; nhs= nx; nvs= ny; } else { /* the view direction is most nearly along x */ dir= 1; if(glCurrWin3d->view[0] < 0) dir= -1; nh= nny; nv= nnz; nhs= ny; nvs= nz; } } #else nh= nnx; nv= nny; #endif glGenTextures(1, &texName); glBindTexture(GL_TEXTURE_2D, texName); newTexImage= (unsigned char *)p_malloc(sizeof(unsigned char)*4*nh*nv); subImage= (unsigned char *)p_malloc(sizeof(unsigned char)*4*nhs*nvs); { int err; const GLubyte *errstr; err= glGetError(); errstr= gluErrorString(err); err++; } #ifdef DO_TEX_TEST glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA, nnx, nny, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_RED_SIZE, &redSize); glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_GREEN_SIZE, &greenSize); glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_BLUE_SIZE, &blueSize); glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_ALPHA_SIZE, &alphaSize); glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &texWidth); glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &texHeight); #endif glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); /* glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); */ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, nh, nv, 0, GL_RGBA, GL_UNSIGNED_BYTE, newTexImage); glEnable(GL_TEXTURE_2D); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); { int err; const GLubyte *errstr; err= glGetError(); errstr= gluErrorString(err); err++; } #ifdef USE_DATA x0= 0.0; x1= x0+(nx-1)*dx; y0= 0.0; y1= y0+(ny-1)*dy; z0= 0.0; z1= z0+(nz-1)*dz; #ifdef DEBUG_PRINT { char msg[100]; sprintf(msg,"direction is %d\n",dir); p_stderr(msg); } #endif switch(dir) { case 1: /* the view direction is most nearly along x */ x= x0; /* draw planes in back to front order */ for(i= 0; i < nx; i++) { /* load the proper texture plane */ for(k= 0; k < nz; k++) { for(j= 0; j < ny; j++) { indt= 4*(j+k*ny); dt= 4*(i+j*nx+k*nx*ny); subImage[indt ]= tex[dt]; subImage[indt+1]= tex[dt+1]; subImage[indt+2]= tex[dt+2]; subImage[indt+3]= tex[dt+3]; } } /* replace the portion of the texture for which there is data */ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, ny, nz, GL_RGBA, GL_UNSIGNED_BYTE, subImage); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex3f(x, y0, z0); glTexCoord2f(fracy, 0.0f); glVertex3f(x, y1, z0); glTexCoord2f(fracy, fracz); glVertex3f(x, y1, z1); glTexCoord2f(0.0f, fracz); glVertex3f(x, y0, z1); glEnd(); x += dx; } break; case -1: /* the view direction is most nearly along negative x */ x= x1; /* draw planes in back to front order */ for(i= nx-1; i >= 0; i--) { /* load the proper texture plane */ for(k= 0; k < nz; k++) { for(j= 0; j < ny; j++) { indt= 4*(j+k*ny); dt= 4*(i+j*nx+k*nx*ny); subImage[indt ]= tex[dt]; subImage[indt+1]= tex[dt+1]; subImage[indt+2]= tex[dt+2]; subImage[indt+3]= tex[dt+3]; } } /* replace the portion of the texture for which there is data */ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, ny, nz, GL_RGBA, GL_UNSIGNED_BYTE, subImage); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex3f(x, y0, z0); glTexCoord2f(0.0f, fracz); glVertex3f(x, y0, z1); glTexCoord2f(fracy, fracz); glVertex3f(x, y1, z1); glTexCoord2f(fracy, 0.0f); glVertex3f(x, y1, z0); glEnd(); x -= dx; } break; case 2: /* the view direction is most nearly along y */ y= y0; /* draw planes in back to front order */ for(j= 0; j < ny; j++) { /* load the poper texture plane */ for(k= 0; k < nz; k++) { for(i= 0; i < nx; i++) { indt= 4*(i+k*nx); dt= 4*(i+j*nx+k*nx*ny); subImage[indt ]= tex[dt]; subImage[indt+1]= tex[dt+1]; subImage[indt+2]= tex[dt+2]; subImage[indt+3]= tex[dt+3]; } } /* replace the portion of the texture for which there is data */ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, nx, nz, GL_RGBA, GL_UNSIGNED_BYTE, subImage); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex3f(x0, y, z0); glTexCoord2f(0.0f, fracz); glVertex3f(x0, y, z1); glTexCoord2f(fracx, fracz); glVertex3f(x1, y, z1); glTexCoord2f(fracx, 0.0f); glVertex3f(x1, y, z0); glEnd(); y += dy; } break; case -2: /* the view direction is most nearly along negative y */ y= y1; /* draw planes in back to front order */ for(j= ny-1; j >=0; j--) { /* load the poper texture plane */ for(k= 0; k < nz; k++) { for(i= 0; i < nx; i++) { indt= 4*(i+k*nx); dt= 4*(i+j*nx+k*nx*ny); subImage[indt ]= tex[dt]; subImage[indt+1]= tex[dt+1]; subImage[indt+2]= tex[dt+2]; subImage[indt+3]= tex[dt+3]; } } /* replace the portion of the texture for which there is data */ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, nx, nz, GL_RGBA, GL_UNSIGNED_BYTE, subImage); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex3f(x0, y, z0); glTexCoord2f(fracx, 0.0f); glVertex3f(x1, y, z0); glTexCoord2f(fracx, fracz); glVertex3f(x1, y, z1); glTexCoord2f(0.0f, fracz); glVertex3f(x0, y, z1); glEnd(); y -= dy; } break; case 3: /* the view direction is most nearly along z */ z= z0; /* draw planes in back to front order */ for(k= 0; k < nz; k++) { /* load the poper texture plane */ for(j= 0; j < ny; j++) { for(i= 0; i < nx; i++) { indt= 4*(i+j*nx); dt= 4*(i+j*nx+k*nx*ny); subImage[indt ]= tex[dt]; subImage[indt+1]= tex[dt+1]; subImage[indt+2]= tex[dt+2]; subImage[indt+3]= tex[dt+3]; } } glBindTexture(GL_TEXTURE_2D, texName); { int err; const GLubyte *errstr; err= glGetError(); errstr= gluErrorString(err); err++; } /* replace the portion of the texture for which there is data */ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, nx, ny, GL_RGBA, GL_UNSIGNED_BYTE, subImage); { int err; const GLubyte *errstr; err= glGetError(); errstr= gluErrorString(err); err++; } glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex3f(x0, y0, z); glTexCoord2f(fracx, 0.0f); glVertex3f(x1, y0, z); glTexCoord2f(fracx, fracy); glVertex3f(x1, y1, z); glTexCoord2f(0.0f, fracy); glVertex3f(x0, y1, z); glEnd(); z += dz; } break; case -3: /* the view direction is most nearly along negative z */ z= z1; /* draw planes in back to front order */ for(k= nz-1; k >= 0; k--) { /* load the poper texture plane */ for(j= 0; j < ny; j++) { for(i= 0; i < nx; i++) { indt= 4*(i+j*nx); dt= 4*(i+j*nx+k*nx*ny); subImage[indt ]= tex[dt]; subImage[indt+1]= tex[dt+1]; subImage[indt+2]= tex[dt+2]; subImage[indt+3]= tex[dt+3]; } } /* replace the portion of the texture for which there is data */ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, nx, ny, GL_RGBA, GL_UNSIGNED_BYTE, subImage); glBindTexture(GL_TEXTURE_2D, texName); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex3f(x0, y0, z); glTexCoord2f(0.0f, fracy); glVertex3f(x0, y1, z); glTexCoord2f(fracx, fracy); glVertex3f(x1, y1, z); glTexCoord2f(fracx, 0.0f); glVertex3f(x1, y0, z); glEnd(); z -= dz; } break; } #else /* the view direction is most nearly along z */ z= 0.0; y0= 0.0; x0= 0.0; y1= y0+(ny-1)*dy; x1= x0+(nx-1)*dx; /* draw planes in back to front order */ for(k= 0; k < nz; k++) { /* load the poper texture plane */ for(j= 0; j < ny; j++) { for(i= 0; i < nx; i++) { subImage[4*(i+j*nnx)]= (int)((i+j+k)*255.0/((nx-1.0)+(ny-1.0))) %255; subImage[4*(i+j*nnx)+1]= (int)((i+j+k)*255.0/((nx-1.0)+(ny-1.0))+80) %255; subImage[4*(i+j*nnx)+2]= (int)((i+j+k)*255.0/((nx-1.0)+(ny-1.0))+160) %255; subImage[4*(i+j*nnx)+3]= 50; } } /* replace the portion of the texture for which there is data */ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, nnx, nny, GL_RGBA, GL_UNSIGNED_BYTE, subImage); glBindTexture(GL_TEXTURE_2D, texName); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex3f(x0, y0, z); glTexCoord2f(0.0f, fracy); glVertex3f(x0, y1, z); glTexCoord2f(fracx, fracy); glVertex3f(x1, y1, z); glTexCoord2f(fracx, 0.0f); glVertex3f(x1, y0, z); glEnd(); z += dz; } #endif glDeleteTextures(1, &texName); p_free(newTexImage); p_free(subImage); yglEndTex2d(); } void yglPrepCubeTex(void) { /* glDisable(GL_LIGHT0); */ glEnable(GL_TEXTURE_CUBE_MAP_EXT); /* glEnable(GL_BLEND); */ /* glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); */ /* glDisable(GL_LIGHT0); */ glDisable(GL_LIGHTING); glDisable(GL_COLOR_MATERIAL); } void yglEndCubeTex(void) { glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); glDisable(GL_TEXTURE_GEN_R); /* Other texture modes (1D, 2D, or 3D) are overridden by cube maps */ glDisable(GL_TEXTURE_CUBE_MAP_EXT); /* glEnable(GL_LIGHT0); */ /* glDisable(GL_BLEND); */ glEnable(GL_LIGHTING); glEnable(GL_COLOR_MATERIAL); } static void yglGenCubeTex(void) { long i, j, icen, iwid; unsigned char alpha; double wid2; /* These textures will be used for lighting using cube maps. The light is white, brightest at the center of the face, and has a width of iwid texels. It is only on the front and back faces. Lighting is handled by making all texels white and varying the opacity (high in the specular highlight, low elsewhere) */ memset(cubeMaps, 127, 6*ygl_cubemap_size*ygl_cubemap_size*4); icen= ygl_cubemap_size/2; iwid= (long) (ygl_cubemap_size/1.5); wid2= iwid*iwid; for(i= 0; i < ygl_cubemap_size; i++) { for(j= 0; j < ygl_cubemap_size; j++) { alpha= (unsigned char)(255.0*exp( -((i-icen)*(i-icen)+(j-icen)*(j-icen))/wid2 ) ); cubeMaps[4][i][j][3]= alpha; cubeMaps[5][i][j][3]= alpha; } } } void yglLdCubeTex(void) { int i; yglMakeCurrent(glCurrWin3d); if( !yglQueryTexCube() ) return; if(alpha_pass) return; /* generate the cube map textures, if necessary */ if(texNameCube) { glBindTexture(GL_TEXTURE_CUBE_MAP_EXT, texNameCube); } else { yglGenCubeTex(); /* generate the texture data */ glGenTextures(1, &texNameCube); /* make the texture object */ glBindTexture(GL_TEXTURE_CUBE_MAP_EXT, texNameCube); glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_CUBE_MAP_EXT, GL_TEXTURE_MAG_FILTER, GL_NEAREST); for(i= 0; i < 6; i++) { glTexImage2D(faceTarget[i], 0, GL_RGBA8, ygl_cubemap_size, ygl_cubemap_size, 0, GL_RGBA, GL_UNSIGNED_BYTE, &(cubeMaps[i][0][0][0]) ); } } glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_EXT); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_EXT); glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_EXT); glEnable(GL_TEXTURE_CUBE_MAP_EXT); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glEnable(GL_TEXTURE_GEN_R); glEnable(GL_NORMALIZE); /* glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); */ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); } void yglPrepTex2d(void) { glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); /* No hidden surface removal for translucent */ glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_TEXTURE_2D); } void yglEndTex2d(void) { /* 1D textures are not available while 2D textures are enabled */ glDisable(GL_TEXTURE_2D); glDisable(GL_BLEND); glEnable(GL_LIGHTING); glEnable(GL_DEPTH_TEST); /* Hidden surface removal */ } void yglPrepTex3d(void) { glDisable(GL_LIGHTING); /* glDisable(GL_DEPTH_TEST); */ /* No hidden surface removal for translucent */ glDepthMask(GL_FALSE); /* do not update depth buffer, but leave enabled */ glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(glCurrWin3d->myGL_TEXTURE_3D); } void yglEndTex3d(void) { /* 2D textures are not available while 3D textures are enabled */ glDisable(glCurrWin3d->myGL_TEXTURE_3D); glDisable(GL_BLEND); glEnable(GL_LIGHTING); glDepthMask(GL_TRUE); /* resume updates of update depth buffer */ /* glEnable(GL_DEPTH_TEST); */ /* Hidden surface removal */ } /* WARNING: Under Visual C++ 6.0 this function seg faults if optimized. */ #pragma optimize( "", off ) void yglLdTex3d(long nx, long ny, long nz, unsigned char *tex) { /* The input is a 3D array of RGBA's. */ long i, j, k, n, ind, indt, indup, n2x, n2y, n2z, nxh, nyh; long tex_siz; if(alpha_pass) return; if(!yglQueryTex3d(glCurrWin3d)) { YError("This computer does not have 3D textures"); } /* Textures must be a power of 2 in size. Find the smallest power of 2 that will hold the input array. */ n= nx-1; n2x= 1; if(n) { do { n2x *= 2; } while(n= n/2); } fracx3d= (float)nx/(float)n2x; n= ny-1; n2y= 1; if(n) { do { n2y *= 2; } while(n= n/2); } fracy3d= (float)ny/(float)n2y; n= nz-1; n2z= 1; if(n) { do { n2z *= 2; } while(n= n/2); } fracz3d= (float)nz/(float)n2z; if(texImage3d) { /* use the previous array if it was the same size */ if(nx3d != n2x || ny3d != n2y || nz3d != n2z) { p_free(texImage3d); nx3d= n2x; ny3d= n2y; nz3d= n2z; tex_siz= sizeof(unsigned char)*4*nx3d*ny3d*nz3d; texImage3d= (unsigned char *)p_malloc(tex_siz); } } else { /* no existing texture, so make a new one */ nx3d= n2x; ny3d= n2y; nz3d= n2z; tex_siz= sizeof(unsigned char)*4*nx3d*ny3d*nz3d; texImage3d= (unsigned char *)p_malloc(tex_siz); } for(k= 0; k < nz; k++) { for(j= 0; j < ny; j++) { for(i= 0; i < nx; i++) { ind= 4*(i+j*nx+k*nx*ny); indt= 4*(i+j*nx3d+k*nx3d*ny3d); texImage3d[indt]= tex[ind]; texImage3d[indt+1]= tex[ind+1]; texImage3d[indt+2]= tex[ind+2]; texImage3d[indt+3]= tex[ind+3]; } } } /* If linear interpolation of texture values is turned on, it will interpolate off the edge of the valid texture data unless the input array is a power of two in size. Deal with this by duplicating boundary values. */ if(nx < nx3d) { i= nx-1; for(k= 0; k < nz; k++) { for(j= 0; j < ny; j++) { indt= 4*(i+j*nx3d+k*nx3d*ny3d); indup= indt+4; texImage3d[indup]= texImage3d[indt]; texImage3d[indup+1]= texImage3d[indt+1]; texImage3d[indup+2]= texImage3d[indt+2]; texImage3d[indup+3]= texImage3d[indt+3]; } } nxh= nx+1; } else { nxh= nx; } if(ny < ny3d) { j= ny-1; for(k= 0; k < nz; k++) { for(i= 0; i < nxh; i++) { indt= 4*(i+j*nx3d+k*nx3d*ny3d); indup= indt+4*nx3d; texImage3d[indup]= texImage3d[indt]; texImage3d[indup+1]= texImage3d[indt+1]; texImage3d[indup+2]= texImage3d[indt+2]; texImage3d[indup+3]= texImage3d[indt+3]; } } nyh= ny+1; } else { nyh= ny; } if(nz < nz3d) { k= nz-1; for(j= 0; j < nyh; j++) { for(i= 0; i < nxh; i++) { indt= 4*(i+j*nx3d+k*nx3d*ny3d); indup= indt+4*nx3d*ny3d; texImage3d[indup]= texImage3d[indt]; texImage3d[indup+1]= texImage3d[indt+1]; texImage3d[indup+2]= texImage3d[indt+2]; texImage3d[indup+3]= texImage3d[indt+3]; } } } yglMakeCurrent(glCurrWin3d); if(!texName3d) { glGenTextures(1, &texName3d); } glBindTexture(glCurrWin3d->myGL_TEXTURE_3D, texName3d); glTexParameteri(glCurrWin3d->myGL_TEXTURE_3D, GL_TEXTURE_WRAP_R_EXT, GL_CLAMP); glTexParameteri(glCurrWin3d->myGL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(glCurrWin3d->myGL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri(glCurrWin3d->myGL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); /* glTexParameteri(glCurrWin3d->myGL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); */ glTexParameteri(glCurrWin3d->myGL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); myglTexImage3D(glCurrWin3d->myGL_TEXTURE_3D, 0, GL_RGBA, nx3d, ny3d, nz3d, 0, GL_RGBA, GL_UNSIGNED_BYTE, texImage3d); #undef DO_TEX3_TEST #ifdef DO_TEX3_TEST { GLint redSize, greenSize, blueSize, alphaSize; GLint texWidth, texHeight, texDepth; myglTexImage3D(myGL_PROXY_TEXTURE_3D, 0, GL_RGBA, nx3d, ny3d, nz3d, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glGetTexLevelParameteriv(myGL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_RED_SIZE, &redSize); glGetTexLevelParameteriv(myGL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_GREEN_SIZE, &greenSize); glGetTexLevelParameteriv(myGL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_BLUE_SIZE, &blueSize); glGetTexLevelParameteriv(myGL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_ALPHA_SIZE, &alphaSize); glGetTexLevelParameteriv(myGL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &texWidth); glGetTexLevelParameteriv(myGL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_HEIGHT, &texHeight); glGetTexLevelParameteriv(myGL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_DEPTH_EXT, &texDepth); if(texDepth <= 0) { /* to provide a space for a breakpoint inside scope */ texDepth= 1; } } #endif glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); } #pragma optimize( "", on ) void yglTexPoly(long nvert, float *verts, float *texverts) { long i; if(alpha_pass) return; /* Draw a 3Dtextured polygon. */ glBindTexture(glCurrWin3d->myGL_TEXTURE_3D, texName3d); glBegin(GL_POLYGON); for(i= 0; i < nvert; i++) { glTexCoord3f(texverts[3*i], texverts[3*i+1], texverts[3*i+2]); glVertex3f(verts[3*i], verts[3*i+1], verts[3*i+2]); } glEnd(); } void yglTexTris(long ntri, float *verts, float *texverts) { long i, nd; if(alpha_pass) return; /* Draw an array of 3Dtextured triangles. */ glBindTexture(glCurrWin3d->myGL_TEXTURE_3D, texName3d); glBegin(GL_TRIANGLES); for(i= 0; i < ntri; i++) { nd= 9*i; /* 3 coords per vertex, 3 vertices per tri */ glTexCoord3fv(texverts+nd); glVertex3fv(verts+nd); glTexCoord3fv(texverts+nd+3); glVertex3fv(verts+nd+3); glTexCoord3fv(texverts+nd+6); glVertex3fv(verts+nd+6); } glEnd(); } void slice_box(double s, double sbox[8], double *origin, double *len, TriArrayGrp *tris) { long dims[]= {4, 4, 4}; long offsets[]= {0, 0, 0, 2, 2, 2}; yPoint3D xyztmp[64], grdtmp[64]; double vartmp[64], v2tmp[64], norigin[3]; unsigned char flagtmp[64]; /* This function finds the intersection of a plane and a "rectangular" hexahedron. The caller must make tris large enough to hold 4 triangles (the worst case). origin is the coordinate of the lowest numbered point in the full array. The first point in the chunk is a guard point and is thus outside the full array. */ norigin[0]= origin[0]-len[0]; norigin[1]= origin[1]-len[1]; norigin[2]= origin[2]-len[2]; /* Contour on a 2-by-2-by-2 grid with no guard cells. All three sides have length 1.0. */ ycInitCartPcen(dims, offsets, len, norigin, sbox, 0); /* iso-surface at the distance, s, of the current plane */ ycContourTet_array(0, dims, s, vartmp, v2tmp, xyztmp, grdtmp, flagtmp, tris); } void yglTex3dbox(double ds, double *origin, double *len) { double s, smin, smax, facx, facy, facz, difs; double s0, s1, s2, s3, s4, s5, s6, s7; double sbox[8]; yPoint3D *dverts; float *verts, *texverts; long i, j, ntri, maxtri, nvert, nslab; if(alpha_pass) return; /* NOTE: len is the length of the sides of the whole volume, not the size of an individual cell. */ maxtri= 4; facx= fracx3d/len[0]; facy= fracy3d/len[1]; facz= fracz3d/len[2]; if(!tris_tex3d) { tris_tex3d= (TriArrayGrp *) p_malloc(sizeof(TriArrayGrp)); tris_tex3d->next= 0; tris_tex3d->cellIDs= (long *) p_malloc(maxtri*sizeof(long)); tris_tex3d->xyzverts= (yPoint3D *) p_malloc(3*maxtri*sizeof(yPoint3D)); tris_tex3d->normals= (yPoint3D *) p_malloc(3*maxtri*sizeof(yPoint3D)); } verts= (float *) p_malloc(sizeof(float)*3*3*maxtri); texverts= (float *) p_malloc(sizeof(float)*3*3*maxtri); dverts= tris_tex3d->xyzverts; s0= glCurrWin3d->view[0]*origin[0]+glCurrWin3d->view[1]*origin[1]+glCurrWin3d->view[2]*origin[2]; sbox[0]= s0; smin= smax= s0; sbox[1]= s1= s0+glCurrWin3d->view[0]*len[0]; if(s1 < smin) smin= s1; if(s1 > smax) smax= s1; sbox[2]= s2= s0+glCurrWin3d->view[1]*len[1]; if(s2 < smin) smin= s2; if(s2 > smax) smax= s2; sbox[3]= s3= s0+glCurrWin3d->view[0]*len[0]+glCurrWin3d->view[1]*len[1]; if(s3 < smin) smin= s3; if(s3 > smax) smax= s3; sbox[4]= s4= s0+glCurrWin3d->view[2]*len[2]; if(s4 < smin) smin= s4; if(s4 > smax) smax= s4; sbox[5]= s5= s4+glCurrWin3d->view[0]*len[0]; if(s5 < smin) smin= s5; if(s5 > smax) smax= s5; sbox[6]= s6= s4+glCurrWin3d->view[1]*len[1]; if(s6 < smin) smin= s6; if(s6 > smax) smax= s6; sbox[7]= s7= s4+glCurrWin3d->view[0]*len[0]+glCurrWin3d->view[1]*len[1]; if(s7 < smin) smin= s7; if(s7 > smax) smax= s7; nslab= (long) ((smax-smin)/ds); difs= (smax-smin)/nslab; s= smin+0.5*difs; yglPrepTex3d(); for(i= 0; i < nslab; i++) { slice_box(s, sbox, origin, len, tris_tex3d); ntri= tris_tex3d->numTri; if(ntri > 0) { nvert= 3*ntri; for(j= 0; j < nvert; j++) { /* The texture coordinate is the fraction of the distance between the minimum and maximum world coord value. This is adjusted for any extra space added when making the texture a power of 2 in size. */ verts[3*j]= (float) dverts[j].x; texverts[3*j]= (float) ((verts[3*j]-origin[0])*facx); verts[3*j+1]= (float) dverts[j].y; texverts[3*j+1]= (float) ((verts[3*j+1]-origin[1])*facy); verts[3*j+2]= (float) dverts[j].z; texverts[3*j+2]= (float) ((verts[3*j+2]-origin[2])*facz); } yglTexTris(ntri, verts, texverts); } s += difs; } yglEndTex3d(); } yorick-gl-1.1+cvs20070922+dfsg.orig/testisotree.i0000640000175000017500000005414210313362473021160 0ustar thibautthibaut/* * $Id: testisotree.i,v 1.1.1.1 2005/09/18 22:07:55 dhmunro Exp $ * Test the version of the iso-surface program that uses octrees. */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ require, "dlist3d.i" use_interleave= 0; require, "pnm.i"; require, "contour.i"; palette3d, "earth.gp"; func sho_slicecrv(ngrid,point=,normal=) { if(is_void(point)) point= [0.0, 0.0, 0.0]; if(is_void(normal)) normal= [1.0, 0.0, 0.0]; res= do_slicetreecrv(ngrid,point,normal); if(!is_void(res)) { write,"number of triangles is ",long(res(1)); write,"time to build tree is ",res(2); write,"time to extract slicing plane is ",res(3); write,"time to set colors is ",res(4); write,"time to draw slicing plane is ",res(5); write,"time to build display list is ",res(6); } } func do_slicetreecrv(ngrid,point,normal) { extern tree; extern gl_rr,gl_gg,gl_bb, gl_ncolr, gl_ctab; extern n_poly_3d, n_tri_3d; if(is_void(ngrid) || ngrid < 6) { nx= test3d_n(1); ny= test3d_n(2); nz= test3d_n(3); } else { nx= ngrid; ny= ngrid; nz= ngrid; } xyz= array(0.0, 3, nx, ny, nz); xyz(1,..)= span(-1,1,nx); xyz(2,..)= span(-1,1,ny)(-,); xyz(3,..)= span(-1,1,nz)(-,-,); /* Now rotate each plane by phi degrees around the z-axis relative to the one below it. */ phi= 0.5*pi/(nz-1.0); snph= sin(phi); csph= cos(phi); for(i= 2; i <= nz; i++) { xyz(1,,,i)= csph*xyz(1,,,i-1)-snph*xyz(2,,,i-1); xyz(2,,,i)= snph*xyz(1,,,i-1)+csph*xyz(2,,,i-1); } r= abs(xyz(1,..),xyz(2,..),xyz(3,..)); theta= acos(xyz(3,..)/(r+!r)); phi= atan(xyz(2,..),xyz(1,..)+(!r)); y32= sin(theta)^2*cos(theta)*cos(2*phi); f= r*(1.+y32); /* point centered */ r= theta= phi= []; palette3d,"stern.gp"; vcen= f(zcen,zcen,zcen); /* zone centered */ varmax= max(vcen); write, " test uses "+pr1((nx-1)*(ny-1)*(nz-1))+" cells"; numTri= nStrip= nVert= 0; clear3d; if(is_void(point)) point= [0.0, 0.0, 0.0]; if(is_void(pl_normal)) pl_normal= [1.0, 0.0, 0.0]; /* NOTE: the input array is assumed to include a layer of guard cells on all sides fi guard is non-zero. This means that the volume being contoured is a bit less than -1 to 1. */ tstart= tfin= array(0.0, 3); timer, tstart; tree= mak_slice_treecrv(xyz,guard=0); timer,tfin; tree_tim= (tfin-tstart)(3); timer, tstart; tris= slice_treecrv(xyz,point,pl_normal,tree); timer,tfin; slice_tim= (tfin-tstart)(3); timer, tstart; triptr= &tris; while(1) { if(is_void(*triptr)) break; if(!triptr) break; ntri= triptr->numTri; if(ntri) { /* one color per triangle based on cellID */ colr= map2color(ntri, *(triptr->cellIDs), vcen, vmin=0.0, vmax=varmax); triptr->colors= &colr; } triptr= triptr->next; } ; timer, tfin; colr_tim= (tfin-tstart)(3); timer,tstart; /* draw all tri arrays in the lists */ if(tris) { res= pltrilists3d(tris,emit=1); } timer,tfin; list_tim= (tfin-tstart)(3); if(!is_void(res)) { numTri += res; nStrip += res; nVert += 3*res; } timer, tstart; draw3d, !making_movie; if(is_void(keepview)) { stdview3d; } else if(!keepview) { stdview3d; } timer, tfin; draw_tim= (tfin-tstart)(3); n_tri_3d= numTri; n_poly_3d= numTri; sizes= [nx, ny, nz]; // chek_slice, point, normal, sizes, tris; write,"Grid is ", nx, "by", ny, "by", nz; return [numTri, tree_tim, slice_tim, colr_tim, draw_tim, list_tim]; } func slicecrv_movie(ngrid) { extern tree; extern gl_rr,gl_gg,gl_bb, gl_ncolr, gl_ctab; normal= [1.0, 0.0, 0.0]; point0= [0.0, 0.0, 0.0]; if(is_void(ngrid) || ngrid < 6) { nx= test3d_n(1); ny= test3d_n(2); nz= test3d_n(3); } else { nx= ngrid; ny= ngrid; nz= ngrid; } npts= 20; xyz= array(0.0, 3, nx,ny,nz); xyz(1,..)= span(-1,1,nx); xyz(2,..)= span(-1,1,nx)(-,); xyz(3,..)= span(-1,1,nx)(-,-,); /* Now rotate each plane by phi degrees around the z-axis relative to the one below it. */ phi= 0.5*pi/(nz-1.0); snph= sin(phi); csph= cos(phi); for(i= 2; i <= nz; i++) { xyz(1,,,i)= csph*xyz(1,,,i-1)-snph*xyz(2,,,i-1); xyz(2,,,i)= snph*xyz(1,,,i-1)+csph*xyz(2,,,i-1); } r= abs(xyz(1,..),xyz(2,..),xyz(3,..)); theta= acos(xyz(3,..)/(r+!r)); phi= atan(xyz(2,..),xyz(1,..)+(!r)); y32= sin(theta)^2*cos(theta)*cos(2*phi); f= r*(1.+y32); /* point centered */ r= theta= phi= []; xyzmin= min(xyz); xyzmax= max(xyz) sizes= (dimsof(f))(2:4); palette3d,"stern.gp"; vcen= f(zcen,zcen,zcen); varmax= max(vcen); write, " test uses "+pr1((nx-1)*(ny-1)*(nz-1))+" cells"; slice_tim= list_tim= draw_tim= colr_tim= 0.0; lookat3d,2.9*normal,[0.0,0.0,0.0],[0.0,0.0,1.0]; /* start the slice plane at the back, sweep through to the middle, rotate it 180 degrees, and sweep to the front. */ posns1= span(xyzmin, 0, npts); posns2= span(0, xyzmax, npts); norms= array(0.0, 3, npts); norms(1,)= cos(span(0.0, pi, npts)); norms(2,)= sin(span(0.0, pi, npts)); norms(3,)= 0.0; write, " test uses "+pr1((nx-1)*(ny-1)*(nz-1))+" cells"; tstart= tfin= array(0.0, 3); timer, tstart; tree= mak_slice_treecrv(xyz,guard=0); timer,tfin; tree_tim= (tfin-tstart)(3); /* NOTE: the input array is assumed to include a layer of guard cells on all sides. This means that the volume being contoured is a bit less than -1 to 1. */ for(jj= 1; jj <= npts; jj++) { timer, tstart; point= point0+posns1(jj)*normal; tris= slice_treecrv(xyz,point,normal,tree); timer,tfin; slice_tim += (tfin-tstart)(3); timer, tstart; triptr= &tris; while(1) { if(is_void(*triptr)) break; if(!triptr) break; ntri= triptr->numTri; if(ntri) { /* one color per triangle based on cellID */ colr= map2color(ntri, *(triptr->cellIDs), vcen, vmin=0.0, vmax=varmax); triptr->colors= &colr; } triptr= triptr->next; } ; timer, tfin; colr_tim += (tfin-tstart)(3); timer,tstart; clear3d; /* draw all tri arrays in the lists */ if(tris) { res= pltrilists3d(tris,emit=1); } timer,tfin; list_tim += (tfin-tstart)(3); timer, tstart; draw3d, !making_movie; timer, tfin; draw_tim += (tfin-tstart)(3); } for(jj= 1; jj <= npts; jj++) { timer, tstart; tris= slice_treecrv(xyz,point0,norms(,jj),tree); timer,tfin; slice_tim += (tfin-tstart)(3); timer, tstart; triptr= &tris; while(1) { if(is_void(*triptr)) break; if(!triptr) break; ntri= triptr->numTri; if(ntri) { /* one color per triangle based on cellID */ colr= map2color(ntri, *(triptr->cellIDs), vcen, vmin=0.0, vmax=varmax); triptr->colors= &colr; } triptr= triptr->next; } ; timer, tfin; colr_tim += (tfin-tstart)(3); timer,tstart; clear3d; /* draw all tri arrays in the lists */ if(tris) { res= pltrilists3d(tris,emit=1); } timer,tfin; list_tim += (tfin-tstart)(3); timer, tstart; draw3d, !making_movie; timer, tfin; draw_tim += (tfin-tstart)(3); } for(jj= 1; jj <= npts; jj++) { timer, tstart; point= point0+posns2(jj)*normal; tris= slice_treecrv(xyz,point,normal,tree); timer,tfin; slice_tim += (tfin-tstart)(3); timer, tstart; triptr= &tris; while(1) { if(is_void(*triptr)) break; if(!triptr) break; ntri= triptr->numTri; if(ntri) { /* one color per triangle based on cellID */ colr= map2color(ntri, *(triptr->cellIDs), vcen, vmin=0.0, vmax=varmax); triptr->colors= &colr; } triptr= triptr->next; } ; timer, tfin; colr_tim += (tfin-tstart)(3); timer,tstart; clear3d; /* draw all tri arrays in the lists */ if(tris) { res= pltrilists3d(tris,emit=1); } timer,tfin; list_tim += (tfin-tstart)(3); timer, tstart; draw3d, !making_movie; timer, tfin; draw_tim += (tfin-tstart)(3); } write,"Slice planes computed using an Octree"; write,"Grid is ", nx, "by", ny, "by", nz; write,"positions range from ",xyzmin," to ",xyzmax; write,"time to build octree is ",tree_tim; write,"time to extract extract plane is ",slice_tim; write,"time to set colors is ", colr_tim; write,"time to draw slicing plane is ", draw_tim; write,"time to build display list is ",list_tim; write,"frames per second is",(3*npts)/(slice_tim+colr_tim+draw_tim+list_tim); } func sho_slice(ngrid,point=,normal=) { if(is_void(point)) point= [0.0, 0.0, 0.0]; if(is_void(normal)) normal= [1.0, 0.0, 0.0]; res= do_slicetree(ngrid,point,normal); if(!is_void(res)) { write,"number of triangles is ",long(res(1)); write,"time to extract slicing plane is ",res(2); write,"time to draw slicing plane is ",res(3); write,"time to build display list is ",res(4); } } func do_slicetree(ngrid,point,normal) { extern gl_rr,gl_gg,gl_bb, gl_ncolr, gl_ctab; extern tree; extern n_poly_3d, n_tri_3d; extern have_slice; extern have_sphere; have_sphere= 0; if(is_void(ngrid) || ngrid < 6) { nx= test3d_n(1); ny= test3d_n(2); nz= test3d_n(3); } else { nx= ngrid; ny= ngrid; nz= ngrid; } xyz= array(0.0, 3, nx,ny,nz); xyz(1,..)= span(-1,1,nx); xyz(2,..)= span(-1,1,nx)(-,); xyz(3,..)= span(-1,1,nx)(-,-,); r= abs(xyz(1,..),xyz(2,..),xyz(3,..)); theta= acos(xyz(3,..)/(r+!r)); phi= atan(xyz(2,..),xyz(1,..)+(!r)); y32= sin(theta)^2*cos(theta)*cos(2*phi); f= r*(1.+y32); r= theta= phi= []; sizes= (dimsof(f))(2:4); palette3d,"stern.gp"; vcen= f(zcen,zcen,zcen); varmax= max(vcen); varfac= gl_ncolr/varmax; write, " test uses "+pr1((nx-1)*(ny-1)*(nz-1))+" cells"; numTri= nStrip= nVert= 0; clear3d; origin= [-1.0,-1.0,-1.0]; delta= [2.0/(nx-1.0), 2.0/(ny-1.0), 2.0/(nz-1.0)]; if(is_void(point)) point= [0.0, 0.0, 0.0]; if(is_void(normal)) normal= [1.0, 0.0, 0.0]; /* NOTE: the input array is assumed to include a layer of guard cells on all sides. This means that the volume being contoured is a bit less than -1 to 1. */ tstart= tfin= array(0.0, 3); timer, tstart; tris= slice_tree(sizes,origin,delta,point,normal); timer,tfin; slice_tim= (tfin-tstart)(3); triptr= &tris; while(1) { if(is_void(*triptr)) break; if(!triptr) break; ntri= triptr->numTri; if(ntri) { /* one color per triangle based on cellID */ cellids= (*(triptr->cellIDs))(1:ntri); /* cellIds are C-style so add one before using as yorick indices */ vals= vcen(*)(cellids+1); nd= long(vals*varfac)+1; nd= min(nd, gl_ncolr); colr= array(0.0, 3, ntri); colr(1,)= gl_rr(nd)/256.0; colr(2,)= gl_gg(nd)/256.0; colr(3,)= gl_bb(nd)/256.0; triptr->colors= &colr; } triptr= triptr->next; } ; timer,tstart; /* draw all tri arrays in the lists */ if(tris) { res= pltrilists3d(tris,emit=1); } timer,tfin; list_tim= (tfin-tstart)(3); if(!is_void(res)) { numTri += res; nStrip += res; nVert += 3*res; } timer, tstart; draw3d, !making_movie; if(is_void(keepview)) { stdview3d; } else if(!keepview) { stdview3d; } timer, tfin; draw_tim= (tfin-tstart)(3); n_tri_3d= numTri; n_poly_3d= numTri; sizes= [nx, ny, nz]; // chek_slice, point, normal, sizes, tris; write,"Grid is ", nx, "by", ny, "by", nz; return [numTri, slice_tim, draw_tim, list_tim]; } func slice_movie(ngrid) { extern tree; extern gl_rr,gl_gg,gl_bb, gl_ncolr, gl_ctab; normal= [1.0, 0.0, 0.0]; point0= [0.0, 0.0, 0.0]; if(is_void(ngrid) || ngrid < 6) { nx= test3d_n(1); ny= test3d_n(2); nz= test3d_n(3); } else { nx= ngrid; ny= ngrid; nz= ngrid; } npts= 20; xyz= array(0.0, 3, nx,ny,nz); xyz(1,..)= span(-1,1,nx); xyz(2,..)= span(-1,1,nx)(-,); xyz(3,..)= span(-1,1,nx)(-,-,); /* Now rotate each plane by phi degrees around the z-axis relative to the one below it. */ phi= 0.5*pi/(nz-1.0); snph= sin(phi); csph= cos(phi); for(i= 2; i <= nz; i++) { xyz(1,,,i)= csph*xyz(1,,,i-1)-snph*xyz(2,,,i-1); xyz(2,,,i)= snph*xyz(1,,,i-1)+csph*xyz(2,,,i-1); } r= abs(xyz(1,..),xyz(2,..),xyz(3,..)); theta= acos(xyz(3,..)/(r+!r)); phi= atan(xyz(2,..),xyz(1,..)+(!r)); y32= sin(theta)^2*cos(theta)*cos(2*phi); f= r*(1.+y32); /* point centered */ r= theta= phi= []; xyzmin= min(xyz); xyzmax= max(xyz) sizes= (dimsof(f))(2:4); palette3d,"stern.gp"; vcen= f(zcen,zcen,zcen); varmax= max(vcen); write, " test uses "+pr1((nx-1)*(ny-1)*(nz-1))+" cells"; slice_tim= list_tim= draw_tim= colr_tim= 0.0; lookat3d,2.9*normal,[0.0,0.0,0.0],[0.0,0.0,1.0]; /* start the slice plane at the back, sweep through to the middle, rotate it 180 degrees, and sweep to the front. */ posns1= span(xyzmin, 0, npts); posns2= span(0, xyzmax, npts); norms= array(0.0, 3, npts); norms(1,)= cos(span(0.0, pi, npts)); norms(2,)= sin(span(0.0, pi, npts)); norms(3,)= 0.0; origin= [-1.0,-1.0,-1.0]; delta= [2.0/(nx-1.0), 2.0/(ny-1.0), 2.0/(nz-1.0)]; write, " test uses "+pr1((nx-1)*(ny-1)*(nz-1))+" cells"; tstart= tfin= array(0.0, 3); /* NOTE: the input array is assumed to include a layer of guard cells on all sides. This means that the volume being contoured is a bit less than -1 to 1. */ for(jj= 1; jj <= npts; jj++) { timer, tstart; point= point0+posns1(jj)*normal; tris= slice_tree(sizes,origin,delta,point,normal); timer,tfin; slice_tim += (tfin-tstart)(3); timer, tstart; triptr= &tris; while(1) { if(is_void(*triptr)) break; if(!triptr) break; ntri= triptr->numTri; if(ntri) { /* one color per triangle based on cellID */ colr= map2color(ntri, *(triptr->cellIDs), vcen, vmin=0.0, vmax=varmax); triptr->colors= &colr; } triptr= triptr->next; } ; timer, tfin; colr_tim += (tfin-tstart)(3); timer,tstart; clear3d; /* draw all tri arrays in the lists */ if(tris) { res= pltrilists3d(tris,emit=1); } timer,tfin; list_tim += (tfin-tstart)(3); timer, tstart; draw3d, !making_movie; timer, tfin; draw_tim += (tfin-tstart)(3); } for(jj= 1; jj <= npts; jj++) { timer, tstart; tris= slice_tree(sizes,origin,delta,point0,norms(,jj)); timer,tfin; slice_tim += (tfin-tstart)(3); timer, tstart; triptr= &tris; while(1) { if(is_void(*triptr)) break; if(!triptr) break; ntri= triptr->numTri; if(ntri) { /* one color per triangle based on cellID */ colr= map2color(ntri, *(triptr->cellIDs), vcen, vmin=0.0, vmax=varmax); triptr->colors= &colr; } triptr= triptr->next; } ; timer, tfin; colr_tim += (tfin-tstart)(3); timer,tstart; clear3d; /* draw all tri arrays in the lists */ if(tris) { res= pltrilists3d(tris,emit=1); } timer,tfin; list_tim += (tfin-tstart)(3); timer, tstart; draw3d, !making_movie; timer, tfin; draw_tim += (tfin-tstart)(3); } for(jj= 1; jj <= npts; jj++) { timer, tstart; point= point0+posns2(jj)*normal; tris= slice_tree(sizes,origin,delta,point,normal); timer,tfin; slice_tim += (tfin-tstart)(3); timer, tstart; triptr= &tris; while(1) { if(is_void(*triptr)) break; if(!triptr) break; ntri= triptr->numTri; if(ntri) { /* one color per triangle based on cellID */ colr= map2color(ntri, *(triptr->cellIDs), vcen, vmin=0.0, vmax=varmax); triptr->colors= &colr; } triptr= triptr->next; } ; timer, tfin; colr_tim += (tfin-tstart)(3); timer,tstart; clear3d; /* draw all tri arrays in the lists */ if(tris) { res= pltrilists3d(tris,emit=1); } timer,tfin; list_tim += (tfin-tstart)(3); timer, tstart; draw3d, !making_movie; timer, tfin; draw_tim += (tfin-tstart)(3); } write,"Slice planes computed using an Octree"; write,"Grid is ", nx, "by", ny, "by", nz; write,"positions range from ",xyzmin," to ",xyzmax; write,"time to extract extract plane is ",slice_tim; write,"time to set colors is ", colr_tim; write,"time to draw slicing plane is ", draw_tim; write,"time to build display list is ",list_tim; write,"frames per second is",(3*npts)/(slice_tim+colr_tim+draw_tim+list_tim); } func print_tree(tree) { trptr= &tree; while(trptr && *trptr) { write,"maxdepth is",trptr->maxdepth; write,"start is";*(trptr->start); write,"chunk is";*(trptr->chunk); write,"triz is";*(trptr->trsiz); write,"ranges are";*(trptr->ranges); trptr= trptr->next; } } func chek_iso(level, sizes, tris) { /* The input is an iso-surface level, the dimensions of the data array, and an array of triangles. Evaluate the function at every triangle vertex to see if the iso-surface is correct */ nx= sizes(1); ny= sizes(2); nz= sizes(3); triptr= &tris; while(triptr && *triptr) { xyz= *(triptr->xyzverts); r= abs(xyz(1,..), xyz(2,..), xyz(3,..)); theta= acos(xyz(3,..)/r); phi= atan(xyz(2,..), xyz(1,..)+(!r)); y32= sin(theta)^2*cos(theta)*cos(2*phi); f= r*(1.+y32); err= f-level; rerr= abs(err)/(abs(f)+(!f)); write,"minimum of function minus iso-level is",min(err); write,"maximum of function minus iso-level is",max(err); write,"maximum relative error is",max(rerr); write,"RMS fractional error is", rerr(*)(rms); triptr= triptr->next; } } func chek_slice(point, normal, sizes, tris) { /* The input is a slicing plane, the dimensions of the data array, and an array of triangles. Evaluate the function at every triangle vertex to see if it is on the plane. */ nx= sizes(1); ny= sizes(2); nz= sizes(3); triptr= &tris; while(triptr && *triptr) { xyz= *(triptr->xyzverts); dist= ((xyz-point)*normal)(sum,..); write,"minimum distance to plane is",min(dist); write,"maximum distance to plane is",max(dist); triptr= triptr->next; } } func iso_movie(ngrid) { extern tree; if(is_void(ngrid) || ngrid < 6) { nx= test3d_n(1); ny= test3d_n(2); nz= test3d_n(3); } else { nx= ngrid; ny= ngrid; nz= ngrid; } nlev= 20; iso_lo= 0.1; iso_hi= 1.0; xyz= array(0.0, 3, nx,ny,nz); xyz(1,..)= span(-1,1,nx); xyz(2,..)= span(-1,1,nx)(-,); xyz(3,..)= span(-1,1,nx)(-,-,); r= abs(xyz(1,..),xyz(2,..),xyz(3,..)); theta= acos(xyz(3,..)/(r+!r)); phi= atan(xyz(2,..),xyz(1,..)+(!r)); y32= sin(theta)^2*cos(theta)*cos(2*phi); f= r*(1.+y32); r= theta= phi= []; origin= [-1.0,-1.0,-1.0]; delta= [2.0/(nx-1.0), 2.0/(nx-1.0), 2.0/(nx-1.0)]; colr= [0.0,1.0,0.2]; levels= span(iso_lo, iso_hi, nlev); tstart= tfin= array(0.0, 3); iso_tim= list_tim= draw_tim= 0.0; lookat3d,[2.2,-0.03,-0.22],[0.0,-0.03,-0.22],[0.0,0.0,1.0]; /* NOTE: the input array is assumed to include a layer of guard cells on all sides. This means that the volume being contoured is a bit less than -1 to 1. */ for(jj= 1; jj <= nlev; jj++) { timer, tstart; tris= iso3cenreg(origin,delta,f,levels(jj),colr); timer,tfin; iso_tim += (tfin-tstart)(3); /* draw all tri arrays in the lists */ clear3d; if(tris) { res= pltrilists3d(tris); } timer, tstart; list_tim += (tstart-tfin)(3); timer, tstart; draw3d, !making_movie; timer, tfin; draw_tim += (tfin-tstart)(3); } write,"Iso-surfaces computed using a Marching Cubes-like scheme"; write,"Grid is ", nx, "by", ny, "by", nz; write,"iso-levels range from ",iso_lo," to ",iso_hi; write,"time to extract iso-surface is ",iso_tim; write,"time to draw iso-surface is ", draw_tim; write,"time to build display list is ",list_tim; write,"frames per second is",nlev/(iso_tim+draw_tim+list_tim); } func isotree_movie(ngrid) { extern tree; if(is_void(ngrid) || ngrid < 6) { nx= test3d_n(1); ny= test3d_n(2); nz= test3d_n(3); } else { nx= ngrid; ny= ngrid; nz= ngrid; } nlev= 40; iso_lo= 0.1; iso_hi= 1.0; xyz= array(0.0, 3, nx,ny,nz); xyz(1,..)= span(-1,1,nx); xyz(2,..)= span(-1,1,nx)(-,); xyz(3,..)= span(-1,1,nx)(-,-,); r= abs(xyz(1,..),xyz(2,..),xyz(3,..)); theta= acos(xyz(3,..)/(r+!r)); phi= atan(xyz(2,..),xyz(1,..)+(!r)); y32= sin(theta)^2*cos(theta)*cos(2*phi); f= r*(1.+y32); r= theta= phi= []; origin= [-1.0,-1.0,-1.0]; delta= [2.0/(nx-1.0), 2.0/(nx-1.0), 2.0/(nx-1.0)]; colr= [0.0,1.0,0.2]; levels= span(iso_lo, iso_hi, nlev); tstart= tfin= array(0.0, 3); timer, tstart; tree= mak_isotree(f); timer,tfin; tree_tim= (tfin-tstart)(3); iso_tim= list_tim= draw_tim= 0.0; lookat3d,[2.2,-0.03,-0.22],[0.0,-0.03,-0.22],[0.0,0.0,1.0]; /* NOTE: the input array is assumed to include a layer of guard cells on all sides. This means that the volume being contoured is a bit less than -1 to 1. */ for(jj= 1; jj <= nlev; jj++) { timer, tstart; tris= iso3_tree(origin,delta,f,levels(jj),colr,tree); timer,tfin; iso_tim += (tfin-tstart)(3); /* draw all tri arrays in the lists */ clear3d; if(tris) { res= pltrilists3d(tris); } timer, tstart; list_tim += (tstart-tfin)(3); timer, tstart; draw3d, !making_movie; timer, tfin; draw_tim += (tfin-tstart)(3); } write,"Iso-surfaces computed an Octree"; write,"Grid is ", nx, "by", ny, "by", nz; write,"iso-levels range from ",iso_lo," to ",iso_hi; write,"number of triangles is ",long(numTri); write,"time to build octtree is ",tree_tim; write,"time to extract iso-surface is ",iso_tim; write,"time to draw iso-surface is ", draw_tim; write,"time to build display list is ",list_tim; write,"frames per second is",nlev/(iso_tim+draw_tim+list_tim); } #if 0 test3d_n= [20,20,20]; /* show objects while rotating with the mouse if non-zero */ always_show_obj3d,0; // create or activate the first OpenGL window win3d,0; thetalight= pi/4.0; light3d, diffuse=.7, specular=1, sdir=[cos(thetalight),.25,sin(thetalight)]; isotree_movie,30; stdview3d; #endif yorick-gl-1.1+cvs20070922+dfsg.orig/glWrappers.h0000640000175000017500000000427510313362464020735 0ustar thibautthibaut/* * $Id: glWrappers.h,v 1.1.1.1 2005/09/18 22:07:48 dhmunro Exp $ * Header file for the routines that handle mouse motion * in OpenGL windows. */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #ifndef __GLWRAPPERS__ #define __GLWRAPPERS__ #include "TriStruct.h" #ifdef __cplusplus extern "C" { #endif extern void yglInitLights3d(void); extern void yglGrabPix3d(int nArgs); extern float yglGetFov3d(void); extern void yglSetFov3d(float fov); extern void yglGetCenter3d(double *center); extern void yglGetEye3d(double *eye); extern void yglGetUp3d(double *up); extern long yglGetWidth3d(void); extern long yglGetHite3d(void); extern int yglHasTex3d(void); extern int yglHasTexcube3d(void); extern void yglAlwaysShowObj3d(long flag); extern void yglUseList3d(long flag); extern void yglUseArray3d(long flag); extern void yglTexTtris3d(int nArgs); extern void yglLdtex3d(int nArgs); extern void yglTexcells3d(int nArgs); extern void yglTstrips_alpha3d(int nArgs); extern void yglQstrips_alpha3d(int nArgs); extern void yglMsmovVal3d(double val); extern void yglOutCcw3d(long dir); extern void yglIncSeq3d(void); extern void yglArsum3d(long nx0, long ny0, long nz0, long nsx, long nsy, long nsz, double *vin, double *vout); extern long yglSizeTriArraysNdx3d(TriVertexGrp *list); extern void yglCopyTriArrayNdx3d(TriVertexGrp *list, TriVertexGrp *nlist); extern void yglCollapseTriArraysNdx3d(long colrtyp, TriVertexGrp *list, TriVertexGrp *nlist); extern void yglDoSortTriNdx3d(TriVertexGrp *oldtri, long *newptndx); extern long yglSizeTriArrays3d(TriArrayGrp *list); extern void yglCopyTriArray3d(long numtri, TriArrayGrp *list, TriArrayGrp *nlist); extern void yglCollapseTriArrays3d(long colrtyp, TriArrayGrp *list, TriArrayGrp *nlist); extern void yglDoSortTri3d(long colrtyp, TriArrayGrp *oldtri, TriArrayGrp *newtri); extern void yglSliceTris3d(long *keep, long *nkeep, double *dp, TriArrayGrp *oldtri, TriArrayGrp *newtri); extern void yglMouseFunc3d(long val); #ifdef __cplusplus } #endif #endif /* Include/Define */ yorick-gl-1.1+cvs20070922+dfsg.orig/Gradient3D.c0000640000175000017500000011147410313362476020531 0ustar thibautthibaut/* * $Id: Gradient3D.c,v 1.1.1.1 2005/09/18 22:07:58 dhmunro Exp $ */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #include "Contour3D.h" #include #include void ycNormalize(yPoint3D *n) { /* normalize the input vector. May fail for points larger than the square root of the maximum double. Answer may be wrong for point smaller than 1.0e-80; */ double len; len= sqrt(n->x*n->x+n->y*n->y+n->z*n->z)+1.0e-80; n->x /= len; n->y /= len; n->z /= len; } void ycPointGradient(long i, long j, long k, long nx, long ny, long nz, double *s, double dx, double dy, double dz, yPoint3D *n) { long sliceSize= nx*ny; long ibase= i + j*nx + k*sliceSize; /* x-direction */ if ( i == 0 ) { n->x = (s[ibase+1] - s[ibase]) / dx; } else if ( i == (nx-1) ) { n->x = (s[ibase] - s[ibase-1]) / dx; } else { n->x = 0.5 * (s[ibase+1] - s[ibase-1]) / dx; } /* y-direction */ if ( j == 0 ) { n->y = (s[ibase + nx] - s[ibase]) / dy; } else if ( j == (ny-1) ) { n->y = (s[ibase] - s[ibase - nx]) / dy; } else { n->y = 0.5 * (s[ibase + nx] - s[ibase - nx]) / dy; } /* z-direction */ if ( k == 0 ) { n->z = (s[ibase + sliceSize] - s[ibase]) / dz; } else if ( k == (nz-1) ) { n->z = (s[ibase] - s[ibase - sliceSize]) / dz; } else { n->z = 0.5 * (s[ibase + sliceSize] - s[ibase - sliceSize]) / dz; } } void ycPointGradientAll(long i, long j, long k, long nx, long ny, long nz, double *s, double dx, double dy, double dz, yPoint3D gradient[8]) { long ii, jj, kk; long sliceSize= nx*ny; long ibase, vrt= 0; /* guaranteed that in j and k directions the point is in the interior of the mesh. Have to test edge cases for i direction */ ii= i; jj= j; kk= k; ibase= ii + jj*nx + kk*sliceSize; /* x-direction */ if ( ii == 0 ) { gradient[vrt].x = (s[ibase+1] - s[ibase]) / dx; } else if ( ii == (nx-1) ) { gradient[vrt].x = (s[ibase] - s[ibase-1]) / dx; } else { gradient[vrt].x = 0.5 * (s[ibase+1] - s[ibase-1]) / dx; } /* y-direction */ gradient[vrt].y = 0.5 * (s[ibase + nx] - s[ibase - nx]) / dy; /* z-direction */ gradient[vrt].z = 0.5 * (s[ibase + sliceSize] - s[ibase - sliceSize]) / dz; vrt++; ii= i+1; jj= j; kk= k; ibase= ii + jj*nx + kk*sliceSize; /* x-direction */ if ( ii == 0 ) { gradient[vrt].x = (s[ibase+1] - s[ibase]) / dx; } else if ( ii == (nx-1) ) { gradient[vrt].x = (s[ibase] - s[ibase-1]) / dx; } else { gradient[vrt].x = 0.5 * (s[ibase+1] - s[ibase-1]) / dx; } /* y-direction */ gradient[vrt].y = 0.5 * (s[ibase + nx] - s[ibase - nx]) / dy; /* z-direction */ gradient[vrt].z = 0.5 * (s[ibase + sliceSize] - s[ibase - sliceSize]) / dz; vrt++; ii= i+1; jj= j+1; kk= k; ibase= ii + jj*nx + kk*sliceSize; /* x-direction */ if ( ii == 0 ) { gradient[vrt].x = (s[ibase+1] - s[ibase]) / dx; } else if ( ii == (nx-1) ) { gradient[vrt].x = (s[ibase] - s[ibase-1]) / dx; } else { gradient[vrt].x = 0.5 * (s[ibase+1] - s[ibase-1]) / dx; } /* y-direction */ gradient[vrt].y = 0.5 * (s[ibase + nx] - s[ibase - nx]) / dy; /* z-direction */ gradient[vrt].z = 0.5 * (s[ibase + sliceSize] - s[ibase - sliceSize]) / dz; vrt++; ii= i; jj= j+1; kk= k; ibase= ii + jj*nx + kk*sliceSize; /* x-direction */ if ( ii == 0 ) { gradient[vrt].x = (s[ibase+1] - s[ibase]) / dx; } else if ( ii == (nx-1) ) { gradient[vrt].x = (s[ibase] - s[ibase-1]) / dx; } else { gradient[vrt].x = 0.5 * (s[ibase+1] - s[ibase-1]) / dx; } /* y-direction */ gradient[vrt].y = 0.5 * (s[ibase + nx] - s[ibase - nx]) / dy; /* z-direction */ gradient[vrt].z = 0.5 * (s[ibase + sliceSize] - s[ibase - sliceSize]) / dz; vrt++; ii= i; jj= j; kk= k+1; ibase= ii + jj*nx + kk*sliceSize; /* x-direction */ if ( ii == 0 ) { gradient[vrt].x = (s[ibase+1] - s[ibase]) / dx; } else if ( ii == (nx-1) ) { gradient[vrt].x = (s[ibase] - s[ibase-1]) / dx; } else { gradient[vrt].x = 0.5 * (s[ibase+1] - s[ibase-1]) / dx; } /* y-direction */ gradient[vrt].y = 0.5 * (s[ibase + nx] - s[ibase - nx]) / dy; /* z-direction */ gradient[vrt].z = 0.5 * (s[ibase + sliceSize] - s[ibase - sliceSize]) / dz; vrt++; ii= i+1; jj= j; kk= k+1; ibase= ii + jj*nx + kk*sliceSize; /* x-direction */ if ( ii == 0 ) { gradient[vrt].x = (s[ibase+1] - s[ibase]) / dx; } else if ( ii == (nx-1) ) { gradient[vrt].x = (s[ibase] - s[ibase-1]) / dx; } else { gradient[vrt].x = 0.5 * (s[ibase+1] - s[ibase-1]) / dx; } /* y-direction */ gradient[vrt].y = 0.5 * (s[ibase + nx] - s[ibase - nx]) / dy; /* z-direction */ gradient[vrt].z = 0.5 * (s[ibase + sliceSize] - s[ibase - sliceSize]) / dz; vrt++; ii= i+1; jj= j+1; kk= k+1; ibase= ii + jj*nx + kk*sliceSize; /* x-direction */ if ( ii == 0 ) { gradient[vrt].x = (s[ibase+1] - s[ibase]) / dx; } else if ( ii == (nx-1) ) { gradient[vrt].x = (s[ibase] - s[ibase-1]) / dx; } else { gradient[vrt].x = 0.5 * (s[ibase+1] - s[ibase-1]) / dx; } /* y-direction */ gradient[vrt].y = 0.5 * (s[ibase + nx] - s[ibase - nx]) / dy; /* z-direction */ gradient[vrt].z = 0.5 * (s[ibase + sliceSize] - s[ibase - sliceSize]) / dz; vrt++; ii= i; jj= j+1; kk= k+1; ibase= ii + jj*nx + kk*sliceSize; /* x-direction */ if ( ii == 0 ) { gradient[vrt].x = (s[ibase+1] - s[ibase]) / dx; } else if ( ii == (nx-1) ) { gradient[vrt].x = (s[ibase] - s[ibase-1]) / dx; } else { gradient[vrt].x = 0.5 * (s[ibase+1] - s[ibase-1]) / dx; } /* y-direction */ gradient[vrt].y = 0.5 * (s[ibase + nx] - s[ibase - nx]) / dy; /* z-direction */ gradient[vrt].z = 0.5 * (s[ibase + sliceSize] - s[ibase - sliceSize]) / dz; vrt++; } void ycPointGradientCrv(long i, long j, long k, long nx, long ny, long nz, yPoint3D *x, double *s, yPoint3D *n) { double sp, sm, del2; long sliceSize= nx*ny; long ibase= i + j*nx + k*sliceSize; yPoint3D delta; /* i-direction */ if ( i == 0 ) { sp = s[ibase+1]; sm = s[ibase]; delta.x= x[ibase+1].x-x[ibase].x; delta.y= x[ibase+1].y-x[ibase].y; delta.z= x[ibase+1].z-x[ibase].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; n->x = (sp - sm)*delta.x / del2; n->y = (sp - sm)*delta.y / del2; n->z = (sp - sm)*delta.z / del2; } else if ( i == (nx-1) ) { sp = s[ibase]; sm = s[ibase-1]; delta.x= x[ibase].x-x[ibase-1].x; delta.y= x[ibase].y-x[ibase-1].y; delta.z= x[ibase].z-x[ibase-1].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; n->x = (sp - sm)*delta.x / del2; n->y = (sp - sm)*delta.y / del2; n->z = (sp - sm)*delta.z / del2; } else { sp = s[ibase+1]; sm = s[ibase-1]; delta.x= x[ibase+1].x-x[ibase-1].x; delta.y= x[ibase+1].y-x[ibase-1].y; delta.z= x[ibase+1].z-x[ibase-1].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; n->x = (sp - sm)*delta.x / del2; n->y = (sp - sm)*delta.y / del2; n->z = (sp - sm)*delta.z / del2; } /* j-direction */ if ( j == 0 ) { sp = s[ibase + nx]; sm = s[ibase]; delta.x= x[ibase+nx].x-x[ibase].x; delta.y= x[ibase+nx].y-x[ibase].y; delta.z= x[ibase+nx].z-x[ibase].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; n->x += (sp - sm) *delta.x / del2; n->y += (sp - sm) *delta.y / del2; n->z += (sp - sm) *delta.z / del2; } else if ( j == (ny-1) ) { sp = s[ibase]; sm = s[ibase - nx]; delta.x= x[ibase].x-x[ibase-nx].x; delta.y= x[ibase].y-x[ibase-nx].y; delta.z= x[ibase].z-x[ibase-nx].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; n->x += (sp - sm) *delta.x / del2; n->y += (sp - sm) *delta.y / del2; n->z += (sp - sm) *delta.z / del2; } else { sp = s[ibase + nx]; sm = s[ibase - nx]; delta.x= x[ibase+nx].x-x[ibase-nx].x; delta.y= x[ibase+nx].y-x[ibase-nx].y; delta.z= x[ibase+nx].z-x[ibase-nx].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; n->x += (sp - sm) *delta.x / del2; n->y += (sp - sm) *delta.y / del2; n->z += (sp - sm) *delta.z / del2; } /* k-direction */ if ( k == 0 ) { sp = s[ibase + sliceSize]; sm = s[ibase]; delta.x= x[ibase+sliceSize].x-x[ibase].x; delta.y= x[ibase+sliceSize].y-x[ibase].y; delta.z= x[ibase+sliceSize].z-x[ibase].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; n->x += (sp - sm) *delta.x / del2; n->y += (sp - sm) *delta.y / del2; n->z += (sp - sm) *delta.z / del2; } else if ( k == (nz-1) ) { sp = s[ibase]; sm = s[ibase - sliceSize]; delta.x= x[ibase].x-x[ibase-sliceSize].x; delta.y= x[ibase].y-x[ibase-sliceSize].y; delta.z= x[ibase].z-x[ibase-sliceSize].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; n->x += (sp - sm) *delta.x / del2; n->y += (sp - sm) *delta.y / del2; n->z += (sp - sm) *delta.z / del2; } else { sp = s[ibase + sliceSize]; sm = s[ibase - sliceSize]; delta.x= x[ibase+sliceSize].x-x[ibase-sliceSize].x; delta.y= x[ibase+sliceSize].y-x[ibase-sliceSize].y; delta.z= x[ibase+sliceSize].z-x[ibase-sliceSize].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; n->x += (sp - sm) *delta.x / del2; n->y += (sp - sm) *delta.y / del2; n->z += (sp - sm) *delta.z / del2; } } #define del_2(a) {del2=a.x*a.x+a.y*a.y+a.z*a.z+1.0e-80;} #define do_diff(a,n,m) {a.x= pts[n].x-pts[m].x;a.y= pts[n].y-pts[m].y;a.z= pts[n].z-pts[m].z;} #define bump_grad(n,a) {gradients[n].x += sp*a.x/del2;gradients[n].y += sp*a.y/del2;gradients[n].z += sp*a.z/del2;} #define set_grad(n,a) {gradients[n].x= sp*a.x/del2;gradients[n].y= sp*a.y/del2;gradients[n].z= sp*a.z/del2;} void ycPointGradientHex(yPoint3D *pts, double *s, yPoint3D *gradients) { double sp, del2; yPoint3D d100_000, d110_010, d101_001, d111_011; yPoint3D d010_000, d110_100, d011_001, d111_101; yPoint3D d001_000, d101_100, d011_010, d111_110; do_diff(d100_000,1,0) do_diff(d110_010,3,2) do_diff(d101_001,5,4) do_diff(d111_011,7,6) do_diff(d010_000,2,0) do_diff(d110_100,3,1) do_diff(d011_001,6,4) do_diff(d111_101,7,5) do_diff(d001_000,4,0) do_diff(d101_100,5,1) do_diff(d011_010,6,2) do_diff(d111_110,7,3) /* x=0, y=0, z=0 corner */ sp = s[1]-s[0]; del_2(d100_000); set_grad(0,d100_000); sp = s[2]-s[0]; del_2(d010_000); bump_grad(0,d010_000); sp = s[4]-s[0]; del_2(d001_000); bump_grad(0,d001_000); /* x=1, y=0, z=0 corner */ sp = s[1]-s[0]; del_2(d100_000); set_grad(1,d100_000); sp = s[3]-s[1]; del_2(d110_100); bump_grad(1,d110_100); sp = s[5]-s[1]; del_2(d101_100); bump_grad(1,d101_100); /* x=0, y=1, z=0 corner */ sp = s[3]-s[2]; del_2(d110_010); set_grad(3,d110_010); sp = s[2]-s[0]; del_2(d010_000); bump_grad(3,d010_000); sp = s[6]-s[2]; del_2(d011_010); bump_grad(3,d011_010); /* x=1, y=1, z=0 corner */ sp = s[3]-s[2]; del_2(d110_010); set_grad(2,d110_010); sp = s[3]-s[1]; del_2(d110_100); bump_grad(2,d110_100); sp = s[7]-s[3]; del_2(d111_110); bump_grad(2,d111_110); /* x=0, y=0, z=1 corner */ sp = s[5]-s[4]; del_2(d101_001); set_grad(4,d101_001); sp = s[6]-s[4]; del_2(d011_001); bump_grad(4,d011_001); sp = s[4]-s[0]; del_2(d001_000); bump_grad(4,d001_000); /* x=1, y=0, z=1 corner */ sp = s[5]-s[4]; del_2(d101_001); set_grad(5,d101_001); sp = s[7]-s[5]; del_2(d111_101); bump_grad(5,d111_101); sp = s[5]-s[1]; del_2(d101_100); bump_grad(5,d101_100); /* x=0, y=1, z=1 corner */ sp = s[7]-s[6]; del_2(d111_011); set_grad(7,d111_011); sp = s[6]-s[4]; del_2(d011_001); bump_grad(7,d011_001); sp = s[6]-s[2]; del_2(d011_010); bump_grad(7,d011_010); /* x=1, y=1, z=1 corner */ sp = s[7]-s[6]; del_2(d111_011); set_grad(6,d111_011); sp = s[7]-s[5]; del_2(d111_101); bump_grad(6,d111_101); sp = s[7]-s[3]; del_2(d111_110); bump_grad(6,d111_110); } void ycPointGradientGrd(long i, long j, long k, long nx, long ny, long nz, double *s, double dx, double dy, double dz, yPoint3D *n, yPoint3D *grd, char *done) { long sliceSize= nx*ny; long ibase= i + j*nx + k*sliceSize; if(done[ibase]) { *n = grd[ibase]; return; } /* x-direction */ if ( i == 0 ) { n->x = (s[ibase+1] - s[ibase]) / dx; } else if ( i == (nx-1) ) { n->x = (s[ibase] - s[ibase-1]) / dx; } else { n->x = 0.5 * (s[ibase+1] - s[ibase-1]) / dx; } /* y-direction */ if ( j == 0 ) { n->y = (s[ibase + nx] - s[ibase]) / dy; } else if ( j == (ny-1) ) { n->y = (s[ibase] - s[ibase - nx]) / dy; } else { n->y = 0.5 * (s[ibase + nx] - s[ibase - nx]) / dy; } /* z-direction */ if ( k == 0 ) { n->z = (s[ibase + sliceSize] - s[ibase]) / dz; } else if ( k == (nz-1) ) { n->z = (s[ibase] - s[ibase - sliceSize]) / dz; } else { n->z = 0.5 * (s[ibase + sliceSize] - s[ibase - sliceSize]) / dz; } grd[ibase] = *n; done[ibase]= 1; } void ycPointGradientAllGrd(long i, long j, long k, long nx, long ny, long nz, double *s, double dx, double dy, double dz, yPoint3D gradient[8], yPoint3D *grd, char *done) { long ii, jj, kk; long sliceSize= nx*ny; long ibase, vrt= 0; /* guaranteed that in j and k directions the point is in the interior of the mesh. Have to test edge cases for i direction */ ii= i; jj= j; kk= k; ibase= ii + jj*nx + kk*sliceSize; if(done[ibase]) { gradient[vrt] = grd[ibase]; } else { /* x-direction */ if ( ii == 0 ) { gradient[vrt].x = (s[ibase+1] - s[ibase]) / dx; } else if ( ii == (nx-1) ) { gradient[vrt].x = (s[ibase] - s[ibase-1]) / dx; } else { gradient[vrt].x = 0.5 * (s[ibase+1] - s[ibase-1]) / dx; } /* y-direction */ gradient[vrt].y = 0.5 * (s[ibase + nx] - s[ibase - nx]) / dy; /* z-direction */ gradient[vrt].z = 0.5 * (s[ibase + sliceSize] - s[ibase - sliceSize]) / dz; grd[ibase]= gradient[vrt]; done[ibase]= 1; } vrt++; ii= i+1; jj= j; kk= k; ibase= ii + jj*nx + kk*sliceSize; if(done[ibase]) { gradient[vrt] = grd[ibase]; } else { /* x-direction */ if ( ii == 0 ) { gradient[vrt].x = (s[ibase+1] - s[ibase]) / dx; } else if ( ii == (nx-1) ) { gradient[vrt].x = (s[ibase] - s[ibase-1]) / dx; } else { gradient[vrt].x = 0.5 * (s[ibase+1] - s[ibase-1]) / dx; } /* y-direction */ gradient[vrt].y = 0.5 * (s[ibase + nx] - s[ibase - nx]) / dy; /* z-direction */ gradient[vrt].z = 0.5 * (s[ibase + sliceSize] - s[ibase - sliceSize]) / dz; grd[ibase]= gradient[vrt]; done[ibase]= 1; } vrt++; ii= i+1; jj= j+1; kk= k; ibase= ii + jj*nx + kk*sliceSize; if(done[ibase]) { gradient[vrt] = grd[ibase]; } else { /* x-direction */ if ( ii == 0 ) { gradient[vrt].x = (s[ibase+1] - s[ibase]) / dx; } else if ( ii == (nx-1) ) { gradient[vrt].x = (s[ibase] - s[ibase-1]) / dx; } else { gradient[vrt].x = 0.5 * (s[ibase+1] - s[ibase-1]) / dx; } /* y-direction */ gradient[vrt].y = 0.5 * (s[ibase + nx] - s[ibase - nx]) / dy; /* z-direction */ gradient[vrt].z = 0.5 * (s[ibase + sliceSize] - s[ibase - sliceSize]) / dz; grd[ibase]= gradient[vrt]; done[ibase]= 1; } vrt++; ii= i; jj= j+1; kk= k; ibase= ii + jj*nx + kk*sliceSize; if(done[ibase]) { gradient[vrt] = grd[ibase]; } else { /* x-direction */ if ( ii == 0 ) { gradient[vrt].x = (s[ibase+1] - s[ibase]) / dx; } else if ( ii == (nx-1) ) { gradient[vrt].x = (s[ibase] - s[ibase-1]) / dx; } else { gradient[vrt].x = 0.5 * (s[ibase+1] - s[ibase-1]) / dx; } /* y-direction */ gradient[vrt].y = 0.5 * (s[ibase + nx] - s[ibase - nx]) / dy; /* z-direction */ gradient[vrt].z = 0.5 * (s[ibase + sliceSize] - s[ibase - sliceSize]) / dz; grd[ibase]= gradient[vrt]; done[ibase]= 1; } vrt++; ii= i; jj= j; kk= k+1; ibase= ii + jj*nx + kk*sliceSize; if(done[ibase]) { gradient[vrt] = grd[ibase]; } else { /* x-direction */ if ( ii == 0 ) { gradient[vrt].x = (s[ibase+1] - s[ibase]) / dx; } else if ( ii == (nx-1) ) { gradient[vrt].x = (s[ibase] - s[ibase-1]) / dx; } else { gradient[vrt].x = 0.5 * (s[ibase+1] - s[ibase-1]) / dx; } /* y-direction */ gradient[vrt].y = 0.5 * (s[ibase + nx] - s[ibase - nx]) / dy; /* z-direction */ gradient[vrt].z = 0.5 * (s[ibase + sliceSize] - s[ibase - sliceSize]) / dz; grd[ibase]= gradient[vrt]; done[ibase]= 1; } vrt++; ii= i+1; jj= j; kk= k+1; ibase= ii + jj*nx + kk*sliceSize; if(done[ibase]) { gradient[vrt] = grd[ibase]; } else { /* x-direction */ if ( ii == 0 ) { gradient[vrt].x = (s[ibase+1] - s[ibase]) / dx; } else if ( ii == (nx-1) ) { gradient[vrt].x = (s[ibase] - s[ibase-1]) / dx; } else { gradient[vrt].x = 0.5 * (s[ibase+1] - s[ibase-1]) / dx; } /* y-direction */ gradient[vrt].y = 0.5 * (s[ibase + nx] - s[ibase - nx]) / dy; /* z-direction */ gradient[vrt].z = 0.5 * (s[ibase + sliceSize] - s[ibase - sliceSize]) / dz; grd[ibase]= gradient[vrt]; done[ibase]= 1; } vrt++; ii= i+1; jj= j+1; kk= k+1; ibase= ii + jj*nx + kk*sliceSize; if(done[ibase]) { gradient[vrt] = grd[ibase]; } else { /* x-direction */ if ( ii == 0 ) { gradient[vrt].x = (s[ibase+1] - s[ibase]) / dx; } else if ( ii == (nx-1) ) { gradient[vrt].x = (s[ibase] - s[ibase-1]) / dx; } else { gradient[vrt].x = 0.5 * (s[ibase+1] - s[ibase-1]) / dx; } /* y-direction */ gradient[vrt].y = 0.5 * (s[ibase + nx] - s[ibase - nx]) / dy; /* z-direction */ gradient[vrt].z = 0.5 * (s[ibase + sliceSize] - s[ibase - sliceSize]) / dz; grd[ibase]= gradient[vrt]; done[ibase]= 1; } vrt++; ii= i; jj= j+1; kk= k+1; ibase= ii + jj*nx + kk*sliceSize; if(done[ibase]) { gradient[vrt] = grd[ibase]; } else { /* x-direction */ if ( ii == 0 ) { gradient[vrt].x = (s[ibase+1] - s[ibase]) / dx; } else if ( ii == (nx-1) ) { gradient[vrt].x = (s[ibase] - s[ibase-1]) / dx; } else { gradient[vrt].x = 0.5 * (s[ibase+1] - s[ibase-1]) / dx; } /* y-direction */ gradient[vrt].y = 0.5 * (s[ibase + nx] - s[ibase - nx]) / dy; /* z-direction */ gradient[vrt].z = 0.5 * (s[ibase + sliceSize] - s[ibase - sliceSize]) / dz; grd[ibase]= gradient[vrt]; done[ibase]= 1; } vrt++; } void ycPointGradientCrvGrd(long i, long j, long k, long nx, long ny, long nz, yPoint3D *x, double *s, yPoint3D *n, yPoint3D *grd, char *done) { double sp, sm, del2; long sliceSize= nx*ny; long ibase= i + j*nx + k*sliceSize; yPoint3D delta; if(done[ibase]) { *n = grd[ibase]; return; } /* i-direction */ if ( i == 0 ) { sp = s[ibase+1]; sm = s[ibase]; delta.x= x[ibase+1].x-x[ibase].x; delta.y= x[ibase+1].y-x[ibase].y; delta.z= x[ibase+1].z-x[ibase].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; n->x = (sp - sm)*delta.x / del2; n->y = (sp - sm)*delta.y / del2; n->z = (sp - sm)*delta.z / del2; } else if ( i == (nx-1) ) { sp = s[ibase]; sm = s[ibase-1]; delta.x= x[ibase].x-x[ibase-1].x; delta.y= x[ibase].y-x[ibase-1].y; delta.z= x[ibase].z-x[ibase-1].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; n->x = (sp - sm)*delta.x / del2; n->y = (sp - sm)*delta.y / del2; n->z = (sp - sm)*delta.z / del2; } else { sp = s[ibase+1]; sm = s[ibase-1]; delta.x= x[ibase+1].x-x[ibase-1].x; delta.y= x[ibase+1].y-x[ibase-1].y; delta.z= x[ibase+1].z-x[ibase-1].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; n->x = (sp - sm)*delta.x / del2; n->y = (sp - sm)*delta.y / del2; n->z = (sp - sm)*delta.z / del2; } /* j-direction */ if ( j == 0 ) { sp = s[ibase + nx]; sm = s[ibase]; delta.x= x[ibase+nx].x-x[ibase].x; delta.y= x[ibase+nx].y-x[ibase].y; delta.z= x[ibase+nx].z-x[ibase].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; n->x += (sp - sm) *delta.x / del2; n->y += (sp - sm) *delta.y / del2; n->z += (sp - sm) *delta.z / del2; } else if ( j == (ny-1) ) { sp = s[ibase]; sm = s[ibase - nx]; delta.x= x[ibase].x-x[ibase-nx].x; delta.y= x[ibase].y-x[ibase-nx].y; delta.z= x[ibase].z-x[ibase-nx].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; n->x += (sp - sm) *delta.x / del2; n->y += (sp - sm) *delta.y / del2; n->z += (sp - sm) *delta.z / del2; } else { sp = s[ibase + nx]; sm = s[ibase - nx]; delta.x= x[ibase+nx].x-x[ibase-nx].x; delta.y= x[ibase+nx].y-x[ibase-nx].y; delta.z= x[ibase+nx].z-x[ibase-nx].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; n->x += (sp - sm) *delta.x / del2; n->y += (sp - sm) *delta.y / del2; n->z += (sp - sm) *delta.z / del2; } /* k-direction */ if ( k == 0 ) { sp = s[ibase + sliceSize]; sm = s[ibase]; delta.x= x[ibase+sliceSize].x-x[ibase].x; delta.y= x[ibase+sliceSize].y-x[ibase].y; delta.z= x[ibase+sliceSize].z-x[ibase].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; n->x += (sp - sm) *delta.x / del2; n->y += (sp - sm) *delta.y / del2; n->z += (sp - sm) *delta.z / del2; } else if ( k == (nz-1) ) { sp = s[ibase]; sm = s[ibase - sliceSize]; delta.x= x[ibase].x-x[ibase-sliceSize].x; delta.y= x[ibase].y-x[ibase-sliceSize].y; delta.z= x[ibase].z-x[ibase-sliceSize].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; n->x += (sp - sm) *delta.x / del2; n->y += (sp - sm) *delta.y / del2; n->z += (sp - sm) *delta.z / del2; } else { sp = s[ibase + sliceSize]; sm = s[ibase - sliceSize]; delta.x= x[ibase+sliceSize].x-x[ibase-sliceSize].x; delta.y= x[ibase+sliceSize].y-x[ibase-sliceSize].y; delta.z= x[ibase+sliceSize].z-x[ibase-sliceSize].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; n->x += (sp - sm) *delta.x / del2; n->y += (sp - sm) *delta.y / del2; n->z += (sp - sm) *delta.z / del2; } grd[ibase]= *n; done[ibase]= 1; } void ycPointGradientIntGrd(long i, long j, long k, long nx, long ny, long nz, double *s, double dx, double dy, double dz, yPoint3D gradient[8], yPoint3D *grd, char *done) { long ii, jj, kk; long sliceSize= nx*ny; long ibase, vrt= 0; /* guaranteed that in i, j and k directions the point is in the interior of the mesh. */ ii= i; jj= j; kk= k; ibase= ii + jj*nx + kk*sliceSize; if(done[ibase]) { gradient[vrt] = grd[ibase]; } else { /* x-direction */ gradient[vrt].x = 0.5 * (s[ibase+1] - s[ibase-1]) / dx; /* y-direction */ gradient[vrt].y = 0.5 * (s[ibase + nx] - s[ibase - nx]) / dy; /* z-direction */ gradient[vrt].z = 0.5 * (s[ibase + sliceSize] - s[ibase - sliceSize]) / dz; grd[ibase]= gradient[vrt]; done[ibase]= 1; } vrt++; ii= i+1; jj= j; kk= k; ibase= ii + jj*nx + kk*sliceSize; if(done[ibase]) { gradient[vrt] = grd[ibase]; } else { /* x-direction */ gradient[vrt].x = 0.5 * (s[ibase+1] - s[ibase-1]) / dx; /* y-direction */ gradient[vrt].y = 0.5 * (s[ibase + nx] - s[ibase - nx]) / dy; /* z-direction */ gradient[vrt].z = 0.5 * (s[ibase + sliceSize] - s[ibase - sliceSize]) / dz; grd[ibase]= gradient[vrt]; done[ibase]= 1; } vrt++; ii= i+1; jj= j+1; kk= k; ibase= ii + jj*nx + kk*sliceSize; if(done[ibase]) { gradient[vrt] = grd[ibase]; } else { /* x-direction */ gradient[vrt].x = 0.5 * (s[ibase+1] - s[ibase-1]) / dx; /* y-direction */ gradient[vrt].y = 0.5 * (s[ibase + nx] - s[ibase - nx]) / dy; /* z-direction */ gradient[vrt].z = 0.5 * (s[ibase + sliceSize] - s[ibase - sliceSize]) / dz; grd[ibase]= gradient[vrt]; done[ibase]= 1; } vrt++; ii= i; jj= j+1; kk= k; ibase= ii + jj*nx + kk*sliceSize; if(done[ibase]) { gradient[vrt] = grd[ibase]; } else { /* x-direction */ gradient[vrt].x = 0.5 * (s[ibase+1] - s[ibase-1]) / dx; /* y-direction */ gradient[vrt].y = 0.5 * (s[ibase + nx] - s[ibase - nx]) / dy; /* z-direction */ gradient[vrt].z = 0.5 * (s[ibase + sliceSize] - s[ibase - sliceSize]) / dz; grd[ibase]= gradient[vrt]; done[ibase]= 1; } vrt++; ii= i; jj= j; kk= k+1; ibase= ii + jj*nx + kk*sliceSize; if(done[ibase]) { gradient[vrt] = grd[ibase]; } else { /* x-direction */ gradient[vrt].x = 0.5 * (s[ibase+1] - s[ibase-1]) / dx; /* y-direction */ gradient[vrt].y = 0.5 * (s[ibase + nx] - s[ibase - nx]) / dy; /* z-direction */ gradient[vrt].z = 0.5 * (s[ibase + sliceSize] - s[ibase - sliceSize]) / dz; grd[ibase]= gradient[vrt]; done[ibase]= 1; } vrt++; ii= i+1; jj= j; kk= k+1; ibase= ii + jj*nx + kk*sliceSize; if(done[ibase]) { gradient[vrt] = grd[ibase]; } else { /* x-direction */ gradient[vrt].x = 0.5 * (s[ibase+1] - s[ibase-1]) / dx; /* y-direction */ gradient[vrt].y = 0.5 * (s[ibase + nx] - s[ibase - nx]) / dy; /* z-direction */ gradient[vrt].z = 0.5 * (s[ibase + sliceSize] - s[ibase - sliceSize]) / dz; grd[ibase]= gradient[vrt]; done[ibase]= 1; } vrt++; ii= i+1; jj= j+1; kk= k+1; ibase= ii + jj*nx + kk*sliceSize; if(done[ibase]) { gradient[vrt] = grd[ibase]; } else { /* x-direction */ gradient[vrt].x = 0.5 * (s[ibase+1] - s[ibase-1]) / dx; /* y-direction */ gradient[vrt].y = 0.5 * (s[ibase + nx] - s[ibase - nx]) / dy; /* z-direction */ gradient[vrt].z = 0.5 * (s[ibase + sliceSize] - s[ibase - sliceSize]) / dz; grd[ibase]= gradient[vrt]; done[ibase]= 1; } vrt++; ii= i; jj= j+1; kk= k+1; ibase= ii + jj*nx + kk*sliceSize; if(done[ibase]) { gradient[vrt] = grd[ibase]; } else { /* x-direction */ gradient[vrt].x = 0.5 * (s[ibase+1] - s[ibase-1]) / dx; /* y-direction */ gradient[vrt].y = 0.5 * (s[ibase + nx] - s[ibase - nx]) / dy; /* z-direction */ gradient[vrt].z = 0.5 * (s[ibase + sliceSize] - s[ibase - sliceSize]) / dz; grd[ibase]= gradient[vrt]; done[ibase]= 1; } vrt++; } void ycPointGradientIntGrdCrv(long i, long j, long k, long nx, long ny, long nz, yPoint3D *xyz, double *s, yPoint3D gradient[8], yPoint3D *grd, char *done) { long ii, jj, kk; long sliceSize= nx*ny; long ibase, vrt= 0; double fac, del2; yPoint3D delta; /* guaranteed that in i, j and k directions the point is in the interior of the mesh. */ ii= i; jj= j; kk= k; ibase= ii + jj*nx + kk*sliceSize; if(done[ibase]) { gradient[vrt] = grd[ibase]; } else { /* i-direction */ delta.x= xyz[ibase+1].x-xyz[ibase-1].x; delta.y= xyz[ibase+1].y-xyz[ibase-1].y; delta.z= xyz[ibase+1].z-xyz[ibase-1].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; fac= (s[ibase+1] - s[ibase-1]) / del2; gradient[vrt].x = delta.x*fac; gradient[vrt].y = delta.y*fac; gradient[vrt].z = delta.z*fac; /* j-direction */ delta.x= xyz[ibase+nx].x-xyz[ibase-nx].x; delta.y= xyz[ibase+nx].y-xyz[ibase-nx].y; delta.z= xyz[ibase+nx].z-xyz[ibase-nx].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; fac= (s[ibase+nx] - s[ibase-nx]) / del2; gradient[vrt].x += delta.x*fac; gradient[vrt].y += delta.y*fac; gradient[vrt].z += delta.z*fac; /* k-direction */ delta.x= xyz[ibase+sliceSize].x-xyz[ibase-sliceSize].x; delta.y= xyz[ibase+sliceSize].y-xyz[ibase-sliceSize].y; delta.z= xyz[ibase+sliceSize].z-xyz[ibase-sliceSize].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; fac= (s[ibase+sliceSize] - s[ibase-sliceSize]) / del2; gradient[vrt].x += delta.x*fac; gradient[vrt].y += delta.y*fac; gradient[vrt].z += delta.z*fac; grd[ibase]= gradient[vrt]; done[ibase]= 1; } vrt++; ii= i+1; jj= j; kk= k; ibase= ii + jj*nx + kk*sliceSize; if(done[ibase]) { gradient[vrt] = grd[ibase]; } else { /* i-direction */ delta.x= xyz[ibase+1].x-xyz[ibase-1].x; delta.y= xyz[ibase+1].y-xyz[ibase-1].y; delta.z= xyz[ibase+1].z-xyz[ibase-1].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; fac= (s[ibase+1] - s[ibase-1]) / del2; gradient[vrt].x = delta.x*fac; gradient[vrt].y = delta.y*fac; gradient[vrt].z = delta.z*fac; /* j-direction */ delta.x= xyz[ibase+nx].x-xyz[ibase-nx].x; delta.y= xyz[ibase+nx].y-xyz[ibase-nx].y; delta.z= xyz[ibase+nx].z-xyz[ibase-nx].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; fac= (s[ibase+nx] - s[ibase-nx]) / del2; gradient[vrt].x += delta.x*fac; gradient[vrt].y += delta.y*fac; gradient[vrt].z += delta.z*fac; /* k-direction */ delta.x= xyz[ibase+sliceSize].x-xyz[ibase-sliceSize].x; delta.y= xyz[ibase+sliceSize].y-xyz[ibase-sliceSize].y; delta.z= xyz[ibase+sliceSize].z-xyz[ibase-sliceSize].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; fac= (s[ibase+sliceSize] - s[ibase-sliceSize]) / del2; gradient[vrt].x += delta.x*fac; gradient[vrt].y += delta.y*fac; gradient[vrt].z += delta.z*fac; grd[ibase]= gradient[vrt]; done[ibase]= 1; } vrt++; ii= i+1; jj= j+1; kk= k; ibase= ii + jj*nx + kk*sliceSize; if(done[ibase]) { gradient[vrt] = grd[ibase]; } else { /* i-direction */ delta.x= xyz[ibase+1].x-xyz[ibase-1].x; delta.y= xyz[ibase+1].y-xyz[ibase-1].y; delta.z= xyz[ibase+1].z-xyz[ibase-1].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; fac= (s[ibase+1] - s[ibase-1]) / del2; gradient[vrt].x = delta.x*fac; gradient[vrt].y = delta.y*fac; gradient[vrt].z = delta.z*fac; /* j-direction */ delta.x= xyz[ibase+nx].x-xyz[ibase-nx].x; delta.y= xyz[ibase+nx].y-xyz[ibase-nx].y; delta.z= xyz[ibase+nx].z-xyz[ibase-nx].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; fac= (s[ibase+nx] - s[ibase-nx]) / del2; gradient[vrt].x += delta.x*fac; gradient[vrt].y += delta.y*fac; gradient[vrt].z += delta.z*fac; /* k-direction */ delta.x= xyz[ibase+sliceSize].x-xyz[ibase-sliceSize].x; delta.y= xyz[ibase+sliceSize].y-xyz[ibase-sliceSize].y; delta.z= xyz[ibase+sliceSize].z-xyz[ibase-sliceSize].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; fac= (s[ibase+sliceSize] - s[ibase-sliceSize]) / del2; gradient[vrt].x += delta.x*fac; gradient[vrt].y += delta.y*fac; gradient[vrt].z += delta.z*fac; grd[ibase]= gradient[vrt]; done[ibase]= 1; } vrt++; ii= i; jj= j+1; kk= k; ibase= ii + jj*nx + kk*sliceSize; if(done[ibase]) { gradient[vrt] = grd[ibase]; } else { /* i-direction */ delta.x= xyz[ibase+1].x-xyz[ibase-1].x; delta.y= xyz[ibase+1].y-xyz[ibase-1].y; delta.z= xyz[ibase+1].z-xyz[ibase-1].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; fac= (s[ibase+1] - s[ibase-1]) / del2; gradient[vrt].x = delta.x*fac; gradient[vrt].y = delta.y*fac; gradient[vrt].z = delta.z*fac; /* j-direction */ delta.x= xyz[ibase+nx].x-xyz[ibase-nx].x; delta.y= xyz[ibase+nx].y-xyz[ibase-nx].y; delta.z= xyz[ibase+nx].z-xyz[ibase-nx].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; fac= (s[ibase+nx] - s[ibase-nx]) / del2; gradient[vrt].x += delta.x*fac; gradient[vrt].y += delta.y*fac; gradient[vrt].z += delta.z*fac; /* k-direction */ delta.x= xyz[ibase+sliceSize].x-xyz[ibase-sliceSize].x; delta.y= xyz[ibase+sliceSize].y-xyz[ibase-sliceSize].y; delta.z= xyz[ibase+sliceSize].z-xyz[ibase-sliceSize].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; fac= (s[ibase+sliceSize] - s[ibase-sliceSize]) / del2; gradient[vrt].x += delta.x*fac; gradient[vrt].y += delta.y*fac; gradient[vrt].z += delta.z*fac; grd[ibase]= gradient[vrt]; done[ibase]= 1; } vrt++; ii= i; jj= j; kk= k+1; ibase= ii + jj*nx + kk*sliceSize; if(done[ibase]) { gradient[vrt] = grd[ibase]; } else { /* i-direction */ delta.x= xyz[ibase+1].x-xyz[ibase-1].x; delta.y= xyz[ibase+1].y-xyz[ibase-1].y; delta.z= xyz[ibase+1].z-xyz[ibase-1].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; fac= (s[ibase+1] - s[ibase-1]) / del2; gradient[vrt].x = delta.x*fac; gradient[vrt].y = delta.y*fac; gradient[vrt].z = delta.z*fac; /* j-direction */ delta.x= xyz[ibase+nx].x-xyz[ibase-nx].x; delta.y= xyz[ibase+nx].y-xyz[ibase-nx].y; delta.z= xyz[ibase+nx].z-xyz[ibase-nx].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; fac= (s[ibase+nx] - s[ibase-nx]) / del2; gradient[vrt].x += delta.x*fac; gradient[vrt].y += delta.y*fac; gradient[vrt].z += delta.z*fac; /* k-direction */ delta.x= xyz[ibase+sliceSize].x-xyz[ibase-sliceSize].x; delta.y= xyz[ibase+sliceSize].y-xyz[ibase-sliceSize].y; delta.z= xyz[ibase+sliceSize].z-xyz[ibase-sliceSize].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; fac= (s[ibase+sliceSize] - s[ibase-sliceSize]) / del2; gradient[vrt].x += delta.x*fac; gradient[vrt].y += delta.y*fac; gradient[vrt].z += delta.z*fac; grd[ibase]= gradient[vrt]; done[ibase]= 1; } vrt++; ii= i+1; jj= j; kk= k+1; ibase= ii + jj*nx + kk*sliceSize; if(done[ibase]) { gradient[vrt] = grd[ibase]; } else { /* i-direction */ delta.x= xyz[ibase+1].x-xyz[ibase-1].x; delta.y= xyz[ibase+1].y-xyz[ibase-1].y; delta.z= xyz[ibase+1].z-xyz[ibase-1].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; fac= (s[ibase+1] - s[ibase-1]) / del2; gradient[vrt].x = delta.x*fac; gradient[vrt].y = delta.y*fac; gradient[vrt].z = delta.z*fac; /* j-direction */ delta.x= xyz[ibase+nx].x-xyz[ibase-nx].x; delta.y= xyz[ibase+nx].y-xyz[ibase-nx].y; delta.z= xyz[ibase+nx].z-xyz[ibase-nx].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; fac= (s[ibase+nx] - s[ibase-nx]) / del2; gradient[vrt].x += delta.x*fac; gradient[vrt].y += delta.y*fac; gradient[vrt].z += delta.z*fac; /* k-direction */ delta.x= xyz[ibase+sliceSize].x-xyz[ibase-sliceSize].x; delta.y= xyz[ibase+sliceSize].y-xyz[ibase-sliceSize].y; delta.z= xyz[ibase+sliceSize].z-xyz[ibase-sliceSize].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; fac= (s[ibase+sliceSize] - s[ibase-sliceSize]) / del2; gradient[vrt].x += delta.x*fac; gradient[vrt].y += delta.y*fac; gradient[vrt].z += delta.z*fac; grd[ibase]= gradient[vrt]; done[ibase]= 1; } vrt++; ii= i+1; jj= j+1; kk= k+1; ibase= ii + jj*nx + kk*sliceSize; if(done[ibase]) { gradient[vrt] = grd[ibase]; } else { /* i-direction */ delta.x= xyz[ibase+1].x-xyz[ibase-1].x; delta.y= xyz[ibase+1].y-xyz[ibase-1].y; delta.z= xyz[ibase+1].z-xyz[ibase-1].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; fac= (s[ibase+1] - s[ibase-1]) / del2; gradient[vrt].x = delta.x*fac; gradient[vrt].y = delta.y*fac; gradient[vrt].z = delta.z*fac; /* j-direction */ delta.x= xyz[ibase+nx].x-xyz[ibase-nx].x; delta.y= xyz[ibase+nx].y-xyz[ibase-nx].y; delta.z= xyz[ibase+nx].z-xyz[ibase-nx].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; fac= (s[ibase+nx] - s[ibase-nx]) / del2; gradient[vrt].x += delta.x*fac; gradient[vrt].y += delta.y*fac; gradient[vrt].z += delta.z*fac; /* k-direction */ delta.x= xyz[ibase+sliceSize].x-xyz[ibase-sliceSize].x; delta.y= xyz[ibase+sliceSize].y-xyz[ibase-sliceSize].y; delta.z= xyz[ibase+sliceSize].z-xyz[ibase-sliceSize].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; fac= (s[ibase+sliceSize] - s[ibase-sliceSize]) / del2; gradient[vrt].x += delta.x*fac; gradient[vrt].y += delta.y*fac; gradient[vrt].z += delta.z*fac; grd[ibase]= gradient[vrt]; done[ibase]= 1; } vrt++; ii= i; jj= j+1; kk= k+1; ibase= ii + jj*nx + kk*sliceSize; if(done[ibase]) { gradient[vrt] = grd[ibase]; } else { /* i-direction */ delta.x= xyz[ibase+1].x-xyz[ibase-1].x; delta.y= xyz[ibase+1].y-xyz[ibase-1].y; delta.z= xyz[ibase+1].z-xyz[ibase-1].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; fac= (s[ibase+1] - s[ibase-1]) / del2; gradient[vrt].x = delta.x*fac; gradient[vrt].y = delta.y*fac; gradient[vrt].z = delta.z*fac; /* j-direction */ delta.x= xyz[ibase+nx].x-xyz[ibase-nx].x; delta.y= xyz[ibase+nx].y-xyz[ibase-nx].y; delta.z= xyz[ibase+nx].z-xyz[ibase-nx].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; fac= (s[ibase+nx] - s[ibase-nx]) / del2; gradient[vrt].x += delta.x*fac; gradient[vrt].y += delta.y*fac; gradient[vrt].z += delta.z*fac; /* k-direction */ delta.x= xyz[ibase+sliceSize].x-xyz[ibase-sliceSize].x; delta.y= xyz[ibase+sliceSize].y-xyz[ibase-sliceSize].y; delta.z= xyz[ibase+sliceSize].z-xyz[ibase-sliceSize].z; del2= delta.x*delta.x+delta.y*delta.y+delta.z*delta.z+1.0e-80; fac= (s[ibase+sliceSize] - s[ibase-sliceSize]) / del2; gradient[vrt].x += delta.x*fac; gradient[vrt].y += delta.y*fac; gradient[vrt].z += delta.z*fac; grd[ibase]= gradient[vrt]; done[ibase]= 1; } vrt++; } yorick-gl-1.1+cvs20070922+dfsg.orig/oglx.c0000640000175000017500000001311710313362503017540 0ustar thibautthibaut/* * $Id: oglx.c,v 1.1.1.1 2005/09/18 22:08:03 dhmunro Exp $ * GL window management for X11, using GLX * for yorick-gl package - this source unused and may be out of date */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #include "config.h" #include "pstdlib.h" #include "playwin.h" #include "playgl.h" #include /* during debug, generate as many Expose events as possible */ #ifndef P_DEBUG # define BACKING_STORE WhenMapped #else # define BACKING_STORE NotUseful #endif static p_glwin *gl_winlist = 0; struct p_glwin { void *context; /* must match p_win struct member */ p_glwin* next; p_scr *s; p_win *parent; int offscreen; Drawable d; Colormap cmap; GLXContext glx; XVisualInfo *v; int error_base, event_base; }; static int pgl_attrib[] = { GLX_DOUBLEBUFFER, GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_DEPTH_SIZE, 1, None }; /* visual debugging: * * int status, value; XVisualInfo *v; * status = glXGetConfig(dpy, v, GLX_USE_GL, &value); * bad if (status==GLX_NO_EXTENSION || status==GLX_BAD_VISUAL || !value) * glXGetConfig(dpy, v, property, &value); * where property is * GLX_BUFFER_SIZE, GLX_LEVEL, GLX_RGBA, GLX_DOUBLEBUFFER, GLX_STEREO, * GLX_AUX_BUFFERS, GLX_DEPTH_SIZE, GLX_STENCIL_SIZE, * GLX_RED_SIZE, GLX_GREEN_SIZE, GLX_BLUE_SIZE, GLX_ALPHA_SIZE, * GLX_ACCUM_RED_SIZE, GLX_ACCUM_GREEN_SIZE, GLX_ACCUM_BLUE_SIZE, * GLX_ACCUM_ALPHA_SIZE * * xdpyinfo utility is also useful */ extern int p_glvid_force; /* set to force this visualid, 0 to choose best */ int p_glvid_force = 0; extern int p_glvid_using; /* p_glcreate sets to actual visualid */ int p_glvid_using = 0; p_glwin * p_glcreate(p_win *parent, int width, int height, int x, int y, void *ctx) { p_scr *s = parent->s; Display *dpy = s->xdpy->dpy; XVisualInfo *v; Colormap cmap = None; int error_base, event_base; p_glwin *w, *cousin = gl_winlist; while (cousin && cousin->s!=s) cousin = cousin->next; if (!cousin) { if (!glXQueryExtension(dpy, &error_base, &event_base)) return 0; if (!p_glvid_force) { v = glXChooseVisual(dpy, s->scr_num, pgl_attrib); } else { XVisualInfo vreq; int n; vreq.screen = s->scr_num; vreq.visualid = p_glvid_force; v = XGetVisualInfo(dpy, (VisualScreenMask | VisualIDMask), &vreq, &n); } if (!v) return 0; } else { error_base = cousin->error_base; event_base = cousin->event_base; cmap = cousin->cmap; v = cousin->v; } p_glvid_using = v->visualid; w = p_malloc(sizeof(p_glwin)); if (!w) return 0; w->context = ctx; w->s = s; w->parent = parent; w->error_base = error_base; w->event_base = event_base; w->v = v; /* go ahead and install rgb-model 5x9x5 palette GLX can use */ if (s->vclass==PseudoColor) x_rgb_palette(parent); if (v->visualid==XVisualIDFromVisual(DefaultVisual(dpy,s->scr_num))) { cmap = parent->parent? parent->parent->cmap : parent->cmap; if (cmap==None) cmap = DefaultColormap(dpy, s->scr_num); w->cmap = None; } else if (cmap==None) { w->cmap = cmap = XCreateColormap(dpy, RootWindow(dpy,s->scr_num), v->visual, AllocNone); } else { w->cmap = cmap; } w->offscreen = (parent->parent!=0); if (!w->offscreen) { XSetWindowAttributes attr; attr.colormap = cmap; attr.backing_store = BACKING_STORE; w->d = XCreateWindow( dpy, parent->d, x, y, width, height, 0, v->depth, InputOutput, v->visual, CWColormap | CWBackingStore, &attr ); if (w->d) { /* let all events propagate to parent window * -- except expose cannot propagate */ XSelectInput(dpy, w->d, ExposureMask); if (p_hinsert(s->xdpy->id2pwin, P_IHASH(w->d), w)) { XDestroyWindow(dpy, w->d); w->d = None; } else { XMapWindow(dpy, w->d); } } } else { #ifndef USE_MESA_PIXMAPS w->d = glXCreateGLXPixmap(dpy, v, parent->d); #else w->d = glXCreateGLXPixmapMESA(dpy, v, parent->d, cmap); #endif } w->glx = (w->d!=None)? glXCreateContext(dpy, v, cousin?cousin->glx:0, True) : 0; if (!w->glx) { p_free(w); return 0; } w->next = gl_winlist; gl_winlist = w; return w; } void p_gldestroy(p_glwin *w) { if (w) { p_glwin *list = gl_winlist; if (list==w) { gl_winlist = w->next; } else while (list) { if (list->next==w) { list->next = w->next; break; } list = list->next; } if (w->cmap != None) { Colormap cmap = w->cmap; w->cmap = None; for (list=gl_winlist ; list ; list=list->next) { if (list->s==w->s && list->cmap==cmap) { cmap = None; break; } } if (cmap != None) XFreeColormap(w->s->xdpy->dpy, cmap); } glXDestroyContext(w->s->xdpy->dpy, w->glx); if (w->offscreen) glXDestroyGLXPixmap(w->s->xdpy->dpy, w->d); else XDestroyWindow(w->s->xdpy->dpy, w->d); } } void p_glresize(p_glwin *w, int width, int height, int x, int y) { if (w && !w->parent->parent) XMoveResizeWindow(w->s->xdpy->dpy, w->d, x, y, width, height); } void p_glswap(p_glwin *w) { glXSwapBuffers(w->s->xdpy->dpy, w->d); p_flush(w->parent); } void p_glcurrent(p_glwin *w) { glXMakeCurrent(w->s->xdpy->dpy, w->d, w->glx); } yorick-gl-1.1+cvs20070922+dfsg.orig/glcode.h0000640000175000017500000001243210515710063020032 0ustar thibautthibaut/* * $Id: glcode.h,v 1.2 2006/10/19 14:48:19 dhmunro Exp $ * Declarations for external OpenGL module. These functions are * defined in glcode.c and are called appropriately by the CView * derived classes. */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #ifndef __GLCODE__ #define __GLCODE__ #ifdef WIN32 /* WARNING: It appears that must be included before . !!!! */ #include /* #include */ #endif #include "dlist3d.h" #include "play.h" #include "playgl.h" #ifdef MACINTOSH #include #else #include #endif #ifdef __cplusplus extern "C" { #endif extern int alpha_pass; typedef struct g_callbacks g_callbacks; struct g_callbacks { char *name; void (*gl_on_expose)(void *c, int *xy); void (*gl_on_destroy)(void *c); void (*gl_on_resize)(void *c,int w,int h); void (*gl_on_focus)(void *c,int in); void (*gl_on_key)(void *c,int k,int md); void (*gl_on_click)(void *c,int b,int md,int x,int y, unsigned long ms); void (*gl_on_motion)(void *c,int md,int x,int y); void (*gl_on_deselect)(void *c); } ; typedef struct glInnerWinProp glInnerWinProp; struct glInnerWinProp { g_callbacks *on; struct glWinProp *topwin; } ; #ifdef WIN32 typedef void (APIENTRY *MYTEX3DFUNC) (GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels ); #else typedef int MYTEX3DFUNC; #endif typedef void (*glBindTextureProc)(GLenum target, GLint level); typedef struct glWinProp glWinProp; struct glWinProp { g_callbacks *on; struct glInnerWinProp *inner; char *name; glInnerWinProp innerWin; p_glwin *gl_win; p_win *top_win; p_scr *s; int dirty; float back_red, back_green, back_blue, back_alpha; /* The "cage" is the three coord. planes at the "back" of the scene as viewed from the current viewpoint. The planes have one color and the grid lines another. The planes are chosen from (xmin,xmax), (ymin,ymax), and (zmin,zmax) pairs. If cage_style is negative, these planes will be the limits of the data, if positive, they will be values set by the user, if zero no cage will be drawn. */ float cage_red, cage_green, cage_blue, cage_alpha; float grid_red, grid_green, grid_blue, grid_alpha; float cage_xmin, cage_xmax, cage_ymin, cage_ymax; float cage_zmin, cage_zmax; long cage_style; int num_xgrid, num_ygrid, num_zgrid; long cage_seq_num; long cage_state; /* Lighting components */ GLfloat ambientLight[4]; GLfloat diffuseLight[4]; GLfloat specularLight[4]; /* if the last parameter is zero, the light is at infinity */ GLfloat positionLight[4]; GLint light_model; GLfloat mat_spec; GLint shade_model; GLint cull_mode; GLint poly_sides; GLint poly_mode; GLint mat_color; /* parameters describing the color of the light */ GLfloat curr_ambient[4]; GLfloat curr_diffuse[4]; GLfloat curr_specular[4]; /* if the last parameter is zero, the light is at infinity */ GLfloat curr_position[4]; GLint curr_light_model; /* current specular color */ GLfloat curr_mat_spec[4]; GLint curr_shade_model; GLint curr_cull_mode; GLint curr_poly_sides; GLint curr_poly_mode; GLint curr_mat_color; double eye[3]; double center[3]; double up[3]; double view[3]; double viewdist; float fov; long width, hite; float curr_alpha; int have_gl_list, the_gl_list, always_show_obj, object_on; int cursor_action; long use_list; long use_array; long seq_num; long list_num; yBox3D boxAll; long BoxSeqNum; int hascubetex, hasTex3d, hasTex3dExt, hasTexExt, tex3dChecked; MYTEX3DFUNC myglTexImage3D_ptr; int myGL_TEXTURE_3D, myGL_PROXY_TEXTURE_3D; glBindTextureProc myglBindTexture3D; }; void yglInitRC(void *pData); void yglResize(glWinProp *theWin3d, GLsizei h, GLsizei w); void draw_plane(float pt1[3], float pt2[3], float pt3[3], int num1, int num2); void yglWireSphere(int list_num, double radius); void yglForceUpdateLight(void); void yglUpdateLight(void); void yglUpdateProperties(void); void yglForceUpdateProperties(void); void yglChekError(char *x); int yglNewList(void); int yglCloseList(void); int yglDrawList(int num); int yglDeleteList(int num); int yglArrlim3D(long nvert, double *arr, double *lims); extern glWinProp *glCurrWin3d; void yglInitWin3d(glWinProp *theWin); /* provide GLU wrappers (see glustub.c) */ #undef gluLookAt #define gluLookAt my_gluLookAt #undef gluPerspective #define gluPerspective my_gluPerspective #undef gluErrorString #define gluErrorString my_gluErrorString void gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez, GLdouble centerx, GLdouble centery, GLdouble centerz, GLdouble upx, GLdouble upy, GLdouble upz); void gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble near, GLdouble far); const GLubyte *gluErrorString(GLenum errorCode); #ifdef __cplusplus } #endif /* Easier way to specify color for Windows bigots */ #define yglRGB(x, y, z) glColor3ub((GLubyte)x, (GLubyte)y, (GLubyte)z) #endif /* Include/Define */ yorick-gl-1.1+cvs20070922+dfsg.orig/glx11setup.c0000640000175000017500000003714210411132435020606 0ustar thibautthibaut/* * $Id: glx11setup.c,v 1.2 2006/03/25 03:12:29 dhmunro Exp $ */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #include "glcode.h" #include "glfunc.h" #include "glMouse.h" #include "glBasic.h" #include "binio.h" #include "pstdlib.h" #include extern void g_disconnect(p_scr *s); extern int p_wincount(p_scr *s); static void gl_on_expose(void *c, int *xy); static void gl_on_destroy(void *c); static void gl_on_resize(void *c,int w,int h); static void gl_on_focus(void *c,int in); static void gl_on_key(void *c,int k,int md); static void gl_on_click(void *c,int b,int md,int x,int y, unsigned long ms); static void gl_on_motion(void *c,int md,int x,int y); static void gl_on_deselect(void *c); extern void MySwapBuffers(void); extern void yglInitlights(void); #if 0 extern void myReshape(int w, int h); #endif extern void yglInitRC(void *pData); extern void ygl_update_3d(void); extern int the_gl_list; static int ygl_mouse_pos_x= 0; static int ygl_mouse_pos_y= 0; static int ygl_mouse_is_down= 0; static int scr_no_win= 0; glWinProp *glCurrWin3d= 0; glWinProp *glWin3dList[8]; /* ------------------------------------------------------------------------ */ extern void (*g_on_keyline)(char *msg); /* gist/xfancy.c */ static char my_msg[96]; static int my_msglen = 0; static g_callbacks gl_x11_on = { "GL top level", 0, gl_on_destroy, gl_on_resize, gl_on_focus, gl_on_key, gl_on_click, gl_on_motion, gl_on_deselect }; static g_callbacks gl_glx_on = { "GL window", gl_on_expose, 0, 0, 0, 0, 0, 0, 0 }; int yglWin3d(int num, int w, int h) { int i; glWinProp *res; char titlstr[80]; if(!glCurrWin3d) { /* make sure the list of window pointers is empty */ for(i= 0; i <= 7; i++) glWin3dList[i]= 0; } if(num < 0 || num > 7) return 1; /* bad window number */ if(glWin3dList[num]) { /* change the current window */ glCurrWin3d= glWin3dList[num]; } else { /* create a new 3D window */ sprintf(titlstr, "3D window %d", num); res= yglMakWin(0, w, h, titlstr); if(!res) { /* failed to create the 3D window */ return 2; } /* reserve an OpenGL display list for this window */ glCurrWin3d->the_gl_list = glGenLists(1); glWin3dList[num]= glCurrWin3d; } return 0; /* indicate success */ } int yglWinKill3d(int num) { glWinProp *theWin3d; if(num < 0 || num > 7) return 1; /* bad window number */ if(glWin3dList[num]) { theWin3d= glWin3dList[num]; shutdown3d(theWin3d); glWin3dList[num]= 0; /* update the current 3D window only if necessary */ if(glCurrWin3d == theWin3d) resetcurrwin3d(); } else { /* tried to delete a non-existent 3D window */ return 2; } return 0; /* indicate success */ } int isWin3d(glWinProp *win) { /* return 1 if this is the top level window for a 3D "canvas" */ if(win && win->on == &gl_x11_on) return 1; /* return 2 if this is the glx window for a 3D "canvas" */ if(win && win->on == &gl_glx_on) return 2; return 0; } int yglCurrWin3d(void) { int i; for(i= 0; i <= 7; i++) { if(glWin3dList[i] == glCurrWin3d) { return i; } } return 0; } glWinProp *yglMakWin(char *displayName, int w, int h, char *title) { p_glwin *gl_win = 0; p_win *top_win = 0; extern p_scr *g_connect(char *displayName); /* gist/xbasic.h */ extern int gist_input_hint; glWinProp *theWin3d; glWinProp *oldWin3d= glCurrWin3d; glInnerWinProp *theInner; p_scr *scr_gl; scr_gl = g_connect(displayName); if (!scr_gl) return 0; theWin3d= (glWinProp *) p_malloc(sizeof(glWinProp)); if(!theWin3d) return 0; theInner= &(theWin3d->innerWin); theWin3d->inner= theInner; theWin3d->on= &gl_x11_on; theWin3d->s= scr_gl; theInner->topwin= theWin3d; theInner->on= &gl_glx_on; yglInitWin3d(theWin3d); glCurrWin3d= theWin3d; top_win = p_window(scr_gl, w, h, title, P_BG, (gist_input_hint?0:P_NOKEY) | P_RGBMODEL, theWin3d); if (!top_win) { glCurrWin3d= oldWin3d; p_free(theWin3d); return 0; } gl_win = p_glcreate(top_win, w, h, 0, 0, theInner); if (!gl_win) { p_win *w = top_win; glCurrWin3d= oldWin3d; top_win = 0; p_destroy(w); p_free(theWin3d); return 0; } theWin3d->gl_win= gl_win; theWin3d->top_win= top_win; theWin3d->width= w; theWin3d->hite= h; /* Finish Set-up */ p_glcurrent(gl_win); yglInitRC(0); return theWin3d; } int shutdown3d(glWinProp *theWin3d) { int num; p_glwin *wg = theWin3d->gl_win; p_win *topwin = theWin3d->top_win; p_scr *s; if(isWin3d(theWin3d) != 1) { /* should never see anything but a top level window for the 3D canvas, so return */ return -1; } /* set a flag indicating that there are (for the moment) no connections to this display */ /* s= (theWin3d->top_win)->s; */ s= theWin3d->s; if (s && !p_wincount(s)) scr_no_win= 1; num= winnum3d(theWin3d); if(num < 0) { /* unknown window, so do nothing */ return -2; } theWin3d->top_win = 0; theWin3d->dirty= 0; /* stop any redraw attempts */ if (wg) p_gldestroy(wg); theWin3d->gl_win = 0; if (topwin) p_destroy(topwin); /* In Windows, the 3D window might have been destroyed by an asynchronous on_destroy() triggered by the p_gldestroy() call. Protect against a double free() */ p_free(theWin3d); glWin3dList[num]= 0; return 0; /* indicate success */ } void resetcurrwin3d(void) { int i; glCurrWin3d= 0; /* indicate no 3D window left */ for(i= 7; i >= 0; i--) { if(glWin3dList[i]) { glCurrWin3d= glWin3dList[i]; break; } } } int winnum3d(glWinProp *theWin3d) { int i; for(i= 7; i >= 0; i--) { if(glWin3dList[i] == theWin3d) { return i; } } return -1; /* indicate not found */ } void MySwapBuffers(void) { if (glCurrWin3d && glCurrWin3d->gl_win) p_glswap(glCurrWin3d->gl_win); } void yglMakeCurrent(glWinProp *theWin3d) { if (theWin3d && theWin3d->gl_win) p_glcurrent(theWin3d->gl_win); } void yglInitWin3d(glWinProp *theWin) { theWin->name= 0; theWin->gl_win= 0; theWin->top_win= 0; theWin->dirty= 0; theWin->back_red= 0.0f; theWin->back_green= 0.3f; theWin->back_blue= 0.8f; theWin->back_alpha= 1.0f; theWin->cage_red= 0.3f; theWin->cage_green= 0.3f; theWin->cage_blue= 0.6f; theWin->cage_alpha= 1.0f; theWin->grid_red= 0.5f; theWin->grid_green= 0.5f; theWin->grid_blue= 0.3f; theWin->grid_alpha= 1.0f; theWin->cage_xmin= 0.0; theWin->cage_xmax= 1.0; theWin->cage_ymin= 0.0; theWin->cage_ymax= 1.0; theWin->cage_zmin= 0.0; theWin->cage_zmax= 1.0; theWin->cage_style= 0; theWin->num_xgrid= 3; theWin->num_ygrid=3; theWin->num_zgrid= 3; /* Lighting components */ theWin->ambientLight[0]= 0.2f; theWin->ambientLight[1]= 0.2f; theWin->ambientLight[2]= 0.2f; theWin->ambientLight[3]= 1.0f; theWin->diffuseLight[0]= 0.6f; theWin->diffuseLight[1]= 0.6f; theWin->diffuseLight[2]= 0.6f; theWin->diffuseLight[3]= 1.0f; theWin->specularLight[0]= 1.0f; theWin->specularLight[1]= 1.0f; theWin->specularLight[2]= 1.0f; theWin->specularLight[3]= 1.0f; /* if the last parameter is zero, the light is at infinity */ theWin->positionLight[0]= 0.0f; theWin->positionLight[1]= 0.0f; theWin->positionLight[2]= 1.0f; theWin->positionLight[3]= 0.0f; theWin->light_model= GL_TRUE; theWin->mat_spec= 1.0f; theWin->shade_model= GL_SMOOTH; theWin->cull_mode= 0; theWin->poly_sides= GL_FRONT_AND_BACK; theWin->poly_mode= GL_FILL; theWin->mat_color= GL_AMBIENT_AND_DIFFUSE; /* parameters describing the color of the light */ theWin->curr_ambient[0]= 0.2f; theWin->curr_ambient[1]= 0.2f; theWin->curr_ambient[2]= 0.2f; theWin->curr_ambient[3]= 1.0f; theWin->curr_diffuse[0]= 0.6f; theWin->curr_diffuse[1]= 0.6f; theWin->curr_diffuse[2]= 0.6f; theWin->curr_diffuse[3]= 1.0f; theWin->curr_specular[0]= 1.0f; theWin->curr_specular[1]= 1.0f; theWin->curr_specular[2]= 1.0f; theWin->curr_specular[3]= 1.0f; /* if the last parameter is zero, the light is at infinity */ theWin->curr_position[0]= 0.0f; theWin->curr_position[1]= 0.0f; theWin->curr_position[2]= 1.0f; theWin->curr_position[3]= 0.0f; theWin->curr_light_model= GL_TRUE; /* current specular color */ theWin->curr_mat_spec[0]= 1.0f; theWin->curr_mat_spec[1]= 1.0f; theWin->curr_mat_spec[2]= 1.0f; theWin->curr_mat_spec[3]= 1.0f; theWin->curr_shade_model= GL_SMOOTH; theWin->curr_cull_mode= 0; theWin->curr_poly_sides= GL_FRONT_AND_BACK; theWin->curr_poly_mode= GL_FILL; theWin->curr_mat_color= GL_AMBIENT_AND_DIFFUSE; theWin->eye[0]= 10.0; theWin->eye[1]= 0.0; theWin->eye[2]= 0.0; theWin->center[0]= 0.0; theWin->center[1]= 0.0; theWin->center[2]= 0.0; theWin->up[0]= 0.0; theWin->up[1]= 0.0; theWin->up[2]= 1.0; theWin->view[0]= 1.0; theWin->view[1]= 0.0; theWin->view[2]= 0.0; theWin->viewdist= 10.0; theWin->fov= 35.0; theWin->width=500; theWin->hite=500; theWin->curr_alpha=0.5; theWin->have_gl_list= 0; theWin->use_list= 1; theWin->use_array= 0; theWin->seq_num= 0; theWin->list_num= -1; theWin->cage_seq_num= 0; theWin->cage_state= -1; theWin->cursor_action= ACTION_ROTATE; theWin->BoxSeqNum= -1; theWin->tex3dChecked= 0; theWin->hasTex3d= 0; theWin->hasTex3dExt= 0; theWin->myglTexImage3D_ptr= 0; theWin->myGL_TEXTURE_3D= 0; theWin->myGL_PROXY_TEXTURE_3D= 0; theWin->myglBindTexture3D= 0; theWin->hascubetex= -1; theWin->hasTexExt= 0; } void ygl_update_3d(void) { int i; /* check 3D windows for dirty bits and redraw as needed */ if(scr_no_win) { /* on X11 systems, need to disconnect from the display when there are no longer any open windows on it */ g_disconnect(0); scr_no_win= 0; } for(i= 0; i <= 7; i++) { if(glWin3dList[i]) { /* Need to draw the window if an event like a mouse action, an expose or a redraw occurred. Also need to draw if yorgl's display list has been altered. */ if(glWin3dList[i]->dirty || (glWin3dList[i]->seq_num > glWin3dList[i]->list_num) ) { yglDraw3d(glWin3dList[i]); } } } } static void gl_on_expose(void *c, int *xy) { glWinProp *theWin3d; glInnerWinProp *theInner= (glInnerWinProp *)c; if(isWin3d((glWinProp *)theInner) != 2) { /* only need to respond to expose events on the inner window */ return; } theWin3d= theInner->topwin; theWin3d->dirty= 1; } static void gl_on_destroy(void *c) { glWinProp *theWin3d= (glWinProp *)c; if(isWin3d(theWin3d) != 1) { /* should never see anything but a top level window for the 3D canvas, so return */ return; } shutdown3d(theWin3d); /* update the current 3D window only if necessary */ if(glCurrWin3d == theWin3d) resetcurrwin3d(); } static void gl_on_resize(void *c,int w,int h) { glWinProp *theWin3d= (glWinProp *)c; if(isWin3d(theWin3d) != 1) { /* should never see anything but a top level window for the 3D canvas, so return */ return; } if (theWin3d->gl_win) { yglResize(theWin3d, w, h); theWin3d->dirty= 1; } } static void gl_on_focus(void *c,int in) { /* nothing to do */ } static void gl_on_deselect(void *c) { /* nothing to do */ } #undef DBG_MOUSE #ifdef DBG_MOUSE #include "play.h" static mouse_count= 0; static char msg_buf[120]; #endif /* b=1 left b=2 middle b=3 right */ static void gl_on_click(void *c,int b,int md,int x,int y, unsigned long ms) { glWinProp *theWin3d= (glWinProp *)c; glWinProp *oldWin3d= glCurrWin3d; if(isWin3d(theWin3d) != 1) { /* should never see anything but a top level window for the 3D canvas, so return */ return; } if (!theWin3d->gl_win) return; oldWin3d= glCurrWin3d; glCurrWin3d= theWin3d; if (md & (1<<(b+2))) { #ifdef DBG_MOUSE sprintf(msg_buf, "Mouse released. %d motion events while down\n", mouse_count); p_stdout(msg_buf); #endif DoLButtonUp(ygl_mouse_is_down, x, y, theWin3d); ygl_mouse_is_down = 0; } else if (!ygl_mouse_is_down) { #ifdef DBG_MOUSE mouse_count= 0; p_stdout("Mouse button pressed\n"); #endif if (b==1) { if (md & P_SHIFT) b = 3; else if (md & P_CONTROL) b = 2; } ygl_mouse_is_down = b; DoLButtonDown(b, x, y); if (!glCurrWin3d->always_show_obj) glCurrWin3d->object_on= 0; } glCurrWin3d= oldWin3d; } static void gl_on_motion(void *c,int md,int x,int y) { glWinProp *theWin3d= (glWinProp *)c; glWinProp *oldWin3d= glCurrWin3d; if(isWin3d(theWin3d) != 1) { /* should never see anything but a top level window for the 3D canvas, so return */ return; } if (!theWin3d->gl_win) return; #ifdef DBG_MOUSE mouse_count++; #endif ygl_mouse_pos_x = x; ygl_mouse_pos_y = y; /* IGNORE mouse motion unless the left button is down */ if (ygl_mouse_is_down) { /* carry out any necessary rotation */ oldWin3d= glCurrWin3d; glCurrWin3d= theWin3d; yglMouseMove(ygl_mouse_is_down, x, y, theWin3d); glCurrWin3d= oldWin3d; } } static void gl_on_key(void *c,int k,int md) { glWinProp *theWin3d= (glWinProp *)c; if(isWin3d(theWin3d) != 1) { /* should never see anything but a top level window for the 3D canvas, so return */ return; } if (!theWin3d->gl_win) return; if (!my_msglen) my_msg[0] = '\0'; if (k>=' ' && k<'\177') { /* append printing characters */ if (my_msglen>=94) my_msglen = 0; /* crude overflow handling */ my_msg[my_msglen++] = k; my_msg[my_msglen] = '\0'; } else if (k=='\177' || k=='\010') { /* delete or backspace kills char */ if (my_msglen) my_msg[--my_msglen] = '\0'; } else if (k=='\027') { /* C-w kills word */ int n = my_msglen; char c = n? my_msg[n-1] : '\0'; if (c<'0' || (c>'9' && c<'A') || (c>'Z' && c<'a' && c!='_') || c>'z') { if (my_msglen) my_msg[--my_msglen] = '\0'; } else { while (--n) { c = my_msg[n-1]; if (c<'0' || (c>'9' && c<'A') || (c>'Z' && c<'a' && c!='_') || c>'z') break; } my_msg[n] = '\0'; my_msglen = n; } } else if (k=='\025') { /* C-u kills line */ my_msg[0] = '\0'; my_msglen = 0; } else if (k=='\012' || k=='\015') { /* linefeed or carriage return sends line to interpreter */ int n = my_msglen; my_msg[n] = '\012'; my_msg[n+1] = '\0'; p_stdout(my_msg); my_msg[n] = '\0'; if (g_on_keyline) g_on_keyline(my_msg); my_msg[0] = '\0'; my_msglen = 0; } /* RedrawMessage(fxe); no feedback for now */ } void yglInitlights(void) { GLfloat ambient[] = { 0.2f, 0.2f, 0.2f, 1.0f }; GLfloat position[] = { 0.0, 0.0, 2.0, 1.0 }; GLfloat mat_diffuse[] = { 0.6f, 0.6f, 0.6f, 1.0f }; GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat mat_shininess[] = { 50.0 }; glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); glLightfv(GL_LIGHT0, GL_POSITION, position); #if 0 glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess); #else glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess); #endif } #if 0 void myReshape(int w, int h) { if(w < 20) w= 20; if(h < 20) h= 20; glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (w <= h) glOrtho(-4.0, 4.0, -4.0*(GLfloat)h/(GLfloat)w, 4.0*(GLfloat)h/(GLfloat)w, -4.0, 4.0); else glOrtho(-4.0*(GLfloat)w/(GLfloat)h, 4.0*(GLfloat)w/(GLfloat)h, -4.0, 4.0, -4.0, 4.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glCurrWin3d->width= w; glCurrWin3d->hite= h; } #endif yorick-gl-1.1+cvs20070922+dfsg.orig/TriUtil.c0000640000175000017500000004707710515710063020201 0ustar thibautthibaut/* * $Id: TriUtil.c,v 1.3 2006/10/19 14:48:19 dhmunro Exp $ * This file contains utility functions for manipulating lists * of triangle arrays and strips */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #include #include #include "TriStruct.h" #include "glWrappers.h" #include "glcode.h" #include "glfunc.h" #include "pstdlib.h" typedef struct entry entry; struct entry { double val; long ndx; } ; extern void myqsort(entry v[], long left, long right); long yglSizeTriArraysNdx3d(TriVertexGrp *list) { long numtri; /* This function returns the number of triangles in a list of triangle arrays. */ numtri= 0; while(list) { numtri += list->numTri; list= list->next; } /* Return the number of triangles summed over everything in the list. */ return numtri; } void yglCopyTriArrayNdx3d( TriVertexGrp *list, TriVertexGrp *nlist) { long i, numtri, numpt, *oldIDs, *newIDs, *oldNdx, *newNdx; yPoint3D *oldVert, *newVert, *oldNorm, *newNorm; double *oldVar2, *newVar2; /* This function copies a triangle array into another triangle array. WARNING!!! it does not copy coolors!!!!!. The caller guarantees that there is enough room in nlist to store all the triangles in list */ newVert= nlist->xyzverts; newNorm= nlist->normals; newIDs= nlist->cellIDs; newVar2= nlist->var2; newNdx= nlist->ptndx; oldVert= list->xyzverts; oldNorm= list->normals; oldIDs= list->cellIDs; oldVar2= list->var2; oldNdx= list->ptndx; numtri= list->numTri; numpt= list->numEdg; for(i=0; i < numtri; i++) { newNdx[0]= oldNdx[0]; newNdx[1]= oldNdx[1]; newNdx[2]= oldNdx[2]; newNdx += 3; oldNdx += 3; } for(i=0; i < numpt; i++) { newVert[0]= oldVert[0]; newVert[1]= oldVert[1]; newVert[2]= oldVert[2]; newVert += 3; oldVert += 3; newNorm[0]= oldNorm[0]; newNorm[1]= oldNorm[1]; newNorm[2]= oldNorm[2]; newNorm += 3; oldNorm += 3; if(oldVar2) { newVar2[0] = oldVar2[0]; newVar2[1] = oldVar2[1]; newVar2[2] = oldVar2[2]; oldVar2 += 3; newVar2 += 3; } *newIDs++ = *oldIDs++; } } void yglCollapseTriArraysNdx3d(long colrtyp, TriVertexGrp *list, TriVertexGrp *nlist) { long i, count, nedg, comp4, colrskip, numtri, ptbase; long *oldIDs, *newIDs, *oldNdx, *newNdx; yPoint3D *oldVert, *newVert, *oldNorm, *newNorm; float *oldColr, *newColr; double *oldVar2, *newVar2; /* This function merges a list of triangle arrays into a single triangle array. abs(colrtyp) is 3 for RGB colors and 4 for RGBA. if colrtyp<0, the input list has scalar colors. The caller guarantees that there is enough room in nlist to store all the triangles in list */ newVert= nlist->xyzverts; newNorm= nlist->normals; newColr= nlist->colors; newIDs= nlist->cellIDs; newVar2= nlist->var2; newNdx= nlist->ptndx; if(colrtyp < 0) { colrskip= 0; if(colrtyp == -4) comp4= 1; else comp4= 0; } else { colrskip= colrtyp; if(colrtyp == 4) comp4= 1; else comp4= 0; } numtri= 0; ptbase= 0; while(list) { oldVert= list->xyzverts; oldNorm= list->normals; oldColr= list->colors; oldIDs= list->cellIDs; oldVar2= list->var2; oldNdx= list->ptndx; count= list->numTri; nedg= list->numEdg; numtri += count; for(i=0; i < count; i++) { /* the vertices for this tri array will be stored after the ones for all previous arrays, so the indices must be adjusted. */ newNdx[0]= oldNdx[0]+ptbase; newNdx[1]= oldNdx[1]+ptbase; newNdx[2]= oldNdx[2]+ptbase; newNdx += 3; oldNdx += 3; } for(i=0; i < nedg; i++) { newVert[0]= oldVert[0]; newVert[1]= oldVert[1]; newVert[2]= oldVert[2]; newVert += 3; oldVert += 3; newNorm[0]= oldNorm[0]; newNorm[1]= oldNorm[1]; newNorm[2]= oldNorm[2]; newNorm += 3; oldNorm += 3; newColr[0]= oldColr[0]; newColr[1]= oldColr[1]; newColr[2]= oldColr[2]; if(comp4) { newColr[3]= oldColr[3]; newColr += 4; } else { newColr += 3; } oldColr += colrskip; if(oldVar2) { newVar2[0] = oldVar2[0]; newVar2[1] = oldVar2[1]; newVar2[2] = oldVar2[2]; oldVar2 += 3; newVar2 += 3; } *newIDs++ = *oldIDs++; } ptbase += nedg; list= list->next; } nlist->numTri= numtri; nlist->numEdg= ptbase; } void yglDoSortTriNdx3d(TriVertexGrp *oldtri, long *newptndx) { entry *dist; double view[3], viewlen; yPoint3D *oldxyz; long *oldndx, i, ntri, ndx, base, pt0, pt1, pt2;; /* This function performs a depth sort of a triangle array. It uses the current viewpoint. The CALLER is responsible for inserting the new point indices into the triangle array (because the input tri array uses indices into coord, normal, etc. arrays, only the indices must be changed). The resulting triangle array should display correctly with translucency when viewed with this viewing transform. Rotating the scene may lead to incorrect results if the triangles are translucent. newptndx must be of length at least 3*ntri. */ view[0]= glCurrWin3d->eye[0] - glCurrWin3d->center[0]; view[1]= glCurrWin3d->eye[1] - glCurrWin3d->center[1]; view[2]= glCurrWin3d->eye[2] - glCurrWin3d->center[2]; viewlen= 1.0e-80+sqrt(view[0]*view[0]+view[1]*view[1]+view[2]*view[2]); view[0] /= viewlen; view[1] /= viewlen; view[2] /= viewlen; /* compute the average z-depth of the three vertices of each triangle */ ntri= oldtri->numTri; oldxyz= oldtri->xyzverts; oldndx= oldtri->ptndx; dist= (entry *) p_malloc(ntri*sizeof(entry)); for(i= 0; i < ntri; i++) { dist[i].ndx= i; base= 3*i; pt0= oldndx[base]; pt1= oldndx[base+1]; pt2= oldndx[base+2]; /* this uses coords that are on average a factor of 3 too large, but that doesn't affect the sort order */ dist[i].val= view[0]*(oldxyz[pt0].x+oldxyz[pt1].x+oldxyz[pt2].x) +view[1]*(oldxyz[pt0].y+oldxyz[pt1].y+oldxyz[pt2].y) +view[2]*(oldxyz[pt0].z+oldxyz[pt1].z+oldxyz[pt2].z); } /* save new triangle order that sorts the polygons from smallest z to largest z */ for(i= 0; i < ntri; i++) { ndx= 3*(dist[i].ndx); base= 3*i; newptndx[base]= oldndx[ndx]; newptndx[base+1]= oldndx[ndx+1]; newptndx[base+2]= oldndx[ndx+2]; } p_free(dist); } long yglSizeTriArrays3d(TriArrayGrp *list) { long numtri; /* This function returns the number of triangles in a list of triangle arrays. */ numtri= 0; while(list) { numtri += list->numTri; list= list->next; } /* Return the number of triangles summed over everything in the list. */ return numtri; } void yglCopyTriArray3d(long numtri, TriArrayGrp *list, TriArrayGrp *nlist) { long i, *oldIDs, *newIDs; yPoint3D *oldVert, *newVert, *oldNorm, *newNorm; double *oldVar2, *newVar2; /* This function copies a triangle array into another triangle array. WARNING!!! it does not copy coolors!!!!!. The caller guarantees that there is enough room in nlist to store all the triangles in list */ newVert= nlist->xyzverts; newNorm= nlist->normals; newIDs= nlist->cellIDs; newVar2= nlist->var2; oldVert= list->xyzverts; oldNorm= list->normals; oldIDs= list->cellIDs; oldVar2= list->var2; for(i=0; i < numtri; i++) { newVert[0]= oldVert[0]; newVert[1]= oldVert[1]; newVert[2]= oldVert[2]; newVert += 3; oldVert += 3; newNorm[0]= oldNorm[0]; newNorm[1]= oldNorm[1]; newNorm[2]= oldNorm[2]; newNorm += 3; oldNorm += 3; if(oldVar2) { newVar2[0] = oldVar2[0]; newVar2[1] = oldVar2[1]; newVar2[2] = oldVar2[2]; oldVar2 += 3; newVar2 += 3; } *newIDs++ = *oldIDs++; } } void yglCollapseTriArrays3d(long colrtyp, TriArrayGrp *list, TriArrayGrp *nlist) { long i, count, comp4, colrskip, numtri, *oldIDs, *newIDs, color_loop, il; yPoint3D *oldVert, *newVert, *oldNorm, *newNorm; float *oldColr, *newColr; double *oldVar2, *newVar2; /* This function merges a list of triangle arrays into a single triangle array. abs(colrtyp) is 3 for RGB colors and 4 for RGBA. if colrtyp<0, the input list has scalar colors. The caller guarantees that there is enough room in nlist to store all the triangles in list */ newVert= nlist->xyzverts; newNorm= nlist->normals; newColr= nlist->colors; newIDs= nlist->cellIDs; newVar2= nlist->var2; color_loop= 1; if(colrtyp < 0) { colrskip= 0; if(colrtyp < -4) { color_loop= 3; colrtyp += 16; } if(colrtyp == -4) comp4= 1; else comp4= 0; } else { if(colrtyp > 4) { color_loop= 3; colrtyp -= 16; } colrskip= colrtyp; if(colrtyp == 4) comp4= 1; else comp4= 0; } numtri= 0; while(list) { oldVert= list->xyzverts; oldNorm= list->normals; oldColr= list->colors; oldIDs= list->cellIDs; oldVar2= list->var2; count= list->numTri; numtri += count; for(i=0; i < count; i++) { newVert[0]= oldVert[0]; newVert[1]= oldVert[1]; newVert[2]= oldVert[2]; newVert += 3; oldVert += 3; newNorm[0]= oldNorm[0]; newNorm[1]= oldNorm[1]; newNorm[2]= oldNorm[2]; newNorm += 3; oldNorm += 3; /* handle both color per vertex and color per triangle */ for(il= 0; il < color_loop; il++) { newColr[0]= oldColr[0]; newColr[1]= oldColr[1]; newColr[2]= oldColr[2]; if(comp4) { newColr[3]= oldColr[3]; newColr += 4; } else { newColr += 3; } oldColr += colrskip; } if(oldVar2) { newVar2[0] = oldVar2[0]; newVar2[1] = oldVar2[1]; newVar2[2] = oldVar2[2]; oldVar2 += 3; newVar2 += 3; } *newIDs++ = *oldIDs++; } list= list->next; } nlist->numTri= numtri; } void yglDoSortTri3d(long colrtyp, TriArrayGrp *oldtri, TriArrayGrp *newtri) { entry *dist; double view[3], viewlen; yPoint3D *oldxyz, *newxyz, *oldnorm, *newnorm; double *oldVar2, *newVar2; float *oldcolr, *newcolr; long *oldid, *newid; long i, ntri, ndx, base, cbase, xbase; /* Perform a depth sort of a triangle array. It uses the current viewpoint. The resulting triangle array should display correctly with translucency when viewed with this viewing transform. Rotating the scene may lead to incorrect results if the triangles are translucent. colrtyp is 3 for RGB colors and 4 for RGBA. There MUST be one color for every triangle vertex. */ view[0]= glCurrWin3d->eye[0] - glCurrWin3d->center[0]; view[1]= glCurrWin3d->eye[1] - glCurrWin3d->center[1]; view[2]= glCurrWin3d->eye[2] - glCurrWin3d->center[2]; viewlen= 1.0e-80+sqrt(view[0]*view[0]+view[1]*view[1]+view[2]*view[2]); view[0] /= viewlen; view[1] /= viewlen; view[2] /= viewlen; /* compute the average z-depth of the three vertices of each triangle */ ntri= oldtri->numTri; oldxyz= oldtri->xyzverts; dist= (entry *) p_malloc(ntri*sizeof(entry)); for(i= 0; i < ntri; i++) { dist[i].ndx= i; base= 3*i; dist[i].val= view[0]*(oldxyz[base].x+oldxyz[base+1].x+oldxyz[base+2].x) +view[1]*(oldxyz[base].y+oldxyz[base+1].y+oldxyz[base+2].y) +view[2]*(oldxyz[base].z+oldxyz[base+1].z+oldxyz[base+2].z); } /* sort the polygons from smallest z to largest z */ myqsort(dist, 0, ntri-1); cbase= 0; xbase= 0; newxyz= newtri->xyzverts; oldnorm= oldtri->normals; newnorm= newtri->normals; oldcolr= oldtri->colors; newcolr= newtri->colors; oldid= oldtri->cellIDs; newid= newtri->cellIDs; oldVar2= oldtri->var2; newVar2= newtri->var2; for(i= 0; i < ntri; i++) { ndx= 3*(dist[i].ndx); newxyz[xbase]= oldxyz[ndx]; newxyz[xbase+1]= oldxyz[ndx+1]; newxyz[xbase+2]= oldxyz[ndx+2]; newnorm[xbase]= oldnorm[ndx]; newnorm[xbase+1]= oldnorm[ndx+1]; newnorm[xbase+2]= oldnorm[ndx+2]; if(oldVar2) { newVar2[xbase]= oldVar2[ndx]; newVar2[xbase+1]= oldVar2[ndx+1]; newVar2[xbase+2]= oldVar2[ndx+2]; } xbase += 3; } if(colrtyp == 4) { for(i= 0; i < ntri; i++) { ndx= dist[i].ndx; newid[i]= oldid[ndx]; ndx *= 4; newcolr[cbase]= oldcolr[ndx]; newcolr[cbase+1]= oldcolr[ndx+1]; newcolr[cbase+2]= oldcolr[ndx+2]; newcolr[cbase+3]= oldcolr[ndx+3]; cbase += 4; } } else { for(i= 0; i < ntri; i++) { ndx= dist[i].ndx; newid[i]= oldid[ndx]; ndx *= 3; newcolr[cbase]= oldcolr[ndx]; newcolr[cbase+1]= oldcolr[ndx+1]; newcolr[cbase+2]= oldcolr[ndx+2]; cbase += 3; } } p_free(dist); } void myqsort(entry v[], long left, long right) { long i, last, mid; entry temp; if(left >= right) return; mid= (left+right)/2; temp= v[left]; v[left]= v[mid]; v[mid]= temp; last= left; for(i= left+1; i <= right; i++) { if(v[i].val < v[left].val) { last++; temp= v[i]; v[i]= v[last]; v[last]= temp; } } temp= v[left]; v[left]= v[last]; v[last]= temp; myqsort(v, left, last-1); myqsort(v, last+1, right); } void yglSliceTris3d(long *keep, long *nkeep, double *dp, TriArrayGrp *oldtri, TriArrayGrp *newtri) { long numold, inew, i3new, i, i3, p0, p1, p2, *oldid, *newid; yPoint3D *oldxyz, *newxyz, *oldnorm, *newnorm; double *oldVar2, *newVar2, frac; float *oldcolr, *newcolr; /* Clip triangles against a plane using nkeep, the number of vertices from each input triangle that are "above" the slicing plane, keep (above the plane for a specific vertex), and dp (the distance to the plane for each vertex). */ numold= oldtri->numTri; oldxyz= oldtri->xyzverts; oldnorm= oldtri->normals; oldcolr= oldtri->colors; oldid= oldtri->cellIDs; oldVar2= oldtri->var2; newxyz= newtri->xyzverts; newnorm= newtri->normals; newcolr= newtri->colors; newid= newtri->cellIDs; newVar2= newtri->var2; inew= 0; for(i= 0; i < numold; i++) { i3= 3*i; i3new= 3*inew; if(nkeep[i] == 3) { /* copy the input triangle to the output triangle list */ newxyz[i3new]= oldxyz[i3]; newxyz[i3new+1]= oldxyz[i3+1]; newxyz[i3new+2]= oldxyz[i3+2]; newnorm[i3new]= oldnorm[i3]; newnorm[i3new+1]= oldnorm[i3+1]; newnorm[i3new+2]= oldnorm[i3+2]; newcolr[i3new]= oldcolr[i3]; newcolr[i3new+1]= oldcolr[i3+1]; newcolr[i3new+2]= oldcolr[i3+2]; newid[inew]= oldid[i]; if(oldVar2) { newVar2[i3new]= oldVar2[i3]; newVar2[i3new+1]= oldVar2[i3+1]; newVar2[i3new+2]= oldVar2[i3+2]; } inew++; } else if(nkeep[i] == 2) { /* two vertices are "above" the plane, so clipping results in two triangles */ if(!keep[i3]) { /* the first point must be thrown out */ p0= 0; p1= 1; p2= 2; } else if(!keep[i3+1]) { /* the second point must be thrown out */ p0= 1; p1= 2; p2= 0; } else { /* the third point must be thrown out */ p0= 2; p1= 0; p2= 1; } frac= -dp[i3+p0]/(dp[i3+p1]-dp[i3+p0]); /* this triangle starts with two points of the existing triangle */ newxyz[i3new]= oldxyz[i3+p1]; newnorm[i3new]= oldnorm[i3+p1]; newxyz[i3new+1]= oldxyz[i3+p2]; newnorm[i3new+1]= oldnorm[i3+p2]; newxyz[i3new+2].x= oldxyz[i3+p0].x+frac*(oldxyz[i3+p1].x-oldxyz[i3+p0].x); newxyz[i3new+2].y= oldxyz[i3+p0].y+frac*(oldxyz[i3+p1].y-oldxyz[i3+p0].y); newxyz[i3new+2].z= oldxyz[i3+p0].z+frac*(oldxyz[i3+p1].z-oldxyz[i3+p0].z); newnorm[i3new+2].x= oldnorm[i3+p0].x+frac*(oldnorm[i3+p1].x-oldnorm[i3+p0].x); newnorm[i3new+2].y= oldnorm[i3+p0].y+frac*(oldnorm[i3+p1].y-oldnorm[i3+p0].y); newnorm[i3new+2].z= oldnorm[i3+p0].z+frac*(oldnorm[i3+p1].z-oldnorm[i3+p0].z); newcolr[i3new]= oldcolr[i3]; newcolr[i3new+1]= oldcolr[i3+1]; newcolr[i3new+2]= oldcolr[i3+2]; newid[inew]= oldid[i]; if(oldVar2) { newVar2[i3new]= oldVar2[i3]; newVar2[i3new+1]= oldVar2[i3+1]; newVar2[i3new+2]= oldVar2[i3+2]; } inew++; i3new= 3*inew; frac= -dp[i3+p0]/(dp[i3+p2]-dp[i3+p0]); /* this triangle starts with the intersection point from the previous triangle */ newxyz[i3new]= newxyz[i3new-1]; newnorm[i3new]= newnorm[i3new-1]; newxyz[i3new+1]= oldxyz[i3+p2]; newnorm[i3new+1]= oldnorm[i3+p2]; newxyz[i3new+2].x= oldxyz[i3+p0].x+frac*(oldxyz[i3+p2].x-oldxyz[i3+p0].x); newxyz[i3new+2].y= oldxyz[i3+p0].y+frac*(oldxyz[i3+p2].y-oldxyz[i3+p0].y); newxyz[i3new+2].z= oldxyz[i3+p0].z+frac*(oldxyz[i3+p2].z-oldxyz[i3+p0].z); newnorm[i3new+2].x= oldnorm[i3+p0].x+frac*(oldnorm[i3+p2].x-oldnorm[i3+p0].x); newnorm[i3new+2].y= oldnorm[i3+p0].y+frac*(oldnorm[i3+p2].y-oldnorm[i3+p0].y); newnorm[i3new+2].z= oldnorm[i3+p0].z+frac*(oldnorm[i3+p2].z-oldnorm[i3+p0].z); newcolr[i3new]= oldcolr[i3]; newcolr[i3new+1]= oldcolr[i3+1]; newcolr[i3new+2]= oldcolr[i3+2]; newid[inew]= oldid[i]; if(oldVar2) { newVar2[i3new]= oldVar2[i3]; newVar2[i3new+1]= oldVar2[i3+1]; newVar2[i3new+2]= oldVar2[i3+2]; } inew++; } else if(nkeep[i] == 1) { /* one vertex is "above" the plane, so clipping results in one triangle */ /* one point of the old triangle extends above the clip plane */ if(keep[i3]) { /* the first point must be kept */ p0= 0; p1= 1; p2= 2; } else if(keep[i3+1]) { /* the second point must be kept */ p0= 1; p1= 2; p2= 0; } else { /* the third point must be kept */ p0= 2; p1= 0; p2= 1; } newxyz[i3new]= oldxyz[i3+p0]; newnorm[i3new]= oldnorm[i3+p0]; /* CAUTION - next two points must be in the proper order */ frac= -dp[i3+p0]/(dp[i3+p1]-dp[i3+p0]); newxyz[i3new+1].x= oldxyz[i3+p0].x+frac*(oldxyz[i3+p1].x-oldxyz[i3+p0].x); newxyz[i3new+1].y= oldxyz[i3+p0].y+frac*(oldxyz[i3+p1].y-oldxyz[i3+p0].y); newxyz[i3new+1].z= oldxyz[i3+p0].z+frac*(oldxyz[i3+p1].z-oldxyz[i3+p0].z); newnorm[i3new+1].x= oldnorm[i3+p0].x+frac*(oldnorm[i3+p1].x-oldnorm[i3+p0].x); newnorm[i3new+1].y= oldnorm[i3+p0].y+frac*(oldnorm[i3+p1].y-oldnorm[i3+p0].y); newnorm[i3new+1].z= oldnorm[i3+p0].z+frac*(oldnorm[i3+p1].z-oldnorm[i3+p0].z); frac= -dp[i3+p0]/(dp[i3+p2]-dp[i3+p0]); newxyz[i3new+2].x= oldxyz[i3+p0].x+frac*(oldxyz[i3+p2].x-oldxyz[i3+p0].x); newxyz[i3new+2].y= oldxyz[i3+p0].y+frac*(oldxyz[i3+p2].y-oldxyz[i3+p0].y); newxyz[i3new+2].z= oldxyz[i3+p0].z+frac*(oldxyz[i3+p2].z-oldxyz[i3+p0].z); newnorm[i3new+2].x= oldnorm[i3+p0].x+frac*(oldnorm[i3+p2].x-oldnorm[i3+p0].x); newnorm[i3new+2].y= oldnorm[i3+p0].y+frac*(oldnorm[i3+p2].y-oldnorm[i3+p0].y); newnorm[i3new+2].z= oldnorm[i3+p0].z+frac*(oldnorm[i3+p2].z-oldnorm[i3+p0].z); newcolr[i3new]= oldcolr[i3]; newcolr[i3new+1]= oldcolr[i3+1]; newcolr[i3new+2]= oldcolr[i3+2]; newid[inew]= oldid[i]; if(oldVar2) { newVar2[i3new]= oldVar2[i3]; newVar2[i3new+1]= oldVar2[i3+1]; newVar2[i3new+2]= oldVar2[i3+2]; } inew++; } } } void yglMap2ColorRaw3d(long ncolr, unsigned char *red, unsigned char *green, unsigned char *blue, double vmin, double vmax, double *var, long ntri, long *cellids, float *colr) { long i, ndx; double x; /* This function takes as input a vector of cell numbers (cellids). The number of such values is ntri. red, green, and blue are a color table with ncolr elements. For a cell with index ii, this function maps the variable value, var[cellids[ii]], into an RGB color. The mapping takes the range from vmin to vmax and generates indices from zero to ncolr. */ for(i= 0; i < ntri; i++) { x= var[cellids[i]]; if(x < vmin) x= vmin; if(x > vmax) x= vmax; ndx= (long) (ncolr*(x-vmin)/(vmax-vmin)); if(ndx > ncolr-1) ndx= ncolr-1; colr[3*i ]= (float) (red[ndx] /256.0); colr[3*i+1]= (float) (green[ndx]/256.0); colr[3*i+2]= (float) (blue[ndx] /256.0); } } yorick-gl-1.1+cvs20070922+dfsg.orig/oglw.c0000640000175000017500000001526110313362503017541 0ustar thibautthibaut/* * $Id: oglw.c,v 1.1.1.1 2005/09/18 22:08:03 dhmunro Exp $ * GL window management for MS Windows * for yorick-gl package - this source unused and may be out of date */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #include "pstdlib.h" #include "playwin.h" #include "playgl.h" static LRESULT CALLBACK w_glsubclass(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp); struct p_glwin { void *ctx; /* ctx, w, keydown must match p_win struct */ HWND w; unsigned long keydown; p_win *parent; HDC dc; HGLRC glrc; int x, y; }; static unsigned char bits3[8] = { 0, 0111>>1, 0222>>1, 0333>>1, 0444>>1, 0555>>1, 0666>>1, 0777>>1 }; static unsigned char bits2[4] = { 0, 0x55, 0xaa, 0xff }; static unsigned char bits1[2] = { 0, 0xff }; static unsigned char *bits[3] = { bits1, bits2, bits3 }; static int std_ndx[13] = { 0, 3, 24, 27, 64, 67, 88, 173, 181, 236, 247, 164, 91 }; static PALETTEENTRY std_pal[20] = { { 0, 0, 0, 0 },{ 0x80,0, 0, 0 },{ 0, 0x80,0, 0 }, { 0x80,0x80,0, 0 },{ 0, 0, 0x80, 0 },{ 0x80,0, 0x80, 0 }, { 0, 0x80,0x80, 0 },{ 0xC0,0xC0,0xC0, 0 }, { 192, 220, 192, 0 },{ 166, 202, 240, 0 },{ 255, 251, 240, 0 }, { 160, 160, 164, 0 }, { 0x80,0x80,0x80, 0 },{ 0xFF,0, 0, 0 },{ 0, 0xFF,0, 0 }, { 0xFF,0xFF,0, 0 },{ 0, 0, 0xFF, 0 },{ 0xFF,0, 0xFF, 0 }, { 0, 0xFF,0xFF, 0 },{ 0xFF,0xFF,0xFF, 0 }}; static HINSTANCE wc_app_instance = 0; static LPCTSTR wc_win_class = 0; static WNDPROC wc_winproc = 0; /* used for glx debugging, irrelevant for MSWindows gl */ extern int p_glvid_force, p_glvid_using; int p_glvid_force = 0, p_glvid_using = 0; p_glwin * p_glcreate(p_win *parent, int width, int height, int x, int y, void *ctx) { int is_pixmap = (parent->bm!=0); HDC dc = parent->dc; p_scr *s = parent->s; p_glwin *w = p_malloc(sizeof(p_glwin)); HWND hw = 0; HGLRC glrc = 0; PIXELFORMATDESCRIPTOR pfd; int pf_index; if (!w) return 0; if (!is_pixmap) { DWORD style = WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; DWORD xstyle = 0; if (!wc_win_class) wc_app_instance = w_linker(&wc_win_class, &wc_winproc); hw = CreateWindowEx(xstyle, wc_win_class, 0, style, x, y, width, height, parent->w, 0, wc_app_instance, 0); if (!hw) return 0; SetWindowLong(hw, GWL_USERDATA, (LONG)w); /* idea -- subclass the window to pass events to parent */ SetWindowLong(hw, GWL_WNDPROC, (LONG)w_glsubclass); ShowWindow(hw, SW_SHOWNA); dc = GetDC(hw); } pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); pfd.nVersion = 1; pfd.dwFlags = (is_pixmap? PFD_DRAW_TO_BITMAP : PFD_DRAW_TO_WINDOW) | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; pfd.iPixelType = PFD_TYPE_RGBA; pfd.cColorBits = 24; pfd.cDepthBits = 32; pfd.iLayerType = PFD_MAIN_PLANE; pfd.cAccumBits = pfd.cStencilBits = pfd.cAuxBuffers = 0; /* rest are ignored */ pfd.cRedBits = pfd.cGreenBits = pfd.cBlueBits = pfd.cAlphaBits = 8; pfd.cRedShift = pfd.cGreenShift = pfd.cBlueShift = pfd.cAlphaShift = 0; pfd.cAccumRedBits = pfd.cAccumGreenBits = pfd.cAccumBlueBits = 0; pfd.cAccumAlphaBits = 0; pfd.bReserved = 0; pfd.dwLayerMask = pfd.dwVisibleMask = pfd.dwDamageMask = 0; pf_index = ChoosePixelFormat(dc, &pfd); if (pf_index && SetPixelFormat(dc, pf_index, &pfd)) { /* retrieve actual pfd obtained */ pf_index = DescribePixelFormat(dc, pf_index, sizeof(PIXELFORMATDESCRIPTOR), &pfd); glrc = wglCreateContext(dc); if (glrc) { w->parent = parent; w->w = hw; w->dc = dc; w->glrc = glrc; w->x = x; w->y = y; w->ctx = ctx; if (pfd.dwFlags & PFD_NEED_PALETTE) { HPALETTE palette; /* from MSDN CUBE sample code */ unsigned int i, n = 1 << pfd.cColorBits; LOGPALETTE *pal = p_malloc(sizeof(LOGPALETTE)+n*sizeof(PALETTEENTRY)); int r = pfd.cRedBits-1, g = pfd.cGreenBits-1, b = pfd.cBlueBits-1; unsigned int rmsk, gmsk, bmsk; if (r<0 || r>2) r = 0; if (g<0 || g>2) r = 0; if (b<0 || b>2) r = 0; rmsk = (2<256) n = 256; pal->palVersion = 0x300; pal->palNumEntries = n; for (i=0 ; ipalPalEntry[i].peRed = bits[r][(i>>pfd.cRedShift)&rmsk]; pal->palPalEntry[i].peGreen = bits[g][(i>>pfd.cGreenShift)&gmsk]; pal->palPalEntry[i].peBlue = bits[b][(i>>pfd.cBlueShift)&bmsk]; pal->palPalEntry[i].peFlags = 0; } if ((pfd.cColorBits == 8) && (pfd.cRedBits == 3) && (pfd.cRedShift == 0) && (pfd.cGreenBits == 3) && (pfd.cGreenShift == 3) && (pfd.cBlueBits == 2) && (pfd.cBlueShift == 6)) { for (i=1 ; i<=12 ; i++) pal->palPalEntry[std_ndx[i]] = std_pal[i]; } palette = CreatePalette(pal); p_free(pal); if (palette) { HPALETTE pt = SelectPalette(parent->dc, palette, 0); if (pt) DeleteObject(pt); parent->rgb_mode = 1; /* inhibit any further palette changes */ RealizePalette(parent->dc); SelectPalette(dc, palette, 0); RealizePalette(dc); } } } } if (!glrc) { if (hw) DestroyWindow(hw); p_free(w); w = 0; } return w; } void p_gldestroy(p_glwin *w) { if (w) { wglDeleteContext(w->glrc); if (w->w) DestroyWindow(w->w); p_free(w); } } void p_glresize(p_glwin *w, int width, int height, int x, int y) { if (w && w->w && !w->parent->bm) SetWindowPos(w->w, 0, x,y, width,height, SWP_NOACTIVATE|SWP_NOZORDER); } void p_glswap(p_glwin *w) { SwapBuffers(w->dc); GdiFlush(); } void p_glcurrent(p_glwin *w) { wglMakeCurrent(w->dc, w->glrc); } static LRESULT CALLBACK w_glsubclass(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) { p_glwin *pgl = (p_glwin *)GetWindowLong(hwnd, GWL_USERDATA); if (pgl && pgl->w==hwnd) { switch (msg) { case WM_PAINT: break; case WM_DESTROY: pgl->w = 0; p_gldestroy(pgl); return 0; case WM_RBUTTONDOWN: case WM_MBUTTONDOWN: case WM_LBUTTONDOWN: case WM_RBUTTONUP: case WM_MBUTTONUP: case WM_LBUTTONUP: case WM_MOUSEMOVE: { int x = LOWORD(lp); int y = HIWORD(lp); x += pgl->x; y += pgl->y; lp = MAKELPARAM(x, y); hwnd = pgl->parent->w; } break; default: hwnd = pgl->parent->w; break; } } return CallWindowProc(wc_winproc, hwnd, msg, wp, lp); } yorick-gl-1.1+cvs20070922+dfsg.orig/slicetree.h0000640000175000017500000000321210313362503020546 0ustar thibautthibaut/* * $Id: slicetree.h,v 1.1.1.1 2005/09/18 22:08:03 dhmunro Exp $ * Header file for octree used by slicing plane. */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #ifndef __SLICETREE__ #define __SLICETREE__ #ifdef __cplusplus extern "C" { #endif typedef struct OctSpan OctSpan; struct OctSpan { double xmin, xmax, ymin, ymax, zmin, zmax; } ; typedef struct OctSTree OctSTree; struct OctSTree { long maxdepth; long *start; long *chunk; long *size; long *trsiz; long *offsets; OctSpan *ranges; OctSTree *next; } ; extern int ycMakeSliceTreeCrv(double *xyz, OctSTree *tree); extern void firstSblk(long *start, long *sizes, long *trsiz, double *xyz, OctSpan *rng); extern void nextSblk(long *trsiz, OctSpan *oldr, OctSpan *nrng); extern int ycSliceTree(long maxdepth, long sizes[3], long chunk[3], long start[3], double deltas[3], double origin[3], double point[3], double normal[3], double *var, TriArrayGrp *triangles); extern int ycSliceTreeCrv(double point[3], double normal[3], double *xyz, double *var, TriArrayGrp *triangles, OctSTree *tree); extern long do_Sblk(long ilo, long ihi, long jlo, long jhi, long klo, long khi, long depth); extern long do_SblkCrv(long newi, long newj, long newk, long depth); extern long grab_Stris(long i, long j, long k, double s[8]); extern long grab_StrisCrv(long i, long j, long k); #ifdef __cplusplus } #endif #endif /* Include/Define */ yorick-gl-1.1+cvs20070922+dfsg.orig/Contour3D.h0000640000175000017500000001771710313362473020434 0ustar thibautthibaut/* * $Id: Contour3D.h,v 1.1.1.1 2005/09/18 22:07:55 dhmunro Exp $ * Contour3D - generates isosurface(s) from volume data */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #ifndef __Contour3D_h #define __Contour3D_h #include "TriStruct.h" /* WARNING: the caller is responsible for freeing the storage pointed in the struct returned by this call, and for freeing the struct. */ extern int ycContour(long sizes[3], long maxTri, double deltas[3], double origin[3], double level, double *var, TriArray *triangles); extern int ycContourCrv(long sizes[3], long maxTri, double level, yPoint3D *xyz, double *var, TriArray *triangles); extern int ycContourList(long sizes[3], long maxVert, double deltas[3], double origin[3], double level, double *var, TriStrip *triangles); extern int ycContourListCrv(long sizes[3], long maxVert, double level, yPoint3D *xyz, double *var, TriStrip *triangles); extern int ycContourHex(long nzone, long maxTri, double level, yPoint3D *xyz, double *var, TriArray *triangles); extern int ycContourStr(long make_strip,long sizes[3], long offsets[5], double deltas[3], double origin[3], double level, double *var, yPoint3D *grd, char *done, unsigned char *above, TriArrayGrp *triangles); extern int ycContourStr_old(long sizes[3], long start[3], long chunk[3], double deltas[3], double origin[3], double level, double *var, TriArrayGrp *triangles); extern int ycContourCrvStr(long make_strip, long sizes[3], long offsets[5], double level, yPoint3D *xyz, double *var, yPoint3D *grd, char *done, unsigned char *above, TriArrayGrp *triangles); extern int ycContourListStr(long make_strip, long sizes[3], long maxVert, double deltas[3], double origin[3], double level, double *var, TriStripGrp *triangles); extern int ycContourListCrvStr(long make_strip, long sizes[3], long maxVert, double level, yPoint3D *xyz, double *var, TriStripGrp *triangles); extern int ycContourHexStr(long nzone, long maxTri, double level, yPoint3D *xyz, double *var, TriArrayGrp *triangles); extern int ycContourStrCen(long make_strip, long sizes[3], long offsets[7], double deltas[3], double origin[3], double level, double *var, double *vcen, yPoint3D *grd, char *done, unsigned char *above, TriArrayGrp *triangles); extern int ycContourStrPt(long make_strip, long sizes[3], long offsets[7], double deltas[3], double origin[3], double level, double *var, yPoint3D *grd, char *done, unsigned char *above, TriArrayGrp *triangles); extern int ycContourPt(long make_strip, long sizes[3], long offsets[7], double deltas[3], double origin[3], double level, double *var, TriArrayGrp *triangles); extern int ycContourPtCrv(long make_strip, long sizes[3], long offsets[5], double level, yPoint3D *xyz, double *var, TriArrayGrp *triangles); extern int ycContourVarrCen(long make_strip, long sizes[3], long offsets[7], double deltas[3], double origin[3], double level, double *var, double *vcen, yPoint3D *grd, char *done, unsigned char *above, long* ndx, TriVertexGrp *triangles); extern int ycContourHexList(long base, long nzone, long npt, double level, long *zones, yPoint3D *xyz, double *var, yPoint3D *norm, TriArray *triangles); extern int ycMakeTriStripNdx(long sizes[3], long offsets[5], char *visited, TriArrayGrp *triangles, TriStripNdx *strip); extern int ycMakeTriStripNdx_old(long sizes[3], long start[3], long chunk[3], char *visited, TriArrayGrp *triangles, TriStripNdx *strip); extern int ycMakeTriStrip(long sizes[3], long start[3], long chunk[3], char *visited, TriArrayGrp *triangles, TriStripGrp *strip); extern int ycMakeTriStripNdxCenVertex(long sizes[3], long offsets[5], char *visited, TriVertexGrp *triangles, TriStripNdx *strip); extern int ycMakeTriStripNdxCen(long sizes[3], long offsets[5], char *visited, TriArrayGrp *triangles, TriStripNdx *strip); extern int ycAssembleStrip(TriArrayGrp *triangles, TriStripNdx *stripNdx, TriStripGrp *strip); extern void ycPointGradient(long i, long j, long k, long nx, long ny, long nz, double *s, double dx, double dy, double dz, yPoint3D *n); extern void ycPointGradientAll(long i, long j, long k, long nx, long ny, long nz, double *s, double dx, double dy, double dz, yPoint3D gradient[8]); extern void ycPointGradientCrv(long i, long j, long k, long nx, long ny, long nz, yPoint3D *x, double *s, yPoint3D *n); extern void ycPointGradientHex(yPoint3D *pts, double *s, yPoint3D *gradients); extern void ycPointGradientGrd(long i, long j, long k, long nx, long ny, long nz, double *s, double dx, double dy, double dz, yPoint3D *n, yPoint3D *grd, char *done); extern void ycPointGradientAllGrd(long i, long j, long k, long nx, long ny, long nz, double *s, double dx, double dy, double dz, yPoint3D gradient[8], yPoint3D *grd, char *done); extern void ycPointGradientCrvGrd(long i, long j, long k, long nx, long ny, long nz, yPoint3D *x, double *s, yPoint3D *n, yPoint3D *grd, char *done); extern void ycPointGradientIntGrd(long i, long j, long k, long nx, long ny, long nz, double *s, double dx, double dy, double dz, yPoint3D gradient[8], yPoint3D *grd, char *done); extern void ycPointGradientIntGrdCrv(long i, long j, long k, long nx, long ny, long nz, yPoint3D *xyz, double *s, yPoint3D gradient[8], yPoint3D *grd, char *done); extern void ycPointGradientIntGrdCenAll(long i, long j, long k, long nx, long ny, long nz, double dx, double dy, double dz, yPoint3D *grd, char *done, long offsets[5], double *var, yPoint3D gradient[8]); extern void ycPointGradientIntGrdPtAll(long i, long j, long k, long nx, long ny, long nz, double dx, double dy, double dz, yPoint3D *grd, char *done, long offsets[5], double *var, yPoint3D gradient[8]); extern void ycPointGradientIntGrdPtAll2(long idxg, double dx, double dy, double dz, long corners[8], long offsets[5], double *var, yPoint3D gradient[8]); extern void ycPointGradientCrvgPtAll(long idxg, long corners[8], long offsets[5], yPoint3D *x, double *var, yPoint3D gradient[8]); extern void ycNormalize(yPoint3D *n); extern long GetNeighbor(long sizes[3], long cellID, long prevEdg, long lastEdg, long *newPrev, long *newLast); extern void extract_tris_tet(int case_index, long idxcg, double *cntr_v2, long *numTri, double lev, double s[8], yPoint3D pts[8], yPoint3D gradients[8], double vars[8], long *cellIDs, yPoint3D *xyzverts, yPoint3D *normals, double *v2vals); extern void extract_tris_tet_ndx(int case_index, long idxv, long idxcg, double *cntr_v2, long *numTri, long *numEdg, double lev, double s[8], yPoint3D pts[8], yPoint3D gradients[8], double vars[8], long edg_offset[12], long *cellIDs, long *ptndx, long *ndx, yPoint3D *xyzverts, yPoint3D *normals, double *v2vals); extern void extract_slicetris_tet(int case_index, long idxcg, double *cntr_v2, long *numTri, double s[8], yPoint3D pts[8], double vars[8], long *cellIDs, yPoint3D *xyzverts, double *v2vals); extern int ycPrepIsoTet(void); extern int have_iso_cases; #endif yorick-gl-1.1+cvs20070922+dfsg.orig/yorgl.i0000640000175000017500000000266110313362503017733 0ustar thibautthibaut/* * $Id: yorgl.i,v 1.1.1.1 2005/09/18 22:08:03 dhmunro Exp $ * autoloads for yorgl package */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ autoload, "glfunc.i", Draw3d, GetBounds3d, win3d; autoload, "glfunc.i", get_currwin3d, winkill3d, mousefunc3d, get_width3d; autoload, "glfunc.i", get_hite3d, gl_always_show_obj, use_list3d, use_array3d; autoload, "glfunc.i", cage_style3d, set_fov3d, get_fov3d, getGLvers; autoload, "glfunc.i", preptex3d, endtex3d, has_tex3d, has_texcube3d; autoload, "glfunc.i", line_width3d, msmov_val3d, out_ccw3d, update_list3d; autoload, "glfunc.i", inc_seq3d; autoload, "dlist3d.i", CollapseTri, SortTri, clear3d, clear3d_cache; autoload, "dlist3d.i", clear3d_direct, draw3d, get_centroid3d, get_lims3d; autoload, "dlist3d.i", get_normal3d, getpix3d, gl_rr, light3d, lookat3d; autoload, "dlist3d.i", palette3d, plcell3d, plcolrsurf3d, plf3d, plglyphs3d; autoload, "dlist3d.i", pllines3d, plm3d, plpoints3d, plpoly3d, plqarray3d; autoload, "dlist3d.i", plqstrips3d, plsurf3d, pltarray3d, pltex2dvol; autoload, "dlist3d.i", pltex3dvol, pltivarray3d, pltivstrips3d, pltrilists3d; autoload, "dlist3d.i", pltstrips3d, pltvarray3d, prtview3d, putpix3d; autoload, "dlist3d.i", stdview3d; autoload, "slicenew.i", nuslice2, nuslice2x, slice2_precision, slice2only; yorick-gl-1.1+cvs20070922+dfsg.orig/glBasic.h0000640000175000017500000000230710313362461020142 0ustar thibautthibaut/* * $Id: glBasic.h,v 1.1.1.1 2005/09/18 22:07:45 dhmunro Exp $ * Header file for window creation and drawing related functions */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #ifndef __GLBASIC__ #define __GLBASIC__ #include "glcode.h" #ifdef __cplusplus extern "C" { #endif extern void yglDoGetPixels(long nx, long ny, unsigned char *pix); extern glWinProp *yglMakWin(char *displayName, int width, int height, char *title); extern int yglWin3d(int num, int w, int h); extern int yglWinKill3d(int num); extern int shutdown3d(glWinProp *win3d); extern void resetcurrwin3d(void); extern int winnum3d(glWinProp *theWin3d); extern void yglDoDraw(glWinProp *theWin3d); extern int isWin3d(glWinProp *win); extern void yglForceDraw(void); extern void yglPrepDraw(glWinProp *theWin3d); extern void yglFinFrame(void); extern void yglFinDirect(void); extern void yglFinCache(void); extern void yglMakeCurrent(glWinProp *theWin3d); extern void yglPrepList(void); extern glWinProp *glWin3dList[8]; #ifdef __cplusplus } #endif #endif /* Include/Define */ yorick-gl-1.1+cvs20070922+dfsg.orig/playgl.h0000640000175000017500000000315410313362503020064 0ustar thibautthibaut/* * $Id: playgl.h,v 1.1.1.1 2005/09/18 22:08:03 dhmunro Exp $ * OpenGL portability layer interface declarations */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ /*************************************************************************/ /* WARNING * PLUG_EXPORT below is correct only for the package which is * building oglx.c/oglw.c, which defines these functions. * Another package should use PLUG_API. Since there are no * other packages currently, I hardwired the changes here. * The correct procedure would be to define a PLAY_GL_INTERNAL * macro in all the source files which include playgl.h in this * directory. Since playgl.h is not installed, the chance of * misuse for the time being is nil. */ /*************************************************************************/ /* include play.h, then playgl.h, then GL/gl.h */ #include "plugin.h" typedef struct p_glwin p_glwin; /* opaque to platform independent code */ BEGIN_EXTERN_C PLUG_EXPORT p_glwin *p_glcreate(p_win *parent, int width, int height, int x, int y, void *ctx); PLUG_EXPORT void p_gldestroy(p_glwin *w); PLUG_EXPORT void p_glresize(p_glwin *w, int width, int height, int x, int y); PLUG_EXPORT void p_glswap(p_glwin *w); PLUG_EXPORT void p_glcurrent(p_glwin *w); END_EXTERN_C /* Mr. Bill buggered so it won't work without this * -- better to have it confined to this one place */ #ifdef _WIN32 #include #endif yorick-gl-1.1+cvs20070922+dfsg.orig/glStrips.c0000640000175000017500000015625210515710063020410 0ustar thibautthibaut/* * $Id: glStrips.c,v 1.3 2006/10/19 14:48:19 dhmunro Exp $ */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #include "glcode.h" #include "glfunc.h" #include "glStrips.h" #include "glWrappers.h" #include "pstdlib.h" #include #include static void yglTstripsSmNoArrAlpha(long nstrip, long *len, float *xyz, float *norm, float *colr); static void yglTstripSmNoArr(long nvert, float *xyz, float *norm, float *colr); static void yglTstripNoArrNoLiteAlpha(long nvert, float *xyz, float *colr); static void yglTstripArrNoLite(long nvert, float *xyz, float *colr); static void yglTstripArrNoLiteAlpha(long nvert, float *xyz, float *colr); static void yglTstripNoArrNoLite(long nvert, float *xyz, float *colr); static void yglTstripSmArr(long nvert, float *xyz, float *norm, float *colr); static void yglTstripSmArrAlpha(long nvert, float *xyz, float *norm, float *colr); static void yglTstripsSmNoArr(long nstrip, long *len, float *xyz, float *norm, float *colr); static void yglTstripArr(long nvert, float *xyz, float *norm, float *colr); static void yglTstripNoArr(long nvert, float *xyz, float *norm, float *colr); static void yglTstripNoArrAlpha(long nvert, float *xyz, float *norm, float *colr); static void yglTstripArrAlpha(long nvert, float *xyz, float *norm, float *colr); static void yglTstripsSmNoArrAlpha(long nstrip, long *len, float *xyz, float *norm, float *colr); static void yglQstripsSmNoArrAlpha(long nstrip, long *len, float *xyz, float *norm, float *colr); static void yglQstripSmNoArr(long nvert, float *xyz, float *norm, float *colr); static void yglQstripArrNoLite(long nvert, float *xyz, float *colr); static void yglQstripArrNoLiteAlpha(long nvert, float *xyz, float *colr); static void yglQstripSmArr(long nvert, float *xyz, float *norm, float *colr); static void yglQstripSmArrAlpha(long nvert, float *xyz, float *norm, float *colr); static void yglQstripsSmNoArr(long nstrip, long *len, float *xyz, float *norm, float *colr); static void yglQstripArr(long nvert, float *xyz, float *norm, float *colr); static void yglQstripNoArr(long nvert, float *xyz, float *norm, float *colr); static void yglQstripNoArrAlpha(long nvert, float *xyz, float *norm, float *colr); static void yglQstripNoArrNoLite(long nvert, float *xyz, float *colr); static void yglQstripNoArrNoLiteAlpha(long nvert, float *xyz, float *colr); static void yglQstripArrAlpha(long nvert, float *xyz, float *norm, float *colr); /* #define CHEK_ERROR(x) yygl_chek_error(x) */ #define CHEK_ERROR(x) void yglTstrips(long nstrip, long *len, float *xyz, float *norm, float *colr, long edge, long smooth, long do_light) { /* The input is a list of triangle strips. There is one color per triangle. There is one normal per vertex or one normal per triangle (depending on smooth), or none for no lighting. */ long i, num, vert, ntri; float oldSpec; if(alpha_pass) return; yglSetPolyMode(edge); if(smooth) { /* use smooth shading */ yglSetShade(1); } else { /* use flat shading */ yglSetShade(0); } yglUpdateProperties(); if(!do_light) { oldSpec= yglGetMatSpec(); yglSetMatSpec(0.0); /* turn off specular highlights */ /* triangles are not lit */ yglSetColorType(0); if(glCurrWin3d->use_array) { for(i= 0, vert= 0, ntri= 0; i < nstrip; i++) { num= len[i]; yglTstripArrNoLite(num, xyz+vert*3, colr+3*ntri); vert += num; ntri += num-2; } } else { for(i= 0, vert= 0, ntri= 0; i < nstrip; i++) { num= len[i]; yglTstripNoArrNoLite(num, xyz+vert*3, colr+3*ntri); vert += num; ntri += num-2; } } yglSetMatSpec(oldSpec); } else if(smooth) { /* smooth shading */ yglSetColorType(1); if(glCurrWin3d->use_array) { for(i= 0, vert= 0, ntri= 0; i < nstrip; i++) { num= len[i]; yglTstripSmArr(num, xyz+vert*3, norm+vert*3, colr+3*ntri); vert += num; ntri += num-2; } } else { yglTstripsSmNoArr(nstrip, len, xyz, norm, colr); } } else { /* flat shading */ yglSetColorType(1); if(glCurrWin3d->use_array) { for(i= 0, vert= 0, ntri= 0; i < nstrip; i++) { num= len[i]; yglTstripArr(num, xyz+vert*3, norm+ntri*3, colr+3*ntri); vert += num; ntri += num-2; } } else { for(i= 0, vert= 0, ntri= 0; i < nstrip; i++) { num= len[i]; yglTstripNoArr(num, xyz+vert*3, norm+ntri*3, colr+3*ntri); vert += num; ntri += num-2; } } } } void yglTstripsAlpha(long nstrip, long *len, float *xyz, float *norm, float *colr, long edge, long smooth, long do_light) { /* The input is a list of triangle strips. There is one color per triangle. There is one normal per vertex or one normal per triangle (depending on smooth), or none for no lighting. */ long i, num, vert, ntri; float oldSpec; #if 0 GLfloat mat_white[]= {1.0, 1.0, 1.0, 1.0}; GLfloat mat_transparent[]= {0.0f, 0.0f, 0.0f, 0.3f}; GLfloat mat_emission[]= {0.0f, 1.0f, 0.0f, 0.3f}; GLfloat mat_nul[]= {0.0, 0.0, 0.0, 1.0}; #endif if(!alpha_pass) return; glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDepthMask(GL_FALSE); yglSetPolyMode(edge); if(smooth) { /* use smooth shading */ yglSetShade(1); } else { /* use flat shading */ yglSetShade(0); } if(!do_light) { oldSpec= yglGetMatSpec(); yglSetMatSpec(0.0); /* turn off specular highlights */ /* triangles are not lit */ yglSetColorType(0); yglUpdateProperties(); if(glCurrWin3d->use_array) { for(i= 0, vert= 0, ntri= 0; i < nstrip; i++) { num= len[i]; yglTstripArrNoLiteAlpha(num, xyz+vert*3, colr+4*ntri); vert += num; ntri += num-2; } } else { for(i= 0, vert= 0, ntri= 0; i < nstrip; i++) { num= len[i]; yglTstripNoArrNoLiteAlpha(num, xyz+vert*3, colr+4*ntri); vert += num; ntri += num-2; } } yglSetMatSpec(oldSpec); } else if(smooth) { /* smooth shading */ yglSetColorType(1); /* set ambient and diffuse color */ yglUpdateProperties(); if(glCurrWin3d->use_array) { for(i= 0, vert= 0, ntri= 0; i < nstrip; i++) { num= len[i]; yglTstripSmArrAlpha(num, xyz+vert*3, norm+vert*3, colr+4*ntri); vert += num; ntri += num-2; } } else { yglTstripsSmNoArrAlpha(nstrip, len, xyz, norm, colr); } } else { /* flat shading */ yglSetColorType(1); yglUpdateProperties(); if(glCurrWin3d->use_array) { for(i= 0, vert= 0, ntri= 0; i < nstrip; i++) { num= len[i]; yglTstripArrAlpha(num, xyz+vert*3, norm+ntri*3, colr+4*ntri); vert += num; ntri += num-2; } } else { for(i= 0, vert= 0, ntri= 0; i < nstrip; i++) { num= len[i]; yglTstripNoArrAlpha(num, xyz+vert*3, norm+ntri*3, colr+4*ntri); vert += num; ntri += num-2; } } } glDepthMask(GL_TRUE); glDisable(GL_BLEND); } void yglQstrips(long nstrip, long *len, float *xyz, float *norm, float *colr, long edge, long smooth, long do_light) { /* The input is a list of quad strips. There is one color per quad. There is one normal per vertex or one normal per quad (depending on smooth). */ long i, num, vert, nquad; float oldSpec; if(alpha_pass) return; yglSetPolyMode(edge); if(smooth) { /* use smooth shading */ yglSetShade(1); } else { /* use flat shading */ yglSetShade(0); } yglUpdateProperties(); if(!do_light) { oldSpec= yglGetMatSpec(); yglSetMatSpec(0.0); /* turn off specular highlights */ /* quads are not lit */ yglSetColorType(0); if(glCurrWin3d->use_array) { for(i= 0, vert= 0, nquad= 0; i < nstrip; i++) { num= len[i]; yglQstripArrNoLite(num, xyz+vert*3, colr+3*nquad); vert += num; nquad += num-1; } } else { for(i= 0, vert= 0, nquad= 0; i < nstrip; i++) { num= len[i]; yglQstripNoArrNoLite(num, xyz+vert*3, colr+3*nquad); vert += num; nquad += num-1; } } yglSetMatSpec(oldSpec); } else if(smooth) { /* smooth shading */ yglSetColorType(1); if(glCurrWin3d->use_array) { for(i= 0, vert= 0, nquad= 0; i < nstrip; i++) { num= len[i]; yglQstripSmArr(num, xyz+vert*3, norm+vert*3, colr+3*nquad); vert += num; nquad += num-1; } } else { yglQstripsSmNoArr(nstrip, len, xyz, norm, colr); } } else { /* flat shading */ yglSetColorType(1); if(glCurrWin3d->use_array) { for(i= 0, vert= 0, nquad= 0; i < nstrip; i++) { num= len[i]; yglQstripArr(num, xyz+vert*3, norm+nquad*3, colr+3*nquad); vert += num; nquad += num-1; } } else { for(i= 0, vert= 0, nquad= 0; i < nstrip; i++) { num= len[i]; yglQstripNoArr(num, xyz+vert*3, norm+nquad*3, colr+3*nquad); vert += num; nquad += num-1; } } } } void yglQstripsAlpha(long nstrip, long *len, float *xyz, float *norm, float *colr, long edge, long smooth, long do_light) { /* The input is a list of quad strips. There is one color per quad. There is one normal per vertex or one normal per quad (depending on smooth). */ long i, num, vert, nquad; float oldSpec; if(!alpha_pass) return; glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); yglSetPolyMode(edge); if(smooth) { /* use smooth shading */ yglSetShade(1); } else { /* use flat shading */ yglSetShade(0); } yglUpdateProperties(); if(!do_light) { oldSpec= yglGetMatSpec(); yglSetMatSpec(0.0); /* turn off specular highlights */ /* quads are not lit */ yglSetColorType(0); if(glCurrWin3d->use_array) { for(i= 0, vert= 0, nquad= 0; i < nstrip; i++) { num= len[i]; yglQstripArrNoLiteAlpha(num, xyz+vert*3, colr+4*nquad); vert += num; nquad += num-1; } } else { for(i= 0, vert= 0, nquad= 0; i < nstrip; i++) { num= len[i]; yglQstripNoArrNoLiteAlpha(num, xyz+vert*3, colr+4*nquad); vert += num; nquad += num-1; } } yglSetMatSpec(oldSpec); } else if(smooth) { /* smooth shading */ yglSetColorType(1); if(glCurrWin3d->use_array) { for(i= 0, vert= 0, nquad= 0; i < nstrip; i++) { num= len[i]; yglQstripSmArrAlpha(num, xyz+vert*3, norm+vert*3, colr+4*nquad); vert += num; nquad += num-1; } } else { yglQstripsSmNoArrAlpha(nstrip, len, xyz, norm, colr); } } else { /* flat shading */ yglSetColorType(1); if(glCurrWin3d->use_array) { for(i= 0, vert= 0, nquad= 0; i < nstrip; i++) { num= len[i]; yglQstripArrAlpha(num, xyz+vert*3, norm+nquad*3, colr+4*nquad); vert += num; nquad += num-1; } } else { for(i= 0, vert= 0, nquad= 0; i < nstrip; i++) { num= len[i]; yglQstripNoArrAlpha(num, xyz+vert*3, norm+nquad*3, colr+4*nquad); vert += num; nquad += num-1; } } } glDisable(GL_BLEND); } void yglTstripsSmNoArr(long nstrip, long *len, float *xyz, float *norm, float *colr) { long i, i3, num; float old_red= -1.0, old_green= -1.0, old_blue= -1.0; for(i= 0; i < nstrip; i++) { num= len[i]; /* number of vertices in this strip */ /* draw the strip */ DEMAND(num > 2, "triangle strip with less than 3 vertices in yglTstripsSmNoArr") glBegin(GL_TRIANGLE_STRIP); if(colr[0] != old_red || colr[1] != old_green || colr[2] != old_blue) { old_red= colr[0]; old_green= colr[1]; old_blue= colr[2]; glColor3fv(colr); } glNormal3fv(norm); glVertex3fv(xyz); glNormal3fv(norm+3); glVertex3fv(xyz+3); norm += 6; xyz += 6; for(i3= 0; i3 < num-2; i3++) { /* NOTE: It makes no difference in local performance if the coords are converted to floats before being stored in the display list */ if(colr[0] != old_red || colr[1] != old_green || colr[2] != old_blue) { old_red= colr[0]; old_green= colr[1]; old_blue= colr[2]; glColor3fv(colr); } glNormal3fv(norm); glVertex3fv(xyz); colr += 3; xyz += 3; norm += 3; } glEnd(); } CHEK_ERROR("yglTstripsSmNoArr"); } void yglTstripsSmNoArrAlpha(long nstrip, long *len, float *xyz, float *norm, float *colr) { long i, i3, num; float old_red= -1.0, old_green= -1.0, old_blue= -1.0, old_alpha= -1.0; for(i= 0; i < nstrip; i++) { num= len[i]; /* number of vertices in this strip */ /* draw the strip */ DEMAND(num > 2, "triangle strip with less than 3 vertices in yglTstripsSmNoArrAlpha") glBegin(GL_TRIANGLE_STRIP); if(colr[0] != old_red || colr[1] != old_green || colr[2] != old_blue || colr[3] != old_alpha) { old_red= colr[0]; old_green= colr[1]; old_blue= colr[2]; old_alpha= colr[3]; glColor4fv(colr); } glNormal3fv(norm); glVertex3fv(xyz); glNormal3fv(norm+3); glVertex3fv(xyz+3); norm += 6; xyz += 6; for(i3= 0; i3 < num-2; i3++) { /* NOTE: It makes no difference in local performance if the coords are converted to floats before being stored in the display list */ if(colr[0] != old_red || colr[1] != old_green || colr[2] != old_blue || colr[3] != old_alpha) { old_red= colr[0]; old_green= colr[1]; old_blue= colr[2]; old_alpha= colr[3]; glColor4fv(colr); } glNormal3fv(norm); glVertex3fv(xyz); colr += 4; xyz += 3; norm += 3; } glEnd(); } CHEK_ERROR("yglTstripsSmNoArrAlpha"); } void yglTstripSmNoArr(long nvert, float *xyz, float *norm, float *colr) { long i3; float old_red, old_green, old_blue; /* draw the strip */ if(nvert <= 2) return; glBegin(GL_TRIANGLE_STRIP); old_red= colr[0]; old_green= colr[1]; old_blue= colr[2]; glColor3fv(colr); glNormal3fv(norm); glVertex3fv(xyz); glNormal3fv(norm+3); glVertex3fv(xyz+3); for(i3= 0; i3 < 3*(nvert-2); i3 += 3) { /* NOTE: It makes no difference in local performance if the coords are converted to floats before being stored in the display list */ if(colr[i3] != old_red || colr[i3+1] != old_green || colr[i3+2] != old_blue) { old_red= colr[i3]; old_green= colr[i3+1]; old_blue= colr[i3+2]; glColor3fv(colr+i3); } glNormal3fv(norm+i3+6); glVertex3fv(xyz+i3+6); } glEnd(); CHEK_ERROR("yglTstripSmNoArr"); } void yglQstripsSmNoArr(long nstrip, long *len, float *xyz, float *norm, float *colr) { long i, i3, num; float old_red= -1.0, old_green= -1.0, old_blue= -1.0; for(i= 0; i < nstrip; i++) { num= len[i]; /* number of vertices on one edge of this strip */ DEMAND(num > 1, "quad strip with less than 2 vertices in yglQstripsSmNoArr"); glBegin(GL_QUAD_STRIP); if(colr[0] != old_red || colr[1] != old_green || colr[2] != old_blue) { old_red= colr[0]; old_green= colr[1]; old_blue= colr[2]; glColor3fv(colr); } glNormal3fv(norm); glVertex3fv(xyz); glNormal3fv(norm+3); glVertex3fv(xyz+3); norm += 6; xyz += 6; for(i3= 0; i3 < num-1; i3++) { /* NOTE: It makes no difference in local performance if the coords are converted to floats before being stored in the display list */ if(colr[0] != old_red || colr[1] != old_green || colr[2] != old_blue) { old_red= colr[0]; old_green= colr[1]; old_blue= colr[2]; glColor3fv(colr); } glNormal3fv(norm); glVertex3fv(xyz); glNormal3fv(norm+3); glVertex3fv(xyz+3); colr += 3; xyz += 6; norm += 6; } glEnd(); } CHEK_ERROR("yglQstripsSmNoArr"); } void yglQstripsSmNoArrAlpha(long nstrip, long *len, float *xyz, float *norm, float *colr) { long i, i3, num; float old_red= -1.0, old_green= -1.0, old_blue= -1.0, old_alpha= -1.0; for(i= 0; i < nstrip; i++) { num= len[i]; /* number of vertices on one edge of this strip */ DEMAND(num > 1,"quad strip with less than 2 vertices in yglQstripsSmNoArrAlpha") glBegin(GL_QUAD_STRIP); if(colr[0] != old_red || colr[1] != old_green || colr[2] != old_blue || colr[3] != old_alpha) { old_red= colr[0]; old_green= colr[1]; old_blue= colr[2]; old_alpha= colr[3]; glColor4fv(colr); } glNormal3fv(norm); glVertex3fv(xyz); glNormal3fv(norm+3); glVertex3fv(xyz+3); norm += 6; xyz += 6; for(i3= 0; i3 < num-1; i3++) { /* NOTE: It makes no difference in local performance if the coords are converted to floats before being stored in the display list */ if(colr[0] != old_red || colr[1] != old_green || colr[2] != old_blue || colr[3] != old_alpha) { old_red= colr[0]; old_green= colr[1]; old_blue= colr[2]; old_alpha= colr[3]; glColor4fv(colr); } glNormal3fv(norm); glVertex3fv(xyz); glNormal3fv(norm+3); glVertex3fv(xyz+3); colr += 4; xyz += 6; norm += 6; } glEnd(); } CHEK_ERROR("yglQstripsSmNoArrAlpha"); } void yglQstripSmNoArr(long nvert, float *xyz, float *norm, float *colr) { long i3, i6; /* draw the strip */ if(nvert <= 1) return; glBegin(GL_QUAD_STRIP); glColor3fv(colr); glNormal3fv(norm); glVertex3fv(xyz); glNormal3fv(norm+3); glVertex3fv(xyz+3); for(i3= 0, i6= 6; i3 < 3*(nvert-1); i3 += 3, i6 += 6) { /* NOTE: It makes no difference in local performance if the coords are converted to floats before being stored in the display list */ glColor3fv(colr+i3); glNormal3fv(norm+i6); glVertex3fv(xyz+i6); glNormal3fv(norm+i6+3); glVertex3fv(xyz+i6+3); } glEnd(); CHEK_ERROR("yglQstripSmNoArr"); } void yglTstripSmArr(long nvert, float *xyz, float *norm, float *colr) { long i3; float *arr_colr, *arr_norm, *arr_vert; long ind_colr, ind_vert; /* draw the strip */ if(nvert <= 2) return; /* make an array big enough to hold all the colors, normals, and vertices for the quad strip */ ind_colr= ind_vert= 0; arr_colr= (float *)p_malloc(3*nvert*sizeof(float)); arr_norm= (float *)p_malloc(3*nvert*sizeof(float)); arr_vert= (float *)p_malloc(3*nvert*sizeof(float)); arr_colr[ind_colr++]= colr[0]; arr_colr[ind_colr++]= colr[1]; arr_colr[ind_colr++]= colr[2]; arr_colr[ind_colr++]= colr[0]; arr_colr[ind_colr++]= colr[1]; arr_colr[ind_colr++]= colr[2]; for(i3= 0; i3 < 3*(nvert-2); i3 += 3) { arr_colr[ind_colr++]= colr[i3]; arr_colr[ind_colr++]= colr[i3+1]; arr_colr[ind_colr++]= colr[i3+2]; } for(i3= 0; i3 < 3*nvert; i3 += 3) { arr_norm[ind_vert]= norm[i3]; arr_vert[ind_vert++]= xyz[i3]; arr_norm[ind_vert]= norm[i3+1]; arr_vert[ind_vert++]= xyz[i3+1]; arr_norm[ind_vert]= norm[i3+2]; arr_vert[ind_vert++]= xyz[i3+2]; } /* NOTE: for each enabled array, a corresponding array must be defined and have data filled in before a call to glDrawArrays, because that call will use data from each enabled array */ glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glColorPointer(3, GL_FLOAT, 0, arr_colr); glNormalPointer(GL_FLOAT, 0, arr_norm); glVertexPointer(3, GL_FLOAT, 0, arr_vert); /* draw all triangles/quads using previously specified colors, vertices, and normals */ glDrawArrays(GL_TRIANGLE_STRIP, 0, nvert); /* free up the storage */ glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_COLOR_ARRAY); p_free(arr_colr); p_free(arr_norm); p_free(arr_vert); CHEK_ERROR("yglTstripSmArr"); } void yglTstripSmArrAlpha(long nvert, float *xyz, float *norm, float *colr) { long i3; float *arr_colr, *arr_norm, *arr_vert; long ind_colr, ind_vert; /* draw the strip */ if(nvert <= 2) return; /* make an array big enough to hold all the colors, normals, and vertices for the quad strip */ ind_colr= ind_vert= 0; arr_colr= (float *)p_malloc(4*nvert*sizeof(float)); arr_norm= (float *)p_malloc(3*nvert*sizeof(float)); arr_vert= (float *)p_malloc(3*nvert*sizeof(float)); arr_colr[ind_colr++]= colr[0]; arr_colr[ind_colr++]= colr[1]; arr_colr[ind_colr++]= colr[2]; arr_colr[ind_colr++]= colr[3]; arr_colr[ind_colr++]= colr[0]; arr_colr[ind_colr++]= colr[1]; arr_colr[ind_colr++]= colr[2]; arr_colr[ind_colr++]= colr[3]; for(i3= 0; i3 < 4*(nvert-2); i3 += 4) { arr_colr[ind_colr++]= colr[i3]; arr_colr[ind_colr++]= colr[i3+1]; arr_colr[ind_colr++]= colr[i3+2]; arr_colr[ind_colr++]= colr[i3+3]; } for(i3= 0; i3 < 3*nvert; i3 += 3) { arr_norm[ind_vert]= norm[i3]; arr_vert[ind_vert++]= xyz[i3]; arr_norm[ind_vert]= norm[i3+1]; arr_vert[ind_vert++]= xyz[i3+1]; arr_norm[ind_vert]= norm[i3+2]; arr_vert[ind_vert++]= xyz[i3+2]; } /* NOTE: for each enabled array, a corresponding array must be defined and have data filled in before a call to glDrawArrays, because that call will use data from each enabled array */ glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glColorPointer(4, GL_FLOAT, 0, arr_colr); glNormalPointer(GL_FLOAT, 0, arr_norm); glVertexPointer(3, GL_FLOAT, 0, arr_vert); /* draw all triangles/quads using previously specified colors, vertices, and normals */ glDrawArrays(GL_TRIANGLE_STRIP, 0, nvert); /* free up the storage */ glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_COLOR_ARRAY); p_free(arr_colr); p_free(arr_norm); p_free(arr_vert); CHEK_ERROR("yglTstripSmArr"); } void yglQstripSmArr(long nvert, float *xyz, float *norm, float *colr) { long i3, i6; float *arr_colr, *arr_norm, *arr_vert; long ind_colr, ind_vert; /* draw the strip */ if(nvert <= 1) return; /* make an array big enough to hold all the colors, normals, and vertices for the quad strip */ ind_colr= ind_vert= 0; arr_colr= (float *)p_malloc(6*nvert*sizeof(float)); arr_norm= (float *)p_malloc(6*nvert*sizeof(float)); arr_vert= (float *)p_malloc(6*nvert*sizeof(float)); arr_colr[ind_colr++]= colr[0]; arr_colr[ind_colr++]= colr[1]; arr_colr[ind_colr++]= colr[2]; arr_colr[ind_colr++]= colr[0]; arr_colr[ind_colr++]= colr[1]; arr_colr[ind_colr++]= colr[2]; for(i3= 0; i3 < 3*(nvert-1); i3 += 3) { arr_colr[ind_colr++]= colr[i3]; arr_colr[ind_colr++]= colr[i3+1]; arr_colr[ind_colr++]= colr[i3+2]; arr_colr[ind_colr++]= colr[i3]; arr_colr[ind_colr++]= colr[i3+1]; arr_colr[ind_colr++]= colr[i3+2]; } for(i6= 0; i6 < 6*nvert; i6 += 6) { arr_norm[ind_vert]= norm[i6]; arr_vert[ind_vert++]= xyz[i6]; arr_norm[ind_vert]= norm[i6+1]; arr_vert[ind_vert++]= xyz[i6+1]; arr_norm[ind_vert]= norm[i6+2]; arr_vert[ind_vert++]= xyz[i6+2]; arr_norm[ind_vert]= norm[i6+3]; arr_vert[ind_vert++]= xyz[i6+3]; arr_norm[ind_vert]= norm[i6+4]; arr_vert[ind_vert++]= xyz[i6+4]; arr_norm[ind_vert]= norm[i6+5]; arr_vert[ind_vert++]= xyz[i6+5]; } /* NOTE: for each enabled array, a corresponding array must be defined and have data filled in before a call to glDrawArrays, because that call will use data from each enabled array */ glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glColorPointer(3, GL_FLOAT, 0, arr_colr); glNormalPointer(GL_FLOAT, 0, arr_norm); glVertexPointer(3, GL_FLOAT, 0, arr_vert); /* draw all triangles/quads using previously specified colors, vertices, and normals */ glDrawArrays(GL_QUAD_STRIP, 0, 2*nvert); /* free up the storage */ glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_COLOR_ARRAY); p_free(arr_colr); p_free(arr_norm); p_free(arr_vert); CHEK_ERROR("yglQstripSmArr"); } void yglQstripSmArrAlpha(long nvert, float *xyz, float *norm, float *colr) { long i3, i6; float *arr_colr, *arr_norm, *arr_vert; long ind_colr, ind_vert; /* draw the strip */ if(nvert <= 1) return; /* make an array big enough to hold all the colors, normals, and vertices for the quad strip */ ind_colr= ind_vert= 0; arr_colr= (float *)p_malloc(8*nvert*sizeof(float)); arr_norm= (float *)p_malloc(6*nvert*sizeof(float)); arr_vert= (float *)p_malloc(6*nvert*sizeof(float)); arr_colr[ind_colr++]= colr[0]; arr_colr[ind_colr++]= colr[1]; arr_colr[ind_colr++]= colr[2]; arr_colr[ind_colr++]= colr[3]; arr_colr[ind_colr++]= colr[0]; arr_colr[ind_colr++]= colr[1]; arr_colr[ind_colr++]= colr[2]; arr_colr[ind_colr++]= colr[3]; for(i3= 0; i3 < 4*(nvert-1); i3 += 4) { arr_colr[ind_colr++]= colr[i3]; arr_colr[ind_colr++]= colr[i3+1]; arr_colr[ind_colr++]= colr[i3+2]; arr_colr[ind_colr++]= colr[i3+3]; arr_colr[ind_colr++]= colr[i3]; arr_colr[ind_colr++]= colr[i3+1]; arr_colr[ind_colr++]= colr[i3+2]; arr_colr[ind_colr++]= colr[i3+3]; } for(i6= 0; i6 < 6*nvert; i6 += 6) { arr_norm[ind_vert]= norm[i6]; arr_vert[ind_vert++]= xyz[i6]; arr_norm[ind_vert]= norm[i6+1]; arr_vert[ind_vert++]= xyz[i6+1]; arr_norm[ind_vert]= norm[i6+2]; arr_vert[ind_vert++]= xyz[i6+2]; arr_norm[ind_vert]= norm[i6+3]; arr_vert[ind_vert++]= xyz[i6+3]; arr_norm[ind_vert]= norm[i6+4]; arr_vert[ind_vert++]= xyz[i6+4]; arr_norm[ind_vert]= norm[i6+5]; arr_vert[ind_vert++]= xyz[i6+5]; } /* NOTE: for each enabled array, a corresponding array must be defined and have data filled in before a call to glDrawArrays, because that call will use data from each enabled array */ glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glColorPointer(4, GL_FLOAT, 0, arr_colr); glNormalPointer(GL_FLOAT, 0, arr_norm); glVertexPointer(3, GL_FLOAT, 0, arr_vert); /* draw all triangles/quads using previously specified colors, vertices, and normals */ glDrawArrays(GL_QUAD_STRIP, 0, 2*nvert); /* free up the storage */ glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_COLOR_ARRAY); p_free(arr_colr); p_free(arr_norm); p_free(arr_vert); CHEK_ERROR("yglQstripSmArr"); } void yglTstripArr(long nvert, float *xyz, float *norm, float *colr) { long i3; float *arr_colr, *arr_norm, *arr_vert; long ind_colr, ind_norm, ind_vert; /* draw the strip */ if(nvert <= 2) return; /* make an array big enough to hold all the colors, normals, and vertices for the quad strip */ ind_colr= ind_norm= ind_vert= 0; arr_colr= (float *)p_malloc(3*nvert*sizeof(float)); arr_norm= (float *)p_malloc(3*nvert*sizeof(float)); arr_vert= (float *)p_malloc(3*nvert*sizeof(float)); arr_colr[ind_colr++]= colr[0]; arr_colr[ind_colr++]= colr[1]; arr_colr[ind_colr++]= colr[2]; arr_norm[ind_norm++]= norm[0]; arr_norm[ind_norm++]= norm[1]; arr_norm[ind_norm++]= norm[2]; arr_colr[ind_colr++]= colr[0]; arr_colr[ind_colr++]= colr[1]; arr_colr[ind_colr++]= colr[2]; arr_norm[ind_norm++]= norm[0]; arr_norm[ind_norm++]= norm[1]; arr_norm[ind_norm++]= norm[2]; for(i3= 0; i3 < 3*(nvert-2); i3 += 3) { arr_colr[ind_colr++]= colr[i3]; arr_colr[ind_colr++]= colr[i3+1]; arr_colr[ind_colr++]= colr[i3+2]; arr_norm[ind_norm++]= norm[i3]; arr_norm[ind_norm++]= norm[i3+1]; arr_norm[ind_norm++]= norm[i3+2]; } for(i3= 0; i3 < 3*nvert; i3 += 3) { arr_vert[ind_vert++]= xyz[i3]; arr_vert[ind_vert++]= xyz[i3+1]; arr_vert[ind_vert++]= xyz[i3+2]; } /* NOTE: for each enabled array, a corresponding array must be defined and have data filled in before a call to glDrawArrays, because that call will use data from each enabled array */ glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glColorPointer(3, GL_FLOAT, 0, arr_colr); glNormalPointer(GL_FLOAT, 0, arr_norm); glVertexPointer(3, GL_FLOAT, 0, arr_vert); /* draw all triangles/quads using previously specified colors, vertices, and normals */ glDrawArrays(GL_TRIANGLE_STRIP, 0, nvert); /* free up the storage */ glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_COLOR_ARRAY); p_free(arr_colr); p_free(arr_norm); p_free(arr_vert); CHEK_ERROR("yglTstripArr"); } void yglTstripArrAlpha(long nvert, float *xyz, float *norm, float *colr) { long i3, ic4; float *arr_colr, *arr_norm, *arr_vert; long ind_colr, ind_norm, ind_vert; /* draw the strip */ if(nvert <= 2) return; /* make an array big enough to hold all the colors, normals, and vertices for the quad strip */ ind_colr= ind_norm= ind_vert= 0; arr_colr= (float *)p_malloc(4*nvert*sizeof(float)); arr_norm= (float *)p_malloc(3*nvert*sizeof(float)); arr_vert= (float *)p_malloc(3*nvert*sizeof(float)); arr_colr[ind_colr++]= colr[0]; arr_colr[ind_colr++]= colr[1]; arr_colr[ind_colr++]= colr[2]; arr_colr[ind_colr++]= colr[3]; arr_norm[ind_norm++]= norm[0]; arr_norm[ind_norm++]= norm[1]; arr_norm[ind_norm++]= norm[2]; arr_colr[ind_colr++]= colr[0]; arr_colr[ind_colr++]= colr[1]; arr_colr[ind_colr++]= colr[2]; arr_colr[ind_colr++]= colr[3]; arr_norm[ind_norm++]= norm[0]; arr_norm[ind_norm++]= norm[1]; arr_norm[ind_norm++]= norm[2]; for(i3= 0, ic4= 0; i3 < 3*(nvert-2); i3 += 3, ic4 += 4) { arr_colr[ind_colr++]= colr[ic4]; arr_colr[ind_colr++]= colr[ic4+1]; arr_colr[ind_colr++]= colr[ic4+2]; arr_colr[ind_colr++]= colr[ic4+3]; arr_norm[ind_norm++]= norm[i3]; arr_norm[ind_norm++]= norm[i3+1]; arr_norm[ind_norm++]= norm[i3+2]; } for(i3= 0; i3 < 3*nvert; i3 += 3) { arr_vert[ind_vert++]= xyz[i3]; arr_vert[ind_vert++]= xyz[i3+1]; arr_vert[ind_vert++]= xyz[i3+2]; } /* NOTE: for each enabled array, a corresponding array must be defined and have data filled in before a call to glDrawArrays, because that call will use data from each enabled array */ glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glColorPointer(4, GL_FLOAT, 0, arr_colr); glNormalPointer(GL_FLOAT, 0, arr_norm); glVertexPointer(3, GL_FLOAT, 0, arr_vert); /* draw all triangles/quads using previously specified colors, vertices, and normals */ glDrawArrays(GL_TRIANGLE_STRIP, 0, nvert); /* free up the storage */ glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_COLOR_ARRAY); p_free(arr_colr); p_free(arr_norm); p_free(arr_vert); CHEK_ERROR("yglTstripArrAlpha"); } void yglQstripArr(long nvert, float *xyz, float *norm, float *colr) { long i3, i6; float *arr_colr, *arr_norm, *arr_vert; long ind_colr, ind_norm, ind_vert; /* draw the strip */ if(nvert <= 1) return; /* make an array big enough to hold all the colors, normals, and vertices for the quad strip */ ind_colr= ind_norm= ind_vert= 0; arr_colr= (float *)p_malloc(6*nvert*sizeof(float)); arr_norm= (float *)p_malloc(6*nvert*sizeof(float)); arr_vert= (float *)p_malloc(6*nvert*sizeof(float)); arr_colr[ind_colr++]= colr[0]; arr_colr[ind_colr++]= colr[1]; arr_colr[ind_colr++]= colr[2]; arr_colr[ind_colr++]= colr[0]; arr_colr[ind_colr++]= colr[1]; arr_colr[ind_colr++]= colr[2]; arr_norm[ind_norm++]= norm[0]; arr_norm[ind_norm++]= norm[1]; arr_norm[ind_norm++]= norm[2]; arr_norm[ind_norm++]= norm[0]; arr_norm[ind_norm++]= norm[1]; arr_norm[ind_norm++]= norm[2]; for(i3= 0; i3 < 3*(nvert-1); i3 += 3) { arr_colr[ind_colr++]= colr[i3]; arr_colr[ind_colr++]= colr[i3+1]; arr_colr[ind_colr++]= colr[i3+2]; arr_colr[ind_colr++]= colr[i3]; arr_colr[ind_colr++]= colr[i3+1]; arr_colr[ind_colr++]= colr[i3+2]; arr_norm[ind_norm++]= norm[i3]; arr_norm[ind_norm++]= norm[i3+1]; arr_norm[ind_norm++]= norm[i3+2]; arr_norm[ind_norm++]= norm[i3]; arr_norm[ind_norm++]= norm[i3+1]; arr_norm[ind_norm++]= norm[i3+2]; } for(i6= 0; i6 < 6*nvert; i6 += 6) { arr_vert[ind_vert++]= xyz[i6]; arr_vert[ind_vert++]= xyz[i6+1]; arr_vert[ind_vert++]= xyz[i6+2]; arr_vert[ind_vert++]= xyz[i6+3]; arr_vert[ind_vert++]= xyz[i6+4]; arr_vert[ind_vert++]= xyz[i6+5]; } /* NOTE: for each enabled array, a corresponding array must be defined and have data filled in before a call to glDrawArrays, because that call will use data from each enabled array */ glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glColorPointer(3, GL_FLOAT, 0, arr_colr); glNormalPointer(GL_FLOAT, 0, arr_norm); glVertexPointer(3, GL_FLOAT, 0, arr_vert); /* draw all triangles/quads using previously specified colors, vertices, and normals */ glDrawArrays(GL_QUAD_STRIP, 0, 2*nvert); /* free up the storage */ glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_COLOR_ARRAY); p_free(arr_colr); p_free(arr_norm); p_free(arr_vert); CHEK_ERROR("yglQstripArr"); } void yglQstripArrAlpha(long nvert, float *xyz, float *norm, float *colr) { long i3, i6, ic4; float *arr_colr, *arr_norm, *arr_vert; long ind_colr, ind_norm, ind_vert; /* draw the strip */ if(nvert <= 1) return; /* make an array big enough to hold all the colors, normals, and vertices for the quad strip */ ind_colr= ind_norm= ind_vert= 0; arr_colr= (float *)p_malloc(8*nvert*sizeof(float)); arr_norm= (float *)p_malloc(6*nvert*sizeof(float)); arr_vert= (float *)p_malloc(6*nvert*sizeof(float)); arr_colr[ind_colr++]= colr[0]; arr_colr[ind_colr++]= colr[1]; arr_colr[ind_colr++]= colr[2]; arr_colr[ind_colr++]= colr[3]; arr_colr[ind_colr++]= colr[0]; arr_colr[ind_colr++]= colr[1]; arr_colr[ind_colr++]= colr[2]; arr_colr[ind_colr++]= colr[3]; arr_norm[ind_norm++]= norm[0]; arr_norm[ind_norm++]= norm[1]; arr_norm[ind_norm++]= norm[2]; arr_norm[ind_norm++]= norm[0]; arr_norm[ind_norm++]= norm[1]; arr_norm[ind_norm++]= norm[2]; for(i3= 0, ic4= 0; i3 < 3*(nvert-1); i3 += 3, ic4 += 4) { arr_colr[ind_colr++]= colr[ic4]; arr_colr[ind_colr++]= colr[ic4+1]; arr_colr[ind_colr++]= colr[ic4+2]; arr_colr[ind_colr++]= colr[ic4+3]; arr_colr[ind_colr++]= colr[ic4]; arr_colr[ind_colr++]= colr[ic4+1]; arr_colr[ind_colr++]= colr[ic4+2]; arr_colr[ind_colr++]= colr[ic4+3]; arr_norm[ind_norm++]= norm[i3]; arr_norm[ind_norm++]= norm[i3+1]; arr_norm[ind_norm++]= norm[i3+2]; arr_norm[ind_norm++]= norm[i3]; arr_norm[ind_norm++]= norm[i3+1]; arr_norm[ind_norm++]= norm[i3+2]; } for(i6= 0; i6 < 6*nvert; i6 += 6) { arr_vert[ind_vert++]= xyz[i6]; arr_vert[ind_vert++]= xyz[i6+1]; arr_vert[ind_vert++]= xyz[i6+2]; arr_vert[ind_vert++]= xyz[i6+3]; arr_vert[ind_vert++]= xyz[i6+4]; arr_vert[ind_vert++]= xyz[i6+5]; } /* NOTE: for each enabled array, a corresponding array must be defined and have data filled in before a call to glDrawArrays, because that call will use data from each enabled array */ glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glColorPointer(4, GL_FLOAT, 0, arr_colr); glNormalPointer(GL_FLOAT, 0, arr_norm); glVertexPointer(3, GL_FLOAT, 0, arr_vert); /* draw all triangles/quads using previously specified colors, vertices, and normals */ glDrawArrays(GL_QUAD_STRIP, 0, 2*nvert); /* free up the storage */ glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_COLOR_ARRAY); p_free(arr_colr); p_free(arr_norm); p_free(arr_vert); CHEK_ERROR("yglQstripArr"); } void yglTstripNoArr(long nvert, float *xyz, float *norm, float *colr) { long i3; double old_red, old_green, old_blue; /* draw the strip */ if(nvert <= 2) return; glBegin(GL_TRIANGLE_STRIP); glColor3fv(colr); old_red= colr[0]; old_green= colr[1]; old_blue= colr[2]; glVertex3fv(xyz); glVertex3fv(xyz+3); for(i3= 0; i3 < 3*(nvert-2); i3 += 3) { if(colr[i3] != old_red || colr[i3+1] != old_green || colr[i3+2] != old_blue) { glColor3fv(colr+i3); old_red= colr[i3]; old_green= colr[i3+1]; old_blue= colr[i3+2]; } glNormal3fv(norm+i3); /* NOTE: It makes no difference in local performance if the coords are converted to floats before being stored in the display list */ glVertex3fv(xyz+i3+6); } glEnd(); CHEK_ERROR("yglTstripNoArr"); } void yglTstripNoArrAlpha(long nvert, float *xyz, float *norm, float *colr) { long i3; double old_red, old_green, old_blue, old_alpha; /* draw the strip */ if(nvert <= 2) return; glBegin(GL_TRIANGLE_STRIP); glColor4fv(colr); old_red= colr[0]; old_green= colr[1]; old_blue= colr[2]; old_alpha= colr[3]; glVertex3fv(xyz); glVertex3fv(xyz+3); for(i3= 0; i3 < 3*(nvert-2); i3 += 3) { if(colr[i3] != old_red || colr[i3+1] != old_green || colr[i3+2] != old_blue || colr[3] != old_alpha) { glColor4fv(colr+i3); old_red= colr[i3]; old_green= colr[i3+1]; old_blue= colr[i3+2]; old_alpha= colr[3]; } glNormal3fv(norm+i3); /* NOTE: It makes no difference in local performance if the coords are converted to floats before being stored in the display list */ glVertex3fv(xyz+i3+6); } glEnd(); CHEK_ERROR("yglTstripNoArr"); } void yglQstripNoArr(long nvert, float *xyz, float *norm, float *colr) { long i3, i6; double old_red, old_green, old_blue; /* draw the strip */ if(nvert <= 2) return; glBegin(GL_QUAD_STRIP); glColor3fv(colr); old_red= colr[0]; old_green= colr[1]; old_blue= colr[2]; glColor3fv(colr); glVertex3fv(xyz); glVertex3fv(xyz+3); for(i3= 0, i6= 6; i3 < 3*(nvert-1); i3 += 3, i6 += 6) { if(colr[i3] != old_red || colr[i3+1] != old_green || colr[i3+2] != old_blue) { glColor3fv(colr+i3); old_red= colr[i3]; old_green= colr[i3+1]; old_blue= colr[i3+2]; } glNormal3fv(norm+i3); /* NOTE: It makes no difference in local performance if the coords are converted to floats before being stored in the display list */ glVertex3fv(xyz+i6); glVertex3fv(xyz+i6+3); } glEnd(); CHEK_ERROR("yglQstripNoArr"); } void yglQstripNoArrAlpha(long nvert, float *xyz, float *norm, float *colr) { long i3, i6; double old_red, old_green, old_blue, old_alpha; /* draw the strip */ if(nvert <= 2) return; glBegin(GL_QUAD_STRIP); glColor4fv(colr); old_red= colr[0]; old_green= colr[1]; old_blue= colr[2]; old_alpha= colr[3]; glColor3fv(colr); glVertex3fv(xyz); glVertex3fv(xyz+3); for(i3= 0, i6= 6; i3 < 3*(nvert-1); i3 += 3, i6 += 6) { if(colr[i3] != old_red || colr[i3+1] != old_green || colr[i3+2] != old_blue || colr[3] != old_alpha) { glColor4fv(colr+i3); old_red= colr[i3]; old_green= colr[i3+1]; old_blue= colr[i3+2]; old_alpha= colr[3]; } glNormal3fv(norm+i3); /* NOTE: It makes no difference in local performance if the coords are converted to floats before being stored in the display list */ glVertex3fv(xyz+i6); glVertex3fv(xyz+i6+3); } glEnd(); CHEK_ERROR("yglQstripNoArr"); } void yglTstripArrNoLite(long nvert, float *xyz, float *colr) { long i3; float *arr_colr, *arr_vert; long ind_colr, ind_vert; /* draw the strip */ if(nvert <= 2) return; /* make an array big enough to hold all the colors and vertices for the quad strip */ ind_colr= ind_vert= 0; arr_colr= (float *)p_malloc(3*nvert*sizeof(float)); arr_vert= (float *)p_malloc(3*nvert*sizeof(float)); arr_colr[ind_colr++]= colr[0]; arr_colr[ind_colr++]= colr[1]; arr_colr[ind_colr++]= colr[2]; arr_colr[ind_colr++]= colr[0]; arr_colr[ind_colr++]= colr[1]; arr_colr[ind_colr++]= colr[2]; for(i3= 0; i3 < 3*(nvert-2); i3 += 3) { arr_colr[ind_colr++]= colr[i3]; arr_colr[ind_colr++]= colr[i3+1]; arr_colr[ind_colr++]= colr[i3+2]; } for(i3= 0; i3 < 3*nvert; i3 += 3) { arr_vert[ind_vert++]= xyz[i3]; arr_vert[ind_vert++]= xyz[i3+1]; arr_vert[ind_vert++]= xyz[i3+2]; } /* NOTE: for each enabled array, a corresponding array must be defined and have data filled in before a call to glDrawArrays, because that call will use data from each enabled array */ glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glColorPointer(3, GL_FLOAT, 0, arr_colr); glVertexPointer(3, GL_FLOAT, 0, arr_vert); /* draw all triangles/quads using previously specified colors, vertices */ glDrawArrays(GL_TRIANGLE_STRIP, 0, nvert); /* free up the storage */ glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); p_free(arr_colr); p_free(arr_vert); CHEK_ERROR("yglTstripArrNoLite"); } void yglTstripArrNoLiteAlpha(long nvert, float *xyz, float *colr) { long i3; float *arr_colr, *arr_vert; long ind_colr, ind_vert; /* draw the strip */ if(nvert <= 2) return; /* make an array big enough to hold all the colors and vertices for the quad strip */ ind_colr= ind_vert= 0; arr_colr= (float *)p_malloc(4*nvert*sizeof(float)); arr_vert= (float *)p_malloc(3*nvert*sizeof(float)); arr_colr[ind_colr++]= colr[0]; arr_colr[ind_colr++]= colr[1]; arr_colr[ind_colr++]= colr[2]; arr_colr[ind_colr++]= colr[3]; arr_colr[ind_colr++]= colr[0]; arr_colr[ind_colr++]= colr[1]; arr_colr[ind_colr++]= colr[2]; arr_colr[ind_colr++]= colr[3]; for(i3= 0; i3 < 3*(nvert-2); i3 += 3) { arr_colr[ind_colr++]= colr[i3]; arr_colr[ind_colr++]= colr[i3+1]; arr_colr[ind_colr++]= colr[i3+2]; arr_colr[ind_colr++]= colr[i3+3]; } for(i3= 0; i3 < 3*nvert; i3 += 3) { arr_vert[ind_vert++]= xyz[i3]; arr_vert[ind_vert++]= xyz[i3+1]; arr_vert[ind_vert++]= xyz[i3+2]; } /* NOTE: for each enabled array, a corresponding array must be defined and have data filled in before a call to glDrawArrays, because that call will use data from each enabled array */ glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glColorPointer(4, GL_FLOAT, 0, arr_colr); glVertexPointer(3, GL_FLOAT, 0, arr_vert); /* draw all triangles/quads using previously specified colors, vertices */ glDrawArrays(GL_TRIANGLE_STRIP, 0, nvert); /* free up the storage */ glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); p_free(arr_colr); p_free(arr_vert); CHEK_ERROR("yglTstripArrNoLite"); } void yglTstripArrNoLiteAlphaMulti(long nvert, float *xyz, float *colr) { long i3, j, csiz, preload; float *arr_colr, *arr_vert; long ind_colr, ind_vert; /* draw the strip */ if(nvert <= 2) return; csiz= 4; /* either 3 for RGB color or 4 for RGBA */ /* If the input is a color per triangle, load the color for the first triangle twice before starting to copy the color array */ preload= 2; /* make an array big enough to hold all the colors and vertices for the quad strip */ ind_colr= ind_vert= 0; arr_colr= (float *)p_malloc(csiz*nvert*sizeof(float)); arr_vert= (float *)p_malloc(3*nvert*sizeof(float)); for(i3= 0; i3 < preload; i3++) { for(j= 0; j< csiz; j++) { arr_colr[ind_colr++]= colr[j]; } } for(i3= 0; i3 < 3*(nvert-2); i3 += 3) { for(j= 0; j< csiz; j++) { arr_colr[ind_colr++]= colr[i3+j]; } } for(i3= 0; i3 < 3*nvert; i3 += 3) { arr_vert[ind_vert++]= xyz[i3]; arr_vert[ind_vert++]= xyz[i3+1]; arr_vert[ind_vert++]= xyz[i3+2]; } /* NOTE: for each enabled array, a corresponding array must be defined and have data filled in before a call to glDrawArrays, because that call will use data from each enabled array */ glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glColorPointer(csiz, GL_FLOAT, 0, arr_colr); glVertexPointer(3, GL_FLOAT, 0, arr_vert); /* draw all triangles/quads using previously specified colors, vertices */ glDrawArrays(GL_TRIANGLE_STRIP, 0, nvert); /* free up the storage */ glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); p_free(arr_colr); p_free(arr_vert); CHEK_ERROR("yglTstripArrNoLite"); } void yglQstripArrNoLite(long nvert, float *xyz, float *colr) { long i3, i6; float *arr_colr, *arr_vert; long ind_colr, ind_vert; /* draw the strip */ if(nvert <= 1) return; /* make an array big enough to hold all the colors and vertices for the quad strip */ ind_colr= ind_vert= 0; arr_colr= (float *)p_malloc(6*nvert*sizeof(float)); arr_vert= (float *)p_malloc(6*nvert*sizeof(float)); arr_colr[ind_colr++]= colr[0]; arr_colr[ind_colr++]= colr[1]; arr_colr[ind_colr++]= colr[2]; arr_colr[ind_colr++]= colr[0]; arr_colr[ind_colr++]= colr[1]; arr_colr[ind_colr++]= colr[2]; for(i3= 0; i3 < 3*(nvert-1); i3 += 3) { arr_colr[ind_colr++]= colr[i3]; arr_colr[ind_colr++]= colr[i3+1]; arr_colr[ind_colr++]= colr[i3+2]; arr_colr[ind_colr++]= colr[i3]; arr_colr[ind_colr++]= colr[i3+1]; arr_colr[ind_colr++]= colr[i3+2]; } for(i6= 0; i6 < 6*nvert; i6 += 6) { arr_vert[ind_vert++]= xyz[i6]; arr_vert[ind_vert++]= xyz[i6+1]; arr_vert[ind_vert++]= xyz[i6+2]; arr_vert[ind_vert++]= xyz[i6+3]; arr_vert[ind_vert++]= xyz[i6+4]; arr_vert[ind_vert++]= xyz[i6+5]; } /* NOTE: for each enabled array, a corresponding array must be defined and have data filled in before a call to glDrawArrays, because that call will use data from each enabled array */ glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glColorPointer(3, GL_FLOAT, 0, arr_colr); glVertexPointer(3, GL_FLOAT, 0, arr_vert); /* draw all triangles/quads using previously specified colors, vertices */ glDrawArrays(GL_QUAD_STRIP, 0, 2*nvert); /* free up the storage */ glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); p_free(arr_colr); p_free(arr_vert); CHEK_ERROR("yglQstripArrNoLite"); } void yglQstripArrNoLiteAlpha(long nvert, float *xyz, float *colr) { long i3, i6; float *arr_colr, *arr_vert; long ind_colr, ind_vert; /* draw the strip */ if(nvert <= 1) return; /* make an array big enough to hold all the colors and vertices for the quad strip */ ind_colr= ind_vert= 0; arr_colr= (float *)p_malloc(8*nvert*sizeof(float)); arr_vert= (float *)p_malloc(6*nvert*sizeof(float)); arr_colr[ind_colr++]= colr[0]; arr_colr[ind_colr++]= colr[1]; arr_colr[ind_colr++]= colr[2]; arr_colr[ind_colr++]= colr[3]; arr_colr[ind_colr++]= colr[0]; arr_colr[ind_colr++]= colr[1]; arr_colr[ind_colr++]= colr[2]; arr_colr[ind_colr++]= colr[3]; for(i3= 0; i3 < 3*(nvert-1); i3 += 3) { arr_colr[ind_colr++]= colr[i3]; arr_colr[ind_colr++]= colr[i3+1]; arr_colr[ind_colr++]= colr[i3+2]; arr_colr[ind_colr++]= colr[i3+3]; arr_colr[ind_colr++]= colr[i3]; arr_colr[ind_colr++]= colr[i3+1]; arr_colr[ind_colr++]= colr[i3+2]; arr_colr[ind_colr++]= colr[i3+3]; } for(i6= 0; i6 < 6*nvert; i6 += 6) { arr_vert[ind_vert++]= xyz[i6]; arr_vert[ind_vert++]= xyz[i6+1]; arr_vert[ind_vert++]= xyz[i6+2]; arr_vert[ind_vert++]= xyz[i6+3]; arr_vert[ind_vert++]= xyz[i6+4]; arr_vert[ind_vert++]= xyz[i6+5]; } /* NOTE: for each enabled array, a corresponding array must be defined and have data filled in before a call to glDrawArrays, because that call will use data from each enabled array */ glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glColorPointer(4, GL_FLOAT, 0, arr_colr); glVertexPointer(3, GL_FLOAT, 0, arr_vert); /* draw all triangles/quads using previously specified colors, vertices */ glDrawArrays(GL_QUAD_STRIP, 0, 2*nvert); /* free up the storage */ glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); p_free(arr_colr); p_free(arr_vert); CHEK_ERROR("yglQstripArrNoLite"); } void yglTstripNoArrNoLite(long nvert, float *xyz, float *colr) { long i3; double old_red, old_green, old_blue; /* draw the strip */ if(nvert <= 2) return; glBegin(GL_TRIANGLE_STRIP); glColor3fv(colr); old_red= colr[0]; old_green= colr[1]; old_blue= colr[2]; glVertex3fv(xyz); glVertex3fv(xyz+3); for(i3= 0; i3 < 3*(nvert-2); i3 += 3) { if(colr[0] != old_red || colr[1] != old_green || colr[2] != old_blue) { glColor3fv(colr); old_red= colr[0]; old_green= colr[1]; old_blue= colr[2]; } colr += 3; /* NOTE: It makes no difference in local performance if the coords are converted to floats before being stored in the display list */ glVertex3fv(xyz+i3+6); } glEnd(); CHEK_ERROR("yglTstripNoArrNoLite"); } void yglTstripNoArrNoLiteAlpha(long nvert, float *xyz, float *colr) { long i3; float old_red, old_green, old_blue, old_alpha; /* draw the strip */ if(nvert <= 2) return; glBegin(GL_TRIANGLE_STRIP); old_red= colr[0]; old_green= colr[1]; old_blue= colr[2]; old_alpha= colr[3]; glColor4fv(colr); glVertex3fv(xyz); glVertex3fv(xyz+3); for(i3= 0; i3 < 3*(nvert-2); i3 += 3) { if(colr[0] != old_red || colr[1] != old_green || colr[2] != old_blue || colr[3] != old_alpha) { glColor4fv(colr); old_red= colr[0]; old_green= colr[1]; old_blue= colr[2]; old_alpha= colr[3]; } colr += 4; /* NOTE: It makes no difference in local performance if the coords are converted to floats before being stored in the display list */ glVertex3fv(xyz+i3+6); } glEnd(); CHEK_ERROR("yglTstripNoArrNoLiteAlpha"); } void yglQstripNoArrNoLiteAlpha(long nvert, float *xyz, float *colr) { long i4, i6; double old_red, old_green, old_blue, old_alpha; /* draw the strip */ if(nvert <= 2) return; glBegin(GL_QUAD_STRIP); glColor4fv(colr); old_red= colr[0]; old_green= colr[1]; old_blue= colr[2]; old_alpha= colr[2]; glVertex3fv(xyz); glVertex3fv(xyz+3); for(i4= 0, i6= 6; i4 < 4*(nvert-1); i4 += 3, i6 += 6) { if(colr[i4] != old_red || colr[i4+1] != old_green || colr[i4+2] != old_blue || colr[i4+3] != old_alpha) { glColor4fv(colr+i4); old_red= colr[i4]; old_green= colr[i4+1]; old_blue= colr[i4+2]; old_alpha= colr[i4+3]; } /* NOTE: It makes no difference in local performance if the coords are converted to floats before being stored in the display list */ glVertex3fv(xyz+i6); glVertex3fv(xyz+i6+3); } glEnd(); CHEK_ERROR("yglQstripNoArrNoLite"); } void yglQstripNoArrNoLite(long nvert, float *xyz, float *colr) { long i3, i6; double old_red, old_green, old_blue; /* draw the strip */ if(nvert <= 2) return; glBegin(GL_QUAD_STRIP); glColor3fv(colr); old_red= colr[0]; old_green= colr[1]; old_blue= colr[2]; glVertex3fv(xyz); glVertex3fv(xyz+3); for(i3= 0, i6= 6; i3 < 3*(nvert-1); i3 += 3, i6 += 6) { if(colr[i3] != old_red || colr[i3+1] != old_green || colr[i3+2] != old_blue) { glColor3fv(colr+i3); old_red= colr[i3]; old_green= colr[i3+1]; old_blue= colr[i3+2]; } /* NOTE: It makes no difference in local performance if the coords are converted to floats before being stored in the display list */ glVertex3fv(xyz+i6); glVertex3fv(xyz+i6+3); } glEnd(); CHEK_ERROR("yglQstripNoArrNoLite"); } void yglTstripsNdx(long nstrip, long numedg, long ntri, long *len, long *ndx, float *xyz, float *norm, float *colr, long edge) { /* The input is a list of triangle strips. There is one color per triangle. There is one normal per vertex. The coordinates and normals are accessed via ndx, an array with one index into xyz and norm per vertex in the tri strip. */ long i, num, i3, indv; float old_red= -1, old_green= -1, old_blue= -1; if(alpha_pass) return; yglSetPolyMode(edge); /* use smooth shading */ yglSetShade(1); yglUpdateProperties(); /* smooth shading */ yglSetColorType(1); for(i= 0, indv= 0; i < nstrip; i++) { num= len[i]; /* number of vertices in this strip */ /* draw the strip */ DEMAND(num > 2, "triangle strip with less than 3 vertices in yglTstripsNdx") glBegin(GL_TRIANGLE_STRIP); if(colr[0] != old_red || colr[1] != old_green || colr[2] != old_blue) { old_red= colr[0]; old_green= colr[1]; old_blue= colr[2]; glColor3fv(colr); } glNormal3fv(norm+3*ndx[indv]); glVertex3fv(xyz+3*ndx[indv]); glNormal3fv(norm+3*ndx[indv+1]); glVertex3fv(xyz+3*ndx[indv+1]); indv += 2; for(i3= 0; i3 < num-2; i3++) { /* NOTE: It makes no difference in local performance if the coords are converted to floats before being stored in the display list */ if(colr[0] != old_red || colr[1] != old_green || colr[2] != old_blue) { old_red= colr[0]; old_green= colr[1]; old_blue= colr[2]; glColor3fv(colr); } glNormal3fv(norm+3*ndx[indv]); glVertex3fv(xyz+3*ndx[indv]); indv++; colr += 3; } glEnd(); } CHEK_ERROR("yglTstripsNdx"); } void yglTstripsAlphaNdx(long nstrip, long numedg, long ntri, long *len, long *ndx, float *xyz, float *norm, float *colr, long edge) { /* The input is a list of triangle strips. There is one color per triangle. There is one normal per vertex. The coordinates and normals are accessed via ndx, an array with one index into xyz and norm per vertex in the tri strip. */ long i, num, i3, indv; float old_red= -1, old_green= -1, old_blue= -1, old_alpha= -1; if(!alpha_pass) return; glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDepthMask(GL_FALSE); yglSetPolyMode(edge); /* use smooth shading */ yglSetShade(1); yglUpdateProperties(); /* smooth shading */ yglSetColorType(1); for(i= 0, indv= 0; i < nstrip; i++) { num= len[i]; /* number of vertices in this strip */ /* draw the strip */ DEMAND(num > 2, "triangle strip with less than 3 vertices in yglTstripsNdx") glBegin(GL_TRIANGLE_STRIP); if(colr[0] != old_red || colr[1] != old_green || colr[2] != old_blue) { old_red= colr[0]; old_green= colr[1]; old_blue= colr[2]; old_alpha= colr[3]; glColor4fv(colr); } glNormal3fv(norm+ndx[indv]); glVertex3fv(xyz+ndx[indv]); glNormal3fv(norm+ndx[indv+1]); glVertex3fv(xyz+ndx[indv+1]); indv += 2; for(i3= 0; i3 < num-2; i3++) { /* NOTE: It makes no difference in local performance if the coords are converted to floats before being stored in the display list */ if(colr[0] != old_red || colr[1] != old_green || colr[2] != old_blue || colr[3] != old_alpha) { old_red= colr[0]; old_green= colr[1]; old_blue= colr[2]; old_alpha= colr[3]; glColor4fv(colr); } glNormal3fv(norm+ndx[indv]); glVertex3fv(xyz+ndx[indv]); indv++; colr += 4; } glEnd(); } glDepthMask(GL_TRUE); glDisable(GL_BLEND); CHEK_ERROR("yglTstripsAlphaNdx"); } yorick-gl-1.1+cvs20070922+dfsg.orig/contour.i0000640000175000017500000020447510313362500020274 0ustar thibautthibaut/* * $Id: contour.i,v 1.1.1.1 2005/09/18 22:08:00 dhmunro Exp $ * These functions extract iso-surfaces and slicing planes * from 3D meshes. * The results can be displayed using functions in pl3gl.i. * Users ordinarily call functions in contour.i so those * functions are autoloaded by the yorgl plugin. * The compiled functions are connected via cntrfunc.i, so * require that cntrfunc.i be "pulled in" any time something in contour.i * is called. */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ require,"tristruct.i"; require,"cntrfunc.i"; /* by default, make triangle strips when possible */ make_strip= 1; func is_scalar_color(colr, name) { if(is_void(colr)) { set_color= 0; } else { dimc= dimsof(colr); if( !(dimc(1) == 1 && (dimc(2) == 3 || dimc(2) == 4)) ) error,"colr must be a vector of length 3 or 4 in "+name; set_color= 1; } return set_color; } func is_3_vector(var, msg) { if(anyof(dimsof(var) != [1,3])) error(msg); } func is_compat(var1, var2, msg) { if(is_void(var2)) return; if( anyof( dimsof(var1) != dimsof(var2) ) ) { error,msg; } } func chek_iso_reg(origin, delta, dimsv, var2, name, zcn=) { if(zcn) zoff= 1; else zoff= 0; if(anyof(dimsof(origin) != [1,3])) error,"origin must be a 3 element vector in "+name; if(anyof(dimsof(delta) != [1,3])) error,"delta must be a 3 element vector in "+name; if(anyof(dimsv(2:) < 4-zoff)) error,"grid must be at least 4-by-4-by-4 in "+name; if(!is_void(var2)) if( anyof( dimsv != dimsof(var2) ) ) error,"var2 must have the same dimensions as var in "+name; } func chek_iso_crv(xyz, dimsv, var2, name, zcn=) { dimsx= dimsof(xyz); if(is_void(zcn)) zcn= 0; if(dimsv(1) != 3) error,"var must be a 3-dimensional array in "+name; if(dimsx(1) != 4 || dimsx(2) != 3) error,"xyz must have leading dimension 3 in "+name; if(anyof(dimsx(3:5) < 4)) error,"grid must be at least 4-by-4-by-4 in "+name; if(zcn) { if( anyof(dimsv(2:4) != dimsx(3:5)-1) ) error,"var must have dimensions nx-1, ny-1, and nz-1 in "+name; } else { if( anyof(dimsv(2:4) != dimsx(3:5)) ) error,"xyz and var must have the same nx, ny, and nz in "+name; } if(!is_void(var2)) if( anyof(dimsv != dimsof(var2)) ) error,"var2 must have the same dimensions as var in "+name; } func get_chunk(sizes) { chunk= CHKSIZ; if( chunk(1)*chunk(2)*chunk(3) >= sizes(1)*sizes(2)*sizes(3) ) { chunk(1)= sizes(1); chunk(2)= sizes(2); chunk(3)= sizes(3); } chunk= min(chunk, sizes); return chunk; } func iso3cenregngrd(origin, delta, var, level, colr, var2=) /* DOCUMENT iso3cenregngrd(origin, delta, var, level, colr, var2=) Extract an iso-surface from a variable on a rectangular 3D grid. Input array var is point centered and NO guard points. var2, if suplied, is an auxiliary variable with the same centering and size as var. The result is a list of groups of triangle arrays. If requested, triangle strips may extend across multiple zones. Uses a 6 tetrahedron decomposition of each hexahedral zone. The result is a list of triangle arrays. SEE ALSO: iso3cenreg, iso3zcenregngrd, iso3cenregndx, iso3cencrv. */ { lst= iso3cenregbase(origin, delta, var, level, colr, 0, var2); return lst; } func iso3(origin, delta, var, level, colr, var2=) /* DOCUMENT iso3(origin, delta, var, level, colr, var2=) Included for compatibility of earlier versions of yorgl. Please call iso3cenreg instead. SEE ALSO: iso3cenreg. */ { lst= iso3cenreg(origin, delta, var, level, colr, var2=var2); return lst; } func iso3cenreg(origin, delta, var, level, colr, var2=) /* DOCUMENT iso3cenreg(origin, delta, var, level, colr, var2=) Extract an iso-surface from a variable on a rectangular 3D grid. Input array var is point centered and has one extra point on each side. var2, if suplied, is an auxiliary variable with the same centering and size as var. The result is a list of groups of triangle arrays. If requested, triangle strips may extend across multiple zones. Uses a 6 tetrahedron decomposition of each hexahedral zone. The result is a list of triangle arrays. SEE ALSO: iso3cenregngrd, iso3zcenreg, iso3cenregndx, iso3cencrv. */ { lst= iso3cenregbase(origin, delta, var, level, colr, 1, var2); return lst; } func iso3cenregbase(origin, delta, var, level, colr, has_guard, var2) /* worker routine for point centered data, not called by user */ { extern CHKSIZ; local make_strip; local numTri, nx, ny, nz, lst; // set name of calling routine and the number of guard // on each side of the grid if(has_guard) { name= "iso3cenreg"; nguard= 1; } else { name= "iso3cenregngrd"; nguard= 0; } make_strip= 0; dimsv= dimsof(var); sizes= dimsv(2:4); chek_iso_reg, origin, delta, dimsv, var2, name, zcn=0; nx= sizes(1); ny= sizes(2); nz= sizes(3); chunk= get_chunk(sizes); cnx= chunk(1); cny= chunk(2); cnz= chunk(3); set_color= is_scalar_color(colr, name); nulvar= []; /* number of cells in a chunk not counting guard cells */ numZone= (cnx-3)*(cny-3)*(cnz-3); /* note: this triangle count assumes that points on edges introduced by the 6 tet decomposition are removed */ maxTri= 6*numZone; maxVert= 3*maxTri; if(!is_void(var2)) { /* need to be able to save one variable value at every triangle vertex */ v2= &array(0.0, 3, maxTri); } else { v2= &[]; } /* note: if second input variable is null, the var2 element of the struct will be zero (the address of a null variable) */ arr0= TriArrayGrp( numTri= 0, cellIDs= &array(0, maxTri), xyzverts= &array(0.0, 3, 3, maxTri), normals= &array(0.0, 3, 3, maxTri), var2= v2, triEdg= &nulvar, triStart= &nulvar, nTris= &nulvar, next= &nulvar ); xyztmp= array(0.0, 3, cnx, cny, cnz); grdtmp= array(0.0, 3, cnx, cny, cnz); vartmp= array(0.0, cnx, cny, cnz); v2tmp= array(0.0, cnx, cny, cnz); flag= array(char, cnx, cny, cnz); lst= []; /* The compiled functions use a chunk (specified by siz) that includes guard points for the chunk. If the input array didn't have guard points, klo and khi will point outside the input array when the chunk is at the border. This is handled by the point fetching routine in the compiled code. The loops below run over the real cells in each chunk, so nx-1-nguard is the upper limit (i.e. the last real cell in the input array). The limits passed in the call includes both real and guard points for the chunk. */ for(k= 1+nguard; k <= nz-1-nguard; k += cnz-3) { klo= k-1; /* the lower guard point of the chunk */ khi= min(nz+1-nguard, klo+cnz-1); for(j= 1+nguard; j <= ny-1-nguard; j += cny-3) { jlo= j-1; jhi= min(ny+1-nguard, jlo+cny-1); for(i= 1+nguard; i <= nx-1-nguard; i += cnx-3) { ilo= i-1; ihi= min(nx+1-nguard, ilo+cnx-1); siz= [ihi-ilo+1, jhi-jlo+1, khi-klo+1]; /* norigin is the location of the first guard point for the chunk, not the first real point. */ norigin= origin+[ilo-1, jlo-1, klo-1]*delta; offsets= [ilo, jlo, klo, nx, ny, nz]; if(has_guard) { res= ContourInitCartGrdPcen(siz,offsets,delta,norigin,var, &var2); } else { res= ContourInitCartPcen(siz,offsets,delta,norigin,var, &var2); } if(!res) { write,"chunk ",siz(1), siz(2), siz(3), " is too small"; continue; } res= ContourTetArray(make_strip,siz,level, vartmp, v2tmp, xyztmp, grdtmp, flag, &arr0); if(!res) continue; /* have an array of triangles. */ numTri= arr0.numTri; xyzverts= (*(arr0.xyzverts))(,,1:numTri); normals= (*(arr0.normals))(,,1:numTri); cellIDs= (*(arr0.cellIDs))(1:numTri); if(!is_void(var2)) { /* need to be able to save one variable value at every triangle vertex */ v2new= (*(arr0.var2))(,1:numTri); } else { v2new= []; } lst= TriArrayGrp( numTri= numTri, xyzverts= &xyzverts, normals= &normals, var2= &v2new, cellIDs= &cellIDs, /* the next three are not used unless assembling strips */ triEdg= &nulvar, triStart= &nulvar, nTris= &nulvar, next= &lst); if(set_color) { lst.colors= &float(colr); } } } } return lst; } func iso3zcenregngrd(origin, delta, var, level, colr, var2=) /* DOCUMENT iso3zcenreg(origin, delta, var, level, colr, var2=) Extract an iso-surface from a variable on a rectangular 3D grid. Input array var is zone centered and has one extra zone on each side. var2, if suplied, is an auxiliary variable with the same centering and size as var. The result is a list of groups of triangle arrays. If requested, triangle strips may extend across multiple zones. Uses a 6 tetrahedron decomposition of each hexahedral zone. The result is a list of triangle arrays. SEE ALSO: iso3zcenreg, iso3zcenregndx, iso3zcencrv. */ { lst= iso3zcenregbase(origin, delta, var, level, colr, 0, var2); return lst; } func iso3zcenreg(origin, delta, var, level, colr, var2=) /* DOCUMENT iso3zcenreg(origin, delta, var, level, colr, var2=) Extract an iso-surface from a variable on a rectangular 3D grid. Input array var is zone centered and has one extra zone on each side. var2, if suplied, is an auxiliary variable with the same centering and size as var. The result is a list of groups of triangle arrays. If requested, triangle strips may extend across multiple zones. Uses a 6 tetrahedron decomposition of each hexahedral zone. The result is a list of triangle arrays. SEE ALSO: iso3, iso3crv, iso3strip, iso3stripcrv, slice3stripcrv. */ { lst= iso3zcenregbase(origin, delta, var, level, colr, 1, var2); return lst; } func iso3zcenregbase(origin, delta, var, level, colr, has_guard, var2) /* worker routine for zone centered data, not called by the user */ { extern CHKSIZ; local make_strip; local numTri, nx, ny, nz, lst; // set name of calling routine and the number of guard cells // on each side of the grid if(has_guard) { name= "iso3zcenreg"; nguard= 1; } else { name= "iso3zcenregngrd"; nguard= 0; } make_strip= 0; dimsv= dimsof(var); sizes= dimsv(2:4)+1; /* number of vertices surrounding the cells */ chek_iso_reg, origin, delta, dimsv, var2, name, zcn=1; nx= sizes(1); ny= sizes(2); nz= sizes(3); chunk= get_chunk(sizes); cnx= chunk(1); cny= chunk(2); cnz= chunk(3); set_color= is_scalar_color(colr, name); nulvar= []; /* number of cells not counting guard cells */ numZone= (cnx-3)*(cny-3)*(cnz-3); /* note: this triangle count assumes that points on edges introduced by the 6 tet decomposition are removed */ maxTri= 6*numZone; maxVert= 3*maxTri; if(!is_void(var2)) { /* need to be able to save one variable value at every triangle vertex */ v2= &array(0.0, 3, maxTri); } else { v2= &[]; } /* note: if second input variable is null, the var2 element of the struct will be zero (the address of a null variable) */ arr0= TriArrayGrp( numTri= 0, cellIDs= &array(0, maxTri), xyzverts= &array(0.0, 3, 3, maxTri), normals= &array(0.0, 3, 3, maxTri), var2= v2, triEdg= &nulvar, triStart= &nulvar, nTris= &nulvar, next= &nulvar ); xyztmp= array(0.0, 3, cnx, cny, cnz); grdtmp= array(0.0, 3, cnx, cny, cnz); vartmp= array(0.0, cnx, cny, cnz); v2tmp= array(0.0, cnx, cny, cnz); flag= array(char, cnx, cny, cnz); lst= []; /* The input array may or may not have guard points on all sides. The compiled functions use a chunk (specified by siz) that includes guard points for the chunk (a chunk has guard points even if the input array does not). The loops below run over the real cells in each chunk, so nx-1-nguard is the upper limit (i.e. the last real cell in the input array). The limits passed in the call include both real and guard points for the chunk. */ for(k= 1+nguard; k <= nz-1-nguard; k += cnz-3) { klo= k-1; /* the lower guard point of the chunk */ khi= min(nz+1-nguard, klo+cnz-1); // the upper guard point of the chunk for(j= 1+nguard; j <= ny-1-nguard; j += cny-3) { jlo= j-1; jhi= min(ny+1-nguard, jlo+cny-1); for(i= 1+nguard; i <= nx-1-nguard; i += cnx-3) { ilo= i-1; ihi= min(nx+1-nguard, ilo+cnx-1); siz= [ihi-ilo+1, jhi-jlo+1, khi-klo+1]; /* norigin is the location of the first guard point for the chunk, not the first real point. */ norigin= origin+[ilo-1, jlo-1, klo-1]*delta; offsets= [ilo, jlo, klo, nx, ny, nz]; if(has_guard) { res= ContourInitCartGrdZcen(siz,offsets,delta,norigin,var, &var2); } else { res= ContourInitCartZcen(siz,offsets,delta,norigin,var, &var2); } if(!res) { write,"chunk ",siz(1), siz(2), siz(3), " is too small"; continue; } res= ContourTetArray(make_strip,siz,level, vartmp, v2tmp, xyztmp, grdtmp, flag, &arr0); if(!res) continue; /* have an array of triangles. */ numTri= arr0.numTri; xyzverts= (*(arr0.xyzverts))(,,1:numTri); normals= (*(arr0.normals))(,,1:numTri); cellIDs= (*(arr0.cellIDs))(1:numTri); if(!is_void(var2)) { /* need to be able to save one variable value at every triangle vertex */ v2new= (*(arr0.var2))(,1:numTri); } else { v2new= []; } lst= TriArrayGrp( numTri= numTri, xyzverts= &xyzverts, normals= &normals, var2= &v2new, cellIDs= &cellIDs, /* the next three are not used unless assembling strips */ triEdg= &nulvar, triStart= &nulvar, nTris= &nulvar, next= &lst); if(set_color) { lst.colors= &float(colr); } } } } return lst; } func iso3ndx(origin, delta, var, level, colr, var2=) /* DOCUMENT iso3ndx(origin, delta, var, level, colr, var2=) Included for compatibility with earlier versions of yorgl. Please call iso3cenregndx instead. Uses a 6 tetrahedron decomposition of each hexahedral zone. SEE ALSO: iso3cenregndx. */ { lst= iso3cenregndx(origin, delta, var, level, colr, var2=var2); return lst; } func iso3cenregndx(origin, delta, var, level, colr, var2=) /* DOCUMENT iso3cenregndx(origin, delta, var, level, colr, var2=) Extract an iso-surface from a variable on a rectangular 3D grid. Input array var is point centered and has one extra point on each side. var2, if suplied, is an auxiliary variable with the same centering and size as var. The result is a list of groups of triangle arrays. If requested, triangle strips may extend across multiple zones. Triangles are specified by indices into vectors of coordinates, gradients, and auxiliary variables. Uses a 6 tetrahedron decomposition of each hexahedral zone. SEE ALSO: iso3cenreg, iso3zcenregndx, iso3cencrv, iso3cencrvndx. */ { extern CHKSIZ; local make_strip; local numTri, nx, ny, nz, lst; name= "iso3cenregndx"; make_strip= 0; dimsv= dimsof(var); sizes= dimsv(2:4); chek_iso_reg, origin, delta, dimsv, var2, name, zcn=0; nx= sizes(1); ny= sizes(2); nz= sizes(3); chunk= get_chunk(sizes); cnx= chunk(1); cny= chunk(2); cnz= chunk(3); set_color= is_scalar_color(colr, name); nulvar= []; /* number of cells not counting guard cells */ numZone= (cnx-3)*(cny-3)*(cnz-3); /* note: this triangle count assumes that points on edges introduced by the 6 tet decomposition are removed */ maxTri= 6*numZone; maxVert= 3*maxTri; maxEdg= 3*cnx*cny*cnz; if(!is_void(var2)) { /* need to be able to save one variable value at every unique vertex */ v2= &array(0.0, maxEdg); } else { v2= &[]; } /* note: if second input variable is null, the var2 element of the struct will be zero (the address of a null variable) */ arr0= TriVertexGrp( numTri= 0, numEdg= 0, cellIDs= &array(0, maxTri), xyzverts= &array(0.0, 3, maxEdg), normals= &array(0.0, 3, maxEdg), ptndx= &array(0, 3, maxTri), var2= v2, triEdg= &nulvar, triStart= &nulvar, next= &nulvar ); xyztmp= array(0.0, 3, cnx, cny, cnz); grdtmp= array(0.0, 3, cnx, cny, cnz); vartmp= array(0.0, cnx, cny, cnz); v2tmp= array(0.0, cnx, cny, cnz); flag= array(char, cnx, cny, cnz); /* there is one index into the vertex array per real edge in the grid */ ndx= array(long, maxEdg); lst= []; /* The input array has guard points on all sides. The compiled functions use a chunk (specified by siz) that includes guard points for the chunk. The loops below run over the real cells in each chunk, so nx-2 is the upper limit (i.e. the last real cell in the input array). The limits passed in the call include both real and guard points for the chunk. */ for(k= 2; k <= nz-2; k += cnz-3) { klo= k-1; /* the lower guard point of the chunk */ khi= min(nz, klo+cnz-1); for(j= 2; j <= ny-2; j += cny-3) { jlo= j-1; jhi= min(ny, jlo+cny-1); for(i= 2; i <= nx-2; i += cnx-3) { ilo= i-1; ihi= min(nx, ilo+cnx-1); siz= [ihi-ilo+1, jhi-jlo+1, khi-klo+1]; /* norigin is the location of the first guard point for the chunk, not the first real point. */ norigin= origin+[ilo-1, jlo-1, klo-1]*delta; offsets= [ilo, jlo, klo, nx, ny, nz]; res= ContourInitCartGrdPcenNdx(siz,offsets,delta,norigin,var, &var2); if(!res) { write,"chunk ",siz(1), siz(2), siz(3), " is too small"; continue; } res= ContourTetArrayNdx(make_strip,siz,level, vartmp, v2tmp, xyztmp, grdtmp, flag, ndx, &arr0); if(!res) continue; /* have an array of triangles specified by indices into vertex arrays. */ numTri= arr0.numTri; numEdg= arr0.numEdg; xyzverts= (*(arr0.xyzverts))(,1:numEdg); normals= (*(arr0.normals))(,1:numEdg); cellIDs= (*(arr0.cellIDs))(1:numTri); ptndx= (*(arr0.ptndx))(,1:numTri); if(!is_void(var2)) { /* need to be able to save one variable value at every triangle vertex */ v2new= (*(arr0.var2))(1:numEdg); } else { v2new= []; } lst= TriVertexGrp( numTri= numTri, numEdg= numEdg, xyzverts= &xyzverts, normals= &normals, var2= &v2new, cellIDs= &cellIDs, ptndx= &ptndx, /* the next three are not used unless assembling strips */ triEdg= &nulvar, triStart= &nulvar, nTris= &nulvar, next= &lst); if(set_color) { lst.colors= &float(colr); } } } } return lst; } func iso3zcenregndx(origin, delta, var, level, colr, var2=) /* DOCUMENT iso3zcenregndx(origin, delta, var, level, colr, var2=) Extract an iso-surface from a variable on a rectangular 3D grid. Input array var is zone centered and has one extra zone on each side. var2, if suplied, is an auxiliary variable with the same centering and size as var. The result is a list of groups of triangle arrays. If requested, triangle strips may extend across multiple zones. Triangles are specified by indices into vectors of coordinates, gradients, and auxiliary variables. Uses a 6 tetrahedron decomposition of each hexahedral zone. SEE ALSO: iso3zcenreg, iso3cenregndx, iso3zcencrv, iso3zcencrvndx. */ { extern CHKSIZ; local make_strip; local numTri, nx, ny, nz, lst; name= "iso3zcenregndx"; make_strip= 0; dimsv= dimsof(var); sizes= dimsv(2:4)+1; /* number of vertices surrounding the cells */ chek_iso_reg, origin, delta, dimsv, var2, name, zcn=1; nx= sizes(1); ny= sizes(2); nz= sizes(3); chunk= get_chunk(sizes); cnx= chunk(1); cny= chunk(2); cnz= chunk(3); set_color= is_scalar_color(colr, name); nulvar= []; /* number of cells not counting guard cells */ numZone= (cnx-3)*(cny-3)*(cnz-3); /* note: this triangle count assumes that points on edges introduced by the 6 tet decomposition are removed */ maxTri= 6*numZone; maxVert= 3*maxTri; maxEdg= 3*cnx*cny*cnz; if(!is_void(var2)) { /* need to be able to save one variable value at every unique vertex */ v2= &array(0.0, maxEdg); } else { v2= &[]; } /* note: if second input variable is null, the var2 element of the struct will be zero (the address of a null variable) */ arr0= TriVertexGrp( numTri= 0, numEdg= 0, cellIDs= &array(0, maxTri), xyzverts= &array(0.0, 3, maxEdg), normals= &array(0.0, 3, maxEdg), ptndx= &array(0, 3, maxTri), var2= v2, triEdg= &nulvar, triStart= &nulvar, nTris= &nulvar, next= &nulvar ); xyztmp= array(0.0, 3, cnx, cny, cnz); grdtmp= array(0.0, 3, cnx, cny, cnz); vartmp= array(0.0, cnx, cny, cnz); v2tmp= array(0.0, cnx, cny, cnz); flag= array(char, cnx, cny, cnz); /* there is one index into the vertex array per real edge in the grid */ ndx= array(long, maxEdg); lst= []; /* The input array has guard points on all sides. The compiled functions use a chunk (specified by siz) that includes guard points for the chunk. The loops below run over the real cells in each chunk, so nx-2 is the upper limit (i.e. the last real cell in the input array). The limits passed in the call include both real and guard points for the chunk. */ for(k= 2; k <= nz-2; k += cnz-3) { klo= k-1; /* the lower guard point of the chunk */ khi= min(nz, klo+cnz-1); for(j= 2; j <= ny-2; j += cny-3) { jlo= j-1; jhi= min(ny, jlo+cny-1); for(i= 2; i <= nx-2; i += cnx-3) { ilo= i-1; ihi= min(nx, ilo+cnx-1); siz= [ihi-ilo+1, jhi-jlo+1, khi-klo+1]; /* norigin is the location of the first guard point for the chunk, not the first real point. */ norigin= origin+[ilo-1, jlo-1, klo-1]*delta; offsets= [ilo, jlo, klo, nx, ny, nz]; res= ContourInitCartGrdZcenNdx(siz,offsets,delta,norigin,var, &var2); if(!res) { write,"chunk ",siz(1), siz(2), siz(3), " is too small"; continue; } res= ContourTetArrayNdx(make_strip,siz,level, vartmp, v2tmp, xyztmp, grdtmp, flag, ndx, &arr0); if(!res) continue; /* have an array of triangles specified by indices into vertex arrays. */ numTri= arr0.numTri; numEdg= arr0.numEdg; xyzverts= (*(arr0.xyzverts))(,1:numEdg); normals= (*(arr0.normals))(,1:numEdg); cellIDs= (*(arr0.cellIDs))(1:numTri); ptndx= (*(arr0.ptndx))(,1:numTri); if(!is_void(var2)) { /* need to be able to save one variable value at every triangle vertex */ v2new= (*(arr0.var2))(1:numEdg); } else { v2new= []; } lst= TriVertexGrp( numTri= numTri, numEdg= numEdg, xyzverts= &xyzverts, normals= &normals, var2= &v2new, cellIDs= &cellIDs, ptndx= &ptndx, /* the next three are not used unless assembling strips */ triEdg= &nulvar, triStart= &nulvar, nTris= &nulvar, next= &lst); if(set_color) { lst.colors= &float(colr); } } } } return lst; } func iso3hex(xyz, grad, hexndx, var, level, colr, var2=) /* DOCUMENT iso3hex(xyz, grad, hexndx, var, level, colr, var2=) Extract an iso-surface from a variable on an arbitrarily connected 3D grid of hexahedra. xyz, grad, and var are coordinates, gradients, and variable values at the points of the grid. var2, if suplied, is an auxiliary variable with the same centering and size as var. hexndx has 8 indices into the xyz etc. arrays for each zone. Uses a 6 tetrahedron decomposition of each hexahedral zone. The result is a list of triangle arrays. SEE ALSO: iso3cenreg, iso3zcenreg, iso3cencrv, iso3_tree. */ { extern CHKSIZ; local make_strip; local numTri, nx, ny, nz, lst; name= "iso3hex"; make_strip= 0; dimsv= dimsof(var); ASSERT, (dimsv(1) == 1 && dimsv(2) >= 8), "The variable array must contain at least 8 points in "+name; is_compat, var, var2, "var2 must have the same dimensions as var in "+name; dimsx= dimsof(xyz); ASSERT, (dimsx(1) == 2 && dimsx(2) == 3 && dimsx(3) == dimsv(2)), "The xyz array must be 3 by N-points in iso3hex"; ASSERT, allof(dimsx == dimsof(grad)), "The gradient array must be 3 by N-points in "+name; dimsh= dimsof(hexndx); ASSERT, (dimsh(1) == 2 && dimsh(2) == 8), "The index array must be 8 by N-zones in "+name; nzone= dimsh(3); set_color= is_scalar_color(colr, name); nulvar= []; /* The input array can easily be chunked if the scratch array for triangles would be too large */ chk= CHKSIZ(1)*CHKSIZ(2)*CHKSIZ(3); if(chk > nzone) chk= nzone; /* note: this triangle count assumes that points on edges introduced by the 6 tet decomposition are removed */ maxTri= 6*chk; maxVert= 3*maxTri; if(!is_void(var2)) { /* need to be able to save one variable value at every triangle vertex */ v2= &array(0.0, 3, maxTri); } else { v2= &[]; } /* note: if second input variable is null, the var2 element of the struct will be zero (the address of a null variable) */ arr0= TriArrayGrp( numTri= 0, cellIDs= &array(0, maxTri), xyzverts= &array(0.0, 3, 3, maxTri), normals= &array(0.0, 3, 3, maxTri), var2= v2, triEdg= &nulvar, triStart= &nulvar, nTris= &nulvar, next= &nulvar ); lst= []; /* The input variables include gradients at all points. There is no need for guard cells. */ for(i= 1; i <= nzone; i += chk) { num= min(chk, nzone-i+1); res= ContourTetHex(level, i, num, xyz, grad, hexndx, var, &var2, &arr0); if(!res) continue; /* have an array of triangles. */ numTri= arr0.numTri; xyzverts= (*(arr0.xyzverts))(,,1:numTri); normals= (*(arr0.normals))(,,1:numTri); cellIDs= (*(arr0.cellIDs))(1:numTri); if(!is_void(var2)) { /* need to be able to save one variable value at every triangle vertex */ v2new= (*(arr0.var2))(,1:numTri); } else { v2new= []; } lst= TriArrayGrp( numTri= numTri, xyzverts= &xyzverts, normals= &normals, var2= &v2new, cellIDs= &cellIDs, /* the next three are not used unless assembling strips */ triEdg= &nulvar, triStart= &nulvar, nTris= &nulvar, next= &lst); if(set_color) { lst.colors= &float(colr); } } return lst; } func iso3cencrv(xyz, var, level, colr, var2=) /* DOCUMENT iso3cencrv(xyz Extract an iso-surface from a variable on a curvilinear 3D grid. Input array var is point centered and has one extra point on each side. var2, if suplied, is an auxiliary variable with the same centering and size as var. Uses a 6 tetrahedron decomposition of each hexahedral zone. The result is a list of triangle arrays. SEE ALSO: iso3cenreg, iso3zcencrv, iso3zcencrvndx. */ { extern CHKSIZ; local make_strip; local numTri, nx, ny, nz, lst; name= "iso3cencrv"; make_strip= 0; dimsv= dimsof(var); sizes= dimsv(2:4); chek_iso_crv, xyz, dimsv, var2, name, zcn=0; nx= sizes(1); ny= sizes(2); nz= sizes(3); chunk= get_chunk(sizes); cnx= chunk(1); cny= chunk(2); cnz= chunk(3); set_color= is_scalar_color(colr, name); nulvar= []; /* number of cells not counting guard cells */ numZone= (cnx-3)*(cny-3)*(cnz-3); /* note: this triangle count assumes that points on edges introduced by the 6 tet decomposition are removed */ maxTri= 6*numZone; maxVert= 3*maxTri; if(!is_void(var2)) { /* need to be able to save one variable value at every triangle vertex */ v2= &array(0.0, 3, maxTri); } else { v2= &[]; } /* note: if second input variable is null, the var2 element of the struct will be zero (the address of a null variable) */ arr0= TriArrayGrp( numTri= 0, cellIDs= &array(0, maxTri), xyzverts= &array(0.0, 3, 3, maxTri), normals= &array(0.0, 3, 3, maxTri), var2= v2, triEdg= &nulvar, triStart= &nulvar, nTris= &nulvar, next= &nulvar ); xyztmp= array(0.0, 3, cnx, cny, cnz); grdtmp= array(0.0, 3, cnx, cny, cnz); vartmp= array(0.0, cnx, cny, cnz); v2tmp= array(0.0, cnx, cny, cnz); flag= array(char, cnx, cny, cnz); lst= []; /* The input array has guard points on all sides. The compiled functions use a chunk (specified by siz) that includes guard points for the chunk. The loops below run over the real cells in each chunk, so nx-2 is the upper limit (i.e. the last real cell in the input array). The limits passed in the call include both real and guard points for the chunk. */ for(k= 2; k <= nz-2; k += cnz-3) { klo= k-1; /* the lower guard point of the chunk */ khi= min(nz, klo+cnz-1); for(j= 2; j <= ny-2; j += cny-3) { jlo= j-1; jhi= min(ny, jlo+cny-1); for(i= 2; i <= nx-2; i += cnx-3) { ilo= i-1; ihi= min(nx, ilo+cnx-1); siz= [ihi-ilo+1, jhi-jlo+1, khi-klo+1]; /* norigin is the location of the first guard point for the chunk, not the first real point. */ norigin= origin+[ilo-1, jlo-1, klo-1]*delta; offsets= [ilo, jlo, klo, nx, ny, nz]; res= ContourInitCrvGrdPcen(siz,offsets,xyz,var, &var2); if(!res) { write,"chunk ",siz(1), siz(2), siz(3), " is too small"; continue; } res= ContourTetArray(make_strip,siz,level, vartmp, v2tmp, xyztmp, grdtmp, flag, &arr0); if(!res) continue; /* have an array of triangles. */ numTri= arr0.numTri; xyzverts= (*(arr0.xyzverts))(,,1:numTri); normals= (*(arr0.normals))(,,1:numTri); cellIDs= (*(arr0.cellIDs))(1:numTri); if(!is_void(var2)) { /* need to be able to save one variable value at every triangle vertex */ v2new= (*(arr0.var2))(,1:numTri); } else { v2new= []; } lst= TriArrayGrp( numTri= numTri, xyzverts= &xyzverts, normals= &normals, var2= &v2new, cellIDs= &cellIDs, /* the next three are not used unless assembling strips */ triEdg= &nulvar, triStart= &nulvar, nTris= &nulvar, next= &lst); if(set_color) { lst.colors= &float(colr); } } } } return lst; } func iso3zcencrv(xyz, var, level, colr, var2=) /* DOCUMENT iso3zcencrv(xyz, var, level, colr, var2=) Extract an iso-surface from a variable on a curvilinear 3D grid. Input array var is zone centered and has one extra zone on each side. var2, if suplied, is an auxiliary variable with the same centering and size as var. The result is a list of groups of triangle arrays. If requested, triangle strips may extend across multiple zones. Uses a 6 tetrahedron decomposition of each hexahedral zone. The result is a list of triangle arrays. SEE ALSO: iso3zcenreg, iso3cencrv, iso3zcencrvndx. */ { extern CHKSIZ; local make_strip; local numTri, nx, ny, nz, lst; name= "iso3zcencrv"; make_strip= 0; dimsv= dimsof(var); sizes= dimsv(2:4)+1; /* number of vertices surrounding the cells */ chek_iso_crv, xyz, dimsv, var2, name, zcn=1; nx= sizes(1); ny= sizes(2); nz= sizes(3); chunk= get_chunk(sizes); cnx= chunk(1); cny= chunk(2); cnz= chunk(3); set_color= is_scalar_color(colr, name); nulvar= []; /* number of cells not counting guard cells */ numZone= (cnx-3)*(cny-3)*(cnz-3); /* note: this triangle count assumes that points on edges introduced by the 6 tet decomposition are removed */ maxTri= 6*numZone; maxVert= 3*maxTri; if(!is_void(var2)) { /* need to be able to save one variable value at every triangle vertex */ v2= &array(0.0, 3, maxTri); } else { v2= &[]; } /* note: if second input variable is null, the var2 element of the struct will be zero (the address of a null variable) */ arr0= TriArrayGrp( numTri= 0, cellIDs= &array(0, maxTri), xyzverts= &array(0.0, 3, 3, maxTri), normals= &array(0.0, 3, 3, maxTri), var2= v2, triEdg= &nulvar, triStart= &nulvar, nTris= &nulvar, next= &nulvar ); xyztmp= array(0.0, 3, cnx, cny, cnz); grdtmp= array(0.0, 3, cnx, cny, cnz); vartmp= array(0.0, cnx, cny, cnz); v2tmp= array(0.0, cnx, cny, cnz); flag= array(char, cnx, cny, cnz); lst= []; /* The input array has guard points on all sides. The compiled functions use a chunk (specified by siz) that includes guard points for the chunk. The loops below run over the real cells in each chunk, so nx-2 is the upper limit (i.e. the last real cell in the input array). The limits passed in the call include both real and guard points for the chunk. */ for(k= 2; k <= nz-2; k += cnz-3) { klo= k-1; /* the lower guard point of the chunk */ khi= min(nz, klo+cnz-1); for(j= 2; j <= ny-2; j += cny-3) { jlo= j-1; jhi= min(ny, jlo+cny-1); for(i= 2; i <= nx-2; i += cnx-3) { ilo= i-1; ihi= min(nx, ilo+cnx-1); siz= [ihi-ilo+1, jhi-jlo+1, khi-klo+1]; /* norigin is the location of the first guard point for the chunk, not the first real point. */ norigin= origin+[ilo-1, jlo-1, klo-1]*delta; offsets= [ilo, jlo, klo, nx, ny, nz]; res= ContourInitCrvGrdZcen(siz,offsets,xyz,var, &var2); if(!res) { write,"chunk ",siz(1), siz(2), siz(3), " is too small"; continue; } res= ContourTetArray(make_strip,siz,level, vartmp, v2tmp, xyztmp, grdtmp, flag, &arr0); if(!res) continue; /* have an array of triangles. */ numTri= arr0.numTri; xyzverts= (*(arr0.xyzverts))(,,1:numTri); normals= (*(arr0.normals))(,,1:numTri); cellIDs= (*(arr0.cellIDs))(1:numTri); if(!is_void(var2)) { /* need to be able to save one variable value at every triangle vertex */ v2new= (*(arr0.var2))(,1:numTri); } else { v2new= []; } lst= TriArrayGrp( numTri= numTri, xyzverts= &xyzverts, normals= &normals, var2= &v2new, cellIDs= &cellIDs, /* the next three are not used unless assembling strips */ triEdg= &nulvar, triStart= &nulvar, nTris= &nulvar, next= &lst); if(set_color) { lst.colors= &float(colr); } } } } return lst; } func iso3cencrvndx(xyz, var, level, colr, var2=) /* DOCUMENT iso3cencrvndx(xyz, var, level, colr, var2=) Extract an iso-surface from a variable on a curvilinear 3D grid. Input array var is point centered and has one extra point on each side. var2, if suplied, is an auxiliary variable with the same centering and size as var. The result is a list of groups of triangle arrays. If requested, triangle strips may extend across multiple zones. Triangles are specified by indices into vectors of coordinates, gradients, and auxiliary variables. Uses a 6 tetrahedron decomposition of each hexahedral zone. SEE ALSO: iso3cenregndx, iso3cencrv, iso3zcencrvndx. */ { extern CHKSIZ; local make_strip; local numTri, nx, ny, nz, lst; name= "iso3cencrvndx"; make_strip= 0; dimsv= dimsof(var); sizes= dimsv(2:4); chek_iso_crv, xyz, dimsv, var2, name, zcn=0; nx= sizes(1); ny= sizes(2); nz= sizes(3); chunk= get_chunk(sizes); cnx= chunk(1); cny= chunk(2); cnz= chunk(3); set_color= is_scalar_color(colr, name); nulvar= []; /* number of cells not counting guard cells */ numZone= (cnx-3)*(cny-3)*(cnz-3); /* note: this triangle count assumes that points on edges introduced by the 6 tet decomposition are removed */ maxTri= 6*numZone; maxVert= 3*maxTri; maxEdg= 3*cnx*cny*cnz; if(!is_void(var2)) { /* need to be able to save one variable value at every unique vertex */ v2= &array(0.0, maxEdg); } else { v2= &[]; } /* note: if second input variable is null, the var2 element of the struct will be zero (the address of a null variable) */ arr0= TriVertexGrp( numTri= 0, numEdg= 0, cellIDs= &array(0, maxTri), xyzverts= &array(0.0, 3, maxEdg), normals= &array(0.0, 3, maxEdg), ptndx= &array(0, 3, maxTri), var2= v2, triEdg= &nulvar, triStart= &nulvar, nTris= &nulvar, next= &nulvar ); xyztmp= array(0.0, 3, cnx, cny, cnz); grdtmp= array(0.0, 3, cnx, cny, cnz); vartmp= array(0.0, cnx, cny, cnz); v2tmp= array(0.0, cnx, cny, cnz); flag= array(char, cnx, cny, cnz); /* there is one index into the vertex array per real edge in the grid */ ndx= array(long, maxEdg); lst= []; /* The input array has guard points on all sides. The compiled functions use a chunk (specified by siz) that includes guard points for the chunk. The loops below run over the real cells in each chunk, so nx-2 is the upper limit (i.e. the last real cell in the input array). The limits passed in the call include both real and guard points for the chunk. */ for(k= 2; k <= nz-2; k += cnz-3) { klo= k-1; /* the lower guard point of the chunk */ khi= min(nz, klo+cnz-1); for(j= 2; j <= ny-2; j += cny-3) { jlo= j-1; jhi= min(ny, jlo+cny-1); for(i= 2; i <= nx-2; i += cnx-3) { ilo= i-1; ihi= min(nx, ilo+cnx-1); siz= [ihi-ilo+1, jhi-jlo+1, khi-klo+1]; /* norigin is the location of the first guard point for the chunk, not the first real point. */ norigin= origin+[ilo-1, jlo-1, klo-1]*delta; offsets= [ilo, jlo, klo, nx, ny, nz]; res= ContourInitCrvGrdPcenNdx(siz,offsets,xyz,var, &var2); if(!res) { write,"chunk ",siz(1), siz(2), siz(3), " is too small"; continue; } res= ContourTetArrayNdx(make_strip,siz,level, vartmp, v2tmp, xyztmp, grdtmp, flag, ndx, &arr0); if(!res) continue; /* have an array of triangles specified by indices into vertex arrays. */ numTri= arr0.numTri; numEdg= arr0.numEdg; xyzverts= (*(arr0.xyzverts))(,1:numEdg); normals= (*(arr0.normals))(,1:numEdg); cellIDs= (*(arr0.cellIDs))(1:numTri); ptndx= (*(arr0.ptndx))(,1:numTri); if(!is_void(var2)) { /* need to be able to save one variable value at every triangle vertex */ v2new= (*(arr0.var2))(1:numEdg); } else { v2new= []; } lst= TriVertexGrp( numTri= numTri, numEdg= numEdg, xyzverts= &xyzverts, normals= &normals, var2= &v2new, cellIDs= &cellIDs, ptndx= &ptndx, /* the next three are not used unless assembling strips */ triEdg= &nulvar, triStart= &nulvar, nTris= &nulvar, next= &lst); if(set_color) { lst.colors= &float(colr); } } } } return lst; } func iso3zcencrvndx(xyz, var, level, colr, var2=) /* DOCUMENT iso3zcencrvndx(xyz, var, level, colr, var2=) Extract an iso-surface from a variable on a curvilinear 3D grid. Input array var is zone centered and has one extra zone on each side. var2, if suplied, is an auxiliary variable with the same centering and size as var. The result is a list of groups of triangle arrays. If requested, triangle strips may extend across multiple zones. Triangles are specified by indices into vectors of coordinates, gradients, and auxiliary variables. Uses a 6 tetrahedron decomposition of each hexahedral zone. SEE ALSO: iso3zcenregndx, iso3zcencrv, iso3cencrvndx. */ { extern CHKSIZ; local make_strip; local numTri, nx, ny, nz, lst; name= "iso3zcencrvndx"; make_strip= 0; dimsv= dimsof(var); sizes= dimsv(2:4)+1; /* number of vertices surrounding the cells */ chek_iso_crv, xyz, dimsv, var2, name, zcn=1; nx= sizes(1); ny= sizes(2); nz= sizes(3); chunk= get_chunk(sizes); cnx= chunk(1); cny= chunk(2); cnz= chunk(3); set_color= is_scalar_color(colr, name); nulvar= []; /* number of cells not counting guard cells */ numZone= (cnx-3)*(cny-3)*(cnz-3); /* note: this triangle count assumes that points on edges introduced by the 6 tet decomposition are removed */ maxTri= 6*numZone; maxVert= 3*maxTri; maxEdg= 3*cnx*cny*cnz; if(!is_void(var2)) { /* need to be able to save one variable value at every unique vertex */ v2= &array(0.0, maxEdg); } else { v2= &[]; } /* note: if second input variable is null, the var2 element of the struct will be zero (the address of a null variable) */ arr0= TriVertexGrp( numTri= 0, numEdg= 0, cellIDs= &array(0, maxTri), xyzverts= &array(0.0, 3, maxEdg), normals= &array(0.0, 3, maxEdg), ptndx= &array(0, 3, maxTri), var2= v2, triEdg= &nulvar, triStart= &nulvar, nTris= &nulvar, next= &nulvar ); xyztmp= array(0.0, 3, cnx, cny, cnz); grdtmp= array(0.0, 3, cnx, cny, cnz); vartmp= array(0.0, cnx, cny, cnz); v2tmp= array(0.0, cnx, cny, cnz); flag= array(char, cnx, cny, cnz); /* there is one index into the vertex array per real edge in the grid */ ndx= array(long, maxEdg); lst= []; /* The input array has guard points on all sides. The compiled functions use a chunk (specified by siz) that includes guard points for the chunk. The loops below run over the real cells in each chunk, so nx-2 is the upper limit (i.e. the last real cell in the input array). The limits passed in the call include both real and guard points for the chunk. */ for(k= 2; k <= nz-2; k += cnz-3) { klo= k-1; /* the lower guard point of the chunk */ khi= min(nz, klo+cnz-1); for(j= 2; j <= ny-2; j += cny-3) { jlo= j-1; jhi= min(ny, jlo+cny-1); for(i= 2; i <= nx-2; i += cnx-3) { ilo= i-1; ihi= min(nx, ilo+cnx-1); siz= [ihi-ilo+1, jhi-jlo+1, khi-klo+1]; /* norigin is the location of the first guard point for the chunk, not the first real point. */ norigin= origin+[ilo-1, jlo-1, klo-1]*delta; offsets= [ilo, jlo, klo, nx, ny, nz]; res= ContourInitCrvGrdZcenNdx(siz,offsets,xyz,var, &var2); if(!res) { write,"chunk ",siz(1), siz(2), siz(3), " is too small"; continue; } res= ContourTetArrayNdx(make_strip,siz,level, vartmp, v2tmp, xyztmp, grdtmp, flag, ndx, &arr0); if(!res) continue; /* have an array of triangles specified by indices into vertex arrays. */ numTri= arr0.numTri; numEdg= arr0.numEdg; xyzverts= (*(arr0.xyzverts))(,1:numEdg); normals= (*(arr0.normals))(,1:numEdg); cellIDs= (*(arr0.cellIDs))(1:numTri); ptndx= (*(arr0.ptndx))(,1:numTri); if(!is_void(var2)) { /* need to be able to save one variable value at every triangle vertex */ v2new= (*(arr0.var2))(1:numEdg); } else { v2new= []; } lst= TriVertexGrp( numTri= numTri, numEdg= numEdg, xyzverts= &xyzverts, normals= &normals, var2= &v2new, cellIDs= &cellIDs, ptndx= &ptndx, /* the next three are not used unless assembling strips */ triEdg= &nulvar, triStart= &nulvar, nTris= &nulvar, next= &lst); if(set_color) { lst.colors= &float(colr); } } } } return lst; } func mak_isotree(var) /* DOCUMENT mak_isotree(var) Build an octree for use in making iso-surfaces. SEE ALSO: iso3_tree, iso3_treecrv, iso3_treevarr, slice_tree */ { local nx, ny, nz, i, j, k; dimsv= dimsof(var); /* NOTE: the variable must have guard cells */ ASSERT, (dimsv(1) == 3 && allof(dimsv(2:4) > 3)), "The variable array must be nx-by-ny-by-nz in mak_isotree"; /* NOTE: var is assumed to be point centered */ sizes= dimsv(2:4); rlsiz= sizes-2; nx= sizes(1); ny= sizes(2); nz= sizes(3); itop= nx-1; jtop= ny-1; ktop= nz-1; /* NOTE: chunk is the number of points in a chunk - the number of cells is one less. A chunk never includes either the first or last points in var. */ chunk= get_chunk(rlsiz); tree= []; nulvar= []; for(k= 2; k < ktop; k += chunk(3)-1) { khi= min(ktop, k+chunk(3)-1); for(j= 2; j < jtop; j += chunk(2)-1) { jhi= min(jtop, j+chunk(2)-1); for(i= 2; i < itop; i += chunk(1)-1) { ihi= min(itop, i+chunk(1)-1); /* chk is the number of vertices in this chunk */ chk= [ihi-i+1, jhi-j+1, khi-k+1]; /* determine the number of levels in the octree */ maxdepth= 1; num= chk(max)-1; /* number of cells */ while(num > 1) { num= (num+1)/2; maxdepth++; } /* Compute the number of "cells" in each direction for all levels of the tree. */ numx= numy= numz= array(0, maxdepth); /* nnx, nny, nnz are numbers of cells */ nnx= chk(1)-1; nny= chk(2)-1; nnz= chk(3)-1; for(id= 1; id <= maxdepth; id++) { numx(id)= nnx; numy(id)= nny; numz(id)= nnz; nnx= (nnx+1)/2; nny= (nny+1)/2; nnz= (nnz+1)/2; } /* Compute C-style offsets into the range array for the start of each level and the total size of the range array. An element of the range is a struct with a min and a max value. A single range array contains all levels. The offsets are counts of range elements, not counts of the doubles that make up ranges. */ lens= numx*numy*numz; /* NOTE: C-style indices into the range array */ offsets= lens(psum); if(numberof(lens) <= 1) { offsets= array(0, 1); } else { offsets= grow(0, offsets(:-1)); } ranges= array(OctRange, lens(sum)); trsiz= array(0, 3, maxdepth); trsiz(1,)= numx; trsiz(2,)= numy; trsiz(3,)= numz; tree= OctTree( maxdepth= maxdepth, size= &sizes, chunk= &chk, start= &[i-1,j-1,k-1], /* C-style start in the full array */ trsiz= &trsiz, offsets= &offsets, ranges= &ranges, next= &tree ); MakeContourTree, var, &tree; } } } return tree; } func slice_tree(sizes, origin, delta, point, pl_normal, var2, guard=) /* DOCUMENT slice_tree(sizes, origin, delta, point, pl_normal, var2, guard=) Extract a slicing plane on a rectangular 3D grid. If var2 is not null, return it's value at each vertex of the slice plane. sizes= [nx,ny,nz] is the grid size. SEE ALSO: slice_treecrv, . */ { local numTri, nVert, nStrip; name= "slice_tree"; /* assume guard cells by default!!! */ if(is_void(guard)) guard= 1; if(guard) { ASSERT, allof(sizes(1:3) >= 4), "The variable array must be nx-by-ny-by-nz in "+name; } else { ASSERT, allof(sizes(1:3) >= 2), "The variable array must be nx-by-ny-by-nz in "+name; } is_3_vector, origin, "origin must be a 3 element vector in "+name; is_3_vector, delta, "delta must be a 3 element vector in "+name; is_3_vector, point, "point must be a 3 element vector in "+name; is_3_vector, pl_normal, "pl_normal must be a 3 element vector in "+name; /* NOTE: var is assumed to be point centered */ if(guard) { rlsiz= sizes-2; ibot= 2; itop= sizes(1)-1; jbot= 2; jtop= sizes(2)-1; kbot= 2; ktop= sizes(3)-1; } else { rlsiz= sizes; ibot= 1; itop= sizes(1); jbot= 1; jtop= sizes(2); kbot= 1; ktop= sizes(3); } /* NOTE: chunk is the number of points in a chunk - the number of cells is one less. A chunk never includes either the first or last points in var. */ chunk= get_chunk(rlsiz); /* arr0 must be big enough for the worst possible case - i.e. several triangles in each zone. This can be huge unless the input array is handled in chunks. No chunk can be bigger than the last chunk in the list (the one that starts at [0,0,0]). */ // trptr= &tree; numZone= (chunk(1)-1)*(chunk(2)-1)*(chunk(3)-1); maxTri= 5*numZone; if(!is_void(var2)) { /* need to be able to save one variable value at every triangle vertex */ v2= &array(0.0, 3, maxTri); } else { v2= &[]; } arr0= TriArrayGrp( numTri= 0, cellIDs= &array(0, maxTri), xyzverts= &array(0.0, 3, 3, maxTri), normals= &array(0.0, 3, 3, maxTri), var2= v2, triEdg= &nulvar, triStart= &nulvar, nTris= &nulvar, next= &nulvar ); lst= []; for(k= kbot; k < ktop; k += chunk(3)-1) { khi= min(ktop, k+chunk(3)-1); for(j= jbot; j < jtop; j += chunk(2)-1) { jhi= min(jtop, j+chunk(2)-1); for(i= ibot; i < itop; i += chunk(1)-1) { ihi= min(itop, i+chunk(1)-1); /* chk is the number of vertices in this chunk */ chk= [ihi-i+1, jhi-j+1, khi-k+1]; /* determine the number of levels in the octree */ maxdepth= 1; num= chk(max)-1; /* number of cells */ while(num > 1) { num= (num+1)/2; maxdepth++; } start= [i-1, j-1, k-1]; /* C-style */ res= SliceTree(maxdepth,sizes,chk,start,delta,origin,point, pl_normal,&var2,&arr0); if(res) { /* have an array of triangles. */ numTri= arr0.numTri; xyzverts= (*(arr0.xyzverts))(,,1:numTri); normals= array(pl_normal,3,1:numTri); cellIDs= (*(arr0.cellIDs))(1:numTri); if(!is_void(var2)) { /* need to be able to save one variable value at every triangle vertex */ v2new= (*(arr0.var2))(,1:numTri); } else { v2new= []; } lst= TriArrayGrp( numTri= numTri, xyzverts= &xyzverts, normals= &normals, var2= &v2new, cellIDs= &cellIDs, colors= &nulvar, /* the next three are not used unless assembling strips */ triEdg= &nulvar, triStart= &nulvar, nTris= &nulvar, next= &lst ); } } } } return lst; } func mak_slice_treecrv(xyz,guard=) /* DOCUMENT mak_slice_treecrv(xyz,guard=) Extract a slicing plane on an ijk 3D grid. SEE ALSO: slice_tree, slice_treecrv. */ { local i, j, k; name= "mak_slice_treecrv"; /* sizes is the number of vertices in the grid. It includes the points from the guard cells */ sizes= dimsof(xyz)(3:5); nx= sizes(1); ny= sizes(2); nz= sizes(3); /* assume guard cells by default!!! */ if(is_void(guard)) guard= 1; if(guard) { ASSERT, allof(sizes >= 4), "The variable array must be nx-by-ny-by-nz in "+name; rlsiz= sizes-2; ibot= 2; itop= nx-1; jbot= 2; jtop= ny-1; kbot= 2; ktop= nz-1; } else { ASSERT, allof(sizes >= 2), "The variable array must be nx-by-ny-by-nz in "+name; rlsiz= sizes; ibot= 1; itop= nx; jbot= 1; jtop= ny; kbot= 1; ktop= nz; } /* NOTE: chunk is the number of points in a chunk - the number of cells is one less. A chunk never includes either the first or last points in the grid if guard is non-zero. */ chunk= get_chunk(rlsiz); tree= []; nulvar= []; for(k= kbot; k < ktop; k += chunk(3)-1) { khi= min(ktop, k+chunk(3)-1); for(j= jbot; j < jtop; j += chunk(2)-1) { jhi= min(jtop, j+chunk(2)-1); for(i= ibot; i < itop; i += chunk(1)-1) { ihi= min(itop, i+chunk(1)-1); /* chk is the number of vertices in this chunk */ chk= [ihi-i+1, jhi-j+1, khi-k+1]; /* determine the number of levels in the octree */ maxdepth= 1; num= chk(max)-1; /* number of cells */ while(num > 1) { num= (num+1)/2; maxdepth++; } /* Compute the number of "cells" in each direction for all levels of the tree. */ numx= numy= numz= array(0, maxdepth); /* nnx, nny, nnz are numbers of cells */ nnx= chk(1)-1; nny= chk(2)-1; nnz= chk(3)-1; for(id= 1; id <= maxdepth; id++) { numx(id)= nnx; numy(id)= nny; numz(id)= nnz; nnx= (nnx+1)/2; nny= (nny+1)/2; nnz= (nnz+1)/2; } /* Compute C-style offsets into the range array for the start of each level and the total size of the range array. An element of the range is a struct with a min and a max value. A single range array contains all levels. The offsets are counts of range elements, not counts of the doubles that make up ranges. */ lens= numx*numy*numz; /* NOTE: C-style indices into the range array */ offsets= lens(psum); if(numberof(lens) <= 1) { offsets= array(0, 1); } else { offsets= grow(0, offsets(:-1)); } ranges= array(OctSpan, lens(sum)); trsiz= array(0, 3, maxdepth); trsiz(1,)= numx; trsiz(2,)= numy; trsiz(3,)= numz; tree= OctSTree( maxdepth= maxdepth, size= &sizes, chunk= &chk, start= &[i-1,j-1,k-1], /* C-style start in the full array */ trsiz= &trsiz, offsets= &offsets, ranges= &ranges, next= &tree ); MakeSliceTreeCrv, xyz, &tree; } } } return tree; } func slice_treecrv(xyz, point, pl_normal, tree, var2=) /* DOCUMENT slice_treecrv(xyz, point, pl_normal, tree, var2=) Extract a slicing plane on an ijk 3D grid using a pre-computed tree. var2 is an optional point-centered variable. If present, it will be interpolated to the points on the slicing plane. The resulting variable can be turned into a color and the slice plane can then be smoothly colored using one color per vertex instead of one color per triangle. SEE ALSO: slice_tree, mak_slice_treecrv. */ { name= "slice_treecrv"; is_3_vector, point, "point must be a 3 element vector in "+name; is_3_vector, pl_normal, "pl_normal must be a 3 element vector in "+name; if(!is_void(var2)) { dimv2= dimsof(var2); dimx= dimsof(xyz); ASSERT, (dimv2(1) == 3 && allof(dimx(3:5) == dimv2(2:4)) ), "var2 must be nx-by-ny-by-nz in "+name; /* force var2 to be a double, using a method that is efficient if it already is a double */ eq_nocopy,var2,double(var2); } /* arr0 must be big enough for the worst possible case - i.e. several triangles in each zone. The tree was pre-computed using reasonable chunks, so allocate a triangle array big enough to handle the largest chunk (the final one in the linked list is at least as big as any other). */ trptr= &tree; while(trptr && *trptr) { chunk= *(trptr->chunk); trptr= trptr->next; } numZone= (chunk(1)-1)*(chunk(2)-1)*(chunk(3)-1); maxTri= 5*numZone; if(!is_void(var2)) { /* need to be able to save one variable value at every triangle vertex */ v2= &array(0.0, 3, maxTri); } else { v2= &[]; } arr0= TriArrayGrp( numTri= 0, cellIDs= &array(0, maxTri), xyzverts= &array(0.0, 3, 3, maxTri), normals= &array(0.0, 3, 3, maxTri), var2= v2, triEdg= &nulvar, triStart= &nulvar, nTris= &nulvar, next= &nulvar ); lst= []; trptr= &tree; while(trptr && *trptr) { res= SliceTreeCrv(point,pl_normal,xyz,&var2,&arr0,trptr); if(res) { /* have an array of triangles. */ numTri= arr0.numTri; xyzverts= (*(arr0.xyzverts))(,,1:numTri); normals= array(pl_normal,3,1:numTri); cellIDs= (*(arr0.cellIDs))(1:numTri); if(!is_void(var2)) { /* need to be able to save one variable value at every triangle vertex */ v2new= (*(arr0.var2))(,1:numTri); } else { v2new= []; } lst= TriArrayGrp( numTri= numTri, xyzverts= &xyzverts, normals= &normals, var2= &v2new, cellIDs= &cellIDs, colors= &nulvar, /* the next three are not used unless assembling strips */ triEdg= &nulvar, triStart= &nulvar, nTris= &nulvar, next= &lst); } trptr= trptr->next; } return lst; } func iso3_tree(origin, delta, var, level, colr, tree, var2=) /* DOCUMENT iso3_tree(origin, delta, var, level, colr, tree, var2=) Extract an iso-surface from a variable on a rectangular 3D grid. SEE ALSO: mak_isotree, iso3cenreg, iso3_treecrv, iso3_treevarr. */ { local numTri, nVert, nStrip; name= "iso3_tree"; dimsv= dimsof(var); sizes= dimsv(2:4); chek_iso_reg, origin, delta, dimsv, var2, name, zcn=0; set_color= is_scalar_color(colr, name); /* arr0 must be big enough for the worst possible case - i.e. several triangles in each zone. This can be huge unless the input array is handled in chunks. No chunk can be bigger than the last chunk in the list (the one that starts at [0,0,0]). */ trptr= &tree; while(trptr && *trptr) { chunk= *(trptr->chunk); trptr= trptr->next; } numZone= (chunk(1)-1)*(chunk(2)-1)*(chunk(3)-1); maxTri= 5*numZone; if(!is_void(var2)) { /* need to be able to save one variable value at every triangle vertex */ v2= array(0.0, 3, maxTri); } else { v2= []; } /* note: if second input variable is null, the var2 element of the struct will be zero (the address of a null variable) */ arr0= TriArrayGrp( numTri= 0, cellIDs= &array(0, maxTri), xyzverts= &array(0.0, 3, 3, maxTri), normals= &array(0.0, 3, 3, maxTri), var2= &v2, triEdg= &nulvar, triStart= &nulvar, nTris= &nulvar, next= &nulvar ); lst= []; trptr= &tree; while(trptr && *trptr) { if(!is_void(var2)) { res= ContourTree2(delta,origin,level,var,&var2,&arr0,trptr); } else { res= ContourTree(delta,origin,level,var,&arr0,trptr); } if(res) { /* have an array of triangles. */ numTri= arr0.numTri; xyzverts= (*(arr0.xyzverts))(,,1:numTri); normals= (*(arr0.normals))(,,1:numTri); cellIDs= (*(arr0.cellIDs))(1:numTri); if(!is_void(var2)) { /* need to be able to save one variable value at every triangle vertex */ v2new= (*(arr0.var2))(,1:numTri); } else { v2new= []; } lst= TriArrayGrp( numTri= numTri, xyzverts= &xyzverts, normals= &normals, var2= &v2new, cellIDs= &cellIDs, /* the next three are not used unless assembling strips */ triEdg= &nulvar, triStart= &nulvar, nTris= &nulvar, next= &lst); if(set_color) { lst.colors= &float(colr); } } trptr= trptr->next; } return lst; } func iso3_treecrv(xyz, var, level, colr, tree, var2=) /* DOCUMENT iso3_treecrv(xyz, var, level, colr, tree, var2=) Extract an iso-surface from a variable on an ijk 3D grid. Uses a tree created by mak_isotree. SEE ALSO: iso3_tree, mak_isotree, iso3crv. */ { extern n_tri_3d, CHKSIZ; local numTri, nVert, nStrip; name= "iso3_treecrv"; dimsv= dimsof(var); ASSERT, (dimsv(1) == 3 && allof(dimsv(2:4) >= 2) ), "The variable array must be nx-by-ny-by-nz in "+name; sizes= dimsv(2:4); ASSERT, allof(sizes == *(tree.sizes)), "The variable size differs from the size used to build the tree in "+name; nx= sizes(1); ny= sizes(2); nz= sizes(3); if(is_void(xyz)) { xyz= array(0.0, 3, nx,ny,nz); xyz(1,..)= span(-1,1,nx); xyz(2,..)= span(-1,1,nx)(-,); xyz(3,..)= span(-1,1,nx)(-,-,); } else { dimsx= dimsof(xyz); ASSERT, (dimsx(1) == 4 && dimsx(2) == 3 && allof(dimsx(3:5) == sizes) ), "dimensions of xyz do not match those of var in "+name; } set_color= is_scalar_color(colr, name); is_compat(var, var2, "var2 must have the same dimensions as var in "+name); /* arr0 must be big enough for the worst possible case - i.e. several triangles in each zone. This can be huge unless the input array is handled in chunks. No chunk can be bigger than the last chunk in the list (the one that starts at [0,0,0]). */ trptr= &tree; while(trptr && *trptr) { chunk= *(trptr->chunk); trptr= trptr->next; } numZone= (chunk(1)-1)*(chunk(2)-1)*(chunk(3)-1); maxTri= 5*numZone; if(!is_void(var2)) { /* need to be able to save one variable value at every triangle vertex */ v2= array(0.0, 3, maxTri); } else { v2= []; } /* note: if second input variable is null, the var2 element of the struct will be zero (the address of a null variable) */ arr0= TriArrayGrp( numTri= 0, cellIDs= &array(0, maxTri), xyzverts= &array(0.0, 3, 3, maxTri), normals= &array(0.0, 3, 3, maxTri), var2= &v2, triEdg= &nulvar, triStart= &nulvar, nTris= &nulvar, next= &nulvar ); lst= []; trptr= &tree; while(trptr && *trptr) { if(!is_void(var2)) { res= ContourTreeCrv2(level,xyz,var,&var2,&arr0,trptr); } else { res= ContourTreeCrv(level,xyz,var,&arr0,trptr); } if(res) { /* have an array of triangles. */ numTri= arr0.numTri; xyzverts= (*(arr0.xyzverts))(,,1:numTri); normals= (*(arr0.normals))(,,1:numTri); cellIDs= (*(arr0.cellIDs))(1:numTri); if(!is_void(var2)) { /* need to be able to save one variable value at every triangle vertex */ v2new= (*(arr0.var2))(,1:numTri); } else { v2new= []; } lst= TriArrayGrp( numTri= numTri, xyzverts= &xyzverts, normals= &normals, var2= &v2new, cellIDs= &cellIDs, /* the next three are not used unless assembling strips */ triEdg= &nulvar, triStart= &nulvar, nTris= &nulvar, next= &lst); if(set_color) { lst.colors= &float(colr); } } trptr= trptr->next; } return lst; } func iso3_treevarr(origin, delta, var, level, colr, tree, var2=) /* DOCUMENT iso3_treevarr(origin, delta, var, level, colr, tree, var2=) Extract an iso-surface from a variable on a rectangular 3D grid. The triangles are returned in vertex arrays. SEE ALSO: iso3_tree, iso3_treecrv, mak_isotree. */ { local numTri, numEdg, nVert, nStrip; name= "iso3_treevarr"; dimsv= dimsof(var); sizes= dimsv(2:4); chek_iso_reg, origin, delta, dimsv, var2, name, zcn=0; set_color= is_scalar_color(colr, name); /* arr0 must be big enough for the worst possible case - i.e. several triangles in each zone. This can be huge unless the input array is handled in chunks. No chunk can be bigger than the last chunk in the list (the one that starts at [0,0,0]). */ trptr= &tree; while(trptr && *trptr) { chunk= *(trptr->chunk); trptr= trptr->next; } numZone= (chunk(1)-1)*(chunk(2)-1)*(chunk(3)-1); maxTri= 5*numZone; maxEdg= 3*chunk(1)*chunk(2)*chunk(3); if(!is_void(var2)) { /* need to be able to save one variable value at every triangle vertex */ v2= array(0.0, 3, maxTri); } else { v2= []; } /* note: if second input variable is null, the var2 element of the struct will be zero (the address of a null variable) */ nulvar= []; arr0= TriVertexGrp( numTri= 0, numEdg= 0, cellIDs= &array(0, maxTri), xyzverts= &array(0.0, 3, maxEdg), normals= &array(0.0, 3, maxEdg), ptndx= &array(long, 3*maxTri), var2= &v2, triEdg= &nulvar, triStart= &nulvar, nTris= &nulvar, next= &nulvar ); /* this scratch array holds the index into the list of vertices associated with the point (if any) on each edge in the chunk */ edgndx= array(-1, 3*chunk(1)*chunk(2)*chunk(3)); lst= []; /* This is a loop over chunks. Each chunk has its own tree. */ trptr= &tree; while(trptr && *trptr) { edgndx(*)= -1; if(!is_void(var2)) { res= ContourTreeVarr2(delta,origin,level,var,&var2,&arr0,trptr,edgndx); } else { res= ContourTreeVarr(delta,origin,level,var,&arr0,trptr,edgndx); } if(res) { /* have an array of triangles. */ numTri= arr0.numTri; numEdg= arr0.numEdg; if(!is_void(var2)) { /* need to be able to save one variable value at every triangle vertex */ v2new= (*(arr0.var2))(1:numEdg); } else { v2new= []; } xyzverts= (*(arr0.xyzverts))(,1:numEdg); normals= (*(arr0.normals))(,1:numEdg); cellIDs= (*(arr0.cellIDs))(1:numTri); ptndx= (*(arr0.ptndx))(1:3*numTri); lst= TriVertexGrp( numTri= numTri, numEdg= numEdg, xyzverts= &xyzverts, normals= &normals, var2= &v2new, cellIDs= &cellIDs, ptndx= &ptndx, /* the next three are not used unless assembling strips */ triEdg= &nulvar, triStart= &nulvar, nTris= &nulvar, next= &lst); if(set_color) { lst.colors= &float(colr); } } trptr= trptr->next; } return lst; } yorick-gl-1.1+cvs20070922+dfsg.orig/glcompat.i0000640000175000017500000000643510313362465020417 0ustar thibautthibaut/* * $Id: glcompat.i,v 1.1.1.1 2005/09/18 22:07:49 dhmunro Exp $ * This file contains functions from earlier versions of * yorgl that have been replaced or renamed. They are provided * to allow earlier decks to run with newer versions of yorgl. * Please do not rely on these functions for the long term - * they may break at some point in the future. */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ func draw3(called_as_idler) { draw3d,called_as_idler; } func draw3_trigger { draw3d_trigger; } func clear3(void) { clear3d; } func clear3_direct(void) { clear3d_direct; } func clear3_cache(void) { clear3d_cache; } func gl_getbackrgb(void) { return getbackrgb3d(); } func gl_getcage_rgb(void) { return getcage_rgb3d(); } func gl_getgrid_rgb(void) { return getgrid_rgb3d(); } func light3(ambient=,diffuse=,specular=,spower=,sdir=) { light3(ambient=ambient,diffuse=diffuse,specular=specular, spower=spower,sdir=sdir); } func stdview3(dummy) { stdview3; } func prtview3 { prtview3; } func lookat(eye,center,up) { return lookat3d(eye,center,up); } func get3lims(dummy) { return get3lims(dummy); } func get3_normal(xyz, nxyz) { return get_normal3d(xyz, nxyz); } func get3_centroid(xyz, nxyz) { return get_centroid3d(xyz, nxyz); } func pl3dpoly_gl(nv, xyz, color, norm, draw_edge=) { return plpoly3d(nv, xyz, color, norm, draw_edge=draw_edge); } func pl3dcell_gl(corners, color) { return plcell3d(corners, color); } func plm3d_gl(xyz, color) { return plm3d(xyz, color); } func plf3d_gl(xyz, color) { return plf3d(xyz, color); } func surf3d_gl(xyz, norm, color, flip=) { return plsurf3d(xyz, norm, color, flip=flip); } func colrsurf3d_gl(xyz, norm, color, flip=) { return plcolrsurf3d(xyz, norm, color, flip=flip); } func pl3dlines_gl(xyz, color) { return pllines3d(xyz, color); } func pl3dpoints_gl(xyz, color) { return plpoints3d(xyz, color); } func pl3dglyphs_gl(xyz, scal, theta, phi, color) { return plglyphs3d(xyz, scal, theta, phi, color); } func pl3dtrilists(tris,flip=,offset=,cubemap=,emit=) { return pltrilists3d(tris,flip=flip,offset=offset,cubemap=cubemap,emit=emit); } func pl3dtstrips_gl(nv, xyz, color, norm, draw_edge=) { return pltstrips3d(nv, xyz, color, norm, draw_edge=draw_edge); } func pl3dqstrips_gl(nv, xyz, color, norm, draw_edge=) { return plqstrips3d(nv, xyz, color, norm, draw_edge=draw_edge); } func pl3dtivstrips_gl(nv, ndx, xyz, norm, color, draw_edge=) { return pltivstrips3d(nv, ndx, xyz, norm, color, draw_edge=draw_edge); } func pl3dtarray_gl(xyz, norm, color, ntri, cubemap, emit, draw_edge=) { return pltarray3d(xyz, norm, color, ntri, cubemap, emit, draw_edge=draw_edge); } func pl3dqarray_gl(xyz, norm, color, nquad, draw_edge=) { return plqarray3d(xyz, norm, color, nquad, draw_edge=); } func pl3dtivarray_gl(ptndx, xyz, norm, color, ntri, nvert) { return pltivarray3d(ptndx, xyz, norm, color, ntri, nvert); } func putpix_gl(arr) { return putpix3d(arr); } func pl3dtexcell2_gl(delta, texval) { return pltex2dvol(delta, texval); } func pltex3d_gl(nslab, boxsiz, texval, origin=) { return pltex3dvol(nslab, boxsiz, texval, origin=origin); } yorick-gl-1.1+cvs20070922+dfsg.orig/gltexsubs.c0000640000175000017500000001624010313362470020612 0ustar thibautthibaut/* * $Id: gltexsubs.c,v 1.1.1.1 2005/09/18 22:07:52 dhmunro Exp $ * This file contains functions that deal with version and OS * specific features of 3D textures. */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #include "glcode.h" #include "glfunc.h" #include "glBasic.h" #include "gl3dtex.h" #include "glcubetex.h" #include "yio.h" #include #include extern void texpal_make_current(void); extern void yglLdTexPal(long nx, long ny, long nz, unsigned char *tex); extern int isExtensionSupported(const char *extension); extern void *LookupFunction(const char *funcName); extern int TexExtSetup(void); extern int yglTexExtSetup(void); static void yglGenCubeTex(void); /* It is not possible to infer anything about the openGL features that will be available at run time from the OpenGL features present on the computer where the code is compiled. The first reason is the obvious point that the code might be run on a different machine than the one that compiled it. The other point is that the program might display on a remote computer using glx (the features then depend on the remote computer's openGL). Another problem is that Microsoft has no plans to release a version of OpenGL newer than version 1.1. Many Window's OpenGL drivers report that they are version 1.2, 1.3, or 1.4, so the features of newer versions of OpenGL are often available on Windows, they just can't be accessed through Microsoft's OpenGL library. On Windows, OpenGL extensions are accessed via function pointers acquired at run time. There is thus no point trying to decide at compile time what features are present. The best approach seems to be to define constants for any interesting extensions that aren't present in and query at runtime. In the case of Unix systems, extensions are accessed through entries must be present in the OpenGL library or the machine where the code is running. On Unix systems it is not possible to call an extension unless it is available at compile time. However, it is still necessary to check for the presence of the extension at run time. The most reasonable approach to using funcitonality newer than OpenGL 1.1 seems to be to only use extensions. On Windows machines, all attempts to check for the extension are deferred until runtime. On Unix systems, the extension must be present on the machine that is compiling the code and on the machine displaying the output during the run. The only reasonably portable approach is to access all OpenGL features added after version 1.1 as extensions. One problem with this approach is that the headers on a Windows computer will not define any useful extensions. The solution is to hand code all the constants needed to query for the extension. As near as I can tell, it is not possible to build a code on Linux that can use both an ATI and an Nvidia extension (the code will link against either a library supplied by ATI or a library supplied by Nvidia, but not both). This argues pretty strongly against using vendor specific extensions. To keep the messing about with extensions localized, I will define my own function for each type of functionality I provided by extensions that I want to use. If the functionality is not present, the function will simply return. */ /* Set a flag indicating whether the computer on which yorgl was compiled has 3D textures available, which means OpenGL 1.2 or later. Whether this function should be called at run time depends on whether the OpenGL on the "desktop" computer is version 1.2 or newer. An example of where this might fail is a program running on a Linux computer and displaying back to a Windows computer via glx. Windows only has 3D textures as an extension. */ #ifdef GL_TEXTURE_3D int host_has_3dtex= 1; #else int host_has_3dtex= 0; #endif void myglTexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels) { /* If earlier tests indicate that both client and server have 3D textures built-in, call that function. This test ensures this branch will not be taken on any machine where the ifdef causes the function call to be absent */ if(glCurrWin3d->hasTex3d) { #ifdef GL_TEXTURE_3D glTexImage3D(target, level, internalformat, width, height, depth, border, format, type, pixels); #endif return; } /* This code the 3D texture extension on either Windows or a Unix system. It returns doing nothing if the 3D texture extension isn't available. */ if(!glCurrWin3d->hasTex3dExt) return; #ifdef WIN32 (*(glCurrWin3d->myglTexImage3D_ptr)) (target, level, internalformat, width, height, depth, border, format, type, pixels); #else glTexImage3DEXT(target, level, internalformat, width, height, depth, border, format, type, pixels); #endif } int yglQueryTex3d(glWinProp *win) { char *version, msg[100]; double vernum; int res; GLenum err; const GLubyte *errstr; char *rest; /* clear earlier GL errors */ err= glGetError(); errstr= gluErrorString(err); /* the 3D window may not have been created yet */ if(!win) { glWinProp *newWin= 0; /* zero forces window creation */ yglPrepDraw(newWin); win= glCurrWin3d; if(!win) return 0; } if(win->hasTex3d || win->hasTex3dExt) return 1; if(win->tex3dChecked) return 0; /* previous check showed no 3D text. */ /* Make sure the OpenGL context is current */ yglMakeCurrent(win); version = (char*) glGetString(GL_VERSION); DEMAND(version, "Failed to get OpenGL version number") sprintf(msg, "OpenGL version number is %s\n", version); YputsOut(msg); vernum= strtod(version, &rest); glCurrWin3d->tex3dChecked= 1; /* note check for 3D texture occurred */ if(host_has_3dtex && vernum > 1.199) { /* This code was compiled on a computer the OpenGL 1.2 or later and the display is on a computer with OpenGL 1.2 or later. */ win->hasTex3d= 1; /* has 3D texture support */ #ifdef GL_TEXTURE_3D win->myGL_TEXTURE_3D= GL_TEXTURE_3D; win->myGL_PROXY_TEXTURE_3D= GL_PROXY_TEXTURE_3D; #endif return 1; } res = isExtensionSupported("GL_EXT_texture3D"); if(res) { win->hasTex3dExt= 1; /* has 3D texture extension */ win->myGL_TEXTURE_3D= GL_TEXTURE_3D_EXT; win->myGL_PROXY_TEXTURE_3D= GL_PROXY_TEXTURE_3D_EXT; #ifdef WIN32 win->myglTexImage3D_ptr = (MYTEX3DFUNC) LookupFunction("glTexImage3DEXT"); #endif return 1; } else { return 0; /* no 3D texture support */ } } void *LookupFunction(const char *funcName) { /* The LookupFunction function finds function pointers in dynamic libraries. */ #ifdef WIN32 return wglGetProcAddress(funcName); #elif defined(IRIX) void *libHandle = dlopen("libgl.so", RTLD_LAZY); void *func = dlsym(libHandle, funcName); dlclose(libHandle); return func; #else /* other OSes... */ return 0; #endif } yorick-gl-1.1+cvs20070922+dfsg.orig/glviewpoint.h0000640000175000017500000000111310313362471021140 0ustar thibautthibaut/* * $Id: glviewpoint.h,v 1.1.1.1 2005/09/18 22:07:53 dhmunro Exp $ * Declarations for the viewpoint transformation.. */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #ifndef __GLVIEWPOINT__ #define __GLVIEWPOINT__ #ifdef __cplusplus extern "C" { #endif extern float ygl_fov; extern double ygl_eye[3], ygl_center[3], ygl_up[3], ygl_view[3], ygl_viewdist; #ifdef __cplusplus } #endif #endif /* Include/Define */ yorick-gl-1.1+cvs20070922+dfsg.orig/glGlyph.c0000640000175000017500000002471710515710063020207 0ustar thibautthibaut/* * $Id: glGlyph.c,v 1.3 2006/10/19 14:48:19 dhmunro Exp $ */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #include "glcode.h" #include "glfunc.h" #include "TriStruct.h" #include "pstdlib.h" #include #include /* #define CHEK_ERROR(x) gl_chek_error(x) */ #define CHEK_ERROR(x) typedef struct glyph glyph; struct glyph { long ntri; yPoint3D *xyz; yPoint3D *nrm; } ; #define HT_RAT 3.0f #define TET_DFLT static glyph *c_glyph= 0; static glyph pyramid_glyph; static glyph tet_glyph; extern void makPyrGlyph(void); extern void makTetGlyph(void); void yglGlyphs(long nglyph, float *origins, float *scal, float *theta, float *phi, float *colr) { int ng, nv; float x, y, z, sc, nrmx, nrmy, nrmz; float th, ph, snth, csth, snph, csph, csph_csth, snph_csth, csph_snth, snph_snth; yPoint3D xyz0, xyz, nrm; /* The input is a list of glyphs (ellipsoids). Each glyph has a center, a scale factor, a color, and a direction (theta and phi). */ /* draw the glyph list now */ if(nglyph <= 0) return; if(alpha_pass) return; if(!c_glyph) { #ifdef TET_DFLT makTetGlyph(); c_glyph= &tet_glyph; #else makPyrGlyph(); c_glyph= &pyramid_glyph; #endif } /* use smooth shading */ yglSetShade(1); yglUpdateProperties(); CHEK_ERROR("yglGlyphs setup"); for(ng= 0; ng < nglyph; ng++) { xyz0.x= origins[3*ng]; xyz0.y= origins[3*ng+1]; xyz0.z= origins[3*ng+2]; sc= scal[ng]; th= theta[ng]; snth= (float) sin(th); csth= (float) cos(th); ph= phi[ng]; snph= (float) sin(ph); csph= (float) cos(ph); csph_csth= csph*csth; snph_csth= snph*csth; csph_snth= csph*snth; snph_snth= snph*snth; glColor3fv(colr+3*ng); glBegin(GL_TRIANGLES); for(nv= 0; nv < 3*c_glyph->ntri; nv++) { xyz= (c_glyph->xyz)[nv]; nrm= (c_glyph->nrm)[nv]; x= (float) (xyz0.x+csph_csth*xyz.x*sc+snph_csth*xyz.y*sc-snth*xyz.z*sc); y= (float) (xyz0.y-snph*xyz.x*sc+csph*xyz.y*sc); z= (float) (xyz0.z+csph_snth*xyz.x*sc+snph_snth*xyz.y*sc+csth*xyz.z*sc); nrmx= (float) (csph_csth*nrm.x+snph_csth*nrm.y-snth*nrm.z); nrmy= (float) (snph*nrm.x+csph*nrm.y); nrmz= (float) (csph_snth*nrm.x+snph_snth*nrm.y+csth*nrm.z); glNormal3f(nrmx, nrmy, nrmz); glVertex3f(x, y, z); } glEnd(); } CHEK_ERROR("yglGlyphs"); } void makPyrGlyph(void) { int nv; yPoint3D *xyz, *nrm; float nrz, nrt; /* The pyramid is made up of 6 triangles. compute and save the coordinates of their vertices. */ pyramid_glyph.ntri= 6; xyz= (yPoint3D *) p_malloc(sizeof(yPoint3D)*3*pyramid_glyph.ntri); nrm= (yPoint3D *) p_malloc(sizeof(yPoint3D)*3*pyramid_glyph.ntri); pyramid_glyph.xyz= xyz; pyramid_glyph.nrm= nrm; nv= 0; /* first do the base (the normal is the same for all 6 vertices) */ nrm[nv].x= 0.0; nrm[nv].y= 0.0; nrm[nv].z= -1.0; xyz[nv].x= -0.5; xyz[nv].y= -0.5; xyz[nv].z= -0.5; nv++; nrm[nv]= nrm[nv-1]; xyz[nv].x= 0.5; xyz[nv].y= -0.5; xyz[nv].z= -0.5; nv++; nrm[nv]= nrm[nv-1]; xyz[nv].x= 0.5; xyz[nv].y= 0.5; xyz[nv].z= -0.5; nv++; nrm[nv]= nrm[nv-1]; xyz[nv].x= -0.5; xyz[nv].y= -0.5; xyz[nv].z= -0.5; nv++; nrm[nv]= nrm[nv-1]; xyz[nv].x= 0.5; xyz[nv].y= 0.5; xyz[nv].z= -0.5; nv++; nrm[nv]= nrm[nv-1]; xyz[nv].x= -0.5; xyz[nv].y= 0.5; xyz[nv].z= -0.5; nv++; /* do the four sides. all 3 vertices in a triangle have the same normal. */ nrz= (float) (1.0/sqrt(5.0)); nrt= (float) (2.0/sqrt(5.0)); nrm[nv].x= 0.0; nrm[nv].y= -nrt; nrm[nv].z= nrz; xyz[nv].x= -0.5; xyz[nv].y= -0.5; xyz[nv].z= -0.5; nv++; nrm[nv]= nrm[nv-1]; xyz[nv].x= 0.5; xyz[nv].y= -0.5; xyz[nv].z= -0.5; nv++; nrm[nv]= nrm[nv-1]; xyz[nv].x= 0.0; xyz[nv].y= 0.0; xyz[nv].z= 0.5; nv++; nrm[nv].x= nrt; nrm[nv].y= 0.0; nrm[nv].z= nrz; xyz[nv].x= 0.5; xyz[nv].y= -0.5; xyz[nv].z= -0.5; nv++; nrm[nv]= nrm[nv-1]; xyz[nv].x= 0.5; xyz[nv].y= 0.5; xyz[nv].z= -0.5; nv++; nrm[nv]= nrm[nv-1]; xyz[nv].x= 0.0; xyz[nv].y= 0.0; xyz[nv].z= 0.5; nv++; nrm[nv].x= 0.0; nrm[nv].y= nrt; nrm[nv].z= nrz; xyz[nv].x= 0.5; xyz[nv].y= 0.5; xyz[nv].z= -0.5; nv++; nrm[nv]= nrm[nv-1]; xyz[nv].x= -0.5; xyz[nv].y= 0.5; xyz[nv].z= -0.5; nv++; nrm[nv]= nrm[nv-1]; xyz[nv].x= 0.0; xyz[nv].y= 0.0; xyz[nv].z= 0.5; nv++; nrm[nv].x= -nrt; nrm[nv].y= 0.0; nrm[nv].z= nrz; xyz[nv].x= -0.5; xyz[nv].y= 0.5; xyz[nv].z= -0.5; nv++; nrm[nv]= nrm[nv-1]; xyz[nv].x= -0.5; xyz[nv].y= -0.5; xyz[nv].z= -0.5; nv++; nrm[nv]= nrm[nv-1]; xyz[nv].x= 0.0; xyz[nv].y= 0.0; xyz[nv].z= 0.5; nv++; } void makTetGlyph(void) { int nv; yPoint3D *xyz, *nrm; float val; /* The tetrahedron is made up of 4 triangles. Compute and save the coordinates of their vertices. */ tet_glyph.ntri= 4; xyz= (yPoint3D *) p_malloc(sizeof(yPoint3D)*3*tet_glyph.ntri); nrm= (yPoint3D *) p_malloc(sizeof(yPoint3D)*3*tet_glyph.ntri); tet_glyph.xyz= xyz; tet_glyph.nrm= nrm; nv= 0; val= (float) (0.5*sqrt(3.0)); /* first do the base (the normal is the same for all 3 vertices) */ nrm[nv].x= 0.0; nrm[nv].y= 0.0; nrm[nv].z= -1.0; xyz[nv].x= 1.0; xyz[nv].y= 0.0; xyz[nv].z= 0.0; nv++; nrm[nv]= nrm[nv-1]; xyz[nv].x= -0.5; xyz[nv].y= val; xyz[nv].z= 0.0; nv++; nrm[nv]= nrm[nv-1]; xyz[nv].x= -0.5; xyz[nv].y= -val; xyz[nv].z= 0.0; nv++; /* Do the three sides. All 3 vertices in a triangle have the same normal. */ nrm[nv].x= HT_RAT; nrm[nv].y= sqrt(3.0)*HT_RAT; nrm[nv].z= 1.0; val= (float) (1.0/sqrt(nrm[nv].x*nrm[nv].x+nrm[nv].y*nrm[nv].y+nrm[nv].z*nrm[nv].z)); nrm[nv].x *= val; nrm[nv].y *= val; nrm[nv].z *= val; xyz[nv].x= 0.0; xyz[nv].y= 0.0; xyz[nv].z= HT_RAT; nv++; nrm[nv]= nrm[nv-1]; xyz[nv]= xyz[1]; nv++; nrm[nv]= nrm[nv-1]; xyz[nv]= xyz[0]; nv++; nrm[nv].x= -2.0*HT_RAT; nrm[nv].y= 0.0; nrm[nv].z= 1.0; val= (float) (1.0/sqrt(nrm[nv].x*nrm[nv].x+nrm[nv].y*nrm[nv].y+nrm[nv].z*nrm[nv].z)); nrm[nv].x *= val; nrm[nv].y *= val; nrm[nv].z *= val; xyz[nv]= xyz[1]; nv++; nrm[nv]= nrm[nv-1]; xyz[nv]= xyz[3]; nv++; nrm[nv]= nrm[nv-1]; xyz[nv]= xyz[2]; nv++; nrm[nv].x= HT_RAT; nrm[nv].y= -sqrt(3.0)*HT_RAT; nrm[nv].z= 1.0; val= (float) (1.0/sqrt(nrm[nv].x*nrm[nv].x+nrm[nv].y*nrm[nv].y+nrm[nv].z*nrm[nv].z)); nrm[nv].x *= val; nrm[nv].y *= val; nrm[nv].z *= val; xyz[nv]= xyz[2]; nv++; nrm[nv]= nrm[nv-1]; xyz[nv]= xyz[3]; nv++; nrm[nv]= nrm[nv-1]; xyz[nv]= xyz[0]; nv++; } void yglGlyphs_old(long nglyph, float *origins, float *hite, float *base, float *theta, float *phi, float *colr) { int ng; float x, y, z, fac, x0, y0, z0, ht, bs, b; /* The input is a list of glyphs (ellipsoids). Each (pyramidal) glyph has a center, a height, a base, a color, and a direction (theta and phi). */ /* draw the glyph list now */ if(nglyph <= 0) return; if(alpha_pass) return; /* use smooth shading */ yglSetShade(1); yglUpdateProperties(); CHEK_ERROR("yglGlyphs setup"); for(ng= 0; ng < nglyph; ng++) { glColor3fv(colr+3*ng); x0= origins[3*ng]; y0= origins[3*ng+1]; z0= origins[3*ng+2]; ht= hite[ng]; bs= base[ng]; b= 0.5f*bs; /* Draw a solid pyramid with specified height and base centered at the specified origin with the specified orientation. */ x= x0-b; y= y0-b; z= z0-0.5f*ht; fac= (float) (1.0/sqrt(b*b+ht*ht)); glBegin(GL_QUADS); glNormal3f(0.0f, 0.0f, 1.0f); glVertex3f(x, y, z); glVertex3f(x+bs, y, z); glVertex3f(x+bs, y+bs, z); glVertex3f(x, y+bs, z); glEnd(); glBegin(GL_TRIANGLES); glNormal3f(0.0f, -ht*fac, b*fac); glVertex3f(x, y, z); glVertex3f(x+bs, y, z); glVertex3f(x0, y0, z+ht); glNormal3f(ht*fac, 0.0f, b*fac); glVertex3f(x+bs, y, z); glVertex3f(x+bs, y+bs, z); glVertex3f(x0, y0, z+ht); glNormal3f(0.0f, ht*fac, b*fac); glVertex3f(x+bs, y+bs, z); glVertex3f(x, y+bs, z); glVertex3f(x0, y0, z+ht); glNormal3f(-ht*fac, 0.0f, b*fac); glVertex3f(x, y+bs, z); glVertex3f(x, y, z); glVertex3f(x0, y0, z+ht); glEnd(); } CHEK_ERROR("yglGlyphs"); } void yglEllipsoids(long nglyph, float *origins, float *radii, float *ellip, float *theta, float *phi, float *colr) { int i, j, ng, numi, numj; double lat, lon, x, y, z, csth, snth, csph, snph, pi, dth; double csth1, snth1, fac, x0, y0, z0, eps, radius; #define ang_step_e 15 /* The input is a list of glyphs (ellipsoids). Each ellipsoid has a center, a radius, an ellipticity, a color, and a direction (theta and phi). */ /* draw the glyph list now */ if(nglyph <= 0) return; if(alpha_pass) return; pi= 4.0*atan(1.0); numi= (int)(360.0/ang_step_e)+1; numj= (int)(180.0/ang_step_e)+1; dth= pi/numj; /* use smooth shading */ yglSetShade(1); yglUpdateProperties(); CHEK_ERROR("yglEllipsoids setup"); for(ng= 0; ng < nglyph; ng++) { glColor3fv(colr+3*ng); x0= origins[3*ng]; y0= origins[3*ng+1]; z0= origins[3*ng+2]; eps= ellip[ng]; radius= radii[ng]; /* Draw a solid ellipsoid with specified radius and ellipticity centered at the specified origin. Points are every 15 degrees in latitude and longitude. */ /* do all latitudes */ for(j= 0; j < numj; j++) { lat= j*pi/numj; csth= cos(lat); snth= sqrt(1.0-csth*csth); csth1= cos(lat+dth); snth1= sqrt(1.0-csth1*csth1); glBegin(GL_TRIANGLE_STRIP); /* do all longitudes */ for(i= 0; i <= numi; i++) { lon= i*2.0*pi/numi; csph= cos(lon); snph= sin(lon); x= csph*snth; y= snph*snth; z= eps*csth; fac= 1.0/sqrt(x*x+y*x+z*z); glNormal3f((float)(x*fac),(float)(y*fac),(float)(z*fac)); x= x0+eps*radius*csph*snth; y= y0+eps*radius*snph*snth; z= z0+radius*csth; glVertex3f((float)x,(float)y,(float)z); x= csph*snth1; y= snph*snth1; z= eps*csth1; fac= 1.0/sqrt(x*x+y*x+z*z); glNormal3f((float)(x*fac),(float)(y*fac),(float)(z*fac)); x= x0+eps*radius*csph*snth1; y= y0+eps*radius*snph*snth1; z= z0+radius*csth1; glVertex3f((float)x,(float)y,(float)z); } glEnd(); } } CHEK_ERROR("yglEllipsoids"); } yorick-gl-1.1+cvs20070922+dfsg.orig/gl3dtex.h0000640000175000017500000000464210313362461020154 0ustar thibautthibaut/* * $Id: gl3dtex.h,v 1.1.1.1 2005/09/18 22:07:45 dhmunro Exp $ */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #ifndef __H_3DTEX__ #define __H_3DTEX__ #ifdef __cplusplus extern "C" { #endif /* Extension: GL_EXT_texture3D */ /* OpenGl 1.2 and greater has 3D textures standard. Version 1.1 may have it as an extension. There may be no 3D textures. It is hard to write code that covers all cases. The strategy is to include the GL headers in glcode.h and assume it will define the appropriate 3D texture constants. Macros are defined based on which, if any, 3D texture constants are defined. All code accesses 3D texture features through macros I define. WARNING: Linux with an Nvidia driver does not currently replace the OpenGL headers - it puts them in /usr/share/doc/NVIDIA or some such place. To use 3D textures, modify the include path to pick up the NVIDIA version. WARNING: Windows apparently will never have an OpenGL library or headers beyond version 1.1. many OpenGL drivers on Windows are version 1.2 or above. The proper appraoch is to try and access advanced GL features as extensions. To do this, we need to augment gl.h with additional constants. */ #ifdef WIN32 #define GL_TEXTURE_BINDING_3D_EXT 0x806A #define GL_PACK_SKIP_IMAGES_EXT 0x806B #define GL_PACK_IMAGE_HEIGHT_EXT 0x806C #define GL_UNPACK_SKIP_IMAGES_EXT 0x806D #define GL_UNPACK_IMAGE_HEIGHT_EXT 0x806E #define GL_TEXTURE_3D_EXT 0x806F /* #define GL_TEXTURE_3D 0x806F */ #define GL_PROXY_TEXTURE_3D_EXT 0x8070 /* #define GL_PROXY_TEXTURE_3D 0x8070 */ #define GL_TEXTURE_DEPTH_EXT 0x8071 #define GL_TEXTURE_WRAP_R_EXT 0x8072 #define GL_MAX_3D_TEXTURE_SIZE_EXT 0x8073 #endif #ifndef WIN32 #ifndef GL_TEXTURE_3D #ifndef GL_TEXTURE_3D_EXT #define GL_TEXTURE_DEPTH_EXT 0x8071 #define GL_TEXTURE_WRAP_R_EXT 0x8072 #endif #endif #endif extern void myglTexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels); #ifdef __cplusplus } #endif #endif /* __H_3DTEX__ */ yorick-gl-1.1+cvs20070922+dfsg.orig/README0000640000175000017500000000263210313362503017303 0ustar thibautthibautyorick-gl --------- OpenGL 3D graphics package for yorick, named yorgl. This package contains a sub-package yiso3d which generates 2D isosurfaces given a function on an arbitrary curvilinear 3D mesh. The configure script will cause yiso3d to be built even if OpenGL cannot be found (or you force --no-opengl on the configure command line). To build the yorgl package: ./configure make To install in Y_HOME: make install To uninstall: make uninstall If you are building on multiple platforms, do not forget to run the configure script before each build. Options for the configure script: --yorick=/path/to/yorick exact name of yorick executable if yorick is not on PATH env variable --prefix=/top/level/path directory containing include/, lib/ subdirectories with OpenGL, unnecessary if this is /usr, /usr/local, or /sw --glinc=/path/to/opengl/headers directory containing the GL/ subdirectory, unnecessary if this is /usr/include, /usr/local/include, or /sw/include --gllib=/path/to/opengl/libs unnecessary if this is /usr/lib, /usr/local/lib, or /sw/lib --no-opengl build only yiso3d, do not even look for OpenGL -------------------------------------------------------------------------- PROBLEMS -------- 1. Linux NVIDIA drivers may fail to replace Mesa gl.h but do replace Mesa libGL. Be sure to use --glinc to force correct gl.h, e.g.- ./configure --glinc=/usr/share/doc/NVIDIA_GLX-1.0/include yorick-gl-1.1+cvs20070922+dfsg.orig/glfunc.i0000640000175000017500000006146210313362456020070 0ustar thibautthibaut/* * $Id: glfunc.i,v 1.1.1.1 2005/09/18 22:07:42 dhmunro Exp $ * This file connects yorick to the compiled functions in * the OpenGL based 3D graphics package. */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ /* Several naming conventions have been followed. Routines that are callable from the interpreter have names that start with "ygl" and end in "3d". These routines often have an interpreted wrapper routine that validates arguments before calling the "ygl...3d" routine. If there is both an interpreted wrapper and a compiled wrapper, the name of the user callable function will normally be "...3d" and the name of the interpreted routine wrapped by codger will be "...raw3d". dlist3d.c contains the drawing routines that are called from the interpreter. These routines enter data into yorgl's display list (note - this is NOT an OpenGL display list). Each routine in dlist3d.c that is callable from the interpreter has a companion routine that is called when it is time to render yorgl's display list. Most of these companion routines extract variables from the display list and pass them on to routines in other files that actually call OpenGL. The names of companion routines normally start "yglDraw" and end "3d". glfunc.c also has routines that are callable from the interpreter. These routines do not draw anything, they change lighting, other GL parameters, the viewpoint, etc. The routines that actually call OpenGL normally have names similar to those callable from the interpreter but without the trailing "3d". */ if (!is_void(plug_in)) plug_in, "yorgl"; extern Draw3d; /* DOCUMENT Draw3d Draw both 3D display lists, handling all preparation and clean-up. SEE ALSO: ClearList3d, ClearDirectList3d, ClearCachedList3d */ /* PROTOTYPE void yglDrawCurr3d(void) */ extern ClearList3d; /* DOCUMENT ClearList3d Clear both 3D display lists. SEE ALSO: DrawList3d, ClearDirectList3d, ClearCachedList3d */ /* PROTOTYPE void yglClearList3d(void) */ func GetBounds3d(void) /* DOCUMENT GetBounds3d Compute the bounding box for all 3D objects. Function returns non-zero if there is at least one object. SEE ALSO: DrawList3d, ClearList3d, GetBoundsDirectList3d, GetBoundsCachedList3d */ { bnd= array(0.0, 2, 3); res= GetBounds_raw3d(bnd); if(res) return bnd; else return []; } extern GetBounds_raw3d; /* PROTOTYPE long yglGetBounds3d(double array box) */ extern GetBoundsCachedList3d; /* xxDOCUMENT GetBoundsCachedList3d Compute the bounding box for the 3D "cached" display list. Function returns non-zero if there was something in the list. SEE ALSO: DrawList3d, ClearList3d, ClearDirectList3d, GetBoundsDirectList3d */ /* PROTOTYPE long yglGetBoundsCachedList3d(double array box) */ extern GetBoundsDirectList3d; /* xxDOCUMENT GetBoundsDirectList3d Compute the bounding box for the 3D "direct" display list. Function returns non-zero if there was something in the list. SEE ALSO: DrawList3d, ClearList3d, ClearDirectList3d, GetBoundsCachedList3d */ /* PROTOTYPE long yglGetBoundsDirectList3d(double array box) */ extern polys3d; /* xxDOCUMENT polys3d(nx, ny, xyz, norm, color) Draw a list of polygons in 3D. SEE ALSO: */ /* PROTOTYPE void yglPolys3d(long npolys, long array len, double array xyz, double array norm, double array colr, long edge, long smooth, long do_light) */ extern glyphs3d; /* xxDOCUMENT glyphs3d(nglyph, xyz, scal, theta, phi, color) Draw a set of glyphs in 3D. SEE ALSO: points3d */ /* PROTOTYPE void yglGlyphs3d(long nglyph, double array origin, double array scal, double array theta, double array phi, double array colr) */ extern cells3d; /* xxDOCUMENT cells3d(nx, ny, xyz, norm, color, do_alpha) Draw a planar cell array in 3D. SEE ALSO: */ /* PROTOTYPE void yglCells3d(long nx, long ny, double array corners, double array norm, double array colr, long do_alpha) */ extern plm3d_raw; /* xxDOCUMENT plm3d_raw(nx, ny, xyz, color) Draw a curvilinear "2D" mesh in 3D. SEE ALSO: */ /* PROTOTYPE void yglPlm3d(long nx, long ny, double array xyz, double array colr) */ extern plf3d_raw; /* xxDOCUMENT plf3d_raw(do_alpha, nx, ny, xyz, color) Fill a curvilinear "2D" mesh in 3D. SEE ALSO: */ /* PROTOTYPE void yglPlf3d(long nx, long ny, double array xyz, double array colr) */ extern surf3d; /* xxDOCUMENT surf3d(nx, ny, xyz, norm, color) Draw a surface in 3D. SEE ALSO: */ /* PROTOTYPE void yglSurf3d(long do_alpha, long nx, long ny, double array xyz, double array norm, double array colr) */ extern colrsurf3d; /* xxDOCUMENT colrsurf3d(nx, ny, xyz, norm, color) Draw a surface in 3D. SEE ALSO: */ /* PROTOTYPE void yglColrsurf3d(long do_alpha, long nx, long ny, double array xyz, double array norm, double array colr) */ extern lines3d; /* xxDOCUMENT lines3d(nvert, xyz, color) Draw a polyline in the current 3D window. Arguments are the number of vertices, an array of coordinate triples, and a single color triple. SEE ALSO: points3d */ /* PROTOTYPE void yglLines3d(long nvert, double array xyz, double array colr) */ extern points3d; /* xxDOCUMENT points3d(nvert, xyz, color) Draw a set of points in the current 3D window. Arguments are the number of vertices, an array of coordinate triples, and a single color triple. SEE ALSO: lines3d, glyphs3d */ /* PROTOTYPE void yglPoints3d(long nvert, double array xyz, double array colr) */ extern tstrips3d; /* xxDOCUMENT tstrips3d(nvert, xyz, color) Draw a set of triangle strips in 3D. SEE ALSO: qstrips3d, tarray3d, qarray3d */ /* PROTOTYPE void yglTstrips3d(long nstrips, long array len, double array xyz, double array norm, double array colr, long edge, long smooth, long do_light, long do_alpha) */ extern qstrips3d; /* xxDOCUMENT qstrips3d(nvert, xyz, color) Draw a set of quadrilateral strips in 3D. SEE ALSO: tstrips3d, tarray3d, qarray3d */ /* PROTOTYPE void yglQstrips3d(long nstrips, long array len, double array xyz, double array norm, double array colr, long edge, long smooth, long do_light, long do_alpha) */ extern tstripsndx3d; /* xxDOCUMENT tstripsndx3d(nstrips, numedg, ntri, len, ndx, xyz, norm, colr, edge, do_alpha; Draw a set of triangle strips in 3D. Coordinates and normals are accessed via an index array. SEE ALSO: tstrips3d, qstrips3d, tarray3d, qarray3d */ /* PROTOTYPE void yglTstripsndx3d(long nstrips, long numedg, long ntri, long array len, long array ndx, double array xyz, double array norm, double array colr, long edge, long do_alpha) */ extern tarray3d; /* xxDOCUMENT tarray3d(nvert, xyz, color) Draw an array of triangles in the current 3D window. SEE ALSO: tstrips3d, qstrips3d, qarray3d */ /* PROTOTYPE void yglTarray3d(long ntri, double array xyz, double array norm, double array colr, long edge, long smooth, long do_light, long do_alpha, long cpervrt, long cubemap, long emit) */ extern qarray3d; /* xxDOCUMENT qarray3d(nquad, xyz, norm, colr, edge, cpervrt, smooth, do_light, do_alpha, cpervrt) Draw an array of quadrilaterals to the current 3D window. */ /* PROTOTYPE void yglQarray3d(long nquad, double array xyz, double array norm, double array colr, long edge, long smooth, long do_light, long do_alpha, long cpervrt) */ extern tivarray3d; /* xxDOCUMENT tivarray3d(ntri, nvert, ptndx, xyz, norm, color) Draw an array of triangles in 3D. Triangles are specified using indices into arrays of points and normals. One RGBA color is used for all triangles. SEE ALSO: tstrips3d, qstrips3d, tarray3d, qarray3d */ /* PROTOTYPE void yglTivarray3d(long ntri, long nvert, long array ptndx, double array xyz, double array norm, double array colr) */ extern tvarray3d; /* xxDOCUMENT tvarray3d(ntri, nvert, do_alpha, ptndx, xyz, norm, color) Draw an array of triangles in 3D. Triangles are specified using indices into arrays of points and normals. One color for each triangle. SEE ALSO: tivarray3d, tstrips3d, qstrips3d, tarray3d, qarray3d */ /* PROTOTYPE void yglTvarray3d(long ntri, long nvert, long do_alpha, long cpervrt, long array ptndx, double array xyz, double array norm, double array colr) */ extern tex3d; /* xxDOCUMENT tex3d(ds, origin, znsiz) Draw a volume visualization in 3D. SEE ALSO: texcell2d */ /* PROTOTYPE void yglTex3d(float ds, double array origin, double array boxsiz) */ extern texcell2d; /* xxDOCUMENT texcell2d(nx, ny, nz, znsiz, texval) Draw a volume visualization in 3D. SEE ALSO: tex3d */ /* PROTOTYPE void yglTexcell2d(long nx, long ny, long nz, double array znsiz, char array texval) */ extern plpix3d; /* xxDOCUMENT plpix3d(pix) Draw an array of pixels in an OpenGL window. Each pixel contains one RGB triple. The data type of pix is character. SEE ALSO: clear3 */ /* PROTOTYPE void yglPlpix3d(long nx, long ny, char array pix) */ func _event_handler /* Redraw the screen using the new coordinate transform. */ { draw3_trigger; draw3,1; } func _toggle_handler /* the navigation sphere has been toggled on or off. force a redraw. */ { draw3_trigger; draw3,1; } GL_NDEVS= 7; func win3d(num, width, height) /* DOCUMENT win3d(num, width, height) Create OpenGL output window number num. Window will have specified width and height (in pixels). */ { if(is_void(num)) num= 0; ASSERT, (num >= 0 && num <= GL_NDEVS), "3D window number must be 0 through 7."; if(is_void(width)) width= 500; if(is_void(height)) height= 500; err= win3d_raw(num, width, height); if(!err) return; ASSERT, (err != 1), "REBUILD Yorick - compiled and interpreted code disagree on maximum window number"; ASSERT, (err != 2), "failed to create 3D window - should not happen"; } extern win3d_raw; /* PROTOTYPE int yglWin3d(int num, int w, int h) */ extern get_currwin3d; /* DOCUMENT get_currwin3d() Return the number of the current 3D window. */ /* PROTOTYPE int yglCurrWin3d(void) */ func winkill3d(num) /* DOCUMENT winkill3d(num) Close OpenGL output window number num. */ { if(is_void(num)) { num= get_currwin3d(); } ASSERT, (num >= 0 && num <= GL_NDEVS), "window number must be 0 through 7."; err= winkill3d_raw(num); if(!err) return; ASSERT, (err != 1), "REBUILD Yorick - compiled and interpreted code disagree on maximum window number"; ASSERT, (err != 2), "Cannot close a non-existent 3D window"; } extern winkill3d_raw; /* PROTOTYPE int yglWinKill3d(int num) */ extern grabpix3d; /* xxDOCUMENT grabpix3d(void) Read pixels from the curent 3D window. Always starts from the (1,1) pixel in the window. */ /* PROTOTYPE void yglGetPixels(long nx, long ny, char array pix); */ extern drawpix3d; /* xxDOCUMENT drawpix3d(void) send pixels to the current 3D window. */ /* PROTOTYPE void yglPutPixels(long nx, long ny, char array pix) */ extern mousefunc3d; /* DOCUMENT mousefunc3d(val) controls the efect of mouse motion in an OpenGL window. val==1 means rotate, val==2 means zoom, and val==3 means pan. */ /* PROTOTYPE void yglMouseFunc3d(long val) */ extern get_width3d; /* DOCUMENT get_width3d(void) return the width of the current OpenGL window in pixels. */ /* PROTOTYPE long yglGetWidth3d(void) */ extern get_hite3d; /* DOCUMENT get_hite3d(void) return the height of the current OpenGL window in pixels. */ /* PROTOTYPE long yglGetHite3d(void) */ extern always_show_obj3d; /* DOCUMENT gl_always_show_obj(flag) Draw objects while rotating if flag is non-zero. */ /* PROTOTYPE void yglAlwaysShowObj3d(long flag) */ extern use_list3d; /* DOCUMENT use_list3d(flag) Use an OpenGL display list if flag is non-zero. */ /* PROTOTYPE void yglUseList3d(long flag) */ extern use_array3d; /* DOCUMENT use_array3d(flag) Use OpenGL arrays if flag is non-zero. */ /* PROTOTYPE void yglUseArray3d(long flag) */ extern lookat_raw3d; /* xxDOCUMENT lookat_raw3d(eye, center, up) OpenGL utility routine to set view parameters. Users should call lookat3d() instead. */ /* PROTOTYPE void yglLookat3d(double array eye, double array center, double array up) */ extern getbackrgb_raw3d; /* xxDOCUMENT getbackrgb_raw3d(rgb) Returns the RGB background color of the OpenGL window Normally the user calls gl_getback_rgb3d(), which allocates room for the result. See also: back_rgb3d, back_rgba3d */ /* PROTOTYPE void yglGetBackRGB3d(double array rgb) */ extern back_rgb3d; /* xxDOCUMENT back_rgb3d(rgb) OpenGL utility routine to set the red, green, and blue component of the background color (range zero to one). See also: getback_rgb3d, back_rgba3d */ /* PROTOTYPE void yglBackRGB3d(double array rgb) */ extern back_rgba3d; /* xxDOCUMENT back_rgba3d(rgba) OpenGL utility routine to set the red, green, blue, and "opacity" component of the background color (range zero to one). See also: getback_rgb3d, back_rgb3d */ /* PROTOTYPE void yglBackRGBA3d(double array rgb) */ extern cage_style3d; /* DOCUMENT cage_style3d(style) If style is zero, the limits for the "cage" surrounding the "interesting" data volume will be the bounds of all objects in the scene. See also: cage_limits3d, getcage_limits3d */ /* PROTOTYPE void yglCageStyle3d(long style) */ extern cage_limits3d; /* xxDOCUMENT cage_limits3d(lims) Set the limits for the "cage" surrounding the "interesting" data volume. lims=[xmin,xmax,ymin,ymax,zmin,zmax]. See also: cage_style3d, getcage_limits3d */ /* PROTOTYPE void yglCageLimits3d(double array lims) */ extern getcage_limits3d; /* xxDOCUMENT getcage_limits3d() Returns the limits for the "cage" surrounding the "interesting" data volume. See also: cage_style3d, cage_limits3d */ /* PROTOTYPE void yglGetCageLimits3d(double array lims) */ extern gl_getcagergb_raw; /* xxDOCUMENT gl_getcagergb_raw(rgb) Returns the RGB color of the "cage" (backdrop) Normally the user calls gl_getcage_rgb(), which allocates room for the result. See also: gl_cage_rgb, gl_cage_rgba */ /* PROTOTYPE void yglGetCageRGB3d(double array rgb) */ extern cage_rgb3d; /* xxDOCUMENT cage_rgb3d(rgb) OpenGL utility routine to set the red, green, and blue component of the "cage" (range zero to one). See also: getcage_rgb3d, cage_rgba3d */ /* PROTOTYPE void yglCageRGB3d(double array rgb) */ extern cage_rgba3d; /* xxDOCUMENT cage_rgba3d(rgba) OpenGL utility routine to set the red, green, blue, and "opacity" component of the "cage" (range zero to one). See also: getcage_rgb3d, cage_rgb3d */ /* PROTOTYPE void yglCageRGBA3d(double array rgb) */ extern getgridrgb_raw3d; /* xxDOCUMENT getgridrgb_raw3d(rgb) Returns the RGB color of the "grid" (backdrop) Normally the user calls getgrid_rgb3d(), which allocates room for the result. See also: grid_rgb3d, grid_rgba3d */ /* PROTOTYPE void yglGetGridRGB3d(double array rgb) */ extern grid_rgb3d; /* xxDOCUMENT grid_rgb3d(rgb) OpenGL utility routine to set the red, green, and blue component of the "grid" (range zero to one). See also: getgrid_rgb3d, grid_rgba3d */ /* PROTOTYPE void yglGridRGB3d(double array rgb) */ extern grid_rgba3d; /* xxDOCUMENT grid_rgba3d(rgba) OpenGL utility routine to set the red, green, blue, and "opacity" component of the "grid" (range zero to one). See also: getgrid_rgb3d, grid_rgb3d */ /* PROTOTYPE void yglGridRGBA3d(double array rgb) */ extern yglMap2ColorRaw3d; /* xxDOCUMENT yglMap2ColorRaw3d(ncolr, red, green, blue, vmin, vmax, var, colr) Map indexed data values into RGB colors. Normally used with slicing planes or iso-surfaces. */ /* PROTOTYPE void yglMap2ColorRaw3d(long ncolr, char array red, char array green, char array blue, double vmin, double vmax, double array var, long ntri, long array cellids, float array colr) */ extern get_center3d; /* xxDOCUMENT get_center3d(center) Return the current "center of attention" for lookat. */ /* PROTOTYPE void yglGetCenter3d(double array center) */ extern get_eye3d; /* xxDOCUMENT get_eye3d(eye) Return the current "viewer location" for lookat. */ /* PROTOTYPE void yglGetEye3d(double array eye) */ extern get_up3d; /* xxDOCUMENT get_up3d(up) Return the current up vector for lookat. */ /* PROTOTYPE void yglGetUp3d(double array up) */ extern set_fov3d; /* DOCUMENT set_fov3d(fov) Set the field of view (in degrees) for the current 3D window. */ /* PROTOTYPE void yglSetFov3d(float fov) */ extern get_fov3d; /* DOCUMENT get_fov3d Returns the field of view (in degrees) for the current 3D window. */ /* PROTOTYPE float yglGetFov3d(void) */ extern getGLvers; /* DOCUMENT getGLvers Get the version number for OpenGL. */ /* PROTOTYPE float yglGetVers3d(void) */ extern preptex3d; /* DOCUMENT preptex3d(void) prepare an OpenGL state suitable for the use of 3D textures. */ /* PROTOTYPE void yglPrepTex3d(void) */ extern endtex3d; /* DOCUMENT endtex3d(void) finish using a 3D texture. */ /* PROTOTYPE void yglEndTex3d(void) */ extern ldtex3d; /* xxDOCUMENT ldtex3d(nx, ny, nz, tex) set the 3D texture (used with all 3D windows). */ /* PROTOTYPE void yglLdTex3d(long nx, long ny, long nz, char array tex) */ extern texbox3d; /* xxDOCUMENT texbox3d(ds, origin, deltas) Perform a volume visualization of a 3D "box" of data. */ /* PROTOTYPE int yglTex3dbox(double ds, double array origin, double array deltas) */ extern has_tex3d; /* DOCUMENT has_tex3d() result is non-zero if 3D textures are supported. */ /* PROTOTYPE int yglHasTex3d(void) */ extern has_texcube3d; /* DOCUMENT has_texcube3d() result is non-zero if cube map textures are supported. */ /* PROTOTYPE int yglHasTexcube3d(void) */ extern line_width3d; /* DOCUMENT line_width3d(void) Set the width in pixels for a polyline in OpenGL. */ /* PROTOTYPE void yglLineWidth(double width) */ extern msmov_val3d; /* DOCUMENT msmov_val3d(void) set the number of pixels the mouse must move before the model should be rotated. */ /* PROTOTYPE void yglMsmovVal3d(double val) */ extern set_light3d; /* xxDOCUMENT set_light3d(void) set values describing the light sources used by OpenGL. */ /* PROTOTYPE void yglSetLight3d(double ambient, double diffuse, double specular, double spower, double array sdir) */ extern out_ccw3d; /* DOCUMENT out_ccw3d(dir_flag) set the direction (zero for clockwise, else CCW) for the front face of polygons. */ /* PROTOTYPE void yglFrontFace3d(long dir) */ extern update_list3d; /* DOCUMENT update_list3d(void) update an existing OpenGL display list. */ /* PROTOTYPE int yglUpdateList3d(void) */ extern inc_seq3d; /* DOCUMENT inc_seq3d(void) increment the OpenGL sequence number. Not a user routine. */ /* PROTOTYPE void yglIncSeq3d(void) */ extern arrlim3d; /* xxDOCUMENT arrlim3d(nverts, arr, lims) compute the limits in x, y, and z for a regular 3D grid. */ /* PROTOTYPE int yglArrlim3d(long nverts, double array arr, double array lims) */ func arsum(nsx, nsy, nsz, vin) { dms= dimsof(vin); ASSERT, (dms(1) == 3), "arsum only works for 3D arrays"; nx0= dms(2); ny0= dms(3); nz0= dms(4); vout= array(0.0, nx0/nsx, ny0/nsy, nz0/nsz); gl_arsum, nx0, ny0, nz0, nsx, nsy, nsz, vin, vout; return vout; } extern arsum3d; /* xxDOCUMENT arsum3d(nx0, ny0, nz0, nsx, nsy, nsz, vin, vout) This function sums nsx-by-nsy-by-nsz zone chunks of vin and store the result in vout. vin is nx0-by-ny0-by-nz0. Users normally call arsum, not gl_arsum. SEE ALSO: arsum */ /* PROTOTYPE void yglArsum3d(long nx0, long ny0, long nz0, long nsx, long nsy, long nsz, double array vin, double array vout) */ extern SizeTriArraysNdx3d; /* xxDOCUMENT SizeTriArraysNdx3d(tris) This function counts the number of triangles in a list of triangle arrays. oldtri and newtri must be a pointer to a TriVertexGrp. SEE ALSO: pl3dtrilists, SizeTriArraysNdx, CollapseTriArraysNdx, CopyTriArrayNdx, DoSortTriNdx */ /* PROTOTYPE long yglSizeTriArraysNdx3d(pointer tris) */ extern CopyTriArrayNdx3d; /* xxDOCUMENT CopyTriArrayNdx3d(oldtris, newtris) This function copies a triangle array into another triangle array. WARNING!!! it does not copy coolors!!!!!. oldtri and newtri must be a pointer to a TriVertexGrp. SEE ALSO: pl3dtrilists, SizeTriArraysNdx, CollapseTriArraysNdx, CopyTriArrayNdx, DoSortTriNdx */ /* PROTOTYPE void yglCopyTriArrayNdx3d(pointer oldtris, pointer newtris) */ extern CollapseTriArraysNdx3d; /* xxDOCUMENT CollapseTriArraysNdx3d(colrtyp, oldtris, newtris) This function merges a list of triangle arrays into a single triangle array. abs(colrtyp) is 3 for RGB colors and 4 for RGBA. if colrtyp<0, the input list has scalar colors. oldtri and newtri must be a pointer to a TriVertexGrp. SEE ALSO: pl3dtrilists, SizeTriArraysNdx, CollapseTriArraysNdx, CopyTriArrayNdx, DoSortTriNdx */ /* PROTOTYPE void yglCollapseTriArraysNdx3d(long colrtyp, pointer oldtris, pointer newtris) */ extern DoSortTriNdx3d; /* xxDOCUMENT DoSortTriNdx3d(tris, newptndx) This function performs a depth sort of a triangle array. It uses the current viewpoint. The CALLER is responsible for inserting the new point indices into the triangle array (because the input tri array uses indices into coord, normal, etc. arrays, only the indices must be changed). The resulting triangle array should display correctly with translucency when viewed with this viewing transform. Rotating the scene may lead to incorrect results if the triangles are translucent. tris must be a pointer to a TriVertexGrp. newptndx must be a long array of length at least 3*ntri. SEE ALSO: pl3dtrilists, SizeTriArraysNdx, CollapseTriArraysNdx, CopyTriArrayNdx, DoSortTriNdx */ /* PROTOTYPE void yglDoSortTriNdx3d(pointer tris, long array newptndx) */ extern SizeTriArrays3d; /* xxDOCUMENT SizeTriArrays3d(pointer tris) This function counts the number of triangles in a list of triangle arrays. tris must be a pointer to a TriArrayGrp. SEE ALSO: pl3dtrilists, SizeTriArrays, CollapseTriArrays, CopyTriArray, DoSortTri */ /* PROTOTYPE long yglSizeTriArrays3d(pointer tris) */ extern CopyTriArray3d; /* xxDOCUMENT CopyTriArray3d(long numtri, pointer oldtri, pointer newtri) This function copies a triangle array into another triangle array. WARNING!!! it does not copy coolors!!!!!. oldtri and newtri must be a pointer to a TriArrayGrp. SEE ALSO: pl3dtrilists, SizeTriArrays, CollapseTriArrays, CopyTriArray, DoSortTri */ /* PROTOTYPE void yglCopyTriArray3d(long numtri, pointer oldtri, pointer newtri) */ extern CollapseTriArrays3d; /* xxDOCUMENT CollapseTriArrays3d(long colrtyp, pointer oldtri, pointer newtri) This function merges a list of triangle arrays into a single triangle array. abs(colrtyp) is 3 for RGB colors and 4 for RGBA. if colrtyp<0, the input list has scalar colors. oldtri and newtri must be a pointer to a TriArrayGrp. SEE ALSO: pl3dtrilists, SizeTriArrays, CollapseTriArrays, CopyTriArray, DoSortTri */ /* PROTOTYPE void yglCollapseTriArrays3d(long colrtyp, pointer oldtri, pointer newtri) */ extern DoSortTri3d; /* xxDOCUMENT DoSortTri3d(long colrtyp, pointer oldtri, pointer newtri) This function performs a depth sort of a triangle array. It uses the current viewpoint. The resulting triangle array should display correctly with translucency when viewed with this viewing transform. Rotating the scene may lead to incorrect results if the triangles are translucent. colrtyp is 3 for RGB colors and 4 for RGBA. There MUST be one color for every triangle vertex. oldtri and newtri must be a pointer to a TriArrayGrp. SEE ALSO: pl3dtrilists, SizeTriArrays, CollapseTriArrays, CopyTriArray, DoSortTri */ /* PROTOTYPE void yglDoSortTri3d(long colrtyp, pointer oldtri, pointer newtri) */ extern SliceTris3d; /* xxDOCUMENT SliceTris3d(keep, nkeep, dp, oldtri, newtri) This function clips triangles against a plane using nkeep, the number of vertices from each input triangle that are "above" the slicing plane, keep (above the plane for a specific vertex), and dp (the distance to the plane for each vertex). A user ordinarily calls slice2, not this function. */ /* PROTOTYPE void yglSliceTris3d(long array keep, long array nkeep, double array dp, pointer oldtri, pointer newtri) */ yorick-gl-1.1+cvs20070922+dfsg.orig/slicenew.i0000640000175000017500000002521610313362472020416 0ustar thibautthibaut/* * $Id: slicenew.i,v 1.1.1.1 2005/09/18 22:07:54 dhmunro Exp $ */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ /* ------------------------------------------------------------------------ */ func nuslice2x(plane, tris) /* DOCUMENT slice2, plane, tris Slice a polygon list, retaining only those triangles or parts of triangles on the positive side of PLANE, that is, the side where xyz(+)*PLANE(+:1:3)-PLANE(4) > 0.0. SEE ALSO: slice2, slice2_precision */ { _slice2x= 1; return nuslice2(plane, tris); } func nuslice2(plane, tris) /* DOCUMENT slice2, plane, tris Slice an array of triangles, retaining only those triangles or parts of triangles on the positive side of PLANE, that is, the side where xyz(+)*PLANE(+:1:3)-PLANE(4) > 0.0. In order to plot two intersecting slices, one could slice (for example) the horizontal plane twice (slice2x) - first with the plane of the vertical slice, then with minus that same plane. Then, plot first the back part of the slice, then the vertical slice, then the front part of the horizontal slice. Of course, the vertical plane could be the one to be sliced, and "back" and "front" vary depending on the view point, but the general idea always works. SEE ALSO: slice2x, slice2_precision */ { have_values= !is_void(values); ntri= tris.numTris; /* make a list of the triangle number for each points in xyzverts */ ndxs= (long(span(1, ntri, ntri))(-:1:3,))(*); /* form dot products of all the points with the given plane */ xyzverts= *(tris.xyzverts); normals= *(tris.normals); ids= *(tris.cellIDs); colr= *(tris.colors); var2= *(tris.var2); hasVar2= !is_void(var2); dp= xyzverts(+,)*plane(+:1:3) - plane(4); /* separate into lists of unclipped and partially clipped polys */ if (!slice2_precision) { /* if precision is not set, slice exactly at dp==0.0, with * any points exactly at dp==0.0 treated as if they had dp>0.0 */ keep= (dp>=0.0); } else { /* if precision is set, polygons are clipped to +-precision, * so that any poly crossing +precision is clipped to dp>=+precision, * any poly crossing -precision is clipped to dp<=-precision, and * any poly lying entirely between +-precision is discarded entirely */ keep= (dp>=slice2_precision); } nkeep= long(histogram(ndxs, keep)); mask0= (nkeep==nverts); /* all vertices on "right" side of plane */ mask1= (nkeep!=0 & !mask0); /* part of the vertices on the "right" side */ list1= where(mask1); if (numberof(list1)) { normc= normals(,,list1); colrc= colr(,list1); if(hasVar2) var2c= var2(,list1); idsc= ids(list1); list= where(mask1(ndxs)); xyzc= xyzverts(,,list); } if (_slice2x) { if (!slice2_precision) { mask2= !nkeep; normc0= normc; colrc0= colrc; if(hasVar2) var2c0= var2c; idsc0= idsc; xyzc0= xyzc; } else { keep2= (dp>-slice2_precision); nkeep2= long(histogram(ndxs, keep2)); mask2= (nkeep!=0 & nkeep=0.0); /* get the indices of the first and last points in each clipped poly */ last= nvertc(psum); frst= last - nvertc + 1; /* get indices of previous and next points in cyclic order */ prev= next= indgen(0:numberof(keep)-1); prev(frst)= last; next(prev)= indgen(numberof(keep)); _nuslice2_part; grow, nverts, nvertc; if (have_values) grow, values, valuec; grow, xyzverts, xyzc; if (_slice2x) { skip: nvertc= nvertc0; valuec= valuec0; xyzc= xyzc0; if (!slice2_precision) { keep= !keep; } else { dp= dp(listc)+slice2_precision; keep= (dp>=0.0); } _nuslice2_part; grow, nvertb, nvertc; if (have_values) grow, valueb, valuec; grow, xyzvertb, xyzc; } } func slice2only(plane, tris) /* DOCUMENT slice2, plane, tris Slice an array of triangles, retaining only those triangles or parts of triangles on the positive side of PLANE, that is, the side where xyz(+)*PLANE(+:1:3)-PLANE(4) > 0.0. In order to plot two intersecting slices, one could slice (for example) the horizontal plane twice (slice2x) - first with the plane of the vertical slice, then with minus that same plane. SEE ALSO: slice2x, slice2_precision */ { if(!tris) return []; ntri= tris.numTri; /* make a list of the triangle number for each point in xyzverts */ ndxs= (long(span(1, ntri, ntri))(-:1:3,))(*); /* form dot products of all the points with the given plane */ xyzverts= *(tris.xyzverts); normals= *(tris.normals); ids= *(tris.cellIDs); colr= *(tris.colors); var2= *(tris.var2); dp= xyzverts(+,)*plane(+:1:3) - plane(4); /* separate into lists of unclipped and partially clipped polys */ if (!slice2_precision) { /* if precision is not set, slice exactly at dp==0.0, with * any points exactly at dp==0.0 treated as if they had dp>0.0 */ keep= (dp>=0.0); } else { /* if precision is set, polygons are clipped to +-precision, * so that any poly crossing +precision is clipped to dp>=+precision, * any poly crossing -precision is clipped to dp<=-precision, and * any poly lying entirely between +-precision is discarded entirely */ keep= (dp>=slice2_precision); } nkeep= long(histogram(ndxs, keep)); /* Create storage for the output triangles. There will be one output triangle for each entry in list0. There will be one triangle for everywhere that nkeep==1 (one vertex is "to the right" of the plane) and two triangles where nkeep==2 (two vertices to the "right"). */ nulvar= []; numnew= sum(nkeep)-2*sum( nkeep==3 ); if(numnew <= 0) return []; newxyz= array(0.0, 3, 3, numnew); newnorm= array(0.0, 3, 3, numnew); newcolr= array(float, 3, numnew); hasVar2= !is_void(var2); if(hasVar2) { newvar2= array(double, 3, numnew); } else { newvar2= nulvar; } newids= array(long, numnew); newtri= TriArrayGrp(numTri= numnew, xyzverts= &newxyz, normals= &newnorm, colors= &newcolr, cellIDs= &newids, var2= &newvar2, /* the next 3 are not used except while forming strips */ nTris= &nulvar, triEdg= &nulvar, triStart= &nulvar, next= &nulvar); /* call the routine that clips triangles and copies unaltered triangles */ SliceTris3d,keep,nkeep,dp,&tris,&newtri; return newtri; } func test_slice2(offset) { require,"testgl.i"; extern n_poly_3d, n_tri_3d; extern have_slice; extern have_sphere; if(is_void(offset)) offset= 0.2; plane= [1.0,0.0,0.0,offset]; write,format="slice plane is in direction (%f,%f,%f) with offset %f\n", plane(1),plane(2),plane(3),plane(4); ngrid= 40; nx= ny= nz= ngrid; xyz= array(0.0, 3, nx,ny,nz); xyz(1,..)= span(-1,1,nx); xyz(2,..)= span(-1,1,nx)(-,); xyz(3,..)= span(-1,1,nx)(-,-,); r= abs(xyz(1,..),xyz(2,..),xyz(3,..)); theta= acos(xyz(3,..)/r); phi= atan(xyz(2,..),xyz(1,..)+(!r)); y32= sin(theta)^2*cos(theta)*cos(2*phi); f= r*(1.+y32); r= theta= phi= []; write, " test uses "+pr1((nx-1)*(ny-1)*(nz-1))+" cells"; origin= [-1.0,-1.0,-1.0]; delta= [2.0/(nx-1.0), 2.0/(nx-1.0), 2.0/(nx-1.0)]; level= 1.0; colr= [0.0,1.0,0.2]; tris= iso3cenre(origin,delta,f,level,colr); if(tris) { tris2= CollapseTri3d(tris); } tnew= slice2only(plane, tris2); clear3; if(tnew) { res= pl3dtrilists(tnew); } draw3, !making_movie; stdview3; } local slice2_precision; /* DOCUMENT slice2_precision= precision Controls how slice2 (or slice2x) handles points very close to the slicing plane. PRECISION should be a positive number or zero. Zero PRECISION means to clip exactly to the plane, with points exactly on the plane acting as if they were slightly on the side the normal points toward. Positive PRECISION means that edges are clipped to parallel planes a distance PRECISION on either side of the given plane. (Polygons lying entirely between these planes are completely discarded.) Default value is 0.0. SEE ALSO: slice2, slice2x */ slice2_precision= 0.0; func _nuslice2_part(num,ntri,keep,dp,xyzc,normc,colrc,idsc,xyznew,normnew,colrnew,idsnew) { ncut= keep(sum,); one= where(ncut == 1); two= where(ncut == 2); /* find the points where any edges of the polys cut the plane */ mask0= (!keep) & keep(next); /* off-->on */ list0= where(mask0); if (numberof(list0)) { list= next(list0); dpl= dp(list0)(-,); dpu= dp(list)(-,); xyz0= (xyzc(,list0)*dpu-xyzc(,list)*dpl)/(dpu-dpl); } mask1= (!keep) & keep(prev); /* on-->off */ list1= where(mask1); if (numberof(list1)) { list= prev(list1); dpl= dp(list1)(-,); dpu= dp(list)(-,); xyz1= (xyzc(,list1)*dpu-xyzc(,list)*dpl)/(dpu-dpl); } /* form an index list xold which gives the indices in the original * xyzc list at the places in the new, sliced xyzc list */ mask= keep+mask0+mask1; /* 0, 1, or 2 */ list= mask(psum); /* index values in new list */ xold= array(0, list(0)); mlist= where(mask); xold(list(mlist))= mlist; dups= where(mask==2); if (numberof(dups)) xold(list(dups)-1)= dups; /* form the new, sliced xyzc vertex list */ xyzc= xyzc(,xold); if (numberof(list0)) xyzc(,list(list0))= xyz0; if (numberof(list1)) xyzc(,list(list1)-mask(list1)+1)= xyz1; /* get the list of indices into nvertc (or valuec) for each of * the points in xyzc */ ndxs= histogram(1+last)(1:-1); ndxs(1)+= 1; ndxs= ndxs(psum); /* compute the new number of vertices */ nvertc= histogram(ndxs(xold)); } yorick-gl-1.1+cvs20070922+dfsg.orig/testgl.i0000640000175000017500000022207510313362470020107 0ustar thibautthibaut/* * $Id: testgl.i,v 1.1.1.1 2005/09/18 22:07:52 dhmunro Exp $ * Demonstration of 3D plots using the OpenGL based * 3D graphics package in yorick. */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ require, "dlist3d.i" use_interleave= 0; require, "testisotree.i" require,"slicenew.i"; require, "pnm.i"; require, "contour.i"; palette3d, "earth.gp"; palette3d, "stern.gp"; n_pass= 1; keepview= 1; do_rotate= 1; sho_scene= 1; have_ylm= 0; func testgl { "testgl.i - exercises the OpenGL based 3D graphics package in Yorick\n"; "testall3d,nn runs thru all the samples with nn-by-nn-by-nn grid"; "and reports performance numbers"; "demo3d,nn shows all the different kinds of plots and pauses at each"; " "; "mak_sphere,ntheta,nphi makes a sphere with the specified grid."; "mak_ellipsoid,ntheta,nphi,eps makes an ellipsoid with the specified grid."; "rsphere rotates the sphere created by mak_sphere."; "mak_slice,ngrid draws a combination of iso-surfaces and a"; " slicing plane. ngrid is the size of the grid."; "dslice rotates the scene made by mak_slice"; "rlines draws and rotates polylines in 3D"; "sho_isotree,ngrid draws a single iso-surface using cell centered data"; " tri arrays and ghost cells. Uses an octree"; "sho_isohex,ngrid draws a single iso-surface using point centered data"; " arbitrarily connected grid"; "sho_volviz3,ngrid draws a volume visualization of a 3D cell array"; "sho_texiso,ngrid draws an iso-surface inside a volume visualization"; "sho_drum,ngrid draws an oscillating drum head"; "Other functions may be of interest - examine the file"; } func testall3d(size) { extern make_strip; if(is_void(size)) size= 32; make_strip= 0; // rotate each scene the same number of times num_rotn= 120; target= 2.0; // target run time for each "movie" start_tim= fin_tim= array(0.0, 3); timer, start_tim; "sho_isoreg: iso-surface on regular grid"; sho_isoreg,size; stdview3d; do_rot,num_rotn,targ_tim=target; "sho_iso2: transparent iso-surfaces on a regular grid"; sho_iso2,size; do_rot,num_rotn,targ_tim=target; "sho_isozcenreg: iso-surface on regular grid with zone-centered data"; sho_isozcenreg,size; do_rot,num_rotn,targ_tim=target; "sho_isozcenregngrd: iso-surface on regular grid with zone-centered data, no guard"; sho_isozcenregngrd,size; do_rot,num_rotn,targ_tim=target; "sho_isoregndx: iso-surface on regular grid returning indices into point list"; sho_isoregndx,size; do_rot,num_rotn,targ_tim=target; "sho_isozcenregndx: iso-surface on regular grid with zone-centered data returning indices into point list"; sho_isozcenregndx,size; do_rot,num_rotn,targ_tim=target; "sho_isocrv: iso-surface on curvilinear grid"; sho_isocrv,size; do_rot,num_rotn,targ_tim=target; "sho_isozcencrv: iso-surface on curvilinear grid with zone-centered data"; sho_isozcencrv,size; do_rot,num_rotn,targ_tim=target; "sho_isocrvndx: iso-surface on curvilinear grid returning indices into point list"; sho_isocrvndx,size; do_rot,num_rotn,targ_tim=target; "sho_isozcencrvndx: iso-surface on curvilinear grid returning indices into point list"; sho_isozcencrvndx,size; do_rot,num_rotn,targ_tim=target; "sho_isohex: iso-surface on a pile of hexahedra"; sho_isohex,size; do_rot,num_rotn,targ_tim=target; "sho_isotree: octtree based iso-surface on a regular grid with a color per vertex"; sho_isotree,size,cpervrt=1; do_rot,num_rotn,targ_tim=target; "sho_isotreevarr: octtree based iso-surface on a regular grid with a color per vertex and indexed triangles"; sho_isotreevarr,size,cpervrt=1; do_rot,num_rotn,targ_tim=target; "sho_volviz3: volume visualization"; sho_volviz3,size; do_rot,num_rotn,targ_tim=target; "sho_texiso: volume visualization using 3D texture hardware"; sho_texiso,size; do_rot,num_rotn,targ_tim=target; "sho_drum: oscillating drum head"; drum_size= size; sho_drum,targ_tim=target; "mak_slice: slice plane and iso-surface"; mak_slice,size; do_rot,num_rotn,targ_tim=target; "mak_sphere: sphere made with quad strips and a color per zone"; mak_sphere,4*size,4*size; do_rot,num_rotn,targ_tim=target; "mak_colrsurf: sphere made with quad strips and a color at each vertex"; mak_colrsurf,4*size,4*size; do_rot,num_rotn,targ_tim=target; "mak_ellipsoid: ellipsoid made with tri strips"; mak_ellipsoid,4*size,4*size,0.5; do_rot,num_rotn,targ_tim=target; "rlines: polylines"; rlines,128*size; do_rot,num_rotn,targ_tim=target; "sho_points3d: 3D points"; sho_points3d,size*3000; do_rot,num_rotn,targ_tim=target; "sho_glyph: 3D glyphs"; sho_glyph,size; do_rot,num_rotn,targ_tim=target; "slicecrv_movie: slicing plane on a curvilinear grid using an octtree"; slicecrv_movie,size; "slice_movie: slicing plane on a regular grid using an octtree"; slice_movie,size; "isotree_movie: iso-surface on a regular grid using an octtree"; isotree_movie,size; timer,fin_tim; write,"****************************************"; tot_tim= (fin_tim - start_tim)(3); write,"time for all plots is", tot_tim; write," "; } func demo3d(size) { extern make_strip, n_pass; if(is_void(size)) size= 32; make_strip= 0; old_npass= n_pass; n_pass= 1; "Iso-surfaces can be computed on Cartesian and curvilinear grids"; sho_isoreg,size; stdview3d; pause,2000; "Transparent iso-surfaces can be be drawn with additional effort"; sho_iso2,size; pause,2000; "Iso-surfaces may have color variation"; sho_isotree,size,cpervrt=1; pause,2000; "Volume visualizations can be helpful for 3D fields"; sho_volviz3,size; pause,2000; "This is a 3D object made from triangles computed by yorick."; mak_sphere,4*size,4*size; draw3d,1; pause,2000; "This is the same sphere, but with a backdrop"; cage_style3d,-1; cage_rgb3d,[1.0,1.0,0.0]; grid_rgb3d,[0.0,0.0,1.0]; mak_sphere,4*size,4*size; draw3d,1; pause,2000; cage_style3d,0; "This is the same sphere, but with a backdrop and user chosen location"; cage_style3d,1; cage_rgb3d,[1.0,1.0,0.0]; grid_rgb3d,[0.0,0.0,1.0]; cage_limits3d,[-2.0,2.0,-1.0,1.0,-1.0,3.0]; mak_sphere,4*size,4*size; draw3d,1; pause,2000; cage_style3d,0; "This drum head is a more complex surface computed by yorick."; drum_size= size; sho_drum,targ_tim=1.0; pause,2000; "Slice planes and iso-surfaces can be combined in a single image."; "This image also involves clipping an iso-surface against a plane."; mak_slice,size; eye= [-2.0,2.0,0.0]; center= [0.0,0.0,0.0]; up= [0.0,0.0,1.0]; lookat3d,eye,center,up; draw3d,1; pause,2000; "Polylines in 3D might be used to show streamlines."; rlines,128*size; draw3d,1; pause,2000; "Points in 3D might come from a particle-in-cell simulation"; sho_points3d,size*3000; draw3d,1; pause,2000; "Surface plots are used to show heights above a 2D grid"; sho_surf3d,size; draw3d,1; pause,2000; "Volume visualizations allow all zonesss to contribute to the final image"; sho_texiso,size; lookat3d,[2.0,0.0,0.0],[0.0,0.0,0.0],[0.0,1.0,0.0]; draw3d,1; pause,2000; n_pass= old_npass; } stern_red= [0x00,0x15,0x2b,0x40,0x56,0x6c,0x82,0x98,0xb8,0xd5,0xeb,0xfc,0xf6,0xf0,0xea, 0xe4,0xdd,0xd7,0xd1,0xcb,0xc4,0xbe,0xb8,0xb2,0xac,0xa0,0x9a,0x94,0x8e,0x87, 0x81,0x7b,0x75,0x6f,0x68,0x62,0x5c,0x56,0x4f,0x49,0x43,0x3c,0x31,0x2b,0x25, 0x1f,0x18,0x12,0x0c,0x06,0x40,0x41,0x42,0x43,0x44,0x46,0x47,0x48,0x4a,0x4b, 0x4d,0x4e,0x4f,0x50,0x51,0x53,0x54,0x55,0x56,0x57,0x59,0x5a,0x5b,0x5c,0x5d, 0x60,0x61,0x62,0x63,0x64,0x66,0x67,0x68,0x69,0x6a,0x6c,0x6d,0x6e,0x6f,0x70, 0x72,0x73,0x75,0x76,0x77,0x79,0x7a,0x7b,0x7c,0x7d,0x80,0x81,0x82,0x83,0x84, 0x86,0x87,0x88,0x8a,0x8b,0x8d,0x8e,0x8f,0x90,0x91,0x93,0x94,0x95,0x96,0x97, 0x99,0x9a,0x9b,0x9c,0x9d,0xa0,0xa1,0xa2,0xa3,0xa4,0xa6,0xa7,0xa8,0xa9,0xaa, 0xac,0xad,0xae,0xaf,0xb0,0xb2,0xb3,0xb5,0xb6,0xb7,0xb9,0xba,0xbb,0xbc,0xbd, 0xc0,0xc1,0xc2,0xc3,0xc4,0xc6,0xc7,0xc8,0xca,0xcb,0xcd,0xce,0xcf,0xd0,0xd1, 0xd3,0xd4,0xd5,0xd6,0xd7,0xd9,0xda,0xdb,0xdc,0xdd,0xe0,0xe1,0xe2,0xe3,0xe4, 0xe6,0xe7,0xe8,0xe9,0xea,0xec,0xed,0xee,0xef,0xf0,0xf2,0xf3,0xf5,0xf6,0xf7, 0xf9,0xfa,0xfb,0xfc,0xfd]; stern_green= [0x00,0x01,0x02,0x03,0x04,0x06,0x07,0x08,0x0a,0x0b,0x0d,0x0e,0x0f,0x10,0x11, 0x13,0x14,0x15,0x16,0x17,0x19,0x1a,0x1b,0x1c,0x1d,0x20,0x21,0x22,0x23,0x24, 0x26,0x27,0x28,0x29,0x2a,0x2c,0x2d,0x2e,0x2f,0x30,0x32,0x33,0x35,0x36,0x37, 0x39,0x3a,0x3b,0x3c,0x3d,0x40,0x41,0x42,0x43,0x44,0x46,0x47,0x48,0x4a,0x4b, 0x4d,0x4e,0x4f,0x50,0x51,0x53,0x54,0x55,0x56,0x57,0x59,0x5a,0x5b,0x5c,0x5d, 0x60,0x61,0x62,0x63,0x64,0x66,0x67,0x68,0x69,0x6a,0x6c,0x6d,0x6e,0x6f,0x70, 0x72,0x73,0x75,0x76,0x77,0x79,0x7a,0x7b,0x7c,0x7d,0x80,0x81,0x82,0x83,0x84, 0x86,0x87,0x88,0x8a,0x8b,0x8d,0x8e,0x8f,0x90,0x91,0x93,0x94,0x95,0x96,0x97, 0x99,0x9a,0x9b,0x9c,0x9d,0xa0,0xa1,0xa2,0xa3,0xa4,0xa6,0xa7,0xa8,0xa9,0xaa, 0xac,0xad,0xae,0xaf,0xb0,0xb2,0xb3,0xb5,0xb6,0xb7,0xb9,0xba,0xbb,0xbc,0xbd, 0xc0,0xc1,0xc2,0xc3,0xc4,0xc6,0xc7,0xc8,0xca,0xcb,0xcd,0xce,0xcf,0xd0,0xd1, 0xd3,0xd4,0xd5,0xd6,0xd7,0xd9,0xda,0xdb,0xdc,0xdd,0xe0,0xe1,0xe2,0xe3,0xe4, 0xe6,0xe7,0xe8,0xe9,0xea,0xec,0xed,0xee,0xef,0xf0,0xf2,0xf3,0xf5,0xf6,0xf7, 0xf9,0xfa,0xfb,0xfc,0xfd]; stern_blue= [0x00,0x01,0x03,0x06,0x08,0x0b,0x0d,0x0f,0x13,0x16,0x19,0x1b,0x1d,0x20,0x22, 0x25,0x27,0x29,0x2c,0x2e,0x31,0x33,0x35,0x38,0x3a,0x3f,0x41,0x43,0x46,0x48, 0x4b,0x4d,0x4f,0x52,0x54,0x57,0x59,0x5b,0x5e,0x60,0x63,0x65,0x69,0x6c,0x6e, 0x71,0x73,0x75,0x78,0x7a,0x7f,0x81,0x83,0x86,0x88,0x8b,0x8d,0x8f,0x93,0x96, 0x99,0x9b,0x9d,0xa0,0xa2,0xa5,0xa7,0xa9,0xac,0xae,0xb1,0xb3,0xb5,0xb8,0xba, 0xbf,0xc1,0xc3,0xc6,0xc8,0xcb,0xcd,0xcf,0xd2,0xd4,0xd7,0xd9,0xdb,0xde,0xe0, 0xe3,0xe6,0xe9,0xec,0xee,0xf1,0xf3,0xf5,0xf8,0xfa,0xfe,0xf9,0xf4,0xef,0xea, 0xe5,0xe0,0xda,0xd3,0xcc,0xc7,0xc2,0xbd,0xb8,0xb3,0xae,0xa8,0xa3,0x9f,0x99, 0x94,0x8f,0x8a,0x85,0x80,0x76,0x71,0x6c,0x67,0x62,0x5d,0x58,0x52,0x4e,0x49, 0x43,0x3e,0x39,0x34,0x2f,0x2a,0x23,0x1b,0x17,0x11,0x0c,0x07,0x02,0x02,0x06, 0x0f,0x14,0x18,0x1d,0x21,0x26,0x2a,0x2f,0x37,0x3b,0x40,0x45,0x4a,0x4e,0x52, 0x57,0x5c,0x60,0x65,0x69,0x6e,0x73,0x77,0x7c,0x80,0x89,0x8d,0x92,0x97,0x9b, 0x9f,0xa4,0xa9,0xae,0xb1,0xb6,0xbb,0xc0,0xc4,0xc8,0xcd,0xd3,0xda,0xdf,0xe3, 0xe8,0xec,0xf1,0xf6,0xfa]; func sho_surf3d(ngrid) { extern sho_scene; xx= span(0.0,3.0*pi,ngrid)(,-:1:ngrid); yy= span(0.0,4.0*pi,ngrid)(-:1:ngrid,); f= sin(xx)+cos(yy); xyz= transpose([xx,yy,f], [3,1,2]); // get zone centered normals normzc= get_normal3d(xyz); // point center the normals norm= xyz; norm(1,..)= ptcen(normzc(1,..)); norm(2,..)= ptcen(normzc(2,..)); norm(3,..)= ptcen(normzc(3,..)); color= [0.3,1.0,0.0]; if(!sho_scene) return; clear3d; plsurf3d, xyz, norm, color; center= [0.5*(min(xx)+max(xx)), 0.5*(min(yy)+max(yy)), 0.0]; up= [0.0,0.0,1.0]; dist= 1.5*(min(xx)+max(xx)); eye= center+dist*[1.0, 0.0, 0.4]; lookat3d,eye,center,up; draw3d,1; } func sho_pic3d(npt,use_dir) { clr_count; res= mak_pic3d(npt,use_dir); if(!is_void(res)) { write,"number of points is ",long(res(1)); write,"number of quads is ",long(res(2)); write,"time to draw points is ",res(3); write,"time to build display list is ",res(4); } } func mak_pic3d(npoint,use_dir) { extern n_poly_3d, n_tri_3d, n_point_3d; extern n_pass, stern_red, stern_green, stern_blue; extern sho_scene; // generate a set of random points inside the -1 to 1 cube. // assign each a velocity based on a "rotating fluid" // color them based on the magnitude or direction of // the velocity if(is_void(npoint)) npoint= 10000; pxyz= array(0.0, 3, npoint); pxyz(1,)= 2.0*random(npoint)-1.0; pxyz(2,)= 2.0*random(npoint)-1.0; pxyz(3,)= 2.0*random(npoint)-1.0; r= abs(pxyz(1,..),pxyz(2,..)); rp= r+!r; phi= atan(pxyz(2,..),pxyz(1,..)+(!r)); vxyz= array(0.0, 3, npoint); vxyz(1,)= sin(phi)*r; vxyz(2,)= -cos(phi)*r; vxyz(3,)= 0.0; if(use_dir) { byt_y= bytscl(phi, top=199); pcolor= array(0.0, 3, npoint); pcolor(1,)= stern_red(1+byt_y)/255.0; pcolor(2,)= stern_green(1+byt_y)/255.0; pcolor(3,)= stern_blue(1+byt_y)/255.0; } else { vel= abs(vxyz(1,..),vxyz(2,..),vxyz(3,..)); byt_y= bytscl(vel, top=199); pcolor= array(0.0, 3, npoint); pcolor(1,)= stern_red(1+byt_y)/255.0; pcolor(2,)= stern_green(1+byt_y)/255.0; pcolor(3,)= stern_blue(1+byt_y)/255.0; } // create a sphere with radius r0 nth= 37; nphi= 73; phi= span(0.0, 2*pi, nphi); csph= cos(phi); snph= sin(phi); theta= span(0.0, pi, nth); csth= cos(theta); snth= sin(theta); r0= 0.125; origin= [0.0, 0.0, 0.0]; // set vertex order to get correct outer side for GL // by reversing on the phi index xx= r0*snth(-,)*csph(0:1:-1); yy= r0*snth(-,)*snph(0:1:-1); zz= r0*csth(-,)*array(1.0, nphi); sxyz= [xx, yy, zz]; sxyz= transpose(sxyz, [3, 1, 2]); sxyz += origin; xx= yy= zz= []; scolor= [0.5, 1.0, 0.0]; nquad= (nth-1)*(nphi-1); tstart= tfin= array(0.0, 3); list_tim= draw_tim= 0.0; back_rgb3d, [0.0,0.0,0.0]; if(!sho_scene) return [0, 0, 0.0, 0.0]; clear3d; /* draw all points in the lists */ timer, tstart; plpoints3d, pxyz, pcolor; // plot a sphere using OpenGL Quad Strips for(i= 1; i < nphi; i++) { txyz= sxyz(,i:i+1,); norm= txyz/r0; plqstrips3d, numberof(txyz(1,1,)), txyz, scolor, norm; } timer,tfin; list_tim += (tfin-tstart)(3); center= [0.0, 0.0, 0.0]; up= [0.0,1.0,0.0]; dist= 3.0; theta= pi/18; view= [sin(theta), 0.0, cos(theta)]; eye= center+dist*view; lookat3d,eye,center,up; draw3d,1; n_point_3d= npoint; n_poly_3d= nquad; n_tri_3d= 2*nquad; return [npoint, nquad, draw_tim, list_tim]; } func sho_points3d(npt) { clr_count; res= mak_points3d(npt); if(!is_void(res)) { write,"number of points is ",long(res(1)); write,"number of quads is ",long(res(2)); write,"time to draw points is ",res(3); write,"time to build display list is ",res(4); } } func mak_points3d(npoint) { extern n_poly_3d, n_tri_3d, n_point_3d; extern n_pass, stern_red, stern_green, stern_blue; extern sho_scene; // generate a set of random points inside the volume // color them based on the value of y32 if(is_void(npoint)) npoint= 10000; pxyz= array(0.0, 3, npoint); pxyz(1,)= 2.0*random(npoint)-1.0; pxyz(2,)= 2.0*random(npoint)-1.0; pxyz(3,)= 2.0*random(npoint)-1.0; r= abs(pxyz(1,..),pxyz(2,..),pxyz(3,..)); rp= r+!r; theta= acos(pxyz(3,..)/rp); phi= atan(pxyz(2,..),pxyz(1,..)+(!r)); y32= sin(theta)^2*cos(theta)*cos(2*phi); byt_y= bytscl(y32, top=199); pcolor= array(0.0, 3, npoint); pcolor(1,)= stern_red(1+byt_y)/255.0; pcolor(2,)= stern_green(1+byt_y)/255.0; pcolor(3,)= stern_blue(1+byt_y)/255.0; // create a sphere with radius r nth= 37; nphi= 73; phi= span(0.0, 2*pi, nphi); csph= cos(phi); snph= sin(phi); theta= span(0.0, pi, nth); csth= cos(theta); snth= sin(theta); r= 0.125; origin= [0.0, 0.0, 0.0]; // set vertex order to get correct outer side for GL // by reversing on the phi index xx= r*snth(-,)*csph(0:1:-1); yy= r*snth(-,)*snph(0:1:-1); zz= r*csth(-,)*array(1.0, nphi); sxyz= [xx, yy, zz]; sxyz= transpose(sxyz, [3, 1, 2]); sxyz += origin; xx= yy= zz= []; scolor= [0.5, 1.0, 0.0]; nquad= (nth-1)*(nphi-1); tstart= tfin= array(0.0, 3); list_tim= draw_tim= 0.0; back_rgb3d, [0.0,0.0,0.0]; if(!sho_scene) return [0, 0, 0.0, 0.0]; clear3d; /* draw all points in the lists */ timer, tstart; plpoints3d, pxyz, pcolor; // plot a sphere using OpenGL Quad Strips for(i= 1; i < nphi; i++) { txyz= sxyz(,i:i+1,); norm= txyz/r; plqstrips3d, numberof(txyz(1,1,)), txyz, scolor, norm; } timer,tfin; list_tim += (tfin-tstart)(3); center= [0.0, 0.0, 0.0]; up= [0.0,1.0,0.0]; dist= 3.0; theta= pi/18; view= [sin(theta), 0.0, cos(theta)]; eye= center+dist*view; lookat3d,eye,center,up; draw3d,1; n_point_3d= npoint; n_poly_3d= nquad; n_tri_3d= 2*nquad; return [npoint, nquad, draw_tim, list_tim]; } func sho_glyph(npt) { clr_count; res= mak_glyph(npt); if(!is_void(res)) { write,"number of triangles is ",long(res(1)); write,"number of quads is ",long(res(2)); write,"time to draw glyphs is ",res(3); write,"time to build display list is ",res(4); } } func mak_glyph(npts) { extern n_poly_3d, n_tri_3d, n_point_3d; extern n_pass, stern_red, stern_green, stern_blue; extern sho_scene; // generate a set of points on a regular cylindrical grid // the grid runs from -zmx to zmx in z, 0 to 2*pi in phi // and 0 to rmx in r. // The vector function is the normal to families of // curves with sine variations: // 0 = r-a*(1+b*sin(0.5*pi*z/zmx)) // so the function is: // r-hat + (0.5*pi*b*r/zmx)*cos(0.5*pi*z/zmx)/(1+b*sin(0.5*pi*z/zmx)) if(is_void(npts)) npts= 32; nz= max(3, npts/5); nrad= max(3, nz/2); nphi= max(3, npts/3); nglyph= nz*nphi*nrad; if(is_void(zmx)) zmx= 1.0; if(is_void(amx)) amx= zmx; if(is_void(b)) b= 0.5; phi= span(0.0, 2*pi, nphi)(-:1:nz, -:1:nrad, ); z= span(-zmx, zmx, nz)(,-:1:nrad, -:1:nphi); a= (span(1.0, nrad, nrad)*amx/nrad)(-:1:nz,,-:1:nphi); r= (1.0+b*sin(0.5*pi*z/zmx))*a; pxyz= array(0.0, 3, nz, nrad, nphi); pxyz(1,..)= r*cos(phi); pxyz(2,..)= r*sin(phi); pxyz(3,..)= z; f= pxyz; f(1,..)= cos(phi); f(2,..)= sin(phi); f(3,..)= 0.5*pi*b/zmx*a*cos(0.5*pi*z/zmx); fsz= abs(f(1,..), f(2,..), f(3,..)); f /= fsz(-,..); byt_y= char(10)+bytscl(fsz, top=189); pcolor= pxyz; pcolor(1,..)= stern_red(1+byt_y)/255.0; pcolor(2,..)= stern_green(1+byt_y)/255.0; pcolor(3,..)= stern_blue(1+byt_y)/255.0; // set the height and base of a glyph scal= array(0.07, nglyph); // set theta and phi (the glyph orientation) thglyph= atan(abs(f(1,..),f(2,..)), f(3,..)); phiglyph= phi; ntri= nglyph*4; // create a sphere with radius r0 nth= 13; nphi= 25; phi= span(0.0, 2*pi, nphi); csph= cos(phi); snph= sin(phi); theta= span(0.0, pi, nth); csth= cos(theta); snth= sin(theta); r0= 0.125; origin= [0.0, 0.0, 0.0]; // set vertex order to get correct outer side for GL // by reversing on the phi index xx= r0*snth(-,)*csph(0:1:-1); yy= r0*snth(-,)*snph(0:1:-1); zz= r0*csth(-,)*array(1.0, nphi); sxyz= [xx, yy, zz]; sxyz= transpose(sxyz, [3, 1, 2]); sxyz += origin; xx= yy= zz= []; scolor= [0.5, 1.0, 0.0]; nquad= (nth-1)*(nphi-1); tstart= tfin= array(0.0, 3); list_tim= draw_tim= 0.0; back_rgb3d, [0.0,0.0,0.0]; if(!sho_scene) return [0, 0, 0.0, 0.0]; clear3d; /* draw all points in the lists */ timer, tstart; plglyphs3d, pxyz(,*), scal(*), thglyph(*), phiglyph(*), pcolor(,*); // plot a sphere using OpenGL Quad Strips for(i= 1; i < nphi; i++) { txyz= sxyz(,i:i+1,); norm= txyz/r0; plqstrips3d, numberof(txyz(1,1,)), txyz, scolor, norm; } timer,tfin; list_tim += (tfin-tstart)(3); center= [0.0, 0.0, 0.0]; up= [0.0,1.0,0.0]; dist= 3.0; theta= pi/18; view= [sin(theta), 0.0, cos(theta)]; eye= center+dist*view; lookat3d,eye,center,up; draw3d,1; n_point_3d= 0; n_poly_3d= nquad+ntri; n_tri_3d= 2*nquad+ntri; return [ntri, nquad, draw_tim, list_tim]; } func one_glyph(npts) { extern sho_scene; // create a sphere with radius r0 nth= 13; nphi= 25; phi= span(0.0, 2*pi, nphi); csph= cos(phi); snph= sin(phi); theta= span(0.0, pi, nth); csth= cos(theta); snth= sin(theta); r0= 0.125; origin= [0.0, 0.0, 0.0]; // set vertex order to get correct outer side for GL // by reversing on the phi index xx= r0*snth(-,)*csph(0:1:-1); yy= r0*snth(-,)*snph(0:1:-1); zz= r0*csth(-,)*array(1.0, nphi); sxyz= [xx, yy, zz]; sxyz= transpose(sxyz, [3, 1, 2]); sxyz += origin; xx= yy= zz= []; scolor= [0.5, 1.0, 0.0]; nquad= (nth-1)*(nphi-1); pxyz= [[2*r0, 0.0, 0.0]]; scal= [0.1]; thglyph= [0.0]; phiglyph= [0.0]; pcolor= [[0.0, 0.3, 1.0]]; back_rgb3d, [0.0,0.0,0.0]; if(!sho_scene) return; clear3d; plglyphs3d, pxyz, scal, thglyph, phiglyph, pcolor; // plot a sphere using OpenGL Quad Strips for(i= 1; i < nphi; i++) { txyz= sxyz(,i:i+1,); norm= txyz/r0; plqstrips3d, numberof(txyz(1,1,)), txyz, scolor, norm; } center= [0.0, 0.0, 0.0]; up= [0.0,1.0,0.0]; dist= 3.0; theta= pi/18; view= [sin(theta), 0.0, cos(theta)]; eye= center+dist*view; lookat3d,eye,center,up; } func sho_iso2(ngrid) { clr_count; res= mak_iso2(ngrid); if(!is_void(res)) { write,"number of triangles is ",long(res(1)); if(res(1) != res(2)) { write,"number of triangles per strip is",res(1)/double(res(2)); } write,"time to extract iso-surface is ",res(3); write,"time to draw iso-surface is ",res(4); write,"time to build display list is ",res(5); } } func mak_iso2(ngrid) { extern n_poly_3d, n_tri_3d, n_strip_3d, n_pass; extern tris2; extern sho_scene; if(is_void(ngrid) || ngrid < 6) { nx= test3d_n(1); ny= test3d_n(2); nz= test3d_n(3); } else { nx= ny= nz= ngrid; } if(is_void(n_pass)) n_pass= 1; var= get_isoreg(nx,ny,nz); write, " test uses "+pr1((nx-1)*(ny-1)*(nz-1))+" cells"; numTri= nStrip= nVert= 0; iso_tim= list_tim= draw_tim= 0.0; tstart= tfin= array(0.0, 3); origin= [-1.0,-1.0,-1.0]; delta= [2.0/(nx-1.0), 2.0/(ny-1.0), 2.0/(nz-1.0)]; level= 1.0; colr= [0.0,1.0,0.2]; colr2= [0.6,0.5,0.0,0.3]; timer, tstart; for(np= 1; np <= n_pass; np++) tris= iso3cenreg(origin,delta,var,0.6*level,colr); for(np= 1; np <= n_pass; np++) tris2= iso3cenreg(origin,delta,var,level,colr2); timer,tfin; iso_tim += (tfin-tstart)(3); if(!sho_scene) return [1.0, 1.0, 0.0, 0.0, 0.0]; back_rgb3d, [0.5,0.5,0.9]; clear3d; for(np= 1; np <= n_pass; np++) { clear3d; timer, tstart; /* draw all opaque triangles in the lists */ if(tris) { res= pltrilists3d(tris); if(!is_void(res)) { numTri += res(1); nStrip += res(2); nVert += res(3); } } /* draw all the translucent triangles */ if(tris2) { tris3= CollapseTri(tris2); tris4= SortTri(tris3); res= pltrilists3d(tris4); if(!is_void(res)) { numTri += res(1); nStrip += res(2); nVert += res(3); } } timer, tfin; list_tim += (tfin-tstart)(3); timer, tstart; draw3d, 1; if(is_void(keepview)) { stdview3d; } else if(!keepview) { stdview3d; } timer, tfin; draw_tim= (tfin-tstart)(3); } n_tri_3d= numTri/n_pass; n_poly_3d= numTri/n_pass; return [numTri/n_pass, nStrip/n_pass, iso_tim/n_pass, draw_tim/n_pass, list_tim/n_pass]; } func sho_isoreg(ngrid) { clr_count; res= mak_isoreg(ngrid); if(!is_void(res)) { write,"number of triangles is ",long(res(1)); if(res(1) != res(2)) { write,"number of triangles per strip is",res(1)/double(res(2)); } write,"time to extract iso-surface is ",res(3); write,"time to draw iso-surface is ",res(4); write,"time to build display list is ",res(5); } } func mak_isoreg(ngrid) { extern n_poly_3d, n_tri_3d, n_strip_3d, n_pass; extern sho_scene; if(is_void(ngrid) || ngrid < 3) { nx= test3d_n(1); ny= test3d_n(2); nz= test3d_n(3); } else { nx= ny= nz= ngrid; } if(is_void(n_pass)) n_pass= 1; var= get_isoreg(nx,ny,nz); write, " test uses "+pr1((nx-1)*(ny-1)*(nz-1))+" cells"; numTri= nStrip= nVert= 0; iso_tim= list_tim= draw_tim= 0.0; tstart= tfin= array(0.0, 3); origin= [-1.0,-1.0,-1.0]; delta= [2.0/(nx-1.0), 2.0/(ny-1.0), 2.0/(nz-1.0)]; level= 1.0; colr= [0.0,1.0,0.2]; timer, tstart; for(np= 1; np <= n_pass; np++) tris= iso3cenreg(origin, delta,var,0.6*level,colr); timer,tfin; iso_tim += (tfin-tstart)(3); if(!sho_scene) return [1.0, 1.0, 0.0, 0.0, 0.0]; for(np= 1; np <= n_pass; np++) { clear3d; /* draw all tristrips in the lists */ timer, tstart; if(tris) { res= pltrilists3d(tris); } timer,tfin; list_tim += (tfin-tstart)(3); if(!is_void(res)) { numTri += res(1); nStrip += res(2); nVert += res(3); } timer, tstart; draw3d, 1; if(is_void(keepview)) { stdview3d; } else if(!keepview) { stdview3d; } timer, tfin; draw_tim= (tfin-tstart)(3); } n_tri_3d= numTri/n_pass; n_poly_3d= numTri/n_pass; return [numTri/n_pass, nStrip/n_pass, iso_tim/n_pass, draw_tim/n_pass, list_tim/n_pass]; } func sho_isozcenreg(ngrid) { clr_count; res= mak_isozcenreg(ngrid); if(!is_void(res)) { write,"number of triangles is ",long(res(1)); if(res(1) != res(2)) { write,"number of triangles per strip is",res(1)/double(res(2)); } write,"time to extract iso-surface is ",res(3); write,"time to draw iso-surface is ",res(4); write,"time to build display list is ",res(5); } } func mak_isozcenreg(ngrid) { extern n_poly_3d, n_tri_3d, n_strip_3d, n_pass; extern sho_scene; if(is_void(ngrid) || ngrid < 3) { nx= test3d_n(1); ny= test3d_n(2); nz= test3d_n(3); } else { nx= ny= nz= ngrid; } if(is_void(n_pass)) n_pass= 1; var= get_isoreg(nx,ny,nz); write, " test uses "+pr1((nx-1)*(ny-1)*(nz-1))+" cells"; numTri= nStrip= nVert= 0; iso_tim= list_tim= draw_tim= 0.0; tstart= tfin= array(0.0, 3); origin= [-1.0,-1.0,-1.0]; delta= [2.0/(nx-1.0), 2.0/(ny-1.0), 2.0/(nz-1.0)]; level= 1.0; colr= [0.0,1.0,0.2]; timer, tstart; for(np= 1; np <= n_pass; np++) tris= iso3zcenreg(origin,delta, var,0.6*level,colr); timer,tfin; iso_tim += (tfin-tstart)(3); if(!sho_scene) return [1.0, 1.0, 0.0, 0.0, 0.0]; for(np= 1; np <= n_pass; np++) { clear3d; /* draw all tristrips in the lists */ timer, tstart; if(tris) { res= pltrilists3d(tris); } timer,tfin; list_tim += (tfin-tstart)(3); if(!is_void(res)) { numTri += res(1); nStrip += res(2); nVert += res(3); } timer, tstart; draw3d, 1; if(is_void(keepview)) { stdview3d; } else if(!keepview) { stdview3d; } timer, tfin; draw_tim= (tfin-tstart)(3); } n_tri_3d= numTri/n_pass; n_poly_3d= numTri/n_pass; return [numTri/n_pass, nStrip/n_pass, iso_tim/n_pass, draw_tim/n_pass, list_tim/n_pass]; } func sho_isozcenregngrd(ngrid) { clr_count; res= mak_isozcenregngrd(ngrid); if(!is_void(res)) { write,"number of triangles is ",long(res(1)); if(res(1) != res(2)) { write,"number of triangles per strip is",res(1)/double(res(2)); } write,"time to extract iso-surface is ",res(3); write,"time to draw iso-surface is ",res(4); write,"time to build display list is ",res(5); } } func mak_isozcenregngrd(ngrid) { extern n_poly_3d, n_tri_3d, n_strip_3d, n_pass; extern sho_scene; if(is_void(ngrid) || ngrid < 3) { nx= test3d_n(1); ny= test3d_n(2); nz= test3d_n(3); } else { nx= ny= nz= ngrid; } if(is_void(n_pass)) n_pass= 1; var= get_isoreg(nx,ny,nz); write, " test uses "+pr1((nx-1)*(ny-1)*(nz-1))+" cells"; numTri= nStrip= nVert= 0; iso_tim= list_tim= draw_tim= 0.0; tstart= tfin= array(0.0, 3); origin= [-1.0,-1.0,-1.0]; delta= [2.0/(nx-1.0), 2.0/(ny-1.0), 2.0/(nz-1.0)]; level= 1.0; colr= [0.0,1.0,0.2]; timer, tstart; for(np= 1; np <= n_pass; np++) tris= iso3zcenregngrd(origin,delta, var,0.6*level,colr); timer,tfin; iso_tim += (tfin-tstart)(3); if(!sho_scene) return [1.0, 1.0, 0.0, 0.0, 0.0]; for(np= 1; np <= n_pass; np++) { clear3d; /* draw all tristrips in the lists */ timer, tstart; if(tris) { res= pltrilists3d(tris); } timer,tfin; list_tim += (tfin-tstart)(3); if(!is_void(res)) { numTri += res(1); nStrip += res(2); nVert += res(3); } timer, tstart; draw3d, 1; if(is_void(keepview)) { stdview3d; } else if(!keepview) { stdview3d; } timer, tfin; draw_tim= (tfin-tstart)(3); } n_tri_3d= numTri/n_pass; n_poly_3d= numTri/n_pass; return [numTri/n_pass, nStrip/n_pass, iso_tim/n_pass, draw_tim/n_pass, list_tim/n_pass]; } func sho_isoregndx(ngrid) { clr_count; res= mak_isoregndx(ngrid); if(!is_void(res)) { write,"number of triangles is ",long(res(1)); if(res(1) != res(2)) { write,"number of triangles per strip is",res(1)/double(res(2)); } write,"time to extract iso-surface is ",res(3); write,"time to draw iso-surface is ",res(4); write,"time to build display list is ",res(5); } } func mak_isoregndx(ngrid) { extern n_poly_3d, n_tri_3d, n_strip_3d, n_pass; extern sho_scene; if(is_void(ngrid) || ngrid < 3) { nx= test3d_n(1); ny= test3d_n(2); nz= test3d_n(3); } else { nx= ny= nz= ngrid; } if(is_void(n_pass)) n_pass= 1; var= get_isoreg(nx,ny,nz); write, " test uses "+pr1((nx-1)*(ny-1)*(nz-1))+" cells"; numTri= nStrip= nVert= 0; iso_tim= list_tim= draw_tim= 0.0; tstart= tfin= array(0.0, 3); origin= [-1.0,-1.0,-1.0]; delta= [2.0/(nx-1.0), 2.0/(ny-1.0), 2.0/(nz-1.0)]; level= 1.0; colr= [0.0,1.0,0.2]; timer, tstart; for(np= 1; np <= n_pass; np++) tris= iso3cenregndx(origin, delta,var,0.6*level,colr); timer,tfin; iso_tim += (tfin-tstart)(3); if(!sho_scene) return [1.0, 1.0, 0.0, 0.0, 0.0]; for(np= 1; np <= n_pass; np++) { clear3d; /* draw all tristrips in the lists */ timer, tstart; if(tris) { res= pltrilists3d(tris); } timer,tfin; list_tim += (tfin-tstart)(3); if(!is_void(res)) { numTri += res(1); nStrip += res(2); nVert += res(3); } timer, tstart; draw3d, 1; if(is_void(keepview)) { stdview3d; } else if(!keepview) { stdview3d; } timer, tfin; draw_tim= (tfin-tstart)(3); } n_tri_3d= numTri/n_pass; n_poly_3d= numTri/n_pass; return [numTri/n_pass, nStrip/n_pass, iso_tim/n_pass, draw_tim/n_pass, list_tim/n_pass]; } func sho_isozcenregndx(ngrid) { clr_count; res= mak_isozcenregndx(ngrid); if(!is_void(res)) { write,"number of triangles is ",long(res(1)); if(res(1) != res(2)) { write,"number of triangles per strip is",res(1)/double(res(2)); } write,"time to extract iso-surface is ",res(3); write,"time to draw iso-surface is ",res(4); write,"time to build display list is ",res(5); } } func mak_isozcenregndx(ngrid) { extern n_poly_3d, n_tri_3d, n_strip_3d, n_pass; extern sho_scene; if(is_void(ngrid) || ngrid < 3) { nx= test3d_n(1); ny= test3d_n(2); nz= test3d_n(3); } else { nx= ny= nz= ngrid; } if(is_void(n_pass)) n_pass= 1; var= get_isoreg(nx,ny,nz); write, " test uses "+pr1((nx-1)*(ny-1)*(nz-1))+" cells"; numTri= nStrip= nVert= 0; iso_tim= list_tim= draw_tim= 0.0; tstart= tfin= array(0.0, 3); origin= [-1.0,-1.0,-1.0]; delta= [2.0/(nx-1.0), 2.0/(ny-1.0), 2.0/(nz-1.0)]; level= 1.0; colr= [0.0,1.0,0.2]; timer, tstart; for(np= 1; np <= n_pass; np++) tris= iso3zcenregndx(origin, delta,var,0.6*level,colr); timer,tfin; iso_tim += (tfin-tstart)(3); if(!sho_scene) return [1.0, 1.0, 0.0, 0.0, 0.0]; for(np= 1; np <= n_pass; np++) { clear3d; /* draw all tristrips in the lists */ timer, tstart; if(tris) { res= pltrilists3d(tris); } timer,tfin; list_tim += (tfin-tstart)(3); if(!is_void(res)) { numTri += res(1); nStrip += res(2); nVert += res(3); } timer, tstart; draw3d, 1; if(is_void(keepview)) { stdview3d; } else if(!keepview) { stdview3d; } timer, tfin; draw_tim= (tfin-tstart)(3); } n_tri_3d= numTri/n_pass; n_poly_3d= numTri/n_pass; return [numTri/n_pass, nStrip/n_pass, iso_tim/n_pass, draw_tim/n_pass, list_tim/n_pass]; } func sho_isocrv(ngrid) { clr_count; res= mak_isocrv(ngrid); if(!is_void(res)) { write,"number of triangles is ",long(res(1)); if(res(1) != res(2)) { write,"number of triangles per strip is",res(1)/double(res(2)); } write,"time to extract iso-surface is ",res(3); write,"time to draw iso-surface is ",res(4); write,"time to build display list is ",res(5); } } func mak_isocrv(ngrid) { extern n_poly_3d, n_tri_3d, n_strip_3d, n_pass; extern sho_scene; if(is_void(ngrid) || ngrid < 3) { nx= test3d_n(1); ny= test3d_n(2); nz= test3d_n(3); } else { nx= ny= nz= ngrid; } if(is_void(n_pass)) n_pass= 1; xyz= get_crvgrid(nx,ny,nz); var= get_isocrv(xyz); write, " test uses "+pr1((nx-1)*(ny-1)*(nz-1))+" cells"; numTri= nStrip= nVert= 0; iso_tim= list_tim= draw_tim= 0.0; tstart= tfin= array(0.0, 3); origin= [-1.0,-1.0,-1.0]; delta= [2.0/(nx-1.0), 2.0/(ny-1.0), 2.0/(nz-1.0)]; level= 1.0; colr= [0.0,1.0,0.2]; timer, tstart; for(np= 1; np <= n_pass; np++) tris= iso3cencrv(xyz,var,0.6*level,colr); timer,tfin; iso_tim += (tfin-tstart)(3); if(!sho_scene) return [1.0, 1.0, 0.0, 0.0, 0.0]; for(np= 1; np <= n_pass; np++) { clear3d; /* draw all tristrips in the lists */ timer, tstart; if(tris) { res= pltrilists3d(tris); } timer,tfin; list_tim += (tfin-tstart)(3); if(!is_void(res)) { numTri += res(1); nStrip += res(2); nVert += res(3); } timer, tstart; draw3d, 1; if(is_void(keepview)) { stdview3d; } else if(!keepview) { stdview3d; } timer, tfin; draw_tim= (tfin-tstart)(3); } n_tri_3d= numTri/n_pass; n_poly_3d= numTri/n_pass; return [numTri/n_pass, nStrip/n_pass, iso_tim/n_pass, draw_tim/n_pass, list_tim/n_pass]; } func sho_isozcencrv(ngrid) { clr_count; res= mak_isozcencrv(ngrid); if(!is_void(res)) { write,"number of triangles is ",long(res(1)); if(res(1) != res(2)) { write,"number of triangles per strip is",res(1)/double(res(2)); } write,"time to extract iso-surface is ",res(3); write,"time to draw iso-surface is ",res(4); write,"time to build display list is ",res(5); } } func mak_isozcencrv(ngrid) { extern n_poly_3d, n_tri_3d, n_strip_3d, n_pass; extern sho_scene; if(is_void(ngrid) || ngrid < 3) { nx= test3d_n(1); ny= test3d_n(2); nz= test3d_n(3); } else { nx= ny= nz= ngrid; } if(is_void(n_pass)) n_pass= 1; xyz= get_crvgrid(nx,ny,nz); var= get_isocrv(xyz); var= var(zcen,zcen,zcen); write, " test uses "+pr1((nx-1)*(ny-1)*(nz-1))+" cells"; numTri= nStrip= nVert= 0; iso_tim= list_tim= draw_tim= 0.0; tstart= tfin= array(0.0, 3); origin= [-1.0,-1.0,-1.0]; delta= [2.0/(nx-1.0), 2.0/(ny-1.0), 2.0/(nz-1.0)]; level= 1.0; colr= [0.0,1.0,0.2]; timer, tstart; for(np= 1; np <= n_pass; np++) tris= iso3zcencrv(xyz,var,0.6*level,colr); timer,tfin; iso_tim += (tfin-tstart)(3); if(!sho_scene) return [1.0, 1.0, 0.0, 0.0, 0.0]; for(np= 1; np <= n_pass; np++) { clear3d; /* draw all tristrips in the lists */ timer, tstart; if(tris) { res= pltrilists3d(tris); } timer,tfin; list_tim += (tfin-tstart)(3); if(!is_void(res)) { numTri += res(1); nStrip += res(2); nVert += res(3); } timer, tstart; draw3d, 1; if(is_void(keepview)) { stdview3d; } else if(!keepview) { stdview3d; } timer, tfin; draw_tim= (tfin-tstart)(3); } n_tri_3d= numTri/n_pass; n_poly_3d= numTri/n_pass; return [numTri/n_pass, nStrip/n_pass, iso_tim/n_pass, draw_tim/n_pass, list_tim/n_pass]; } func sho_isocrvndx(ngrid) { clr_count; res= mak_isocrvndx(ngrid); if(!is_void(res)) { write,"number of triangles is ",long(res(1)); if(res(1) != res(2)) { write,"number of triangles per strip is",res(1)/double(res(2)); } write,"time to extract iso-surface is ",res(3); write,"time to draw iso-surface is ",res(4); write,"time to build display list is ",res(5); } } func mak_isocrvndx(ngrid) { extern n_poly_3d, n_tri_3d, n_strip_3d, n_pass; extern sho_scene; if(is_void(ngrid) || ngrid < 3) { nx= test3d_n(1); ny= test3d_n(2); nz= test3d_n(3); } else { nx= ny= nz= ngrid; } if(is_void(n_pass)) n_pass= 1; xyz= get_crvgrid(nx,ny,nz); var= get_isocrv(xyz); write, " test uses "+pr1((nx-1)*(ny-1)*(nz-1))+" cells"; numTri= nStrip= nVert= 0; iso_tim= list_tim= draw_tim= 0.0; tstart= tfin= array(0.0, 3); origin= [-1.0,-1.0,-1.0]; delta= [2.0/(nx-1.0), 2.0/(ny-1.0), 2.0/(nz-1.0)]; level= 1.0; colr= [0.0,1.0,0.2]; timer, tstart; for(np= 1; np <= n_pass; np++) tris= iso3cencrvndx(xyz,var,0.6*level,colr); timer,tfin; iso_tim += (tfin-tstart)(3); if(!sho_scene) return [1.0, 1.0, 0.0, 0.0, 0.0]; for(np= 1; np <= n_pass; np++) { clear3d; /* draw all tristrips in the lists */ timer, tstart; if(tris) { res= pltrilists3d(tris); } timer,tfin; list_tim += (tfin-tstart)(3); if(!is_void(res)) { numTri += res(1); nStrip += res(2); nVert += res(3); } timer, tstart; draw3d, 1; if(is_void(keepview)) { stdview3d; } else if(!keepview) { stdview3d; } timer, tfin; draw_tim= (tfin-tstart)(3); } n_tri_3d= numTri/n_pass; n_poly_3d= numTri/n_pass; return [numTri/n_pass, nStrip/n_pass, iso_tim/n_pass, draw_tim/n_pass, list_tim/n_pass]; } func sho_isozcencrvndx(ngrid) { clr_count; res= mak_isozcencrvndx(ngrid); if(!is_void(res)) { write,"number of triangles is ",long(res(1)); if(res(1) != res(2)) { write,"number of triangles per strip is",res(1)/double(res(2)); } write,"time to extract iso-surface is ",res(3); write,"time to draw iso-surface is ",res(4); write,"time to build display list is ",res(5); } } func mak_isozcencrvndx(ngrid) { extern n_poly_3d, n_tri_3d, n_strip_3d, n_pass; extern sho_scene; if(is_void(ngrid) || ngrid < 3) { nx= test3d_n(1); ny= test3d_n(2); nz= test3d_n(3); } else { nx= ny= nz= ngrid; } if(is_void(n_pass)) n_pass= 1; xyz= get_crvgrid(nx,ny,nz); var= get_isocrv(xyz); var= var(zcen,zcen,zcen); write, " test uses "+pr1((nx-1)*(ny-1)*(nz-1))+" cells"; numTri= nStrip= nVert= 0; iso_tim= list_tim= draw_tim= 0.0; tstart= tfin= array(0.0, 3); origin= [-1.0,-1.0,-1.0]; delta= [2.0/(nx-1.0), 2.0/(ny-1.0), 2.0/(nz-1.0)]; level= 1.0; colr= [0.0,1.0,0.2]; timer, tstart; for(np= 1; np <= n_pass; np++) tris= iso3zcencrvndx(xyz,var,0.6*level,colr); timer,tfin; iso_tim += (tfin-tstart)(3); if(!sho_scene) return [1.0, 1.0, 0.0, 0.0, 0.0]; for(np= 1; np <= n_pass; np++) { clear3d; /* draw all tristrips in the lists */ timer, tstart; if(tris) { res= pltrilists3d(tris); } timer,tfin; list_tim += (tfin-tstart)(3); if(!is_void(res)) { numTri += res(1); nStrip += res(2); nVert += res(3); } timer, tstart; draw3d, 1; if(is_void(keepview)) { stdview3d; } else if(!keepview) { stdview3d; } timer, tfin; draw_tim= (tfin-tstart)(3); } n_tri_3d= numTri/n_pass; n_poly_3d= numTri/n_pass; return [numTri/n_pass, nStrip/n_pass, iso_tim/n_pass, draw_tim/n_pass, list_tim/n_pass]; } func sho_isohex(ngrid) { clr_count; res= mak_isohex(ngrid); if(!is_void(res)) { write,"number of triangles is ",long(res(1)); if(res(1) != res(2)) { write,"number of triangles per strip is",res(1)/double(res(2)); } write,"time to extract iso-surface is ",res(3); write,"time to draw iso-surface is ",res(4); write,"time to build display list is ",res(5); } } func mak_isohex(ngrid) { extern n_poly_3d, n_tri_3d, n_strip_3d, n_pass; extern sho_scene; if(is_void(ngrid) || ngrid < 3) { nx= test3d_n(1); ny= test3d_n(2); nz= test3d_n(3); } else { nx= ny= nz= ngrid; } if(is_void(n_pass)) n_pass= 1; xyz= array(0.0, 3, nx,ny,nz); xyz(1,..)= span(-1,1,nx); xyz(2,..)= span(-1,1,ny)(-,); xyz(3,..)= span(-1,1,nz)(-,-,); r= abs(xyz(1,..),xyz(2,..),xyz(3,..)); rp= r+!r; theta= acos(xyz(3,..)/rp); phi= atan(xyz(2,..),xyz(1,..)+(!r)); y32= sin(theta)^2*cos(theta)*cos(2*phi); f= r*(1.+y32); /* compute the gradient */ dfx= xyz(1,..)/rp*(1.0+2*xyz(3,..)*(xyz(3,..)^2+2*xyz(2,..)^2)/rp^3); dfy= xyz(2,..)/rp*(1.0-2*xyz(3,..)*(xyz(3,..)^2+2*xyz(1,..)^2)/rp^3); dfz= xyz(3,..)/rp+(xyz(1,..)^2-xyz(2,..)^2)*(xyz(1,..)^2+xyz(2,..)^2-xyz(3,..)^2)/rp^4; grad= xyz; grad(1,..)= dfx; grad(2,..)= dfy; grad(3,..)= dfz; r= theta= phi= dfx= dfy= dfz= []; /* Convert from 3D to 1D coord etc. arrays */ xyz= xyz(,*); grad= grad(,*); f= f(*); /* The iso-surface function wants the grid to be specified by indices into point, gradient, and variable arrays. All zones are made up of the same offsets from the lowest numbered corner of the zone. */ nzone= (nx-1)*(ny-1)*(nz-1); hexndx= array(0, 8, nzone); offsets= [0, 1, nx+1, nx, nx*ny, nx*ny+1, nx*ny+nx+1, nx*ny+nx]; for(k= 1; k < nz; k++) { for(j= 1; j < ny; j++) { for(i= 1; i < nx; i++) { idzn= 1+(i-1)+(nx-1)*(j-1)+(nx-1)*(ny-1)*(k-1); idpt= 1+(i-1)+nx*(j-1)+nx*ny*(k-1); hexndx(,idzn)= idpt+offsets; } } } write, " test uses "+pr1(nzone)+" cells"; numTri= nStrip= nVert= 0; iso_tim= list_tim= draw_tim= 0.0; tstart= tfin= array(0.0, 3); level= 1.0; colr= [0.0,1.0,0.2]; timer, tstart; for(np= 1; np <= n_pass; np++) tris= iso3hex(xyz,grad,hexndx, f,0.6*level,colr); timer,tfin; iso_tim += (tfin-tstart)(3); if(!sho_scene) return [1.0, 1.0, 0.0, 0.0, 0.0]; for(np= 1; np <= n_pass; np++) { clear3d; /* draw all tristrips in the lists */ timer, tstart; if(tris) { res= pltrilists3d(tris); } timer,tfin; list_tim += (tfin-tstart)(3); if(!is_void(res)) { numTri += res(1); nStrip += res(2); nVert += res(3); } timer, tstart; draw3d, 1; if(is_void(keepview)) { stdview3d; } else if(!keepview) { stdview3d; } timer, tfin; draw_tim= (tfin-tstart)(3); } n_tri_3d= numTri/n_pass; n_poly_3d= numTri/n_pass; return [numTri/n_pass, nStrip/n_pass, iso_tim/n_pass, draw_tim/n_pass, list_tim/n_pass]; } func draw_polys(polys, color) { nv= *(polys.nVerts); xyz= *(polys.xyzverts); norm= *(polys.normals); plpoly3d, nv, xyz, color, norm; } func sho_isotree(ngrid,cpervrt=) { clr_count; res= do_isotree(ngrid,cpervrt=cpervrt); if(!is_void(res)) { write,"number of triangles is ",long(res(1)); if(res(1) != res(2)) { write,"number of triangles per strip is",res(1)/double(res(2)); } write,"time to build octtree is ",res(3); write,"time to extract iso-surface is ",res(4); write,"time to draw iso-surface is ",res(5); write,"time to build display list is ",res(6); } } func do_isotree(ngrid,cpervrt=) { extern tree, n_poly_3d, n_tri_3d, n_strip_3d, n_pass; extern sho_scene; if(is_void(ngrid) || ngrid < 6) { nx= test3d_n(1); ny= test3d_n(2); nz= test3d_n(3); } else { nx= ny= nz= ngrid; } if(is_void(cpervrt)) cpervrt= 0; if(is_void(n_pass)) n_pass= 1; var= get_isoreg(nx,ny,nz); if(cpervrt) { var2= get_var2reg(nx,ny,nz); vmax= max(var2); vmin= min(var2); } write, " test uses "+pr1((nx-1)*(ny-1)*(nz-1))+" cells"; numTri= nStrip= nVert= 0; /* NOTE: the input array is assumed to include a layer of guard cells on all sides. This means that the volume being contoured is a bit less than -1 to 1. */ origin= [-1.0,-1.0,-1.0]; delta= [2.0/(nx-1.0), 2.0/(ny-1.0), 2.0/(nz-1.0)]; level= 0.6; colr= [0.0,1.0,0.2]; tstart= tfin= array(0.0, 3); timer, tstart; for(np= 1; np <= n_pass; np++) tree= mak_isotree(var); timer,tfin; tree_tim= (tfin-tstart)(3); timer, tstart; if(cpervrt) { for(np= 1; np <= n_pass; np++) tris= iso3_tree(origin,delta, var,level,colr,tree,var2=var2); } else { for(np= 1; np <= n_pass; np++) tris= iso3_tree(origin,delta, var,level,colr,tree); } timer,tfin; iso_tim= (tfin-tstart)(3); if(tris && cpervrt) { triptr= &tris; while(1) { if(!triptr) break; if(is_void(*triptr)) break; if(triptr->numTri) { /* one color per per vertex based on auxiliary variable */ ndx= 1 + (long) (gl_ncolr*(*(triptr->var2)-vmin)/(vmax-vmin)); ndx= min(ndx, gl_ncolr); nclr= numberof(ndx)/3; colr= array(float, 3, 3, nclr); colr(1,,)= gl_rr(ndx)/256.0; colr(2,,)= gl_gg(ndx)/256.0; colr(3,,)= gl_bb(ndx)/256.0; triptr->colors= &colr; } triptr= triptr->next; } ; } if(!sho_scene) return [1.0, 1.0, 0.0, 0.0, 0.0]; for(np= 1; np <= n_pass; np++) { clear3d; /* draw all tri arrays in the lists */ timer, tstart; if(tris) { res= pltrilists3d(tris); } timer,tfin; list_tim= (tfin-tstart)(3); if(!is_void(res)) { numTri += res(1); nStrip += res(2); nVert += res(3); } timer, tstart; draw3d, 1; if(is_void(keepview)) { stdview3d; } else if(!keepview) { stdview3d; } timer, tfin; draw_tim= (tfin-tstart)(3); } n_tri_3d= numTri/n_pass; n_poly_3d= numTri/n_pass; sizes= [nx, ny, nz]; return [numTri/n_pass, nStrip/n_pass, tree_tim/n_pass, iso_tim/n_pass, draw_tim/n_pass, list_tim/n_pass]; } func sho_isotreevarr(ngrid,cpervrt=) { clr_count; res= do_isotreevarr(ngrid,cpervrt=cpervrt); if(!is_void(res)) { write,"number of triangles is ",long(res(1)); if(res(1) != res(2)) { write,"number of triangles per strip is",res(1)/double(res(2)); } write,"time to build octtree is ",res(3); write,"time to extract iso-surface is ",res(4); write,"time to draw iso-surface is ",res(5); write,"time to build display list is ",res(6); } } func do_isotreevarr(ngrid,cpervrt=) { extern tree, n_poly_3d, n_tri_3d, n_strip_3d, n_pass; extern sho_scene; if(is_void(ngrid) || ngrid < 6) { nx= test3d_n(1); ny= test3d_n(2); nz= test3d_n(3); } else { nx= ny= nz= ngrid; } if(is_void(cpervrt)) cpervrt= 0; if(is_void(n_pass)) n_pass= 1; var= get_isoreg(nx,ny,nz); if(cpervrt) { var2= get_var2reg(nx,ny,nz); vmax= max(var2); vmin= min(var2); } write, " test uses "+pr1((nx-1)*(ny-1)*(nz-1))+" cells"; numTri= nStrip= nVert= 0; /* NOTE: the input array is assumed to include a layer of guard cells on all sides. This means that the volume being contoured is a bit less than -1 to 1. */ origin= [-1.0,-1.0,-1.0]; delta= [2.0/(nx-1.0), 2.0/(ny-1.0), 2.0/(nz-1.0)]; level= 0.6; colr= [0.0,1.0,0.2]; tstart= tfin= array(0.0, 3); timer, tstart; for(np= 1; np <= n_pass; np++) tree= mak_isotree(var); timer,tfin; tree_tim= (tfin-tstart)(3); timer, tstart; if(cpervrt) { for(np= 1; np <= n_pass; np++) tris= iso3_treevarr(origin,delta, var,level,colr,tree,var2=var2); } else { for(np= 1; np <= n_pass; np++) tris= iso3_treevarr(origin,delta, var,level,colr,tree); } timer,tfin; iso_tim= (tfin-tstart)(3); if(tris && cpervrt) { triptr= &tris; while(1) { if(!triptr) break; if(is_void(*triptr)) break; if(triptr->numTri) { /* one color per per vertex based on auxiliary variable */ ndx= 1 + (long) (gl_ncolr*(*(triptr->var2)-vmin)/(vmax-vmin)); ndx= min(ndx, gl_ncolr); nclr= numberof(ndx); colr= array(float, 3, nclr); colr(1,)= gl_rr(ndx(*))/256.0; colr(2,)= gl_gg(ndx(*))/256.0; colr(3,)= gl_bb(ndx(*))/256.0; triptr->colors= &colr; } triptr= triptr->next; } ; } if(!sho_scene) return [1.0, 1.0, 0.0, 0.0, 0.0]; for(np= 1; np <= n_pass; np++) { clear3d; /* draw all tri arrays in the lists */ timer, tstart; if(tris) { res= pltrilists3d(tris); } timer,tfin; list_tim= (tfin-tstart)(3); if(!is_void(res)) { numTri += res(1); nStrip += res(2); nVert += res(3); } timer, tstart; draw3d, 1; if(is_void(keepview)) { stdview3d; } else if(!keepview) { stdview3d; } timer, tfin; draw_tim= (tfin-tstart)(3); } n_tri_3d= numTri/n_pass; n_poly_3d= numTri/n_pass; sizes= [nx, ny, nz]; return [numTri/n_pass, nStrip/n_pass, tree_tim/n_pass, iso_tim/n_pass, draw_tim/n_pass, list_tim/n_pass]; } func sho_volviz3(ngrid) { extern sho_scene; if(is_void(ngrid)) ngrid= 6; if(is_void(ngrid) || ngrid < 6) { nx= test3d_n(1); ny= test3d_n(2); nz= test3d_n(3); } else { nx= ngrid; ny= ngrid; nz= ngrid; } var= get_isoreg(nx,ny,nz); maxvar= max(var); /* create functions that are large where f is near interesting values */ var1= 0.25*maxvar; var2= 0.5*maxvar; var3= 0.75*maxvar; dv= 0.07*maxvar; v1= exp(-((var-var1)/dv)^2); v2= exp(-((var-var2)/dv)^2); v3= exp(-((var-var3)/dv)^2); texout= array(char,4,nx,ny,nz); alpha= v1+v2+v3; alpha /= max(alpha); /* a guess at the alpha needed to make each surface just barely opaque */ bigalpha= 0.07/dv*14.0/nx*255; /* alpha is large where any of the three functions are large */ texout(4,..)= char(bigalpha*alpha); /* turn on specific colors where one of the funcions is large */ texout(1,..)= char(255*v1); texout(2,..)= char(255*v2); texout(3,..)= char(255*v3); f= []; write, " test uses "+pr1((nx-1)*(ny-1)*(nz-1))+" cells"; back_rgb3d, [0.0,0.0,0.0]; lookat3d, [0.0, 0.0, 2.0], [0.5, 0.5, 0.5], [0.0, 1.0, 0.0]; clear3d; iso_tim= list_tim= draw_tim= 0.0; tstart= tfin= array(0.0, 3); timer, tstart; delta= [1.0/(nx-1.0), 1.0/(ny-1.0), 1.0/(nz-1.0)]; if(!sho_scene) return [0.0, 0.0]; /* draw the volume visualization */ pltex2dvol,delta,texout; timer, tfin; list_tim= (tfin-tstart)(3); timer, tstart; draw3d, 1; draw3d_trigger; timer, tfin; draw_tim= (tfin-tstart)(3); write,"time to build display list is ",list_tim; write,"time to draw is ",draw_tim; return [list_tim, draw_tim]; } func sho_texiso(ngrid,frac=) { extern sho_scene; ASSERT, has_tex3d(), "3D textures are not available."; make_strip= 0; if(is_void(ngrid)) ngrid= 10; if(ngrid < 6) { nx= test3d_n(1); ny= test3d_n(2); nz= test3d_n(3); } else { nx= ngrid; ny= ngrid; nz= ngrid; } nslab= max(nx,ny,nz); xyz= array(0.0, 3, nx,ny,nz); xyz(1,..)= span(-1,1,nx); xyz(2,..)= span(-1,1,ny)(-,); xyz(3,..)= span(-1,1,nz)(-,-,); r= abs(xyz(1,..),xyz(2,..),xyz(3,..)); theta= acos(xyz(3,..)/(r+1.0e-10)); phi= atan(xyz(2,..),xyz(1,..)+(!r)); y32= 1.5*sqrt(3.0)*sin(theta)^2*cos(theta)*cos(2*phi); y21= 2.0*sin(theta)*cos(theta)*cos(phi); y22= sin(theta)^2; exr= exp(-3.0*r/max(r)); r1= 0.2*max(r); r2= 0.4*max(r) dr= 0.07*max(r); f32= (1.0+y32)*exp( -((r-r1)/dr)^2 ); f21= (1.0+y21)*exp( -((r-r2)/dr)^2 ); mxr= max(r); f22= 4.0*r/mxr*(1.0-r/mxr)*y22; f= f32+f21; df= 0.07*max(f); r= theta= phi= []; maxvar= max(f); texout= array(char,4,nx,ny,nz); alpha= f/max(f); /* a guess at the alpha needed to make each surface just barely opaque */ bigalpha= 0.07/df*14.0/nslab*255; /* alpha is large where any of the three functions are large */ texout(4,..)= char(bigalpha*alpha); /* turn on specific colors where one of the funcions is large */ texout(3,..)= char(255*f32/max(f32)); texout(1,..)= 0; texout(2,..)= char(255*f21/max(f21)); f= []; write, " test uses "+pr1((nx-1)*(ny-1)*(nz-1))+" cells"; len= [2.0,2.0,2.0]; delta= [2.0/(nx-1.0),2.0/(ny-1.0),2.0/(nz-1.0)]; origin= [-1.0,-1.0,-1.0]; /* location of the first real cell */ if(is_void(frac)) { level= 0.12*max(f22); } else { level= frac*max(f22); } back_rgb3d, [0.0,0.0,0.0]; lookat3d, [0.0, 0.0, 2.0], [0.0, 0.0, 0.0], [0.0, 1.0, 0.0]; clear3d; numTri= nStrip= nVert= 0; colr= [0.0, 0.0, 1.0]; iso_tim= list_tim= draw_tim= 0.0; tstart= tfin= array(0.0, 3); timer, tstart; tris= iso3cenreg(origin,delta,f22,level,colr); timer,tfin; iso_tim += (tfin-tstart)(3); tstart= tfin= array(0.0, 3); timer, tstart; if(!sho_scene) return [0.0, 0.0]; /* draw iso-surface using all triangles */ res= pltrilists3d(tris); if(!is_void(res)) { numTri += res(1); nStrip += res(2); nVert += res(3); } timer, tfin; list_tim += (tfin-tstart)(3); timer, tstart; /* draw the volume visualization */ pltex3dvol, nslab, len, texout, origin=origin; timer, tfin; list_tim += (tfin-tstart)(3); timer, tstart; draw3d, 1; timer, tfin; draw_tim= (tfin-tstart)(3); write,"time to build display list is ",list_tim; write,"time to draw is ",draw_tim; return [list_tim, draw_tim]; } func mak_ghost(f) { dimf= dimsof(f); nx= dimf(2); ny= dimf(3); nz= dimf(4); /* wrap ghost cells around the data */ fg= array(0.0, nx+2, ny+2, nz+2); fg(2:-1,2:-1,2:-1)= f; /* extrapolate from the 6 faces to get more accurate ghosts */ fg(1,2:-1,2:-1)= 2*f(1,..)-f(2,..); fg(0,2:-1,2:-1)= 2*f(0,..)-f(-1,..); fg(2:-1,1,2:-1)= 2*f(,1,)-f(,2,); fg(2:-1,0,2:-1)= 2*f(,0,)-f(,-1,); fg(2:-1,2:-1,1)= 2*f(..,1)-f(..,2); fg(2:-1,2:-1,0)= 2*f(..,0)-f(..,-1); /* extrapolate to the 12 edges */ fg(1,1,2:-1)= 2.0*f(1,1,)-f(2,2); fg(0,1,2:-1)= 2.0*f(0,1,)-f(-1,2,); fg(1,0,2:-1)= 2.0*f(1,0,)-f(2,-1,); fg(0,0,2:-1)= 2.0*f(0,0,)-f(-1,-1,); fg(1,2:-1,1)= 2.0*f(1,,1)-f(2,,2); fg(0,2:-1,1)= 2.0*f(0,,1)-f(-1,,2); fg(1,2:-1,0)= 2.0*f(1,,-1)-f(2,,-1); fg(0,2:-1,0)= 2.0*f(-1,,0)-f(-1,,-1); fg(2:-1,1,1)= 2.0*f(,1,1)-f(,2,2); fg(2:-1,0,1)= 2.0*f(,0,1)-f(,-1,2); fg(2:-1,1,0)= 2.0*f(,1,0)-f(,2,-1); fg(2:-1,0,0)= 2.0*f(,0,0)-f(,-1,-1); /* interpolate to the eight corners */ fg(0,0,0)= (fg(-1,0,0)+fg(0,-1,0)+fg(0,0,-1))/3.0; fg(1,0,0)= (fg(2,0,0)+fg(1,-1,0)+fg(1,0,-1))/3.0; fg(0,1,0)= (fg(-1,1,0)+fg(0,2,0)+fg(0,1,-1))/3.0; fg(1,1,0)= (fg(2,1,0)+fg(1,2,0)+fg(1,1,-1))/3.0; fg(0,0,1)= (fg(-1,0,1)+fg(0,-1,1)+fg(0,0,2))/3.0; fg(1,0,1)= (fg(2,0,1)+fg(1,-1,1)+fg(1,0,2))/3.0; fg(0,1,1)= (fg(-1,1,1)+fg(0,2,1)+fg(0,1,2))/3.0; fg(1,1,1)= (fg(2,1,1)+fg(1,2,1)+fg(1,1,2))/3.0; return fg; } func clr_count { extern n_tri_3d, n_poly_3d, n_strip_3d, n_point_3d, n_line_3d; n_tri_3d= n_poly_3d= n_strip_3d= n_point_3d= n_line_3d= 0; } func do_rot(num,theta,phi,dtheta,dphi,targ_tim=) { extern n_tri_3d, n_poly_3d, n_strip_3d, n_point_3d, n_line_3d, do_rotate; if(!do_rotate) return; if(is_void(num)) num= 50; if(is_void(theta)) theta= pi/2; if(is_void(phi)) phi= 0.0; if(is_void(dtheta)) dtheta= pi/10.0; if(is_void(dphi)) dphi= pi/18; eye= center= array(0.0, 3); get_center3d,center; get_eye3d,eye; up= [0.0,0.0,1.0]; dist= sqrt( sum( (eye-center)^2 ) ); elapsed= [0.,0.,0.]; timer, elapsed; elapsed0= elapsed; for(i= 1; i <= num; i++) { phi += dphi; thet= theta+dtheta*sin(2.3*phi); csth= cos(thet); snth= sin(thet); view= [snth*cos(phi), snth*sin(phi), csth]; eye= center+dist*view; lookat3d,eye,center,up; draw3d, 1; if(targ_tim) { timer, elapsed; if(elapsed(3)-elapsed0(3) > targ_tim) { num= i; break; } } } timer, elapsed; rate= num/(elapsed(3)-elapsed0(3)+1.0e-10); write,"display rate is "+pr1(rate)+" frames per second"; if(n_poly_3d) write,pr1(n_poly_3d*rate)+" polygons per second"; if(n_tri_3d) write,pr1(n_tri_3d*rate)+" equiv. triangles per second"; if(n_poly_3d) write,pr1(n_poly_3d)+" polygons drawn per frame"; if(n_tri_3d && n_strip_3d) write,"average number of triangles per strip is "+ pr1(n_tri_3d/double(n_strip_3d)); if(n_line_3d) write,pr1(n_line_3d*rate)+" line segments per second"; if(n_point_3d) write,pr1(n_point_3d*rate)+" points per second"; } func mak_slice(ngrid) { extern gl_rr, gl_gg, gl_bb, gl_ncolr, gl_ctab; extern n_poly_3d, n_tri_3d; extern sho_scene; if(is_void(ngrid) || ngrid < 6) { nx= ny= nz= 64; } else { nx= ngrid; ny= ngrid; nz= ngrid; } numTri= 0; nStrip= 0; nVert= 0; clr_count; palette3d,"stern.gp"; f= get_isoreg(nx,ny,nz); write, " test uses "+pr1((nx-1)*(ny-1)*(nz-1))+" cells"; origin= [-1.0,-1.0,-1.0]; delta= [2.0/(nx-1.0), 2.0/(ny-1.0), 2.0/(nz-1.0)]; level= 1.0; colr1= [0.0,1.0,0.2]; colrtyp= -3; /* three component scalar color */ level1= 0.5; tris_i= iso3cenreg(origin,delta,f,level1,colr1) if(tris_i) { num= SizeTriArrays3d(&tris_i); newtris= TriArrayGrp( numTri= 0, cellIDs= &array(0, num), xyzverts= &array(0.0, 3, 3, num), normals= &array(0.0, 3, 3, num), colors= &array(float, 3, num), var2= &nulvar, triEdg= &nulvar, triStart= &nulvar, nTris= &nulvar, next= &nulvar ); if(tris_i.var2) newtris.var2= &array(0.0, 3, num); CollapseTriArrays3d, colrtyp, &tris_i, &newtris; tris_i= newtris; newtris= []; } colr2= [1.0,0.2,0.0]; colrtyp= -3; /* three component scalar color */ level2= 1.0; tris_o= iso3cenreg(origin,delta,f,level2,colr2) if(tris_o) { num= SizeTriArrays3d(&tris_o); newtris= TriArrayGrp( numTri= 0, cellIDs= &array(0, num), xyzverts= &array(0.0, 3, 3, num), normals= &array(0.0, 3, 3, num), colors= &array(float, 3, num), var2= &nulvar, triEdg= &nulvar, triStart= &nulvar, nTris= &nulvar, next= &nulvar ); if(tris_o.var2) newtris.var2= &array(0.0, 3, num); CollapseTriArrays3d, colrtyp, &tris_o, &newtris; tris_o= newtris; newtris= []; } pxy= [0, 0, 1.0, 0]; pyz= [1.0, 0, 0, 0]; tnew_il= slice2only(pyz, tris_i); tnew_ir= slice2only(-pyz, tris_i); tnew_ir= slice2only(-pxy, tnew_ir); tnew_ol= slice2only(pyz, tris_o); norm= pyz(1:3); pnt= norm*pyz(4); /* NOTE: the input array is assumed to include a layer of guard cells on all sides if guard is non-zero. This means that the volume being contoured is a bit less than -1 to 1. */ tris= slice_tree([nx,ny,nz], origin, delta, pnt, norm, f, guard=1); vmin= 0.0; vmax= max(f); triptr= &tris; while(1) { if(is_void(*triptr)) break; if(!triptr) break; ntri= triptr->numTri; if(ntri) { /* one color per vertex based on var2 */ vx= *(triptr->var2); vx= min(vmax, max(vmin, vx)); ndx= 1 + (long) (gl_ncolr*(vx-vmin)/(vmax-vmin)); ndx= min(ndx, gl_ncolr); colr= array(float, 3, 3, numberof(ndx(1,))); colr(1,,)= gl_rr(ndx)/256.0; colr(2,,)= gl_gg(ndx)/256.0; colr(3,,)= gl_bb(ndx)/256.0; triptr->colors= &colr; } triptr= triptr->next; } ; if(!sho_scene) return; clear3d; if(tris) { res= pltrilists3d(tris,emit=1); if(!is_void(res)) { numTri += res(1); nStrip += res(2); nVert += res(3); } } if(tnew_il) { res= pltrilists3d(tnew_il); if(!is_void(res)) { numTri += res(1); nStrip += res(2); nVert += res(3); } } if(tnew_ir) { res= pltrilists3d(tnew_ir); if(!is_void(res)) { numTri += res(1); nStrip += res(2); nVert += res(3); } } if(tnew_ol) { res= pltrilists3d(tnew_ol); if(!is_void(res)) { numTri += res(1); nStrip += res(2); nVert += res(3); } } draw3d, 1; stdview3d; n_poly_3d= numTri; n_tri_3d=numTri; } func dslice(size, numrot, dphi) { if(is_void(size)) size= 40; mak_slice,size; theta= pi/3; phi= 0.0; if(is_void(dphi)) dphi= pi/18; if(is_void(numrot)) numrot= 50; do_rot,numrot,theta,phi,0.0,dphi; } func rsphere(num, dtheta) { mak_sphere; theta= pi/6; phi= 0.0; if(is_void(dphi)) dphi= pi/18; if(is_void(num)) num= 50; do_rot,num,theta,phi,0.0,dphi; } func makppm(name) { extern pix; nx= get_width3d(); ny= get_hite3d(); pix= array(char, 3, nx, ny); grabpix3d, nx, ny, pix; if(is_void(name)) { pnm_write, pix, "test.ppm"; } else { pnm_write, pix, name; } } func getput { extern pix; nx= get_width3d(); ny= get_hite3d(); pix= array(char, 3, nx, ny); grabpix3d, nx, ny, pix; clear3d; pix= pix(,,0:1:-1); putpix3d,pix; } func mak_sphere(nth, nphi, triangle=, alpha=, origin=, radius=, color=, kpfrm=) { extern n_poly_3d, n_tri_3d; extern do_smooth, one_color; extern sho_scene; if(is_void(alpha)) { alpha= -1.0; } else { alpha= min(1.0, max(0.0, alpha)); } if(is_void(do_smooth)) do_smooth= 1; if(is_void(triangle)) triangle= 0; if(is_void(one_color)) one_color= 0; if(is_void(color)) color= [0.5, 1.0, 0.0]; if(is_void(kpfrm)) kpfrm= 0; if(!kpfrm) clear3d; clr_count; if(is_void(nth)) nth= 37; if(is_void(nphi)) nphi= 73; // make phi decrease as index increases so zones will be "walked" // in the correct order for OpenGL phi= span(2*pi, 0.0, nphi); csph= cos(phi); snph= sin(phi); theta= span(0.0, pi, nth); csth= cos(theta); snth= sin(theta); if(is_void(radius)) r= 1.0; else r= radius; if(is_void(origin)) origin= [0.0, 0.0, 0.0]; if(one_color) { cbase= array(color, nphi-1); } else { if(alpha >= 0) { cbase= array([0.0, 0.0, 0.0, 1.0], nphi-1); cbase(4,)= alpha; } else { cbase= array([0.0, 0.0, 0.0], nphi-1); } cbase(2,1:nphi/2)= span(0, 1.0, nphi/2); cbase(2,nphi/2:nphi-1)= span(1.0, 0.0, nphi-1-nphi/2+1); cbase(1,nphi/2:nphi-1)= span(0, 1.0, nphi-1-nphi/2+1); cbase(3,1:nphi/2)= span(1.0, 0.0, nphi/2); } xx= r*snth(-,)*csph; yy= r*snth(-,)*snph; zz= r*csth(-,)*array(1.0, nphi); xyz= [xx, yy, zz]; xyz= transpose(xyz, [3, 1, 2]); xyz += origin; xx= yy= zz= []; if(!sho_scene) return; // plot a sphere using OpenGL Quad Strips for(i= 1; i < nphi; i++) { if(triangle) { pxyz= xyz(,i:i+1,)(,*)/r; if(do_smooth) { norm= pxyz; } else { norm= pxyz(,zcen)(,*); } color= array(cbase(,i), 2*nth-2); pltstrips3d, numberof(pxyz(1,)), pxyz, color, norm; } else { pxyz= xyz(,i:i+1,); if(do_smooth) { norm= pxyz; } else { norm= pxyz(,zcen,zcen)(,*); } color= array(cbase(,i), nth-1); plqstrips3d, numberof(pxyz(1,1,)), pxyz, color, norm; } } if(!kpfrm) stdview3d; draw3d,1; if(triangle) { n_poly_3d += 2*(nth-1)*(nphi-1); n_tri_3d += 2*(nth-1)*(nphi-1); } else { n_poly_3d += (nth-1)*(nphi-1); n_tri_3d += 2*(nth-1)*(nphi-1); } } func mak_colrsurf(nth, nphi, triangle=, kpfrm=) { extern n_poly_3d, n_tri_3d; extern sho_scene; // draw a sphere colored by the value of Y32 on the sphere. if(is_void(nth)) nth= 37; if(is_void(nphi)) nphi= 73; if(is_void(triangle)) triangle= 0; if(is_void(kpfrm)) kpfrm= 0; if(!kpfrm) clear3d; clr_count; // make phi decrease as index increases so zones will be "walked" // in the correct order for OpenGL phi= span(2*pi, 0.0, nphi); csph= cos(phi); snph= sin(phi); theta= span(0.0, pi, nth); csth= cos(theta); snth= sin(theta); // set vertex order to get correct outer side for GL // by reversing on the phi index xx= snth(-,)*csph(0:1:-1); yy= snth(-,)*snph(0:1:-1); zz= csth(-,)*array(1.0, nphi); xyz= [xx, yy, zz]; xyz= transpose(xyz, [3, 1, 2]); xx= yy= zz= []; /* The surface is a unit radius sphere, so the normal is the same as the ray from the origin to the point on the surface. */ norm= xyz; y32= snth^2*csth*cos(2*phi); var= 1.+y32; vmax= max(var); vmin= min(var); ndx= 1 + (long) (gl_ncolr*(var-vmin)/(vmax-vmin)); ndx= min(ndx, gl_ncolr); colr= array(float, 3, nth, nphi); colr(1,,)= gl_rr(ndx)/256.0; colr(2,,)= gl_gg(ndx)/256.0; colr(3,,)= gl_bb(ndx)/256.0; if(!sho_scene) return; plcolrsurf3d, xyz, norm, colr; if(!kpfrm) stdview3d; draw3d,1; if(triangle) { n_poly_3d += 2*(nth-1)*(nphi-1); n_tri_3d += 2*(nth-1)*(nphi-1); } else { n_poly_3d += (nth-1)*(nphi-1); n_tri_3d += 2*(nth-1)*(nphi-1); } } func mak_ellipsoid(nth, nphi, eps, origin=, radius=, color=, kpfrm=) { extern n_poly_3d, n_tri_3d; extern do_smooth, one_color; extern sho_scene; if(is_void(do_smooth)) do_smooth= 1; if(is_void(one_color)) one_color= 0; if(is_void(color)) color= [0.5, 1.0, 0.0]; if(is_void(kpfrm)) kpfrm= 0; if(!kpfrm) clear3d; clr_count; if(is_void(nth)) nth= 37; if(is_void(nphi)) nphi= 73; phi= span(0.0, 2*pi, nphi); csph= cos(phi); snph= sin(phi); theta= span(0.0, pi, nth); csth= cos(theta); snth= sin(theta); if(is_void(radius)) r= 1.0; else r= radius; if(is_void(eps)) eps= 1.0; else if(eps <= 0.0) eps= 1.0; if(is_void(origin)) origin= [0.0, 0.0, 0.0]; if(one_color) { cbase= array(color, nphi-1); } else { cbase= array([0.0, 0.0, 0.0], nphi-1); cbase(2,1:nphi/2)= span(0, 1.0, nphi/2); cbase(2,nphi/2:nphi-1)= span(1.0, 0.0, nphi-1-nphi/2+1); cbase(1,nphi/2:nphi-1)= span(0, 1.0, nphi-1-nphi/2+1); cbase(3,1:nphi/2)= span(1.0, 0.0, nphi/2); } // set vertex order to get correct outer side for GL // by reversing on the phi index xx= r*snth(-,)*csph(0:1:-1); yy= r*snth(-,)*snph(0:1:-1); zz= r*csth(-,)*array(1.0, nphi); xyz= [eps*xx, eps*yy, zz]; xyz= transpose(xyz, [3, 1, 2]); norm= [xx, yy, eps*zz]; norm= transpose(norm, [3, 1, 2]); ln= abs(norm(1,..), norm(2,..), norm(3,..)); norm /= (ln+!ln)(-:1:3,..); xyz += origin; xx= yy= zz= []; if(!sho_scene) return; // plot a sphere using OpenGL Quad Strips for(i= 1; i < nphi; i++) { pxyz= xyz(,i:i+1,)(,*)/r; nrm= norm(,i:i+1,)(,*)/r; color= array(cbase(,i), 2*nth-2); pltstrips3d, numberof(pxyz(1,)), pxyz, color, nrm; } if(!kpfrm) stdview3d; draw3d,1; n_poly_3d += 2*(nth-1)*(nphi-1); n_tri_3d += 2*(nth-1)*(nphi-1); } func rlines(nseg,npos) { extern n_line_3d; extern sho_scene; if(is_void(nseg)) nseg= 200; if(is_void(npos)) npos= 8; if(is_void(dtheta)) dtheta= pi/18; if(is_void(dphi)) dphi= 2.0*pi/3.0; clr_count; // generate a number of streamlines with // various initial positions zhi= 2.0; sp= span(0.0, zhi, npos); // set angular shift between points on a streamline phi_hi= 1.3*dphi; phi= span(0.0, phi_hi, nseg); xyz= array(0.0, 3, nseg, 3*npos); // compute all streamlines phi0= 0.0; r0= 1.0; x= r0*cos(phi+phi0)(,-:1:npos); y= r0*sin(phi+phi0)(,-:1:npos); z= (r0*sp)(-,)+r0*phi/phi_hi; txyz= [x, y, z]; xyz(,,1:npos)= transpose(txyz, [3,1,2]); phi1= dphi; r1= 1.5; ibase= npos; x= r1*cos(phi+phi1)(,-:1:npos); y= r1*sin(phi+phi1)(,-:1:npos); z= (r1*sp)(-,)+r1*phi/phi_hi; txyz= [x, y, z]; xyz(,,ibase+1:ibase+npos)= transpose(txyz, [3,1,2]); phi2= 2*dphi; r2= 2.0; ibase= 2*npos; x= r2*cos(phi+phi2)(,-:1:npos); y= r2*sin(phi+phi2)(,-:1:npos); z= (r2*sp)(-,)+r2*phi/phi_hi; txyz= [x, y, z]; xyz(,,ibase+1:ibase+npos)= transpose(txyz, [3,1,2]); if(!sho_scene) return [0.0, 0.0, 3]; /* put the lines into the display list */ color= [[0.4, 0.9, 0.0], [1.0, 0.0, 0.0], [0.0, 0.7, 0.7]]; clear3d; list_time= draw_time= 0.0; tstart= tfin= array(0.0, 3); timer, tstart; for(i= 1; i <= npos; i++) { pllines3d, xyz(..,i), color(,1); } for(i= npos+1; i <= 2*npos; i++) { pllines3d, xyz(..,i), color(,2); } for(i= 2*npos+1; i <= 3*npos; i++) { pllines3d, xyz(..,i), color(,3); } timer,tfin; list_time += tfin(3)-tstart(3); center= [0.0, 0.0, 0.0]; up= [0.0,1.0,0.0]; dist= 12.0; theta= 0.5*dtheta; view= [sin(theta), 0.0, cos(theta)]; eye= center+dist*view; lookat3d,eye,center,up; draw3d,1; n_line_3d= 3*npos*nseg; return [list_time, draw_time, 3*npos*nseg]; } func sho_drum(time_limit,targ_tim=) /* DOCUMENT sho_drum Display a drum head moving in 3D. The drumhead is initially stationary, but has a bump near one edge. Yorick is solving a 2D wave equation to compute the evolution of this bump. There is an optional argument to sho_drum: the time limit on the duration of the movie in seconds (default is 60 seconds). The size of the grid is set by the external variable drum_size. */ { require, "movie.i"; extern sho_scene; maxfr= 200; /* generate a num-by-num cell mesh on the [-1,1] square */ if(is_void(num)) num= 30; x= span(-1, 1, num+1)(,-:1:num+1); y= transpose(x); /* map the square mesh into a mesh on the unit circle this mesh has more nearly equal area cells than a polar coordinate circle */ scale= max(abs(y),abs(x))/(abs(y,x)+1.e-30); /* note that abs(y,x)=sqrt(x^2+y^2) */ x*= scale; y*= scale; f= f0= exp(-8.*abs(y+.67,x+.25)^2)*(1.-abs(y,x)^2); fdot= 0.0*f(2:-1,2:-1); af= abs(f(2:-1,2:-1)); lf= laplacian(f, y,x); /* set the "Courant" lmit */ xdz= x(dif,zcen); xzd= x(zcen,dif); ydz= y(dif,zcen); yzd= y(zcen,dif); dt= 0.375*sqrt(min(abs(xdz*yzd - xzd*ydz))); mcolor= [1.0,1.0,0.0]; lookat3d,[1.75,0.0,0.77],[0.0,0.0,0.0], [-0.401,-0.043,0.915]; clear3d; elapsed= [0.,0.,0.]; timer, elapsed; elapsed0= elapsed; /* roll the movie */ f= f0; for(i= 0; i < maxfr; i++) { /* display first */ xyz= [x, y, f]; xyz= transpose(xyz,2); /* compute surface normals at the vertices */ norm= get_normal3d(xyz); norm= norm(,pcen,pcen); if(sho_scene) { clear3d; plsurf3d,xyz,norm,mcolor; draw3d,1; if(targ_tim) { timer, elapsed; if(elapsed(3)-elapsed0(3) > targ_tim) { break; } } } /* then take a step forward in time */ lf= laplacian(f, y, x); af= abs(f(2:-1,2:-1)); fdot+= lf*dt; f(2:-1,2:-1)+= fdot*dt; } timer, elapsed; rate= i/(elapsed(3)-elapsed0(3)+1.0e-10); write,"display rate is "+pr1(rate)+" frames segments per second"; } func laplacian(f, y,x) { /* There are many ways to form the Laplacian as a finite difference. This one is nice in Yorick. */ /* Start with the two median vectors across each zone. */ fdz= f(dif,zcen); fzd= f(zcen,dif); xdz= x(dif,zcen); xzd= x(zcen,dif); ydz= y(dif,zcen); yzd= y(zcen,dif); /* Estimate the gradient at the center of each cell. */ area= xdz*yzd - xzd*ydz; gradfx= (fdz*yzd - fzd*ydz)/area; gradfy= (xdz*fzd - xzd*fdz)/area; /* Now consider the mesh formed by the center points of the original. */ x= x(zcen,zcen); y= y(zcen,zcen); xdz= x(dif,); xzd= x(,dif); ydz= y(dif,); yzd= y(,dif); area= xdz(,zcen)*yzd(zcen,) - xzd(zcen,)*ydz(,zcen); return ((xdz*gradfy(zcen,)-ydz*gradfx(zcen,))(,dif) + (yzd*gradfx(,zcen)-xzd*gradfy(,zcen))(dif,)) / area; } func get_isoreg(nx,ny,nz) { // in some special cases the variable may have // been pre-computed and saved in a file if(nx == 80 && ny == 80 && nz == 80) { var= get_y32(80); } else if(nx == 100 && ny == 100 && nz == 100) { var= get_y32(100); } else if(nx == 120 && ny == 120 && nz == 120) { var= get_y32(120); } else if(nx == 150 && ny == 150 && nz == 150) { var= get_y32(150); } else { xyz= array(0.0, 3, nx,ny,nz); xyz(1,..)= span(-1,1,nx); xyz(2,..)= span(-1,1,ny)(-,); xyz(3,..)= span(-1,1,nz)(-,-,); r= abs(xyz(1,..),xyz(2,..),xyz(3,..)); rp= r+!r; theta= acos(xyz(3,..)/rp); phi= atan(xyz(2,..),xyz(1,..)+(!r)); y32= sin(theta)^2*cos(theta)*cos(2*phi); var= r*(1.+y32); } return var; } func get_var2reg(nx,ny,nz) { xyz= array(0.0, 3, nx,ny,nz); xyz(1,..)= span(-1,1,nx); xyz(2,..)= span(-1,1,ny)(-,); xyz(3,..)= span(-1,1,nz)(-,-,); r= abs(xyz(1,..),xyz(2,..),xyz(3,..)); rp= r+!r; theta= acos(xyz(3,..)/rp); phi= atan(xyz(2,..),xyz(1,..)+(!r)); var2= (sin(theta)^2+cos(theta))*cos(4*phi); return var2; } func get_crvgrid(nx,ny,nz) { xyz= array(0.0, 3, nx,ny,nz); xyz(1,..)= span(-1,1,nx); xyz(2,..)= span(-1,1,ny)(-,); xyz(3,..)= span(-1,1,nz)(-,-,); return xyz; } func get_isocrv(xyz) { r= abs(xyz(1,..),xyz(2,..),xyz(3,..)); rp= r+!r; theta= acos(xyz(3,..)/rp); phi= atan(xyz(2,..),xyz(1,..)+(!r)); y32= sin(theta)^2*cos(theta)*cos(2*phi); var= r*(1.+y32); return var; } func mak_y32(nx, ny, nz) { if(is_void(nx) || nx < 2) nx= 40; if(is_void(ny) || ny < 2) ny= nx; if(is_void(nz) || nz < 2) nz= nx; xyz= array(0.0, 3, nx,ny,nz); xyz(1,..)= span(-1,1,nx); xyz(2,..)= span(-1,1,ny)(-,); xyz(3,..)= span(-1,1,nz)(-,-,); r= abs(xyz(1,..),xyz(2,..),xyz(3,..)); rp= r+!r; theta= acos(xyz(3,..)/rp); phi= atan(xyz(2,..),xyz(1,..)+(!r)); y32= sin(theta)^2*cos(theta)*cos(2*phi); f= r*(1.+y32); r= theta= phi= []; return f; } func get_y32(ngrid) { extern f80, f100, f120, f150; extern have_ylm; // calling this function is faster than calling mak_y32 // if the file already exists or sav_y32 has previously // been called if(have_ylm) { if(ngrid == 80) var= f80; else if(ngrid == 100) var= f100; else if(ngrid == 120) var= f120; else if(ngrid == 150) var= f150; else var= mak_y32(ngrid); } else if( open("y32vals.pdb", "rb", 1) ) { /* the file exists, so restore function values */ restore,openb("y32vals.pdb"); have_ylm= 1; if(ngrid == 80) var= f80; else if(ngrid == 100) var= f100; else if(ngrid == 120) var= f120; else if(ngrid == 150) var= f150; else var= mak_y32(ngrid); } else { var= mak_y32(ngrid); } return var; } func sav_y32 { extern f80, f100, f120, f150; f80= mak_y32(80); f100= mak_y32(100); f120= mak_y32(120); f150= mak_y32(150); have_ylm= 1; f= createb("y32vals.pdb"); save,f,f80,f100,f120,f150; close,f; } grab_32= 0; if(grab_32) get_y32; test3d_n= [20,20,20]; // create or activate the first OpenGL window win3d,0; thetalight= pi/4.0; light3d, diffuse=.7, specular=1, sdir=[cos(thetalight),.25,sin(thetalight)]; mak_sphere,73,73; stdview3d; // sho_texiso,16; /* show objects while rotating with the mouse if non-zero */ always_show_obj3d,0; cage_style3d,0; write,"mak_sphere,ntheta,nphi to make a new sphere"; write,"mak_slice to slice a pair of iso-surfaces and add a slicing plane"; write,"do_rot to rotate the existing scene"; if(is_void(bequiet)) { testgl; bequiet= 1; } yorick-gl-1.1+cvs20070922+dfsg.orig/ContourTets3D.c0000640000175000017500000024544010411132435021253 0ustar thibautthibaut/* * $Id: ContourTets3D.c,v 1.2 2006/03/25 03:12:29 dhmunro Exp $ * Iso-surface routines based on a 6 tetrahedron decomposition of * each hexahedral cell. */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #include "Contour3D.h" #include "pstdlib.h" #include #include #define TET_USE_POLYS #define DBG_ISO /* These iso-surface routines use a 6 tetrahedron decomposition of each hexahedral zone. The diagonal from the lowest numbered vertex in the zone to the diagonally opposite vertex is used to make the split. The remaining six vertices form six pairs that share an edge of the hexahedron. The six tethedrons are formed by combining those pairs with the two points on the diagonal. The two points on the main diagonal are vertices of every tetrahedron. There are 12 edges on the hexahedron. These will be referred to as "real" edges. They are numbered zero through 11. There are 7 other edges that occur in the tetrahedrons. Edge 12 is the long diagonal of the hexahedron and edges 13-18 are diagonals of the faces of the hexahedron. User data may be cell-centered or point-centered. It may have or not have ghost cells. Handling all cases leads to an explosion of routines. The underlying iso-surface routines work with point-centered values. Converting a full input array from zone-centered to point-centered can chew up a lot of memory. CONCLUSION: The iso-surface routine will work on a chunk in a (potentially) larger array. The iso-surface will be computed using point-centered data stored in a "chunk" sized array. The calling routine will provide a function pointer to map data from the original grid to the chunk, point-centering if needed. Gradients will be computed on the chunk. The chunk will always have a layer of ghost points. The "re-mapping" function will be able to handle ghost cells if the request "over-reaches" the input array. Octree based iso-surfacing routines build a tree based on the data range for a cell, then a 2-by-2-by-2 group of cells and so on until they have the data range for a whole chunk. Computing the octree requires point-centered variable values for all vertices in the chunk. Generating an iso-surface requires point-centered variable values and gradients at all corners of a zone cut by the iso-surface, but doesn't need them for other zones. Gradients (in particular) are expensive to compute, so it is faster to only compute the ones that are needed. CONCLUSION: The iso-surface routine will take as input storage for a point-centered variable (and storage for an auxiliary variable if requested) with one ghost point on all sides of the chunk. There is also chunk-sized input storage for co-ordinates and gradients. There is a chunk-sized input character array that contains bit flags for whether co-ordinates, variables, auxiliary variables, and gradients have been computed at each point. All these variables are computed as needed and tracked with bit flags. If creating an octree, only variable values will be computed. When generating an iso-surface, all of them may be computed. The lower level iso-surface routine is now the same for any ijk-indexible grid. Differences between point-centered and zone-centered, the presence or absence of ghost zones, and Cartesian versus curvi-linear grids are all handled by the "data gathering" routines supplied as arguments. There are multiple low-level iso-surface routines, but that is to provide different kinds of output triangles. One approach is an array of triangles, another is a list of triangle strips, another is an array of triangles described by indices into a vertex array, and a fourth is triangle strips described by index lists. There is a set of functions for each combination of grid type, variable centering, and for the case that a cell-centered variable is the same size as the grid (i.e. the variable size is one greater in each dimension than the size needed to store the variable to allow the same 1D indices to be used for the grid and the variable). An initialization function stores the information needed to map between a point in a chunk and the full array. The second function fetches a function value at a point in the chunk (may involve centering), the third fetches the coordinates of a point in a chunk, and the fourth computes the gradient at a point in a chunk. --------------------------------------------------- offsets[0:2] contains 0-based starting indices of this chunk in the larger array. Yorick must convert to C-style indices before calling the compiled routines. These offsets point to the first real cell of this chunk in the full array. We CAN'T use the first ghost cell because the larger array may not have ghost cells. If the input array is point-centered, the offset is to the first vertex of the first real cell. offsets[3:5] contains the number of CELLS in the larger array (including ghost cells if present) in the "x", "y", and "z" directions. This is used to compute STRIDES in the full array. Strides for coordinate arrays (in the case of curvi-linear coordinates) are obtained by adding one to these values. This choice was made because there is always an input variable array, but there isn't a coordinate array for Cartesian grids. sizes[0:2] contains the number of POINTS in each direction in this chunk of the array including the extra point on each side of this chunk. The extra point is a "ghost" from the viewpoint of the chunk, but it may be a real point/cell in the larger array. The chunk always includes ghost points, even if they "overlay" points outside the full array. A chunk array is NEVER cell-centered. deltas[0:2] contains the physical size of each cell. origin[0:2] is the co-ordinate of the first real point. This point is interior to the chunk volume and is located between the first and second cells of the input chunk. The var and var2 (optional) chunk arrays always have point-centered values. The grd array has point-centered gradients. The chunk always has room for ghost points on all sides. The values in var and var2 are copied from the full arrays if they are point-centered. They are computed from the surrounding cells in the full array if it iarrays zone-centered. The only time extrapolation is needed is at the boundaries of the full array when the full array doesn't have ghost cells. sizes(1:3) is the number of points in the chunk, including ghost points. The number of cells processed in one call is (sizes(1)-3)*(sizes(2)-1)*(sizes(3)-1). grd, done, and above are scratch arrays. These are point centered arrays. */ typedef struct Edge { int vert0, vert1; } Edge ; static int hex2tets[6][4] = { {0,6,5,1}, {0,6,1,2}, {0,6,2,3}, {0,6,3,7}, {0,6,7,4}, {0,6,4,5} }; static Edge edges[19] = {{0,1}, {1,2}, {2,3}, {3,0}, {4,5}, {5,6}, {6,7}, {7,4}, {0,4}, {1,5}, {2,6}, {3,7}, {0,6}, {0,5}, {1,6}, {0,2}, {3,6}, {0,7}, {4,6} }; static int tet_edges[6][6] = { {12,5,13,0,14,9}, {12,14,0,15,10,1}, {12,10,15,3,16,2}, {12,16,3,17,6,11}, {12,6,17,8,18,7}, {12,18,8,13,5,4} }; #ifdef OLD_ISO_STUFF /* There may be up to two triangles (i.e. 6 edges cut) per tet. -1 means "not there". The edge numbering is relative to the tet. To get edges relative to the hex, use the edges[] array. */ static int tet_cases[16][6]= { {-1,-1,-1,-1,-1,-1}, {0,3,2,-1,-1,-1}, {0,1,4,-1,-1,-1}, {3,2,1,3,1,4}, {1,2,5,-1,-1,-1}, {3,5,1,3,1,0}, {2,5,4,2,4,0}, {3,5,4,-1,-1,-1}, {5,3,4,-1,-1,-1}, {5,2,0,5,0,4}, {5,3,0,5,0,1}, {5,2,1,-1,-1,-1}, {2,3,4,2,4,1}, {0,4,1,-1,-1,-1}, {3,0,2,-1,-1,-1}, {-1,-1,-1,-1,-1,-1} } ; #endif /* The iso-surface may also be described using polygons. In all cases, the first and second vertices (indices 0 and 1) are those on the first face of the tet. The poly_last vector indicates the index of the first vertex on the last face. */ static int tet_polys[16][4]= { {-1,-1,-1,-1}, {2,0,3,-1}, {0,1,4,-1}, {2,1,4,3}, {1,2,5,-1}, {1,0,3,5}, {0,2,5,4}, {5,4,3,-1}, {5,3,4,-1}, {2,0,4,5}, {0,1,5,3}, {2,1,5,-1}, {1,2,3,4}, {1,0,4,-1}, {0,2,3,-1}, {-1,-1,-1,-1} } ; static int poly_first[16]= { -1, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, -1 } ; static int poly_last[16]= { -1, 1, 2, 2, -1, 1, 3, 1, 1, 1, 3, -1, 2, 1, 2, -1 } ; static int tri_count[16]= { 0, 1, 1, 2, 1, 2, 2, 1, 1, 2, 2, 1, 2, 1, 1, 0} ; /* The tets are ordered so that each one has a "first face" and a "last face". The last face of tet N is the same as ths first face of tet N+1. For each of the 16 cases, the edges on the first and last faces have been identified and stored in arrays first_edge[] and last_edge[]. These edges are numbered relative to the tet, so they must be mapped through tet_edges before they can be compared to the edges in the adjacent tet. */ static Edge first_edge[16]= { {-1,-1}, {2,0}, {0,1}, {2,1}, {1,2}, {1,0}, {0,2}, {-1,-1}, {-1,-1}, {2,0}, {0,1}, {2,1}, {1,2}, {1,0}, {0,2}, {-1,-1} } ; static Edge last_edge[16]= { {-1,-1}, {0,3}, {4,0}, {4,3}, {-1,-1}, {0,3}, {4,0}, {4,3}, {3,4}, {0,4}, {3,0}, {-1,-1}, {3,4}, {0,4}, {3,0}, {-1,-1} } ; static char face_code[16]= {0x03, 0x05, 0x09, 0x11, 0x22, 0x24, 0x28, 0x30, 0x12, 0x06, 0x0c, 0x18 } ; /* The worst case is two triangles per tet. Provide space for that, then collapse down to triangles with vertices only on the "real" edges */ typedef struct tri_data { int edge1, edge2, edge3; double x, y, z, nrmx, nrmy, nrmz; } tri_data ; /* The triangles will be assembled into polygons. After all tets have been processed, vertices on internal edges will be removed and the polygons will be turned back into triangle strips. The worst case polygon will have 12 triangles per zone. This can happen when the vertices at the end of the main diagonal are both low and all other points are high or vice versa. In the worst case there can't be more than 6 polys (most likely some polys have to patch together if there are 6 of them). */ typedef struct poly_data { int edges[36], num_edge, ndx_first, ndx_last; } poly_data ; typedef struct tstrip_data { long nvert, edges[12]; } tstrip_data ; typedef struct tstrip_array { long nStrip; tstrip_data the_tris[6]; } tstrip_array ; typedef struct zone_tris { long nStrip; long *lens; long *edges; } zone_tris ; zone_tris iso_cases[256]; int have_iso_cases= 0; #ifdef OLD_ISO_STUFF static tstrip_data the_tris[12]; static int tri_edges_found[12][3]; #endif static poly_data the_polys[6]; static tstrip_data the_strips[6]; static int num_poly; char vertflag[8]; #define XYZ_DONE 1 #define GRD_DONE 2 #define VAR_DONE 4 #define V2_DONE 8 #define ABOVE_DONE 16 #define VAR_ABOVE 32 typedef yPoint3D (*GET_XYZ)(long i, long j, long k); typedef double (*GET_VAR)(long i, long j, long k); typedef double (*GET_V2)(long i, long j, long k); static GET_XYZ f_xyz; static GET_VAR f_var; static GET_V2 f_v2; double *cntr_var, *cntr_v2; double cntr_dx, cntr_dy, cntr_dz, cntr_x0, cntr_y0, cntr_z0; yPoint3D *cntr_xyz, cntr_grad; long cntr_iOrigin, cntr_jOrigin, cntr_kOrigin, cntr_iSize, cntr_jSize, cntr_kSize; long cntr_xy_siz, cntr_x_siz, cntr_nzone, cntr_nexndx; extern int ycContourTet_array(long make_strip, long sizes[3], double level, double *var, double *var2, yPoint3D *xyz, yPoint3D *grd, unsigned char *flag, TriArrayGrp *triangles); extern int ycContourTet_array_ndx(long make_strip, long sizes[3], double level, double *var, double *var2, yPoint3D *xyz, yPoint3D *grd, unsigned char *flag, long *ndx, TriVertexGrp *triangles); extern int ycContourTetHex(double level, long ifirst, long nzone, yPoint3D *xyz, yPoint3D *grad, long hexndx[][8], double *var, double *var2, TriArrayGrp *triangles); extern int ycGradientChunk(long nx, long xy_siz, long i, long j, long k, long idx, yPoint3D *xyz, double *var, yPoint3D *grd, unsigned char *flag); extern int ycGetVarXyzCart(long nx, long xy_siz, long i, long j, long k, long idx, yPoint3D *xyz, double *var, unsigned char *flag, GET_XYZ f_xyz, GET_VAR f_var); extern int ycInitCartGrdPcen(long sizes[3], long offsets[6], double deltas[3], double origin[3], double *var, double *var2); extern int ycInitCartGrdZcen(long sizes[3], long offsets[6], double deltas[3], double origin[3], double *var, double *var2); extern int ycInitCartGrdPcenNdx(long sizes[3], long offsets[6], double deltas[3], double origin[3], double *var, double *var2); extern int ycInitCartGrdZcenNdx(long sizes[3], long offsets[6], double deltas[3], double origin[3], double *var, double *var2); extern int ycInitCrvGrdPcen(long sizes[3], long offsets[6], yPoint3D *xyz, double *var, double *var2); extern int ycInitCrvGrdZcen(long sizes[3], long offsets[6], yPoint3D *xyz, double *var, double *var2); extern int ycInitCrvGrdPcenNdx(long sizes[3], long offsets[6], yPoint3D *xyz, double *var, double *var2); extern int ycInitCrvGrdZcenNdx(long sizes[3], long offsets[6], yPoint3D *xyz, double *var, double *var2); extern int ycContourTet_OneZone(double level, long zon_ndx, int index, double s[8], double vars[8], yPoint3D pts[8], yPoint3D gradients[8], TriArrayGrp *triangles); extern double ycContourGrdPcenVar(long i, long j, long k); extern double ycContourGrdPcenV2(long i, long j, long k); extern yPoint3D ycContourCartXyz(long i, long j, long k); extern double ycContourCartZcenVar(long i, long j, long k); extern double ycContourCartZcenV2(long i, long j, long k); extern double ycContourCartGrdZcenVar(long i, long j, long k); extern double ycContourCartGrdZcenV2(long i, long j, long k); extern double ycContourPcenVar(long i, long j, long k); extern double ycContourPcenV2(long i, long j, long k); extern double ycContourPcenAllvar(long i, long j, long k, double *var); extern yPoint3D ycContourCrvGrdXyz(long i, long j, long k); extern double ycContourCrvGrdZcenVar(long i, long j, long k); extern double ycContourCrvGrdZcenV2(long i, long j, long k); extern double ycContourCrvGrdZcenAllvar(long i, long j, long k, double *var); extern int ycTetIso_zone(double level, double *var, tstrip_array *t_strips); extern int tetiso_zone(tstrip_data t_strips[6]); extern void patch_poly(long pnum, long index, long num, long itet); extern void patch_2polys(long ip1, long ip2); extern void assemble_strip(int ndx, int ipn, tstrip_data *t_strips); #ifdef _DEBUG #define ASSERT(cond, msg) if(!(cond)) YError(msg); #else #define ASSERT(cond, msg) #endif void patch_poly(long pnum, long index, long num, long itet) { long num_edg, nd_old, nd_new, ii; nd_old= the_polys[pnum].ndx_last; num_edg= the_polys[pnum].num_edge; /* Shift vertices of existing polygon up to make room to insert new ones. If appending, the for does nothing. */ for(ii= num_edg+num-1; ii > nd_old+num; ii--) { the_polys[pnum].edges[ii]= the_polys[pnum].edges[ii-num]; } nd_new= nd_old+1; the_polys[pnum].num_edge += num; /* the first edge of the new tri or quad is at the start, so 1 or 2 vertices need to be inserted into the existing poly between the vertices of its current final edge */ the_polys[pnum].edges[nd_new]= tet_edges[itet][ tet_polys[index][2] ]; if(num == 2) { the_polys[pnum].edges[nd_new+1]= tet_edges[itet][ tet_polys[index][3] ]; } switch(poly_last[index]) { case 1: /* the edge on the last face of the tet starts at tet edge 1 */ the_polys[pnum].ndx_last= nd_new-1; break; case 2: /* the edge on the last face of the tet starts at tet edge 2 */ the_polys[pnum].ndx_last= nd_new; break; case 3: /* the edge on the last face of the tet starts at tet edge 3 */ the_polys[pnum].ndx_last= nd_new+1; break; default: /* Impossible case? No, apparently not. */ /* ASSERT(0, "impossible case in patch_poly"); */ break; } } void patch_2polys(long ip1, long ip2) { long num_old, num_new, nd_new, ii, jj, nadd; #ifdef CHEK_POLYS long bad= 0; #endif /* This function should only be called when ip1 has a first and no last and ip2 has a last but no first. ACTUALLY, it appears that this is not true. There are cases where the test fails, but the resulting iso-surfaces appear to be fine. NO EXPLANATION at this time. */ #ifdef CHEK_POLYS if(the_polys[ip1].ndx_last >= 0) { bad |= 1; } if(the_polys[ip1].ndx_first != 0) { bad |= 2; } if(the_polys[ip2].ndx_last < 0) { bad |= 4; } if(the_polys[ip2].ndx_first == 0) { bad |= 8; } if(bad) { return; /* should never reach this line */ } #endif num_old= the_polys[ip1].num_edge; nd_new= the_polys[ip2].ndx_last; num_new= the_polys[ip2].num_edge; nadd= num_new-2; /* Shift vertices of existing polygon up to make room to insert new ones. */ for(ii= num_old-1; ii > 0; ii--) { the_polys[ip1].edges[ii+nadd]= the_polys[ip1].edges[ii]; } /* copy vertices from the second polygon */ for(ii= 1, jj= (nd_new+2)%num_new; ii < 1+nadd; ii++, jj= (jj+1)%num_new) { the_polys[ip1].edges[ii]= the_polys[ip2].edges[jj]; } the_polys[ip1].num_edge += nadd; the_polys[ip1].ndx_last= the_polys[ip1].ndx_first; /* now remove ip2 (WARNING - this involves a lot of data movement!!) */ for(ii= ip2; ii < num_poly; ii++) { the_polys[ii]= the_polys[ii+1]; } num_poly--; } int ycInitCartPcen(long sizes[3], long offsets[6], double deltas[3], double origin[3], double *var, double *var2) { /* This is the version for point-centered data on a Cartesian grid. The input arrays do NOT include any guard cells. Validate arguments here. */ if (!var || sizes[0] < 2 || sizes[1] < 2 || sizes[2] < 2) { return 0; } cntr_var= var; cntr_v2= var2; cntr_dx= deltas[0]; cntr_dy= deltas[1]; cntr_dz= deltas[2]; cntr_x0= origin[0]; cntr_y0= origin[1]; cntr_z0= origin[2]; /* on input, the offsets are 1-based, so convert to 0-based now */ cntr_iOrigin= offsets[0]-1; cntr_jOrigin= offsets[1]-1; cntr_kOrigin= offsets[2]-1; /* iSize and jSize are numbers of points in the full array. Leave them this way. */ cntr_iSize= offsets[3]; cntr_jSize= offsets[4]; cntr_kSize= offsets[5]; f_xyz= ycContourCartXyz; f_var= ycContourPcenVar; f_v2= ycContourPcenV2; return 1; } int ycInitCartGrdPcen(long sizes[3], long offsets[6], double deltas[3], double origin[3], double *var, double *var2) { /* This is the version for point-centered data on a Cartesian grid. The input arrays include guard cells on all sides. */ if (!var || sizes[0] < 4 || sizes[1] < 4 || sizes[2] < 4) { return 0; } cntr_var= var; cntr_v2= var2; cntr_dx= deltas[0]; cntr_dy= deltas[1]; cntr_dz= deltas[2]; cntr_x0= origin[0]; cntr_y0= origin[1]; cntr_z0= origin[2]; /* on input, the offsets are 1-based, so convert to 0-based now */ cntr_iOrigin= offsets[0]-1; cntr_jOrigin= offsets[1]-1; cntr_kOrigin= offsets[2]-1; /* iSize and jSize are numbers of cells including ghost cells in the full array. Leave them this way. */ cntr_iSize= offsets[3]; cntr_jSize= offsets[4]; cntr_kSize= offsets[5]; f_xyz= ycContourCartXyz; f_var= ycContourGrdPcenVar; f_v2= ycContourGrdPcenV2; return 1; } int ycInitCartZcen(long sizes[3], long offsets[6], double deltas[3], double origin[3], double *var, double *var2) { /* This is the version for zone-centered data on a Cartesian grid. The input arrays do not have any guard cells. */ if (!var || sizes[0] < 3 || sizes[1] < 3 || sizes[2] < 3) { return 0; } cntr_xyz= 0; /* this is not used for Cartesian grids */ cntr_var= var; cntr_v2= var2; cntr_dx= deltas[0]; cntr_dy= deltas[1]; cntr_dz= deltas[2]; cntr_x0= origin[0]; cntr_y0= origin[1]; cntr_z0= origin[2]; /* on input, the offsets are 1-based, so convert to 0-based now */ cntr_iOrigin= offsets[0]-1; cntr_jOrigin= offsets[1]-1; cntr_kOrigin= offsets[2]-1; /* iSize and jSize are numbers of points including ghost points in the full array. Leave them this way. */ cntr_iSize= offsets[3]; cntr_jSize= offsets[4]; cntr_kSize= offsets[5]; f_xyz= ycContourCartXyz; f_var= ycContourCartZcenVar; f_v2= ycContourCartZcenV2; return 1; } int ycInitCartGrdZcen(long sizes[3], long offsets[6], double deltas[3], double origin[3], double *var, double *var2) { /* This is the version for zone-centered data on a Cartesian grid. The input arrays include guard cells on all sides. */ if (!var || sizes[0] < 3 || sizes[1] < 3 || sizes[2] < 3) { return 0; } cntr_xyz= 0; /* this is not used for Cartesian grids */ cntr_var= var; cntr_v2= var2; cntr_dx= deltas[0]; cntr_dy= deltas[1]; cntr_dz= deltas[2]; cntr_x0= origin[0]; cntr_y0= origin[1]; cntr_z0= origin[2]; /* on input, the offsets are 1-based, so convert to 0-based now */ cntr_iOrigin= offsets[0]-1; cntr_jOrigin= offsets[1]-1; cntr_kOrigin= offsets[2]-1; /* iSize and jSize are numbers of points including ghost points in the full array. Leave them this way. */ cntr_iSize= offsets[3]; cntr_jSize= offsets[4]; cntr_kSize= offsets[5]; f_xyz= ycContourCartXyz; f_var= ycContourCartGrdZcenVar; f_v2= ycContourCartGrdZcenV2; return 1; } int ycInitCartGrdPcenNdx(long sizes[3], long offsets[6], double deltas[3], double origin[3], double *var, double *var2) { /* This is the version for point-centered data on a Cartesian grid. The input arrays include guard cells on all sides. The result is triangles given by indices into a point list. */ if (!var || sizes[0] < 4 || sizes[1] < 4 || sizes[2] < 4) { return 0; } cntr_xyz= 0; /* this is not used for Cartesian grids */ cntr_var= var; cntr_v2= var2; cntr_dx= deltas[0]; cntr_dy= deltas[1]; cntr_dz= deltas[2]; cntr_x0= origin[0]; cntr_y0= origin[1]; cntr_z0= origin[2]; /* on input, the offsets are 1-based, so convert to 0-based now */ cntr_iOrigin= offsets[0]-1; cntr_jOrigin= offsets[1]-1; cntr_kOrigin= offsets[2]-1; /* iSize and jSize are numbers of points including ghost points in the full array. Leave them this way. */ cntr_iSize= offsets[3]; cntr_jSize= offsets[4]; cntr_kSize= offsets[5]; f_xyz= ycContourCartXyz; f_var= ycContourGrdPcenVar; f_v2= ycContourGrdPcenV2; return 1; } int ycInitCartGrdZcenNdx(long sizes[3], long offsets[6], double deltas[3], double origin[3], double *var, double *var2) { /* This is the version for zone-centered data on a Cartesian grid. The input arrays include guard cells on all sides. The result is triangles given by indices into a point list. */ if (!var || sizes[0] < 3 || sizes[1] < 3 || sizes[2] < 3) { return 0; } cntr_var= var; cntr_v2= var2; cntr_dx= deltas[0]; cntr_dy= deltas[1]; cntr_dz= deltas[2]; cntr_x0= origin[0]; cntr_y0= origin[1]; cntr_z0= origin[2]; /* on input, the offsets are 1-based, so convert to 0-based now */ cntr_iOrigin= offsets[0]-1; cntr_jOrigin= offsets[1]-1; cntr_kOrigin= offsets[2]-1; /* iSize and jSize are numbers of points including ghost points in the full array. Leave them this way. */ cntr_iSize= offsets[3]; cntr_jSize= offsets[4]; cntr_kSize= offsets[5]; f_xyz= ycContourCartXyz; f_var= ycContourCartGrdZcenVar; f_v2= ycContourCartGrdZcenV2; return 1; } int ycInitCrvGrdPcen(long sizes[3], long offsets[6], yPoint3D *xyz, double *var, double *var2) { /* This is the version for point-centered data on a Curvilinear grid. The input arrays include guard cells on all sides. */ if (!var || sizes[0] < 4 || sizes[1] < 4 || sizes[2] < 4) { return 0; } cntr_xyz= xyz; cntr_var= var; cntr_v2= var2; cntr_dx= 0.0; cntr_dy= 0.0; cntr_dz= 0.0; cntr_x0= 0.0; cntr_y0= 0.0; cntr_z0= 0.0; /* on input, the offsets are 1-based, so convert to 0-based now */ cntr_iOrigin= offsets[0]-1; cntr_jOrigin= offsets[1]-1; cntr_kOrigin= offsets[2]-1; /* iSize and jSize are numbers of points including ghost points in the full array. Leave them this way. */ cntr_iSize= offsets[3]; cntr_jSize= offsets[4]; cntr_kSize= offsets[5]; f_xyz= ycContourCrvGrdXyz; f_var= ycContourGrdPcenVar; f_v2= ycContourGrdPcenV2; return 1; } int ycInitCrvGrdZcen(long sizes[3], long offsets[6], yPoint3D *xyz, double *var, double *var2) { /* This is the version for zone-centered data on a Curvilinear grid. The input arrays include guard cells on all sides. */ if (!var || sizes[0] < 3 || sizes[1] < 3 || sizes[2] < 3) { return 0; } cntr_xyz= xyz; cntr_var= var; cntr_v2= var2; cntr_dx= 0.0; cntr_dy= 0.0; cntr_dz= 0.0; cntr_x0= 0.0; cntr_y0= 0.0; cntr_z0= 0.0; /* on input, the offsets are 1-based, so convert to 0-based now */ cntr_iOrigin= offsets[0]-1; cntr_jOrigin= offsets[1]-1; cntr_kOrigin= offsets[2]-1; /* iSize and jSize are numbers of points including ghost points in the full array. Leave them this way. */ cntr_iSize= offsets[3]; cntr_jSize= offsets[4]; cntr_kSize= offsets[5]; f_xyz= ycContourCrvGrdXyz; f_var= ycContourCrvGrdZcenVar; f_v2= ycContourCrvGrdZcenV2; return 1; } int ycInitCrvGrdPcenNdx(long sizes[3], long offsets[6], yPoint3D *xyz, double *var, double *var2) { /* This is the version for point-centered data on a Curvilinear grid. The input arrays include guard cells on all sides. The result is triangles given by indices into a point list. */ if (!var || sizes[0] < 4 || sizes[1] < 4 || sizes[2] < 4) { return 0; } cntr_xyz= xyz; cntr_var= var; cntr_v2= var2; cntr_dx= 0.0; cntr_dy= 0.0; cntr_dz= 0.0; cntr_x0= 0.0; cntr_y0= 0.0; cntr_z0= 0.0; /* on input, the offsets are 1-based, so convert to 0-based now */ cntr_iOrigin= offsets[0]-1; cntr_jOrigin= offsets[1]-1; cntr_kOrigin= offsets[2]-1; /* iSize and jSize are numbers of points including ghost points in the full array. Leave them this way. */ cntr_iSize= offsets[3]; cntr_jSize= offsets[4]; cntr_kSize= offsets[5]; f_xyz= ycContourCrvGrdXyz; f_var= ycContourGrdPcenVar; f_v2= ycContourGrdPcenV2; return 1; } int ycInitCrvGrdZcenNdx(long sizes[3], long offsets[6], yPoint3D *xyz, double *var, double *var2) { /* This is the version for zone-centered data on a Curvilinear grid. The input arrays include guard cells on all sides. The result is triangles given by indices into a point list. */ if (!var || sizes[0] < 3 || sizes[1] < 3 || sizes[2] < 3) { return 0; } cntr_xyz= xyz; cntr_var= var; cntr_v2= var2; cntr_dx= 0.0; cntr_dy= 0.0; cntr_dz= 0.0; cntr_x0= 0.0; cntr_y0= 0.0; cntr_z0= 0.0; /* on input, the offsets are 1-based, so convert to 0-based now */ cntr_iOrigin= offsets[0]-1; cntr_jOrigin= offsets[1]-1; cntr_kOrigin= offsets[2]-1; /* iSize and jSize are numbers of points including ghost points in the full array. Leave them this way. */ cntr_iSize= offsets[3]; cntr_jSize= offsets[4]; cntr_kSize= offsets[5]; f_xyz= ycContourCrvGrdXyz; f_var= ycContourCrvGrdZcenVar; f_v2= ycContourCrvGrdZcenV2; return 1; } yPoint3D ycContourCartXyz(long i, long j, long k) { yPoint3D xyz_out; /* i,j,k are indices relative to the current chunk. Use the location of the corner of this chunk to get xyz. Same function for point centered and zone centered Cartesian grids. Works whether there are guard points or not*/ xyz_out.x= cntr_x0+i*cntr_dx; xyz_out.y= cntr_y0+j*cntr_dy; xyz_out.z= cntr_z0+k*cntr_dz; return xyz_out; } double ycContourPcenAllvar(long i, long j, long k, double *var) { long idxg, i0, j0, k0; /* NOTE: This function is for the case of point-centered variables without guard cell data. The iso-surface is set up to act as if guard cells are present. This means the iso-surface may generate indices outside the full array (e.g. a global index of -1). Force the indices back in range. */ /* i,j,k are indices relative to the current chunk. Convert into indices into the global array. Same function for Cartesian and Curvilinear grids. For the case of no guard points. For now, do not try to extrapolate outside of the data range. This will produce curvature at the boundaries, but is very easy to program. If the effect is visually unpleasing, the user should generate guard points. */ /* get indices relative to the full grid */ i0= i+cntr_iOrigin; j0= j+cntr_jOrigin; k0= k+cntr_kOrigin; if(i0 < 0 || j0 < 0 || k0 < 0 || i0 > cntr_iSize-1 || j0 > cntr_jSize-1 || k0 > cntr_kSize-1 ) { /* the point is outside the grid. */ if(i0 < 0) i0= 0; if(j0 < 0) j0= 0; if(k0 < 0) k0= 0; if(i0 > cntr_iSize-1) i0= cntr_iSize-1; if(j0 > cntr_iSize-1) j0= cntr_jSize-1; if(k0 > cntr_iSize-1) k0= cntr_jSize-1; idxg= i0+j0*cntr_iSize+k0*cntr_iSize*cntr_jSize; } else { /* normal case - the point is in the grid */ idxg= i0+j0*cntr_iSize+k0*cntr_iSize*cntr_jSize; } return var[idxg]; } double ycContourPcenVar(long i, long j, long k) { /* call with the contour variable */ return ycContourPcenAllvar(i, j, k, cntr_var); } double ycContourPcenV2(long i, long j, long k) { /* call with the auxiliary variable */ return ycContourPcenAllvar(i, j, k, cntr_v2); } double ycContourGrdPcenVar(long i, long j, long k) { long idxg; /* i,j,k are indices relative to the current chunk. Convert into indices into the global array. Same function for Cartesian and Curvilinear. */ idxg= i+cntr_iOrigin+(j+cntr_jOrigin)*cntr_iSize +(k+cntr_kOrigin)*cntr_iSize*cntr_jSize; return cntr_var[idxg]; } double ycContourGrdPcenV2(long i, long j, long k) { long idxg; /* i,j,k are indices relative to the current chunk. Convert into indices into the global array. Same function for Cartesian and Curvilinear. */ idxg= i+cntr_iOrigin+(j+cntr_jOrigin)*cntr_iSize +(k+cntr_kOrigin)*cntr_iSize*cntr_jSize; return cntr_v2[idxg]; } double ycContourCartZcenAllvar(long i, long j, long k, double *var) { long ig, jg, kg, ilo, ihi, jlo, jhi, klo, khi; long ijSize= (cntr_iSize-1)*(cntr_jSize-1); long var_iSize= (cntr_iSize-1); double vcen; /* i,j,k are indices relative to the current chunk. Convert into indices into the global array. The variable is zone centered so need to interpolate except on the boundaries. The contributing cells are ig and ig-1 etc. NOTE: the var array is one smaller in each direction than given by cntr_isize etc. */ ig= i+cntr_iOrigin; jg= j+cntr_jOrigin; kg= k+cntr_kOrigin; if(ig <= 0) { ilo= ihi= 0; } else if(ig > cntr_iSize-2) { /* cntr_iSize-2 is the last ZONE */ ilo= ihi= cntr_iSize-2; } else { ilo= ig-1; ihi= ig; } if(jg <= 0) { jlo= jhi= 0; } else if(jg > cntr_jSize-2) { jlo= jhi= cntr_jSize-2; } else { jlo= jg-1; jhi= jg; } if(kg <= 0) { klo= khi= 0; } else if(kg > cntr_kSize-2) { klo= khi= cntr_kSize-2; } else { klo= kg-1; khi= kg; } vcen= var[ilo+jlo*var_iSize+klo*ijSize] + var[ihi+jlo*var_iSize+klo*ijSize] + var[ilo+jhi*var_iSize+klo*ijSize] + var[ihi+jhi*var_iSize+klo*ijSize] + var[ilo+jlo*var_iSize+khi*ijSize] + var[ihi+jlo*var_iSize+khi*ijSize] + var[ilo+jhi*var_iSize+khi*ijSize] + var[ihi+jhi*var_iSize+khi*ijSize]; vcen *= 0.125; return vcen; } double ycContourCartZcenVar(long i, long j, long k) { /* call with the contour variable */ return ycContourCartZcenAllvar(i, j, k, cntr_var); } double ycContourCartZcenV2(long i, long j, long k) { /* call with the auxiliary variable */ return ycContourCartZcenAllvar(i, j, k, cntr_v2); } double ycContourCartGrdZcenVar(long i, long j, long k) { /* call with the contour variable */ return ycContourCartZcenAllvar(i, j, k, cntr_var); } double ycContourCartGrdZcenV2(long i, long j, long k) { /* call with the auxiliary variable */ return ycContourCartZcenAllvar(i, j, k, cntr_v2); } yPoint3D ycContourCrvGrdXyz(long i, long j, long k) { long idxg; /* i,j,k are indices relative to the current chunk. Use the location of the corner of this chunk to get xyz. Same function for point centered and zone centered Cartesian grids. */ idxg= i+cntr_iOrigin+(j+cntr_jOrigin)*cntr_iSize +(k+cntr_kOrigin)*cntr_iSize*cntr_jSize; return cntr_xyz[idxg]; } double ycContourCrvGrdZcenAllvar(long i, long j, long k, double *var) { long ig, jg, kg, ilo, ihi, jlo, jhi, klo, khi; long ijSize= (cntr_iSize-1)*(cntr_jSize-1); long var_iSize= (cntr_iSize-1); double vcen; /* i,j,k are indices relative to the current chunk. Convert into indices into the global array. The variable is zone centered so need to interpolate except on the boundaries. The contributing cells are ig and ig-1 etc. NOTE: the var array is one smaller in each direction than given by cntr_isize etc. */ ig= i+cntr_iOrigin; jg= j+cntr_jOrigin; kg= k+cntr_kOrigin; if(ig <= 0) { ilo= ihi= 0; } else if(ig > cntr_iSize-2) { /* cntr_iSize-2 is the last ZONE */ ilo= ihi= cntr_iSize-2; } else { ilo= ig-1; ihi= ig; } if(jg <= 0) { jlo= jhi= 0; } else if(jg > cntr_jSize-2) { jlo= jhi= cntr_jSize-2; } else { jlo= jg-1; jhi= jg; } if(kg <= 0) { klo= khi= 0; } else if(kg > cntr_kSize-2) { klo= khi= cntr_kSize-2; } else { klo= kg-1; khi= kg; } vcen= var[ilo+jlo*var_iSize+klo*ijSize] + var[ihi+jlo*var_iSize+klo*ijSize] + var[ilo+jhi*var_iSize+klo*ijSize] + var[ihi+jhi*var_iSize+klo*ijSize] + var[ilo+jlo*var_iSize+khi*ijSize] + var[ihi+jlo*var_iSize+khi*ijSize] + var[ilo+jhi*var_iSize+khi*ijSize] + var[ihi+jhi*var_iSize+khi*ijSize]; vcen *= 0.125; return vcen; } double ycContourCrvGrdZcenVar(long i, long j, long k) { /* call with the contour variable */ return ycContourCrvGrdZcenAllvar(i, j, k, cntr_var); } double ycContourCrvGrdZcenV2(long i, long j, long k) { /* call with the auxiliary variable */ return ycContourCrvGrdZcenAllvar(i, j, k, cntr_v2); } int ycGradientChunk(long nx, long xy_siz, long i, long j, long k, long idx, yPoint3D *xyz, double *var, yPoint3D *grd, unsigned char *flag) { double del2, delx, dely, delz, delv, delv2; long ii, jj, kk, id; /* WARNING: this doesn't work next to the domain boundary for zone centered data. The variable on the guard points is not set properly. The consistent solution is to use a different gradient calculation using only zone centered values. */ /* compute gradients at all 8 corners */ for(kk= 0; kk <= 1; kk++) { for(jj= 0; jj <= 1; jj++) { for(ii= 0; ii <= 1; ii++) { id= idx+ii+jj*nx+kk*xy_siz; if(!(flag[id] & GRD_DONE)) { /* i-direction */ delv= var[id+1] -var[id-1]; delx= xyz[id+1].x-xyz[id-1].x; dely= xyz[id+1].y-xyz[id-1].y; delz= xyz[id+1].z-xyz[id-1].z; del2= delx*delx+dely*dely+delz*delz+1.0e-80; delv2= delv/del2; grd[id].x = delv2*delx; grd[id].y = delv2*dely; grd[id].z = delv2*delz; /* j-direction */ delv= var[id+nx] -var[id-nx]; delx= xyz[id+nx].x-xyz[id-nx].x; dely= xyz[id+nx].y-xyz[id-nx].y; delz= xyz[id+nx].z-xyz[id-nx].z; del2= delx*delx+dely*dely+delz*delz+1.0e-80; delv2= delv/del2; grd[id].x += delv2*delx; grd[id].y += delv2*dely; grd[id].z += delv2*delz; /* k-direction */ delv= var[id+xy_siz] -var[id-xy_siz]; delx= xyz[id+xy_siz].x-xyz[id-xy_siz].x; dely= xyz[id+xy_siz].y-xyz[id-xy_siz].y; delz= xyz[id+xy_siz].z-xyz[id-xy_siz].z; del2= delx*delx+dely*dely+delz*delz+1.0e-80; delv2= delv/del2; grd[id].x += delv2*delx; grd[id].y += delv2*dely; grd[id].z += delv2*delz; flag[id] |= GRD_DONE; } } } } return 0; } int ycGetVarXyzCart(long nx, long xy_siz, long i, long j, long k, long idx, yPoint3D *xyz, double *var, unsigned char *flag, GET_XYZ f_xyz, GET_VAR f_var) { long id; /* idx is an index relative to the current chunk. First make sure point-centered coordinates and variable values are in the chunk-sized arrays for all vertices of this cell and all the vertices directly connected to the cell's vertices. */ /* NOTE: already have variable values at the corners of the cell from deciding which points were above and below the contour level. */ id= idx -xy_siz; if(!(flag[id] & XYZ_DONE)) {xyz[id] = (*f_xyz)(i, j, k-1); flag[id] |= XYZ_DONE;} if(!(flag[id] & VAR_DONE)) {var[id] = (*f_var)(i, j, k-1); flag[id] |= VAR_DONE;} id= idx+1 -xy_siz; if(!(flag[id] & XYZ_DONE)) {xyz[id] = (*f_xyz)(i+1,j, k-1); flag[id] |= XYZ_DONE;} if(!(flag[id] & VAR_DONE)) {var[id] = (*f_var)(i+1,j, k-1); flag[id] |= VAR_DONE;} id= idx +nx-xy_siz; if(!(flag[id] & XYZ_DONE)) {xyz[id] = (*f_xyz)(i, j+1,k-1); flag[id] |= XYZ_DONE;} if(!(flag[id] & VAR_DONE)) {var[id] = (*f_var)(i, j+1,k-1); flag[id] |= VAR_DONE;} id= idx+1+nx-xy_siz; if(!(flag[id] & XYZ_DONE)) {xyz[id] = (*f_xyz)(i+1,j+1,k-1); flag[id] |= XYZ_DONE;} if(!(flag[id] & VAR_DONE)) {var[id] = (*f_var)(i+1,j+1,k-1); flag[id] |= VAR_DONE;} id= idx -nx; if(!(flag[id] & XYZ_DONE)) {xyz[id] = (*f_xyz)(i, j-1,k ); flag[id] |= XYZ_DONE;} if(!(flag[id] & VAR_DONE)) {var[id] = (*f_var)(i, j-1,k ); flag[id] |= VAR_DONE;} id= idx+1-nx; if(!(flag[id] & XYZ_DONE)) {xyz[id] = (*f_xyz)(i+1,j-1,k ); flag[id] |= XYZ_DONE;} if(!(flag[id] & VAR_DONE)) {var[id] = (*f_var)(i+1,j-1,k ); flag[id] |= VAR_DONE;} id= idx-1; if(!(flag[id] & XYZ_DONE)) {xyz[id] = (*f_xyz)(i-1,j, k ); flag[id] |= XYZ_DONE;} if(!(flag[id] & VAR_DONE)) {var[id] = (*f_var)(i-1,j, k ); flag[id] |= VAR_DONE;} id= idx; if(!(flag[id] & XYZ_DONE)) {xyz[id] = (*f_xyz)(i, j, k ); flag[id] |= XYZ_DONE;} id= idx+1; if(!(flag[id] & XYZ_DONE)) {xyz[id] = (*f_xyz)(i+1,j, k ); flag[id] |= XYZ_DONE;} id= idx+2; if(!(flag[id] & XYZ_DONE)) {xyz[id] = (*f_xyz)(i+2,j, k ); flag[id] |= XYZ_DONE;} if(!(flag[id] & VAR_DONE)) {var[id] = (*f_var)(i+2,j, k ); flag[id] |= VAR_DONE;} id= idx-1+nx; if(!(flag[id] & XYZ_DONE)) {xyz[id] = (*f_xyz)(i-1,j+1,k ); flag[id] |= XYZ_DONE;} if(!(flag[id] & VAR_DONE)) {var[id] = (*f_var)(i-1,j+1,k ); flag[id] |= VAR_DONE;} id= idx +nx; if(!(flag[id] & XYZ_DONE)) {xyz[id] = (*f_xyz)(i, j+1,k ); flag[id] |= XYZ_DONE;} id= idx+1+nx; if(!(flag[id] & XYZ_DONE)) {xyz[id] = (*f_xyz)(i+1,j+1,k ); flag[id] |= XYZ_DONE;} id= idx+2+nx; if(!(flag[id] & XYZ_DONE)) {xyz[id] = (*f_xyz)(i+2,j+1,k ); flag[id] |= XYZ_DONE;} if(!(flag[id] & VAR_DONE)) {var[id] = (*f_var)(i+2,j+1,k ); flag[id] |= VAR_DONE;} id= idx +2*nx; if(!(flag[id] & XYZ_DONE)) {xyz[id] = (*f_xyz)(i, j+2,k ); flag[id] |= XYZ_DONE;} if(!(flag[id] & VAR_DONE)) {var[id] = (*f_var)(i, j+2,k ); flag[id] |= VAR_DONE;} id= idx+1+2*nx; if(!(flag[id] & XYZ_DONE)) {xyz[id] = (*f_xyz)(i+1,j+2,k ); flag[id] |= XYZ_DONE;} if(!(flag[id] & VAR_DONE)) {var[id] = (*f_var)(i+1,j+2,k ); flag[id] |= VAR_DONE;} id= idx -nx+xy_siz; if(!(flag[id] & XYZ_DONE)) {xyz[id] = (*f_xyz)(i, j-1,k+1); flag[id] |= XYZ_DONE;} if(!(flag[id] & VAR_DONE)) {var[id] = (*f_var)(i, j-1,k+1); flag[id] |= VAR_DONE;} id= idx+1-nx+xy_siz; if(!(flag[id] & XYZ_DONE)) {xyz[id] = (*f_xyz)(i+1,j-1,k+1); flag[id] |= XYZ_DONE;} if(!(flag[id] & VAR_DONE)) {var[id] = (*f_var)(i+1,j-1,k+1); flag[id] |= VAR_DONE;} id= idx-1 +xy_siz; if(!(flag[id] & XYZ_DONE)) {xyz[id] = (*f_xyz)(i-1,j ,k+1); flag[id] |= XYZ_DONE;} if(!(flag[id] & VAR_DONE)) {var[id] = (*f_var)(i-1,j ,k+1); flag[id] |= VAR_DONE;} id= idx +xy_siz; if(!(flag[id] & XYZ_DONE)) {xyz[id] = (*f_xyz)(i, j ,k+1); flag[id] |= XYZ_DONE;} id= idx+1 +xy_siz; if(!(flag[id] & XYZ_DONE)) {xyz[id] = (*f_xyz)(i+1,j ,k+1); flag[id] |= XYZ_DONE;} id= idx+2 +xy_siz; if(!(flag[id] & XYZ_DONE)) {xyz[id] = (*f_xyz)(i+2,j ,k+1); flag[id] |= XYZ_DONE;} if(!(flag[id] & VAR_DONE)) {var[id] = (*f_var)(i+2,j ,k+1); flag[id] |= VAR_DONE;} id= idx-1+nx+xy_siz; if(!(flag[id] & XYZ_DONE)) {xyz[id] = (*f_xyz)(i-1,j+1,k+1); flag[id] |= XYZ_DONE;} if(!(flag[id] & VAR_DONE)) {var[id] = (*f_var)(i-1,j+1,k+1); flag[id] |= VAR_DONE;} id= idx +nx+xy_siz; if(!(flag[id] & XYZ_DONE)) {xyz[id] = (*f_xyz)(i ,j+1,k+1); flag[id] |= XYZ_DONE;} id= idx+1+nx+xy_siz; if(!(flag[id] & XYZ_DONE)) {xyz[id] = (*f_xyz)(i+1,j+1,k+1); flag[id] |= XYZ_DONE;} id= idx+2+nx+xy_siz; if(!(flag[id] & XYZ_DONE)) {xyz[id] = (*f_xyz)(i+2,j+1,k+1); flag[id] |= XYZ_DONE;} if(!(flag[id] & VAR_DONE)) {var[id] = (*f_var)(i+2,j+1,k+1); flag[id] |= VAR_DONE;} id= idx +2*nx+xy_siz; if(!(flag[id] & XYZ_DONE)) {xyz[id] = (*f_xyz)(i, j+2,k+1); flag[id] |= XYZ_DONE;} if(!(flag[id] & VAR_DONE)) {var[id] = (*f_var)(i, j+2,k+1); flag[id] |= VAR_DONE;} id= idx+1+2*nx+xy_siz; if(!(flag[id] & XYZ_DONE)) {xyz[id] = (*f_xyz)(i+1,j+2,k+1); flag[id] |= XYZ_DONE;} if(!(flag[id] & VAR_DONE)) {var[id] = (*f_var)(i+1,j+2,k+1); flag[id] |= VAR_DONE;} id= idx +2*xy_siz; if(!(flag[id] & XYZ_DONE)) {xyz[id] = (*f_xyz)(i, j, k+2); flag[id] |= XYZ_DONE;} if(!(flag[id] & VAR_DONE)) {var[id] = (*f_var)(i, j, k+2); flag[id] |= VAR_DONE;} id= idx+1 +2*xy_siz; if(!(flag[id] & XYZ_DONE)) {xyz[id] = (*f_xyz)(i+1,j, k+2); flag[id] |= XYZ_DONE;} if(!(flag[id] & VAR_DONE)) {var[id] = (*f_var)(i+1,j, k+2); flag[id] |= VAR_DONE;} id= idx +nx+2*xy_siz; if(!(flag[id] & XYZ_DONE)) {xyz[id] = (*f_xyz)(i ,j+1,k+2); flag[id] |= XYZ_DONE;} if(!(flag[id] & VAR_DONE)) {var[id] = (*f_var)(i, j+1,k+2); flag[id] |= VAR_DONE;} id= idx+1+nx+2*xy_siz; if(!(flag[id] & XYZ_DONE)) {xyz[id] = (*f_xyz)(i+1,j+1,k+2); flag[id] |= XYZ_DONE;} if(!(flag[id] & VAR_DONE)) {var[id] = (*f_var)(i+1,j+1,k+2); flag[id] |= VAR_DONE;} return 0; } int ycContourTet_OneZone(double level, long zonidx, int index, double s[8], double vars[8], yPoint3D pts[8], yPoint3D gradients[8], TriArrayGrp *triangles) { int ie, vert0, vert1; Edge the_edg; long *cellIDs, numTri, numVert, ipn, nedg, indbase; double t, v1, v2, *v2vals; yPoint3D *xyzverts, *normals, n, x1, x2, n1, n2; /* The caller allocates storage for the triangles making up the iso-surface. The input is a hexahedral zone. s is the variable values. vars is the auxiliary variable (optional). pts is the coordinates of the corner of the hex. gradients is the gradient of s at the corners. index is the 8 bit code for the high and low corners. */ cellIDs = triangles->cellIDs; xyzverts = triangles->xyzverts; normals = triangles->normals; v2vals= triangles->var2; numTri= triangles->numTri; /* Generate triangles and point gradients using a 6 tet decomposition. The contour level is known to cut this zone. */ num_poly= iso_cases[index].nStrip; /* For all tri-strips, find the intersection points. Break them back up into triangles for now. */ for(ipn= 0, indbase= 0; ipn < num_poly; ipn++) { int phase= 1, ij, ind; nedg= (iso_cases[index].lens)[ipn]; for(ie= 0; ie < nedg-2; ie++) { for(ij= 0; ij < 3; ij++) { if(phase == 0) { ind= ie+ij; } else { ind= ie+2-ij; } /* get the two vertices at the ends of the edge on which the point lies */ the_edg= edges[ (iso_cases[index].edges)[indbase+ind] ]; vert0= the_edg.vert0; vert1= the_edg.vert1; t = (double)(level - s[vert0]) / (s[vert1] - s[vert0]); x1 = pts[vert0]; x2 = pts[vert1]; n1 = gradients[vert0]; n2 = gradients[vert1]; numVert= 3*numTri+ij; xyzverts[numVert].x = x1.x + t * (x2.x - x1.x); xyzverts[numVert].y = x1.y + t * (x2.y - x1.y); xyzverts[numVert].z = x1.z + t * (x2.z - x1.z); if(vars) { v1 = vars[vert0]; v2 = vars[vert1]; v2vals[numVert] = v1 + t * (v2-v1); } n.x = n1.x + t * (n2.x - n1.x); n.y = n1.y + t * (n2.y - n1.y); n.z = n1.z + t * (n2.z - n1.z); ycNormalize(&n); normals[numVert]= n; } cellIDs[numTri]= zonidx; /* the C-style index of this cell */ numTri++; if(phase == 0) phase= 1; else phase= 0; } indbase += nedg; } triangles->numTri= numTri; return 1; } int ycContourTetHex(double level, long ifirst, long nzone, yPoint3D *xyz, yPoint3D *grad, long hexndx[][8], double *var, double *var2, TriArrayGrp *triangles) { int mask, index, ii, nlo, nhi; long i, ndx0, ndx1, ndx2, ndx3, ndx4, ndx5, ndx6, ndx7; double s[8], vars[8]; yPoint3D pts[8], gradients[8]; /* This is the version for point-centered data on an arbitrarily connected grid of hexes. hexndx is an 8 by nzone array of indices into the xyz, grad, var, and var2 arrays. Do not use any chunking. The caller is urged to arrange the ordering of nexndx so that zones that appear together in hexndx are nearby spatially. To avoid making triangles very large, pass chunks of hexndx. The input does NOT include guard cells because the gradient is supplied. */ /* The caller allocates storage for the triangles making up the iso-surface. */ if (!var || nzone < 1) { return 0; } /* The input is an array of hexahedral zones. Each zone is specified by 8 indices into arrays of coordinates, gradients, variables, and (optionally) auxiliary variables. */ ifirst--; /* convert from yorick-style index to C-style */ triangles->numTri= 0; /* prepare the case table for the iso-surfaces, if not already done */ if(!have_iso_cases) ycPrepIsoTet(); /* Traverse all cells, generating triangles and point gradients using a 6 tet decomposition of each hexahedron. */ for (i= ifirst; i < ifirst+nzone; i++) { /* Get data values at the corners. Note that this circulates around the zone, which is not in storage order. Note also that hexndx has yorick style indices. */ ndx0 = hexndx[i][0]-1; ndx1 = hexndx[i][1]-1; ndx2 = hexndx[i][2]-1; ndx3 = hexndx[i][3]-1; ndx4 = hexndx[i][4]-1; ndx5 = hexndx[i][5]-1; ndx6 = hexndx[i][6]-1; ndx7 = hexndx[i][7]-1; s[0] = var[ndx0]; s[1] = var[ndx1]; s[2] = var[ndx2]; s[3] = var[ndx3]; s[4] = var[ndx4]; s[5] = var[ndx5]; s[6] = var[ndx6]; s[7] = var[ndx7]; /* Build the case table */ for ( ii=0, nlo= 0, nhi= 0, mask= 1, index= 0; ii < 8; ii++, mask += mask) { if ( s[ii] >= level ) { index |= mask; nhi++; } else { nlo++; } } if ( nlo == 0 || nhi == 0 ) continue; /* no surface */ /* pick up the coordinates of the corners of the cell */ pts[0] = xyz[ndx0]; pts[1] = xyz[ndx1]; pts[2] = xyz[ndx2]; pts[3] = xyz[ndx3]; pts[4] = xyz[ndx4]; pts[5] = xyz[ndx5]; pts[6] = xyz[ndx6]; pts[7] = xyz[ndx7]; /* pick up the gradients at the corners of the cell */ gradients[0] = grad[ndx0]; gradients[1] = grad[ndx1]; gradients[2] = grad[ndx2]; gradients[3] = grad[ndx3]; gradients[4] = grad[ndx4]; gradients[5] = grad[ndx5]; gradients[6] = grad[ndx6]; gradients[7] = grad[ndx7]; if(var2) { vars[0] = var[ndx0]; vars[1] = var[ndx1]; vars[2] = var[ndx2]; vars[3] = var[ndx3]; vars[4] = var[ndx4]; vars[5] = var[ndx5]; vars[6] = var[ndx6]; vars[7] = var[ndx7]; ycContourTet_OneZone(level, i, index, s, vars, pts, gradients, triangles); } else { ycContourTet_OneZone(level, i, index, s, 0, pts, gradients, triangles); } } /* for i */ if(triangles->numTri > 0) return 1; else return 0; } int ycContourTet_array(long make_strip, long sizes[3], double level, double *var, double *var2, yPoint3D *xyz, yPoint3D *grd, unsigned char *flag, TriArrayGrp *triangles) { int i, j, k, xy_siz, mask, index; int jOffset, kOffset, idxv, idxcg, idxnow, ii, nlo, nhi; long numTri, ihi, jhi, khi, *cellIDs, *nTris, *triStart; long nx= sizes[0]; long ny= sizes[1]; long nz= sizes[2]; double s[8], vars[8], *v2vals; yPoint3D *xyzverts, *normals, pts[8], gradients[8]; /* The caller allocates storage for the triangles making up the iso-surface. The input array has dimensions sizes[3]. There are ghost cells on all sides so that gradients can be computed without testing for boundaries. This means there are sizes[i]-3 real cells in each direction. NOTE: origin is the coordinate of the 0,0,0 point. */ cellIDs = triangles->cellIDs; xyzverts = triangles->xyzverts; normals = triangles->normals; v2vals= triangles->var2; triStart= triangles->triStart; nTris = triangles->nTris; xy_siz = nx * ny; /* set stride for y and z in a chunk array. */ cntr_x_siz= nx; cntr_xy_siz= nx*ny; /* ihi, jhi, khi are the indices of the upper vertex to be processed in this call */ ihi= nx-2; jhi= ny-2; khi= nz-2; numTri= 0; /* This loop runs over all vertices in the chunk, including guard points. */ for(k= 0; k < nz; k++) { for(j= 0; j < ny; j++) { for(i= 0; i < nx; i++) { idxv = i + j*nx + k*xy_siz; flag[idxv]= 0; } } } /* prepare the case table for the iso-surfaces, if not already done */ if(!have_iso_cases) ycPrepIsoTet(); /* Traverse all cells, generating triangles and point gradients using a 6 tet decomposition of each hexahedron. The upper loop limit is a cell index, not a vertex index, so need a less than. */ for ( k=1; k < khi; k++) { kOffset = k*xy_siz; for ( j=1; j < jhi; j++) { jOffset = j*nx; for ( i=1; i < ihi; i++) { /* get data values at the corners. idxv is a zero-based POINT index */ idxv = i + jOffset + kOffset; if(make_strip) { /* record the first triangle for this cell */ triStart[idxv]= numTri; nTris[idxv]= 0; } /* get data values at the corners */ idxnow= idxv ; if(!(flag[idxnow] & VAR_DONE)) {var[idxnow] = (*f_var)(i, j, k ); flag[idxnow] |= VAR_DONE;} idxnow= idxv+1 ; if(!(flag[idxnow] & VAR_DONE)) {var[idxnow] = (*f_var)(i+1,j, k ); flag[idxnow] |= VAR_DONE;} idxnow= idxv +nx ; if(!(flag[idxnow] & VAR_DONE)) {var[idxnow] = (*f_var)(i, j+1,k ); flag[idxnow] |= VAR_DONE;} idxnow= idxv+1+nx ; if(!(flag[idxnow] & VAR_DONE)) {var[idxnow] = (*f_var)(i+1,j+1,k ); flag[idxnow] |= VAR_DONE;} idxnow= idxv +xy_siz; if(!(flag[idxnow] & VAR_DONE)) {var[idxnow] = (*f_var)(i, j, k+1); flag[idxnow] |= VAR_DONE;} idxnow= idxv+1 +xy_siz; if(!(flag[idxnow] & VAR_DONE)) {var[idxnow] = (*f_var)(i+1,j, k+1); flag[idxnow] |= VAR_DONE;} idxnow= idxv +nx+xy_siz; if(!(flag[idxnow] & VAR_DONE)) {var[idxnow] = (*f_var)(i, j+1,k+1); flag[idxnow] |= VAR_DONE;} idxnow= idxv+1+nx+xy_siz; if(!(flag[idxnow] & VAR_DONE)) {var[idxnow] = (*f_var)(i+1,j+1,k+1); flag[idxnow] |= VAR_DONE;} /* note that this circulates around the zone, not counts up in i,j,k */ s[0] = var[idxv]; s[1] = var[idxv+1]; s[2] = var[idxv+1+nx]; s[3] = var[idxv +nx]; s[4] = var[idxv +xy_siz]; s[5] = var[idxv+1 +xy_siz]; s[6] = var[idxv+1+nx+xy_siz]; s[7] = var[idxv +nx+xy_siz]; /* Build the case table */ for ( ii=0, nlo= 0, nhi= 0, mask= 1, index= 0; ii < 8; ii++, mask += mask) { if ( s[ii] >= level ) { index |= mask; nhi++; } else { nlo++; } } if ( nlo == 0 || nhi == 0 ) continue; /* no surface */ if(cntr_v2) { idxnow= idxv ; if(!(flag[idxnow] & V2_DONE)) {var2[idxnow] = (*f_v2)(i, j, k ); flag[idxnow] |= V2_DONE;} idxnow= idxv+1 ; if(!(flag[idxnow] & V2_DONE)) {var2[idxnow] = (*f_v2)(i+1,j, k ); flag[idxnow] |= V2_DONE;} idxnow= idxv +nx ; if(!(flag[idxnow] & V2_DONE)) {var2[idxnow] = (*f_v2)(i, j+1,k ); flag[idxnow] |= V2_DONE;} idxnow= idxv+1+nx ; if(!(flag[idxnow] & V2_DONE)) {var2[idxnow] = (*f_v2)(i+1,j+1,k ); flag[idxnow] |= V2_DONE;} idxnow= idxv +xy_siz; if(!(flag[idxnow] & V2_DONE)) {var2[idxnow] = (*f_v2)(i, j, k+1); flag[idxnow] |= V2_DONE;} idxnow= idxv+1 +xy_siz; if(!(flag[idxnow] & V2_DONE)) {var2[idxnow] = (*f_v2)(i+1,j, k+1); flag[idxnow] |= V2_DONE;} idxnow= idxv +nx+xy_siz; if(!(flag[idxnow] & V2_DONE)) {var2[idxnow] = (*f_v2)(i, j+1,k+1); flag[idxnow] |= V2_DONE;} idxnow= idxv+1+nx+xy_siz; if(!(flag[idxnow] & V2_DONE)) {var2[idxnow] = (*f_v2)(i+1,j+1,k+1); flag[idxnow] |= V2_DONE;} vars[0] = var2[idxv]; vars[1] = var2[idxv+1]; vars[2] = var2[idxv+1+nx]; vars[3] = var2[idxv +nx]; vars[4] = var2[idxv +xy_siz]; vars[5] = var2[idxv+1 +xy_siz]; vars[6] = var2[idxv+1+nx+xy_siz]; vars[7] = var2[idxv +nx+xy_siz]; } /* Get coordinates and variable values necessary for computing the gradient. After this call will have coordinates for all corners of this cell. */ ycGetVarXyzCart(nx, xy_siz, i, j, k, idxv, xyz, var, flag, f_xyz, f_var); /* pick up the coordinates of the corners of the cell */ pts[0] = xyz[idxv]; pts[1] = xyz[idxv+1]; pts[2] = xyz[idxv+1+nx]; pts[3] = xyz[idxv +nx]; pts[4] = xyz[idxv +xy_siz]; pts[5] = xyz[idxv+1 +xy_siz]; pts[6] = xyz[idxv+1+nx+xy_siz]; pts[7] = xyz[idxv +nx+xy_siz]; /* Compute gradients (if not already known) using values on the chunk, not from the global array. */ ycGradientChunk(nx, xy_siz, i, j, k, idxv, xyz, var, grd, flag); gradients[0] = grd[idxv]; gradients[1] = grd[idxv+1]; gradients[2] = grd[idxv+1+nx]; gradients[3] = grd[idxv +nx]; gradients[4] = grd[idxv +xy_siz]; gradients[5] = grd[idxv+1 +xy_siz]; gradients[6] = grd[idxv+1+nx+xy_siz]; gradients[7] = grd[idxv +nx+xy_siz]; num_poly= iso_cases[index].nStrip; /* For all tri-strips, find the intersection points. Break them back up into triangles for now. */ idxcg= i+cntr_iOrigin+(j+cntr_jOrigin)*(cntr_iSize-1)+(k+cntr_kOrigin)*(cntr_iSize-1)*(cntr_jSize-1); extract_tris_tet(index, idxcg, cntr_v2, &numTri, level, s, pts, gradients, vars, cellIDs, xyzverts, normals, v2vals); } /* for i */ } /* for j */ } /* for k */ triangles->numTri= numTri; if(numTri > 0) return 1; else return 0; } int ycContourTet_array_ndx(long make_strip, long sizes[3], double level, double *var, double *var2, yPoint3D *xyz, yPoint3D *grd, unsigned char *flag, long *ndx, TriVertexGrp *triangles) { int i, j, k, xy_siz, mask, index, num_idx; int jOffset, kOffset, idxv, idxc, idxcg, idxnow, ii, nlo, nhi; long numTri, numEdg, ihi, jhi, khi, *cellIDs, *nTris, *ptndx; long *triStart, edg_offset[12]; long nx= sizes[0]; long ny= sizes[1]; long nz= sizes[2]; double s[8], vars[8], *v2vals; yPoint3D *xyzverts, *normals, pts[8], gradients[8]; /* The caller allocates storage for the triangles making up the iso-surface. The triangles in the output are given by indices into vectors of vertices, gradients, and associated variables. */ /* The input array has dimensions sizes[3]. There are ghost cells on all sides so that gradients can be computed without testing for boundaries. This means there are sizes[i]-3 real cells in each direction. */ cellIDs = triangles->cellIDs; xyzverts = triangles->xyzverts; normals = triangles->normals; ptndx= triangles->ptndx; v2vals= triangles->var2; triStart= triangles->triStart; nTris = triangles->nTris; xy_siz = nx * ny; /* set stride for y and z in a chunk array. */ cntr_x_siz= nx; cntr_xy_siz= nx*ny; edg_offset[0]= 0; edg_offset[1]= 4; edg_offset[2]= 3*nx; edg_offset[3]= 1; edg_offset[4]= 3*xy_siz; edg_offset[5]= 3*xy_siz+4; edg_offset[6]= 3*xy_siz+3*nx; edg_offset[7]= 3*xy_siz+1; edg_offset[8]= 2; edg_offset[9]= 5; edg_offset[10]= 3*nx+5; edg_offset[11]= 3*nx+2; /* ihi, jhi, khi are the indices of the upper vertex to be processed in this call */ ihi= nx-2; jhi= ny-2; khi= nz-2; /* This loop runs over all vertices in the chunk, including guard points. */ for(k= 0; k < nz; k++) { for(j= 0; j < ny; j++) { for(i= 0; i < nx; i++) { idxv = i + j*nx + k*xy_siz; flag[idxv]= 0; } } } num_idx= 3*nx*ny*nz; for(i= 0; i < num_idx; i++) { ndx[i]= -1; } numTri= 0; numEdg= 0; /* number of unique edges cut by the iso-surface */ /* prepare the case table for the iso-surfaces, if not already done */ if(!have_iso_cases) ycPrepIsoTet(); /* Traverse all cells, generating triangles and point gradients using a 6 tet decomposition of each hexahedron. The upper loop limit is a cell index, not a vertex index, so need a less than. */ for ( k=1; k < khi; k++) { kOffset = k*xy_siz; for ( j=1; j < jhi; j++) { jOffset = j*nx; for ( i=1; i < ihi; i++) { /* get data values at the corners. idxv is a zero-based POINT index */ idxv = i + jOffset + kOffset; idxc = i + j*(nx-1) + k*(nx-1)*(ny-1); if(make_strip) { /* record the first triangle for this cell */ triStart[idxv]= numTri; nTris[idxv]= 0; } /* get data values at the corners */ idxnow= idxv ; if(!(flag[idxnow] & VAR_DONE)) {var[idxnow] = (*f_var)(i, j, k ); flag[idxnow] |= VAR_DONE;} idxnow= idxv+1 ; if(!(flag[idxnow] & VAR_DONE)) {var[idxnow] = (*f_var)(i+1,j, k ); flag[idxnow] |= VAR_DONE;} idxnow= idxv +nx ; if(!(flag[idxnow] & VAR_DONE)) {var[idxnow] = (*f_var)(i, j+1,k ); flag[idxnow] |= VAR_DONE;} idxnow= idxv+1+nx ; if(!(flag[idxnow] & VAR_DONE)) {var[idxnow] = (*f_var)(i+1,j+1,k ); flag[idxnow] |= VAR_DONE;} idxnow= idxv +xy_siz; if(!(flag[idxnow] & VAR_DONE)) {var[idxnow] = (*f_var)(i, j, k+1); flag[idxnow] |= VAR_DONE;} idxnow= idxv+1 +xy_siz; if(!(flag[idxnow] & VAR_DONE)) {var[idxnow] = (*f_var)(i+1,j, k+1); flag[idxnow] |= VAR_DONE;} idxnow= idxv +nx+xy_siz; if(!(flag[idxnow] & VAR_DONE)) {var[idxnow] = (*f_var)(i, j+1,k+1); flag[idxnow] |= VAR_DONE;} idxnow= idxv+1+nx+xy_siz; if(!(flag[idxnow] & VAR_DONE)) {var[idxnow] = (*f_var)(i+1,j+1,k+1); flag[idxnow] |= VAR_DONE;} /* note that this circulates around the zone, not counts up in i,j,k */ s[0] = var[idxv]; s[1] = var[idxv+1]; s[2] = var[idxv+1+nx]; s[3] = var[idxv +nx]; s[4] = var[idxv +xy_siz]; s[5] = var[idxv+1 +xy_siz]; s[6] = var[idxv+1+nx+xy_siz]; s[7] = var[idxv +nx+xy_siz]; /* Build the case table */ for ( ii=0, nlo= 0, nhi= 0, mask= 1, index= 0; ii < 8; ii++, mask += mask) { if ( s[ii] >= level ) { index |= mask; nhi++; } else { nlo++; } } if ( nlo == 0 || nhi == 0 ) continue; /* no surface */ if(cntr_v2) { idxnow= idxv ; if(!(flag[idxnow] & V2_DONE)) {var2[idxnow] = (*f_v2)(i, j, k ); flag[idxnow] |= V2_DONE;} idxnow= idxv+1 ; if(!(flag[idxnow] & V2_DONE)) {var2[idxnow] = (*f_v2)(i+1,j, k ); flag[idxnow] |= V2_DONE;} idxnow= idxv +nx ; if(!(flag[idxnow] & V2_DONE)) {var2[idxnow] = (*f_v2)(i, j+1,k ); flag[idxnow] |= V2_DONE;} idxnow= idxv+1+nx ; if(!(flag[idxnow] & V2_DONE)) {var2[idxnow] = (*f_v2)(i+1,j+1,k ); flag[idxnow] |= V2_DONE;} idxnow= idxv +xy_siz; if(!(flag[idxnow] & V2_DONE)) {var2[idxnow] = (*f_v2)(i, j, k+1); flag[idxnow] |= V2_DONE;} idxnow= idxv+1 +xy_siz; if(!(flag[idxnow] & V2_DONE)) {var2[idxnow] = (*f_v2)(i+1,j, k+1); flag[idxnow] |= V2_DONE;} idxnow= idxv +nx+xy_siz; if(!(flag[idxnow] & V2_DONE)) {var2[idxnow] = (*f_v2)(i, j+1,k+1); flag[idxnow] |= V2_DONE;} idxnow= idxv+1+nx+xy_siz; if(!(flag[idxnow] & V2_DONE)) {var2[idxnow] = (*f_v2)(i+1,j+1,k+1); flag[idxnow] |= V2_DONE;} vars[0] = var2[idxv]; vars[1] = var2[idxv+1]; vars[2] = var2[idxv+1+nx]; vars[3] = var2[idxv +nx]; vars[4] = var2[idxv +xy_siz]; vars[5] = var2[idxv+1 +xy_siz]; vars[6] = var2[idxv+1+nx+xy_siz]; vars[7] = var2[idxv +nx+xy_siz]; } /* Get coordinates and variable values necessary for computing the gradient. After this call will have coordinates for all corners of this cell. */ ycGetVarXyzCart(nx, xy_siz, i, j, k, idxv, xyz, var, flag, f_xyz, f_var); /* pick up the coordinates of the corners of the cell */ pts[0] = xyz[idxv]; pts[1] = xyz[idxv+1]; pts[2] = xyz[idxv+1+nx]; pts[3] = xyz[idxv +nx]; pts[4] = xyz[idxv +xy_siz]; pts[5] = xyz[idxv+1 +xy_siz]; pts[6] = xyz[idxv+1+nx+xy_siz]; pts[7] = xyz[idxv +nx+xy_siz]; /* Compute gradients (if not already known) using values on the chunk, not from the global array. */ ycGradientChunk(nx, xy_siz, i, j, k, idxv, xyz, var, grd, flag); gradients[0] = grd[idxv]; gradients[1] = grd[idxv+1]; gradients[2] = grd[idxv+1+nx]; gradients[3] = grd[idxv +nx]; gradients[4] = grd[idxv +xy_siz]; gradients[5] = grd[idxv+1 +xy_siz]; gradients[6] = grd[idxv+1+nx+xy_siz]; gradients[7] = grd[idxv +nx+xy_siz]; num_poly= iso_cases[index].nStrip; /* For all tri-strips, find the intersection points. Break them back up into triangles for now. */ idxcg= i+cntr_iOrigin+(j+cntr_jOrigin)*(cntr_iSize-1)+(k+cntr_kOrigin)*(cntr_iSize-1)*(cntr_jSize-1); extract_tris_tet_ndx(index, idxv, idxcg, cntr_v2, &numTri, &numEdg, level, s, pts, gradients, vars, edg_offset, cellIDs, ptndx, ndx, xyzverts, normals, v2vals); } /* for i */ } /* for j */ } /* for k */ triangles->numTri= numTri; triangles->numEdg= numEdg; if(numTri > 0) return 1; else return 0; } int tetiso_zone(tstrip_data t_strips[6]) { int poly_add, first_vert; int index, mask, ntri, num, ie; Edge first; long itet, vrt, ip, ipn, nedg, vrt0, vrt1, kk; ntri= 0; /* no triangles found so far in this zone */ num_poly= 0; /* no polygons constructed so far for this cell */ /* run through all tethedra for this cell. */ for(itet= 0; itet < 6; itet++) { for(vrt= 0, mask= 1, index= 0; vrt < 4; vrt++, mask *= 2) { if(vertflag[hex2tets[itet][vrt]]) index |= mask; } /* The tet has been identified as one of the 16 possible cases */ num= tri_count[index]; if(num <= 0) { /* no polygons in this tet, so proceed to the next tet */ continue; } ntri += num; /* There is only one polygon per tet, although there might be two triangles. Use hex relative edge numbers. */ first.vert0= tet_edges[itet][ first_edge[index].vert0 ]; first.vert1= tet_edges[itet][ first_edge[index].vert1 ]; poly_add= 1; if(num_poly > 0) { /* determine whether this triangle can be patched onto a previous polygon */ for(ip= 0; ip < num_poly; ip++) { vrt0= the_polys[ip].edges[ the_polys[ip].ndx_last ]; vrt1= the_polys[ip].edges[ (the_polys[ip].ndx_last+1) % the_polys[ip].num_edge ]; if(vrt0 == first.vert1 && vrt1 == first.vert0) { /* patch this triangle onto the existing polygon */ poly_add= 0; /* don't make a new polygon */ patch_poly(ip, index, num, itet); /* the triangle has been matched, so break out of the for loop */ break; } } } if(poly_add) { /* The new polygon doesn't patch onto an old one. Keep the index into this polygon of the initial vertex of the last edge of the polygon. The first index is really a flag for whether the poly starts on the first face of the first tet. */ the_polys[num_poly].ndx_first= poly_first[index]; the_polys[num_poly].ndx_last= poly_last[index]; the_polys[num_poly].edges[0]= tet_edges[itet][ tet_polys[index][0] ]; the_polys[num_poly].edges[1]= tet_edges[itet][ tet_polys[index][1] ]; the_polys[num_poly].edges[2]= tet_edges[itet][ tet_polys[index][2] ]; if(num == 1) { the_polys[num_poly].num_edge= 3; } else { the_polys[num_poly].num_edge= 4; the_polys[num_poly].edges[3]= tet_edges[itet][ tet_polys[index][3] ]; } num_poly++; } } /* Match polygons with an open last to those with an open first. */ for(ip= 0; ip < num_poly-1; ip++) { poly_data *oldpoly= &(the_polys[ip]); long ip2, oldlast= oldpoly->ndx_last; if(oldlast >= 0 && oldpoly->ndx_first != 0) { /* the last edge of this polygon may patch onto the first edge of another polygon. */ for(ip2= ip+1; ip2 < num_poly; ip2++) { if(the_polys[ip2].edges[0] != 0) continue; if(the_polys[ip2].edges[1] == oldpoly->edges[oldlast] && the_polys[ip2].edges[0] == oldpoly->edges[ (oldlast+1)%oldpoly->num_edge] ) { /* patch the two polygons together, then adjust first and last */ patch_2polys(ip2, ip); break; } } } else if(oldpoly->ndx_first == 0 && oldpoly->ndx_last < 0) { /* the first edge of this polygon may patch onto the last edge of another polygon. */ for(ip2= ip+1; ip2 < num_poly; ip2++) { long ip2last= the_polys[ip2].ndx_last; if(ip2last < 0) continue; if(the_polys[ip2].edges[ip2last] == oldpoly->edges[1] && the_polys[ip2].edges[(ip2last+1)%the_polys[ip2].num_edge] == oldpoly->edges[0] ) { /* patch the two polygons together, then adjust first and last */ patch_2polys(ip, ip2); break; } } } else if(oldpoly->ndx_first == 0 && oldpoly->ndx_last >= 0) { /* This polygon has both a first and last edge. See if it patches onto any other polygon. */ for(ip2= ip+1; ip2 < num_poly; ip2++) { long ip2last= the_polys[ip2].ndx_last; if(ip2last < 0) continue; if(the_polys[ip2].edges[ip2last] == oldpoly->edges[1] && the_polys[ip2].edges[(ip2last+1)%the_polys[ip2].num_edge] == oldpoly->edges[0] ) { /* patch the two polygons together, then adjust first and last */ patch_2polys(ip, ip2); break; } } } } /* find all open polygons and try to close them */ for(ip= 0; ip < num_poly; ip++) { if(the_polys[ip].ndx_last == the_polys[ip].ndx_first) { /* this should be the result of patching two polys together in the previous loop */ continue; } if(the_polys[ip].ndx_last >= 0) { /* the last edge of this polygon should patch onto the first edge */ if(the_polys[ip].edges[0] == the_polys[ip].edges[2]) { /* remove the first two vertices */ for(kk= 2; kk < the_polys[ip].num_edge; kk++) { the_polys[ip].edges[kk-2]= the_polys[ip].edges[kk]; } the_polys[ip].num_edge -= 2; } else if(the_polys[ip].edges[0] == the_polys[ip].edges[the_polys[ip].num_edge-2]) { /* remove the final two points */ the_polys[ip].num_edge -= 2; } else { /* impossible error?? */ } } } /* For all polygons, remove all points that are not on real edges. */ for(ipn= 0; ipn < num_poly; ipn++) { int iout; nedg= the_polys[ipn].num_edge; for(ie= 0, iout= 0; ie < nedg; ie++) { if(the_polys[ipn].edges[ie] >= 12) continue; if(iout < ie) { /* move the real edge down in the polygon */ the_polys[ipn].edges[iout]= the_polys[ipn].edges[ie]; } iout++; } the_polys[ipn].num_edge= iout; } /* For all polygons, remove duplicate first and last points. */ for(ipn= 0; ipn < num_poly; ipn++) { nedg= the_polys[ipn].num_edge; if(the_polys[ipn].edges[0] == the_polys[ipn].edges[nedg-1]) the_polys[ipn].num_edge--; } /* Convert all polygons into triangle strips. Special steps are required for cases where all 4 edges on a face are cut by the iso-surface. */ for(ipn= 0; ipn < num_poly; ipn++) { int fn, msk, fnum[6], nfours, last4; nfours= 0; nedg= the_polys[ipn].num_edge; for(fn= 0, msk= 1; fn < 6; fn++) { num= 0; for(ie= 0; ie < nedg; ie++) { if(face_code[ the_polys[ipn].edges[ie] ] & msk) num++; } if(num >= 3) { nfours++; last4= msk; #undef BADNUM_CHEK #ifdef BADNUM_CHEK /* ASSERT( (num != 3), "bad count in tetiso_zone"); */ if(num == 3) { int badone= 1; } #endif } fnum[fn]= num; msk += msk; } switch(nedg) { case 0: default: break; case 3: case 4: case 5: /* tri-strip is simple because there aren't more than two edges cut on any one face. */ assemble_strip(0, ipn, t_strips); break; case 6: if(nfours > 0) { /* Find the first edge not on the face with four edges cut. The tri-strip should be started at the next vertex, which will be on the face that is cut 4 times. */ for(ie= 0; ie < nedg; ie++) { if( !(face_code[ the_polys[ipn].edges[ie] ] & last4) ) { /* this edge is not on the "special" face. Start the tri-strip at the next vertex in the polygon */ first_vert= (ie+1) % nedg; break; } } assemble_strip(first_vert, ipn, t_strips); } else { /* tri-strip can be started anywhere */ assemble_strip(0, ipn, t_strips); } break; case 7: case 8: if(nfours > 0) { /* Find the first edge not on the face with four edges cut. If the next edge is on the face that is cut 4 times, start the tri-strip at that next vertex. If not, skip one more vertex and start the tri-strip there (the start will now be on the face with 4 edges cut). */ for(ie= 0; ie < nedg; ie++) { if( !(face_code[ the_polys[ipn].edges[ie] ] & last4) ) { first_vert= (ie+1) % nedg; if( !(face_code[ the_polys[ipn].edges[ie+1] ] & last4) ) { first_vert= (ie+2) % nedg; } break; } } assemble_strip(first_vert, ipn, t_strips); } else { /* tri-strip can be started anywhere */ assemble_strip(0, ipn, t_strips); } break; case 9: if(nfours > 0) { /* There are three faces that have all 4 edges cut by the iso-surface. The tri-strip should be started at the first edge that is shared between two faces. Find that edge. */ for(ie= 0; ie < nedg; ie++) { int nfaces= 0; for(fn= 0; fn < 6; fn++) { if(fnum[fn] >= 3) nfaces++; } if(nfaces > 1) { assemble_strip(ie, ipn, t_strips); break; } } #undef BAD_NEDG_CHEK #ifdef BAD_NEDG_CHEK /* should never be able to drop out of the loop without finding the desired edge */ if(ie >= nedg) { int nbad= 1; } #endif } else { /* impossible error */ assemble_strip(0, ipn, t_strips); } break; case 12: if(nfours > 0) { /* There are six faces that have all 4 edges cut by the iso-surface. The tri-strip should be started at the first edge on face zero. */ for(ie= 0; ie < nedg; ie++) { if(face_code[ the_polys[ipn].edges[ie] ] & 1) { /* have to make sure there isn't a problem with wrap-around */ if(ie == 0 && !(face_code[ the_polys[ipn].edges[ie+1] ] & 1) ) { assemble_strip(nedg-1, ipn, t_strips); break; } else { assemble_strip(ie, ipn, t_strips); break; } } } #ifdef BAD_NEDG_CHEK /* should never be able to drop out of the loop without finding the desired edge */ if(ie >= nedg) { int nbad= 1; } #endif } else { /* impossible error */ assemble_strip(0, ipn, t_strips); } break; case 1: case 2: case 10: case 11: /* impossible!! */ #ifdef BAD_NEDG_CHEK { int badone= 1; } #endif break; } } #ifdef BAD_FACE_CHEK /* For all tri-strips, find cases with three consecutive edges on the same face. */ for(ipn= 0; ipn < num_poly; ipn++) { int i1, i2; nedg= t_strips[ipn].nvert; for(ie= 0; ie < nedg; ie++) { i1= (ie+1) % nedg; i2= (ie+2) % nedg; if(face_code[ t_strips[ipn].edges[ie] ] & face_code[ t_strips[ipn].edges[i1] ] & face_code[ t_strips[ipn].edges[i2] ] ) { int badone= 1; } } } #endif return num_poly; } int ycTetIso_one_zone(double level, double *var, tstrip_array *t_strips) { int ii, nstrip; /* Build the case table */ for ( ii=0; ii < 8; ii++) { if ( var[ii] >= level ) { vertflag[ii]= 1; } else { vertflag[ii]= 0; } } nstrip= tetiso_zone( t_strips->the_tris ); t_strips->nStrip= nstrip; return nstrip; } int ycPrepIsoTet(void) { int ii, jj, kk, nstrip, mask; long *lens, *edges, lentot, now; /* release storage if necessary */ if(have_iso_cases) { for(jj= 0; jj < 256; jj++) { if(iso_cases[jj].lens) p_free(iso_cases[jj].lens); if(iso_cases[jj].edges) p_free(iso_cases[jj].edges); } have_iso_cases= 0; } /* Run over all possible hi-lo combinations for the vertices of a hexahedron */ for(jj= 0; jj < 256; jj++) { /* Build the case table */ for ( ii=0, mask= 1; ii < 8; ii++, mask += mask) { if(jj & mask) { vertflag[ii]= 1; } else { vertflag[ii]= 0; } } nstrip= tetiso_zone( the_strips ); iso_cases[jj].nStrip= nstrip; if(nstrip) { lens= (long *) p_malloc(nstrip*sizeof(long)); iso_cases[jj].lens= lens; lentot= 0; for(ii= 0; ii < nstrip; ii++) { lens[ii]= the_strips[ii].nvert; lentot += lens[ii]; } edges= (long *) p_malloc(lentot*sizeof(long)); iso_cases[jj].edges= edges; now= 0; for(ii= 0; ii < nstrip; ii++) { for(kk= 0; kk < lens[ii]; kk++) { edges[now++]= the_strips[ii].edges[kk]; } } } else { iso_cases[jj].lens= 0; iso_cases[jj].edges= 0; } } have_iso_cases= 1; return 0; } void assemble_strip(int ndx, int ipn, tstrip_data *t_strips) { int phase= 0, lo, hi, nu, nedg, ie; /* start a triangle strip at index ndx */ nedg= the_polys[ipn].num_edge; lo= ndx; hi= (lo-1); if(hi < 0) hi += nedg; nu= (lo+1); if(nu >= nedg) nu -= nedg; phase= 0; t_strips[ipn].edges[0]= the_polys[ipn].edges[lo]; t_strips[ipn].edges[1]= the_polys[ipn].edges[hi]; for(ie= 2; ie < nedg; ie++) { t_strips[ipn].edges[ie]= the_polys[ipn].edges[nu]; if(phase == 0) { /* the new point in the strip is currently at the "low" side, so it will be at the "high" side next time */ lo= nu; nu= hi-1; if(nu < 0) nu += nedg; phase= 1; } else { /* the new point moves from the "high" side to the "low" side */ hi= nu; nu= lo+1; if(nu >= nedg) nu -= nedg; phase= 0; } } t_strips[ipn].nvert= nedg; } void extract_tris_tet(int case_index, long idxcg, double *cntr_v2, long *numTri, double lev, double s[8], yPoint3D pts[8], yPoint3D gradients[8], double vars[8], long *cellIDs, yPoint3D *xyzverts, yPoint3D *normals, double *v2vals) { int indbase, ie, vert0, vert1, ij, ind; long ipn, nedg, numVert; double t, v1, v2; yPoint3D n, x1, x2, n1, n2; Edge the_edg; num_poly= iso_cases[case_index].nStrip; /* For all tri-strips, find the intersection points. Break them back up into triangles for now. */ for(ipn= 0, indbase= 0; ipn < num_poly; ipn++) { int phase= 1; nedg= (iso_cases[case_index].lens)[ipn]; for(ie= 0; ie < nedg-2; ie++) { for(ij= 0; ij < 3; ij++) { if(phase == 0) { ind= ie+ij; } else { ind= ie+2-ij; } /* get the two vertices at the ends of the edge on which the point lies */ the_edg= edges[ (iso_cases[case_index].edges)[indbase+ind] ]; vert0= the_edg.vert0; vert1= the_edg.vert1; t = (double)(lev - s[vert0]) / (s[vert1] - s[vert0]); x1 = pts[vert0]; x2 = pts[vert1]; n1 = gradients[vert0]; n2 = gradients[vert1]; numVert= 3*(*numTri)+ij; xyzverts[numVert].x = x1.x + t * (x2.x - x1.x); xyzverts[numVert].y = x1.y + t * (x2.y - x1.y); xyzverts[numVert].z = x1.z + t * (x2.z - x1.z); if(cntr_v2) { v1 = vars[vert0]; v2 = vars[vert1]; v2vals[numVert] = v1 + t * (v2-v1); } n.x = n1.x + t * (n2.x - n1.x); n.y = n1.y + t * (n2.y - n1.y); n.z = n1.z + t * (n2.z - n1.z); ycNormalize(&n); normals[numVert]= n; } cellIDs[*numTri]= idxcg; /* the C-style global index of this cell */ (*numTri)++; if(phase == 0) phase= 1; else phase= 0; } indbase += nedg; } } void extract_tris_tet_ndx(int case_index, long idxv, long idxcg, double *cntr_v2, long *numTri, long *numEdg, double lev, double s[8], yPoint3D pts[8], yPoint3D gradients[8], double vars[8], long edg_offset[12], long *cellIDs, long *ptndx, long *ndx, yPoint3D *xyzverts, yPoint3D *normals, double *v2vals) { int indbase, ie, vert0, vert1, ij, ind; long ipn, nedg, numVert, itmp, edgnum, currEdg, currTri; double t, v1, v2; yPoint3D n, x1, x2, n1, n2; Edge the_edg; num_poly= iso_cases[case_index].nStrip; /* For all tri-strips, find the intersection points. Break them back up into triangles for now. */ currEdg= *numEdg; currTri= *numTri; for(ipn= 0, indbase= 0; ipn < num_poly; ipn++) { int phase= 1; nedg= (iso_cases[case_index].lens)[ipn]; for(ie= 0; ie < nedg-2; ie++) { for(ij= 0; ij < 3; ij++) { if(phase == 0) { ind= ie+ij; } else { ind= ie+2-ij; } itmp= (iso_cases[case_index].edges)[indbase+ind]; edgnum= 3*idxv+edg_offset[itmp]; if(ndx[edgnum] < 0) { /* get the two vertices at the ends of the edge on which the point lies */ the_edg= edges[itmp]; ndx[edgnum]= currEdg; vert0= the_edg.vert0; vert1= the_edg.vert1; t = (double)(lev - s[vert0]) / (s[vert1] - s[vert0]); x1 = pts[vert0]; x2 = pts[vert1]; xyzverts[currEdg].x = x1.x + t * (x2.x - x1.x); xyzverts[currEdg].y = x1.y + t * (x2.y - x1.y); xyzverts[currEdg].z = x1.z + t * (x2.z - x1.z); n1 = gradients[vert0]; n2 = gradients[vert1]; n.x = n1.x + t * (n2.x - n1.x); n.y = n1.y + t * (n2.y - n1.y); n.z = n1.z + t * (n2.z - n1.z); ycNormalize(&n); normals[currEdg]= n; if(cntr_v2) { v1 = vars[vert0]; v2 = vars[vert1]; v2vals[currEdg] = v1 + t * (v2-v1); } currEdg++; } /* Insert vertex into the triangle array. Note: vertex can be on any of the edges already cut. */ numVert= 3*currTri+ij; ptndx[numVert]= ndx[edgnum]; } cellIDs[currTri]= idxcg; /* the C-style globalindex of this cell */ currTri++; if(phase == 0) phase= 1; else phase= 0; } indbase += nedg; } *numEdg= currEdg; *numTri= currTri; } void extract_slicetris_tet(int case_index, long idxcg, double *cntr_v2, long *numTri, double s[8], yPoint3D pts[8], double vars[8], long *cellIDs, yPoint3D *xyzverts, double *v2vals) { long numVert, ipn, indbase, nedg, ie, ij, ind, vert0, vert1; double t, var_1, var_2; yPoint3D x1, x2; Edge the_edg; num_poly= iso_cases[case_index].nStrip; /* For all tri-strips, find the intersection points. Break them back up into triangles for now. */ for(ipn= 0, indbase= 0; ipn < num_poly; ipn++) { int phase= 1; nedg= (iso_cases[case_index].lens)[ipn]; for(ie= 0; ie < nedg-2; ie++) { for(ij= 0; ij < 3; ij++) { if(phase == 0) { ind= ie+ij; } else { ind= ie+2-ij; } /* get the two vertices at the ends of the edge on which the point lies */ the_edg= edges[ (iso_cases[case_index].edges)[indbase+ind] ]; vert0= the_edg.vert0; vert1= the_edg.vert1; /* NOTE: if the program is functionally correctly, this statement can't result in a divide by zero. */ t = (double)(0.0 - s[vert0]) / (s[vert1] - s[vert0]); x1 = pts[vert0]; x2 = pts[vert1]; numVert= 3*(*numTri)+ij; xyzverts[numVert].x = x1.x + t * (x2.x - x1.x); xyzverts[numVert].y = x1.y + t * (x2.y - x1.y); xyzverts[numVert].z = x1.z + t * (x2.z - x1.z); /* note: no normal because slicing plane */ if(cntr_v2) { var_1= vars[vert0]; var_2= vars[vert1]; v2vals[numVert]= var_1 + t * (var_2-var_1); } } /* the C-style index of this cell in the global array */ cellIDs[*numTri]= idxcg; (*numTri)++; } /* for each triangle */ } } yorick-gl-1.1+cvs20070922+dfsg.orig/README.glx0000640000175000017500000001163210313362503020074 0ustar thibautthibaut GLX 1.3 documentation --------------------- Prior to 1.3, specifying GLX_RGBA attribute to glXChooseVisual guaranteed a true (or direct) color visual would be selected, and not specifying GLX_RGBA guaranteed a pseudo (or static) color visual. This is no longer true in GLX 1.3 which supports a fancier notion of GLXFBConfigs. Mesa is also happy with RGBA in pseudocolor visuals. Colormaps and associated behavior are not specified in the standard. GLXDrawable is union of GLXWindow, GLXPixmap, GLXPbuffer, Window (Pbuffer is like Pixmap, but not assocated with any X Drawable) -- note X's Window is included in this list, this is how Mesa works, and apparently pre-1.3 GLX ------------------------------------------------------------------------ Notes gleaned from Mesa implementation: --------------------------------------- The colormap may be inherited from the parent, or a private map for the window can be created (informing the window manager by a property on its toplevel that the map should be installed). Mesa will go ahead and allocate its own colors in this colormap, in either case. When the colormap is exhausted, it moves on to a "closest" RGB algorithm in the colormap. Note that Mesa uses XGetWindowAttributes to return the colormap. If O'Reilly is right, this defaults to CopyFromParent (i.e.- 0), which it looks like Mesa would decide to allocate its own. Hence the colormap attribute should actually be set on the Mesa window, even if only to the default colormap. The colors Mesa attempts to allocate are determined by the DITHER666 macro at (Mesa) compile time -- if set, it tries to get a 6x6x6 RGB cube; by default Mesa takes a 5x9x5 RGB cube. Apparently, neither OpenGL nor GLX provides any way to tell anything about how colors are handled. Mesa defines the symbol MESA, but nothing in its published headers (xmesaP.h is the unpublished header) tells how DITHER666 was set at compile time. Note says 5x9x5 better for general colors, 6x6x6 better for grayscale (but why would you dither grayscale??). The 5x9x5 appears to be the default. xcol.red =gamma_adjust(v->RedGamma, r*65535/(_R-1),65535); xcol.green=gamma_adjust(v->GreenGamma, g*65535/(_G-1),65535); xcol.blue =gamma_adjust(v->BlueGamma, b*65535/(_B-1),65535); noFaultXAllocColor(v->display, cmap, v->visinfo->colormap_size, &xcol, &exact, &alloced); (Note that Mesa allocates these in order, which means that when the table fills up, all the colors it's missing lie at one end.) /* * Apply gamma correction to an intensity value in [0..max]. Return the * new intensity value. */ static GLint gamma_adjust( GLfloat gamma, GLint value, GLint max ) { double x = (double) value / (double) max; return (GLint) ((GLfloat) max * pow( x, 1.0F/gamma ) ); } Where gamma (defaults to 1.0) is separately set for RGB in the MESA_GAMMA environment variable. My guess in general is that OpenGL is not going to work very well unless the X server has true color. In pseudocolor, there is no way to make GLX work together with any other clients. In particular, it is apparently impossible to figure out what colors a GL window has allocated in order to use them in non-GL windows. The best color policy is probably to allocate a few colors -- the standard colors -- in the colormap before giving the window to GL. Note that the 8 standard colors are always on the list requested by Mesa's cubes, so Mesa will need either 217 or 208 colors to get its full set. In practice, if you were using Mesa, you could easily allocate the identical colormap for your own use, in effect reusing Mesa's colors. ------------------------------------------------------------------------ Non-Mesa GLX problems: ---------------------- Note that the GL header files may be the Mesa headers, even when the library actually linked is not Mesa. (This is true for, e.g., Redhat Linux when you use a hardware accelerated libGL, such as the one from NVidia.) The only non-standard call is glXCreateGLXPixmapMESA, and the glconfig.sh script should properly sort out whether this API really exists or not. The bottom line is, you can probably compile with any GL headers, even if they do not correspond to the library you will link against. Nevertheless, caveat compilor. When using a true GLX implementation, glXChooseVisual may well return a visual different from the default visual for your screen. If that happens, the XCreateWindow call to make the GL window *must* set the colormap to one created for the GL visual. Not setting any colormap, or using a colormap from a different visual, results in a BadMatch error during XCreateWindow, and bizarre behavior thereafter. For XFree86 4.0 at least, "bizarre" ranges from SIGSEGV when you attempt to make the window the current GL device, to blank windows, to windows with incorrect colors. This behavior depends on the server as well as the libGL, so a single executable will behave very differently when displaying to different X servers. yorick-gl-1.1+cvs20070922+dfsg.orig/cntrfunc.i0000640000175000017500000005176010313362477020437 0ustar thibautthibaut/* * $Id: cntrfunc.i,v 1.1.1.1 2005/09/18 22:07:59 dhmunro Exp $ * This file connects yorick to the compiled functions in * the OpenGL based 3D graphics package. */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ if (!is_void(plug_in)) plug_in, "yorgl"; /* set default chunk size for iso-surface and slice plane generation */ CHKSIZ= [20,16,10]; extern MakeSliceTreeCrv; /* xxDOCUMENT MakeSliceTreeCrv(xyz, tree) Build an octree for use in extracting slicing planes from an ijk grid. tree holds the size of the overall grid, the size of the chunk to process on this call, and the point where the chunk starts within the larger array. array. xyz is the coordinates of the grid points. The octree is returned in tree. */ /* PROTOTYPE int ycMakeSliceTreeCrv(double array xyz, pointer tree) */ extern SliceTreeCrv; /* xxDOCUMENT SliceTreeCrv(point, normal, xyz, var, triangles, tree) Compute a slicing plane on an ijk grid using a pre-computed octree. tree holds the size of the overall grid, the size of the chunk to process on this call, and the point where the chunk starts within the larger array. array. xyz is the coordinates of the grid points. var is an optional point centered variable to be interpolated to the vertices on the slicing plane. point lies on the slicing plane and normal is perpendicular to the plane. triangles is a struct with space in which to return the result. Makes a triangle array. */ /* PROTOTYPE int ycSliceTreeCrv(double array point, double array normal, double array xyz, pointer var, pointer triangles, pointer tree) */ extern SliceTree; /* xxDOCUMENT SliceTree(maxdepth, sizes, chunk, start, point, normal, deltas, origin, var2, triangles) Compute a slicing plane on a regular grid using bisection to efficiently find the cells cut by the plane. The number of bisections is maxdepth. The full grid has dimensions sizes=[nx,ny,nz]. This call handles chunk vertices and the chunk starts at location start in the full grid. deltas is the size of a zone and origin is the coordinate of the first point. point lies on the slicing plane and normal is perpendicular to the plane. var2 (if not null) is an auxiliary variable whose value is returned at each vertex of the slice plane. triangles is a struct with space in which to return the result. Makes a triangle array. */ /* PROTOTYPE int ycSliceTree(long maxdepth, long array sizes, long array chunk, long array start, double array point, double array normal, double array deltas, double array origin, pointer var2, pointer triangles) */ extern MakeContourTree; /* xxDOCUMENT MakeContourTree(var, tree) Build an octree for use in extracting iso-surfaces from a regular grid. tree holds the size of the overall grid, the size of the chunk to process on this call, and the point where the chunk starts within the larger array. array. var has cell centered values. The octree is returned in tree. */ /* PROTOTYPE int ycMakeContourTree(double array var, pointer tree) */ extern ContourTree; /* xxDOCUMENT ContourTree(deltas, origin, level, var, triangles, tree) Compute an iso-surface at the specified level on a regular grid using a pre-computed octree. tree holds the size of the overall grid, the size of the chunk to process on this call, and the point where the chunk starts within the larger array. array. var has cell centered values. level is the contour level and var is the array to contour. triangles is a struct with space in which to return the result. Makes a triangle array. */ /* PROTOTYPE int ycContourTree(double array deltas, double array origin, double level, double array var, pointer triangles, pointer tree) */ extern ContourTree2; /* xxDOCUMENT ContourTree2(deltas, origin, level, var, var2, triangles, tree) Compute an iso-surface at the specified level on a regular grid using a pre-computed octree. var2 is interpolated to the vertices of the iso-surface. tree holds the size of the overall grid, the size of the chunk to process on this call, and the point where the chunk starts within the larger array. array. var has cell centered values. level is the contour level and var is the array to contour. triangles is a struct with space in which to return the result. Makes a triangle array. */ /* PROTOTYPE int ycContourTree2(double array deltas, double array origin, double level, double array var, pointer var2, pointer triangles, pointer tree) */ extern ContourTreeCrv; /* xxDOCUMENT ContourTreeCrv(level, xyz, var, triangles, tree) Compute an iso-surface at the specified level on an ijk grid using a pre-computed octree. tree holds the size of the overall grid, the size of the chunk to process on this call, and the point where the chunk starts within the larger array. array. var has cell centered values. level is the contour level and var is the array to contour. triangles is a struct with space in which to return the result. Makes a triangle array. */ /* PROTOTYPE int ycContourTreeCrv(double level, double array xyz, double array var, pointer triangles, pointer tree) */ extern ContourTreeCrv2; /* xxDOCUMENT ContourTreeCrv2(level, xyz, var, var2, triangles, tree) Compute an iso-surface at the specified level on an ijk grid using a pre-computed octree. var2 is interpolated to the vertices of the iso-surface. tree holds the size of the overall grid, the size of the chunk to process on this call, and the point where the chunk starts within the larger array. array. var has cell centered values. level is the contour level and var is the array to contour. triangles is a struct with space in which to return the result. Makes a triangle array. */ /* PROTOTYPE int ycContourTreeCrv2(double level, double array xyz, double array var, pointer var2, pointer triangles, pointer tree) */ extern ContourInitCartPcen; /* xxDOCUMENT ContourInitCartPcen(sizes, offsets, deltas, origin, var, var2) Prepare to compute an iso-surface at the specified level on a regular grid. The grid does NOT include any guard cells. var has point centered values. var2 is an auxiliary point centered variable that is the same size as var. sizes is the size of the chunk to be processed including the ghost points on both sides. offsets has 5 elements. The first three are the i, j, and k of the first real cell in this chunk of the grid relative to the global grid. They are 1-based, so they must be adjusted before use in C. The fourth, fifth, and sixth are the numbers of cells in the i, j, and k directions in the global grid. */ /* PROTOTYPE int ycInitCartPcen(long array sizes, long array offsets, double array deltas, double array origin, double array var, pointer var2) */ extern ContourInitCartGrdPcen; /* xxDOCUMENT ContourInitCartGrdPcen(sizes, offsets, deltas, origin, var, var2) Prepare to compute an iso-surface at the specified level on a regular grid. var has point centered values. var2 is an auxiliary point centered variable that is the same size as var. sizes is the size of the chunk to be processed including the ghost points on both sides. offsets has 5 elements. The first three are the i, j, and k of the first real cell in this chunk of the grid relative to the global grid. They are 1-based, so they must be adjusted before use in C. The fourth, fifth, and sixth are the numbers of cells in the i, j, and k directions in the global grid. */ /* PROTOTYPE int ycInitCartGrdPcen(long array sizes, long array offsets, double array deltas, double array origin, double array var, pointer var2) */ extern ContourInitCartZcen; /* xxDOCUMENT ContourInitCartZcen(offsets, deltas, origin, var, var2) Prepare to compute an iso-surface at the specified level on a regular grid. var has zone centered values. var2 is an auxiliary zone centered variable that is the same size as var. sizes is the size of the chunk to be processed including the ghost points on both sides. offsets has 5 elements. The first three are the i, j, and k of the first real cell in this chunk of the grid relative to the global grid. They are 1-based, so they must be adjusted before use in C. The fourth, fifth, and sixth arguemnts are the numbers of cells in the i, j, and k directions in the global grid. */ /* PROTOTYPE int ycInitCartZcen(long array sizes, long array offsets, double array deltas, double array origin, double array var, pointer var2) */ extern ContourInitCartGrdZcen; /* xxDOCUMENT ContourInitCartGrdZcen(offsets, deltas, origin, var, var2) Prepare to compute an iso-surface at the specified level on a regular grid. var has zone centered values. var2 is an auxiliary zone centered variable that is the same size as var. sizes is the size of the chunk to be processed including the ghost points on both sides. offsets has 5 elements. The first three are the i, j, and k of the first real cell in this chunk of the grid relative to the global grid. They are 1-based, so they must be adjusted before use in C. The fourth, fifth, and sixth arguments are the numbers of cells in the i, j, and k directions in the global grid. */ /* PROTOTYPE int ycInitCartGrdZcen(long array sizes, long array offsets, double array deltas, double array origin, double array var, pointer var2) */ extern ContourInitCartGrdPcenNdx; /* xxDOCUMENT ContourInitCartGrdPcenNdx(sizes, offsets, deltas, origin, var, var2) Prepare to compute an iso-surface at the specified level on a regular grid. var has point centered values. var2 is an auxiliary point centered variable that is the same size as var. sizes is the size of the chunk to be processed including the ghost points on both sides. offsets has 5 elements. The first three are the i, j, and k of the first real cell in this chunk of the grid relative to the global grid. They are 1-based, so they must be adjusted before use in C. The fourth, fifth, and sixth arguments are the numbers of cells in the i, j, and k directions in the global grid. The output triangles are specified by indices into vectors of coordinates, gradients, and auxiliary variables. */ /* PROTOTYPE int ycInitCartGrdPcenNdx(long array sizes, long array offsets, double array deltas, double array origin, double array var, pointer var2) */ extern ContourInitCartGrdZcenNdx; /* xxDOCUMENT ContourInitCartGrdZcenNdx(sizes, offsets, deltas, origin, var, var2) Prepare to compute an iso-surface at the specified level on a regular grid. var has zone centered values. var2 is an auxiliary zone centered variable that is the same size as var. sizes is the size of the chunk to be processed including the ghost points on both sides. offsets has 5 elements. The first three are the i, j, and k of the first real cell in this chunk of the grid relative to the global grid. They are 1-based, so they must be adjusted before use in C. The fourth, fifth, and sixth arguments are the numbers of cells in the i, j, and k directions in the global grid. xyz is the grid. The output triangles are specified by indices into vectors of coordinates, gradients, and auxiliary variables. */ /* PROTOTYPE int ycInitCartGrdZcenNdx(long array sizes, long array offsets, double array deltas, double array origin, double array var, pointer var2) */ extern ContourInitCrvGrdPcen; /* xxDOCUMENT ContourInitCrvGrdPcen(sizes, offsets, xyz, var, var2) Prepare to compute an iso-surface at the specified level on a curvi-linear grid. var has point centered values. var2 is an auxiliary point centered variable that is the same size as var. sizes is the size of the chunk to be processed including the ghost points on both sides. offsets has 5 elements. The first three are the i, j, and k of the first point in this chunk of the grid relative to the global grid. They are 1-based, so they must be adjusted before use in C. The fourth, fifth, and sixth arguments are the numbers of cells in the i, j, and k directions in the global grid. xyz is the grid. */ /* PROTOTYPE int ycInitCrvGrdPcen(long array sizes, long array offsets, double array xyz, double array var, pointer var2) */ extern ContourInitCrvGrdZcen; /* xxDOCUMENT ContourInitCrvGrdZcen(sizes, offsets, xyzn, var, var2) Prepare to compute an iso-surface at the specified level on a curvi-linear grid. var has zone centered values. var2 is an auxiliary zone centered variable that is the same size as var. sizes is the size of the chunk to be processed including the ghost points on both sides. offsets has 5 elements. The first three are the i, j, and k of the first point in this chunk of the grid relative to the global grid. They are 1-based, so they must be adjusted before use in C. The fourth, fifth, and sixth arguments are the numbers of cells in the i, j, and k directions in the global grid. xyz is the grid. */ /* PROTOTYPE int ycInitCrvGrdZcen(long array sizes, long array offsets, double array xyz, double array var, pointer var2) */ extern ContourInitCrvGrdPcenNdx; /* xxDOCUMENT ContourInitCrvGrdPcenNdx(sizes, offsets, xyz, var, var2) Prepare to compute an iso-surface at the specified level on a curvi-linear grid. var has point centered values. var2 is an auxiliary point centered variable that is the same size as var. sizes is the size of the chunk to be processed including the ghost points on both sides. offsets has 5 elements. The first three are the i, j, and k of the first point in this chunk of the grid relative to the global grid. They are 1-based, so they must be adjusted before use in C. The fourth, fifth, and sixth arguments are the numbers of cells in the i, j, and k directions in the global grid. xyz is the grid. The output triangles are specified by indices into vectors of coordinates, gradients, and auxiliary variables. */ /* PROTOTYPE int ycInitCrvGrdPcenNdx(long array sizes, long array offsets, double array xyz, double array var, pointer var2) */ extern ContourInitCrvGrdZcenNdx; /* xxDOCUMENT ContourInitCrvGrdZcenNdx(sizes, offsets, xyz, var, var2) Prepare to compute an iso-surface at the specified level on a curvi-linear grid. var has zone centered values. var2 is an auxiliary zone centered variable that is the same size as var. sizes is the size of the chunk to be processed including the ghost points on both sides. offsets has 5 elements. The first three are the i, j, and k of the first point in this chunk of the grid relative to the global grid. They are 1-based, so they must be adjusted before use in C. The fourth, fifth, and sixth arguments are the numbers of cells in the i, j, and k directions in the global grid. xyz is the grid. The output triangles are specified by indices into vectors of coordinates, gradients, and auxiliary variables. */ /* PROTOTYPE int ycInitCrvGrdZcenNdx(long array sizes, long array offsets, double array xyz, double array var, pointer var2) */ extern ContourTetHex; /* xxDOCUMENT ContourTetHex(level, ifirst, nzone, xyz, grad, hexndx, var, var2, triangles) compute an iso-surface at the specified level on an arbitrarily connected grid of hexahedra. xyz, grad, and var are coordinates, gradients, and variable values at the points making up the grid. var2 is an optional auxiliary variable that is the same size as var. hexndx has 8 indices into xyz etc. for each hex making up the grid. level is the contour level. triangles is a struct with space in which to return the result. */ /* PROTOTYPE int ycContourTetHex(double level, long ifirst, long nzone, double array xyz, double array grad, long array hexndx, double array var, pointer var2, pointer triangles) */ extern ContourTreeVarr; /* xxDOCUMENT ContourTreeVarr(deltas, origin, level, var, triangles, tree) compute an iso-surface at the specified level on a regular grid. level is the contour level and var is the array to contour. var has cell centered values. triangles is a struct with space in which to return the result. tree contains a pre-computed octtree to be used in computing the iso-surface. The tree structure holds several pieces of information about the grid etc. A triangle is specified by 3 indices into a list of the unique vertices on the iso-surface which is stored in triangles. */ /* PROTOTYPE int ycContourTreeVarr(double array deltas, double array origin, double level, double array var, pointer triangles, pointer tree, long array edgndx) */ extern ContourTreeVarr2; /* xxDOCUMENT ContourTreeVarr2(deltas, origin, level, var, var2, triangles, tree) compute an iso-surface at the specified level on a regular grid. level is the contour level and var is the array to contour. var has cell centered values. triangles is a struct with space in which to return the result. tree contains a pre-computed octtree to be used in computing the iso-surface. The tree structure holds several pieces of information about the grid etc. A triangle is specified by 3 indices into a list of the unique vertices on the iso-surface which is stored in triangles. var2 is a second variable that will be interpolated to the vertices of the iso-surface (if var2 is non-zero). */ /* PROTOTYPE int ycContourTreeVarr2(double array deltas, double array origin, double level, double array var, pointer var2, pointer triangles, pointer tree, long array edgndx) */ extern ContourTetArray; /* xxDOCUMENT ContourTetArray(make_strip, sizes, level, var, var2, xyz, grid, flag, triangles) Compute an iso-surface at the specified level for a chunk within the full grid. A initialization routine suitable for the grid type must be called before this function for every chunk to establish the "mapping" between the full grid and the chunk. sizes is the number of points in each coordinate direction for the chunk passed in this call. There is a ghost point at both ends of each direction (included in sizes). level is the contour level and var is the array to contour. triangles is a struct with space in which to return the result. var2 is a second variable that will be interpolated to the vertices of the iso-surface (if var2 is non-zero). */ /* PROTOTYPE int ycContourTet_array(long make_strip, long array sizes, double level, double array var, double array var2, double array xyz, double array grd, char array flag, pointer triangles) */ extern ContourTetArrayNdx; /* xxDOCUMENT ContourTetArrayNdx(make_strip, sizes, level, var, var2, xyz, grid, flag, ndx, triangles) Compute an iso-surface at the specified level for a chunk within the full grid. A initialization routine suitable for the grid type must be called before this function for every chunk to establish the "mapping" between the full grid and the chunk. sizes is the number of points in each coordinate direction for the chunk passed in this call. There is a ghost point at both ends of each direction (included in sizes). level is the contour level and var is the array to contour. triangles is a struct with space in which to return the result. A triangle is specified by 3 indices in ndx. They point into a list of the unique vertices on the iso-surface which is stored in triangles. var2 is a second variable that will be interpolated to the vertices of the iso-surface (if var2 is non-zero). */ /* PROTOTYPE int ycContourTet_array_ndx(long make_strip, long array sizes, double level, double array var, double array var2, double array xyz, double array grd, char array flag, long array ndx, pointer triangles) */ extern ContourTetZone; /* xxDOCUMENT ContourTetZone(level, var, t_strips) Compute an iso-surface for a single hexahedral zone at the specified level. The result is the set of hex edges cut in the form of a (possibly more than one) tri-strip. The result is in the form of an array of IsoTriStrip. var is a 2-by-2-by-2 set of function values. level is the contour level. */ /* PROTOTYPE int ycTetIso_one_zone(double level, double array var, pointer t_strip) */ extern PrepIsoTet; /* xxDOCUMENT PrepIsoTet() Prepare the case table for iso-surfaces generated using a 6 tet decompostion of a hexahedral zone. */ /* PROTOTYPE int ycPrepIsoTet(void) */ yorick-gl-1.1+cvs20070922+dfsg.orig/glfunc.c0000640000175000017500000002373610313362465020064 0ustar thibautthibaut/* * $Id: glfunc.c,v 1.1.1.1 2005/09/18 22:07:49 dhmunro Exp $ */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #include "ydata.h" #include "glfunc.h" #include "glcode.h" #include "glBasic.h" #include "glStrips.h" #include "glMouse.h" #include "glWrappers.h" #include /* Yorick tends to work with doubles, but floats are better for OpenGL. Use floats here. */ void yglForceWin3d(void) { /* force the creation of a 3D window if none is currently open */ if(!glCurrWin3d) { yglWin3d(0, 500, 500); } } float yglGetFov3d(void) { /* Return the field of view in degrees. */ if(!glCurrWin3d) { yglForceWin3d(); } return glCurrWin3d->fov; } void yglSetFov3d(float fov) { /* require the field-of-view to be somewhat reasonable */ ASSERT(fov >= 1.0e-4 && fov <= 90.0, "gl_set_fov: field of view must be between 1.0e-4 and 90 degrees") if(!glCurrWin3d) { yglForceWin3d(); } glCurrWin3d->fov= fov; } long yglGetWidth3d(void) { /* Return the width in pixels of the OpenGL window. */ if(!glCurrWin3d) { yglForceWin3d(); } return glCurrWin3d->width; } long yglGetHite3d(void) { /* Return the height in pixels of the OpenGL window. */ if(!glCurrWin3d) { yglForceWin3d(); } return glCurrWin3d->hite; } int yglHasTex3d(void) { int res; /* Non-zero indicates that this OpenGL supports 3D textures. */ if(!glCurrWin3d) { yglForceWin3d(); } res= yglQueryTex3d(glCurrWin3d); return res; } int yglHasTexcube3d(void) { int res; /* Non-zero indicates that this OpenGL supports cube map textures. */ if(!glCurrWin3d) { yglForceWin3d(); } res= yglQueryTexCube(); return res; } void yglAlwaysShowObj3d(long flag) { /* Object will be drawn even when rotating if flag is non-zero */ if(!glCurrWin3d) { yglForceWin3d(); } if(flag) glCurrWin3d->always_show_obj= 1; else glCurrWin3d->always_show_obj= 0; } void yglUseList3d(long flag) { /* Turn on use of an OpenGL display list on if non-zero */ if(!glCurrWin3d) { yglForceWin3d(); } if(flag) glCurrWin3d->use_list= 1; else glCurrWin3d->use_list= 0; } void yglUseArray3d(long flag) { /* Turn use of OpenGL arrays on if non-zero */ if(!glCurrWin3d) { yglForceWin3d(); } if(flag) glCurrWin3d->use_array= 1; else glCurrWin3d->use_array= 0; } void yglMsmovVal3d(double val) { ASSERT(val >= 2.0 && val <= 200.0, "gl_mov_val must be between 2 and 200") ygl_ms_mov_val= val; } void yglGetBackRGB3d(double *rgb) { if(!glCurrWin3d) { yglForceWin3d(); } rgb[0]= glCurrWin3d->back_red; rgb[1]= glCurrWin3d->back_green; rgb[2]= glCurrWin3d->back_blue; } void yglBackRGB3d(double *rgb) { if(!glCurrWin3d) { yglForceWin3d(); } if(rgb[0] >= 0.0 && rgb[0] <= 1.0) glCurrWin3d->back_red= (float) rgb[0]; if(rgb[1] >= 0.0 && rgb[1] <= 1.0) glCurrWin3d->back_green= (float) rgb[1]; if(rgb[2] >= 0.0 && rgb[2] <= 1.0) glCurrWin3d->back_blue= (float) rgb[2]; } void yglBackRGBA3d(double *rgba) { if(!glCurrWin3d) { yglForceWin3d(); } if(rgba[0] >= 0.0 && rgba[0] <= 1.0) glCurrWin3d->back_red= (float) rgba[0]; if(rgba[1] >= 0.0 && rgba[1] <= 1.0) glCurrWin3d->back_green= (float) rgba[1]; if(rgba[2] >= 0.0 && rgba[2] <= 1.0) glCurrWin3d->back_blue= (float) rgba[2]; if(rgba[3] >= 0.0 && rgba[3] <= 1.0) glCurrWin3d->back_alpha= (float) rgba[3]; } void yglCageStyle3d(long style) { /* zero means no cage, negative means use data bounds, positive means use limits supplied by user in the most recent call to gl_cage_limits. */ if(!glCurrWin3d) { yglForceWin3d(); } if(style != glCurrWin3d->cage_style) { glCurrWin3d->cage_style= style; glCurrWin3d->cage_seq_num++; /* changing the cage style changes the plot */ } } void yglGetCageRGB3d(double *rgb) { if(!glCurrWin3d) { yglForceWin3d(); } rgb[0]= glCurrWin3d->cage_red; rgb[1]= glCurrWin3d->cage_green; rgb[2]= glCurrWin3d->cage_blue; } void yglCageRGB3d(double *rgb) { if(!glCurrWin3d) { yglForceWin3d(); } if(rgb[0] >= 0.0 && rgb[0] <= 1.0) glCurrWin3d->cage_red= (float) rgb[0]; if(rgb[1] >= 0.0 && rgb[1] <= 1.0) glCurrWin3d->cage_green= (float) rgb[1]; if(rgb[2] >= 0.0 && rgb[2] <= 1.0) glCurrWin3d->cage_blue= (float) rgb[2]; } void yglCageRGBA3d(double *rgba) { if(!glCurrWin3d) { yglForceWin3d(); } if(rgba[0] >= 0.0 && rgba[0] <= 1.0) glCurrWin3d->cage_red= (float) rgba[0]; if(rgba[1] >= 0.0 && rgba[1] <= 1.0) glCurrWin3d->cage_green= (float) rgba[1]; if(rgba[2] >= 0.0 && rgba[2] <= 1.0) glCurrWin3d->cage_blue= (float) rgba[2]; if(rgba[3] >= 0.0 && rgba[3] <= 1.0) glCurrWin3d->cage_alpha= (float) rgba[3]; } void yglGetGridRGB3d(double *rgb) { if(!glCurrWin3d) { yglForceWin3d(); } rgb[0]= glCurrWin3d->grid_red; rgb[1]= glCurrWin3d->grid_green; rgb[2]= glCurrWin3d->grid_blue; } void yglGridRGB3d(double *rgb) { if(!glCurrWin3d) { yglForceWin3d(); } if(rgb[0] >= 0.0 && rgb[0] <= 1.0) glCurrWin3d->grid_red= (float) rgb[0]; if(rgb[1] >= 0.0 && rgb[1] <= 1.0) glCurrWin3d->grid_green= (float) rgb[1]; if(rgb[2] >= 0.0 && rgb[2] <= 1.0) glCurrWin3d->grid_blue= (float) rgb[2]; } void yglGridRGBA3d(double *rgba) { if(!glCurrWin3d) { yglForceWin3d(); } if(rgba[0] >= 0.0 && rgba[0] <= 1.0) glCurrWin3d->grid_red= (float) rgba[0]; if(rgba[1] >= 0.0 && rgba[1] <= 1.0) glCurrWin3d->grid_green= (float) rgba[1]; if(rgba[2] >= 0.0 && rgba[2] <= 1.0) glCurrWin3d->grid_blue= (float) rgba[2]; if(rgba[3] >= 0.0 && rgba[3] <= 1.0) glCurrWin3d->grid_alpha= (float) rgba[3]; } void yglGetCageLimits3d(double *lims) { if(!glCurrWin3d) { yglForceWin3d(); } lims[0]= glCurrWin3d->cage_xmin; lims[1]= glCurrWin3d->cage_xmax; lims[2]= glCurrWin3d->cage_ymin; lims[3]= glCurrWin3d->cage_ymax; lims[4]= glCurrWin3d->cage_zmin; lims[5]= glCurrWin3d->cage_zmax; } void yglCageLimits3d(double *lims) { if(!glCurrWin3d) { yglForceWin3d(); } if(lims[0] <= lims[1]) { glCurrWin3d->cage_xmin= (float)lims[0]; glCurrWin3d->cage_xmax= (float)lims[1]; } else { glCurrWin3d->cage_xmin= (float)lims[1]; glCurrWin3d->cage_xmax= (float)lims[0]; } if(lims[2] <= lims[3]) { glCurrWin3d->cage_ymin= (float)lims[2]; glCurrWin3d->cage_ymax= (float)lims[3]; } else { glCurrWin3d->cage_ymin= (float)lims[3]; glCurrWin3d->cage_ymax= (float)lims[2]; } if(lims[4] <= lims[5]) { glCurrWin3d->cage_zmin= (float)lims[4]; glCurrWin3d->cage_zmax= (float)lims[5]; } else { glCurrWin3d->cage_zmin= (float)lims[5]; glCurrWin3d->cage_zmax= (float)lims[4]; } /* increase the sequence number so that this change will be reflected in the next plot (only if active) */ if(glCurrWin3d->cage_style > 0) glCurrWin3d->cage_seq_num++; } void yglLookat3d(double *eye, double *center, double *up) { double dot, len; if(!glCurrWin3d) { yglForceWin3d(); } glCurrWin3d->eye[0]= eye[0]; glCurrWin3d->eye[1]= eye[1]; glCurrWin3d->eye[2]= eye[2]; glCurrWin3d->center[0]= center[0]; glCurrWin3d->center[1]= center[1]; glCurrWin3d->center[2]= center[2]; /* compute the unit view vector and viewing distance */ glCurrWin3d->view[0]= glCurrWin3d->eye[0]-glCurrWin3d->center[0]; glCurrWin3d->view[1]= glCurrWin3d->eye[1]-glCurrWin3d->center[1]; glCurrWin3d->view[2]= glCurrWin3d->eye[2]-glCurrWin3d->center[2]; glCurrWin3d->viewdist= sqrt(glCurrWin3d->view[0]*glCurrWin3d->view[0] +glCurrWin3d->view[1]*glCurrWin3d->view[1] +glCurrWin3d->view[2]*glCurrWin3d->view[2]); glCurrWin3d->view[0] /= glCurrWin3d->viewdist; glCurrWin3d->view[1] /= glCurrWin3d->viewdist; glCurrWin3d->view[2] /= glCurrWin3d->viewdist; /* force the up vector to have unit length and be normal to the viewing direction. */ dot= up[0]*glCurrWin3d->view[0]+up[1]*glCurrWin3d->view[1]+up[2]*glCurrWin3d->view[2]; glCurrWin3d->up[0]= up[0]-dot*glCurrWin3d->view[0]; glCurrWin3d->up[1]= up[1]-dot*glCurrWin3d->view[1]; glCurrWin3d->up[2]= up[2]-dot*glCurrWin3d->view[2]; len= sqrt(glCurrWin3d->up[0]*glCurrWin3d->up[0]+glCurrWin3d->up[1]*glCurrWin3d->up[1]+ glCurrWin3d->up[2]*glCurrWin3d->up[2]); if(len < 1.0e-4) { /* a bad up vector was supplied - an impossible error if the interpreted wrapper function was called. Try a "random" direction. */ glCurrWin3d->up[0]= 0.5; glCurrWin3d->up[1]= 1.0/sqrt(2.0); glCurrWin3d->up[2]= 0.5; } else { glCurrWin3d->up[0] /= len; glCurrWin3d->up[1] /= len; glCurrWin3d->up[2] /= len; } } int yglUpdateList3d(void) { /* Return a flag indicating whether objects need to be added to the OpenGL display list. */ if(!glCurrWin3d) { yglForceWin3d(); } return (glCurrWin3d->seq_num > glCurrWin3d->list_num); } void yglIncSeq3d(void) { if(!glCurrWin3d) { yglForceWin3d(); } glCurrWin3d->seq_num++; } void yglArsum3d(long nx0, long ny0, long nz0, long nsx, long nsy, long nsz, double *vin, double *vout) { long nxout, nyout, nzout, i, j, k, iout, jout, kout, ndin, ndout; /* sum up nsx-by-nsy-by-nsz zone chunks of vin and store the result in vout. This function thus makes an integral preserving, lower resolution version of the input array. If the caller wants a smoothed version of vin, he/she should divide vout by nsx*nsy*nsz. */ nxout= nx0/nsx; nyout= ny0/nsy; nzout= nz0/nsz; /* clear the output array */ for(k= 0; k < nzout; k++) { for(j= 0; j < nyout; j++) { for(i= 0; i < nxout; i++) { ndout= i/nsx+j/nsy*nxout+k/nsz*nxout*nyout; vout[ndout]= 0.0; } } } /* the following nested loops sums the input array in memory order into the output array. */ for(k= 0; k < nz0; k++) { for(j= 0; j < ny0; j++) { for(i= 0; i < nx0; i++) { iout= i/nsx; jout= j/nsy; kout= k/nsz; ndout= iout+jout*nxout+kout*nxout*nyout; ndin= i+j*nx0+k*nx0*ny0; vout[ndout] += vin[ndin]; } } } } yorick-gl-1.1+cvs20070922+dfsg.orig/glprofile.i0000640000175000017500000003137510313362466020576 0ustar thibautthibaut/* * $Id: glprofile.i,v 1.1.1.1 2005/09/18 22:07:50 dhmunro Exp $ * run this file to generate profiling information for the OpenGL * based 3D graphics package in yorick */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ require, "dlist3d.i" use_interleave= 0; require, "contour.i"; palette3d, "earth.gp"; // gl_win_size,1024,820; /* width,height */ n_pass= 5; func mak_slicecrv(ngrid) { extern tree; extern gl_rr,gl_gg,gl_bb, gl_ncolr, gl_ctab; extern tot_slice_tri; normal= [1.0, 0.0, 0.0]; point0= [0.0, 0.0, 0.0]; if(is_void(ngrid) || ngrid < 6) { nx= test3d_n(1); ny= test3d_n(2); nz= test3d_n(3); } else { nx= ngrid; ny= ngrid; nz= ngrid; } npts= 20; xyz= array(0.0, 3, nx,ny,nz); xyz(1,..)= span(-1,1,nx); xyz(2,..)= span(-1,1,nx)(-,); xyz(3,..)= span(-1,1,nx)(-,-,); /* Now rotate each plane by phi degrees around the z-axis relative to the one below it. */ phi= 0.5*pi/(nz-1.0); snph= sin(phi); csph= cos(phi); for(i= 2; i <= nz; i++) { xyz(1,,,i)= csph*xyz(1,,,i-1)-snph*xyz(2,,,i-1); xyz(2,,,i)= snph*xyz(1,,,i-1)+csph*xyz(2,,,i-1); } r= abs(xyz(1,..),xyz(2,..),xyz(3,..)); theta= acos(xyz(3,..)/(r+!r)); phi= atan(xyz(2,..),xyz(1,..)+(!r)); y32= sin(theta)^2*cos(theta)*cos(2*phi); f= r*(1.+y32); /* point centered */ r= theta= phi= []; xyzmin= min(xyz); xyzmax= max(xyz) sizes= (dimsof(f))(2:4); vcen= f(zcen,zcen,zcen); varmax= max(vcen); varfac= gl_ncolr/varmax; /* start the slice plane at the back, sweep through to the middle, rotate it 180 degrees, and sweep to the front. */ posns1= span(xyzmin, 0, npts); posns2= span(0, xyzmax, npts); norms= array(0.0, 3, npts); norms(1,)= cos(span(0.0, pi, npts)); norms(2,)= sin(span(0.0, pi, npts)); norms(3,)= 0.0; write, " test uses "+pr1((nx-1)*(ny-1)*(nz-1))+" cells"; slice_tim= colr_tim= 0.0; tstart= tfin= array(0.0, 3); timer, tstart; tree= mak_slice_treecrv(xyz,guard=0); timer,tfin; tree_tim= (tfin-tstart)(3); tris_sav= array(pointer, 3*npts); tris_sav(*)= &[]; tot_tri= 0; /* NOTE: the input array is assumed to include a layer of guard cells on all sides. This means that the volume being contoured is a bit less than -1 to 1. */ for(jj= 1; jj <= npts; jj++) { timer, tstart; point= point0+posns1(jj)*normal; tris= slice_treecrv(xyz,point,normal,tree); timer,tfin; slice_tim += (tfin-tstart)(3); timer, tstart; if(tris) { if(!tris_sav(jj)) { tris_sav(jj)= &tris; } else { tris.next= tris_sav(jj); tris_sav(jj)= &tris; } triptr= tris_sav(jj); while(1) { if(!triptr) break; if(is_void(*triptr)) break; ntri= triptr->numTri; tot_tri += ntri; if(ntri) { /* one color per triangle based on cellID */ colr= map2color(ntri, *(triptr->cellIDs), vcen, vmin=0.0, vmax=varmax); triptr->colors= &colr; } triptr= triptr->next; } ; timer, tfin; colr_tim += (tfin-tstart)(3); } } for(jj= 1; jj <= npts; jj++) { timer, tstart; tris= slice_treecrv(xyz,point0,norms(,jj),tree); timer,tfin; slice_tim += (tfin-tstart)(3); jp= jj+npts; timer, tstart; if(tris) { if(!tris_sav(jp)) { tris_sav(jp)= &tris; } else { tris.next= tris_sav(jp); tris_sav(jp)= &tris; } triptr= tris_sav(jp); while(1) { if(!triptr) break; if(is_void(*triptr)) break; ntri= triptr->numTri; tot_tri += ntri; if(ntri) { /* one color per triangle based on cellID */ colr= map2color(ntri, *(triptr->cellIDs), vcen, vmin=0.0, vmax=varmax); triptr->colors= &colr; } triptr= triptr->next; } ; timer, tfin; colr_tim += (tfin-tstart)(3); } } for(jj= 1; jj <= npts; jj++) { timer, tstart; point= point0+posns2(jj)*normal; tris= slice_treecrv(xyz,point,normal,tree); timer,tfin; slice_tim += (tfin-tstart)(3); timer, tstart; jp= jj+2*npts; if(tris) { if(!tris_sav(jp)) { tris_sav(jp)= &tris; } else { tris.next= tris_sav(jp); tris_sav(jp)= &tris; } triptr= tris_sav(jp); while(1) { if(!triptr) break; if(is_void(*triptr)) break; ntri= triptr->numTri; tot_tri += ntri; if(ntri) { /* one color per triangle based on cellID */ colr= map2color(ntri, *(triptr->cellIDs), vcen, vmin=0.0, vmax=varmax); triptr->colors= &colr; } triptr= triptr->next; } ; timer, tfin; colr_tim += (tfin-tstart)(3); } } write,"Slice planes computed using an Octree"; write,"Grid is ", nx, "by", ny, "by", nz; write,"positions range from ",xyzmin," to ",xyzmax; write,"time to build octree is ",tree_tim; write,"time to extract extract plane is ",slice_tim; write,"time to compute colors is ",colr_tim; write,"number of triangles for all frames is ",tot_tri; write,"Storage for results is roughly ",8*(3*3+3*3+3)*tot_tri," bytes"; tot_slice_tri= tot_tri; return tris_sav; } func slicecrv_movie(tris_sav) { extern tot_slice_tri, n_pass; palette3d,"stern.gp"; normal= [1.0, 0.0, 0.0]; lookat3d,2.9*normal,[0.0,0.0,0.0],[0.0,0.0,1.0]; list_tim= draw_tim= 0.0; tstart= tfin= array(0.0, 3); /* Draw all slice planes */ nplanes= numberof(tris_sav); for(ii= 1; ii <= n_pass; ii++) { for(jj= 1; jj <= nplanes; jj++) { triptr= tris_sav(jj); tris= *triptr; timer,tstart; clear3d; /* draw all tri arrays in the lists */ if(tris) { res= pltrilists3d(tris,emit=1); } timer,tfin; list_tim += (tfin-tstart)(3); timer, tstart; draw3d, !making_movie; timer, tfin; draw_tim += (tfin-tstart)(3); } } write,"number of passes is ",n_pass; write,"time to draw slicing plane is ", draw_tim; write,"time to build display list is ",list_tim; write,"frames per second is",n_pass*nplanes/(draw_tim+list_tim); write,"triangles per second is ",n_pass*tot_slice_tri/(draw_tim+list_tim); write,"triangle rendering rate is ",n_pass*tot_slice_tri/draw_tim; } func mak_isos(ngrid) { extern tot_iso_tri, do_collapse; if(is_void(ngrid) || ngrid < 6) { nx= test3d_n(1); ny= test3d_n(2); nz= test3d_n(3); } else { nx= ngrid; ny= ngrid; nz= ngrid; } nlev= 40; iso_lo= 0.1; iso_hi= 1.0; xyz= array(0.0, 3, nx,ny,nz); xyz(1,..)= span(-1,1,nx); xyz(2,..)= span(-1,1,nx)(-,); xyz(3,..)= span(-1,1,nx)(-,-,); r= abs(xyz(1,..),xyz(2,..),xyz(3,..)); theta= acos(xyz(3,..)/(r+!r)); phi= atan(xyz(2,..),xyz(1,..)+(!r)); y32= sin(theta)^2*cos(theta)*cos(2*phi); f= r*(1.+y32); /* point centered */ r= theta= phi= []; origin= [-1.0, -1.0, -1.0]; delta= [2.0/(nx-1.0), 2.0/(ny-1.0), 2.0/(nz-1.0)]; colr= [0.0,1.0,0.2]; levels= span(iso_lo, iso_hi, nlev); tstart= tfin= array(0.0, 3); timer, tstart; tree= mak_isotree(f); timer,tfin; tree_tim= (tfin-tstart)(3); iso_tim= append_tim= 0.0; tris_sav= array(pointer, nlev); tris_sav(*)= &[]; tot_tri= 0; /* NOTE: the input array is assumed to include a layer of guard cells on all sides. This means that the volume being contoured is a bit less than -1 to 1. */ for(jj= 1; jj <= nlev; jj++) { timer, tstart; tris= iso3_tree(origin,delta,f,levels(jj),colr,tree); timer,tfin; iso_tim += (tfin-tstart)(3); timer, tstart; if(tris) { if(!tris_sav(jj)) { tris_sav(jj)= &tris; } else { tris.next= tris_sav(jj); tris_sav(jj)= &tris; } triptr= tris_sav(jj); while(1) { if(!triptr) break; if(is_void(*triptr)) break; ntri= triptr->numTri; tot_tri += ntri; triptr= triptr->next; } ; } if(do_collapse) { /* collapse into a single triangle array if requested */ newtris= &tris; num= SizeTriArrays3d(tris_sav(jj)); newtris= TriArrayGrp( numTri= 0, cellIDs= &array(0, num), xyzverts= &array(0.0, 3, 3, num), normals= &array(0.0, 3, 3, num), colors= &array(float, 3, num), var2= &nulvar, triEdg= &nulvar, triStart= &nulvar, nTris= &nulvar, next= &nulvar ); if(tris_sav(jj)->var2) newtris.var2= &array(0.0, 3, num); CollapseTriArrays3d, -3, tris_sav(jj), &newtris; tris_sav(jj)= &newtris; } timer, tfin; append_tim += (tfin-tstart)(3); } write,"Iso-surfaces computed using an Octree"; write,"Grid is ", nx, "by", ny, "by", nz; write,"number of iso-levels is ",nlev; write,"iso-levels range from ",iso_lo," to ",iso_hi; write,"time to append is ",append_tim; write,"time to extract iso-surfaces is ",iso_tim; write,"number of triangles for all frames is ",tot_tri; write,"Storage for results is roughly ",8*(3*3+3*3+3)*tot_tri," bytes"; tot_iso_tri= tot_tri; return tris_sav; } func isotree_movie(tris_sav) { extern tot_iso_tri, n_pass; nlev= numberof(tris_sav); tstart= tfin= array(0.0, 3); list_tim= draw_tim= clr_tim= 0.0; lookat3d,[2.2,-0.03,-0.22],[0.0,-0.03,-0.22],[0.0,0.0,1.0]; /* Draw all iso-surfaces */ for(ii= 1; ii <= n_pass; ii++) { for(jj= 1; jj <= nlev; jj++) { triptr= tris_sav(jj); tris= *triptr; timer,tstart; clear3d; timer,tfin; clr_tim += (tfin-tstart)(3); timer,tstart; /* draw all tri arrays in the lists */ if(tris) { res= pltrilists3d(tris); } timer,tfin; list_tim += (tfin-tstart)(3); timer, tstart; draw3d, !making_movie; timer, tfin; draw_tim += (tfin-tstart)(3); } } write,"number of passes is ",n_pass; write,"time to draw slicing plane is ", draw_tim; write,"time to build display list is ",list_tim; write,"time to clear screen is ",clr_tim; write,"frames per second is",n_pass*nlev/(draw_tim+list_tim); write,"triangles per second is ",n_pass*tot_iso_tri/(draw_tim+list_tim); write,"triangle rendering rate is ",n_pass*tot_iso_tri/draw_tim; } func runprof(size) { extern make_strip; if(is_void(size)) size= 32; make_strip= 0; // rotate each scene the same number of times num_rotn= 12; "sho_isoreg: iso-surface on regular grid"; sho_isoreg,size do_rot,num_rotn; "sho_isoregzcen: iso-surface on regular grid with zone-centered data"; sho_isoregzcen,size do_rot,num_rotn; "sho_isoregndx: iso-surface on regular grid returning indices into point list"; sho_isoregndx,size do_rot,num_rotn; // "sho_isoregzcenndx: iso-surface on regular grid with zone-centered data returning indices into point list"; // sho_isoregzcenndx,size // do_rot,num_rotn; "sho_isocrv: iso-surface on curvilinear grid"; sho_isocrv,size do_rot,num_rotn; // "sho_isocrvzcen: iso-surface on curvilinear grid with zone-centered data"; // sho_isocrvzcen,size // do_rot,num_rotn; // "sho_isocrvndx: iso-surface on curvilinear grid returning indices into point list"; // sho_isocrvndx,size // do_rot,num_rotn; // "sho_isoregzcrvndx: iso-surface on curvilinear grid returning indices into point list"; // sho_isoregzcrvndx,size // do_rot,num_rotn; "sho_isohex: iso-surface on a pile of hexahedra"; sho_isohex,size do_rot,num_rotn; "sho_iso: iso-surface on a regular grid"; sho_iso,size do_rot,num_rotn; // "sho_isondx: iso-surface on a regular grid returning indices into point list"; // sho_isondx,size // do_rot,num_rotn; "sho_isotree: iso-surface on regular grid using an octtree"; sho_isotree,size; do_rot,num_rotn; "sho_drum: oscillating drum head"; drum_size= size; sho_drum; "mak_slice: slice plane and iso-surface"; mak_slice,size; do_rot,num_rotn; "mak_sphere: sphere made with quad strips"; mak_sphere,4*size,4*size; do_rot,num_rotn; "rlines: polylines"; rlines,12,1024*size; "slicecrv_movie: slicing plane on a curvilinear grid using an octtree"; slicecrv_movie,size; "slice_movie: slicing plane on a regular grid using an octtree"; slice_movie,size; "isotree_movie: iso-surface on a regular grid using an octtree"; isotree_movie,size; } // create the OpenGL window // make_3d; // sometimes it dramatically reduces performance to call this function!! system,"netstat -s |grep etra | grep -v term | grep -v TCP" /* runprof,32; */ if(is_void(ngrid)) ngrid= 60; tri_arr= mak_slicecrv(ngrid); win3d,0; slicecrv_movie,tri_arr; tri_arr= []; do_collapse= 1; tris_sav= mak_isos(ngrid); isotree_movie,tris_sav; system,"netstat -s |grep etra | grep -v term | grep -v TCP" // quit; yorick-gl-1.1+cvs20070922+dfsg.orig/TriStruct.h0000640000175000017500000000437110313362476020552 0ustar thibautthibaut/* * $Id: TriStruct.h,v 1.1.1.1 2005/09/18 22:07:58 dhmunro Exp $ * TriStruct - defines triangle array and strip structures */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #ifndef __TriStruct_h #define __TriStruct_h typedef struct yPoint3D yPoint3D; struct yPoint3D { double x; double y; double z; } ; typedef struct TriArray TriArray; struct TriArray { long numTri; long *cellIDs; yPoint3D *xyzverts; yPoint3D *normals; long nxti; long nxtj; long nxtk; TriArray *next; } ; typedef struct TriStrip TriStrip; struct TriStrip { long nVert; long nStrip; long *cellIDs; yPoint3D *xyzverts; yPoint3D *normals; long *triLen; long nxti; long nxtj; long nxtk; TriStrip *next; } ; typedef struct TriArrayGrp TriArrayGrp; struct TriArrayGrp { long numTri; long *cellIDs; yPoint3D *xyzverts; yPoint3D *normals; double *var2; float *colors; long *triEdg; long *triStart; long *nTris; TriArrayGrp *next; } ; typedef struct TriStripGrp TriStripGrp; struct TriStripGrp { long nVert; long nStrip; long *cellIDs; yPoint3D *xyzverts; yPoint3D *normals; float *colors; long *triLen; TriStripGrp *next; } ; typedef struct TriStripNdx TriStripNdx; struct TriStripNdx { long nVert; long nStrip; long *cellIDs; long *ndx; long *triLen; } ; typedef struct TriStripNdxGrp TriStripNdxGrp; struct TriStripNdxGrp { long nVert; long nStrip; long numEdg; long numTri; long *cellIDs; long *ndx; yPoint3D *xyzverts; yPoint3D *normals; float *colors; long *triLen; TriStripNdxGrp *next; } ; typedef struct TriVertexGrp TriVertexGrp; struct TriVertexGrp { long numTri; long numEdg; long *cellIDs; yPoint3D *xyzverts; yPoint3D *normals; float *colors; double *var2; long *ptndx; long *triEdg; long *triStart; long *nTris; TriVertexGrp *next; } ; typedef struct PolyArrayGrp PolyArrayGrp; struct PolyArrayGrp { long numPoly; long *edges; long *cellIDs; yPoint3D *xyzverts; yPoint3D *normals; double *var2; float *colors; long *triEdg; long *triStart; long *nVerts; PolyArrayGrp *next; } ; #endif yorick-gl-1.1+cvs20070922+dfsg.orig/glx11view.c0000640000175000017500000001130510313362472020420 0ustar thibautthibaut/* * $Id: glx11view.c,v 1.1.1.1 2005/09/18 22:07:54 dhmunro Exp $ */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #undef ONE_SIDED #include #include #include "glBasic.h" #include "glcode.h" #include "glfunc.h" #include "glMouse.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif extern void MySwapBuffers(void); #define SPHERE_LIST 1 #define DRAW_LIST 2 int have_sphere= 0; extern glWinProp *glCurrWin3d; extern glWinProp *glWin3dList[8]; /* //////////////////////////////////////////////////////////////// */ void yglPrepList(void) { if(!glCurrWin3d) return; if(glCurrWin3d->use_list) { if( (glCurrWin3d->seq_num > 0) && (glCurrWin3d->seq_num > glCurrWin3d->list_num) ) { if(glCurrWin3d->have_gl_list) glDeleteLists(glCurrWin3d->the_gl_list, 1); glCurrWin3d->have_gl_list= 0; glNewList(glCurrWin3d->the_gl_list, GL_COMPILE); } } } void yglPrepDraw(glWinProp *theWin3d) { glWinProp *res; if(!theWin3d) { char *tmp; tmp= getenv("DISPLAY"); res= yglMakWin(tmp, 500, 500, "3D window 0"); DEMAND(res, "failed to create 3D window") /* reserve an OpenGL display list for this window */ glCurrWin3d->the_gl_list = glGenLists(1); theWin3d= glCurrWin3d; glWin3dList[0]= theWin3d; } DEMAND(theWin3d, "Unable to make OpenGL window") /* Make the rendering context current */ yglMakeCurrent(theWin3d); /* Clear the window with current clearing color */ glClearColor(theWin3d->back_red, theWin3d->back_green, theWin3d->back_blue, theWin3d->back_alpha); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); #ifdef ONE_SIDED glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); #else glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); #endif } void yglFinFrame(void) { /* all drawing complete. swap the back buffer to the screen */ glFlush(); /* Swap our scene to the front */ MySwapBuffers(); /* Allow other rendering contexts to co-exist */ yglMakeCurrent(0); } void yglFinCache(void) { /* close the display list at the end of "cached" mode drawing */ if(!glCurrWin3d) return; if(glCurrWin3d->use_list) { if(!glCurrWin3d->have_gl_list) { glEndList(); glCurrWin3d->have_gl_list= 1; glCurrWin3d->list_num= glCurrWin3d->seq_num; } glCallList(glCurrWin3d->the_gl_list); } } void yglFinDirect(void) { /* nothing to do at the end of direct mode drawing */ } void yglForceDraw(void) { /* If this could be done in the "windows way" I would just post an invalidate. However, yorick does not drop into the event loop until it is completely idle, so instead call a special OnDraw() clone function. */ if(glCurrWin3d) yglDoDraw(glCurrWin3d); } void yglDoDraw(glWinProp *theWin3d) { /* Make the rendering context current This call doesn't do anything useful when printing, because the only display list that exists is tied to the on screen window. */ yglMakeCurrent(theWin3d); if(theWin3d->have_gl_list) { glCallList(theWin3d->the_gl_list); /* Flush drawing commands */ glFlush(); } /* Swap our scene to the front */ MySwapBuffers(); /* Allow other rendering contexts to co-exist */ yglMakeCurrent(0); /* clear any pending redraw requests */ /* ValidateRect(NULL); */ } void yglGetPixels(long nx, long ny, unsigned char *pix) { GLint align_old; if(!glCurrWin3d) return; /* Make the rendering context current */ yglMakeCurrent(glCurrWin3d); /* Read the screen buffer WARNING: the pixel alignment must be set properly or the call may write to bytes outside the array and give an improper phase for pixels in the array. */ glReadBuffer(GL_FRONT); glGetIntegerv(GL_PACK_ALIGNMENT,&align_old); glPixelStorei(GL_PACK_ALIGNMENT,1); glReadPixels(0, 0, nx, ny, GL_RGB, GL_UNSIGNED_BYTE, pix); glPixelStorei(GL_PACK_ALIGNMENT,align_old); } void yglPutPixels(long nx, long ny, unsigned char *pix) { if(!glCurrWin3d) return; /* Make the rendering context current */ yglMakeCurrent(glCurrWin3d); /* save coord xform */ glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0.0, (GLfloat) nx, 0.0, (GLfloat)ny, -1.0, 1.0); glMatrixMode(GL_MODELVIEW); glPushMatrix(); /* save existing modelview matrix */ glLoadIdentity(); /* position at the lower left corner and draw the pixels. */ glRasterPos2i(0, 0); glDrawPixels(nx, ny, GL_RGB, GL_UNSIGNED_BYTE, pix); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); } yorick-gl-1.1+cvs20070922+dfsg.orig/dlist3d.i0000640000175000017500000016513410313362461020155 0ustar thibautthibaut/* * $Id: dlist3d.i,v 1.1.1.1 2005/09/18 22:07:45 dhmunro Exp $ * These functions insert objects into the yorgl display, * change the viewpoint, play the display list, etc. * Users ordinarily call functions in dlist3d.i so those * functions are autoloaded by the yorgl plugin. * The compiled functions are connected via glfunc.i, so * require that glfunc.i be "pulled in" any time something in dlist3d.i * is called. */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ require,"tristruct.i"; require,"glfunc.i"; // by default do not use interleaved vertex arrays (i.e. separate vertex // arrays for xyz, normal, and color) use_interleave= 0; func draw3d(called_as_idler) /* DOCUMENT draw3d Draw the current 3D "cached" and "direct" display lists. (Ordinarily triggered automatically when the drawing changes.) */ { if (_draw3_changes) { /* draw "cached" and direct display lists */ Draw3d; _draw3_changes= []; } } func draw3d_trigger { extern _draw3_changes; /* arrange to call draw3 when everything else is finished */ set_idler, _draw3_idler; _draw3_changes= 1; } func clear3d(void) /* DOCUMENT clear3d Clear the 3D "cached" and "direct" display lists. Clear the screen. */ { ClearList3d; } func clear3d_direct(void) /* DOCUMENT clear3d_direct Clear the 3D "direct" display list. */ { ClearDirectList3d; } func clear3d_cache(void) /* DOCUMENT clear3d_cache Clear the 3D "cached" display list. */ { ClearCachedList3d; } func getback_rgb3d(void) { rgb= array(0.0, 3); getbackrgb_raw3d,rgb; return rgb; } func getcage_rgb3d(void) { rgb= array(0.0, 3); getcagergb_raw3d,rgb; return rgb; } func getgrid_rgb3d(void) { rgb= array(0.0, 3); getgridrgb_raw3d,rgb; return rgb; } func map2color(ntri, cellids, var, vmin=, vmax=) { /* map var(cellids) into RGB colors (where a color is a float triple between zero and one). */ if(is_void(vmin)) vmin= min(var); if(is_void(vmax)) vmax= max(var); colr= array(float, 3, ntri); yglMap2ColorRaw3d, gl_ncolr, gl_rr, gl_gg, gl_bb, vmin, vmax, var, ntri, cellids, colr; return colr; } func palette3d(name) /* DOCUMENT palette3d, palette_name Select a color palette to be used, for example, to color slices through 3D meshes. Uses the same palettes as the 2D graphics package. SEE ALSO: palette */ { extern gl_rr,gl_gg,gl_bb, gl_ncolr, gl_ctab; // NOTE: If name is a fully qualified path, should // try to open it and return if that fails. // Otherwise should try to find the file along the // "palette path" is_absolute= strpart(name, 1:1) == "/"; if(is_absolute) { f= open(name, "r"); } else { fnam= Y_SITE+"g/"+name; f= open(fnam, "r"); } lin= rdline(f); while(1) { lin= rdline(f); res= strmatch(lin, "ncolors="); if(res) break; } gl_ncolr= 0; sread, lin, format="ncolors=%d", gl_ncolr; while(1) { lin= rdline(f); ASSERT, (lin), "EOF in palette file without finding rgb header line"; lin2= strtok(lin); if(lin2(1) == "#") { lin2= strtok(lin2(2)); if(lin2(1) == "r") { lin2= strtok(lin2(2)); if(lin2(1) == "g") { lin2= strtok(lin2(2)); if(lin2(1) == "b") break; } } } } gl_rr= gl_gg= gl_bb= array(char, gl_ncolr); read,f,gl_rr,gl_gg,gl_bb; gl_ctab= transpose([gl_rr,gl_gg,gl_bb]); } /* ------------------------------------------------------------------------ */ func light3d(ambient=,diffuse=,specular=,spower=,sdir=) /* DOCUMENT light3d, ambient=a_level, diffuse=d_level, specular=s_level, spower=n, sdir=xyz Sets lighting properties for 3D shading effects. A surface will be shaded according to its orientation relative to the viewing direction. The ambient level A_LEVEL is a light level (arbitrary units) that is added to every surface independent of its orientation. The diffuse level D_LEVEL is a light level which is proportional to cos(theta), where theta is the angle between the surface normal and the viewing direction, so that surfaces directly facing the viewer are bright, while surfaces viewed edge on are unlit (and surfaces facing away, if drawn, are shaded as if they faced the viewer). The specular level S_LEVEL is a light level proportional to a high power spower=N of 1+cos(alpha), where alpha is the angle between the specular reflection angle and the viewing direction. The light source for the calculation of alpha lies in the direction XYZ (a 3 element vector) in the viewer's coordinate system at infinite distance. EXAMPLES: light3d, diffuse=.1, specular=1., sdir=[0,0,-1] (dramatic "tail lighting" effect) light3d, diffuse=.5, specular=1., sdir=[1,.5,1] (classic "over your right shoulder" lighting) */ { fn_name= "light3d"; if (!is_void(ambient)) { ASSERT, (dimsof(ambient)(1) = 0), "ambient light level must be scalar in "+fn_name; ambient += 0.0; } else { ambient= 0.2; } if (!is_void(diffuse)) { ASSERT, (dimsof(diffuse)(1) == 0), "diffuse light level must be a scalar"+fn_name; diffuse += 0.0; } else { diffuse= 0.6; } if (!is_void(specular)) { ASSERT, (dimsof(specular)(1) == 0), "specular strength must be a scalar in "+fn_name; specular += 0.0; } else { specular= 1.0; } if (!is_void(spower)) { ASSERT, (dimsof(spower)(1) == 0), "specular power must be a scalar in "+fn_name; spower += 0.0; } else { spower= 2.0; } if (!is_void(sdir)) { dims= dimsof(sdir); ASSERT, (dims(1) == 1 && dims(2) == 3), "lighting direction must be 3 vector in "+fn_name; sdirval= [sdir(1), sdir(2), sdir(3), 0.0]; } else { sdirval= [0.0, 0.0, 1.0, 0.0]; } set_light3d, ambient, diffuse, specular, spower, sdirval; draw3d_trigger; } /* ------------------------------------------------------------------------ */ func stdview3d(dummy) /* DOCUMENT stdview3d Sets the 3D viewing transform to a default value that makes the whole scene visible. SEE ALSO: lookat3d, prtview3d */ { box= GetBounds3d(); if(box(1,1) > box(2,1) || box(1,2) > box(2,2)|| box(1,3) > box(2,3)) { // didn't find any objects, so set default values center= [0.0,0.0,0.0]; delta= [1.0,1.0,1.0]; } else { center= box(avg,); delta= abs(box(dif,)); } /* The stdview3 function sets the viewpoint so that all objects will be visible, no matter how the scene is rotated. The field-of-view is for the width or height of the screen (not its diagonal), so sizing is done in a plane (y=0 is fine). Take the longest edge of the bounding box and construct a square of that size and the same center in the y=0 plane. Draw the circumscribing circle (it has radius sqrt(2)/2 times the longest edge). Draw a tangent line from the viewpoint to the circle using the given field-of-view. The distance from the eye to the center of interest is the radius of the circle divided by the sine of the fov. */ radius= sqrt(2.0)*0.5*max(delta); dist= radius/sin(pi/180.0*get_fov3d()); eye= center+[dist, 0.0, 0.0]; up= [0.0, 0.0, 1.0]; lookat3d,eye,center,up; } func prtview3d /* DOCUMENT prtview3d Print the parameters for the current viewing transformation. SEE ALSO: lookat3d, stdview3 */ { eye= center= up= array(0.0, 3); get_center3d,center; get_eye3d,eye; get_up3d,up; write,"[viewpoint], [center of interest], [up direction] are"; write,format="[%e,%e,%e], \n", eye(1), eye(2), eye(3); write,format="[%e,%e,%e], \n", center(1), center(2), center(3); write,format="[%f,%f,%f] \n", up(1), up(2), up(3); } func lookat3d(eye,center,up) /* DOCUMENT lookat3d(eye,center,up) Sets the 3D viewing transform so that the viewer is at "eye, the center of the view is "center", and "up" points upward. SEE ALSO: stdview3, prtview3 */ { fn_name= "lookat3d"; dim_e= dimsof(eye); ASSERT, (dim_e(1) == 1 && dim_e(2) == 3), "eye must be a 3 element vector in "+fn_name; dim_c= dimsof(center); ASSERT, (dim_c(1) == 1 && dim_c(2) == 3), "center must be a 3 element vector in "+fn_name; if (is_void(up)) { vw= eye-center; crs= [-vw(2), vw(1), 0.0]; lv= vw(rms); lc= crs(rms); if(lc < 1.0e-4*lv) { up= [0.0, 1.0, 0.0]; } else { up= [vw(2)*crs(3)-vw(3)*crs(2), vw(3)*crs(1)-vw(1)*crs(3), vw(1)*crs(2)-vw(2)*crs(1)]; } } /* lookat_raw3d will make compute an up vector that is orthonormal to the viewing direction. */ lookat_raw3d,eye,center,up; draw3d_trigger; } func get_lims3d(dummy) /* DOCUMENT get_lims3d Compute and return a bounding box containing everything in the "cached" 3D display list. */ { lim3d= array(0.0, 2, 3); res= GetBounds3d(lim3d); /* if no objects, will return an empty box */ return lim3d; } func get_normal3d(xyz, nxyz) /* DOCUMENT get_normal3d(xyz, nxyz) or get_normal3d(xyz) return 3D normals for polygons with vertices XYZ. If NXYZ is specified, XYZ should be 3-by-sum(nxyz), with NXYZ being the list of numbers of vertices for each polygon (as for the plfp function). If NXYZ is not specified, XYZ should be a quadrilateral mesh, 3-by-ni-by-nj (as for the plf function). In the first case, the return value is 3-by-numberof(NXYZ); in the second case, the return value is 3-by-(ni-1)-by-(nj-1). The normals are constructed from the cross product of the lines joining the midpoints of two edges which as nearly quarter the polygon as possible (the medians for a quadrilateral). No check is made that these not be parallel; the returned "normal" is [0,0,0] in that case. Also, if the polygon vertices are not coplanar, the "normal" has no precisely definable meaning. SEE ALSO: get_centroid3d */ { if (is_void(nxyz)) { /* if no polygon list is given, assume xyz is 2D mesh */ /* form normal as cross product of medians */ m1= xyz(,zcen,dif); m2= xyz(,dif,zcen); } else { /* with polygon list, more elaborate calculation required */ frst= nxyz(psum)-nxyz+1; /* form normal by getting two approximate diameters * (reduces to above medians for quads) */ n2= (nxyz+1)/2; zero= frst-1; c0= 0.5*(xyz(,zero+1)+xyz(,zero+2)); i= zero+n2; /* n2>=2, nxyz>=3 */ c1= 0.5*(xyz(,i)+xyz(,i+1)); i= 1+n2/2; c2= 0.5*(xyz(,zero+i)+xyz(,zero+i+1)); i= min(i+n2, nxyz); c3= 0.5*(xyz(,zero+i)+xyz(,zero+i%nxyz+1)); m1= c1 - c0; m2= c3 - c2; } /* poly normal is cross product of two medians (or diameters) */ normal= m1; normal(1,..)= n1= m1(2,..)*m2(3,..) - m1(3,..)*m2(2,..); normal(2,..)= n2= m1(3,..)*m2(1,..) - m1(1,..)*m2(3,..); normal(3,..)= n3= m1(1,..)*m2(2,..) - m1(2,..)*m2(1,..); m1= abs(n1,n2,n3)(-,..); m1= m1 + (m1==0.0); normal/= m1; return normal; } func get_centroid3d(xyz, nxyz) /* DOCUMENT get_centroid3d(xyz, nxyz) or get_centroid3d(xyz) return 3D centroids for polygons with vertices XYZ. If NXYZ is specified, XYZ should be 3-by-sum(nxyz), with NXYZ being the list of numbers of vertices for each polygon (as for the plfp function). If NXYZ is not specified, XYZ should be a quadrilateral mesh, 3-by-ni-by-nj (as for the plf function). In the first case, the return value is 3-by-numberof(NXYZ); in the second case, the return value is 3-by-(ni-1)-by-(nj-1). The centroids are constructed as the mean value of all vertices of each polygon. SEE ALSO: get_normal3d, get_light3d */ { if(is_void(xyz)) return [0.0,0.0,0.0]; if (is_void(nxyz)) { /* if no polygon list is given, assume xyz is 2D mesh */ centroid= xyz(,zcen,zcen); } else { /* with polygon list, more elaborate calculation required */ last= nxyz(psum); list= histogram(1+last)(1:-1); list(1)+= 1; list= list(psum); centroid= array(0.0, 3, numberof(nxyz)); centroid(1,)= histogram(list, xyz(1,)); centroid(2,)= histogram(list, xyz(2,)); centroid(3,)= histogram(list, xyz(3,)); centroid/= double(nxyz); } return centroid; } func plpoly3d(nv, xyz, color, norm, draw_edge=) /* DOCUMENT plpoly3d(nv, xyz, color, norm, draw_edge=) Draws a set of filled polygons in 3D using OpenGL. SEE ALSO: plcell3d, lookat3d, light3d, win3d */ { /* This function accepts a wide range of inputs and coerces them into a more restricted set that are saved in yorick's display list. This function expects xyz, color, and norm to be doubles, but should function correctly if they happen to be floats. */ fn_name= "plpoly3d"; dimsx= dimsof(xyz); ASSERT, (dimsx(1) == 2 && dimsx(2) == 3), "xyz must be a 3-by-nverts array in "+fn_name; nvert= sum(nv); npoly= numberof(nv); dimc= dimsof(color); if(dimc(1) == 1) { ASSERT, (dimc(2) == 3), "color must be a 3-by-ncolor array in "+fn_name; /* broadcast color out to all polys */ color= array(color, npoly); } else { ASSERT, (dimc(1) == 2 && dimc(2) == 3), "color must be a 3-by-ncolor array in "+fn_name; if(dimc(3) == 1) { /* broadcast color out to all polys */ color= array(color(,1), npoly); } else { ASSERT, (dimc(3) == npoly), "number of colors must be 1 or npoly in "+fn_name; } } if(typeof(color) == "char") color= float(color/255.0); /* the user can request outlined edges, not filled polygons */ do_edge= 0; if(!is_void(draw_edge) && draw_edge) do_edge= 1; /* Do not light the surface unless normals were supplied. If there are as many normals as vertices, use smooth shading */ do_light= 1; if(is_void(norm)) { do_light= 0; norm= 0; } else { dimsn= dimsof(norm); ASSERT, (dimsn(1) == 2 && dimsn(2) == 3), "norm must be a 3-by-n array in "+fn_name; /* normals must be one per poly */ if(dimsn(3) == npoly) { smooth= 0; /* normal per polygon, so use flat shading */ } else if(dimsn(3) == dimsx(3)) { /* normals must be one per vertex */ smooth= 1; /* normal per vertex, so use smooth shading */ } else { ASSERT, (0),"norm must be a 3-by-npoly or a 3-by-nvert array in "+fn_name; } } /* add the object to the display list */ polys3d, npoly, nv, xyz, norm, color, do_edge, smooth, do_light; /* increment counter so that later code knows to make a new OpenGL display list. */ inc_seq3d; draw3d_trigger; } func plcell3d(corners, color) /* DOCUMENT plcell3d(corners, color) Draws a cell array in 3D using OpenGL. SEE ALSO: plpoly3d, lookat3d, light3d, win3d */ { /* This function expects corner, color, and norm to be doubles on input, but should function correctly if they happen to be floats. No check is made for corners containing 3 co-linear points. */ fn_name= "plcell3d"; dimc= dimsof(color); ASSERT, (dimc(1) == 3), "color array must be 3-by-nx-by-ny in "+fn_name; if(dimc(2) == 3) { do_alpha= 0; } else if(dimc(2) == 4) { do_alpha= 1; } else { ASSERT, (0),"color array must have first dimension 3 or 4 in "+fn_name; } if(typeof(color) == "char") color= float(color/255.0); nx= dimc(3); ny= dimc(4); norm= get_normal3d(corners, [3]); /* add the object to the display list */ cells3d, nx, ny, corners, norm, color, do_alpha; /* increment counter so that later code knows to make a new OpenGL display list. */ inc_seq3d; draw3d_trigger; } func plm3d(xyz, color) /* DOCUMENT plm3d(xyz, color) Draws a logically 2D mesh in 3D using OpenGL. SEE ALSO: plpoly3d, plcell3d, lookat3d, light3d, win3d */ { /* This function expects xyz and color to be doubles, but should function correctly if they happen to be floats. */ /* are the arguments compatible lengths? */ fn_name= "plm3d"; dimsx= dimsof(xyz); ASSERT, (dimsx(1) == 3 && dimsx(2) == 3), "mesh vertices must be 3-by-nx-by-ny in "+fn_name; nx= dimsx(3); ny= dimsx(4); is_3_vector,color,"color must be a 3 element vector in "+fn_name; if(typeof(color) == "char") color= float(color/255.0); /* add the object to the display list */ plm3d_raw, nx, ny, xyz, color; /* increment counter so that later code knows to make a new OpenGL display list. */ inc_seq3d; draw3d_trigger; } func plf3d(xyz, color) /* DOCUMENT plf3d(xyz, color) Fills a logically 2D mesh in 3D using OpenGL. color is (3 or 4)-by-(nx-1)-by-(ny-1). The initial index of color is 3 (for RGB colors) or 4 (for translucent RGBA colors). Each zone is filled with a single color. The surface does not "reflect" light, so there will not be any shiny highlights. SEE ALSO: plm3d, plsurf3d, plcolrsurf3d, plcell3d, lookat3d, light3d, win3d */ { /* This function expects xyz and color to be doubles, but should function correctly if they happen to be floats. */ /* are the arguments compatible lengths? */ fn_name= "plf3d"; dimsx= dimsof(xyz); ASSERT, (dimsx(1) == 3 && dimsx(2) == 3), "mesh vertices must be 3-by-nx-by-ny in "+fn_name; nx= dimsx(3); ny= dimsx(4); dimc= dimsof(color); ASSERT, (dimc(1) == 3), "color must be a 2D array of colors in "+fn_name; if(dimc(3) == nx-1 && dimc(4) == ny-1) { // proper zone centered colors } else { ASSERT, (0),"color is not a 3-by-(nx-1)-by-(ny-1) or 4-by-(nx-1)-by-(ny-1) array in "+fn_name; } if(typeof(color) == "char") color= float(color/255.0); // The compiled routine needs to have an alpha value for each color, so set alpha to one // if it was not supplied if(dimc(2) == 3) { colnu= array(float, 4, nx-1, ny-1); colnu(1:3,..)= color; colnu(4,..)= 1.0f; /* add the object to the display list */ plf3d_raw, nx, ny, xyz, colnu; } else { /* add the object to the display list */ plf3d_raw, nx, ny, xyz, color; } /* increment counter so that later code knows to make a new OpenGL display list. */ inc_seq3d; draw3d_trigger; } func plsurf3d(xyz, norm, color, flip=) /* DOCUMENT plsurf3d(xyz, norm, color, flip=) Draws a lit 2D mesh in 3D using OpenGL. SEE ALSO: plcolrsurf3d, plm3d, plpoly3d, plcell3d, lookat3d, light3d, win3d */ { /* This function expects xyz, color, and norm to be doubles, but should function correctly if they happen to be floats. */ /* are the arguments compatible lengths? */ fn_name= "plsurf3d"; dimsx= dimsof(xyz); ASSERT, (dimsx(1) == 3 && dimsx(2) == 3), "mesh vertices must be 3-by-nx-by-ny in "+fn_name; nx= dimsx(3); ny= dimsx(4); ASSERT, allof(dimsx == dimsof(norm)),"coordinates and normals must have the same dimensions in "+fn_name; dimc= dimsof(color); if(dimc(2) == 3) { do_alpha= 0; } else if(dimc(2) == 4) { do_alpha= 1; } else { ASSERT, (0), "color must have 3 or 4 components in "+fn_name; } if(typeof(color) == "char") color= float(color/255.0); if(!is_void(flip)) { dimf= dimsof(flip); ASSERT, (dimf(1) == 1 && dimf(2) == 3), "flip must be a 3 element vector in "+fn_name; xyz2= xyz*flip; norm2= norm*flip; /* Must keep normal and circulation order of triangles consistent. Normals will be found by same reflection operation as points. Will reverse order of triangle vertices in tri-arrays, but multiply normals by an extra minus for other lists if the reflection has "odd parity". */ nneg= numberof(where(flip < 0)); if(nneg & 1) { xyz2= xyz2(,0:1:-1,..); norm2= norm2(,0:1:-1,..); } /* add the object to the display list */ surf3d, do_alpha, nx, ny, xyz2, norm2, color; } else { /* add the object to the display list */ surf3d, do_alpha, nx, ny, xyz, norm, color; } /* increment counter so that later code knows to make a new OpenGL display list. */ inc_seq3d; draw3d_trigger; } func plcolrsurf3d(xyz, norm, color, flip=) /* DOCUMENT plcolrsurf3d(xyz, norm, color, flip=) Draws a lit 2D mesh in 3D using OpenGL. Color varies across the mesh and is specified at mesh vertices. SEE ALSO: plsurf3d, plm3d, plpoly3d, plcell3d, lookat3d, light3d, win3d */ { /* This function expects xyz, color, and norm to be doubles, but should function correctly if they happen to be floats. */ /* are the arguments compatible lengths? */ fn_name= "plcolrsurf3d"; dimsx= dimsof(xyz); ASSERT, (dimsx(1) == 3 && dimsx(2) == 3), "mesh vertices must be 3-by-nx-by-ny in "+fn_name; nx= dimsx(3); ny= dimsx(4); ASSERT, allof(dimsx == dimsof(norm)),"coordinates and normals must have the same dimensions in "+fn_name; dimc= dimsof(color); if(dimc(2) == 3) { do_alpha= 0; } else if(dimc(2) == 4) { do_alpha= 1; } else { ASSERT, (0), "color must have 3 or 4 components in "+fn_name; } ASSERT, ( (dimc(1) == 3) && (dimsx(3) == dimc(3)) && (dimsx(4) == dimc(4)) ), "coordinates and colors must have the same dimensions in "+fn_name; if(typeof(color) == "char") color= float(color/255.0); if(!is_void(flip)) { dimf= dimsof(flip); ASSERT, (dimf(1) == 1 && dimf(2) == 3),"flip must be a 3 element vector in "+fn_name; xyz2= xyz*flip; norm2= norm*flip; /* Must keep normal and circulation order of triangles consistent. Normals will be found by same reflection operation as points. Will reverse order of triangle vertices in tri-arrays, but multiply normals by an extra minus for other lists if the reflection has "odd parity". */ nneg= numberof(where(flip < 0)); if(nneg & 1) { xyz2= xyz2(,0:1:-1,..); norm2= norm2(,0:1:-1,..); colr2= color(,0:1:-1,..); } /* add the object to the display list */ colrsurf3d, do_alpha, nx, ny, xyz2, norm2, colr2; } else { /* add the object to the display list */ colrsurf3d, do_alpha, nx, ny, xyz, norm, color; } /* increment counter so that later code knows to make a new OpenGL display list. */ inc_seq3d; draw3d_trigger; } func pllines3d(xyz, color) /* DOCUMENT pllines3d(xyz, color) Draws a Polyline in 3D using OpenGL. SEE ALSO: plpoly3d, plcell3d, lookat3d, light3d, win3d */ { /* This function expects xyz and color to be doubles, but should function correctly if they happen to be floats. */ /* are the arguments compatible lengths? */ fn_name= "pllines3d"; dimsx= dimsof(xyz); dimc= dimsof(color); ASSERT, (dimsx(1) == 2 && dimsx(2) == 3), "vertices must be 3-by-nvert in "+fn_name; if(typeof(color) == "char") color= float(color/255.0); nvert= dimsx(3); ASSERT, (dimc(1) == 1 && dimc(2) == 3 ), "color array must be a 3 element vector in "+fn_name; /* add the object to the display list */ lines3d, nvert, xyz, color; /* increment counter so that later code knows to make a new OpenGL display list. */ inc_seq3d; draw3d_trigger; } func plpoints3d(xyz, color) /* DOCUMENT plpoints3d(xyz, color) Draws a set of Points in 3D using OpenGL. SEE ALSO: plpoly3d, plcell3d, lookat3d, light3d, win3d */ { /* This function expects xyz and color to be doubles, but should function correctly if they happen to be floats. */ /* are the arguments compatible lengths? */ fn_name= "plpoints3d"; dimsx= dimsof(xyz); dimc= dimsof(color); ASSERT, (dimsx(1) == 2 && dimsx(2) == 3), "vertices must be 3-by-nvert in "+fn_name; if(typeof(color) == "char") color= float(color/255.0); nvert= dimsx(3); ASSERT, (dimc(1) == 2 && dimc(2) == 3 && dimc(3) == nvert ), "color array must be 3-by-nvert in "+fn_name; /* add the object to the display list */ points3d, nvert, xyz, color; /* increment counter so that later code knows to make a new OpenGL display list. */ inc_seq3d; draw3d_trigger; } func plglyphs3d(xyz, scal, theta, phi, color) /* DOCUMENT plglyphs3d(xyz, scal, theta, phi, color) Draws a set of Glyphs using OpenGL. The glyphs are located at xyz and have color "color". The base glyph size is multiplied scal and the glyph axis points in the direction (theta, phi). SEE ALSO: plpoints3d, lookat3d, light3d, win3d */ { /* This function expects the arguments to be doubles, but should function correctly if they happen to be floats. */ /* are the arguments compatible lengths? */ fn_name= "plglyphs3d"; dimsx= dimsof(xyz); ASSERT, (dimsx(1) == 2 && dimsx(2) == 3), "points must be 3-by-nglyph in "+fn_name; nglyph= dimsx(3); dims= dimsof(scal); ASSERT, (dims(1) == 1 && dims(2) == nglyph ), "scale vector must be nglyph long in "+fn_name; dimt= dimsof(theta); ASSERT, (dimt(1) == 1 && dimt(2) == nglyph ), "theta vector must be nglyph long in "+fn_name; dimp= dimsof(phi); ASSERT, (dimp(1) == 1 && dimp(2) == nglyph ), "phi vector must be nglyph long in "+fn_name; dimc= dimsof(color); ASSERT, (dimc(1) == 2 && dimc(2) == 3 && dimc(3) == nglyph ), "color array must be 3-by-nglyph in "+fn_name; if(typeof(color) == "char") color= float(color/255.0); /* add the object to the display list */ glyphs3d, nglyph, xyz, scal, theta, phi, color; /* increment counter so that later code knows to make a new OpenGL display list. */ inc_seq3d; draw3d_trigger; } func pltrilists3d(tris,flip=,offset=,cubemap=,emit=) /* DOCUMENT pltrilists3d(tris,flip=,offset=,cubemap=,emit=) This function is used to display an arbitrary number of triangle strips or arrays in 3D. An example is the output of an iso-surface routine. tris is either a TriStripGrp, a TriArrayGrp, or a TriVertexGrp. flip, if present, is a 3 element vector that multiplies the x, y, and z coords of every point and normal. Ordinarily, all elements are either +1 or -1. If cubemap is non-zero, perform specular lighting using cube map textures. A TriStripGrp is composed of several triangle strips. It has a pointer to the next TriStripGrp. A TriArrayGrp is an array of triangles with a pointer to the next TriArrayGrp. A TriVertexGrp is like a TriArrayGrp except that the vertices and normals have been gathered into vectors and each triangle is specified by three indices into these vectors. SEE ALSO: plcell3d, lookat3d, light3d, win3d */ { extern n_tri_3d; fn_name= "pltrilists3d"; if(is_void(tris)) return; if(!is_void(flip)) { dimf= dimsof(flip); ASSERT, (dimf(1) == 1 && dimf(2) == 3), "flip must be a 3 element vector in "+fn_name; /* Must keep normal and circulation order of triangles consistent. Normals will be found by same reflection operation as points. Will reverse order of triangle vertices in tri-arrays, but multiply normals by an extra minus for other lists if the reflection has "odd parity". */ nneg= numberof(where(flip < 0)); if(nneg & 1) { /* negative number of flips */ flipn= flip*[-1.0,-1.0,-1.0]; odd_parity= 1; } else { flipn= flip; odd_parity= 0; } } if(!is_void(offset)) { dimo= dimsof(offset); ASSERT, (dimo(1) == 1 && dimo(2) == 3), "offset must b e a 3 element vector in "+fn_name; } if(is_void(cubemap)) { cubemap= 0; } else if(cubemap) { /* CURRENTLY ONLY SUPPORT CUBE MAP LIGHTING FOR TRIANGLE ARRAYS */ if(structof(tris) != TriArrayGrp) cubemap= 0; } if(is_void(emit)) { emit= 0; } /* NOTE: Currently create an object in yorick's display list for every object in the list of triangle groups. Could consider collapsing all of them into one large object. */ /* run over the triangle list */ nTriTot= nStripTot= nVertTot=0; triptr= &tris; if(structof(tris) == TriStripGrp) { while(1) { if(!triptr) break; if(is_void(*triptr)) break; nStrip= triptr->nStrip; nVert= triptr->nVert; if(nStrip) { ntri= nVert-2*nStrip; if(!is_void(flip)) { xyz2= (*(triptr->xyzverts))*flip; norm2= (*(triptr->normals))*flipn; if(!is_void(offset)) { xyz2 += offset; } /* normals for smooth shading must have been supplied */ pltstrips3d, (*(triptr->triLen)), xyz2, (*(triptr->colors)), norm2; } else { /* normals for smooth shading must have been supplied */ xyz2= (*(triptr->xyzverts)); if(!is_void(offset)) { xyz2 += offset; } pltstrips3d, (*(triptr->triLen)), xyz2, (*(triptr->colors)), (*(triptr->normals)); } nTriTot += ntri; nStripTot += nStrip; nVertTot += nVert; } triptr= triptr->next; } ; return [nTriTot, nStripTot, nVertTot]; } else if(structof(tris) == TriArrayGrp) { while(1) { if(!triptr) break; if(is_void(*triptr)) break; ntri= triptr->numTri; if(ntri <= 0) break; colr= *(triptr->colors); dimc= dimsof(colr); ASSERT, (dimc(1) > 0 && (dimc(2) == 3 || dimc(2) == 4) ), "a color must have leading length 3 or 4 in "+fn_name; if(dimc(1) == 1) { /* broadcast the color out to the proper length */ colr= array(colr, ntri); } else if(dimc(1) == 2 && dimc(3) != ntri) { ASSERT, (0), "there must be ntri colors in "+fn_name; } else if(dimc(1) == 3 && (dimc(3) != 3 || dimc(4) != ntri) ) { ASSERT, (0), "there must be 3-by-ntri colors in "+fn_name; } else if(dimc(1) > 3) { ASSERT, (0), "there must be one color, a color per triangle, or a color per vertex in "+fn_name; } if(!is_void(flip)) { xyz2= (*(triptr->xyzverts))*flip; norm2= (*(triptr->normals))*flip; if(odd_parity) { xyz2= xyz2(,0:1:-1,..); norm2= norm2(,0:1:-1,..); if(dimc(1) == 3 && dimc(4) == ntri) { colr= colr(,0:1:-1,..); } } if(!is_void(offset)) { xyz2 += offset; } pltarray3d, xyz2, norm2, colr, ntri, cubemap, emit; } else { xyz2= (*(triptr->xyzverts)); if(!is_void(offset)) { xyz2 += offset; } pltarray3d, xyz2, *(triptr->normals), colr, ntri, cubemap, emit; } nTriTot += ntri; triptr= triptr->next; } /* logically one triangle per "strip" */ return [nTriTot, nTriTot, 3*nTriTot]; } else if(structof(tris) == TriVertexGrp) { while(1) { if(!triptr) break; if(is_void(*triptr)) break; ntri= triptr->numTri; if(ntri <= 0) break; nvert= triptr->numEdg colr= *(triptr->colors); dimc= dimsof(colr); ASSERT, (dimc(1) > 0 && (dimc(2) == 3 || dimc(2) == 4) ), "a color must have leading length 3 or 4 in "+fn_name; if(dimc(2) == 3) { // convert color from RGB to RGBA dimc(2)= 4; colrnew= array(1.0f, dimc); colrnew(1:3,..)= colr; colr= colrnew; colrnew= []; } if(dimc(1) == 1) { /* broadcast the color out to the proper length */ colr= array(colr, nvert); } else if(dimc(1) == 2) { ASSERT, (dimc(3) == nvert), "there must be nvert colors in "+fn_name; } else { write,"color has dimensions", dimc(1), dimc(2), dimc(3), dimc(4); ASSERT, (0), "there should be nvert colors in "+fn_name; } if(!is_void(flip)) { xyz2= (*(triptr->xyzverts))*flip; norm2= (*(triptr->normals))*flipn; if(!is_void(offset)) { xyz2 += offset; } if(use_interleave) pltivarray3d, *(triptr->ptndx), xyz2, norm2, colr, ntri, nvert; else pltvarray3d, *(triptr->ptndx), xyz2, norm2, colr, ntri, nvert; } else { xyz2= (*(triptr->xyzverts)); if(!is_void(offset)) { xyz2= offset+(*(triptr->xyzverts)); if(use_interleave) pltivarray3d, *(triptr->ptndx), xyz2, *(triptr->normals), colr, ntri, nvert; else pltvarray3d, *(triptr->ptndx), xyz2, *(triptr->normals), colr, ntri, nvert; } else { if(use_interleave) pltivarray3d, *(triptr->ptndx), *(triptr->xyzverts), *(triptr->normals), colr, ntri, nvert; else pltvarray3d, *(triptr->ptndx), *(triptr->xyzverts), *(triptr->normals), colr, ntri, nvert; } } nTriTot += ntri; triptr= triptr->next; } /* logically one triangle per "strip" */ return [nTriTot, nTriTot, 3*nTriTot]; } else if(structof(tris) == TriStripNdxGrp) { while(1) { if(!triptr) break; if(is_void(*triptr)) break; nVert= triptr->nVert; nStrip= triptr->nStrip; ntri= nVert-2*nStrip; numedg= triptr->numEdg; if(nStrip <= 0) break; colr= *(triptr->colors); dimc= dimsof(colr); ASSERT, (dimc(1) == 1 && (dimc(2) == 3 || dimc(2) == 4) ), "color must be a 3 or 4 element vector in "+fn_name; if(!is_void(flip)) { xyz2= (*(triptr->xyzverts))*flip; norm2= (*(triptr->normals))*flipn; if(!is_void(offset)) { xyz2 += offset; } pltivstrips3d, *(triptr->triLen), *(triptr->ptndx), xyz2, norm2, colr; } else { xyz2= (*(triptr->xyzverts)); if(!is_void(offset)) { xyz2 += offset; } pltivstrips3d, *(triptr->triLen), *(triptr->ptndx), xyz2, *(triptr->normals), colr; } nTriTot += ntri; nStripTot += nStrip; nVertTot += nVert; triptr= triptr->next; } return [nTriTot, nStripTot, nVertTot]; } else { ASSERT, (0),"the tris argument is neither a TriArrayGrp, a TriVertexGrp, TriStripNdxGrp, nor a TriStripGrp in "+fn_name; } } func pltstrips3d(nv, xyz, color, norm, draw_edge=) /* DOCUMENT pltstrips3d(nv, xyz, color, norm, draw_edge=) Draws a set of triangle-strips in 3D using OpenGL. pltrilists3d is normally called instead of this lower level routine. xyz is 3-by-nvert. nv is the number of vertices per triangle strip (i.e. the length of the run in the last index of xyz). nvert= sum(nv) nstrip= numberof(nv); ntri= nvert-2*nstrip; color is normally 3-by-ncolor. ncolor can be 1 (all tris the same color), numberof(nv) (one color per strip), or ntri (one color per triangle). color will always be increased in size to ntri before being stored. If color is 4-by-ncolor, the 4th element is the alpha value. norm can be 3-by-ntri for flat shading or 3-by-nvert for smooth shading. If norm is not specified, lighting will not be used (the specified color will be used directly). SEE ALSO: pltrilists3d, lookat3d, light3d, win3d */ { /* This function expects xyz, color, and norm to be doubles, but should function correctly if they happen to be floats. */ /* This function accepts a wide range of inputs and coerces them into a more restricted set that are saved in yorick's display list. */ fn_name= "pltstrips3d"; nvert= sum(nv); nstrip= numberof(nv); ntri= nvert-2*nstrip; if(nstrip <= 0) return; /* The float conversions below makes sure that the right data type is passed to the compiled routine. */ dimsx= dimsof(xyz); ASSERT, (dimsx(1) == 2 && dimsx(2) == 3 && dimsx(3) == nvert), "xyz must be a 3-by-nvert array in "+fn_name; dimc= dimsof(color); ASSERT, (dimc(2) == 3 || dimc(2) == 4), "first dimension of color must be 3 or 4 in "+fn_name; if(dimc(2) == 3) { do_alpha= 0; } else { do_alpha= 1; } if(typeof(color) == "char") color= float(color/255.0); if(dimc(1) == 1) { /* broadcast color out to all tris */ color= array(color, ntri); } else { ASSERT, (dimc(1) == 2), "color can have at most 2 dimensions in "+fn_name; if(dimc(3) == 1) { /* broadcast color out to all tris */ color= array(color(,1), ntri); } else if(dimc(3) == nstrip) { clrnew= array(0.0, dimc(2), ntri); for(i= 1, base= 1; i <= nstrip; i++) { ntr= nv(i)-2; clrnew(,base:base+ntr-1)= color(,i); base += ntr; } /* NOTE: eq_nocopy doesn't work unless arg. 2 is a temporary (there is no copy involved here, just that there is a temporary variable on the yorick stack). */ eq_nocopy, color, *&clrnew; clrnew= []; } else { ASSERT, (dimc(3) == ntri), "number of colors must be 1, nstrip, or ntri in "+fn_name; } } /* the user can request outlined edges, not filled polygons */ do_edge= 0; if(!is_void(draw_edge) && draw_edge) do_edge= 1; /* Do not light the surface unless normals were supplied. If there are as many normals as vertices, use smooth shading */ smooth= 0; do_light= 1; if(is_void(norm)) { do_light= 0; norm= 0; } else { dimsn= dimsof(norm); ASSERT, (dimsn(1) == 2 && dimsn(2) == 3), "norm must be a 3-by-n array in "+fn_name; if(dimsn(3) == dimsx(3)) { smooth= 1; /* normal per vertex, so use smooth shading */ } else if(dimsn(3) == ntri) { smooth= 0; /* normal per triangle, so use flat shading */ } else { ASSERT, (0),"norm must have length nvertices or ntris in "+fn_name; } } /* add the object to the display list */ tstrips3d, nstrip, nv, xyz, norm, color, do_edge, smooth, do_light, do_alpha; /* increment counter so that later code knows to make a new OpenGL display list. */ inc_seq3d; draw3d_trigger; } func plqstrips3d(nv, xyz, color, norm, draw_edge=) /* DOCUMENT plqstrips3d(nv, xyz, color, norm, draw_edge=) Draws a set of quad-strips in 3D using OpenGL. xyz is 3-by-2-by-nvert. nv is the number of vertices per quad strip (i.e. the length of the run in the last index of xyz). nvert= sum(nv) nstrip= numberof(nv); nquad= nvert-nstrip; color is 3-by-ncolor. ncolor can be 1 (all quads the same color), numberof(nv) (one color per strip), or nquad (one color per quad). color will always be increased in size to nquad before being stored. norm can be 3-by-nquad for flat shading or 3-by-2-by-nvert for smooth shading. If norm is not specified, lighting will not be used (the specified color will be used directly). SEE ALSO: pltrilists3d, pltstrips3d, lookat3d, light3d, win3d */ { /* This function expects xyz, color, and norm to be doubles, but should function correctly if they happen to be floats. */ /* This function accepts a wide range of inputs and coerces them into a more restricted set that are saved in yorick's display list. */ fn_name= "plqstrips3d"; nvert= sum(nv); nstrip= numberof(nv); nquad= nvert-nstrip; dimsx= dimsof(xyz); ASSERT, (dimsx(1) == 3 && dimsx(2) == 3 && dimsx(3) == 2 && dimsx(4) == nvert), "xyz must be a 3-by-2-by-nvert array in "+fn_name; dimc= dimsof(color); ASSERT, (dimc(2) == 3 || dimc(2) == 4), "first dimension of color must be 3 or 4 in "+fn_name; if(dimc(2) == 3) { do_alpha= 0; } else { do_alpha= 1; } if(typeof(color) == "char") color= float(color/255.0); if(dimc(1) == 1) { /* broadcast color out to all quads */ color= array(color, nquad); } else { ASSERT, (dimc(1) == 2), "color can have at most 2 dimensions in "+fn_name; if(dimc(3) == 1) { /* broadcast color out to all tris */ color= array(color(,1), nquad); } else if(dimc(3) == nstrip) { clrnew= array(0.0, dimc(2), nquad); for(i= 1, base= 1; i <= nstrip; i++) { nq= nv(i)-1; clrnew(,base:base+nq-1)= color(,i); base += nq; } /* NOTE: eq_nocopy doesn't work unless arg. 2 is a temporary (there is no copy involved here, just that there is a temporary variable on the yorick stack). */ eq_nocopy, color, *&clrnew; clrnew= []; } else if(dimc(3) != nquad) { ASSERT, (0),"number of colors must be 1, nstrip, or ntri in "+fn_name; } } /* the user can request outlined edges, not filled polygons */ do_edge= 0; if(!is_void(draw_edge) && draw_edge) do_edge= 1; /* Do not light the surface unless normals were supplied. If there are as many normals as vertices, use smooth shading */ do_light= 1; if(is_void(norm)) { do_light= 0; norm= 0; smooth= 0; } else { dimsn= dimsof(norm); if(dimsn(1) == 2) { /* normals must be one per quad */ ASSERT, (dimsn(3) == nquad), "norm must be a 3-by-nquad array in "+fn_name; smooth= 0; /* normal per quad, so use flat shading */ } else if(dimsn(1) == 3) { /* normals must be one per vertex */ ASSERT, (dimsn(2) == 3 && dimsn(3) == 2 && dimsn(4) == dimsx(4)), "norm must a 3-by-2-by-nvert array in "+fn_name; smooth= 1; /* normal per vertex, so use smooth shading */ } else { ASSERT, (0),"norm must be a 3-by-nquad or a 3-by-2-by-nvert array in "+fn_name; } } /* add the object to the display list */ qstrips3d, nstrip, nv, xyz, norm, color, do_edge, smooth, do_light, do_alpha; /* increment counter so that later code knows to make a new OpenGL display list. */ inc_seq3d; draw3d_trigger; } func pltivstrips3d(nv, ndx, xyz, norm, color, draw_edge=) /* DOCUMENT pltivstrips3d(nv, ndx, xyz, norm, color, draw_edge=) Draws a set of triangle-strips in 3D using OpenGL. pltrilists3d is normally called instead of this lower level routine. xyz and norm are 3-by-nvert. ndx holds the vertex numbers (indices into xyz or norm) of the vertices in the tristrips. nv is the number of vertices per triangle strip (i.e. the length of the run in the last index of ndx). nvert= sum(nv) nstrip= numberof(nv); ntri= nvert-2*nstrip; color is normally 3-by-ncolor. ncolor can be 1 (all tris the same color), numberof(nv) (one color per strip), or ntri (one color per triangle). color will always be increased in size to ntri before being stored. If color is 4-by-ncolor, the 4th element is the alpha value. SEE ALSO: pltrilists3d, pltristrips3d, lookat3d, light3d, win3d */ { /* This function expects xyz, color, and norm to be doubles, but should function correctly if they happen to be floats. */ /* This function accepts a wide range of inputs and coerces them into a more restricted set that are saved in yorick's display list. */ fn_name= "pltivstrips3d"; nvert= sum(nv); nstrip= numberof(nv); ntri= nvert-2*nstrip; numedg= numberof(xyz(1,..)); if(nstrip <= 0) return; /* The float conversions below makes sure that the right data type is passed to the compiled routine. */ dimsx= dimsof(xyz); ASSERT, (dimsx(1) == 2 && dimsx(2) == 3 && dimsx(3) == numedg), "xyz must be a 3-by-numedg array in "+fn_name; if(is_void(norm)) { ASSERT, (0), "norm must be supplied in "+fn_name; } else { dimsn= dimsof(norm); ASSERT, (dimsn(1) == 2 && dimsn(2) == 3 && dimsx(3) == numedg), "norm must be a 3-by-numedg array in "+fn_name; } dimc= dimsof(color); ASSERT, (dimc(2) == 3 || dimc(2) == 4), "first dimension of color must be 3 or 4 in "+fn_name; if(dimc(2) == 3) { do_alpha= 0; } else { do_alpha= 1; } if(typeof(color) == "char") color= float(color/255.0); if(dimc(1) == 1) { /* broadcast color out to all tris */ color= array(color, ntri); } else { ASSERT, (dimc(1) == 2), "color can have at most 2 dimensions in "+fn_name; if(dimc(3) == 1) { /* broadcast color out to all tris */ color= array(color(,1), ntri); } else if(dimc(3) == nstrip) { clrnew= array(0.0, dimc(2), ntri); for(i= 1, base= 1; i <= nstrip; i++) { ntr= nv(i)-2; clrnew(,base:base+ntr-1)= color(,i); base += ntr; } /* NOTE: eq_nocopy doesn't work unless arg. 2 is a temporary (there is no copy involved here, just that there is a temporary variable on the yorick stack). */ eq_nocopy, color, *&clrnew; clrnew= []; } else if(dimc(3) != ntri) { ASSERT, (0),"number of colors must be 1, nstrip, or ntri in "+fn_name; } } /* the user can request outlined edges, not filled polygons */ do_edge= 0; if(!is_void(draw_edge) && draw_edge) do_edge= 1; /* add the object to the display list */ tstripsndx3d, nstrip, numedg, ntri, nv, ndx, xyz, norm, color, do_edge, do_alpha; /* increment counter so that later code knows to make a new OpenGL display list. */ inc_seq3d; draw3d_trigger; } func pltarray3d(xyz, norm, color, ntri, cubemap, emit, draw_edge=) /* DOCUMENT pltarray3d(xyz, norm, color, ntri, cubemap, emit, draw_edge=) Draws a Triangle Array in 3D using OpenGL. pltrilists3d is normally called instead of this lower level routine. If cubemap is non-zero, specular lighting is handled by cube map textures. SEE ALSO: pltrilists3d, lookat3d, light3d, win3d */ { /* This function expects xyz, color, and norm to be doubles, but should function correctly if they happen to be floats. */ /* make private copies of all input arrays so that they can be used as OpenGL vertex arrays (whose storage must remain undisturbed until the picture is cleared) */ fn_name= "pltarray3d"; dimsx= dimsof(xyz); ASSERT, (dimsx(1) == 3 && dimsx(2) == 3 && dimsx(3) == 3 && dimsx(4) >= ntri), "triangle array vertices must be 3-by-3-by-ntri in "+fn_name; dimc= dimsof(color); ASSERT, (dimc(2) == 3 || dimc(2) == 4), "first dimension of color must be 3 or 4 in "+fn_name; if(dimc(2) == 3) { do_alpha= 0; } else { do_alpha= 1; } ASSERT, (dimc(1) <= 3), "color can have at most 3 dimensions in "+fn_name; if(typeof(color) == "char") color= float(color/255.0); if(dimc(1) == 1) { /* broadcast color out to all tris */ color= array(color, ntri); colrpervrt= 0; } else { if(dimc(1) == 3) { ASSERT, (dimc(3) == 3 && dimc(4) == ntri), "number of colors must be 1 or ntri or 3*ntri in "+fn_name; cpervrt= 1; /* triangles have a color per vertex */ } else { if(dimc(3) == 1) { /* broadcast color out to all tris */ color= array(color(,1), ntri); } else if(dimc(3) != ntri) { ASSERT, (0),"number of colors must be 1 or ntri in "+fn_name; } cpervrt= 0; } } if(is_void(norm)) { smooth= 1; norm= array(0.0, 3, 4, ntri); ln= array(3, ntri); nr= get_normal3d(xyz, ln); norm(,1,)= nr; norm(,2,)= nr; norm(,3,)= nr; nr= []; } else { dimsn= dimsof(norm); if(dimsn(1) == 2) { smooth= 0; ASSERT, (dimsn(2) == 3 && dimsn(3) >= ntri), "triangle array normals must be 3-by-ntri in "+fn_name; /* replicate to get one normal per vertex to make the array compatible with OpenGL 1.1 vertex arrays */ norm= norm(,-:1:3,); } else if(dimsn(1) == 3) { smooth= 1; ASSERT, (dimsn(2) == 3 && dimsn(3) == 3 && dimsn(4) == ntri), "triangle array normals must be 3-by-3-by-ntri in "+fn_name; } else { ASSERT, (0),"triangle array normals must be 3-by-ntri or 3-by-3-by-ntri in "+fn_name; } } /* the user can request outlined edges, not filled polygons */ do_edge= 0; if(!is_void(draw_edge) && draw_edge) do_edge= 1; do_light= 1; /* add the object to the display list */ tarray3d, ntri, xyz, norm, color, do_edge, smooth, do_light, do_alpha, cpervrt, cubemap, emit; /* increment counter so that later code knows to make a new OpenGL display list. */ inc_seq3d; draw3d_trigger; } func plqarray3d(xyz, norm, color, nquad, draw_edge=) /* DOCUMENT plqarray3d(xyz, norm, color, nquad, draw_edge=) Draws a Quadrangle Array in 3D using OpenGL. SEE ALSO: pltarray3d, plqstrips3d, lookat3d, light3d, win3d */ { /* This function expects xyz, color, and norm to be doubles, but should function correctly if they happen to be floats. */ /* make private copies of all input arrays so that they can be used as OpenGL vertex arrays (whose storage must remain undisturbed until the picture is cleared) */ fn_name= "plqarray3d"; dimsx= dimsof(xyz); ASSERT, (dimsx(1) == 3 && dimsx(2) == 3 && dimsx(3) == 4 && dimsx(4) == nquad), "quad array vertices must be 3-by-4-by-nquad in "+fn_name; dimc= dimsof(color); ASSERT, (dimc(2) == 3 || dimc(2) == 4), "first dimension of color must be 3 or 4 in "+fn_name; if(dimc(2) == 3) { do_alpha= 0; } else { do_alpha= 1; } ASSERT, (dimc(1) > 3), "color can have at most 2 dimensions in "+fn_name; if(typeof(color) == "char") color= float(color/255.0); if(dimc(1) == 1) { /* broadcast color out to all tris */ color= array(color, ntri); colrpervrt= 0; } else { if(dimc(1) == 3) { ASSERT, (dimc(3) == 4 && dimc(4) == nquad), "number of colors must be 1 or nquad or 4*nquad in "+fn_name; cpervrt= 1; /* triangles have a color per vertex */ } else { if(dimc(3) == 1) { /* broadcast color out to all quads */ color= array(color(,1), nquad); } else if(dimc(3) != nqaud) { ASSERT, (0), "number of colors must be 1 or nquad in "+fn_name; } cpervrt= 0; } } /* normals could be either one per quad or one per vertex. one per vertex means smooth shading. */ if(is_void(norm)) { smooth= 1; norm= array(0.0, 3, 4, nquad); ln= array(4, nquad); nr= get_normal3d(xyz, ln); norm(,1,)= nr; norm(,2,)= nr; norm(,3,)= nr; norm(,4,)= nr; nr= []; } else { dimsn= dimsof(norm); if(dimsn(1) == 2) { smooth= 0; ASSERT, (dimsn(2) == 4 && dimsn(3) == nquad), "quad array normals must be 4-by-nquad in "+fn_name; /* replicate to get one normal per vertex to make the array compatible with OpenGL 1.1 vertex arrays */ norm= norm(,-:1:4,); } else if(dimsn(1) == 3) { smooth= 1; ASSERT, (dimsn(2) == 3 && dimsn(3) == 4 && dimsn(4) >= nquad), "triangle array normals must be 3-by-4-by-nquad in "+fn_name; } else { ASSERT, (0),"triangle array normals must be 3-by-nquad or 3-by-4-by-nquad in "+fn_name; } } /* the user can request outlined edges, not filled polygons */ do_edge= 0; if(!is_void(draw_edge) && draw_edge) do_edge= 1; do_light= 1; /* add the object to the display list */ qarray3d, nquad, xyz, norm, color, do_edge, smooth, do_light, do_alpha, cpervrt; /* increment counter so that later code knows to make a new OpenGL display list. */ inc_seq3d; draw3d_trigger; } func pltivarray3d(ptndx, xyz, norm, color, ntri, nvert) /* DOCUMENT pltivarray3d Draws a Triangle Array in 3D using OpenGL. Triangles are specified using indices into a list of vertices, normals, and colors. pltrilists3d is normally called instead of this lower level routine. SEE ALSO: pltarray3d, lookat3d, pltrilists3d */ { /* make a private interleaved array containing all input arrays so that it can be used as OpenGL vertex array */ fn_name= "pltivarray3d"; dimsx= dimsof(xyz); ASSERT, (dimsx(1) == 2 && dimsx(2) == 3 && dimsx(3) >= nvert), "triangle array vertices must be 3-by-n_edges_cut in "+fn_name; if(is_void(norm)) { ASSERT, (0), "normals must be supplied in "+fn_name; } else { dimsn= dimsof(norm); ASSERT, allof(dimsn == dimsx), "normals and xyz must be the same size in "+fn_name; } /* there must be an RGBA color for every vertex */ dimc= dimsof(color); ASSERT, (dimc(1) == 2 && dimc(2) == 4 && dimc(3) >= nvert), "triangle array colors must be 4-by-n_edges_cut in "+fn_name; if(typeof(color) == "char") color= float(color/255.0); tivarray3d, ntri, nvert, ptndx, xyz, norm, colr; /* increment counter so that later code knows to make a new OpenGL display list. */ inc_seq3d; draw3d_trigger; } func pltvarray3d(ptndx, xyz, norm, color, ntri, nvert) /* DOCUMENT pltvarray3d Draws a Triangle Array in 3D using OpenGL. Triangles are specified using indices into a list of vertices, normals, and colors. pltrilists3d is normally called instead of this lower level routine. SEE ALSO: pltarray3d, pltivarray3d, lookat3d, pltrilists3d */ { fn_name= "pltvarray3d"; dimsx= dimsof(xyz); ASSERT, (dimsx(1) == 2 && dimsx(2) == 3 && dimsx(3) >= nvert), "triangle array vertices must be 3-by-n_edges_cut in "+fn_name; if(is_void(norm)) { ASSERT, (0), "normals must be supplied in "+fn_name; } else { dimsn= dimsof(norm); ASSERT, allof(dimsn == dimsx), "normals and xyz must be the same size in "+fn_name; } /* there must be a RGB color for every vertex */ dimc= dimsof(color); ASSERT, (dimc(2) == 3 || dimc(2) == 4), "triangle array colors must be RGB or RGBA in "+fn_name; if(dimc(2) == 4) do_alpha= 1; else do_alpha= 0; if(dimc(1) == 1) { cpervrt= 0; } else { cpervrt= 1; ASSERT, (dimc(1) == 2 && dimc(3) >= nvert), "must have n_edges_cut colors in "+fn_name; } if(typeof(color) == "char") color= float(color/255.0); tvarray3d, ntri, nvert, do_alpha, cpervrt, ptndx, xyz, norm, colr; /* increment counter so that later code knows to make a new OpenGL display list. */ inc_seq3d; draw3d_trigger; } func getpix3d(nx,ny) /* DOCUMENT getpix3d Read pixels from an OpenGL window. */ { /* if the input sizes are bigger than the window, reduce them before reading the pixels */ maxnx= get_width3d(); if(is_void(nx)) { nx= maxnx } else { nx= min(nx, maxnx); } maxny= get_hite3d(); if(is_void(ny)) { ny= maxny; } else { ny= min(ny, maxny); } pix= array(char, 3, nx, ny); grabpix3d,nx,ny,pix; return pix; } func putpix3d(arr) /* DOCUMENT putpix3d Draws pixels into an OpenGL window. SEE ALSO: clear3 */ { dima= dimsof(arr); nx= dima(3); ny= dima(4); /* add the object to the display list */ plpix3d, nx, ny, arr; /* increment counter so that later code knows to make a new OpenGL display list. */ inc_seq3d; draw3d_trigger; } func CollapseTri(tris) /* DOCUMENT CollapseTri(tris) This function is used to collapse an arbitrary number of triangle arrays into a single triangle array. tris must be a TriArrayGrp (which can point to another TriArrayGrp, etc.). SEE ALSO: pltrilists3d, sortTri */ { local newtri, triptr, nTriTot; if(is_void(tris)) return []; /* run over the triangle list */ ASSERT, (structof(tris) == TriArrayGrp), "CollapseTri requires a TriArrayGrp as its argument"; /* count the number of triangles in all the lists and at the same determine whether colors are RGB or RGBA and whether there is a color per triangle or a color per array. */ dimc= dimsof(*(tris.colors)); ASSERT, (dimc(1) >= 1), "CollapseTri invalid color in a TriArrayGrp"; ncomp= dimc(2); nTriTot= 0; triptr= &tris; while(triptr && !is_void(*triptr)) { nTriTot += triptr->numTri; triptr= triptr->next; } if(nTriTot <= 0) return []; /* colrtyp is the number of color components per triangle. It is negative if there is a single color for all triangles. The program is likely to CRASH if the number of color components varies in the list or if some parts have a color per triangle and some have a color per list. */ colrtyp= ncomp; if(dimc(1) <= 1 || dimc(3) <= 1) colrtyp= -colrtyp; color_per_vert= 0; if(dimc(1) == 3) { // apparently one color per triangle vertex if(dimc(3) != 3 || numberof((*tris.colors)(1,1,)) != numberof((*tris.colors)(1,1,)) ) { error,"Dimensions of colors are wrong for color per vertex in CollapseTris"; } else { // set color per vertex flag color_per_vert= 1; if(colrtyp < 0) colrtyp -= 16; else colrtyp += 16; } } /* xyzverts and normals are really array(Point3D, 3, nTriTot) */ newxyz= array(double, 3, 3, nTriTot ); newnorm= array(double, 3, 3, nTriTot ); if(color_per_vert) { newcolr= array(float, ncomp, 3, nTriTot ); } else { newcolr= array(float, ncomp, nTriTot ); } newids= array(long, nTriTot ); triptr= &tris; if( triptr->var2 && !is_void(*(triptr->var2)) ) { nvar2= array(double, 3, nTriTot); } else { nvar2= nulvar; } nulvar= []; newtri= TriArrayGrp(numTri= nTriTot, xyzverts= &newxyz, normals= &newnorm, colors= &newcolr, cellIDs= &newids, var2= &nvar2, /* the next 3 are not used */ nTris= &nulvar, triEdg= &nulvar, triStart= &nulvar, next= &nulvar); triptr= &tris; CollapseTriArrays3d, colrtyp, triptr, &newtri; return newtri; } func SortTri(tris) /* DOCUMENT SortTri(tris) This function performs a depth sort of a triangle array. It uses the current viewpoint. The resulting triangle array should display correctly with translucency when viewed from the same point. Rotating the scene may lead to incorrect results if the triangles are translucent. tris must be a TriArrayGrp. SEE ALSO: pltrilists3d, collapseTri */ { local newxyz, newnorm, newcolr, newids; ntri= tris.numTri; dimc= dimsof(*(tris.colors)); ncomp= dimc(2); newxyz= array(double, 3, 3, ntri); newnorm= array(double, 3, 3, ntri); newcolr= array(float, ncomp, ntri); newids= array(long, ntri); hasVar2= ( tris.var2 && !is_void(*(tris.var2)) ); if(hasVar2) { nvar2= array(double, 3, nTriTot); } else { nvar2= nulvar; } nulvar= []; newtri= TriArrayGrp(numTri= ntri, xyzverts= &newxyz, normals= &newnorm, colors= &newcolr, cellIDs= &newids, /* the next 3 are not used except while forming strips */ nTris= &nulvar, triEdg= &nulvar, triStart= &nulvar, next= &nulvar); DoSortTri3d, ncomp, &tris, &newtri; return newtri; } func pltex2dvol(delta, texval) /* DOCUMENT pltex2dvol Draws a volume visualization of a 3D cell array using OpenGL. Uses 2D textures. SEE ALSO: pltex3dvol, lookat3d, light3d, win3d, pltex3dvol */ { fn_name= "pltex2dvol"; texval= char(texval); dimv= dimsof(texval); ASSERT, ((dimv(1) == 4) && (dimv(2) == 4)), "data array must be 4-nx-ny-nz in "+fn_name; nx= dimv(3); ny= dimv(4); nz= dimv(5); /* add the object to the display list */ texcell2d, nx, ny, nz, delta, texval; /* increment counter so that later code knows to make a new OpenGL display list. */ inc_seq3d; draw3d_trigger; } func pltex3dvol(nslab, boxsiz, texval, origin=) /* DOCUMENT pltex3dvol Draws a volume visualization of a 3D cell array using OpenGL. Uses 3D textures. SEE ALSO: pltex2dvol, lookat3d, light3d, win3d */ { fn_name= "pltex3dvol"; if(typeof(texval) != "char") texval= char(texval); if(is_void(boxsiz)) boxsiz= [1.0,1.0,1.0]; dimv= dimsof(texval); if(dimv(1) == 4 && dimv(2) == 4) { nx= dimv(3); ny= dimv(4); nz= dimv(5); } else { ASSERT, (0),"data array must be 4-nx-ny-nz in "+fn_name; } if(is_void(origin)) origin= [0.0, 0.0, 0.0]; ds= max(boxsiz)/nslab; /* NOTE: The 3D texture will be loaded now, which is good if the object is rotated, but bad if it is not shown even once. */ ldtex3d, nx, ny, nz, texval; /* add the object to the display list */ tex3d, ds, origin, boxsiz; /* Increment counter so that later code knows to make a new OpenGL display list. QUESTION - is this needed for "direct" objects? */ // inc_seq3d; draw3d_trigger; } yorick-gl-1.1+cvs20070922+dfsg.orig/.DS_Store0000644000175000017500000001400410676240302020112 0ustar thibautthibautBud1%  @€ @€ @€ @ E%DSDB`€ @€ @€ @yorick-gl-1.1+cvs20070922+dfsg.orig/isotree.h0000640000175000017500000000702310313362502020244 0ustar thibautthibaut/* * $Id: isotree.h,v 1.1.1.1 2005/09/18 22:08:02 dhmunro Exp $ * Header file for octree used by iso-surface. */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #ifndef __ISOTREE__ #define __ISOTREE__ #ifdef __cplusplus extern "C" { #endif typedef struct OctRange OctRange; struct OctRange { double lo, hi; } ; typedef struct OctTree OctTree; struct OctTree { long maxdepth; long *start; long *chunk; long *size; long *trsiz; long *offsets; OctRange *ranges; OctTree *next; } ; extern int ycMakeContourTree(double *var, OctTree *tree); extern void firstblk(double *data, long *start, long *sizes, long *trsiz, OctRange *rng); extern void nextblk(long *trsiz, OctRange *oldr, OctRange *nrng); extern int ycContourTree(double deltas[3], double origin[3], double level, double *var, TriArrayGrp *triangles, OctTree *tree); extern int ycContourTree2(double deltas[3], double origin[3], double level, double *var, double *var2, TriArrayGrp *triangles, OctTree *tree); extern int ycContourTreeCrv(double level, yPoint3D *xyz, double *var, TriArrayGrp *triangles, OctTree *tree); extern int ycContourTreeCrv2(double level, yPoint3D *xyz, double *var, double *var2, TriArrayGrp *triangles, OctTree *tree); extern int ycContourTreeZcen(double deltas[3], double origin[3], double level, double *var, double *vcen, TriArrayGrp *triangles, OctTree *tree); extern int ycContourTreeZcen2(double deltas[3], double origin[3], double level, double *var, double *vcen, double *var2, TriArrayGrp *triangles, OctTree *tree); extern int ycContourTreeCrvZcen(double level, yPoint3D *xyz, double *var, double *vcen, TriArrayGrp *triangles, OctTree *tree); extern int ycContourTreeCrvZcen2(double level, yPoint3D *xyz, double *var, double *vcen, double *var2, TriArrayGrp *triangles, OctTree *tree); extern int ycContourTreeVarr(double deltas[3], double origin[3], double level, double *var, TriVertexGrp *triangles, OctTree *tree, long *edgndx); extern int ycContourTreeVarr2(double deltas[3], double origin[3], double level, double *var, double *var2, TriVertexGrp *triangles, OctTree *tree, long *edgndx); extern int ycContourTreeVarrStr(double deltas[3], double origin[3], double level, double *var, TriVertexGrp *triangles, OctTree *tree, long *edgndx); extern long do_blk(long i, long j, long k, long depth); extern long grab_tris(long i, long j, long k); extern long grab_tris_ijk(long i, long j, long k); extern long grab_tris_crv(long i, long j, long k); extern long grab_tris_zcen(long i, long j, long k); extern long grab_tris_zcen_crv(long i, long j, long k); extern long grab_tris_varr(long i, long j, long k); extern void ycPointGradientIntGrdAllZcen(long i, long j, long k, long iSize, long jSize, double dx, double dy, double dz, double *var, yPoint3D gradient[8]); extern void ycPointGradientCrvgAllZcen(long idxg, long iSize, long jSize, yPoint3D *x, double *var, yPoint3D gradient[8]); #ifdef __cplusplus } #endif #endif /* Include/Define */ yorick-gl-1.1+cvs20070922+dfsg.orig/glPolys.h0000640000175000017500000000177710313362462020242 0ustar thibautthibaut/* * $Id: glPolys.h,v 1.1.1.1 2005/09/18 22:07:46 dhmunro Exp $ * Header file for the routines that draw lists of polygons. */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #ifndef __GLPOLYS__ #define __GLPOLYS__ #ifdef __cplusplus extern "C" { #endif void gl_polys_arr(long npoly, long *nverts, float *xyz, float *norm, float *colr); void gl_polys_no_arr(long npoly, long *nverts, float *xyz, float *norm, float *colr); void gl_polys_arr_no_lite(long npoly, long *nverts, float *xyz, float *colr); void gl_polys_no_arr_no_lite(long npoly, long *nverts, float *xyz, float *colr); void gl_polys_sm_arr(long npoly, long *nverts, float *xyz, float *norm, float *colr); void gl_polys_sm_no_arr(long npoly, long *nverts, float *xyz, float *norm, float *colr); #ifdef __cplusplus } #endif #endif /* Include/Define */ yorick-gl-1.1+cvs20070922+dfsg.orig/LICENSE0000640000175000017500000000562310315157545017445 0ustar thibautthibautBSD License Copyright (c) 2005, The Regents of the University of California. Produced at the Lawrence Livermore National Laboratory. Written by Steven Langer and David H. Munro . UCRL-CODE-155996 All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the disclaimer below. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the disclaimer (as noted below) in the documentation and/or other materials provided with the distribution. * Neither the name of the UC/LLNL nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF CALIFORNIA, THE U.S. DEPARTMENT OF ENERGY OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Additional BSD Notice 1. This notice is required to be provided under our contract with the U.S. Department of Energy (DOE). This work was produced at the University of California, Lawrence Livermore National Laboratory under Contract No. W-7405-ENG-48 with the DOE. 2. Neither the United States Government nor the University of California nor any of their employees, makes any warranty, express or implied, or assumes any liability or responsibility for the accuracy, completeness, or usefulness of any information, apparatus, product, or process disclosed, or represents that its use would not infringe privately-owned rights. 3. Also, reference herein to any specific commercial products, process, or services by trade name, trademark, manufacturer or otherwise does not necessarily constitute or imply its endorsement, recommendation, or favoring by the United States Government or the University of California. The views and opinions of authors expressed herein do not necessarily state or reflect those of the United States Government or the University of California, and shall not be used for advertising or product endorsement purposes. yorick-gl-1.1+cvs20070922+dfsg.orig/dlist3d.h0000640000175000017500000001531610313362460020147 0ustar thibautthibaut/* * $Id: dlist3d.h,v 1.1.1.1 2005/09/18 22:07:44 dhmunro Exp $ * Declare functions used for manipulating 3D display lists. */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #ifndef DLIST3D_H #define DLIST3D_H typedef struct yBox3D yBox3D; struct yBox3D { double xmin, xmax, ymin, ymax, zmin, zmax; } ; typedef void yglDrawFunc3d(int mode, void *data); typedef struct yList3d_Elem yList3d_Elem; struct yList3d_Elem { yBox3D box; yglDrawFunc3d *func; void *data; yList3d_Elem *next; } ; typedef struct yPoly3dData yPoly3dData; struct yPoly3dData { long npolys, edge, smooth, do_light; long *len; float *xyz, *norm, *colr; } ; typedef struct yGlyph3dData yGlyph3dData; struct yGlyph3dData { long nglyph; float *origin, *scal, *theta, *phi, *colr; } ; typedef struct yCell3dData yCell3dData; struct yCell3dData { long nx, ny, do_alpha; float *xyz, *norm, *colr; } ; typedef struct yPlm3dData yPlm3dData; struct yPlm3dData { long nx, ny; float *xyz, *colr; } ; typedef struct yPlf3dData yPlf3dData; struct yPlf3dData { long nx, ny; float *xyz, *colr; } ; typedef struct ySurf3dData ySurf3dData; struct ySurf3dData { long do_alpha, nx, ny; float *xyz, *norm, *colr; } ; typedef struct yColrSurf3dData yColrSurf3dData; struct yColrSurf3dData { long do_alpha, nx, ny; float *xyz, *norm, *colr; } ; typedef struct yTstrips3dData yTstrips3dData; struct yTstrips3dData { long nstrips, edge, smooth, do_light, do_alpha; long *len; float *xyz, *norm, *colr; } ; typedef struct yQstrips3dData yQstrips3dData; struct yQstrips3dData { long nstrips, edge, smooth, do_light, do_alpha; long *len; float *xyz, *norm, *colr; } ; typedef struct yTstripsNdx3dData yTstripsNdx3dData; struct yTstripsNdx3dData { long nstrips, ntri, nvert, numedg, edge, do_alpha; long *len, *ndx; float *xyz, *norm, *colr; } ; typedef struct yTarray3dData yTarray3dData; struct yTarray3dData { long ntri, edge, smooth, do_light, do_alpha, cpervrt, cubemap, emit; float *xyz, *norm, *colr; } ; typedef struct yQarray3dData yQarray3dData; struct yQarray3dData { long nquad, edge, smooth, do_light, do_alpha, cpervrt; float *xyz, *norm, *colr; } ; typedef struct yTivarray3dData yTivarray3dData; struct yTivarray3dData { long ntri, nvert; unsigned int *ptndx; float *ileave; } ; typedef struct yTvarray3dData yTvarray3dData; struct yTvarray3dData { long ntri, nvert, cpervrt, do_alpha; unsigned int *ptndx; float *xyz, *norm, *colr; } ; typedef struct yLines3dData yLines3dData; struct yLines3dData { long nvert; float *xyz, *colr; } ; typedef struct yPoints3dData yPoints3dData; struct yPoints3dData { long nvert; float *xyz, *colr; } ; typedef struct yTex3dData yTex3dData; struct yTex3dData { double ds, *origin, *boxsiz; } ; typedef struct yTexcell2dData yTexcell2dData; struct yTexcell2dData { long nx, ny, nz; double *znsiz; unsigned char *texval; } ; typedef struct yPix3dData yPix3dData; struct yPix3dData { long nx, ny; unsigned char *pix; } ; extern yList3d_Elem *yglNewCachedList3dElem(void); extern yList3d_Elem *yglNewDirectList3dElem(void); extern void yglDrawCurr3d(void); extern void yglClearList3d(void); extern void yglClearCachedList3d(void); extern void yglClearDirectList3d(void); extern void yglDrawList3d(void); extern void yglDrawListCache3d(void); extern void yglDrawListDirect3d(void); extern long yglGetBounds3d(yBox3D *box); extern long yglGetBoundsDirectList3d(yBox3D *box); extern long yglGetBoundsCachedList3d(yBox3D *box); extern void yglSetLims3d(yList3d_Elem *elem, long nvert, float *xyz); extern void yglDrawGnomon(void); extern void yglDrawCage(void); extern void yglPolys3d(long npolys, long *len, double *xyz, double *norm, double *colr, long edge, long smooth, long do_light); extern void yglGlyphs3d(long nglyph, double *origin, double *scal, double *theta, double *phi, double *colr); extern void yglCells3d(long nx, long ny, double *corners, double *norm, double *colr, long do_alpha); extern void yglPlm3d(long nx, long ny, double *xyz, double *colr); extern void yglPlf3d(long nx, long ny, double *xyz, double *colr); extern void yglSurf3d(long do_alpha, long nx, long ny, double *xyz, double *norm, double *colr); extern void yglColrsurf3d(long do_alpha, long nx, long ny, double *xyz, double *norm, double *colr); extern void yglLines3d(long nvert, double *xyz, double *colr); extern void yglPoints3d(long nvert, double *xyz, double *colr); extern void yglTstrips3d(long nstrips, long *len, double *xyz, double *norm, double *colr, long edge, long smooth, long do_light, long do_alpha); extern void yglQstrips3d(long nstrips, long *len, double *xyz, double *norm, double *colr, long edge, long smooth, long do_light, long do_alpha); extern void yglTstripsndx3d(long nstrips, long numedg, long ntri, long *len, long *ndx, double *xyz, double *norm, double *colr, long edge, long do_alpha); extern void yglTarray3d(long ntri, double *xyz, double *norm, double *colr, long edge, long smooth, long do_light, long do_alpha, long cpervrt, long cubemap, long emit); extern void yglQarray3d(long nquad, double *xyz, double *norm, double *colr, long edge, long smooth, long do_light, long do_alpha, long cpervrt); extern void yglTivarray3d(long ntri, long nvert, long *ptndx, double *xyz, double *norm, double *colr); extern void yglTvarray3d(long ntri, long nvert, long do_alpha, long cpervrt, long *ptndx, double *xyz, double *norm, double *colr); extern void yglTex3d(float ds, double *origin, double *boxsiz); extern void yglTexcell2d(long nx, long ny, long nz, double *znsiz, char *texval); extern void yglPlpix3d(long nx, long ny, char *pix); extern yglDrawFunc3d yglDrawPolys3d; extern yglDrawFunc3d yglDrawGlyphs3d; extern yglDrawFunc3d yglDrawCells3d; extern yglDrawFunc3d yglDrawPlm3d; extern yglDrawFunc3d yglDrawPlf3d; extern yglDrawFunc3d yglDrawSurf3d; extern yglDrawFunc3d yglDrawColrSurf3d; extern yglDrawFunc3d yglDrawLines3d; extern yglDrawFunc3d yglDrawPoints3d; extern yglDrawFunc3d yglDrawTstrips3d; extern yglDrawFunc3d yglDrawQstrips3d; extern yglDrawFunc3d yglDrawTstripsNdx3d; extern yglDrawFunc3d yglDrawTarray3d; extern yglDrawFunc3d yglDrawQarray3d; extern yglDrawFunc3d yglDrawTivarray3d; extern yglDrawFunc3d yglDrawTvarray3d; extern yglDrawFunc3d yglDrawTex3d; extern yglDrawFunc3d yglDrawTexcell2d; extern yglDrawFunc3d yglDrawPix3d; extern yList3d_Elem *yListDirectHead; extern yList3d_Elem *yListCachedHead; extern int yDrawBBox3d; #endif yorick-gl-1.1+cvs20070922+dfsg.orig/glInfo.h0000640000175000017500000000156610313362462020023 0ustar thibautthibaut/* * $Id: glInfo.h,v 1.1.1.1 2005/09/18 22:07:46 dhmunro Exp $ */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ typedef enum { Normal, Wide, Verbose } InfoMode; struct visual_attribs { /* X visual attribs */ int id; int klass; int depth; int redMask, greenMask, blueMask; int colormapSize; int bitsPerRGB; /* GL visual attribs */ int supportsGL; int transparent; int bufferSize; int level; int rgba; int doubleBuffer; int stereo; int auxBuffers; int redSize, greenSize, blueSize, alphaSize; int depthSize; int stencilSize; int accumRedSize, accumGreenSize, accumBlueSize, accumAlphaSize; int numSamples, numMultisample; int visualCaveat; }; yorick-gl-1.1+cvs20070922+dfsg.orig/glStrips.h0000640000175000017500000000602210313362463020405 0ustar thibautthibaut/* * $Id: glStrips.h,v 1.1.1.1 2005/09/18 22:07:47 dhmunro Exp $ * Header file for the routines that draw lists of polygons. */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #ifndef __GLSTRIPS__ #define __GLSTRIPS__ #ifdef __cplusplus extern "C" { #endif extern void yglTstrips(long nstrip, long *len, float *xyz, float *norm, float *colr, long edge, long smooth, long do_light); extern void yglTstripsAlpha(long nstrip, long *len, float *xyz, float *norm, float *colr, long edge, long smooth, long do_light); extern void yglQstrips(long nstrip, long *len, float *xyz, float *norm, float *colr, long edge, long smooth, long do_light); extern void yglQstripsAlpha(long nstrip, long *len, float *xyz, float *norm, float *colr, long edge, long smooth, long do_light); extern void yglTstripsNdx(long nstrip, long numedg, long ntri, long *len, long *ndx, float *xyz, float *norm, float *colr, long edge); extern void yglTstripsAlphaNdx(long nstrip, long numedg, long ntri, long *len, long *ndx, float *xyz, float *norm, float *colr, long edge); void yglTstrips_sm_no_arr(long nstrip, long *len, float *xyz, float *norm, float *colr); void yglQstrips_sm_no_arr(long nstrip, long *len, float *xyz, float *norm, float *colr); void yglTstrip_sm_no_arr(long nobj, float *xyz, float *norm, float *colr); void yglQstrip_sm_no_arr(long nobj, float *xyz, float *norm, float *colr); void yglTstrip_sm_arr(long nobj, float *xyz, float *norm, float *colr); void yglQstrip_sm_arr(long nobj, float *xyz, float *norm, float *colr); void yglTstrip_arr(long nobj, float *xyz, float *norm, float *colr); void yglQstrip_arr(long nobj, float *xyz, float *norm, float *colr); void yglTstrip_no_arr(long nobj, float *xyz, float *norm, float *colr); void yglQstrip_no_arr(long nobj, float *xyz, float *norm, float *colr); void yglTstrip_arr_no_lite(long nvert, float *xyz, float *colr); void yglQstrip_arr_no_lite(long nvert, float *xyz, float *colr); void yglTstrip_no_arr_no_lite(long nvert, float *xyz, float *colr); void yglQstrip_no_arr_no_lite(long nvert, float *xyz, float *colr); extern void yglTarrayCubeMapAlpha(long ntri, float *xyz, float *norm, float *colr, long cpervrt); extern void yglTarrayCubeMap(long ntri, float *xyz, float *norm, float *colr, long cpervrt); void yglTarray(long smooth, long ntri, float *xyz, float *norm, float *colr, long edge, long cpervrt, long emit); void yglTarrayAlpha(long smooth, long ntri, float *xyz, float *norm, float *colr, long edge, long cpervrt, long emit); void yglTarrayEmit(long do_alpha, long ntri, float *xyz, float *colr, long cpervrt); void yglQarray(long smooth, long nquad, float *xyz, float *norm, float *colr, long edge, long cpervrt); void yglQarrayAlpha(long smooth, long nquad, float *xyz, float *norm, float *colr, long edge, long cpervrt); #ifdef __cplusplus } #endif #endif /* Include/Define */ yorick-gl-1.1+cvs20070922+dfsg.orig/yiso3d.i0000640000175000017500000000306210313362470020010 0ustar thibautthibaut/* * $Id: yiso3d.i,v 1.1.1.1 2005/09/18 22:07:52 dhmunro Exp $ * autoloads for yiso3d subpackage of yorgl package */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ /* FIX ME -- many of cntrfunc items have PROTOTYPE comments, * which almost certainly should not be called directly by user */ autoload, "cntrfunc.i", ContourInitCartGrdPcen, ContourInitCartGrdPcenNdx; autoload, "cntrfunc.i", ContourInitCartGrdZcen, ContourInitCartGrdZcenNdx; autoload, "cntrfunc.i", ContourInitCartPcen, ContourInitCartZcen; autoload, "cntrfunc.i", ContourInitCrvGrdPcen, ContourInitCrvGrdPcenNdx; autoload, "cntrfunc.i", ContourInitCrvGrdZcen, ContourInitCrvGrdZcenNdx; autoload, "cntrfunc.i", ContourTetArray, ContourTetArrayNdx, ContourTetHex; autoload, "cntrfunc.i", ContourTetZone, ContourTree, ContourTree2; autoload, "cntrfunc.i", ContourTreeCrv, ContourTreeCrv2, ContourTreeVarr; autoload, "cntrfunc.i", ContourTreeVarr2, MakeContourTree, MakeSliceTreeCrv; autoload, "cntrfunc.i", PrepIsoTet, SliceTree, SliceTreeCrv; autoload, "contour.i", iso3, iso3_tree, iso3_treecrv, iso3_treevarr; autoload, "contour.i", iso3cencrv, iso3cencrvndx, iso3cenreg, iso3cenregndx; autoload, "contour.i", iso3cenregngrd, iso3hex, iso3ndx, iso3zcencrv; autoload, "contour.i", iso3zcencrvndx, iso3zcenreg, iso3zcenregndx; autoload, "contour.i", iso3zcenregngrd, mak_isotree, mak_slice_treecrv; autoload, "contour.i", slice_tree, slice_treecrv;