| @@ -1,10 +1,9 @@ | |||
| /* $Id: glu.h,v 1.21 2000/05/22 19:40:43 brianp Exp $ */ | |||
| /* $Id: glu.h,v 1.22 2000/07/11 14:11:44 brianp Exp $ */ | |||
| /* | |||
| * Mesa 3-D graphics library | |||
| * Version: 3.3 | |||
| * | |||
| * Copyright (C) 1995-1999 Brian Paul | |||
| * Copyright (C) 1995-2000 Brian Paul | |||
| * | |||
| * This library is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Library General Public | |||
| @@ -22,22 +21,23 @@ | |||
| */ | |||
| #ifndef __glu_h__ | |||
| #define __glu_h__ | |||
| #ifndef GLU_H | |||
| #define GLU_H | |||
| #if defined(USE_MGL_NAMESPACE) | |||
| #include "glu_mangle.h" | |||
| #endif | |||
| #include "GL/gl.h" | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| #include <GL/gl.h> | |||
| /* to facilitate clean DLL building ... */ | |||
| #if !defined(OPENSTEP) && (defined(__WIN32__) || defined(__CYGWIN__)) | |||
| # if defined(_MSC_VER) && defined(BUILD_GLU32) /* tag specify we're building mesa as a DLL */ | |||
| @@ -61,7 +61,6 @@ extern "C" { | |||
| #endif | |||
| #ifdef macintosh | |||
| #pragma enumsalwaysint on | |||
| #if PRAGMA_IMPORT_SUPPORTED | |||
| @@ -83,7 +82,7 @@ extern "C" { | |||
| #define GLU_VERSION_1_1 1 | |||
| #define GLU_VERSION_1_2 1 | |||
| #define GLU_TRUE 1 | |||
| @@ -215,8 +214,7 @@ extern "C" { | |||
| #define GLU_EXTENSIONS 100801 | |||
| /*** GLU 1.0 tessellation - obsolete! ***/ | |||
| /*** GLU 1.0 tessellation ***/ | |||
| /* Contour types */ | |||
| #define GLU_CW 100120 | |||
| @@ -233,20 +231,26 @@ extern "C" { | |||
| #define GLU_EDGE_FLAG GLU_TESS_EDGE_FLAG | |||
| /* | |||
| * These are the GLU 1.1 typedefs. GLU 1.3 has different ones! | |||
| */ | |||
| #if defined(__BEOS__) | |||
| /* The BeOS does something funky and makes these typedefs in one | |||
| * of its system headers. | |||
| */ | |||
| #else | |||
| #if defined GLU_VERSION_1_2 | |||
| typedef struct GLUquadric GLUquadricObj; | |||
| typedef struct GLUnurbs GLUnurbsObj; | |||
| /* FIXME: We need to implement the other 1.3 typedefs - GH */ | |||
| typedef struct GLUtesselator GLUtesselator; | |||
| typedef GLUtesselator GLUtriangulatorObj; | |||
| #else | |||
| /* GLU 1.1 and older */ | |||
| typedef struct GLUquadric GLUquadricObj; | |||
| typedef struct GLUtriangulatorObj GLUtriangulatorObj; | |||
| typedef struct GLUnurbs GLUnurbsObj; | |||
| #endif | |||
| #endif | |||
| @@ -306,17 +310,17 @@ GLUAPI const GLubyte* GLAPIENTRY gluErrorString( GLenum errorCode ); | |||
| */ | |||
| GLUAPI GLint GLAPIENTRY gluScaleImage( GLenum format, | |||
| GLint widthin, GLint heightin, | |||
| GLsizei widthin, GLsizei heightin, | |||
| GLenum typein, const void *datain, | |||
| GLint widthout, GLint heightout, | |||
| GLsizei widthout, GLsizei heightout, | |||
| GLenum typeout, void *dataout ); | |||
| GLUAPI GLint GLAPIENTRY gluBuild1DMipmaps( GLenum target, GLint components, | |||
| GLint width, GLenum format, | |||
| GLsizei width, GLenum format, | |||
| GLenum type, const void *data ); | |||
| GLUAPI GLint GLAPIENTRY gluBuild2DMipmaps( GLenum target, GLint components, | |||
| GLint width, GLint height, | |||
| GLsizei width, GLsizei height, | |||
| GLenum format, | |||
| GLenum type, const void *data ); | |||
| @@ -355,14 +359,15 @@ GLUAPI void GLAPIENTRY gluCylinder( GLUquadricObj *qobj, | |||
| GLint slices, GLint stacks ); | |||
| GLUAPI void GLAPIENTRY gluSphere( GLUquadricObj *qobj, | |||
| GLdouble radius, GLint slices, | |||
| GLint stacks ); | |||
| GLdouble radius, | |||
| GLint slices, GLint stacks ); | |||
| GLUAPI void GLAPIENTRY gluDisk( GLUquadricObj *qobj, | |||
| GLdouble innerRadius, GLdouble outerRadius, | |||
| GLint slices, GLint loops ); | |||
| GLUAPI void GLAPIENTRY gluPartialDisk( GLUquadricObj *qobj, GLdouble innerRadius, | |||
| GLUAPI void GLAPIENTRY gluPartialDisk( GLUquadricObj *qobj, | |||
| GLdouble innerRadius, | |||
| GLdouble outerRadius, GLint slices, | |||
| GLint loops, GLdouble startAngle, | |||
| GLdouble sweepAngle ); | |||
| @@ -416,8 +421,8 @@ GLUAPI void GLAPIENTRY gluBeginTrim( GLUnurbsObj *nobj ); | |||
| GLUAPI void GLAPIENTRY gluEndTrim( GLUnurbsObj *nobj ); | |||
| GLUAPI void GLAPIENTRY gluPwlCurve( GLUnurbsObj *nobj, GLint count, | |||
| GLfloat *array, GLint stride, | |||
| GLenum type ); | |||
| GLfloat *array, | |||
| GLint stride, GLenum type ); | |||
| GLUAPI void GLAPIENTRY gluNurbsCallback( GLUnurbsObj *nobj, GLenum which, | |||
| void (GLCALLBACK *fn)() ); | |||
| @@ -430,6 +435,8 @@ GLUAPI void GLAPIENTRY gluNurbsCallback( GLUnurbsObj *nobj, GLenum which, | |||
| * | |||
| */ | |||
| #ifdef GLU_VERSION_1_2 | |||
| GLUAPI GLUtesselator* GLAPIENTRY gluNewTess( void ); | |||
| GLUAPI void GLAPIENTRY gluDeleteTess( GLUtesselator *tobj ); | |||
| @@ -458,17 +465,26 @@ GLUAPI void GLAPIENTRY gluTessCallback( GLUtesselator *tobj, GLenum which, | |||
| GLUAPI void GLAPIENTRY gluGetTessProperty( GLUtesselator *tobj, GLenum which, | |||
| GLdouble *value ); | |||
| /* | |||
| * | |||
| * Obsolete 1.0 tessellation functions | |||
| * | |||
| */ | |||
| #else | |||
| GLUAPI GLUtriangulatorObj* GLAPIENTRY gluNewTess( void ); | |||
| GLUAPI void GLAPIENTRY gluBeginPolygon( GLUtesselator *tobj ); | |||
| GLUAPI void GLAPIENTRY gluTessCallback( GLUtriangulatorObj *tobj, GLenum which, | |||
| void (GLCALLBACK *fn)() ); | |||
| GLUAPI void GLAPIENTRY gluNextContour( GLUtesselator *tobj, GLenum type ); | |||
| GLUAPI void GLAPIENTRY gluDeleteTess( GLUtriangulatorObj *tobj ); | |||
| GLUAPI void GLAPIENTRY gluBeginPolygon( GLUtriangulatorObj *tobj ); | |||
| GLUAPI void GLAPIENTRY gluEndPolygon( GLUtriangulatorObj *tobj ); | |||
| GLUAPI void GLAPIENTRY gluNextContour( GLUtriangulatorObj *tobj, GLenum type ); | |||
| GLUAPI void GLAPIENTRY gluTessVertex( GLUtriangulatorObj *tobj, GLdouble v[3], | |||
| void *data ); | |||
| #endif | |||
| GLUAPI void GLAPIENTRY gluEndPolygon( GLUtesselator *tobj ); | |||
| @@ -488,38 +504,12 @@ GLUAPI const GLubyte* GLAPIENTRY gluGetString( GLenum name ); | |||
| * | |||
| */ | |||
| GLUAPI GLboolean GLAPIENTRY | |||
| gluCheckExtension(const char *extName, const GLubyte *extString); | |||
| GLUAPI GLint GLAPIENTRY | |||
| gluBuild3DMipmaps( GLenum target, GLint internalFormat, GLsizei width, | |||
| GLsizei height, GLsizei depth, GLenum format, | |||
| GLenum type, const void *data ); | |||
| GLUAPI GLint GLAPIENTRY | |||
| gluBuild1DMipmapLevels( GLenum target, GLint internalFormat, GLsizei width, | |||
| GLenum format, GLenum type, GLint level, GLint base, | |||
| GLint max, const void *data ); | |||
| #ifdef GLU_VERSION_1_3 | |||
| GLUAPI GLint GLAPIENTRY | |||
| gluBuild2DMipmapLevels( GLenum target, GLint internalFormat, GLsizei width, | |||
| GLsizei height, GLenum format, GLenum type, | |||
| GLint level, GLint base, GLint max, | |||
| const void *data ); | |||
| GLUAPI GLint GLAPIENTRY | |||
| gluBuild3DMipmapLevels( GLenum target, GLint internalFormat, GLsizei width, | |||
| GLsizei height, GLsizei depth, GLenum format, | |||
| GLenum type, GLint level, GLint base, GLint max, | |||
| const void *data ); | |||
| GLUAPI GLboolean GLAPIENTRY | |||
| gluCheckExtension( const char *extName, const GLubyte *extString ); | |||
| GLUAPI GLint GLAPIENTRY | |||
| gluUnProject4( GLdouble winx, GLdouble winy, GLdouble winz, GLdouble clipw, | |||
| const GLdouble modelMatrix[16], const GLdouble projMatrix[16], | |||
| const GLint viewport[4], GLclampd zNear, GLclampd zFar, | |||
| GLdouble *objx, GLdouble *objy, GLdouble *objz, | |||
| GLdouble *objw ); | |||
| #endif | |||
| @@ -541,4 +531,4 @@ gluUnProject4( GLdouble winx, GLdouble winy, GLdouble winz, GLdouble clipw, | |||
| #endif | |||
| #endif /* __glu_h__ */ | |||
| #endif | |||
| @@ -2,8 +2,8 @@ | |||
| # Tinic Uro <5uro@informatik.uni-hamburg.de> | |||
| # Mesa 3-D graphics library | |||
| # Version: 2.6 | |||
| # Copyright (C) 1995-1997 Brian Paul | |||
| # Version: 3.3 | |||
| # Copyright (C) 1995-2000 Brian Paul | |||
| # | |||
| # This library is free software; you can redistribute it and/or | |||
| # modify it under the terms of the GNU Library General Public | |||
| @@ -29,8 +29,7 @@ INCDIR = ../include | |||
| LIBDIR = ../lib | |||
| SOURCES = glu.c mipmap.c nurbs.c nurbscrv.c nurbssrf.c nurbsutl.c \ | |||
| project.c quadric.c tess.c tess_fist.c tess_hash.c tess_heap.c \ | |||
| tess_winding.c tess_clip.c | |||
| polytest.c project.c quadric.c tess.c tesselat.c | |||
| OBJECTS = $(SOURCES:.c=.o) | |||
| @@ -1,8 +1,9 @@ | |||
| # $Id: Makefile.BeOS-R4,v 1.7 2000/07/11 14:11:04 brianp Exp $ | |||
| # Makefile for GLU for BeOS R4 | |||
| # Mesa 3-D graphics library | |||
| # Version: 3.1 | |||
| # Copyright (C) 1995-1999 Brian Paul | |||
| # Version: 3.3 | |||
| # Copyright (C) 1995-2000 Brian Paul | |||
| # | |||
| # This library is free software; you can redistribute it and/or | |||
| # modify it under the terms of the GNU Library General Public | |||
| @@ -19,41 +20,11 @@ | |||
| # Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| # $Id: Makefile.BeOS-R4,v 1.6 1999/12/06 09:39:34 gareth Exp $ | |||
| # $Log: Makefile.BeOS-R4,v $ | |||
| # Revision 1.6 1999/12/06 09:39:34 gareth | |||
| # Merging in work from 3.1/3.2 branch. Tessellator is essentially fully | |||
| # functional now. | |||
| # | |||
| # Revision 1.5 1999/10/03 00:53:38 gareth | |||
| # Added tessellation winding rule files. | |||
| # | |||
| # Revision 1.4 1999/09/17 00:06:57 brianp | |||
| # version symbol changes | |||
| # | |||
| # Revision 1.3 1999/09/15 15:11:01 brianp | |||
| # added third, tiny version number to mklib scripts | |||
| # | |||
| # Revision 1.2 1999/09/10 02:03:31 gareth | |||
| # Added GLU 1.3 tessellation (except winding rule code). | |||
| # | |||
| # Revision 1.1.1.1 1999/08/19 00:55:42 jtg | |||
| # Imported sources | |||
| # | |||
| # Revision 1.2 1999/02/02 04:44:40 brianp | |||
| # fixed some problems | |||
| # | |||
| # Revision 1.1 1999/01/19 04:10:02 brianp | |||
| # Initial revision | |||
| # | |||
| ##### MACROS ##### | |||
| GLU_MAJOR = 1 | |||
| GLU_MINOR = 2 | |||
| GLU_MINOR = 1 | |||
| GLU_TINY = $(MESA_MAJOR)$(MESA_MINOR)$(MESA_TINY) | |||
| VPATH = RCS | |||
| @@ -62,8 +33,7 @@ INCDIR = ../include | |||
| LIBDIR = ../lib | |||
| SOURCES = glu.c mipmap.c nurbs.c nurbscrv.c nurbssrf.c nurbsutl.c \ | |||
| project.c quadric.c tess.c tess_fist.c tess_hash.c tess_heap.c \ | |||
| tess_winding.c tess_clip.c | |||
| polytest.c project.c quadric.c tess.c tesselat.c | |||
| OBJECTS = $(SOURCES:.c=.o) | |||
| @@ -1,8 +1,8 @@ | |||
| # $Id: Makefile.X11,v 1.7 1999/12/06 09:39:34 gareth Exp $ | |||
| # $Id: Makefile.X11,v 1.8 2000/07/11 14:11:04 brianp Exp $ | |||
| # Mesa 3-D graphics library | |||
| # Version: 3.1 | |||
| # Copyright (C) 1995-1999 Brian Paul | |||
| # Version: 3.3 | |||
| # Copyright (C) 1995-2000 Brian Paul | |||
| # Makefile for GLU library | |||
| @@ -10,7 +10,7 @@ | |||
| ##### MACROS ##### | |||
| GLU_MAJOR = 1 | |||
| GLU_MINOR = 2 | |||
| GLU_MINOR = 1 | |||
| GLU_TINY = 0$(MESA_MAJOR)0$(MESA_MINOR)0$(MESA_TINY) | |||
| VPATH = RCS | |||
| @@ -19,8 +19,7 @@ INCDIR = ../include | |||
| LIBDIR = ../lib | |||
| SOURCES = glu.c mipmap.c nurbs.c nurbscrv.c nurbssrf.c nurbsutl.c \ | |||
| project.c quadric.c tess.c tess_fist.c tess_hash.c tess_heap.c \ | |||
| tess_winding.c tess_clip.c | |||
| polytest.c project.c quadric.c tess.c tesselat.c | |||
| OBJECTS = $(SOURCES:.c=.o) | |||
| @@ -43,8 +43,7 @@ INCDIR = ../include | |||
| LIBDIR = ../lib | |||
| SOURCES = glu.c mipmap.c nurbs.c nurbscrv.c nurbssrf.c nurbsutl.c \ | |||
| project.c quadric.c tess.c tess_fist.c tess_hash.c tess_heap.c \ | |||
| tess_winding.c tess_clip.c | |||
| polytest.c project.c quadric.c tess.c tesselat.c | |||
| OBJECTS = $(SOURCES:.c=.o) | |||
| @@ -1,9 +1,9 @@ | |||
| /* $Id: all.h,v 1.1 1999/08/19 00:55:42 jtg Exp $ */ | |||
| /* $Id: all.h,v 1.2 2000/07/11 14:11:04 brianp Exp $ */ | |||
| /* | |||
| * Mesa 3-D graphics library | |||
| * Version: 2.3 | |||
| * Copyright (C) 1995-1997 Brian Paul | |||
| * Version: 3.3 | |||
| * Copyright (C) 1995-2000 Brian Paul | |||
| * | |||
| * This library is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Library General Public | |||
| @@ -21,20 +21,6 @@ | |||
| */ | |||
| /* | |||
| * $Log: all.h,v $ | |||
| * Revision 1.1 1999/08/19 00:55:42 jtg | |||
| * Initial revision | |||
| * | |||
| * Revision 1.2 1997/11/20 00:28:20 brianp | |||
| * changed PCH to PC_HEADER | |||
| * | |||
| * Revision 1.1 1997/05/28 02:29:14 brianp | |||
| * Initial revision | |||
| * | |||
| */ | |||
| /* | |||
| * This file includes all .h files needed for the GLU source code for | |||
| * the purpose of precompiled headers. | |||
| @@ -50,7 +36,7 @@ | |||
| #ifndef PC_HEADER | |||
| This is an error. all.h should be included only if PCH is defined. | |||
| This is an error. all.h should be included only if PCH is defined. | |||
| #endif | |||
| @@ -66,4 +52,4 @@ | |||
| #include "tess.h" | |||
| #endif /*GLU_ALL_H*/ | |||
| #endif /*GLU_ALL_H */ | |||
| @@ -1,9 +1,9 @@ | |||
| /* $Id: glu.c,v 1.19 2000/01/07 07:22:48 brianp Exp $ */ | |||
| /* $Id: glu.c,v 1.20 2000/07/11 14:11:04 brianp Exp $ */ | |||
| /* | |||
| * Mesa 3-D graphics library | |||
| * Version: 3.3 | |||
| * Copyright (C) 1999-2000 Brian Paul | |||
| * Copyright (C) 1995-2000 Brian Paul | |||
| * | |||
| * This library is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Library General Public | |||
| @@ -21,108 +21,6 @@ | |||
| */ | |||
| /* | |||
| * $Log: glu.c,v $ | |||
| * Revision 1.19 2000/01/07 07:22:48 brianp | |||
| * updated version string | |||
| * | |||
| * Revision 1.18 1999/11/22 22:15:50 brianp | |||
| * removed GLU_EXT_get_proc_address from ext strings | |||
| * | |||
| * Revision 1.17 1999/11/19 21:23:37 brianp | |||
| * replace encounteed with encountered | |||
| * | |||
| * Revision 1.16 1999/10/27 09:47:41 brianp | |||
| * disabled gluGetProcAddressEXT | |||
| * | |||
| * Revision 1.15 1999/09/19 02:03:19 tjump | |||
| * More Win32 build compliance fixups | |||
| * | |||
| * Revision 1.14 1999/09/17 12:21:53 brianp | |||
| * glGetProcAddressEXT changes to accomodate Win32 and non-Win32 | |||
| * | |||
| * Revision 1.13 1999/09/17 03:17:18 tjump | |||
| * Patch error fixup | |||
| * | |||
| * Revision 1.12 1999/09/17 03:07:28 tjump | |||
| * Win32 build req't updates | |||
| * | |||
| * Revision 1.11 1999/09/17 01:00:38 brianp | |||
| * fixed typo | |||
| * | |||
| * Revision 1.10 1999/09/17 00:06:14 brianp | |||
| * gluGetProcAddressEXT change for C++ / BeOS | |||
| * | |||
| * Revision 1.9 1999/09/16 22:37:56 brianp | |||
| * added some casts in gluGetProcAddressEXT() | |||
| * | |||
| * Revision 1.8 1999/09/16 16:53:28 brianp | |||
| * clean-up of GLU_EXT_get_proc_address | |||
| * | |||
| * Revision 1.7 1999/09/14 00:11:40 brianp | |||
| * added gluCheckExtension() | |||
| * | |||
| * Revision 1.6 1999/09/13 14:31:32 joukj | |||
| * | |||
| * strcmp needs the string.h | |||
| * | |||
| * Revision 1.5 1999/09/11 12:04:54 brianp | |||
| * added 1.2 function to gluGetProcAddressEXT() | |||
| * | |||
| * Revision 1.4 1999/09/11 11:36:26 brianp | |||
| * added GLU_EXT_get_proc_address | |||
| * | |||
| * Revision 1.3 1999/09/10 04:32:10 gareth | |||
| * Fixed triangle output, recovery process termination. | |||
| * | |||
| * Revision 1.2 1999/09/10 02:03:31 gareth | |||
| * Added GLU 1.3 tessellation (except winding rule code). | |||
| * | |||
| * Revision 1.1.1.1 1999/08/19 00:55:42 jtg | |||
| * Imported sources | |||
| * | |||
| * Revision 1.13 1999/03/31 19:07:28 brianp | |||
| * added GL_EXT_abgr to extensions | |||
| * | |||
| * Revision 1.12 1999/02/06 06:12:41 brianp | |||
| * updated version string to 3.1 | |||
| * | |||
| * Revision 1.11 1999/01/03 03:23:15 brianp | |||
| * now using GLAPIENTRY and GLCALLBACK keywords (Ted Jump) | |||
| * | |||
| * Revision 1.10 1998/04/22 00:35:50 brianp | |||
| * changed version to 3.0 | |||
| * | |||
| * Revision 1.9 1997/12/09 03:03:32 brianp | |||
| * changed version to 2.6 | |||
| * | |||
| * Revision 1.8 1997/10/04 01:30:20 brianp | |||
| * changed version to 2.5 | |||
| * | |||
| * Revision 1.7 1997/08/13 01:25:21 brianp | |||
| * changed version string to 2.4 | |||
| * | |||
| * Revision 1.6 1997/07/24 01:28:44 brianp | |||
| * changed precompiled header symbol from PCH to PC_HEADER | |||
| * | |||
| * Revision 1.5 1997/07/13 22:59:11 brianp | |||
| * added const to viewport parameter of gluPickMatrix() | |||
| * | |||
| * Revision 1.4 1997/05/28 02:29:38 brianp | |||
| * added support for precompiled headers (PCH), inserted APIENTRY keyword | |||
| * | |||
| * Revision 1.3 1997/04/12 16:19:02 brianp | |||
| * changed version to 2.3 | |||
| * | |||
| * Revision 1.2 1997/03/11 00:58:34 brianp | |||
| * changed version to 2.2 | |||
| * | |||
| * Revision 1.1 1996/09/27 01:19:39 brianp | |||
| * Initial revision | |||
| * | |||
| */ | |||
| #ifdef PC_HEADER | |||
| #include "all.h" | |||
| #else | |||
| @@ -148,9 +46,10 @@ | |||
| void GLAPIENTRY gluLookAt( GLdouble eyex, GLdouble eyey, GLdouble eyez, | |||
| GLdouble centerx, GLdouble centery, GLdouble centerz, | |||
| GLdouble upx, GLdouble upy, GLdouble upz ) | |||
| void GLAPIENTRY | |||
| gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez, | |||
| GLdouble centerx, GLdouble centery, GLdouble centerz, | |||
| GLdouble upx, GLdouble upy, GLdouble upz) | |||
| { | |||
| GLdouble m[16]; | |||
| GLdouble x[3], y[3], z[3]; | |||
| @@ -162,8 +61,8 @@ void GLAPIENTRY gluLookAt( GLdouble eyex, GLdouble eyey, GLdouble eyez, | |||
| z[0] = eyex - centerx; | |||
| z[1] = eyey - centery; | |||
| z[2] = eyez - centerz; | |||
| mag = sqrt( z[0]*z[0] + z[1]*z[1] + z[2]*z[2] ); | |||
| if (mag) { /* mpichler, 19950515 */ | |||
| mag = sqrt(z[0] * z[0] + z[1] * z[1] + z[2] * z[2]); | |||
| if (mag) { /* mpichler, 19950515 */ | |||
| z[0] /= mag; | |||
| z[1] /= mag; | |||
| z[2] /= mag; | |||
| @@ -175,28 +74,28 @@ void GLAPIENTRY gluLookAt( GLdouble eyex, GLdouble eyey, GLdouble eyez, | |||
| y[2] = upz; | |||
| /* X vector = Y cross Z */ | |||
| x[0] = y[1]*z[2] - y[2]*z[1]; | |||
| x[1] = -y[0]*z[2] + y[2]*z[0]; | |||
| x[2] = y[0]*z[1] - y[1]*z[0]; | |||
| x[0] = y[1] * z[2] - y[2] * z[1]; | |||
| x[1] = -y[0] * z[2] + y[2] * z[0]; | |||
| x[2] = y[0] * z[1] - y[1] * z[0]; | |||
| /* Recompute Y = Z cross X */ | |||
| y[0] = z[1]*x[2] - z[2]*x[1]; | |||
| y[1] = -z[0]*x[2] + z[2]*x[0]; | |||
| y[2] = z[0]*x[1] - z[1]*x[0]; | |||
| y[0] = z[1] * x[2] - z[2] * x[1]; | |||
| y[1] = -z[0] * x[2] + z[2] * x[0]; | |||
| y[2] = z[0] * x[1] - z[1] * x[0]; | |||
| /* mpichler, 19950515 */ | |||
| /* cross product gives area of parallelogram, which is < 1.0 for | |||
| * non-perpendicular unit-length vectors; so normalize x, y here | |||
| */ | |||
| mag = sqrt( x[0]*x[0] + x[1]*x[1] + x[2]*x[2] ); | |||
| mag = sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]); | |||
| if (mag) { | |||
| x[0] /= mag; | |||
| x[1] /= mag; | |||
| x[2] /= mag; | |||
| } | |||
| mag = sqrt( y[0]*y[0] + y[1]*y[1] + y[2]*y[2] ); | |||
| mag = sqrt(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]); | |||
| if (mag) { | |||
| y[0] /= mag; | |||
| y[1] /= mag; | |||
| @@ -204,47 +103,59 @@ void GLAPIENTRY gluLookAt( GLdouble eyex, GLdouble eyey, GLdouble eyez, | |||
| } | |||
| #define M(row,col) m[col*4+row] | |||
| M(0,0) = x[0]; M(0,1) = x[1]; M(0,2) = x[2]; M(0,3) = 0.0; | |||
| M(1,0) = y[0]; M(1,1) = y[1]; M(1,2) = y[2]; M(1,3) = 0.0; | |||
| M(2,0) = z[0]; M(2,1) = z[1]; M(2,2) = z[2]; M(2,3) = 0.0; | |||
| M(3,0) = 0.0; M(3,1) = 0.0; M(3,2) = 0.0; M(3,3) = 1.0; | |||
| M(0, 0) = x[0]; | |||
| M(0, 1) = x[1]; | |||
| M(0, 2) = x[2]; | |||
| M(0, 3) = 0.0; | |||
| M(1, 0) = y[0]; | |||
| M(1, 1) = y[1]; | |||
| M(1, 2) = y[2]; | |||
| M(1, 3) = 0.0; | |||
| M(2, 0) = z[0]; | |||
| M(2, 1) = z[1]; | |||
| M(2, 2) = z[2]; | |||
| M(2, 3) = 0.0; | |||
| M(3, 0) = 0.0; | |||
| M(3, 1) = 0.0; | |||
| M(3, 2) = 0.0; | |||
| M(3, 3) = 1.0; | |||
| #undef M | |||
| glMultMatrixd( m ); | |||
| glMultMatrixd(m); | |||
| /* Translate Eye to Origin */ | |||
| glTranslated( -eyex, -eyey, -eyez ); | |||
| glTranslated(-eyex, -eyey, -eyez); | |||
| } | |||
| void GLAPIENTRY gluOrtho2D( GLdouble left, GLdouble right, | |||
| GLdouble bottom, GLdouble top ) | |||
| void GLAPIENTRY | |||
| gluOrtho2D(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top) | |||
| { | |||
| glOrtho( left, right, bottom, top, -1.0, 1.0 ); | |||
| glOrtho(left, right, bottom, top, -1.0, 1.0); | |||
| } | |||
| void GLAPIENTRY gluPerspective( GLdouble fovy, GLdouble aspect, | |||
| GLdouble zNear, GLdouble zFar ) | |||
| void GLAPIENTRY | |||
| gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar) | |||
| { | |||
| GLdouble xmin, xmax, ymin, ymax; | |||
| ymax = zNear * tan( fovy * M_PI / 360.0 ); | |||
| ymax = zNear * tan(fovy * M_PI / 360.0); | |||
| ymin = -ymax; | |||
| xmin = ymin * aspect; | |||
| xmax = ymax * aspect; | |||
| glFrustum( xmin, xmax, ymin, ymax, zNear, zFar ); | |||
| glFrustum(xmin, xmax, ymin, ymax, zNear, zFar); | |||
| } | |||
| void GLAPIENTRY gluPickMatrix( GLdouble x, GLdouble y, | |||
| GLdouble width, GLdouble height, | |||
| const GLint viewport[4] ) | |||
| void GLAPIENTRY | |||
| gluPickMatrix(GLdouble x, GLdouble y, | |||
| GLdouble width, GLdouble height, const GLint viewport[4]) | |||
| { | |||
| GLfloat m[16]; | |||
| GLfloat sx, sy; | |||
| @@ -256,18 +167,31 @@ void GLAPIENTRY gluPickMatrix( GLdouble x, GLdouble y, | |||
| ty = (viewport[3] + 2.0 * (viewport[1] - y)) / height; | |||
| #define M(row,col) m[col*4+row] | |||
| M(0,0) = sx; M(0,1) = 0.0; M(0,2) = 0.0; M(0,3) = tx; | |||
| M(1,0) = 0.0; M(1,1) = sy; M(1,2) = 0.0; M(1,3) = ty; | |||
| M(2,0) = 0.0; M(2,1) = 0.0; M(2,2) = 1.0; M(2,3) = 0.0; | |||
| M(3,0) = 0.0; M(3,1) = 0.0; M(3,2) = 0.0; M(3,3) = 1.0; | |||
| M(0, 0) = sx; | |||
| M(0, 1) = 0.0; | |||
| M(0, 2) = 0.0; | |||
| M(0, 3) = tx; | |||
| M(1, 0) = 0.0; | |||
| M(1, 1) = sy; | |||
| M(1, 2) = 0.0; | |||
| M(1, 3) = ty; | |||
| M(2, 0) = 0.0; | |||
| M(2, 1) = 0.0; | |||
| M(2, 2) = 1.0; | |||
| M(2, 3) = 0.0; | |||
| M(3, 0) = 0.0; | |||
| M(3, 1) = 0.0; | |||
| M(3, 2) = 0.0; | |||
| M(3, 3) = 1.0; | |||
| #undef M | |||
| glMultMatrixf( m ); | |||
| glMultMatrixf(m); | |||
| } | |||
| const GLubyte* GLAPIENTRY gluErrorString( GLenum errorCode ) | |||
| const GLubyte *GLAPIENTRY | |||
| gluErrorString(GLenum errorCode) | |||
| { | |||
| static char *tess_error[] = { | |||
| "missing gluBeginPolygon", | |||
| @@ -320,48 +244,48 @@ const GLubyte* GLAPIENTRY gluErrorString( GLenum errorCode ) | |||
| }; | |||
| /* GL Errors */ | |||
| if (errorCode==GL_NO_ERROR) { | |||
| if (errorCode == GL_NO_ERROR) { | |||
| return (GLubyte *) "no error"; | |||
| } | |||
| else if (errorCode==GL_INVALID_VALUE) { | |||
| else if (errorCode == GL_INVALID_VALUE) { | |||
| return (GLubyte *) "invalid value"; | |||
| } | |||
| else if (errorCode==GL_INVALID_ENUM) { | |||
| else if (errorCode == GL_INVALID_ENUM) { | |||
| return (GLubyte *) "invalid enum"; | |||
| } | |||
| else if (errorCode==GL_INVALID_OPERATION) { | |||
| else if (errorCode == GL_INVALID_OPERATION) { | |||
| return (GLubyte *) "invalid operation"; | |||
| } | |||
| else if (errorCode==GL_STACK_OVERFLOW) { | |||
| else if (errorCode == GL_STACK_OVERFLOW) { | |||
| return (GLubyte *) "stack overflow"; | |||
| } | |||
| else if (errorCode==GL_STACK_UNDERFLOW) { | |||
| else if (errorCode == GL_STACK_UNDERFLOW) { | |||
| return (GLubyte *) "stack underflow"; | |||
| } | |||
| else if (errorCode==GL_OUT_OF_MEMORY) { | |||
| else if (errorCode == GL_OUT_OF_MEMORY) { | |||
| return (GLubyte *) "out of memory"; | |||
| } | |||
| /* GLU Errors */ | |||
| else if (errorCode==GLU_NO_ERROR) { | |||
| else if (errorCode == GLU_NO_ERROR) { | |||
| return (GLubyte *) "no error"; | |||
| } | |||
| else if (errorCode==GLU_INVALID_ENUM) { | |||
| else if (errorCode == GLU_INVALID_ENUM) { | |||
| return (GLubyte *) "invalid enum"; | |||
| } | |||
| else if (errorCode==GLU_INVALID_VALUE) { | |||
| else if (errorCode == GLU_INVALID_VALUE) { | |||
| return (GLubyte *) "invalid value"; | |||
| } | |||
| else if (errorCode==GLU_OUT_OF_MEMORY) { | |||
| else if (errorCode == GLU_OUT_OF_MEMORY) { | |||
| return (GLubyte *) "out of memory"; | |||
| } | |||
| else if (errorCode==GLU_INCOMPATIBLE_GL_VERSION) { | |||
| else if (errorCode == GLU_INCOMPATIBLE_GL_VERSION) { | |||
| return (GLubyte *) "incompatible GL version"; | |||
| } | |||
| else if (errorCode>=GLU_TESS_ERROR1 && errorCode<=GLU_TESS_ERROR8) { | |||
| return (GLubyte *) tess_error[errorCode-GLU_TESS_ERROR1]; | |||
| else if (errorCode >= GLU_TESS_ERROR1 && errorCode <= GLU_TESS_ERROR8) { | |||
| return (GLubyte *) tess_error[errorCode - GLU_TESS_ERROR1]; | |||
| } | |||
| else if (errorCode>=GLU_NURBS_ERROR1 && errorCode<=GLU_NURBS_ERROR37) { | |||
| return (GLubyte *) nurbs_error[errorCode-GLU_NURBS_ERROR1]; | |||
| else if (errorCode >= GLU_NURBS_ERROR1 && errorCode <= GLU_NURBS_ERROR37) { | |||
| return (GLubyte *) nurbs_error[errorCode - GLU_NURBS_ERROR1]; | |||
| } | |||
| else { | |||
| return NULL; | |||
| @@ -374,58 +298,60 @@ const GLubyte* GLAPIENTRY gluErrorString( GLenum errorCode ) | |||
| * New in GLU 1.1 | |||
| */ | |||
| const GLubyte* GLAPIENTRY gluGetString( GLenum name ) | |||
| const GLubyte *GLAPIENTRY | |||
| gluGetString(GLenum name) | |||
| { | |||
| static char *extensions = "GL_EXT_abgr"; | |||
| static char *version = "1.2 Mesa 3.3 beta"; | |||
| static char *version = "1.1 Mesa 3.2.1"; | |||
| switch (name) { | |||
| case GLU_EXTENSIONS: | |||
| return (GLubyte *) extensions; | |||
| case GLU_VERSION: | |||
| return (GLubyte *) version; | |||
| default: | |||
| return NULL; | |||
| case GLU_EXTENSIONS: | |||
| return (GLubyte *) extensions; | |||
| case GLU_VERSION: | |||
| return (GLubyte *) version; | |||
| default: | |||
| return NULL; | |||
| } | |||
| } | |||
| #if 0 /* gluGetProcAddressEXT not finalized yet! */ | |||
| #if 0 /* gluGetProcAddressEXT not finalized yet! */ | |||
| #ifdef __cplusplus | |||
| /* for BeOS R4.5 */ | |||
| void GLAPIENTRY (*gluGetProcAddressEXT(const GLubyte *procName))(...) | |||
| void GLAPIENTRY(*gluGetProcAddressEXT(const GLubyte * procName)) (...) | |||
| #else | |||
| void (GLAPIENTRY *gluGetProcAddressEXT(const GLubyte *procName))() | |||
| void (GLAPIENTRY * gluGetProcAddressEXT(const GLubyte * procName)) () | |||
| #endif | |||
| { | |||
| struct proc { | |||
| struct proc | |||
| { | |||
| const char *name; | |||
| void *address; | |||
| }; | |||
| static struct proc procTable[] = { | |||
| { "gluGetProcAddressEXT", (void *) gluGetProcAddressEXT }, /* me! */ | |||
| {"gluGetProcAddressEXT", (void *) gluGetProcAddressEXT}, /* me! */ | |||
| /* new 1.1 functions */ | |||
| { "gluGetString", (void *) gluGetString }, | |||
| {"gluGetString", (void *) gluGetString}, | |||
| /* new 1.2 functions */ | |||
| { "gluTessBeginPolygon", (void *) gluTessBeginPolygon }, | |||
| { "gluTessBeginContour", (void *) gluTessBeginContour }, | |||
| { "gluTessEndContour", (void *) gluTessEndContour }, | |||
| { "gluTessEndPolygon", (void *) gluTessEndPolygon }, | |||
| { "gluGetTessProperty", (void *) gluGetTessProperty }, | |||
| {"gluTessBeginPolygon", (void *) gluTessBeginPolygon}, | |||
| {"gluTessBeginContour", (void *) gluTessBeginContour}, | |||
| {"gluTessEndContour", (void *) gluTessEndContour}, | |||
| {"gluTessEndPolygon", (void *) gluTessEndPolygon}, | |||
| {"gluGetTessProperty", (void *) gluGetTessProperty}, | |||
| /* new 1.3 functions */ | |||
| { NULL, NULL } | |||
| {NULL, NULL} | |||
| }; | |||
| GLuint i; | |||
| for (i = 0; procTable[i].address; i++) { | |||
| if (strcmp((const char *) procName, procTable[i].name) == 0) | |||
| return (void (GLAPIENTRY *)()) procTable[i].address; | |||
| return (void (GLAPIENTRY *) ()) procTable[i].address; | |||
| } | |||
| return NULL; | |||
| @@ -438,8 +364,9 @@ const GLubyte* GLAPIENTRY gluGetString( GLenum name ) | |||
| /* | |||
| * New in GLU 1.3 | |||
| */ | |||
| #ifdef GLU_VERSION_1_3 | |||
| GLboolean GLAPIENTRY | |||
| gluCheckExtension( const char *extName, const GLubyte *extString ) | |||
| gluCheckExtension(const char *extName, const GLubyte * extString) | |||
| { | |||
| assert(extName); | |||
| assert(extString); | |||
| @@ -448,14 +375,15 @@ gluCheckExtension( const char *extName, const GLubyte *extString ) | |||
| const char *start = (const char *) extString; | |||
| while (1) { | |||
| const char *c = strstr( start, extName ); | |||
| if (!c) | |||
| return GL_FALSE; | |||
| const char *c = strstr(start, extName); | |||
| if (!c) | |||
| return GL_FALSE; | |||
| if ((c == start || c[-1] == ' ') && (c[len] == ' ' || c[len] == 0)) | |||
| return GL_TRUE; | |||
| if ((c == start || c[-1] == ' ') && (c[len] == ' ' || c[len] == 0)) | |||
| return GL_TRUE; | |||
| start = c + len; | |||
| start = c + len; | |||
| } | |||
| } | |||
| } | |||
| #endif | |||
| @@ -1,9 +1,9 @@ | |||
| /* $Id: gluP.h,v 1.4 2000/05/22 19:41:11 brianp Exp $ */ | |||
| /* $Id: gluP.h,v 1.5 2000/07/11 14:11:04 brianp Exp $ */ | |||
| /* | |||
| * Mesa 3-D graphics library | |||
| * Version: 3.1 | |||
| * Copyright (C) 1995-1999 Brian Paul | |||
| * Version: 3.3 | |||
| * Copyright (C) 1995-2000 Brian Paul | |||
| * | |||
| * This library is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Library General Public | |||
| @@ -21,43 +21,6 @@ | |||
| */ | |||
| /* | |||
| * $Log: gluP.h,v $ | |||
| * Revision 1.4 2000/05/22 19:41:11 brianp | |||
| * replaced __CYGWIN32__ with __CYGWIN__ | |||
| * | |||
| * Revision 1.3 2000/05/22 16:25:37 brianp | |||
| * added some Window-isms formerly in gl.h | |||
| * | |||
| * Revision 1.2 1999/12/07 09:02:12 joukj | |||
| * | |||
| * Committing in . | |||
| * | |||
| * Make supportupdate for VMS | |||
| * | |||
| * Modified Files: | |||
| * Mesa/src-glu/descrip.mms Mesa/src-glu/gluP.h | |||
| * ---------------------------------------------------------------------- | |||
| * | |||
| * Revision 1.1.1.1 1999/08/19 00:55:42 jtg | |||
| * Imported sources | |||
| * | |||
| * Revision 1.4 1999/01/03 03:23:15 brianp | |||
| * now using GLAPIENTRY and GLCALLBACK keywords (Ted Jump) | |||
| * | |||
| * Revision 1.3 1997/08/01 22:25:27 brianp | |||
| * check for Cygnus Win32 (Stephen Rehel) | |||
| * | |||
| * Revision 1.2 1997/05/27 02:59:46 brianp | |||
| * added defines for APIENTRY and CALLBACK if not compiling on Win32 | |||
| * | |||
| * Revision 1.1 1996/09/27 01:19:39 brianp | |||
| * Initial revision | |||
| * | |||
| */ | |||
| /* | |||
| * This file allows the GLU code to be compiled either with the Mesa | |||
| * headers or with the real OpenGL headers. | |||
| @@ -68,12 +31,11 @@ | |||
| #define GLUP_H | |||
| #include "GL/gl.h" | |||
| #include "GL/glu.h" | |||
| #include <GL/gl.h> | |||
| #include <GL/glu.h> | |||
| #include <string.h> | |||
| #if defined(_WIN32) && !defined(__WIN32__) | |||
| # define __WIN32__ | |||
| #endif | |||
| @@ -153,8 +115,7 @@ typedef struct tagPIXELFORMATDESCRIPTOR PIXELFORMATDESCRIPTOR, *PPIXELFORMATDESC | |||
| #ifndef MESA | |||
| #ifndef GLU_TESS_ERROR9 | |||
| /* If we're using the real OpenGL header files... */ | |||
| # define GLU_TESS_ERROR9 100159 | |||
| #endif | |||
| @@ -1,9 +1,9 @@ | |||
| /* $Id: nurbs.h,v 1.2 1999/11/11 03:21:43 kendallb Exp $ */ | |||
| /* $Id: nurbs.h,v 1.3 2000/07/11 14:11:04 brianp Exp $ */ | |||
| /* | |||
| * Mesa 3-D graphics library | |||
| * Version: 3.1 | |||
| * Copyright (C) 1995-1999 Brian Paul | |||
| * Version: 3.3 | |||
| * Copyright (C) 1995-2000 Brian Paul | |||
| * | |||
| * This library is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Library General Public | |||
| @@ -21,46 +21,6 @@ | |||
| */ | |||
| /* | |||
| * $Log: nurbs.h,v $ | |||
| * Revision 1.2 1999/11/11 03:21:43 kendallb | |||
| * | |||
| * . Updated GL/gl.h with GLCALLACKP and GLAPIENTRYP macros for compatibility | |||
| * with the IBM VisualAge C++ compiler. Eventually some more code will be | |||
| * needed in the headers to enable the reversal of (__stdcall*) to (*__stdcall) | |||
| * for the IBM compilers, however we currently build using our own header files | |||
| * that already handle this. | |||
| * | |||
| * . Changed instances of (GLCALLBACK*) to GLCALLBACKP for compatibility | |||
| * with the IBM VisualAge C++ compiler in src-glu. | |||
| * | |||
| * . Misc cleanups for warnings generated with Watcom C++ in src-glu. Compiles | |||
| * with 0 warnings now. | |||
| * | |||
| * . tess_hash.c: line 244 - Why is this function stubbed out? I removed the | |||
| * code with a #if 0 to avoid a compiler warning, but it looks dangerous. | |||
| * | |||
| * Revision 1.1.1.1 1999/08/19 00:55:42 jtg | |||
| * Imported sources | |||
| * | |||
| * Revision 1.5 1999/02/27 13:55:31 brianp | |||
| * fixed BeOS-related GLU typedef problems | |||
| * | |||
| * Revision 1.4 1999/01/03 03:23:15 brianp | |||
| * now using GLAPIENTRY and GLCALLBACK keywords (Ted Jump) | |||
| * | |||
| * Revision 1.3 1997/05/27 03:18:23 brianp | |||
| * minor clean-up | |||
| * | |||
| * Revision 1.2 1997/05/27 03:00:16 brianp | |||
| * incorporated Bogdan's new NURBS code | |||
| * | |||
| * Revision 1.1 1996/09/27 01:19:39 brianp | |||
| * Initial revision | |||
| * | |||
| */ | |||
| /* | |||
| * NURBS implementation written by Bogdan Sikorski (bogdan@cira.it) | |||
| * See README2 for more info. | |||
| @@ -71,198 +31,222 @@ | |||
| #define NURBS_H | |||
| #define EPSILON 1e-06 /* epsilon for double precision compares */ | |||
| #define EPSILON 1e-06 /* epsilon for double precision compares */ | |||
| typedef enum | |||
| { | |||
| GLU_NURBS_CURVE, GLU_NURBS_SURFACE, GLU_NURBS_TRIM, GLU_NURBS_NO_TRIM, | |||
| GLU_NURBS_TRIM_DONE, GLU_NURBS_NONE | |||
| } GLU_nurbs_enum; | |||
| GLU_NURBS_CURVE, GLU_NURBS_SURFACE, GLU_NURBS_TRIM, GLU_NURBS_NO_TRIM, | |||
| GLU_NURBS_TRIM_DONE, GLU_NURBS_NONE | |||
| } | |||
| GLU_nurbs_enum; | |||
| typedef enum | |||
| { | |||
| GLU_TRIM_NURBS, GLU_TRIM_PWL | |||
| } GLU_trim_enum; | |||
| GLU_TRIM_NURBS, GLU_TRIM_PWL | |||
| } | |||
| GLU_trim_enum; | |||
| typedef struct | |||
| { | |||
| GLint sknot_count; | |||
| GLfloat *sknot; | |||
| GLint tknot_count; | |||
| GLfloat *tknot; | |||
| GLint s_stride; | |||
| GLint t_stride; | |||
| GLfloat *ctrlarray; | |||
| GLint sorder; | |||
| GLint torder; | |||
| GLint dim; | |||
| GLenum type; | |||
| } surface_attribs; | |||
| GLint sknot_count; | |||
| GLfloat *sknot; | |||
| GLint tknot_count; | |||
| GLfloat *tknot; | |||
| GLint s_stride; | |||
| GLint t_stride; | |||
| GLfloat *ctrlarray; | |||
| GLint sorder; | |||
| GLint torder; | |||
| GLint dim; | |||
| GLenum type; | |||
| } | |||
| surface_attribs; | |||
| typedef struct | |||
| { | |||
| surface_attribs geom; | |||
| surface_attribs color; | |||
| surface_attribs texture; | |||
| surface_attribs normal; | |||
| } nurbs_surface; | |||
| surface_attribs geom; | |||
| surface_attribs color; | |||
| surface_attribs texture; | |||
| surface_attribs normal; | |||
| } | |||
| nurbs_surface; | |||
| typedef struct | |||
| { | |||
| GLint knot_count; | |||
| GLfloat *knot; | |||
| GLint stride; | |||
| GLfloat *ctrlarray; | |||
| GLint order; | |||
| GLint dim; | |||
| GLenum type; | |||
| } curve_attribs; | |||
| GLint knot_count; | |||
| GLfloat *knot; | |||
| GLint stride; | |||
| GLfloat *ctrlarray; | |||
| GLint order; | |||
| GLint dim; | |||
| GLenum type; | |||
| } | |||
| curve_attribs; | |||
| typedef struct | |||
| { | |||
| GLint pt_count; | |||
| GLfloat *ctrlarray; | |||
| GLint stride; | |||
| GLint dim; | |||
| GLenum type; | |||
| } pwl_curve_attribs; | |||
| GLint pt_count; | |||
| GLfloat *ctrlarray; | |||
| GLint stride; | |||
| GLint dim; | |||
| GLenum type; | |||
| } | |||
| pwl_curve_attribs; | |||
| typedef struct | |||
| { | |||
| curve_attribs geom; | |||
| curve_attribs color; | |||
| curve_attribs texture; | |||
| curve_attribs normal; | |||
| } nurbs_curve; | |||
| curve_attribs geom; | |||
| curve_attribs color; | |||
| curve_attribs texture; | |||
| curve_attribs normal; | |||
| } | |||
| nurbs_curve; | |||
| typedef struct trim_list_str | |||
| { | |||
| GLU_trim_enum trim_type; | |||
| union | |||
| { | |||
| pwl_curve_attribs pwl_curve; | |||
| curve_attribs nurbs_curve; | |||
| } curve; | |||
| struct trim_list_str *next; | |||
| } trim_list; | |||
| GLU_trim_enum trim_type; | |||
| union | |||
| { | |||
| pwl_curve_attribs pwl_curve; | |||
| curve_attribs nurbs_curve; | |||
| } | |||
| curve; | |||
| struct trim_list_str *next; | |||
| } | |||
| trim_list; | |||
| typedef struct seg_trim_str | |||
| { | |||
| GLfloat *points; | |||
| GLint pt_cnt,seg_array_len; | |||
| struct seg_trim_str *next; | |||
| } trim_segments; | |||
| GLfloat *points; | |||
| GLint pt_cnt, seg_array_len; | |||
| struct seg_trim_str *next; | |||
| } | |||
| trim_segments; | |||
| typedef struct nurbs_trim_str | |||
| { | |||
| trim_list *trim_loop; | |||
| trim_segments *segments; | |||
| struct nurbs_trim_str *next; | |||
| } nurbs_trim; | |||
| trim_list *trim_loop; | |||
| trim_segments *segments; | |||
| struct nurbs_trim_str *next; | |||
| } | |||
| nurbs_trim; | |||
| typedef struct | |||
| { | |||
| GLfloat model[16],proj[16],viewport[4]; | |||
| } culling_and_sampling_str; | |||
| struct GLUnurbs { | |||
| GLboolean culling; | |||
| GLenum error; | |||
| void (GLCALLBACKP error_callback)( GLenum err ); | |||
| GLenum display_mode; | |||
| GLU_nurbs_enum nurbs_type; | |||
| GLboolean auto_load_matrix; | |||
| culling_and_sampling_str | |||
| sampling_matrices; | |||
| GLenum sampling_method; | |||
| GLfloat sampling_tolerance; | |||
| GLfloat parametric_tolerance; | |||
| GLint u_step, v_step; | |||
| nurbs_surface surface; | |||
| nurbs_curve curve; | |||
| nurbs_trim *trim; | |||
| GLfloat model[16], proj[16], viewport[4]; | |||
| } | |||
| culling_and_sampling_str; | |||
| struct GLUnurbs | |||
| { | |||
| GLboolean culling; | |||
| GLenum error; | |||
| void (GLCALLBACK * error_callback) (GLenum err); | |||
| GLenum display_mode; | |||
| GLU_nurbs_enum nurbs_type; | |||
| GLboolean auto_load_matrix; | |||
| culling_and_sampling_str sampling_matrices; | |||
| GLenum sampling_method; | |||
| GLfloat sampling_tolerance; | |||
| GLfloat parametric_tolerance; | |||
| GLint u_step, v_step; | |||
| nurbs_surface surface; | |||
| nurbs_curve curve; | |||
| nurbs_trim *trim; | |||
| }; | |||
| typedef struct | |||
| { | |||
| GLfloat *knot; | |||
| GLint nknots; | |||
| GLfloat *unified_knot; | |||
| GLint unified_nknots; | |||
| GLint order; | |||
| GLint t_min,t_max; | |||
| GLint delta_nknots; | |||
| GLboolean open_at_begin,open_at_end; | |||
| GLfloat *new_knot; | |||
| GLfloat *alpha; | |||
| } knot_str_type; | |||
| GLfloat *knot; | |||
| GLint nknots; | |||
| GLfloat *unified_knot; | |||
| GLint unified_nknots; | |||
| GLint order; | |||
| GLint t_min, t_max; | |||
| GLint delta_nknots; | |||
| GLboolean open_at_begin, open_at_end; | |||
| GLfloat *new_knot; | |||
| GLfloat *alpha; | |||
| } | |||
| knot_str_type; | |||
| typedef struct | |||
| { | |||
| GLfloat *geom_ctrl; | |||
| GLint geom_s_stride,geom_t_stride; | |||
| GLfloat **geom_offsets; | |||
| GLint geom_s_pt_cnt,geom_t_pt_cnt; | |||
| GLfloat *color_ctrl; | |||
| GLint color_s_stride,color_t_stride; | |||
| GLfloat **color_offsets; | |||
| GLint color_s_pt_cnt,color_t_pt_cnt; | |||
| GLfloat *normal_ctrl; | |||
| GLint normal_s_stride,normal_t_stride; | |||
| GLfloat **normal_offsets; | |||
| GLint normal_s_pt_cnt,normal_t_pt_cnt; | |||
| GLfloat *texture_ctrl; | |||
| GLint texture_s_stride,texture_t_stride; | |||
| GLfloat **texture_offsets; | |||
| GLint texture_s_pt_cnt,texture_t_pt_cnt; | |||
| GLint s_bezier_cnt,t_bezier_cnt; | |||
| } new_ctrl_type; | |||
| extern void call_user_error( GLUnurbsObj *nobj, GLenum error ); | |||
| extern GLenum test_knot(GLint nknots, GLfloat *knot, GLint order); | |||
| extern GLenum explode_knot(knot_str_type *the_knot); | |||
| extern GLenum calc_alphas(knot_str_type *the_knot); | |||
| extern GLenum calc_new_ctrl_pts(GLfloat *ctrl,GLint stride,knot_str_type *the_knot, | |||
| GLint dim,GLfloat **new_ctrl,GLint *ncontrol); | |||
| extern GLenum glu_do_sampling_crv(GLUnurbsObj *nobj, GLfloat *new_ctrl,GLint n_ctrl, | |||
| GLint order,GLint dim,GLint **factors); | |||
| extern GLenum glu_do_sampling_3D(GLUnurbsObj *nobj, new_ctrl_type *new_ctrl, | |||
| int **sfactors, GLint **tfactors); | |||
| extern GLenum glu_do_sampling_uv(GLUnurbsObj *nobj, new_ctrl_type *new_ctrl, | |||
| int **sfactors, GLint **tfactors); | |||
| extern GLenum glu_do_sampling_param_3D(GLUnurbsObj *nobj, new_ctrl_type *new_ctrl, | |||
| int **sfactors, GLint **tfactors); | |||
| extern GLboolean fine_culling_test_2D(GLUnurbsObj *nobj, GLfloat *ctrl, GLint n_ctrl, | |||
| GLint stride, GLint dim); | |||
| extern GLboolean fine_culling_test_3D(GLUnurbsObj *nobj, GLfloat *ctrl, | |||
| GLint s_n_ctrl, GLint t_n_ctrl, GLint s_stride, GLint t_stride, GLint dim); | |||
| extern void do_nurbs_curve( GLUnurbsObj *nobj); | |||
| extern void do_nurbs_surface( GLUnurbsObj *nobj); | |||
| extern GLenum patch_trimming(GLUnurbsObj *nobj,new_ctrl_type *new_ctrl, | |||
| GLint *sfactors, GLint *tfactors); | |||
| extern void collect_unified_knot(knot_str_type *dest, knot_str_type *src, | |||
| GLfloat maximal_min_knot, GLfloat minimal_max_knot); | |||
| extern GLenum select_knot_working_range(GLUnurbsObj *nobj,knot_str_type *geom_knot, | |||
| knot_str_type *color_knot, knot_str_type *normal_knot, | |||
| knot_str_type *texture_knot); | |||
| extern void free_unified_knots(knot_str_type *geom_knot, knot_str_type *color_knot, | |||
| knot_str_type *normal_knot, knot_str_type *texture_knot); | |||
| GLfloat *geom_ctrl; | |||
| GLint geom_s_stride, geom_t_stride; | |||
| GLfloat **geom_offsets; | |||
| GLint geom_s_pt_cnt, geom_t_pt_cnt; | |||
| GLfloat *color_ctrl; | |||
| GLint color_s_stride, color_t_stride; | |||
| GLfloat **color_offsets; | |||
| GLint color_s_pt_cnt, color_t_pt_cnt; | |||
| GLfloat *normal_ctrl; | |||
| GLint normal_s_stride, normal_t_stride; | |||
| GLfloat **normal_offsets; | |||
| GLint normal_s_pt_cnt, normal_t_pt_cnt; | |||
| GLfloat *texture_ctrl; | |||
| GLint texture_s_stride, texture_t_stride; | |||
| GLfloat **texture_offsets; | |||
| GLint texture_s_pt_cnt, texture_t_pt_cnt; | |||
| GLint s_bezier_cnt, t_bezier_cnt; | |||
| } | |||
| new_ctrl_type; | |||
| extern void call_user_error(GLUnurbsObj * nobj, GLenum error); | |||
| extern GLenum test_knot(GLint nknots, GLfloat * knot, GLint order); | |||
| extern GLenum explode_knot(knot_str_type * the_knot); | |||
| extern GLenum calc_alphas(knot_str_type * the_knot); | |||
| extern GLenum calc_new_ctrl_pts(GLfloat * ctrl, GLint stride, | |||
| knot_str_type * the_knot, GLint dim, | |||
| GLfloat ** new_ctrl, GLint * ncontrol); | |||
| extern GLenum glu_do_sampling_crv(GLUnurbsObj * nobj, GLfloat * new_ctrl, | |||
| GLint n_ctrl, GLint order, GLint dim, | |||
| GLint ** factors); | |||
| extern GLenum glu_do_sampling_3D(GLUnurbsObj * nobj, new_ctrl_type * new_ctrl, | |||
| int **sfactors, GLint ** tfactors); | |||
| extern GLenum glu_do_sampling_uv(GLUnurbsObj * nobj, new_ctrl_type * new_ctrl, | |||
| int **sfactors, GLint ** tfactors); | |||
| extern GLenum glu_do_sampling_param_3D(GLUnurbsObj * nobj, | |||
| new_ctrl_type * new_ctrl, | |||
| int **sfactors, GLint ** tfactors); | |||
| extern GLboolean fine_culling_test_2D(GLUnurbsObj * nobj, GLfloat * ctrl, | |||
| GLint n_ctrl, GLint stride, GLint dim); | |||
| extern GLboolean fine_culling_test_3D(GLUnurbsObj * nobj, GLfloat * ctrl, | |||
| GLint s_n_ctrl, GLint t_n_ctrl, | |||
| GLint s_stride, GLint t_stride, | |||
| GLint dim); | |||
| extern void do_nurbs_curve(GLUnurbsObj * nobj); | |||
| extern void do_nurbs_surface(GLUnurbsObj * nobj); | |||
| extern GLenum patch_trimming(GLUnurbsObj * nobj, new_ctrl_type * new_ctrl, | |||
| GLint * sfactors, GLint * tfactors); | |||
| extern void collect_unified_knot(knot_str_type * dest, knot_str_type * src, | |||
| GLfloat maximal_min_knot, | |||
| GLfloat minimal_max_knot); | |||
| extern GLenum select_knot_working_range(GLUnurbsObj * nobj, | |||
| knot_str_type * geom_knot, | |||
| knot_str_type * color_knot, | |||
| knot_str_type * normal_knot, | |||
| knot_str_type * texture_knot); | |||
| extern void free_unified_knots(knot_str_type * geom_knot, | |||
| knot_str_type * color_knot, | |||
| knot_str_type * normal_knot, | |||
| knot_str_type * texture_knot); | |||
| @@ -1,9 +1,9 @@ | |||
| /* $Id: nurbscrv.c,v 1.1 1999/08/19 00:55:42 jtg Exp $ */ | |||
| /* $Id: nurbscrv.c,v 1.2 2000/07/11 14:11:04 brianp Exp $ */ | |||
| /* | |||
| * Mesa 3-D graphics library | |||
| * Version: 2.4 | |||
| * Copyright (C) 1995-1997 Brian Paul | |||
| * Version: 3.3 | |||
| * Copyright (C) 1995-2000 Brian Paul | |||
| * | |||
| * This library is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Library General Public | |||
| @@ -21,32 +21,6 @@ | |||
| */ | |||
| /* | |||
| * $Log: nurbscrv.c,v $ | |||
| * Revision 1.1 1999/08/19 00:55:42 jtg | |||
| * Initial revision | |||
| * | |||
| * Revision 1.6 1997/07/24 01:28:44 brianp | |||
| * changed precompiled header symbol from PCH to PC_HEADER | |||
| * | |||
| * Revision 1.5 1997/05/28 02:29:38 brianp | |||
| * added support for precompiled headers (PCH), inserted APIENTRY keyword | |||
| * | |||
| * Revision 1.4 1997/05/27 03:21:22 brianp | |||
| * minor clean-up | |||
| * | |||
| * Revision 1.3 1997/05/27 03:00:16 brianp | |||
| * incorporated Bogdan's new NURBS code | |||
| * | |||
| * Revision 1.2 1996/09/27 23:12:22 brianp | |||
| * added return 0 to get_surface_dim() to silence warning | |||
| * | |||
| * Revision 1.1 1996/09/27 01:19:39 brianp | |||
| * Initial revision | |||
| * | |||
| */ | |||
| /* | |||
| * NURBS implementation written by Bogdan Sikorski (bogdan@cira.it) | |||
| * See README2 for more info. | |||
| @@ -66,435 +40,406 @@ | |||
| static int | |||
| get_curve_dim(GLenum type) | |||
| { | |||
| switch(type) | |||
| { | |||
| case GL_MAP1_VERTEX_3: return 3; | |||
| case GL_MAP1_VERTEX_4: return 4; | |||
| case GL_MAP1_INDEX: return 1; | |||
| case GL_MAP1_COLOR_4: return 4; | |||
| case GL_MAP1_NORMAL: return 3; | |||
| case GL_MAP1_TEXTURE_COORD_1: return 1; | |||
| case GL_MAP1_TEXTURE_COORD_2: return 2; | |||
| case GL_MAP1_TEXTURE_COORD_3: return 3; | |||
| case GL_MAP1_TEXTURE_COORD_4: return 4; | |||
| default: abort(); /* TODO: is this OK? */ | |||
| } | |||
| return 0; /*never get here*/ | |||
| switch (type) { | |||
| case GL_MAP1_VERTEX_3: | |||
| return 3; | |||
| case GL_MAP1_VERTEX_4: | |||
| return 4; | |||
| case GL_MAP1_INDEX: | |||
| return 1; | |||
| case GL_MAP1_COLOR_4: | |||
| return 4; | |||
| case GL_MAP1_NORMAL: | |||
| return 3; | |||
| case GL_MAP1_TEXTURE_COORD_1: | |||
| return 1; | |||
| case GL_MAP1_TEXTURE_COORD_2: | |||
| return 2; | |||
| case GL_MAP1_TEXTURE_COORD_3: | |||
| return 3; | |||
| case GL_MAP1_TEXTURE_COORD_4: | |||
| return 4; | |||
| default: | |||
| abort(); /* TODO: is this OK? */ | |||
| } | |||
| return 0; /*never get here */ | |||
| } | |||
| static GLenum | |||
| test_nurbs_curve(GLUnurbsObj *nobj, curve_attribs *attribs) | |||
| test_nurbs_curve(GLUnurbsObj * nobj, curve_attribs * attribs) | |||
| { | |||
| GLenum err; | |||
| GLint tmp_int; | |||
| GLenum err; | |||
| GLint tmp_int; | |||
| if(attribs->order < 0) | |||
| { | |||
| call_user_error(nobj,GLU_INVALID_VALUE); | |||
| return GLU_ERROR; | |||
| } | |||
| glGetIntegerv(GL_MAX_EVAL_ORDER,&tmp_int); | |||
| if(attribs->order > tmp_int || attribs->order < 2) | |||
| { | |||
| call_user_error(nobj,GLU_NURBS_ERROR1); | |||
| return GLU_ERROR; | |||
| } | |||
| if(attribs->knot_count < attribs->order +2) | |||
| { | |||
| call_user_error(nobj,GLU_NURBS_ERROR2); | |||
| return GLU_ERROR; | |||
| } | |||
| if(attribs->stride < 0) | |||
| { | |||
| call_user_error(nobj,GLU_NURBS_ERROR34); | |||
| return GLU_ERROR; | |||
| } | |||
| if(attribs->knot==NULL || attribs->ctrlarray==NULL) | |||
| { | |||
| call_user_error(nobj,GLU_NURBS_ERROR36); | |||
| return GLU_ERROR; | |||
| } | |||
| if((err=test_knot(attribs->knot_count,attribs->knot,attribs->order)) | |||
| !=GLU_NO_ERROR) | |||
| { | |||
| call_user_error(nobj,err); | |||
| return GLU_ERROR; | |||
| } | |||
| return GLU_NO_ERROR; | |||
| if (attribs->order < 0) { | |||
| call_user_error(nobj, GLU_INVALID_VALUE); | |||
| return GLU_ERROR; | |||
| } | |||
| glGetIntegerv(GL_MAX_EVAL_ORDER, &tmp_int); | |||
| if (attribs->order > tmp_int || attribs->order < 2) { | |||
| call_user_error(nobj, GLU_NURBS_ERROR1); | |||
| return GLU_ERROR; | |||
| } | |||
| if (attribs->knot_count < attribs->order + 2) { | |||
| call_user_error(nobj, GLU_NURBS_ERROR2); | |||
| return GLU_ERROR; | |||
| } | |||
| if (attribs->stride < 0) { | |||
| call_user_error(nobj, GLU_NURBS_ERROR34); | |||
| return GLU_ERROR; | |||
| } | |||
| if (attribs->knot == NULL || attribs->ctrlarray == NULL) { | |||
| call_user_error(nobj, GLU_NURBS_ERROR36); | |||
| return GLU_ERROR; | |||
| } | |||
| if ((err = test_knot(attribs->knot_count, attribs->knot, attribs->order)) | |||
| != GLU_NO_ERROR) { | |||
| call_user_error(nobj, err); | |||
| return GLU_ERROR; | |||
| } | |||
| return GLU_NO_ERROR; | |||
| } | |||
| static GLenum | |||
| test_nurbs_curves(GLUnurbsObj *nobj) | |||
| test_nurbs_curves(GLUnurbsObj * nobj) | |||
| { | |||
| /* test the geometric data */ | |||
| if(test_nurbs_curve(nobj,&(nobj->curve.geom))!=GLU_NO_ERROR) | |||
| return GLU_ERROR; | |||
| /* now test the attributive data */ | |||
| /* color */ | |||
| if(nobj->curve.color.type!=GLU_INVALID_ENUM) | |||
| if(test_nurbs_curve(nobj,&(nobj->curve.color))!=GLU_NO_ERROR) | |||
| return GLU_ERROR; | |||
| /* normal */ | |||
| if(nobj->curve.normal.type!=GLU_INVALID_ENUM) | |||
| if(test_nurbs_curve(nobj,&(nobj->curve.normal))!=GLU_NO_ERROR) | |||
| return GLU_ERROR; | |||
| /* texture */ | |||
| if(nobj->curve.texture.type!=GLU_INVALID_ENUM) | |||
| if(test_nurbs_curve(nobj,&(nobj->curve.texture))!=GLU_NO_ERROR) | |||
| return GLU_ERROR; | |||
| return GLU_NO_ERROR; | |||
| /* test the geometric data */ | |||
| if (test_nurbs_curve(nobj, &(nobj->curve.geom)) != GLU_NO_ERROR) | |||
| return GLU_ERROR; | |||
| /* now test the attributive data */ | |||
| /* color */ | |||
| if (nobj->curve.color.type != GLU_INVALID_ENUM) | |||
| if (test_nurbs_curve(nobj, &(nobj->curve.color)) != GLU_NO_ERROR) | |||
| return GLU_ERROR; | |||
| /* normal */ | |||
| if (nobj->curve.normal.type != GLU_INVALID_ENUM) | |||
| if (test_nurbs_curve(nobj, &(nobj->curve.normal)) != GLU_NO_ERROR) | |||
| return GLU_ERROR; | |||
| /* texture */ | |||
| if (nobj->curve.texture.type != GLU_INVALID_ENUM) | |||
| if (test_nurbs_curve(nobj, &(nobj->curve.texture)) != GLU_NO_ERROR) | |||
| return GLU_ERROR; | |||
| return GLU_NO_ERROR; | |||
| } | |||
| /* prepare the knot information structures */ | |||
| static GLenum | |||
| fill_knot_structures(GLUnurbsObj *nobj,knot_str_type *geom_knot, | |||
| knot_str_type *color_knot, knot_str_type *normal_knot, | |||
| knot_str_type *texture_knot) | |||
| fill_knot_structures(GLUnurbsObj * nobj, knot_str_type * geom_knot, | |||
| knot_str_type * color_knot, knot_str_type * normal_knot, | |||
| knot_str_type * texture_knot) | |||
| { | |||
| GLint order; | |||
| GLfloat *knot; | |||
| GLint nknots; | |||
| GLint t_min,t_max; | |||
| GLint order; | |||
| GLfloat *knot; | |||
| GLint nknots; | |||
| GLint t_min, t_max; | |||
| geom_knot->unified_knot=NULL; | |||
| knot=geom_knot->knot=nobj->curve.geom.knot; | |||
| nknots=geom_knot->nknots=nobj->curve.geom.knot_count; | |||
| order=geom_knot->order=nobj->curve.geom.order; | |||
| geom_knot->delta_nknots=0; | |||
| t_min=geom_knot->t_min=order-1; | |||
| t_max=geom_knot->t_max=nknots-order; | |||
| if(fabs(knot[t_min]-knot[t_max])<EPSILON) | |||
| { | |||
| call_user_error(nobj,GLU_NURBS_ERROR3); | |||
| return GLU_ERROR; | |||
| } | |||
| if(fabs(knot[0]-knot[t_min])<EPSILON) | |||
| { | |||
| /* knot open at beggining */ | |||
| geom_knot->open_at_begin=GL_TRUE; | |||
| } | |||
| else | |||
| geom_knot->open_at_begin=GL_FALSE; | |||
| if(fabs(knot[t_max]-knot[nknots-1])<EPSILON) | |||
| { | |||
| /* knot open at end */ | |||
| geom_knot->open_at_end=GL_TRUE; | |||
| } | |||
| else | |||
| geom_knot->open_at_end=GL_FALSE; | |||
| if(nobj->curve.color.type!=GLU_INVALID_ENUM) | |||
| { | |||
| color_knot->unified_knot=(GLfloat *)1; | |||
| knot=color_knot->knot=nobj->curve.color.knot; | |||
| nknots=color_knot->nknots=nobj->curve.color.knot_count; | |||
| order=color_knot->order=nobj->curve.color.order; | |||
| color_knot->delta_nknots=0; | |||
| t_min=color_knot->t_min=order-1; | |||
| t_max=color_knot->t_max=nknots-order; | |||
| if(fabs(knot[t_min]-knot[t_max])<EPSILON) | |||
| { | |||
| call_user_error(nobj,GLU_NURBS_ERROR3); | |||
| return GLU_ERROR; | |||
| } | |||
| if(fabs(knot[0]-knot[t_min])<EPSILON) | |||
| { | |||
| /* knot open at beggining */ | |||
| color_knot->open_at_begin=GL_TRUE; | |||
| } | |||
| else | |||
| color_knot->open_at_begin=GL_FALSE; | |||
| if(fabs(knot[t_max]-knot[nknots-1])<EPSILON) | |||
| { | |||
| /* knot open at end */ | |||
| color_knot->open_at_end=GL_TRUE; | |||
| } | |||
| else | |||
| color_knot->open_at_end=GL_FALSE; | |||
| } | |||
| else | |||
| color_knot->unified_knot=NULL; | |||
| if(nobj->curve.normal.type!=GLU_INVALID_ENUM) | |||
| { | |||
| normal_knot->unified_knot=(GLfloat *)1; | |||
| knot=normal_knot->knot=nobj->curve.normal.knot; | |||
| nknots=normal_knot->nknots=nobj->curve.normal.knot_count; | |||
| order=normal_knot->order=nobj->curve.normal.order; | |||
| normal_knot->delta_nknots=0; | |||
| t_min=normal_knot->t_min=order-1; | |||
| t_max=normal_knot->t_max=nknots-order; | |||
| if(fabs(knot[t_min]-knot[t_max])<EPSILON) | |||
| { | |||
| call_user_error(nobj,GLU_NURBS_ERROR3); | |||
| return GLU_ERROR; | |||
| } | |||
| if(fabs(knot[0]-knot[t_min])<EPSILON) | |||
| { | |||
| /* knot open at beggining */ | |||
| normal_knot->open_at_begin=GL_TRUE; | |||
| } | |||
| else | |||
| normal_knot->open_at_begin=GL_FALSE; | |||
| if(fabs(knot[t_max]-knot[nknots-1])<EPSILON) | |||
| { | |||
| /* knot open at end */ | |||
| normal_knot->open_at_end=GL_TRUE; | |||
| } | |||
| else | |||
| normal_knot->open_at_end=GL_FALSE; | |||
| } | |||
| else | |||
| normal_knot->unified_knot=NULL; | |||
| if(nobj->curve.texture.type!=GLU_INVALID_ENUM) | |||
| { | |||
| texture_knot->unified_knot=(GLfloat *)1; | |||
| knot=texture_knot->knot=nobj->curve.texture.knot; | |||
| nknots=texture_knot->nknots=nobj->curve.texture.knot_count; | |||
| order=texture_knot->order=nobj->curve.texture.order; | |||
| texture_knot->delta_nknots=0; | |||
| t_min=texture_knot->t_min=order-1; | |||
| t_max=texture_knot->t_max=nknots-order; | |||
| if(fabs(knot[t_min]-knot[t_max])<EPSILON) | |||
| { | |||
| call_user_error(nobj,GLU_NURBS_ERROR3); | |||
| return GLU_ERROR; | |||
| } | |||
| if(fabs(knot[0]-knot[t_min])<EPSILON) | |||
| { | |||
| /* knot open at beggining */ | |||
| texture_knot->open_at_begin=GL_TRUE; | |||
| } | |||
| else | |||
| texture_knot->open_at_begin=GL_FALSE; | |||
| if(fabs(knot[t_max]-knot[nknots-1])<EPSILON) | |||
| { | |||
| /* knot open at end */ | |||
| texture_knot->open_at_end=GL_TRUE; | |||
| } | |||
| else | |||
| texture_knot->open_at_end=GL_FALSE; | |||
| } | |||
| else | |||
| texture_knot->unified_knot=NULL; | |||
| return GLU_NO_ERROR; | |||
| geom_knot->unified_knot = NULL; | |||
| knot = geom_knot->knot = nobj->curve.geom.knot; | |||
| nknots = geom_knot->nknots = nobj->curve.geom.knot_count; | |||
| order = geom_knot->order = nobj->curve.geom.order; | |||
| geom_knot->delta_nknots = 0; | |||
| t_min = geom_knot->t_min = order - 1; | |||
| t_max = geom_knot->t_max = nknots - order; | |||
| if (fabs(knot[t_min] - knot[t_max]) < EPSILON) { | |||
| call_user_error(nobj, GLU_NURBS_ERROR3); | |||
| return GLU_ERROR; | |||
| } | |||
| if (fabs(knot[0] - knot[t_min]) < EPSILON) { | |||
| /* knot open at beggining */ | |||
| geom_knot->open_at_begin = GL_TRUE; | |||
| } | |||
| else | |||
| geom_knot->open_at_begin = GL_FALSE; | |||
| if (fabs(knot[t_max] - knot[nknots - 1]) < EPSILON) { | |||
| /* knot open at end */ | |||
| geom_knot->open_at_end = GL_TRUE; | |||
| } | |||
| else | |||
| geom_knot->open_at_end = GL_FALSE; | |||
| if (nobj->curve.color.type != GLU_INVALID_ENUM) { | |||
| color_knot->unified_knot = (GLfloat *) 1; | |||
| knot = color_knot->knot = nobj->curve.color.knot; | |||
| nknots = color_knot->nknots = nobj->curve.color.knot_count; | |||
| order = color_knot->order = nobj->curve.color.order; | |||
| color_knot->delta_nknots = 0; | |||
| t_min = color_knot->t_min = order - 1; | |||
| t_max = color_knot->t_max = nknots - order; | |||
| if (fabs(knot[t_min] - knot[t_max]) < EPSILON) { | |||
| call_user_error(nobj, GLU_NURBS_ERROR3); | |||
| return GLU_ERROR; | |||
| } | |||
| if (fabs(knot[0] - knot[t_min]) < EPSILON) { | |||
| /* knot open at beggining */ | |||
| color_knot->open_at_begin = GL_TRUE; | |||
| } | |||
| else | |||
| color_knot->open_at_begin = GL_FALSE; | |||
| if (fabs(knot[t_max] - knot[nknots - 1]) < EPSILON) { | |||
| /* knot open at end */ | |||
| color_knot->open_at_end = GL_TRUE; | |||
| } | |||
| else | |||
| color_knot->open_at_end = GL_FALSE; | |||
| } | |||
| else | |||
| color_knot->unified_knot = NULL; | |||
| if (nobj->curve.normal.type != GLU_INVALID_ENUM) { | |||
| normal_knot->unified_knot = (GLfloat *) 1; | |||
| knot = normal_knot->knot = nobj->curve.normal.knot; | |||
| nknots = normal_knot->nknots = nobj->curve.normal.knot_count; | |||
| order = normal_knot->order = nobj->curve.normal.order; | |||
| normal_knot->delta_nknots = 0; | |||
| t_min = normal_knot->t_min = order - 1; | |||
| t_max = normal_knot->t_max = nknots - order; | |||
| if (fabs(knot[t_min] - knot[t_max]) < EPSILON) { | |||
| call_user_error(nobj, GLU_NURBS_ERROR3); | |||
| return GLU_ERROR; | |||
| } | |||
| if (fabs(knot[0] - knot[t_min]) < EPSILON) { | |||
| /* knot open at beggining */ | |||
| normal_knot->open_at_begin = GL_TRUE; | |||
| } | |||
| else | |||
| normal_knot->open_at_begin = GL_FALSE; | |||
| if (fabs(knot[t_max] - knot[nknots - 1]) < EPSILON) { | |||
| /* knot open at end */ | |||
| normal_knot->open_at_end = GL_TRUE; | |||
| } | |||
| else | |||
| normal_knot->open_at_end = GL_FALSE; | |||
| } | |||
| else | |||
| normal_knot->unified_knot = NULL; | |||
| if (nobj->curve.texture.type != GLU_INVALID_ENUM) { | |||
| texture_knot->unified_knot = (GLfloat *) 1; | |||
| knot = texture_knot->knot = nobj->curve.texture.knot; | |||
| nknots = texture_knot->nknots = nobj->curve.texture.knot_count; | |||
| order = texture_knot->order = nobj->curve.texture.order; | |||
| texture_knot->delta_nknots = 0; | |||
| t_min = texture_knot->t_min = order - 1; | |||
| t_max = texture_knot->t_max = nknots - order; | |||
| if (fabs(knot[t_min] - knot[t_max]) < EPSILON) { | |||
| call_user_error(nobj, GLU_NURBS_ERROR3); | |||
| return GLU_ERROR; | |||
| } | |||
| if (fabs(knot[0] - knot[t_min]) < EPSILON) { | |||
| /* knot open at beggining */ | |||
| texture_knot->open_at_begin = GL_TRUE; | |||
| } | |||
| else | |||
| texture_knot->open_at_begin = GL_FALSE; | |||
| if (fabs(knot[t_max] - knot[nknots - 1]) < EPSILON) { | |||
| /* knot open at end */ | |||
| texture_knot->open_at_end = GL_TRUE; | |||
| } | |||
| else | |||
| texture_knot->open_at_end = GL_FALSE; | |||
| } | |||
| else | |||
| texture_knot->unified_knot = NULL; | |||
| return GLU_NO_ERROR; | |||
| } | |||
| /* covert the NURBS curve into a series of adjacent Bezier curves */ | |||
| static GLenum | |||
| convert_curve(knot_str_type *the_knot, curve_attribs *attrib, | |||
| GLfloat **new_ctrl,GLint *ncontrol) | |||
| convert_curve(knot_str_type * the_knot, curve_attribs * attrib, | |||
| GLfloat ** new_ctrl, GLint * ncontrol) | |||
| { | |||
| GLenum err; | |||
| GLenum err; | |||
| if((err=explode_knot(the_knot))!=GLU_NO_ERROR) | |||
| { | |||
| if(the_knot->unified_knot) | |||
| { | |||
| free(the_knot->unified_knot); | |||
| the_knot->unified_knot=NULL; | |||
| } | |||
| return err; | |||
| } | |||
| if(the_knot->unified_knot) | |||
| { | |||
| free(the_knot->unified_knot); | |||
| the_knot->unified_knot=NULL; | |||
| } | |||
| if((err=calc_alphas(the_knot))!=GLU_NO_ERROR) | |||
| { | |||
| free(the_knot->new_knot); | |||
| return err; | |||
| } | |||
| free(the_knot->new_knot); | |||
| if((err=calc_new_ctrl_pts(attrib->ctrlarray,attrib->stride,the_knot, | |||
| attrib->dim,new_ctrl,ncontrol)) | |||
| !=GLU_NO_ERROR) | |||
| { | |||
| free(the_knot->alpha); | |||
| return err; | |||
| } | |||
| free(the_knot->alpha); | |||
| return GLU_NO_ERROR; | |||
| if ((err = explode_knot(the_knot)) != GLU_NO_ERROR) { | |||
| if (the_knot->unified_knot) { | |||
| free(the_knot->unified_knot); | |||
| the_knot->unified_knot = NULL; | |||
| } | |||
| return err; | |||
| } | |||
| if (the_knot->unified_knot) { | |||
| free(the_knot->unified_knot); | |||
| the_knot->unified_knot = NULL; | |||
| } | |||
| if ((err = calc_alphas(the_knot)) != GLU_NO_ERROR) { | |||
| free(the_knot->new_knot); | |||
| return err; | |||
| } | |||
| free(the_knot->new_knot); | |||
| if ((err = calc_new_ctrl_pts(attrib->ctrlarray, attrib->stride, the_knot, | |||
| attrib->dim, new_ctrl, ncontrol)) | |||
| != GLU_NO_ERROR) { | |||
| free(the_knot->alpha); | |||
| return err; | |||
| } | |||
| free(the_knot->alpha); | |||
| return GLU_NO_ERROR; | |||
| } | |||
| /* covert curves - geometry and possible attribute ones into equivalent */ | |||
| /* sequence of adjacent Bezier curves */ | |||
| static GLenum | |||
| convert_curves(GLUnurbsObj *nobj, GLfloat **new_geom_ctrl, | |||
| GLint *ncontrol, GLfloat **new_color_ctrl, GLfloat **new_normal_ctrl, | |||
| GLfloat **new_texture_ctrl) | |||
| convert_curves(GLUnurbsObj * nobj, GLfloat ** new_geom_ctrl, | |||
| GLint * ncontrol, GLfloat ** new_color_ctrl, | |||
| GLfloat ** new_normal_ctrl, GLfloat ** new_texture_ctrl) | |||
| { | |||
| knot_str_type geom_knot,color_knot,normal_knot,texture_knot; | |||
| GLint junk; | |||
| GLenum err; | |||
| knot_str_type geom_knot, color_knot, normal_knot, texture_knot; | |||
| GLint junk; | |||
| GLenum err; | |||
| *new_color_ctrl=*new_normal_ctrl=*new_texture_ctrl=NULL; | |||
| *new_color_ctrl = *new_normal_ctrl = *new_texture_ctrl = NULL; | |||
| if(fill_knot_structures(nobj,&geom_knot,&color_knot,&normal_knot, | |||
| &texture_knot)!=GLU_NO_ERROR) | |||
| return GLU_ERROR; | |||
| if (fill_knot_structures(nobj, &geom_knot, &color_knot, &normal_knot, | |||
| &texture_knot) != GLU_NO_ERROR) | |||
| return GLU_ERROR; | |||
| /* unify knots - all knots should have the same number of working */ | |||
| /* ranges */ | |||
| if((err=select_knot_working_range(nobj,&geom_knot,&color_knot,&normal_knot, | |||
| &texture_knot))!=GLU_NO_ERROR) | |||
| { | |||
| return err; | |||
| } | |||
| /* convert the geometry curve */ | |||
| nobj->curve.geom.dim=get_curve_dim(nobj->curve.geom.type); | |||
| if((err=convert_curve(&geom_knot,&(nobj->curve.geom),new_geom_ctrl, | |||
| ncontrol))!=GLU_NO_ERROR) | |||
| { | |||
| free_unified_knots(&geom_knot,&color_knot,&normal_knot,&texture_knot); | |||
| call_user_error(nobj,err); | |||
| return err; | |||
| } | |||
| /* if additional attributive curves are given convert them as well */ | |||
| if(color_knot.unified_knot) | |||
| { | |||
| nobj->curve.color.dim=get_curve_dim(nobj->curve.color.type); | |||
| if((err=convert_curve(&color_knot,&(nobj->curve.color), | |||
| new_color_ctrl,&junk))!=GLU_NO_ERROR) | |||
| { | |||
| free_unified_knots(&geom_knot,&color_knot,&normal_knot,&texture_knot); | |||
| free(*new_geom_ctrl); | |||
| call_user_error(nobj,err); | |||
| return err; | |||
| } | |||
| } | |||
| if(normal_knot.unified_knot) | |||
| { | |||
| nobj->curve.normal.dim=get_curve_dim(nobj->curve.normal.type); | |||
| if((err=convert_curve(&normal_knot,&(nobj->curve.normal), | |||
| new_normal_ctrl,&junk))!=GLU_NO_ERROR) | |||
| { | |||
| free_unified_knots(&geom_knot,&color_knot,&normal_knot,&texture_knot); | |||
| free(*new_geom_ctrl); | |||
| if(*new_color_ctrl) | |||
| free(*new_color_ctrl); | |||
| call_user_error(nobj,err); | |||
| return err; | |||
| } | |||
| } | |||
| if(texture_knot.unified_knot) | |||
| { | |||
| nobj->curve.texture.dim=get_curve_dim(nobj->curve.texture.type); | |||
| if((err=convert_curve(&texture_knot,&(nobj->curve.texture), | |||
| new_texture_ctrl,&junk))!=GLU_NO_ERROR) | |||
| { | |||
| free_unified_knots(&geom_knot,&color_knot,&normal_knot,&texture_knot); | |||
| free(*new_geom_ctrl); | |||
| if(*new_color_ctrl) | |||
| free(*new_color_ctrl); | |||
| if(*new_normal_ctrl) | |||
| free(*new_normal_ctrl); | |||
| call_user_error(nobj,err); | |||
| return err; | |||
| } | |||
| } | |||
| return GLU_NO_ERROR; | |||
| /* unify knots - all knots should have the same number of working */ | |||
| /* ranges */ | |||
| if ( | |||
| (err = | |||
| select_knot_working_range(nobj, &geom_knot, &color_knot, &normal_knot, | |||
| &texture_knot)) != GLU_NO_ERROR) { | |||
| return err; | |||
| } | |||
| /* convert the geometry curve */ | |||
| nobj->curve.geom.dim = get_curve_dim(nobj->curve.geom.type); | |||
| if ((err = convert_curve(&geom_knot, &(nobj->curve.geom), new_geom_ctrl, | |||
| ncontrol)) != GLU_NO_ERROR) { | |||
| free_unified_knots(&geom_knot, &color_knot, &normal_knot, | |||
| &texture_knot); | |||
| call_user_error(nobj, err); | |||
| return err; | |||
| } | |||
| /* if additional attributive curves are given convert them as well */ | |||
| if (color_knot.unified_knot) { | |||
| nobj->curve.color.dim = get_curve_dim(nobj->curve.color.type); | |||
| if ((err = convert_curve(&color_knot, &(nobj->curve.color), | |||
| new_color_ctrl, &junk)) != GLU_NO_ERROR) { | |||
| free_unified_knots(&geom_knot, &color_knot, &normal_knot, | |||
| &texture_knot); | |||
| free(*new_geom_ctrl); | |||
| call_user_error(nobj, err); | |||
| return err; | |||
| } | |||
| } | |||
| if (normal_knot.unified_knot) { | |||
| nobj->curve.normal.dim = get_curve_dim(nobj->curve.normal.type); | |||
| if ((err = convert_curve(&normal_knot, &(nobj->curve.normal), | |||
| new_normal_ctrl, &junk)) != GLU_NO_ERROR) { | |||
| free_unified_knots(&geom_knot, &color_knot, &normal_knot, | |||
| &texture_knot); | |||
| free(*new_geom_ctrl); | |||
| if (*new_color_ctrl) | |||
| free(*new_color_ctrl); | |||
| call_user_error(nobj, err); | |||
| return err; | |||
| } | |||
| } | |||
| if (texture_knot.unified_knot) { | |||
| nobj->curve.texture.dim = get_curve_dim(nobj->curve.texture.type); | |||
| if ((err = convert_curve(&texture_knot, &(nobj->curve.texture), | |||
| new_texture_ctrl, &junk)) != GLU_NO_ERROR) { | |||
| free_unified_knots(&geom_knot, &color_knot, &normal_knot, | |||
| &texture_knot); | |||
| free(*new_geom_ctrl); | |||
| if (*new_color_ctrl) | |||
| free(*new_color_ctrl); | |||
| if (*new_normal_ctrl) | |||
| free(*new_normal_ctrl); | |||
| call_user_error(nobj, err); | |||
| return err; | |||
| } | |||
| } | |||
| return GLU_NO_ERROR; | |||
| } | |||
| /* main NURBS curve procedure */ | |||
| void do_nurbs_curve( GLUnurbsObj *nobj) | |||
| void | |||
| do_nurbs_curve(GLUnurbsObj * nobj) | |||
| { | |||
| GLint geom_order,color_order=0,normal_order=0,texture_order=0; | |||
| GLenum geom_type; | |||
| GLint n_ctrl; | |||
| GLfloat *new_geom_ctrl,*new_color_ctrl,*new_normal_ctrl,*new_texture_ctrl; | |||
| GLfloat *geom_ctrl,*color_ctrl,*normal_ctrl,*texture_ctrl; | |||
| GLint *factors; | |||
| GLint i,j; | |||
| GLint geom_dim,color_dim=0,normal_dim=0,texture_dim=0; | |||
| GLint geom_order, color_order = 0, normal_order = 0, texture_order = 0; | |||
| GLenum geom_type; | |||
| GLint n_ctrl; | |||
| GLfloat *new_geom_ctrl, *new_color_ctrl, *new_normal_ctrl, | |||
| *new_texture_ctrl; | |||
| GLfloat *geom_ctrl, *color_ctrl, *normal_ctrl, *texture_ctrl; | |||
| GLint *factors; | |||
| GLint i, j; | |||
| GLint geom_dim, color_dim = 0, normal_dim = 0, texture_dim = 0; | |||
| /* test the user supplied data */ | |||
| if(test_nurbs_curves(nobj)!=GLU_NO_ERROR) | |||
| return; | |||
| /* test the user supplied data */ | |||
| if (test_nurbs_curves(nobj) != GLU_NO_ERROR) | |||
| return; | |||
| if(convert_curves(nobj,&new_geom_ctrl,&n_ctrl,&new_color_ctrl, | |||
| &new_normal_ctrl,&new_texture_ctrl)!=GLU_NO_ERROR) | |||
| return; | |||
| if (convert_curves(nobj, &new_geom_ctrl, &n_ctrl, &new_color_ctrl, | |||
| &new_normal_ctrl, &new_texture_ctrl) != GLU_NO_ERROR) | |||
| return; | |||
| geom_order=nobj->curve.geom.order; | |||
| geom_type=nobj->curve.geom.type; | |||
| geom_dim=nobj->curve.geom.dim; | |||
| geom_order = nobj->curve.geom.order; | |||
| geom_type = nobj->curve.geom.type; | |||
| geom_dim = nobj->curve.geom.dim; | |||
| if(glu_do_sampling_crv(nobj,new_geom_ctrl,n_ctrl,geom_order,geom_dim, | |||
| &factors) | |||
| !=GLU_NO_ERROR) | |||
| { | |||
| free(new_geom_ctrl); | |||
| if(new_color_ctrl) | |||
| free(new_color_ctrl); | |||
| if(new_normal_ctrl) | |||
| free(new_normal_ctrl); | |||
| if(new_texture_ctrl) | |||
| free(new_texture_ctrl); | |||
| return; | |||
| } | |||
| glEnable(geom_type); | |||
| if(new_color_ctrl) | |||
| { | |||
| glEnable(nobj->curve.color.type); | |||
| color_dim=nobj->curve.color.dim; | |||
| color_ctrl=new_color_ctrl; | |||
| color_order=nobj->curve.color.order; | |||
| } | |||
| if(new_normal_ctrl) | |||
| { | |||
| glEnable(nobj->curve.normal.type); | |||
| normal_dim=nobj->curve.normal.dim; | |||
| normal_ctrl=new_normal_ctrl; | |||
| normal_order=nobj->curve.normal.order; | |||
| } | |||
| if(new_texture_ctrl) | |||
| { | |||
| glEnable(nobj->curve.texture.type); | |||
| texture_dim=nobj->curve.texture.dim; | |||
| texture_ctrl=new_texture_ctrl; | |||
| texture_order=nobj->curve.texture.order; | |||
| } | |||
| for(i=0 , j=0, geom_ctrl=new_geom_ctrl; | |||
| i<n_ctrl; | |||
| i+=geom_order , j++ , geom_ctrl+=geom_order*geom_dim) | |||
| { | |||
| if(fine_culling_test_2D(nobj,geom_ctrl,geom_order,geom_dim,geom_dim)) | |||
| { | |||
| color_ctrl+=color_order*color_dim; | |||
| normal_ctrl+=normal_order*normal_dim; | |||
| texture_ctrl+=texture_order*texture_dim; | |||
| continue; | |||
| } | |||
| glMap1f(geom_type, 0.0, 1.0, geom_dim, geom_order, geom_ctrl); | |||
| if(new_color_ctrl) | |||
| { | |||
| glMap1f(nobj->curve.color.type, 0.0, 1.0, color_dim, | |||
| color_order,color_ctrl); | |||
| color_ctrl+=color_order*color_dim; | |||
| } | |||
| if(new_normal_ctrl) | |||
| { | |||
| glMap1f(nobj->curve.normal.type, 0.0, 1.0, normal_dim, | |||
| normal_order,normal_ctrl); | |||
| normal_ctrl+=normal_order*normal_dim; | |||
| } | |||
| if(new_texture_ctrl) | |||
| { | |||
| glMap1f(nobj->curve.texture.type, 0.0, 1.0, texture_dim, | |||
| texture_order,texture_ctrl); | |||
| texture_ctrl+=texture_order*texture_dim; | |||
| } | |||
| glMapGrid1f(factors[j],0.0,1.0); | |||
| glEvalMesh1(GL_LINE,0,factors[j]); | |||
| } | |||
| free(new_geom_ctrl); | |||
| free(factors); | |||
| if(new_color_ctrl) | |||
| free(new_color_ctrl); | |||
| if(new_normal_ctrl) | |||
| free(new_normal_ctrl); | |||
| if(new_texture_ctrl) | |||
| free(new_texture_ctrl); | |||
| if (glu_do_sampling_crv(nobj, new_geom_ctrl, n_ctrl, geom_order, geom_dim, | |||
| &factors) != GLU_NO_ERROR) { | |||
| free(new_geom_ctrl); | |||
| if (new_color_ctrl) | |||
| free(new_color_ctrl); | |||
| if (new_normal_ctrl) | |||
| free(new_normal_ctrl); | |||
| if (new_texture_ctrl) | |||
| free(new_texture_ctrl); | |||
| return; | |||
| } | |||
| glEnable(geom_type); | |||
| if (new_color_ctrl) { | |||
| glEnable(nobj->curve.color.type); | |||
| color_dim = nobj->curve.color.dim; | |||
| color_ctrl = new_color_ctrl; | |||
| color_order = nobj->curve.color.order; | |||
| } | |||
| if (new_normal_ctrl) { | |||
| glEnable(nobj->curve.normal.type); | |||
| normal_dim = nobj->curve.normal.dim; | |||
| normal_ctrl = new_normal_ctrl; | |||
| normal_order = nobj->curve.normal.order; | |||
| } | |||
| if (new_texture_ctrl) { | |||
| glEnable(nobj->curve.texture.type); | |||
| texture_dim = nobj->curve.texture.dim; | |||
| texture_ctrl = new_texture_ctrl; | |||
| texture_order = nobj->curve.texture.order; | |||
| } | |||
| for (i = 0, j = 0, geom_ctrl = new_geom_ctrl; | |||
| i < n_ctrl; i += geom_order, j++, geom_ctrl += geom_order * geom_dim) { | |||
| if (fine_culling_test_2D | |||
| (nobj, geom_ctrl, geom_order, geom_dim, geom_dim)) { | |||
| color_ctrl += color_order * color_dim; | |||
| normal_ctrl += normal_order * normal_dim; | |||
| texture_ctrl += texture_order * texture_dim; | |||
| continue; | |||
| } | |||
| glMap1f(geom_type, 0.0, 1.0, geom_dim, geom_order, geom_ctrl); | |||
| if (new_color_ctrl) { | |||
| glMap1f(nobj->curve.color.type, 0.0, 1.0, color_dim, | |||
| color_order, color_ctrl); | |||
| color_ctrl += color_order * color_dim; | |||
| } | |||
| if (new_normal_ctrl) { | |||
| glMap1f(nobj->curve.normal.type, 0.0, 1.0, normal_dim, | |||
| normal_order, normal_ctrl); | |||
| normal_ctrl += normal_order * normal_dim; | |||
| } | |||
| if (new_texture_ctrl) { | |||
| glMap1f(nobj->curve.texture.type, 0.0, 1.0, texture_dim, | |||
| texture_order, texture_ctrl); | |||
| texture_ctrl += texture_order * texture_dim; | |||
| } | |||
| glMapGrid1f(factors[j], 0.0, 1.0); | |||
| glEvalMesh1(GL_LINE, 0, factors[j]); | |||
| } | |||
| free(new_geom_ctrl); | |||
| free(factors); | |||
| if (new_color_ctrl) | |||
| free(new_color_ctrl); | |||
| if (new_normal_ctrl) | |||
| free(new_normal_ctrl); | |||
| if (new_texture_ctrl) | |||
| free(new_texture_ctrl); | |||
| } | |||
| @@ -0,0 +1,938 @@ | |||
| /* $Id: polytest.c,v 1.3 2000/07/11 14:11:04 brianp Exp $ */ | |||
| /* | |||
| * Mesa 3-D graphics library | |||
| * Version: 3.3 | |||
| * Copyright (C) 1995-2000 Brian Paul | |||
| * | |||
| * This library is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Library General Public | |||
| * License as published by the Free Software Foundation; either | |||
| * version 2 of the License, or (at your option) any later version. | |||
| * | |||
| * This library is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
| * Library General Public License for more details. | |||
| * | |||
| * You should have received a copy of the GNU Library General Public | |||
| * License along with this library; if not, write to the Free | |||
| * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| */ | |||
| /* | |||
| * This file is part of the polygon tesselation code contributed by | |||
| * Bogdan Sikorski | |||
| */ | |||
| #ifdef PC_HEADER | |||
| #include "all.h" | |||
| #else | |||
| #include <math.h> | |||
| #include <stdlib.h> | |||
| #include "gluP.h" | |||
| #include "tess.h" | |||
| #endif | |||
| static GLenum store_polygon_as_contour(GLUtriangulatorObj *); | |||
| static void free_current_polygon(tess_polygon *); | |||
| static void prepare_projection_info(GLUtriangulatorObj *); | |||
| static GLdouble twice_the_polygon_area(tess_vertex *, tess_vertex *); | |||
| static GLenum verify_edge_vertex_intersections(GLUtriangulatorObj *); | |||
| void tess_find_contour_hierarchies(GLUtriangulatorObj *); | |||
| static GLenum test_for_overlapping_contours(GLUtriangulatorObj *); | |||
| static GLenum contours_overlap(tess_contour *, tess_polygon *); | |||
| static GLenum is_contour_contained_in(tess_contour *, tess_contour *); | |||
| static void add_new_exterior(GLUtriangulatorObj *, tess_contour *); | |||
| static void add_new_interior(GLUtriangulatorObj *, tess_contour *, | |||
| tess_contour *); | |||
| static void add_interior_with_hierarchy_check(GLUtriangulatorObj *, | |||
| tess_contour *, tess_contour *); | |||
| static void reverse_hierarchy_and_add_exterior(GLUtriangulatorObj *, | |||
| tess_contour *, | |||
| tess_contour *); | |||
| static GLboolean point_in_polygon(tess_contour *, GLdouble, GLdouble); | |||
| static void shift_interior_to_exterior(GLUtriangulatorObj *, tess_contour *); | |||
| static void add_exterior_with_check(GLUtriangulatorObj *, tess_contour *, | |||
| tess_contour *); | |||
| static GLenum cut_out_hole(GLUtriangulatorObj *, tess_contour *, | |||
| tess_contour *); | |||
| static GLenum merge_hole_with_contour(GLUtriangulatorObj *, | |||
| tess_contour *, tess_contour *, | |||
| tess_vertex *, tess_vertex *); | |||
| static GLenum | |||
| find_normal(GLUtriangulatorObj * tobj) | |||
| { | |||
| tess_polygon *polygon = tobj->current_polygon; | |||
| tess_vertex *va, *vb, *vc; | |||
| GLdouble A, B, C; | |||
| GLdouble A0, A1, A2, B0, B1, B2; | |||
| va = polygon->vertices; | |||
| vb = va->next; | |||
| A0 = vb->location[0] - va->location[0]; | |||
| A1 = vb->location[1] - va->location[1]; | |||
| A2 = vb->location[2] - va->location[2]; | |||
| for (vc = vb->next; vc != va; vc = vc->next) { | |||
| B0 = vc->location[0] - va->location[0]; | |||
| B1 = vc->location[1] - va->location[1]; | |||
| B2 = vc->location[2] - va->location[2]; | |||
| A = A1 * B2 - A2 * B1; | |||
| B = A2 * B0 - A0 * B2; | |||
| C = A0 * B1 - A1 * B0; | |||
| if (fabs(A) > EPSILON || fabs(B) > EPSILON || fabs(C) > EPSILON) { | |||
| polygon->A = A; | |||
| polygon->B = B; | |||
| polygon->C = C; | |||
| polygon->D = | |||
| -A * va->location[0] - B * va->location[1] - C * va->location[2]; | |||
| return GLU_NO_ERROR; | |||
| } | |||
| } | |||
| tess_call_user_error(tobj, GLU_TESS_ERROR7); | |||
| return GLU_ERROR; | |||
| } | |||
| void | |||
| tess_test_polygon(GLUtriangulatorObj * tobj) | |||
| { | |||
| tess_polygon *polygon = tobj->current_polygon; | |||
| /* any vertices defined? */ | |||
| if (polygon->vertex_cnt < 3) { | |||
| free_current_polygon(polygon); | |||
| return; | |||
| } | |||
| /* wrap pointers */ | |||
| polygon->last_vertex->next = polygon->vertices; | |||
| polygon->vertices->previous = polygon->last_vertex; | |||
| /* determine the normal */ | |||
| if (find_normal(tobj) == GLU_ERROR) | |||
| return; | |||
| /* compare the normals of previously defined contours and this one */ | |||
| /* first contour define ? */ | |||
| if (tobj->contours == NULL) { | |||
| tobj->A = polygon->A; | |||
| tobj->B = polygon->B; | |||
| tobj->C = polygon->C; | |||
| tobj->D = polygon->D; | |||
| /* determine the best projection to use */ | |||
| if (fabs(polygon->A) > fabs(polygon->B)) | |||
| if (fabs(polygon->A) > fabs(polygon->C)) | |||
| tobj->projection = OYZ; | |||
| else | |||
| tobj->projection = OXY; | |||
| else if (fabs(polygon->B) > fabs(polygon->C)) | |||
| tobj->projection = OXZ; | |||
| else | |||
| tobj->projection = OXY; | |||
| } | |||
| else { | |||
| GLdouble a[3], b[3]; | |||
| tess_vertex *vertex = polygon->vertices; | |||
| a[0] = tobj->A; | |||
| a[1] = tobj->B; | |||
| a[2] = tobj->C; | |||
| b[0] = polygon->A; | |||
| b[1] = polygon->B; | |||
| b[2] = polygon->C; | |||
| /* compare the normals */ | |||
| if (fabs(a[1] * b[2] - a[2] * b[1]) > EPSILON || | |||
| fabs(a[2] * b[0] - a[0] * b[2]) > EPSILON || | |||
| fabs(a[0] * b[1] - a[1] * b[0]) > EPSILON) { | |||
| /* not coplanar */ | |||
| tess_call_user_error(tobj, GLU_TESS_ERROR9); | |||
| return; | |||
| } | |||
| /* the normals are parallel - test for plane equation */ | |||
| if (fabs(a[0] * vertex->location[0] + a[1] * vertex->location[1] + | |||
| a[2] * vertex->location[2] + tobj->D) > EPSILON) { | |||
| /* not the same plane */ | |||
| tess_call_user_error(tobj, GLU_TESS_ERROR9); | |||
| return; | |||
| } | |||
| } | |||
| prepare_projection_info(tobj); | |||
| if (verify_edge_vertex_intersections(tobj) == GLU_ERROR) | |||
| return; | |||
| if (test_for_overlapping_contours(tobj) == GLU_ERROR) | |||
| return; | |||
| if (store_polygon_as_contour(tobj) == GLU_ERROR) | |||
| return; | |||
| } | |||
| static GLenum | |||
| test_for_overlapping_contours(GLUtriangulatorObj * tobj) | |||
| { | |||
| tess_contour *contour; | |||
| tess_polygon *polygon; | |||
| polygon = tobj->current_polygon; | |||
| for (contour = tobj->contours; contour != NULL; contour = contour->next) | |||
| if (contours_overlap(contour, polygon) != GLU_NO_ERROR) { | |||
| tess_call_user_error(tobj, GLU_TESS_ERROR5); | |||
| return GLU_ERROR; | |||
| } | |||
| return GLU_NO_ERROR; | |||
| } | |||
| static GLenum | |||
| store_polygon_as_contour(GLUtriangulatorObj * tobj) | |||
| { | |||
| tess_polygon *polygon = tobj->current_polygon; | |||
| tess_contour *contour = tobj->contours; | |||
| /* the first contour defined */ | |||
| if (contour == NULL) { | |||
| if ((contour = (tess_contour *) malloc(sizeof(tess_contour))) == NULL) { | |||
| tess_call_user_error(tobj, GLU_OUT_OF_MEMORY); | |||
| free_current_polygon(polygon); | |||
| return GLU_ERROR; | |||
| } | |||
| tobj->contours = tobj->last_contour = contour; | |||
| contour->next = contour->previous = NULL; | |||
| } | |||
| else { | |||
| if ((contour = (tess_contour *) malloc(sizeof(tess_contour))) == NULL) { | |||
| tess_call_user_error(tobj, GLU_OUT_OF_MEMORY); | |||
| free_current_polygon(polygon); | |||
| return GLU_ERROR; | |||
| } | |||
| contour->previous = tobj->last_contour; | |||
| tobj->last_contour->next = contour; | |||
| tobj->last_contour = contour; | |||
| contour->next = NULL; | |||
| } | |||
| /* mark all vertices in new contour as not special */ | |||
| /* and all are boundary edges */ | |||
| { | |||
| tess_vertex *vertex; | |||
| GLuint vertex_cnt, i; | |||
| for (vertex = polygon->vertices, i = 0, vertex_cnt = | |||
| polygon->vertex_cnt; i < vertex_cnt; vertex = vertex->next, i++) { | |||
| vertex->shadow_vertex = NULL; | |||
| vertex->edge_flag = GL_TRUE; | |||
| } | |||
| } | |||
| contour->vertex_cnt = polygon->vertex_cnt; | |||
| contour->area = polygon->area; | |||
| contour->orientation = polygon->orientation; | |||
| contour->type = GLU_UNKNOWN; | |||
| contour->vertices = polygon->vertices; | |||
| contour->last_vertex = polygon->last_vertex; | |||
| polygon->vertices = polygon->last_vertex = NULL; | |||
| polygon->vertex_cnt = 0; | |||
| ++(tobj->contour_cnt); | |||
| return GLU_NO_ERROR; | |||
| } | |||
| static void | |||
| free_current_polygon(tess_polygon * polygon) | |||
| { | |||
| tess_vertex *vertex, *vertex_tmp; | |||
| GLuint i; | |||
| /* free current_polygon structures */ | |||
| for (vertex = polygon->vertices, i = 0; i < polygon->vertex_cnt; i++) { | |||
| vertex_tmp = vertex->next; | |||
| free(vertex); | |||
| vertex = vertex_tmp; | |||
| } | |||
| polygon->vertices = polygon->last_vertex = NULL; | |||
| polygon->vertex_cnt = 0; | |||
| } | |||
| static void | |||
| prepare_projection_info(GLUtriangulatorObj * tobj) | |||
| { | |||
| tess_polygon *polygon = tobj->current_polygon; | |||
| tess_vertex *vertex, *last_vertex_ptr; | |||
| GLdouble area; | |||
| last_vertex_ptr = polygon->last_vertex; | |||
| switch (tobj->projection) { | |||
| case OXY: | |||
| for (vertex = polygon->vertices; vertex != last_vertex_ptr; | |||
| vertex = vertex->next) { | |||
| vertex->x = vertex->location[0]; | |||
| vertex->y = vertex->location[1]; | |||
| } | |||
| last_vertex_ptr->x = last_vertex_ptr->location[0]; | |||
| last_vertex_ptr->y = last_vertex_ptr->location[1]; | |||
| break; | |||
| case OXZ: | |||
| for (vertex = polygon->vertices; vertex != last_vertex_ptr; | |||
| vertex = vertex->next) { | |||
| vertex->x = vertex->location[0]; | |||
| vertex->y = vertex->location[2]; | |||
| } | |||
| last_vertex_ptr->x = last_vertex_ptr->location[0]; | |||
| last_vertex_ptr->y = last_vertex_ptr->location[2]; | |||
| break; | |||
| case OYZ: | |||
| for (vertex = polygon->vertices; vertex != last_vertex_ptr; | |||
| vertex = vertex->next) { | |||
| vertex->x = vertex->location[1]; | |||
| vertex->y = vertex->location[2]; | |||
| } | |||
| last_vertex_ptr->x = last_vertex_ptr->location[1]; | |||
| last_vertex_ptr->y = last_vertex_ptr->location[2]; | |||
| break; | |||
| } | |||
| area = twice_the_polygon_area(polygon->vertices, polygon->last_vertex); | |||
| if (area >= 0.0) { | |||
| polygon->orientation = GLU_CCW; | |||
| polygon->area = area; | |||
| } | |||
| else { | |||
| polygon->orientation = GLU_CW; | |||
| polygon->area = -area; | |||
| } | |||
| } | |||
| static GLdouble | |||
| twice_the_polygon_area(tess_vertex * vertex, tess_vertex * last_vertex) | |||
| { | |||
| tess_vertex *next; | |||
| GLdouble area, x, y; | |||
| area = 0.0; | |||
| x = vertex->x; | |||
| y = vertex->y; | |||
| vertex = vertex->next; | |||
| for (; vertex != last_vertex; vertex = vertex->next) { | |||
| next = vertex->next; | |||
| area += | |||
| (vertex->x - x) * (next->y - y) - (vertex->y - y) * (next->x - x); | |||
| } | |||
| return area; | |||
| } | |||
| /* test if edges ab and cd intersect */ | |||
| /* if not return GLU_NO_ERROR, else if cross return GLU_TESS_ERROR8, */ | |||
| /* else if adjacent return GLU_TESS_ERROR4 */ | |||
| static GLenum | |||
| edge_edge_intersect(tess_vertex * a, | |||
| tess_vertex * b, tess_vertex * c, tess_vertex * d) | |||
| { | |||
| GLdouble denom, r, s; | |||
| GLdouble xba, ydc, yba, xdc, yac, xac; | |||
| xba = b->x - a->x; | |||
| yba = b->y - a->y; | |||
| xdc = d->x - c->x; | |||
| ydc = d->y - c->y; | |||
| xac = a->x - c->x; | |||
| yac = a->y - c->y; | |||
| denom = xba * ydc - yba * xdc; | |||
| r = yac * xdc - xac * ydc; | |||
| /* parallel? */ | |||
| if (fabs(denom) < EPSILON) { | |||
| if (fabs(r) < EPSILON) { | |||
| /* colinear */ | |||
| if (fabs(xba) < EPSILON) { | |||
| /* compare the Y coordinate */ | |||
| if (yba > 0.0) { | |||
| if ( | |||
| (fabs(a->y - c->y) < EPSILON | |||
| && fabs(c->y - b->y) < EPSILON) | |||
| || (fabs(a->y - d->y) < EPSILON | |||
| && fabs(d->y - b->y) < | |||
| EPSILON)) return GLU_TESS_ERROR4; | |||
| } | |||
| else { | |||
| if ( | |||
| (fabs(b->y - c->y) < EPSILON | |||
| && fabs(c->y - a->y) < EPSILON) | |||
| || (fabs(b->y - d->y) < EPSILON | |||
| && fabs(d->y - a->y) < | |||
| EPSILON)) return GLU_TESS_ERROR4; | |||
| } | |||
| } | |||
| else { | |||
| /* compare the X coordinate */ | |||
| if (xba > 0.0) { | |||
| if ( | |||
| (fabs(a->x - c->x) < EPSILON | |||
| && fabs(c->x - b->x) < EPSILON) | |||
| || (fabs(a->x - d->x) < EPSILON | |||
| && fabs(d->x - b->x) < | |||
| EPSILON)) return GLU_TESS_ERROR4; | |||
| } | |||
| else { | |||
| if ( | |||
| (fabs(b->x - c->x) < EPSILON | |||
| && fabs(c->x - a->x) < EPSILON) | |||
| || (fabs(b->x - d->x) < EPSILON | |||
| && fabs(d->x - a->x) < | |||
| EPSILON)) return GLU_TESS_ERROR4; | |||
| } | |||
| } | |||
| } | |||
| return GLU_NO_ERROR; | |||
| } | |||
| r /= denom; | |||
| s = (yac * xba - xac * yba) / denom; | |||
| /* test if one vertex lies on other edge */ | |||
| if (((fabs(r) < EPSILON || (r < 1.0 + EPSILON && r > 1.0 - EPSILON)) && | |||
| s > -EPSILON && s < 1.0 + EPSILON) || | |||
| ((fabs(s) < EPSILON || (s < 1.0 + EPSILON && s > 1.0 - EPSILON)) && | |||
| r > -EPSILON && r < 1.0 + EPSILON)) { | |||
| return GLU_TESS_ERROR4; | |||
| } | |||
| /* test for crossing */ | |||
| if (r > -EPSILON && r < 1.0 + EPSILON && s > -EPSILON && s < 1.0 + EPSILON) { | |||
| return GLU_TESS_ERROR8; | |||
| } | |||
| return GLU_NO_ERROR; | |||
| } | |||
| static GLenum | |||
| verify_edge_vertex_intersections(GLUtriangulatorObj * tobj) | |||
| { | |||
| tess_polygon *polygon = tobj->current_polygon; | |||
| tess_vertex *vertex1, *last_vertex, *vertex2; | |||
| GLenum test; | |||
| last_vertex = polygon->last_vertex; | |||
| vertex1 = last_vertex; | |||
| for (vertex2 = vertex1->next->next; | |||
| vertex2->next != last_vertex; vertex2 = vertex2->next) { | |||
| test = edge_edge_intersect(vertex1, vertex1->next, vertex2, | |||
| vertex2->next); | |||
| if (test != GLU_NO_ERROR) { | |||
| tess_call_user_error(tobj, test); | |||
| return GLU_ERROR; | |||
| } | |||
| } | |||
| for (vertex1 = polygon->vertices; | |||
| vertex1->next->next != last_vertex; vertex1 = vertex1->next) { | |||
| for (vertex2 = vertex1->next->next; | |||
| vertex2 != last_vertex; vertex2 = vertex2->next) { | |||
| test = edge_edge_intersect(vertex1, vertex1->next, vertex2, | |||
| vertex2->next); | |||
| if (test != GLU_NO_ERROR) { | |||
| tess_call_user_error(tobj, test); | |||
| return GLU_ERROR; | |||
| } | |||
| } | |||
| } | |||
| return GLU_NO_ERROR; | |||
| } | |||
| static int | |||
| #ifdef WIN32 | |||
| __cdecl | |||
| #endif | |||
| area_compare(const void *a, const void *b) | |||
| { | |||
| GLdouble area1, area2; | |||
| area1 = (*((tess_contour **) a))->area; | |||
| area2 = (*((tess_contour **) b))->area; | |||
| if (area1 < area2) | |||
| return 1; | |||
| if (area1 > area2) | |||
| return -1; | |||
| return 0; | |||
| } | |||
| void | |||
| tess_find_contour_hierarchies(GLUtriangulatorObj * tobj) | |||
| { | |||
| tess_contour **contours; /* dinamic array of pointers */ | |||
| tess_contour *tmp_contour_ptr = tobj->contours; | |||
| GLuint cnt, i; | |||
| GLenum result; | |||
| GLboolean hierarchy_changed; | |||
| /* any contours? */ | |||
| if (tobj->contour_cnt < 2) { | |||
| tobj->contours->type = GLU_EXTERIOR; | |||
| return; | |||
| } | |||
| if ((contours = (tess_contour **) | |||
| malloc(sizeof(tess_contour *) * (tobj->contour_cnt))) == NULL) { | |||
| tess_call_user_error(tobj, GLU_OUT_OF_MEMORY); | |||
| return; | |||
| } | |||
| for (tmp_contour_ptr = tobj->contours, cnt = 0; | |||
| tmp_contour_ptr != NULL; tmp_contour_ptr = tmp_contour_ptr->next) | |||
| contours[cnt++] = tmp_contour_ptr; | |||
| /* now sort the contours in decreasing area size order */ | |||
| qsort((void *) contours, (size_t) cnt, (size_t) sizeof(tess_contour *), | |||
| area_compare); | |||
| /* we leave just the first contour - remove others from list */ | |||
| tobj->contours = contours[0]; | |||
| tobj->contours->next = tobj->contours->previous = NULL; | |||
| tobj->last_contour = tobj->contours; | |||
| tobj->contour_cnt = 1; | |||
| /* first contour is the one with greatest area */ | |||
| /* must be EXTERIOR */ | |||
| tobj->contours->type = GLU_EXTERIOR; | |||
| tmp_contour_ptr = tobj->contours; | |||
| /* now we play! */ | |||
| for (i = 1; i < cnt; i++) { | |||
| hierarchy_changed = GL_FALSE; | |||
| for (tmp_contour_ptr = tobj->contours; | |||
| tmp_contour_ptr != NULL; tmp_contour_ptr = tmp_contour_ptr->next) { | |||
| if (tmp_contour_ptr->type == GLU_EXTERIOR) { | |||
| /* check if contour completely contained in EXTERIOR */ | |||
| result = is_contour_contained_in(tmp_contour_ptr, contours[i]); | |||
| switch (result) { | |||
| case GLU_INTERIOR: | |||
| /* now we have to check if contour is inside interiors */ | |||
| /* or not */ | |||
| /* any interiors? */ | |||
| if (tmp_contour_ptr->next != NULL && | |||
| tmp_contour_ptr->next->type == GLU_INTERIOR) { | |||
| /* for all interior, check if inside any of them */ | |||
| /* if not inside any of interiors, its another */ | |||
| /* interior */ | |||
| /* or it may contain some interiors, then change */ | |||
| /* the contained interiors to exterior ones */ | |||
| add_interior_with_hierarchy_check(tobj, | |||
| tmp_contour_ptr, | |||
| contours[i]); | |||
| } | |||
| else { | |||
| /* not in interior, add as new interior contour */ | |||
| add_new_interior(tobj, tmp_contour_ptr, contours[i]); | |||
| } | |||
| hierarchy_changed = GL_TRUE; | |||
| break; | |||
| case GLU_EXTERIOR: | |||
| /* ooops, the marked as EXTERIOR (contours[i]) is */ | |||
| /* actually an interior of tmp_contour_ptr */ | |||
| /* reverse the local hierarchy */ | |||
| reverse_hierarchy_and_add_exterior(tobj, tmp_contour_ptr, | |||
| contours[i]); | |||
| hierarchy_changed = GL_TRUE; | |||
| break; | |||
| case GLU_NO_ERROR: | |||
| break; | |||
| default: | |||
| abort(); | |||
| } | |||
| } | |||
| if (hierarchy_changed) | |||
| break; /* break from for loop */ | |||
| } | |||
| if (hierarchy_changed == GL_FALSE) { | |||
| /* disjoint with all contours, add to contour list */ | |||
| add_new_exterior(tobj, contours[i]); | |||
| } | |||
| } | |||
| free(contours); | |||
| } | |||
| /* returns GLU_INTERIOR if inner is completey enclosed within outer */ | |||
| /* returns GLU_EXTERIOR if outer is completely enclosed within inner */ | |||
| /* returns GLU_NO_ERROR if contours are disjoint */ | |||
| static GLenum | |||
| is_contour_contained_in(tess_contour * outer, tess_contour * inner) | |||
| { | |||
| GLenum relation_flag; | |||
| /* set relation_flag to relation of containment of first inner vertex */ | |||
| /* regarding outer contour */ | |||
| if (point_in_polygon(outer, inner->vertices->x, inner->vertices->y)) | |||
| relation_flag = GLU_INTERIOR; | |||
| else | |||
| relation_flag = GLU_EXTERIOR; | |||
| if (relation_flag == GLU_INTERIOR) | |||
| return GLU_INTERIOR; | |||
| if (point_in_polygon(inner, outer->vertices->x, outer->vertices->y)) | |||
| return GLU_EXTERIOR; | |||
| return GLU_NO_ERROR; | |||
| } | |||
| static GLboolean | |||
| point_in_polygon(tess_contour * contour, GLdouble x, GLdouble y) | |||
| { | |||
| tess_vertex *v1, *v2; | |||
| GLuint i, vertex_cnt; | |||
| GLdouble xp1, yp1, xp2, yp2; | |||
| GLboolean tst; | |||
| tst = GL_FALSE; | |||
| v1 = contour->vertices; | |||
| v2 = contour->vertices->previous; | |||
| for (i = 0, vertex_cnt = contour->vertex_cnt; i < vertex_cnt; i++) { | |||
| xp1 = v1->x; | |||
| yp1 = v1->y; | |||
| xp2 = v2->x; | |||
| yp2 = v2->y; | |||
| if ((((yp1 <= y) && (y < yp2)) || ((yp2 <= y) && (y < yp1))) && | |||
| (x < (xp2 - xp1) * (y - yp1) / (yp2 - yp1) + xp1)) | |||
| tst = (tst == GL_FALSE ? GL_TRUE : GL_FALSE); | |||
| v2 = v1; | |||
| v1 = v1->next; | |||
| } | |||
| return tst; | |||
| } | |||
| static GLenum | |||
| contours_overlap(tess_contour * contour, tess_polygon * polygon) | |||
| { | |||
| tess_vertex *vertex1, *vertex2; | |||
| GLuint vertex1_cnt, vertex2_cnt, i, j; | |||
| GLenum test; | |||
| vertex1 = contour->vertices; | |||
| vertex2 = polygon->vertices; | |||
| vertex1_cnt = contour->vertex_cnt; | |||
| vertex2_cnt = polygon->vertex_cnt; | |||
| for (i = 0; i < vertex1_cnt; vertex1 = vertex1->next, i++) { | |||
| for (j = 0; j < vertex2_cnt; vertex2 = vertex2->next, j++) | |||
| if ((test = edge_edge_intersect(vertex1, vertex1->next, vertex2, | |||
| vertex2->next)) != GLU_NO_ERROR) | |||
| return test; | |||
| } | |||
| return GLU_NO_ERROR; | |||
| } | |||
| static void | |||
| add_new_exterior(GLUtriangulatorObj * tobj, tess_contour * contour) | |||
| { | |||
| contour->type = GLU_EXTERIOR; | |||
| contour->next = NULL; | |||
| contour->previous = tobj->last_contour; | |||
| tobj->last_contour->next = contour; | |||
| tobj->last_contour = contour; | |||
| } | |||
| static void | |||
| add_new_interior(GLUtriangulatorObj * tobj, | |||
| tess_contour * outer, tess_contour * contour) | |||
| { | |||
| contour->type = GLU_INTERIOR; | |||
| contour->next = outer->next; | |||
| contour->previous = outer; | |||
| if (outer->next != NULL) | |||
| outer->next->previous = contour; | |||
| outer->next = contour; | |||
| if (tobj->last_contour == outer) | |||
| tobj->last_contour = contour; | |||
| } | |||
| static void | |||
| add_interior_with_hierarchy_check(GLUtriangulatorObj * tobj, | |||
| tess_contour * outer, | |||
| tess_contour * contour) | |||
| { | |||
| tess_contour *ptr; | |||
| /* for all interiors of outer check if they are interior of contour */ | |||
| /* if so, change that interior to exterior and move it of of the */ | |||
| /* interior sequence */ | |||
| if (outer->next != NULL && outer->next->type == GLU_INTERIOR) { | |||
| GLenum test; | |||
| for (ptr = outer->next; ptr != NULL && ptr->type == GLU_INTERIOR; | |||
| ptr = ptr->next) { | |||
| test = is_contour_contained_in(ptr, contour); | |||
| switch (test) { | |||
| case GLU_INTERIOR: | |||
| /* contour is contained in one of the interiors */ | |||
| /* check if possibly contained in other exteriors */ | |||
| /* move ptr to first EXTERIOR */ | |||
| for (; ptr != NULL && ptr->type == GLU_INTERIOR; ptr = ptr->next); | |||
| if (ptr == NULL) | |||
| /* another exterior */ | |||
| add_new_exterior(tobj, contour); | |||
| else | |||
| add_exterior_with_check(tobj, ptr, contour); | |||
| return; | |||
| case GLU_EXTERIOR: | |||
| /* one of the interiors is contained in the contour */ | |||
| /* change it to EXTERIOR, and shift it away from the */ | |||
| /* interior sequence */ | |||
| shift_interior_to_exterior(tobj, ptr); | |||
| break; | |||
| case GLU_NO_ERROR: | |||
| /* disjoint */ | |||
| break; | |||
| default: | |||
| abort(); | |||
| } | |||
| } | |||
| } | |||
| /* add contour to the interior sequence */ | |||
| add_new_interior(tobj, outer, contour); | |||
| } | |||
| static void | |||
| reverse_hierarchy_and_add_exterior(GLUtriangulatorObj * tobj, | |||
| tess_contour * outer, | |||
| tess_contour * contour) | |||
| { | |||
| tess_contour *ptr; | |||
| /* reverse INTERIORS to EXTERIORS */ | |||
| /* any INTERIORS? */ | |||
| if (outer->next != NULL && outer->next->type == GLU_INTERIOR) | |||
| for (ptr = outer->next; ptr != NULL && ptr->type == GLU_INTERIOR; | |||
| ptr = ptr->next) ptr->type = GLU_EXTERIOR; | |||
| /* the outer now becomes inner */ | |||
| outer->type = GLU_INTERIOR; | |||
| /* contour is the EXTERIOR */ | |||
| contour->next = outer; | |||
| if (tobj->contours == outer) { | |||
| /* first contour beeing reversed */ | |||
| contour->previous = NULL; | |||
| tobj->contours = contour; | |||
| } | |||
| else { | |||
| outer->previous->next = contour; | |||
| contour->previous = outer->previous; | |||
| } | |||
| outer->previous = contour; | |||
| } | |||
| static void | |||
| shift_interior_to_exterior(GLUtriangulatorObj * tobj, tess_contour * contour) | |||
| { | |||
| contour->previous->next = contour->next; | |||
| if (contour->next != NULL) | |||
| contour->next->previous = contour->previous; | |||
| else | |||
| tobj->last_contour = contour->previous; | |||
| } | |||
| static void | |||
| add_exterior_with_check(GLUtriangulatorObj * tobj, | |||
| tess_contour * outer, tess_contour * contour) | |||
| { | |||
| GLenum test; | |||
| /* this contour might be interior to further exteriors - check */ | |||
| /* if not, just add as a new exterior */ | |||
| for (; outer != NULL && outer->type == GLU_EXTERIOR; outer = outer->next) { | |||
| test = is_contour_contained_in(outer, contour); | |||
| switch (test) { | |||
| case GLU_INTERIOR: | |||
| /* now we have to check if contour is inside interiors */ | |||
| /* or not */ | |||
| /* any interiors? */ | |||
| if (outer->next != NULL && outer->next->type == GLU_INTERIOR) { | |||
| /* for all interior, check if inside any of them */ | |||
| /* if not inside any of interiors, its another */ | |||
| /* interior */ | |||
| /* or it may contain some interiors, then change */ | |||
| /* the contained interiors to exterior ones */ | |||
| add_interior_with_hierarchy_check(tobj, outer, contour); | |||
| } | |||
| else { | |||
| /* not in interior, add as new interior contour */ | |||
| add_new_interior(tobj, outer, contour); | |||
| } | |||
| return; | |||
| case GLU_NO_ERROR: | |||
| /* disjoint */ | |||
| break; | |||
| default: | |||
| abort(); | |||
| } | |||
| } | |||
| /* add contour to the exterior sequence */ | |||
| add_new_exterior(tobj, contour); | |||
| } | |||
| void | |||
| tess_handle_holes(GLUtriangulatorObj * tobj) | |||
| { | |||
| tess_contour *contour, *hole; | |||
| GLenum exterior_orientation; | |||
| /* verify hole orientation */ | |||
| for (contour = tobj->contours; contour != NULL;) { | |||
| exterior_orientation = contour->orientation; | |||
| for (contour = contour->next; | |||
| contour != NULL && contour->type == GLU_INTERIOR; | |||
| contour = contour->next) { | |||
| if (contour->orientation == exterior_orientation) { | |||
| tess_call_user_error(tobj, GLU_TESS_ERROR5); | |||
| return; | |||
| } | |||
| } | |||
| } | |||
| /* now cut-out holes */ | |||
| for (contour = tobj->contours; contour != NULL;) { | |||
| hole = contour->next; | |||
| while (hole != NULL && hole->type == GLU_INTERIOR) { | |||
| if (cut_out_hole(tobj, contour, hole) == GLU_ERROR) | |||
| return; | |||
| hole = contour->next; | |||
| } | |||
| contour = contour->next; | |||
| } | |||
| } | |||
| static GLenum | |||
| cut_out_hole(GLUtriangulatorObj * tobj, | |||
| tess_contour * contour, tess_contour * hole) | |||
| { | |||
| tess_contour *tmp_hole; | |||
| tess_vertex *v1, *v2, *tmp_vertex; | |||
| GLuint vertex1_cnt, vertex2_cnt, tmp_vertex_cnt; | |||
| GLuint i, j, k; | |||
| GLenum test; | |||
| /* find an edge connecting contour and hole not intersecting any other */ | |||
| /* edge belonging to either the contour or any of the other holes */ | |||
| for (v1 = contour->vertices, vertex1_cnt = contour->vertex_cnt, i = 0; | |||
| i < vertex1_cnt; i++, v1 = v1->next) { | |||
| for (v2 = hole->vertices, vertex2_cnt = hole->vertex_cnt, j = 0; | |||
| j < vertex2_cnt; j++, v2 = v2->next) { | |||
| /* does edge (v1,v2) intersect any edge of contour */ | |||
| for (tmp_vertex = contour->vertices, tmp_vertex_cnt = | |||
| contour->vertex_cnt, k = 0; k < tmp_vertex_cnt; | |||
| tmp_vertex = tmp_vertex->next, k++) { | |||
| /* skip edge tests for edges directly connected */ | |||
| if (v1 == tmp_vertex || v1 == tmp_vertex->next) | |||
| continue; | |||
| test = edge_edge_intersect(v1, v2, tmp_vertex, tmp_vertex->next); | |||
| if (test != GLU_NO_ERROR) | |||
| break; | |||
| } | |||
| if (test == GLU_NO_ERROR) { | |||
| /* does edge (v1,v2) intersect any edge of hole */ | |||
| for (tmp_vertex = hole->vertices, | |||
| tmp_vertex_cnt = hole->vertex_cnt, k = 0; | |||
| k < tmp_vertex_cnt; tmp_vertex = tmp_vertex->next, k++) { | |||
| /* skip edge tests for edges directly connected */ | |||
| if (v2 == tmp_vertex || v2 == tmp_vertex->next) | |||
| continue; | |||
| test = | |||
| edge_edge_intersect(v1, v2, tmp_vertex, tmp_vertex->next); | |||
| if (test != GLU_NO_ERROR) | |||
| break; | |||
| } | |||
| if (test == GLU_NO_ERROR) { | |||
| /* does edge (v1,v2) intersect any other hole? */ | |||
| for (tmp_hole = hole->next; | |||
| tmp_hole != NULL && tmp_hole->type == GLU_INTERIOR; | |||
| tmp_hole = tmp_hole->next) { | |||
| /* does edge (v1,v2) intersect any edge of hole */ | |||
| for (tmp_vertex = tmp_hole->vertices, | |||
| tmp_vertex_cnt = tmp_hole->vertex_cnt, k = 0; | |||
| k < tmp_vertex_cnt; tmp_vertex = tmp_vertex->next, k++) { | |||
| test = edge_edge_intersect(v1, v2, tmp_vertex, | |||
| tmp_vertex->next); | |||
| if (test != GLU_NO_ERROR) | |||
| break; | |||
| } | |||
| if (test != GLU_NO_ERROR) | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| if (test == GLU_NO_ERROR) { | |||
| /* edge (v1,v2) is good for eliminating the hole */ | |||
| if (merge_hole_with_contour(tobj, contour, hole, v1, v2) | |||
| == GLU_NO_ERROR) | |||
| return GLU_NO_ERROR; | |||
| else | |||
| return GLU_ERROR; | |||
| } | |||
| } | |||
| } | |||
| /* other holes are blocking all possible connections of hole */ | |||
| /* with contour, we shift this hole as the last hole and retry */ | |||
| for (tmp_hole = hole; | |||
| tmp_hole != NULL && tmp_hole->type == GLU_INTERIOR; | |||
| tmp_hole = tmp_hole->next); | |||
| contour->next = hole->next; | |||
| hole->next->previous = contour; | |||
| if (tmp_hole == NULL) { | |||
| /* last EXTERIOR contour, shift hole as last contour */ | |||
| hole->next = NULL; | |||
| hole->previous = tobj->last_contour; | |||
| tobj->last_contour->next = hole; | |||
| tobj->last_contour = hole; | |||
| } | |||
| else { | |||
| tmp_hole->previous->next = hole; | |||
| hole->previous = tmp_hole->previous; | |||
| tmp_hole->previous = hole; | |||
| hole->next = tmp_hole; | |||
| } | |||
| hole = contour->next; | |||
| /* try once again - recurse */ | |||
| return cut_out_hole(tobj, contour, hole); | |||
| } | |||
| static GLenum | |||
| merge_hole_with_contour(GLUtriangulatorObj * tobj, | |||
| tess_contour * contour, | |||
| tess_contour * hole, | |||
| tess_vertex * v1, tess_vertex * v2) | |||
| { | |||
| tess_vertex *v1_new, *v2_new; | |||
| /* make copies of v1 and v2, place them respectively after their originals */ | |||
| if ((v1_new = (tess_vertex *) malloc(sizeof(tess_vertex))) == NULL) { | |||
| tess_call_user_error(tobj, GLU_OUT_OF_MEMORY); | |||
| return GLU_ERROR; | |||
| } | |||
| if ((v2_new = (tess_vertex *) malloc(sizeof(tess_vertex))) == NULL) { | |||
| tess_call_user_error(tobj, GLU_OUT_OF_MEMORY); | |||
| return GLU_ERROR; | |||
| } | |||
| v1_new->edge_flag = GL_TRUE; | |||
| v1_new->data = v1->data; | |||
| v1_new->location[0] = v1->location[0]; | |||
| v1_new->location[1] = v1->location[1]; | |||
| v1_new->location[2] = v1->location[2]; | |||
| v1_new->x = v1->x; | |||
| v1_new->y = v1->y; | |||
| v1_new->shadow_vertex = v1; | |||
| v1->shadow_vertex = v1_new; | |||
| v1_new->next = v1->next; | |||
| v1_new->previous = v1; | |||
| v1->next->previous = v1_new; | |||
| v1->next = v1_new; | |||
| v2_new->edge_flag = GL_TRUE; | |||
| v2_new->data = v2->data; | |||
| v2_new->location[0] = v2->location[0]; | |||
| v2_new->location[1] = v2->location[1]; | |||
| v2_new->location[2] = v2->location[2]; | |||
| v2_new->x = v2->x; | |||
| v2_new->y = v2->y; | |||
| v2_new->shadow_vertex = v2; | |||
| v2->shadow_vertex = v2_new; | |||
| v2_new->next = v2->next; | |||
| v2_new->previous = v2; | |||
| v2->next->previous = v2_new; | |||
| v2->next = v2_new; | |||
| /* link together the two lists */ | |||
| v1->next = v2_new; | |||
| v2_new->previous = v1; | |||
| v2->next = v1_new; | |||
| v1_new->previous = v2; | |||
| /* update the vertex count of the contour */ | |||
| contour->vertex_cnt += hole->vertex_cnt + 2; | |||
| /* remove the INTERIOR contour */ | |||
| contour->next = hole->next; | |||
| if (hole->next != NULL) | |||
| hole->next->previous = contour; | |||
| free(hole); | |||
| /* update tobj structure */ | |||
| --(tobj->contour_cnt); | |||
| if (contour->last_vertex == v1) | |||
| contour->last_vertex = v1_new; | |||
| /* mark two vertices with edge_flag */ | |||
| v2->edge_flag = GL_FALSE; | |||
| v1->edge_flag = GL_FALSE; | |||
| return GLU_NO_ERROR; | |||
| } | |||
| @@ -1,9 +1,9 @@ | |||
| /* $Id: project.c,v 1.2 1999/09/14 00:10:31 brianp Exp $ */ | |||
| /* $Id: project.c,v 1.3 2000/07/11 14:11:04 brianp Exp $ */ | |||
| /* | |||
| * Mesa 3-D graphics library | |||
| * Version: 3.1 | |||
| * Copyright (C) 1995-1999 Brian Paul | |||
| * Version: 3.3 | |||
| * Copyright (C) 1995-2000 Brian Paul | |||
| * | |||
| * This library is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Library General Public | |||
| @@ -21,38 +21,6 @@ | |||
| */ | |||
| /* | |||
| * $Log: project.c,v $ | |||
| * Revision 1.2 1999/09/14 00:10:31 brianp | |||
| * added gluUnProject4() | |||
| * | |||
| * Revision 1.1.1.1 1999/08/19 00:55:42 jtg | |||
| * Imported sources | |||
| * | |||
| * Revision 1.7 1999/01/03 03:23:15 brianp | |||
| * now using GLAPIENTRY and GLCALLBACK keywords (Ted Jump) | |||
| * | |||
| * Revision 1.6 1998/07/08 01:43:43 brianp | |||
| * new version of invert_matrix() (also in src/matrix.c) | |||
| * | |||
| * Revision 1.5 1997/07/24 01:28:44 brianp | |||
| * changed precompiled header symbol from PCH to PC_HEADER | |||
| * | |||
| * Revision 1.4 1997/05/28 02:29:38 brianp | |||
| * added support for precompiled headers (PCH), inserted APIENTRY keyword | |||
| * | |||
| * Revision 1.3 1997/04/11 23:22:42 brianp | |||
| * added divide by zero checks to gluProject() and gluUnproject() | |||
| * | |||
| * Revision 1.2 1997/01/29 19:05:29 brianp | |||
| * faster invert_matrix() function from Stephane Rehel | |||
| * | |||
| * Revision 1.1 1996/09/27 01:19:39 brianp | |||
| * Initial revision | |||
| * | |||
| */ | |||
| #ifdef PC_HEADER | |||
| #include "all.h" | |||
| #else | |||
| @@ -81,14 +49,18 @@ | |||
| * in - the 4x1 vector | |||
| * Output: out - the resulting 4x1 vector. | |||
| */ | |||
| static void transform_point( GLdouble out[4], const GLdouble m[16], | |||
| const GLdouble in[4] ) | |||
| static void | |||
| transform_point(GLdouble out[4], const GLdouble m[16], const GLdouble in[4]) | |||
| { | |||
| #define M(row,col) m[col*4+row] | |||
| out[0] = M(0,0) * in[0] + M(0,1) * in[1] + M(0,2) * in[2] + M(0,3) * in[3]; | |||
| out[1] = M(1,0) * in[0] + M(1,1) * in[1] + M(1,2) * in[2] + M(1,3) * in[3]; | |||
| out[2] = M(2,0) * in[0] + M(2,1) * in[1] + M(2,2) * in[2] + M(2,3) * in[3]; | |||
| out[3] = M(3,0) * in[0] + M(3,1) * in[1] + M(3,2) * in[2] + M(3,3) * in[3]; | |||
| out[0] = | |||
| M(0, 0) * in[0] + M(0, 1) * in[1] + M(0, 2) * in[2] + M(0, 3) * in[3]; | |||
| out[1] = | |||
| M(1, 0) * in[0] + M(1, 1) * in[1] + M(1, 2) * in[2] + M(1, 3) * in[3]; | |||
| out[2] = | |||
| M(2, 0) * in[0] + M(2, 1) * in[1] + M(2, 2) * in[2] + M(2, 3) * in[3]; | |||
| out[3] = | |||
| M(3, 0) * in[0] + M(3, 1) * in[1] + M(3, 2) * in[2] + M(3, 3) * in[3]; | |||
| #undef M | |||
| } | |||
| @@ -100,7 +72,8 @@ static void transform_point( GLdouble out[4], const GLdouble m[16], | |||
| * Input: a, b - matrices to multiply | |||
| * Output: product - product of a and b | |||
| */ | |||
| static void matmul( GLdouble *product, const GLdouble *a, const GLdouble *b ) | |||
| static void | |||
| matmul(GLdouble * product, const GLdouble * a, const GLdouble * b) | |||
| { | |||
| /* This matmul was contributed by Thomas Malik */ | |||
| GLdouble temp[16]; | |||
| @@ -111,18 +84,29 @@ static void matmul( GLdouble *product, const GLdouble *a, const GLdouble *b ) | |||
| #define T(row,col) temp[(col<<2)+row] | |||
| /* i-te Zeile */ | |||
| for (i = 0; i < 4; i++) | |||
| { | |||
| T(i, 0) = A(i, 0) * B(0, 0) + A(i, 1) * B(1, 0) + A(i, 2) * B(2, 0) + A(i, 3) * B(3, 0); | |||
| T(i, 1) = A(i, 0) * B(0, 1) + A(i, 1) * B(1, 1) + A(i, 2) * B(2, 1) + A(i, 3) * B(3, 1); | |||
| T(i, 2) = A(i, 0) * B(0, 2) + A(i, 1) * B(1, 2) + A(i, 2) * B(2, 2) + A(i, 3) * B(3, 2); | |||
| T(i, 3) = A(i, 0) * B(0, 3) + A(i, 1) * B(1, 3) + A(i, 2) * B(2, 3) + A(i, 3) * B(3, 3); | |||
| } | |||
| for (i = 0; i < 4; i++) { | |||
| T(i, 0) = | |||
| A(i, 0) * B(0, 0) + A(i, 1) * B(1, 0) + A(i, 2) * B(2, 0) + A(i, | |||
| 3) * | |||
| B(3, 0); | |||
| T(i, 1) = | |||
| A(i, 0) * B(0, 1) + A(i, 1) * B(1, 1) + A(i, 2) * B(2, 1) + A(i, | |||
| 3) * | |||
| B(3, 1); | |||
| T(i, 2) = | |||
| A(i, 0) * B(0, 2) + A(i, 1) * B(1, 2) + A(i, 2) * B(2, 2) + A(i, | |||
| 3) * | |||
| B(3, 2); | |||
| T(i, 3) = | |||
| A(i, 0) * B(0, 3) + A(i, 1) * B(1, 3) + A(i, 2) * B(2, 3) + A(i, | |||
| 3) * | |||
| B(3, 3); | |||
| } | |||
| #undef A | |||
| #undef B | |||
| #undef T | |||
| MEMCPY( product, temp, 16*sizeof(GLdouble) ); | |||
| MEMCPY(product, temp, 16 * sizeof(GLdouble)); | |||
| } | |||
| @@ -132,118 +116,175 @@ static void matmul( GLdouble *product, const GLdouble *a, const GLdouble *b ) | |||
| * Code contributed by Jacques Leroy jle@star.be | |||
| * Return GL_TRUE for success, GL_FALSE for failure (singular matrix) | |||
| */ | |||
| static GLboolean invert_matrix( const GLdouble *m, GLdouble *out ) | |||
| static GLboolean | |||
| invert_matrix(const GLdouble * m, GLdouble * out) | |||
| { | |||
| /* NB. OpenGL Matrices are COLUMN major. */ | |||
| #define SWAP_ROWS(a, b) { GLdouble *_tmp = a; (a)=(b); (b)=_tmp; } | |||
| #define MAT(m,r,c) (m)[(c)*4+(r)] | |||
| GLdouble wtmp[4][8]; | |||
| GLdouble m0, m1, m2, m3, s; | |||
| GLdouble *r0, *r1, *r2, *r3; | |||
| r0 = wtmp[0], r1 = wtmp[1], r2 = wtmp[2], r3 = wtmp[3]; | |||
| r0[0] = MAT(m,0,0), r0[1] = MAT(m,0,1), | |||
| r0[2] = MAT(m,0,2), r0[3] = MAT(m,0,3), | |||
| r0[4] = 1.0, r0[5] = r0[6] = r0[7] = 0.0, | |||
| r1[0] = MAT(m,1,0), r1[1] = MAT(m,1,1), | |||
| r1[2] = MAT(m,1,2), r1[3] = MAT(m,1,3), | |||
| r1[5] = 1.0, r1[4] = r1[6] = r1[7] = 0.0, | |||
| r2[0] = MAT(m,2,0), r2[1] = MAT(m,2,1), | |||
| r2[2] = MAT(m,2,2), r2[3] = MAT(m,2,3), | |||
| r2[6] = 1.0, r2[4] = r2[5] = r2[7] = 0.0, | |||
| r3[0] = MAT(m,3,0), r3[1] = MAT(m,3,1), | |||
| r3[2] = MAT(m,3,2), r3[3] = MAT(m,3,3), | |||
| r3[7] = 1.0, r3[4] = r3[5] = r3[6] = 0.0; | |||
| /* choose pivot - or die */ | |||
| if (fabs(r3[0])>fabs(r2[0])) SWAP_ROWS(r3, r2); | |||
| if (fabs(r2[0])>fabs(r1[0])) SWAP_ROWS(r2, r1); | |||
| if (fabs(r1[0])>fabs(r0[0])) SWAP_ROWS(r1, r0); | |||
| if (0.0 == r0[0]) return GL_FALSE; | |||
| /* eliminate first variable */ | |||
| m1 = r1[0]/r0[0]; m2 = r2[0]/r0[0]; m3 = r3[0]/r0[0]; | |||
| s = r0[1]; r1[1] -= m1 * s; r2[1] -= m2 * s; r3[1] -= m3 * s; | |||
| s = r0[2]; r1[2] -= m1 * s; r2[2] -= m2 * s; r3[2] -= m3 * s; | |||
| s = r0[3]; r1[3] -= m1 * s; r2[3] -= m2 * s; r3[3] -= m3 * s; | |||
| s = r0[4]; | |||
| if (s != 0.0) { r1[4] -= m1 * s; r2[4] -= m2 * s; r3[4] -= m3 * s; } | |||
| s = r0[5]; | |||
| if (s != 0.0) { r1[5] -= m1 * s; r2[5] -= m2 * s; r3[5] -= m3 * s; } | |||
| s = r0[6]; | |||
| if (s != 0.0) { r1[6] -= m1 * s; r2[6] -= m2 * s; r3[6] -= m3 * s; } | |||
| s = r0[7]; | |||
| if (s != 0.0) { r1[7] -= m1 * s; r2[7] -= m2 * s; r3[7] -= m3 * s; } | |||
| /* choose pivot - or die */ | |||
| if (fabs(r3[1])>fabs(r2[1])) SWAP_ROWS(r3, r2); | |||
| if (fabs(r2[1])>fabs(r1[1])) SWAP_ROWS(r2, r1); | |||
| if (0.0 == r1[1]) return GL_FALSE; | |||
| /* eliminate second variable */ | |||
| m2 = r2[1]/r1[1]; m3 = r3[1]/r1[1]; | |||
| r2[2] -= m2 * r1[2]; r3[2] -= m3 * r1[2]; | |||
| r2[3] -= m2 * r1[3]; r3[3] -= m3 * r1[3]; | |||
| s = r1[4]; if (0.0 != s) { r2[4] -= m2 * s; r3[4] -= m3 * s; } | |||
| s = r1[5]; if (0.0 != s) { r2[5] -= m2 * s; r3[5] -= m3 * s; } | |||
| s = r1[6]; if (0.0 != s) { r2[6] -= m2 * s; r3[6] -= m3 * s; } | |||
| s = r1[7]; if (0.0 != s) { r2[7] -= m2 * s; r3[7] -= m3 * s; } | |||
| /* choose pivot - or die */ | |||
| if (fabs(r3[2])>fabs(r2[2])) SWAP_ROWS(r3, r2); | |||
| if (0.0 == r2[2]) return GL_FALSE; | |||
| /* eliminate third variable */ | |||
| m3 = r3[2]/r2[2]; | |||
| r3[3] -= m3 * r2[3], r3[4] -= m3 * r2[4], | |||
| r3[5] -= m3 * r2[5], r3[6] -= m3 * r2[6], | |||
| r3[7] -= m3 * r2[7]; | |||
| /* last check */ | |||
| if (0.0 == r3[3]) return GL_FALSE; | |||
| s = 1.0/r3[3]; /* now back substitute row 3 */ | |||
| r3[4] *= s; r3[5] *= s; r3[6] *= s; r3[7] *= s; | |||
| m2 = r2[3]; /* now back substitute row 2 */ | |||
| s = 1.0/r2[2]; | |||
| r2[4] = s * (r2[4] - r3[4] * m2), r2[5] = s * (r2[5] - r3[5] * m2), | |||
| r2[6] = s * (r2[6] - r3[6] * m2), r2[7] = s * (r2[7] - r3[7] * m2); | |||
| m1 = r1[3]; | |||
| r1[4] -= r3[4] * m1, r1[5] -= r3[5] * m1, | |||
| r1[6] -= r3[6] * m1, r1[7] -= r3[7] * m1; | |||
| m0 = r0[3]; | |||
| r0[4] -= r3[4] * m0, r0[5] -= r3[5] * m0, | |||
| r0[6] -= r3[6] * m0, r0[7] -= r3[7] * m0; | |||
| m1 = r1[2]; /* now back substitute row 1 */ | |||
| s = 1.0/r1[1]; | |||
| r1[4] = s * (r1[4] - r2[4] * m1), r1[5] = s * (r1[5] - r2[5] * m1), | |||
| r1[6] = s * (r1[6] - r2[6] * m1), r1[7] = s * (r1[7] - r2[7] * m1); | |||
| m0 = r0[2]; | |||
| r0[4] -= r2[4] * m0, r0[5] -= r2[5] * m0, | |||
| r0[6] -= r2[6] * m0, r0[7] -= r2[7] * m0; | |||
| m0 = r0[1]; /* now back substitute row 0 */ | |||
| s = 1.0/r0[0]; | |||
| r0[4] = s * (r0[4] - r1[4] * m0), r0[5] = s * (r0[5] - r1[5] * m0), | |||
| r0[6] = s * (r0[6] - r1[6] * m0), r0[7] = s * (r0[7] - r1[7] * m0); | |||
| MAT(out,0,0) = r0[4]; MAT(out,0,1) = r0[5], | |||
| MAT(out,0,2) = r0[6]; MAT(out,0,3) = r0[7], | |||
| MAT(out,1,0) = r1[4]; MAT(out,1,1) = r1[5], | |||
| MAT(out,1,2) = r1[6]; MAT(out,1,3) = r1[7], | |||
| MAT(out,2,0) = r2[4]; MAT(out,2,1) = r2[5], | |||
| MAT(out,2,2) = r2[6]; MAT(out,2,3) = r2[7], | |||
| MAT(out,3,0) = r3[4]; MAT(out,3,1) = r3[5], | |||
| MAT(out,3,2) = r3[6]; MAT(out,3,3) = r3[7]; | |||
| return GL_TRUE; | |||
| GLdouble wtmp[4][8]; | |||
| GLdouble m0, m1, m2, m3, s; | |||
| GLdouble *r0, *r1, *r2, *r3; | |||
| r0 = wtmp[0], r1 = wtmp[1], r2 = wtmp[2], r3 = wtmp[3]; | |||
| r0[0] = MAT(m, 0, 0), r0[1] = MAT(m, 0, 1), | |||
| r0[2] = MAT(m, 0, 2), r0[3] = MAT(m, 0, 3), | |||
| r0[4] = 1.0, r0[5] = r0[6] = r0[7] = 0.0, | |||
| r1[0] = MAT(m, 1, 0), r1[1] = MAT(m, 1, 1), | |||
| r1[2] = MAT(m, 1, 2), r1[3] = MAT(m, 1, 3), | |||
| r1[5] = 1.0, r1[4] = r1[6] = r1[7] = 0.0, | |||
| r2[0] = MAT(m, 2, 0), r2[1] = MAT(m, 2, 1), | |||
| r2[2] = MAT(m, 2, 2), r2[3] = MAT(m, 2, 3), | |||
| r2[6] = 1.0, r2[4] = r2[5] = r2[7] = 0.0, | |||
| r3[0] = MAT(m, 3, 0), r3[1] = MAT(m, 3, 1), | |||
| r3[2] = MAT(m, 3, 2), r3[3] = MAT(m, 3, 3), | |||
| r3[7] = 1.0, r3[4] = r3[5] = r3[6] = 0.0; | |||
| /* choose pivot - or die */ | |||
| if (fabs(r3[0]) > fabs(r2[0])) | |||
| SWAP_ROWS(r3, r2); | |||
| if (fabs(r2[0]) > fabs(r1[0])) | |||
| SWAP_ROWS(r2, r1); | |||
| if (fabs(r1[0]) > fabs(r0[0])) | |||
| SWAP_ROWS(r1, r0); | |||
| if (0.0 == r0[0]) | |||
| return GL_FALSE; | |||
| /* eliminate first variable */ | |||
| m1 = r1[0] / r0[0]; | |||
| m2 = r2[0] / r0[0]; | |||
| m3 = r3[0] / r0[0]; | |||
| s = r0[1]; | |||
| r1[1] -= m1 * s; | |||
| r2[1] -= m2 * s; | |||
| r3[1] -= m3 * s; | |||
| s = r0[2]; | |||
| r1[2] -= m1 * s; | |||
| r2[2] -= m2 * s; | |||
| r3[2] -= m3 * s; | |||
| s = r0[3]; | |||
| r1[3] -= m1 * s; | |||
| r2[3] -= m2 * s; | |||
| r3[3] -= m3 * s; | |||
| s = r0[4]; | |||
| if (s != 0.0) { | |||
| r1[4] -= m1 * s; | |||
| r2[4] -= m2 * s; | |||
| r3[4] -= m3 * s; | |||
| } | |||
| s = r0[5]; | |||
| if (s != 0.0) { | |||
| r1[5] -= m1 * s; | |||
| r2[5] -= m2 * s; | |||
| r3[5] -= m3 * s; | |||
| } | |||
| s = r0[6]; | |||
| if (s != 0.0) { | |||
| r1[6] -= m1 * s; | |||
| r2[6] -= m2 * s; | |||
| r3[6] -= m3 * s; | |||
| } | |||
| s = r0[7]; | |||
| if (s != 0.0) { | |||
| r1[7] -= m1 * s; | |||
| r2[7] -= m2 * s; | |||
| r3[7] -= m3 * s; | |||
| } | |||
| /* choose pivot - or die */ | |||
| if (fabs(r3[1]) > fabs(r2[1])) | |||
| SWAP_ROWS(r3, r2); | |||
| if (fabs(r2[1]) > fabs(r1[1])) | |||
| SWAP_ROWS(r2, r1); | |||
| if (0.0 == r1[1]) | |||
| return GL_FALSE; | |||
| /* eliminate second variable */ | |||
| m2 = r2[1] / r1[1]; | |||
| m3 = r3[1] / r1[1]; | |||
| r2[2] -= m2 * r1[2]; | |||
| r3[2] -= m3 * r1[2]; | |||
| r2[3] -= m2 * r1[3]; | |||
| r3[3] -= m3 * r1[3]; | |||
| s = r1[4]; | |||
| if (0.0 != s) { | |||
| r2[4] -= m2 * s; | |||
| r3[4] -= m3 * s; | |||
| } | |||
| s = r1[5]; | |||
| if (0.0 != s) { | |||
| r2[5] -= m2 * s; | |||
| r3[5] -= m3 * s; | |||
| } | |||
| s = r1[6]; | |||
| if (0.0 != s) { | |||
| r2[6] -= m2 * s; | |||
| r3[6] -= m3 * s; | |||
| } | |||
| s = r1[7]; | |||
| if (0.0 != s) { | |||
| r2[7] -= m2 * s; | |||
| r3[7] -= m3 * s; | |||
| } | |||
| /* choose pivot - or die */ | |||
| if (fabs(r3[2]) > fabs(r2[2])) | |||
| SWAP_ROWS(r3, r2); | |||
| if (0.0 == r2[2]) | |||
| return GL_FALSE; | |||
| /* eliminate third variable */ | |||
| m3 = r3[2] / r2[2]; | |||
| r3[3] -= m3 * r2[3], r3[4] -= m3 * r2[4], | |||
| r3[5] -= m3 * r2[5], r3[6] -= m3 * r2[6], r3[7] -= m3 * r2[7]; | |||
| /* last check */ | |||
| if (0.0 == r3[3]) | |||
| return GL_FALSE; | |||
| s = 1.0 / r3[3]; /* now back substitute row 3 */ | |||
| r3[4] *= s; | |||
| r3[5] *= s; | |||
| r3[6] *= s; | |||
| r3[7] *= s; | |||
| m2 = r2[3]; /* now back substitute row 2 */ | |||
| s = 1.0 / r2[2]; | |||
| r2[4] = s * (r2[4] - r3[4] * m2), r2[5] = s * (r2[5] - r3[5] * m2), | |||
| r2[6] = s * (r2[6] - r3[6] * m2), r2[7] = s * (r2[7] - r3[7] * m2); | |||
| m1 = r1[3]; | |||
| r1[4] -= r3[4] * m1, r1[5] -= r3[5] * m1, | |||
| r1[6] -= r3[6] * m1, r1[7] -= r3[7] * m1; | |||
| m0 = r0[3]; | |||
| r0[4] -= r3[4] * m0, r0[5] -= r3[5] * m0, | |||
| r0[6] -= r3[6] * m0, r0[7] -= r3[7] * m0; | |||
| m1 = r1[2]; /* now back substitute row 1 */ | |||
| s = 1.0 / r1[1]; | |||
| r1[4] = s * (r1[4] - r2[4] * m1), r1[5] = s * (r1[5] - r2[5] * m1), | |||
| r1[6] = s * (r1[6] - r2[6] * m1), r1[7] = s * (r1[7] - r2[7] * m1); | |||
| m0 = r0[2]; | |||
| r0[4] -= r2[4] * m0, r0[5] -= r2[5] * m0, | |||
| r0[6] -= r2[6] * m0, r0[7] -= r2[7] * m0; | |||
| m0 = r0[1]; /* now back substitute row 0 */ | |||
| s = 1.0 / r0[0]; | |||
| r0[4] = s * (r0[4] - r1[4] * m0), r0[5] = s * (r0[5] - r1[5] * m0), | |||
| r0[6] = s * (r0[6] - r1[6] * m0), r0[7] = s * (r0[7] - r1[7] * m0); | |||
| MAT(out, 0, 0) = r0[4]; | |||
| MAT(out, 0, 1) = r0[5], MAT(out, 0, 2) = r0[6]; | |||
| MAT(out, 0, 3) = r0[7], MAT(out, 1, 0) = r1[4]; | |||
| MAT(out, 1, 1) = r1[5], MAT(out, 1, 2) = r1[6]; | |||
| MAT(out, 1, 3) = r1[7], MAT(out, 2, 0) = r2[4]; | |||
| MAT(out, 2, 1) = r2[5], MAT(out, 2, 2) = r2[6]; | |||
| MAT(out, 2, 3) = r2[7], MAT(out, 3, 0) = r3[4]; | |||
| MAT(out, 3, 1) = r3[5], MAT(out, 3, 2) = r3[6]; | |||
| MAT(out, 3, 3) = r3[7]; | |||
| return GL_TRUE; | |||
| #undef MAT | |||
| #undef SWAP_ROWS | |||
| @@ -252,63 +293,70 @@ static GLboolean invert_matrix( const GLdouble *m, GLdouble *out ) | |||
| /* projection du point (objx,objy,obz) sur l'ecran (winx,winy,winz) */ | |||
| GLint GLAPIENTRY gluProject(GLdouble objx,GLdouble objy,GLdouble objz, | |||
| const GLdouble model[16],const GLdouble proj[16], | |||
| const GLint viewport[4], | |||
| GLdouble *winx,GLdouble *winy,GLdouble *winz) | |||
| GLint GLAPIENTRY | |||
| gluProject(GLdouble objx, GLdouble objy, GLdouble objz, | |||
| const GLdouble model[16], const GLdouble proj[16], | |||
| const GLint viewport[4], | |||
| GLdouble * winx, GLdouble * winy, GLdouble * winz) | |||
| { | |||
| /* matrice de transformation */ | |||
| GLdouble in[4],out[4]; | |||
| /* initilise la matrice et le vecteur a transformer */ | |||
| in[0]=objx; in[1]=objy; in[2]=objz; in[3]=1.0; | |||
| transform_point(out,model,in); | |||
| transform_point(in,proj,out); | |||
| /* d'ou le resultat normalise entre -1 et 1*/ | |||
| if (in[3]==0.0) | |||
| return GL_FALSE; | |||
| in[0]/=in[3]; in[1]/=in[3]; in[2]/=in[3]; | |||
| /* en coordonnees ecran */ | |||
| *winx = viewport[0]+(1+in[0])*viewport[2]/2; | |||
| *winy = viewport[1]+(1+in[1])*viewport[3]/2; | |||
| /* entre 0 et 1 suivant z */ | |||
| *winz = (1+in[2])/2; | |||
| return GL_TRUE; | |||
| /* matrice de transformation */ | |||
| GLdouble in[4], out[4]; | |||
| /* initilise la matrice et le vecteur a transformer */ | |||
| in[0] = objx; | |||
| in[1] = objy; | |||
| in[2] = objz; | |||
| in[3] = 1.0; | |||
| transform_point(out, model, in); | |||
| transform_point(in, proj, out); | |||
| /* d'ou le resultat normalise entre -1 et 1 */ | |||
| if (in[3] == 0.0) | |||
| return GL_FALSE; | |||
| in[0] /= in[3]; | |||
| in[1] /= in[3]; | |||
| in[2] /= in[3]; | |||
| /* en coordonnees ecran */ | |||
| *winx = viewport[0] + (1 + in[0]) * viewport[2] / 2; | |||
| *winy = viewport[1] + (1 + in[1]) * viewport[3] / 2; | |||
| /* entre 0 et 1 suivant z */ | |||
| *winz = (1 + in[2]) / 2; | |||
| return GL_TRUE; | |||
| } | |||
| /* transformation du point ecran (winx,winy,winz) en point objet */ | |||
| GLint GLAPIENTRY gluUnProject(GLdouble winx,GLdouble winy,GLdouble winz, | |||
| const GLdouble model[16],const GLdouble proj[16], | |||
| const GLint viewport[4], | |||
| GLdouble *objx,GLdouble *objy,GLdouble *objz) | |||
| GLint GLAPIENTRY | |||
| gluUnProject(GLdouble winx, GLdouble winy, GLdouble winz, | |||
| const GLdouble model[16], const GLdouble proj[16], | |||
| const GLint viewport[4], | |||
| GLdouble * objx, GLdouble * objy, GLdouble * objz) | |||
| { | |||
| /* matrice de transformation */ | |||
| GLdouble m[16], A[16]; | |||
| GLdouble in[4],out[4]; | |||
| /* transformation coordonnees normalisees entre -1 et 1 */ | |||
| in[0]=(winx-viewport[0])*2/viewport[2] - 1.0; | |||
| in[1]=(winy-viewport[1])*2/viewport[3] - 1.0; | |||
| in[2]=2*winz - 1.0; | |||
| in[3]=1.0; | |||
| /* calcul transformation inverse */ | |||
| matmul(A,proj,model); | |||
| invert_matrix(A,m); | |||
| /* d'ou les coordonnees objets */ | |||
| transform_point(out,m,in); | |||
| if (out[3]==0.0) | |||
| return GL_FALSE; | |||
| *objx=out[0]/out[3]; | |||
| *objy=out[1]/out[3]; | |||
| *objz=out[2]/out[3]; | |||
| return GL_TRUE; | |||
| /* matrice de transformation */ | |||
| GLdouble m[16], A[16]; | |||
| GLdouble in[4], out[4]; | |||
| /* transformation coordonnees normalisees entre -1 et 1 */ | |||
| in[0] = (winx - viewport[0]) * 2 / viewport[2] - 1.0; | |||
| in[1] = (winy - viewport[1]) * 2 / viewport[3] - 1.0; | |||
| in[2] = 2 * winz - 1.0; | |||
| in[3] = 1.0; | |||
| /* calcul transformation inverse */ | |||
| matmul(A, proj, model); | |||
| invert_matrix(A, m); | |||
| /* d'ou les coordonnees objets */ | |||
| transform_point(out, m, in); | |||
| if (out[3] == 0.0) | |||
| return GL_FALSE; | |||
| *objx = out[0] / out[3]; | |||
| *objy = out[1] / out[3]; | |||
| *objz = out[2] / out[3]; | |||
| return GL_TRUE; | |||
| } | |||
| @@ -316,36 +364,39 @@ GLint GLAPIENTRY gluUnProject(GLdouble winx,GLdouble winy,GLdouble winz, | |||
| * New in GLU 1.3 | |||
| * This is like gluUnProject but also takes near and far DepthRange values. | |||
| */ | |||
| #ifdef GLU_VERSION_1_3 | |||
| GLint GLAPIENTRY | |||
| gluUnProject4( GLdouble winx, GLdouble winy, GLdouble winz, GLdouble clipw, | |||
| const GLdouble modelMatrix[16], | |||
| const GLdouble projMatrix[16], | |||
| const GLint viewport[4], | |||
| GLclampd nearZ, GLclampd farZ, | |||
| GLdouble *objx, GLdouble *objy, GLdouble *objz, GLdouble *objw ) | |||
| gluUnProject4(GLdouble winx, GLdouble winy, GLdouble winz, GLdouble clipw, | |||
| const GLdouble modelMatrix[16], | |||
| const GLdouble projMatrix[16], | |||
| const GLint viewport[4], | |||
| GLclampd nearZ, GLclampd farZ, | |||
| GLdouble * objx, GLdouble * objy, GLdouble * objz, | |||
| GLdouble * objw) | |||
| { | |||
| /* matrice de transformation */ | |||
| GLdouble m[16], A[16]; | |||
| GLdouble in[4],out[4]; | |||
| GLdouble z = nearZ + winz * (farZ - nearZ); | |||
| /* transformation coordonnees normalisees entre -1 et 1 */ | |||
| in[0] = (winx-viewport[0])*2/viewport[2] - 1.0; | |||
| in[1] = (winy-viewport[1])*2/viewport[3] - 1.0; | |||
| in[2] = 2.0 * z - 1.0; | |||
| in[3] = clipw; | |||
| /* calcul transformation inverse */ | |||
| matmul(A,projMatrix,modelMatrix); | |||
| invert_matrix(A,m); | |||
| /* d'ou les coordonnees objets */ | |||
| transform_point(out,m,in); | |||
| if (out[3]==0.0) | |||
| return GL_FALSE; | |||
| *objx=out[0]/out[3]; | |||
| *objy=out[1]/out[3]; | |||
| *objz=out[2]/out[3]; | |||
| *objw=out[3]; | |||
| return GL_TRUE; | |||
| /* matrice de transformation */ | |||
| GLdouble m[16], A[16]; | |||
| GLdouble in[4], out[4]; | |||
| GLdouble z = nearZ + winz * (farZ - nearZ); | |||
| /* transformation coordonnees normalisees entre -1 et 1 */ | |||
| in[0] = (winx - viewport[0]) * 2 / viewport[2] - 1.0; | |||
| in[1] = (winy - viewport[1]) * 2 / viewport[3] - 1.0; | |||
| in[2] = 2.0 * z - 1.0; | |||
| in[3] = clipw; | |||
| /* calcul transformation inverse */ | |||
| matmul(A, projMatrix, modelMatrix); | |||
| invert_matrix(A, m); | |||
| /* d'ou les coordonnees objets */ | |||
| transform_point(out, m, in); | |||
| if (out[3] == 0.0) | |||
| return GL_FALSE; | |||
| *objx = out[0] / out[3]; | |||
| *objy = out[1] / out[3]; | |||
| *objz = out[2] / out[3]; | |||
| *objw = out[3]; | |||
| return GL_TRUE; | |||
| } | |||
| #endif | |||
| @@ -1,131 +1,108 @@ | |||
| /* $Id: tess.h,v 1.16 1999/12/06 09:39:34 gareth Exp $ */ | |||
| /* $Id: tess.h,v 1.17 2000/07/11 14:11:04 brianp Exp $ */ | |||
| /* | |||
| * Mesa 3-D graphics library | |||
| * Version: 3.1 | |||
| * Version: 3.3 | |||
| * Copyright (C) 1995-2000 Brian Paul | |||
| * | |||
| * Copyright (C) 1999 Brian Paul All Rights Reserved. | |||
| * This library is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Library General Public | |||
| * License as published by the Free Software Foundation; either | |||
| * version 2 of the License, or (at your option) any later version. | |||
| * | |||
| * 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: | |||
| * This library is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
| * Library General Public License for more details. | |||
| * | |||
| * 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. | |||
| * You should have received a copy of the GNU Library General Public | |||
| * License along with this library; if not, write to the Free | |||
| * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| */ | |||
| /***************************************************************************** | |||
| * | |||
| * GLU 1.3 Polygon Tessellation by Gareth Hughes <garethh@bell-labs.com> | |||
| * | |||
| *****************************************************************************/ | |||
| #ifndef __GLU_TESS_H__ | |||
| #define __GLU_TESS_H__ | |||
| /* | |||
| * This file is part of the polygon tesselation code contributed by | |||
| * Bogdan Sikorski | |||
| */ | |||
| #include <stdarg.h> | |||
| #include <stdio.h> | |||
| #include "gluP.h" | |||
| #ifndef TESS_H | |||
| #define TESS_H | |||
| #include "tess_typedefs.h" | |||
| #include "tess_macros.h" | |||
| #include "tess_hash.h" | |||
| #include "tess_heap.h" | |||
| #if 0 | |||
| #include "tess_grid.h" | |||
| #endif | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| #include "gluP.h" | |||
| #define EPSILON 1e-06 /* epsilon for double precision compares */ | |||
| /***************************************************************************** | |||
| * The GLUtesselator structure: | |||
| *****************************************************************************/ | |||
| struct GLUtesselator | |||
| typedef enum | |||
| { | |||
| tess_callbacks_t callbacks; | |||
| GLenum winding_rule; | |||
| GLboolean boundary_only; | |||
| GLdouble tolerance; | |||
| GLenum orientation; | |||
| void *data; | |||
| GLint num_contours; | |||
| tess_contour_t *contours, *last_contour; | |||
| tess_contour_t *current_contour; | |||
| GLdouble mins[2], maxs[2]; | |||
| GLint num_vertices; | |||
| tess_vertex_t **sorted_vertices; | |||
| #if 0 | |||
| tess_grid_t *grid; /* Not currently used... */ | |||
| #endif | |||
| heap_t *ears; | |||
| GLboolean edge_flag; | |||
| GLuint label; | |||
| tess_plane_t plane; | |||
| GLenum error; | |||
| }; | |||
| OXY, | |||
| OYZ, | |||
| OXZ | |||
| } | |||
| projection_type; | |||
| typedef struct callbacks_str | |||
| { | |||
| void (GLCALLBACK * begin) (GLenum mode); | |||
| void (GLCALLBACK * edgeFlag) (GLboolean flag); | |||
| void (GLCALLBACK * vertex) (GLvoid * v); | |||
| void (GLCALLBACK * end) (void); | |||
| void (GLCALLBACK * error) (GLenum err); | |||
| } | |||
| tess_callbacks; | |||
| /***************************************************************************** | |||
| * Common tessellation functions: | |||
| *****************************************************************************/ | |||
| extern void tess_error_callback( GLUtesselator *, GLenum ); | |||
| typedef struct vertex_str | |||
| { | |||
| void *data; | |||
| GLdouble location[3]; | |||
| GLdouble x, y; | |||
| GLboolean edge_flag; | |||
| struct vertex_str *shadow_vertex; | |||
| struct vertex_str *next, *previous; | |||
| } | |||
| tess_vertex; | |||
| extern GLdouble twice_contour_area( tess_contour_t *contour ); | |||
| extern void reverse_contour( tess_contour_t *contour ); | |||
| extern void delete_contour( tess_contour_t **contour ); | |||
| typedef struct contour_str | |||
| { | |||
| GLenum type; | |||
| GLuint vertex_cnt; | |||
| GLdouble area; | |||
| GLenum orientation; | |||
| struct vertex_str *vertices, *last_vertex; | |||
| struct contour_str *next, *previous; | |||
| } | |||
| tess_contour; | |||
| extern void contour_dump( tess_contour_t *contour ); | |||
| typedef struct polygon_str | |||
| { | |||
| GLuint vertex_cnt; | |||
| GLdouble A, B, C, D; | |||
| GLdouble area; | |||
| GLenum orientation; | |||
| struct vertex_str *vertices, *last_vertex; | |||
| } | |||
| tess_polygon; | |||
| struct GLUtriangulatorObj | |||
| { | |||
| tess_contour *contours, *last_contour; | |||
| GLuint contour_cnt; | |||
| tess_callbacks callbacks; | |||
| tess_polygon *current_polygon; | |||
| GLenum error; | |||
| GLdouble A, B, C, D; | |||
| projection_type projection; | |||
| }; | |||
| /***************************************************************************** | |||
| * Debugging output: | |||
| *****************************************************************************/ | |||
| #ifdef DEBUG | |||
| extern int tess_dbg_level; | |||
| #define DBG_LEVEL_BASE 1 | |||
| #define DBG_LEVEL_VERBOSE 10 | |||
| #define DBG_LEVEL_ENTEREXIT 20 | |||
| extern void tess_call_user_error(GLUtriangulatorObj *, GLenum); | |||
| extern void tess_test_polygon(GLUtriangulatorObj *); | |||
| extern void tess_find_contour_hierarchies(GLUtriangulatorObj *); | |||
| extern void tess_handle_holes(GLUtriangulatorObj *); | |||
| extern void tess_tesselate(GLUtriangulatorObj *); | |||
| extern void tess_tesselate_with_edge_flag(GLUtriangulatorObj *); | |||
| #ifdef _WIN32 | |||
| #define DBG_STREAM stdout | |||
| #else | |||
| #define DBG_STREAM stderr | |||
| #endif | |||
| #ifdef __GNUC__ | |||
| #define MSG( level, format, args... ) \ | |||
| if ( level <= tess_dbg_level ) { \ | |||
| fprintf( DBG_STREAM, "%9.9s:%d:\t ", __FILE__, __LINE__ ); \ | |||
| fprintf( DBG_STREAM, format, ## args ); \ | |||
| fflush( DBG_STREAM ); \ | |||
| } | |||
| #else | |||
| #define MSG tess_msg | |||
| #endif /* __GNUC__ */ | |||
| #else | |||
| #define MSG tess_msg | |||
| #endif /* DEBUG */ | |||
| extern INLINE void tess_msg( GLint level, char *format, ... ); | |||
| extern INLINE void tess_info( char *file, GLint line ); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* __GLU_TESS_H__ */ | |||
| @@ -0,0 +1,407 @@ | |||
| /* $Id: tesselat.c,v 1.3 2000/07/11 14:11:04 brianp Exp $ */ | |||
| /* | |||
| * Mesa 3-D graphics library | |||
| * Version: 3.3 | |||
| * Copyright (C) 1995-2000 Brian Paul | |||
| * | |||
| * This library is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Library General Public | |||
| * License as published by the Free Software Foundation; either | |||
| * version 2 of the License, or (at your option) any later version. | |||
| * | |||
| * This library is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
| * Library General Public License for more details. | |||
| * | |||
| * You should have received a copy of the GNU Library General Public | |||
| * License along with this library; if not, write to the Free | |||
| * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| */ | |||
| /* | |||
| * This file is part of the polygon tesselation code contributed by | |||
| * Bogdan Sikorski | |||
| */ | |||
| #ifdef PC_HEADER | |||
| #include "all.h" | |||
| #else | |||
| #include <stdlib.h> | |||
| #include <math.h> | |||
| #include "tess.h" | |||
| #endif | |||
| static GLboolean edge_flag; | |||
| static void emit_triangle(GLUtriangulatorObj *, tess_vertex *, | |||
| tess_vertex *, tess_vertex *); | |||
| static void emit_triangle_with_edge_flag(GLUtriangulatorObj *, | |||
| tess_vertex *, GLboolean, | |||
| tess_vertex *, GLboolean, | |||
| tess_vertex *, GLboolean); | |||
| static GLdouble | |||
| twice_the_triangle_area(tess_vertex * va, tess_vertex * vb, tess_vertex * vc) | |||
| { | |||
| return (vb->x - va->x) * (vc->y - va->y) - (vb->y - va->y) * (vc->x - | |||
| va->x); | |||
| } | |||
| static GLboolean | |||
| left(GLdouble A, GLdouble B, GLdouble C, GLdouble x, GLdouble y) | |||
| { | |||
| if (A * x + B * y + C > -EPSILON) | |||
| return GL_TRUE; | |||
| else | |||
| return GL_FALSE; | |||
| } | |||
| static GLboolean | |||
| right(GLdouble A, GLdouble B, GLdouble C, GLdouble x, GLdouble y) | |||
| { | |||
| if (A * x + B * y + C < EPSILON) | |||
| return GL_TRUE; | |||
| else | |||
| return GL_FALSE; | |||
| } | |||
| static GLint | |||
| convex_ccw(tess_vertex * va, | |||
| tess_vertex * vb, tess_vertex * vc, GLUtriangulatorObj * tobj) | |||
| { | |||
| GLdouble d; | |||
| d = twice_the_triangle_area(va, vb, vc); | |||
| if (d > EPSILON) { | |||
| return 1; | |||
| } | |||
| else if (d < -EPSILON) { | |||
| return 0; | |||
| } | |||
| else { | |||
| return -1; | |||
| } | |||
| } | |||
| static GLint | |||
| convex_cw(tess_vertex * va, | |||
| tess_vertex * vb, tess_vertex * vc, GLUtriangulatorObj * tobj) | |||
| { | |||
| GLdouble d; | |||
| d = twice_the_triangle_area(va, vb, vc); | |||
| if (d < -EPSILON) { | |||
| return 1; | |||
| } | |||
| else if (d > EPSILON) { | |||
| return 0; | |||
| } | |||
| else { | |||
| return -1; | |||
| } | |||
| } | |||
| static GLboolean | |||
| diagonal_ccw(tess_vertex * va, | |||
| tess_vertex * vb, | |||
| GLUtriangulatorObj * tobj, tess_contour * contour) | |||
| { | |||
| tess_vertex *vc = va->next, *vertex, *shadow_vertex; | |||
| struct | |||
| { | |||
| GLdouble A, B, C; | |||
| } | |||
| ac, cb, ba; | |||
| GLdouble x, y; | |||
| GLint res = convex_ccw(va, vc, vb, tobj); | |||
| if (res == 0) | |||
| return GL_FALSE; | |||
| if (res == -1) | |||
| return GL_TRUE; | |||
| ba.A = vb->y - va->y; | |||
| ba.B = va->x - vb->x; | |||
| ba.C = -ba.A * va->x - ba.B * va->y; | |||
| ac.A = va->y - vc->y; | |||
| ac.B = vc->x - va->x; | |||
| ac.C = -ac.A * vc->x - ac.B * vc->y; | |||
| cb.A = vc->y - vb->y; | |||
| cb.B = vb->x - vc->x; | |||
| cb.C = -cb.A * vb->x - cb.B * vb->y; | |||
| for (vertex = vb->next; vertex != va; vertex = vertex->next) { | |||
| shadow_vertex = vertex->shadow_vertex; | |||
| if (shadow_vertex != NULL && | |||
| (shadow_vertex == va || shadow_vertex == vb || shadow_vertex == vc)) | |||
| continue; | |||
| x = vertex->x; | |||
| y = vertex->y; | |||
| if (left(ba.A, ba.B, ba.C, x, y) && | |||
| left(ac.A, ac.B, ac.C, x, y) && left(cb.A, cb.B, cb.C, x, y)) | |||
| return GL_FALSE; | |||
| } | |||
| return GL_TRUE; | |||
| } | |||
| static GLboolean | |||
| diagonal_cw(tess_vertex * va, | |||
| tess_vertex * vb, | |||
| GLUtriangulatorObj * tobj, tess_contour * contour) | |||
| { | |||
| tess_vertex *vc = va->next, *vertex, *shadow_vertex; | |||
| struct | |||
| { | |||
| GLdouble A, B, C; | |||
| } | |||
| ac, cb, ba; | |||
| GLdouble x, y; | |||
| GLint res = convex_cw(va, vc, vb, tobj); | |||
| if (res == 0) | |||
| return GL_FALSE; | |||
| if (res == -1) | |||
| return GL_TRUE; | |||
| ba.A = vb->y - va->y; | |||
| ba.B = va->x - vb->x; | |||
| ba.C = -ba.A * va->x - ba.B * va->y; | |||
| ac.A = va->y - vc->y; | |||
| ac.B = vc->x - va->x; | |||
| ac.C = -ac.A * vc->x - ac.B * vc->y; | |||
| cb.A = vc->y - vb->y; | |||
| cb.B = vb->x - vc->x; | |||
| cb.C = -cb.A * vb->x - cb.B * vb->y; | |||
| for (vertex = vb->next; vertex != va; vertex = vertex->next) { | |||
| shadow_vertex = vertex->shadow_vertex; | |||
| if (shadow_vertex != NULL && | |||
| (shadow_vertex == va || shadow_vertex == vb || shadow_vertex == vc)) | |||
| continue; | |||
| x = vertex->x; | |||
| y = vertex->y; | |||
| if (right(ba.A, ba.B, ba.C, x, y) && | |||
| right(ac.A, ac.B, ac.C, x, y) && right(cb.A, cb.B, cb.C, x, y)) | |||
| return GL_FALSE; | |||
| } | |||
| return GL_TRUE; | |||
| } | |||
| static void | |||
| clip_ear(GLUtriangulatorObj * tobj, tess_vertex * v, tess_contour * contour) | |||
| { | |||
| emit_triangle(tobj, v->previous, v, v->next); | |||
| /* the first in the list */ | |||
| if (contour->vertices == v) { | |||
| contour->vertices = v->next; | |||
| contour->last_vertex->next = v->next; | |||
| v->next->previous = contour->last_vertex; | |||
| } | |||
| else | |||
| /* the last ? */ | |||
| if (contour->last_vertex == v) { | |||
| contour->vertices->previous = v->previous; | |||
| v->previous->next = v->next; | |||
| contour->last_vertex = v->previous; | |||
| } | |||
| else { | |||
| v->next->previous = v->previous; | |||
| v->previous->next = v->next; | |||
| } | |||
| free(v); | |||
| --(contour->vertex_cnt); | |||
| } | |||
| static void | |||
| clip_ear_with_edge_flag(GLUtriangulatorObj * tobj, | |||
| tess_vertex * v, tess_contour * contour) | |||
| { | |||
| emit_triangle_with_edge_flag(tobj, v->previous, v->previous->edge_flag, | |||
| v, v->edge_flag, v->next, GL_FALSE); | |||
| v->previous->edge_flag = GL_FALSE; | |||
| /* the first in the list */ | |||
| if (contour->vertices == v) { | |||
| contour->vertices = v->next; | |||
| contour->last_vertex->next = v->next; | |||
| v->next->previous = contour->last_vertex; | |||
| } | |||
| else | |||
| /* the last ? */ | |||
| if (contour->last_vertex == v) { | |||
| contour->vertices->previous = v->previous; | |||
| v->previous->next = v->next; | |||
| contour->last_vertex = v->previous; | |||
| } | |||
| else { | |||
| v->next->previous = v->previous; | |||
| v->previous->next = v->next; | |||
| } | |||
| free(v); | |||
| --(contour->vertex_cnt); | |||
| } | |||
| static void | |||
| triangulate_ccw(GLUtriangulatorObj * tobj, tess_contour * contour) | |||
| { | |||
| tess_vertex *vertex; | |||
| GLuint vertex_cnt = contour->vertex_cnt; | |||
| while (vertex_cnt > 3) { | |||
| vertex = contour->vertices; | |||
| while (diagonal_ccw(vertex, vertex->next->next, tobj, contour) == | |||
| GL_FALSE && tobj->error == GLU_NO_ERROR) | |||
| vertex = vertex->next; | |||
| if (tobj->error != GLU_NO_ERROR) | |||
| return; | |||
| clip_ear(tobj, vertex->next, contour); | |||
| --vertex_cnt; | |||
| } | |||
| } | |||
| static void | |||
| triangulate_cw(GLUtriangulatorObj * tobj, tess_contour * contour) | |||
| { | |||
| tess_vertex *vertex; | |||
| GLuint vertex_cnt = contour->vertex_cnt; | |||
| while (vertex_cnt > 3) { | |||
| vertex = contour->vertices; | |||
| while (diagonal_cw(vertex, vertex->next->next, tobj, contour) == | |||
| GL_FALSE && tobj->error == GLU_NO_ERROR) | |||
| vertex = vertex->next; | |||
| if (tobj->error != GLU_NO_ERROR) | |||
| return; | |||
| clip_ear(tobj, vertex->next, contour); | |||
| --vertex_cnt; | |||
| } | |||
| } | |||
| static void | |||
| triangulate_ccw_with_edge_flag(GLUtriangulatorObj * tobj, | |||
| tess_contour * contour) | |||
| { | |||
| tess_vertex *vertex; | |||
| GLuint vertex_cnt = contour->vertex_cnt; | |||
| while (vertex_cnt > 3) { | |||
| vertex = contour->vertices; | |||
| while (diagonal_ccw(vertex, vertex->next->next, tobj, contour) == | |||
| GL_FALSE && tobj->error == GLU_NO_ERROR) | |||
| vertex = vertex->next; | |||
| if (tobj->error != GLU_NO_ERROR) | |||
| return; | |||
| clip_ear_with_edge_flag(tobj, vertex->next, contour); | |||
| --vertex_cnt; | |||
| } | |||
| } | |||
| static void | |||
| triangulate_cw_with_edge_flag(GLUtriangulatorObj * tobj, | |||
| tess_contour * contour) | |||
| { | |||
| tess_vertex *vertex; | |||
| GLuint vertex_cnt = contour->vertex_cnt; | |||
| while (vertex_cnt > 3) { | |||
| vertex = contour->vertices; | |||
| while (diagonal_cw(vertex, vertex->next->next, tobj, contour) == | |||
| GL_FALSE && tobj->error == GLU_NO_ERROR) | |||
| vertex = vertex->next; | |||
| if (tobj->error != GLU_NO_ERROR) | |||
| return; | |||
| clip_ear_with_edge_flag(tobj, vertex->next, contour); | |||
| --vertex_cnt; | |||
| } | |||
| } | |||
| void | |||
| tess_tesselate(GLUtriangulatorObj * tobj) | |||
| { | |||
| tess_contour *contour; | |||
| for (contour = tobj->contours; contour != NULL; contour = contour->next) { | |||
| if (contour->orientation == GLU_CCW) { | |||
| triangulate_ccw(tobj, contour); | |||
| } | |||
| else { | |||
| triangulate_cw(tobj, contour); | |||
| } | |||
| if (tobj->error != GLU_NO_ERROR) | |||
| return; | |||
| /* emit the last triangle */ | |||
| emit_triangle(tobj, contour->vertices, contour->vertices->next, | |||
| contour->vertices->next->next); | |||
| } | |||
| } | |||
| void | |||
| tess_tesselate_with_edge_flag(GLUtriangulatorObj * tobj) | |||
| { | |||
| tess_contour *contour; | |||
| edge_flag = GL_TRUE; | |||
| /* first callback with edgeFlag set to GL_TRUE */ | |||
| (tobj->callbacks.edgeFlag) (GL_TRUE); | |||
| for (contour = tobj->contours; contour != NULL; contour = contour->next) { | |||
| if (contour->orientation == GLU_CCW) | |||
| triangulate_ccw_with_edge_flag(tobj, contour); | |||
| else | |||
| triangulate_cw_with_edge_flag(tobj, contour); | |||
| if (tobj->error != GLU_NO_ERROR) | |||
| return; | |||
| /* emit the last triangle */ | |||
| emit_triangle_with_edge_flag(tobj, contour->vertices, | |||
| contour->vertices->edge_flag, | |||
| contour->vertices->next, | |||
| contour->vertices->next->edge_flag, | |||
| contour->vertices->next->next, | |||
| contour->vertices->next->next->edge_flag); | |||
| } | |||
| } | |||
| static void | |||
| emit_triangle(GLUtriangulatorObj * tobj, | |||
| tess_vertex * v1, tess_vertex * v2, tess_vertex * v3) | |||
| { | |||
| (tobj->callbacks.begin) (GL_TRIANGLES); | |||
| (tobj->callbacks.vertex) (v1->data); | |||
| (tobj->callbacks.vertex) (v2->data); | |||
| (tobj->callbacks.vertex) (v3->data); | |||
| (tobj->callbacks.end) (); | |||
| } | |||
| static void | |||
| emit_triangle_with_edge_flag(GLUtriangulatorObj * tobj, | |||
| tess_vertex * v1, | |||
| GLboolean edge_flag1, | |||
| tess_vertex * v2, | |||
| GLboolean edge_flag2, | |||
| tess_vertex * v3, GLboolean edge_flag3) | |||
| { | |||
| (tobj->callbacks.begin) (GL_TRIANGLES); | |||
| if (edge_flag1 != edge_flag) { | |||
| edge_flag = (edge_flag == GL_TRUE ? GL_FALSE : GL_TRUE); | |||
| (tobj->callbacks.edgeFlag) (edge_flag); | |||
| } | |||
| (tobj->callbacks.vertex) (v1->data); | |||
| if (edge_flag2 != edge_flag) { | |||
| edge_flag = (edge_flag == GL_TRUE ? GL_FALSE : GL_TRUE); | |||
| (tobj->callbacks.edgeFlag) (edge_flag); | |||
| } | |||
| (tobj->callbacks.vertex) (v2->data); | |||
| if (edge_flag3 != edge_flag) { | |||
| edge_flag = (edge_flag == GL_TRUE ? GL_FALSE : GL_TRUE); | |||
| (tobj->callbacks.edgeFlag) (edge_flag); | |||
| } | |||
| (tobj->callbacks.vertex) (v3->data); | |||
| (tobj->callbacks.end) (); | |||
| } | |||