From f88602394d7cc340cc850622308ce1cbbff332a5 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Tue, 11 Jul 2000 14:11:04 +0000 Subject: reverted to old tessellator (GLU 1.1) --- src/glu/mesa/Makefile.BeOS | 7 +- src/glu/mesa/Makefile.BeOS-R4 | 40 +- src/glu/mesa/Makefile.X11 | 11 +- src/glu/mesa/Makefile.m32 | 3 +- src/glu/mesa/all.h | 24 +- src/glu/mesa/glu.c | 294 ++--- src/glu/mesa/gluP.h | 51 +- src/glu/mesa/mipmap.c | 838 ++++++++------- src/glu/mesa/nurbs.c | 986 ++++++++--------- src/glu/mesa/nurbs.h | 374 +++---- src/glu/mesa/nurbscrv.c | 789 +++++++------- src/glu/mesa/nurbssrf.c | 2388 ++++++++++++++++++++--------------------- src/glu/mesa/nurbsutl.c | 2215 ++++++++++++++++++-------------------- src/glu/mesa/polytest.c | 938 ++++++++++++++++ src/glu/mesa/project.c | 525 +++++---- src/glu/mesa/quadric.c | 716 ++++++------ src/glu/mesa/tess.c | 1235 +++++---------------- src/glu/mesa/tess.h | 189 ++-- src/glu/mesa/tesselat.c | 407 +++++++ 19 files changed, 6153 insertions(+), 5877 deletions(-) create mode 100644 src/glu/mesa/polytest.c create mode 100644 src/glu/mesa/tesselat.c (limited to 'src') diff --git a/src/glu/mesa/Makefile.BeOS b/src/glu/mesa/Makefile.BeOS index e8851dea444..71624e392cb 100644 --- a/src/glu/mesa/Makefile.BeOS +++ b/src/glu/mesa/Makefile.BeOS @@ -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) diff --git a/src/glu/mesa/Makefile.BeOS-R4 b/src/glu/mesa/Makefile.BeOS-R4 index ebe3a689d38..dcc58aaf540 100644 --- a/src/glu/mesa/Makefile.BeOS-R4 +++ b/src/glu/mesa/Makefile.BeOS-R4 @@ -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) diff --git a/src/glu/mesa/Makefile.X11 b/src/glu/mesa/Makefile.X11 index 4373c8f2b4d..e8a4e18c428 100644 --- a/src/glu/mesa/Makefile.X11 +++ b/src/glu/mesa/Makefile.X11 @@ -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) diff --git a/src/glu/mesa/Makefile.m32 b/src/glu/mesa/Makefile.m32 index 6f1d8219a25..3e217ef5d52 100644 --- a/src/glu/mesa/Makefile.m32 +++ b/src/glu/mesa/Makefile.m32 @@ -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) diff --git a/src/glu/mesa/all.h b/src/glu/mesa/all.h index 3712ca884ab..427fc3898d5 100644 --- a/src/glu/mesa/all.h +++ b/src/glu/mesa/all.h @@ -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 */ diff --git a/src/glu/mesa/glu.c b/src/glu/mesa/glu.c index 8ccacf5f7f1..11d1cd8675d 100644 --- a/src/glu/mesa/glu.c +++ b/src/glu/mesa/glu.c @@ -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 diff --git a/src/glu/mesa/gluP.h b/src/glu/mesa/gluP.h index 89bfa9c92cd..7d0ec3c84d7 100644 --- a/src/glu/mesa/gluP.h +++ b/src/glu/mesa/gluP.h @@ -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 +#include #include - #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 diff --git a/src/glu/mesa/mipmap.c b/src/glu/mesa/mipmap.c index f1c6d9ce761..e5efc6240f5 100644 --- a/src/glu/mesa/mipmap.c +++ b/src/glu/mesa/mipmap.c @@ -1,4 +1,4 @@ -/* $Id: mipmap.c,v 1.6 2000/06/05 16:27:41 brianp Exp $ */ +/* $Id: mipmap.c,v 1.7 2000/07/11 14:11:04 brianp Exp $ */ /* * Mesa 3-D graphics library @@ -47,18 +47,21 @@ /* To work around optimizer bug in MSVC4.1 */ #if defined(__WIN32__) && !defined(OPENSTEP) -void dummy(GLuint j, GLuint k){ +void +dummy(GLuint j, GLuint k) +{ } #else #define dummy(J, K) #endif -GLint GLAPIENTRY gluScaleImage( GLenum format, - GLsizei widthin, GLsizei heightin, - GLenum typein, const void *datain, - GLsizei widthout, GLsizei heightout, - GLenum typeout, void *dataout ) +GLint GLAPIENTRY +gluScaleImage(GLenum format, + GLsizei widthin, GLsizei heightin, + GLenum typein, const void *datain, + GLsizei widthout, GLsizei heightout, + GLenum typeout, void *dataout) { GLint components, i, j, k; GLfloat *tempin, *tempout; @@ -71,84 +74,112 @@ GLint GLAPIENTRY gluScaleImage( GLenum format, /* Determine number of components per pixel */ switch (format) { - case GL_COLOR_INDEX: - case GL_STENCIL_INDEX: - case GL_DEPTH_COMPONENT: - case GL_RED: - case GL_GREEN: - case GL_BLUE: - case GL_ALPHA: - case GL_LUMINANCE: - components = 1; - break; - case GL_LUMINANCE_ALPHA: - components = 2; - break; - case GL_RGB: - case GL_BGR: - components = 3; - break; - case GL_RGBA: - case GL_BGRA: + case GL_COLOR_INDEX: + case GL_STENCIL_INDEX: + case GL_DEPTH_COMPONENT: + case GL_RED: + case GL_GREEN: + case GL_BLUE: + case GL_ALPHA: + case GL_LUMINANCE: + components = 1; + break; + case GL_LUMINANCE_ALPHA: + components = 2; + break; + case GL_RGB: + case GL_BGR: + components = 3; + break; + case GL_RGBA: + case GL_BGRA: #ifdef GL_EXT_abgr - case GL_ABGR_EXT: + case GL_ABGR_EXT: #endif - components = 4; - break; - default: - return GLU_INVALID_ENUM; + components = 4; + break; + default: + return GLU_INVALID_ENUM; } /* Determine bytes per input datum */ switch (typein) { - case GL_UNSIGNED_BYTE: sizein = sizeof(GLubyte); break; - case GL_BYTE: sizein = sizeof(GLbyte); break; - case GL_UNSIGNED_SHORT: sizein = sizeof(GLushort); break; - case GL_SHORT: sizein = sizeof(GLshort); break; - case GL_UNSIGNED_INT: sizein = sizeof(GLuint); break; - case GL_INT: sizein = sizeof(GLint); break; - case GL_FLOAT: sizein = sizeof(GLfloat); break; - case GL_BITMAP: - /* not implemented yet */ - default: - return GL_INVALID_ENUM; + case GL_UNSIGNED_BYTE: + sizein = sizeof(GLubyte); + break; + case GL_BYTE: + sizein = sizeof(GLbyte); + break; + case GL_UNSIGNED_SHORT: + sizein = sizeof(GLushort); + break; + case GL_SHORT: + sizein = sizeof(GLshort); + break; + case GL_UNSIGNED_INT: + sizein = sizeof(GLuint); + break; + case GL_INT: + sizein = sizeof(GLint); + break; + case GL_FLOAT: + sizein = sizeof(GLfloat); + break; + case GL_BITMAP: + /* not implemented yet */ + default: + return GL_INVALID_ENUM; } /* Determine bytes per output datum */ switch (typeout) { - case GL_UNSIGNED_BYTE: sizeout = sizeof(GLubyte); break; - case GL_BYTE: sizeout = sizeof(GLbyte); break; - case GL_UNSIGNED_SHORT: sizeout = sizeof(GLushort); break; - case GL_SHORT: sizeout = sizeof(GLshort); break; - case GL_UNSIGNED_INT: sizeout = sizeof(GLuint); break; - case GL_INT: sizeout = sizeof(GLint); break; - case GL_FLOAT: sizeout = sizeof(GLfloat); break; - case GL_BITMAP: - /* not implemented yet */ - default: - return GL_INVALID_ENUM; + case GL_UNSIGNED_BYTE: + sizeout = sizeof(GLubyte); + break; + case GL_BYTE: + sizeout = sizeof(GLbyte); + break; + case GL_UNSIGNED_SHORT: + sizeout = sizeof(GLushort); + break; + case GL_SHORT: + sizeout = sizeof(GLshort); + break; + case GL_UNSIGNED_INT: + sizeout = sizeof(GLuint); + break; + case GL_INT: + sizeout = sizeof(GLint); + break; + case GL_FLOAT: + sizeout = sizeof(GLfloat); + break; + case GL_BITMAP: + /* not implemented yet */ + default: + return GL_INVALID_ENUM; } /* Get glPixelStore state */ - glGetIntegerv( GL_UNPACK_ROW_LENGTH, &unpackrowlength ); - glGetIntegerv( GL_UNPACK_ALIGNMENT, &unpackalignment ); - glGetIntegerv( GL_UNPACK_SKIP_ROWS, &unpackskiprows ); - glGetIntegerv( GL_UNPACK_SKIP_PIXELS, &unpackskippixels ); - glGetIntegerv( GL_PACK_ROW_LENGTH, &packrowlength ); - glGetIntegerv( GL_PACK_ALIGNMENT, &packalignment ); - glGetIntegerv( GL_PACK_SKIP_ROWS, &packskiprows ); - glGetIntegerv( GL_PACK_SKIP_PIXELS, &packskippixels ); + glGetIntegerv(GL_UNPACK_ROW_LENGTH, &unpackrowlength); + glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpackalignment); + glGetIntegerv(GL_UNPACK_SKIP_ROWS, &unpackskiprows); + glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &unpackskippixels); + glGetIntegerv(GL_PACK_ROW_LENGTH, &packrowlength); + glGetIntegerv(GL_PACK_ALIGNMENT, &packalignment); + glGetIntegerv(GL_PACK_SKIP_ROWS, &packskiprows); + glGetIntegerv(GL_PACK_SKIP_PIXELS, &packskippixels); /* Allocate storage for intermediate images */ - tempin = (GLfloat *) malloc( widthin * heightin - * components * sizeof(GLfloat) ); + tempin = (GLfloat *) malloc(widthin * heightin + * components * sizeof(GLfloat)); if (!tempin) { return GLU_OUT_OF_MEMORY; } - tempout = (GLfloat *) malloc( widthout * heightout - * components * sizeof(GLfloat) ); + tempout = (GLfloat *) malloc(widthout * heightout + * components * sizeof(GLfloat)); if (!tempout) { - free( tempin ); + free(tempin); return GLU_OUT_OF_MEMORY; } @@ -157,7 +188,7 @@ GLint GLAPIENTRY gluScaleImage( GLenum format, * Unpack the pixel data and convert to floating point */ - if (unpackrowlength>0) { + if (unpackrowlength > 0) { rowlen = unpackrowlength; } else { @@ -167,104 +198,97 @@ GLint GLAPIENTRY gluScaleImage( GLenum format, rowstride = components * rowlen; } else { - rowstride = unpackalignment/sizein - * CEILING( components * rowlen * sizein, unpackalignment ); + rowstride = unpackalignment / sizein + * CEILING(components * rowlen * sizein, unpackalignment); } switch (typein) { - case GL_UNSIGNED_BYTE: - k = 0; - for (i=0;i 1) - sx = (GLfloat) (widthin-1) / (GLfloat) (widthout-1); + sx = (GLfloat) (widthin - 1) / (GLfloat) (widthout - 1); else - sx = (GLfloat) (widthin-1); + sx = (GLfloat) (widthin - 1); if (heightout > 1) - sy = (GLfloat) (heightin-1) / (GLfloat) (heightout-1); + sy = (GLfloat) (heightin - 1) / (GLfloat) (heightout - 1); else - sy = (GLfloat) (heightin-1); + sy = (GLfloat) (heightin - 1); /*#define POINT_SAMPLE*/ #ifdef POINT_SAMPLE - for (i=0;i= heightin) i1 = heightin-1; + if (i1 >= heightin) + i1 = heightin - 1; /* i1 = (i+1) * sy - EPSILON;*/ - alpha = i*sy - i0; - for (j=0;j= widthin) j1 = widthin-1; + if (j1 >= widthin) + j1 = widthin - 1; /* j1 = (j+1) * sx - EPSILON; */ - beta = j*sx - j0; + beta = j * sx - j0; /* compute weighted average of pixels in rect (i0,j0)-(i1,j1) */ src00 = tempin + (i0 * widthin + j0) * components; @@ -326,10 +352,10 @@ GLint GLAPIENTRY gluScaleImage( GLenum format, dst = tempout + (i * widthout + j) * components; - for (k=0;k= heightin) i1 = heightin-1; + if (i1 >= heightin) + i1 = heightin - 1; /* i1 = (i+1) * sy - EPSILON; */ - for (j=0;j= widthin) j1 = widthin-1; + if (j1 >= widthin) + j1 = widthin - 1; /* j1 = (j+1) * sx - EPSILON; */ dst = tempout + (i * widthout + j) * components; /* compute average of pixels in the rectangle (i0,j0)-(i1,j1) */ - for (k=0;k0) { + if (packrowlength > 0) { rowlen = packrowlength; } else { @@ -385,110 +413,103 @@ GLint GLAPIENTRY gluScaleImage( GLenum format, rowstride = components * rowlen; } else { - rowstride = packalignment/sizeout - * CEILING( components * rowlen * sizeout, packalignment ); + rowstride = packalignment / sizeout + * CEILING(components * rowlen * sizeout, packalignment); } switch (typeout) { - case GL_UNSIGNED_BYTE: - k = 0; - for (i=0;i>=1; k++) ; + if (n <= 0) + return 0; + for (k = 0; n >>= 1; k++); return k; } @@ -512,19 +535,19 @@ static GLint ilog2( GLint n ) /* * Find the value nearest to n which is also a power of two. */ -static GLint round2( GLint n ) +static GLint +round2(GLint n) { GLint m; - for (m=1; m=n */ - if (m-n <= n-m/2) { + if (m - n <= n - m / 2) { return m; } else { - return m/2; + return m / 2; } } @@ -533,48 +556,66 @@ static GLint round2( GLint n ) * Given an pixel format and datatype, return the number of bytes to * store one pixel. */ -static GLint bytes_per_pixel( GLenum format, GLenum type ) +static GLint +bytes_per_pixel(GLenum format, GLenum type) { GLint n, m; switch (format) { - case GL_COLOR_INDEX: - case GL_STENCIL_INDEX: - case GL_DEPTH_COMPONENT: - case GL_RED: - case GL_GREEN: - case GL_BLUE: - case GL_ALPHA: - case GL_LUMINANCE: - n = 1; - break; - case GL_LUMINANCE_ALPHA: - n = 2; - break; - case GL_RGB: - n = 3; - break; - case GL_RGBA: - case GL_BGRA: + case GL_COLOR_INDEX: + case GL_STENCIL_INDEX: + case GL_DEPTH_COMPONENT: + case GL_RED: + case GL_GREEN: + case GL_BLUE: + case GL_ALPHA: + case GL_LUMINANCE: + n = 1; + break; + case GL_LUMINANCE_ALPHA: + n = 2; + break; + case GL_RGB: + n = 3; + break; + case GL_RGBA: + case GL_BGRA: #ifdef GL_EXT_abgr - case GL_ABGR_EXT: + case GL_ABGR_EXT: #endif - n = 4; - break; - default: - n = 0; + n = 4; + break; + default: + n = 0; } switch (type) { - case GL_UNSIGNED_BYTE: m = sizeof(GLubyte); break; - case GL_BYTE: m = sizeof(GLbyte); break; - case GL_BITMAP: m = 1; break; - case GL_UNSIGNED_SHORT: m = sizeof(GLushort); break; - case GL_SHORT: m = sizeof(GLshort); break; - case GL_UNSIGNED_INT: m = sizeof(GLuint); break; - case GL_INT: m = sizeof(GLint); break; - case GL_FLOAT: m = sizeof(GLfloat); break; - default: m = 0; + case GL_UNSIGNED_BYTE: + m = sizeof(GLubyte); + break; + case GL_BYTE: + m = sizeof(GLbyte); + break; + case GL_BITMAP: + m = 1; + break; + case GL_UNSIGNED_SHORT: + m = sizeof(GLushort); + break; + case GL_SHORT: + m = sizeof(GLshort); + break; + case GL_UNSIGNED_INT: + m = sizeof(GLuint); + break; + case GL_INT: + m = sizeof(GLint); + break; + case GL_FLOAT: + m = sizeof(GLfloat); + break; + default: + m = 0; } return n * m; @@ -585,9 +626,9 @@ static GLint bytes_per_pixel( GLenum format, GLenum type ) /* * WARNING: This function isn't finished and has never been tested!!!! */ -GLint GLAPIENTRY gluBuild1DMipmaps( GLenum target, GLint components, - GLsizei width, GLenum format, - GLenum type, const void *data ) +GLint GLAPIENTRY +gluBuild1DMipmaps(GLenum target, GLint components, + GLsizei width, GLenum format, GLenum type, const void *data) { GLubyte *texture; GLint levels, max_levels; @@ -597,18 +638,18 @@ GLint GLAPIENTRY gluBuild1DMipmaps( GLenum target, GLint components, if (width < 1) return GLU_INVALID_VALUE; - glGetIntegerv( GL_MAX_TEXTURE_SIZE, &max_width ); - max_levels = ilog2( max_width ) + 1; + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_width); + max_levels = ilog2(max_width) + 1; /* Compute how many mipmap images to make */ - levels = ilog2( width ) + 1; - if (levels>max_levels) { + levels = ilog2(width) + 1; + if (levels > max_levels) { levels = max_levels; } - new_width = 1 << (levels-1); + new_width = 1 << (levels - 1); - texture = (GLubyte *) malloc( new_width * components ); + texture = (GLubyte *) malloc(new_width * components); if (!texture) { return GLU_OUT_OF_MEMORY; } @@ -616,50 +657,51 @@ GLint GLAPIENTRY gluBuild1DMipmaps( GLenum target, GLint components, if (width != new_width) { /* initial rescaling */ switch (type) { - case GL_UNSIGNED_BYTE: - { - GLubyte *ub_data = (GLubyte *) data; - for (i=0;imaxsize) { + w = round2(width); + if (w > maxsize) { w = maxsize; } - h = round2( height ); - if (h>maxsize) { + h = round2(height); + if (h > maxsize) { h = maxsize; } - bpp = bytes_per_pixel( format, type ); - if (bpp==0) { + bpp = bytes_per_pixel(format, type); + if (bpp == 0) { /* probably a bad format or type enum */ return GLU_INVALID_ENUM; } /* Get current glPixelStore values */ - glGetIntegerv( GL_UNPACK_ROW_LENGTH, &unpackrowlength ); - glGetIntegerv( GL_UNPACK_ALIGNMENT, &unpackalignment ); - glGetIntegerv( GL_UNPACK_SKIP_ROWS, &unpackskiprows ); - glGetIntegerv( GL_UNPACK_SKIP_PIXELS, &unpackskippixels ); - glGetIntegerv( GL_PACK_ROW_LENGTH, &packrowlength ); - glGetIntegerv( GL_PACK_ALIGNMENT, &packalignment ); - glGetIntegerv( GL_PACK_SKIP_ROWS, &packskiprows ); - glGetIntegerv( GL_PACK_SKIP_PIXELS, &packskippixels ); + glGetIntegerv(GL_UNPACK_ROW_LENGTH, &unpackrowlength); + glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpackalignment); + glGetIntegerv(GL_UNPACK_SKIP_ROWS, &unpackskiprows); + glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &unpackskippixels); + glGetIntegerv(GL_PACK_ROW_LENGTH, &packrowlength); + glGetIntegerv(GL_PACK_ALIGNMENT, &packalignment); + glGetIntegerv(GL_PACK_SKIP_ROWS, &packskiprows); + glGetIntegerv(GL_PACK_SKIP_PIXELS, &packskippixels); /* set pixel packing */ - glPixelStorei( GL_PACK_ROW_LENGTH, 0 ); - glPixelStorei( GL_PACK_ALIGNMENT, 1 ); - glPixelStorei( GL_PACK_SKIP_ROWS, 0 ); - glPixelStorei( GL_PACK_SKIP_PIXELS, 0 ); + glPixelStorei(GL_PACK_ROW_LENGTH, 0); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glPixelStorei(GL_PACK_SKIP_ROWS, 0); + glPixelStorei(GL_PACK_SKIP_PIXELS, 0); done = GL_FALSE; - if (w!=width || h!=height) { + if (w != width || h != height) { /* must rescale image to get "top" mipmap texture image */ - image = malloc( (w+4) * h * bpp ); + image = malloc((w + 4) * h * bpp); if (!image) { return GLU_OUT_OF_MEMORY; } - error = gluScaleImage( format, width, height, type, data, - w, h, type, image ); + error = gluScaleImage(format, width, height, type, data, + w, h, type, image); if (error) { - retval = error; - done = GL_TRUE; + retval = error; + done = GL_TRUE; } } else { @@ -728,33 +770,34 @@ GLint GLAPIENTRY gluBuild2DMipmaps( GLenum target, GLint components, level = 0; while (!done) { if (image != data) { - /* set pixel unpacking */ - glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 ); - glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); - glPixelStorei( GL_UNPACK_SKIP_ROWS, 0 ); - glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0 ); + /* set pixel unpacking */ + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); } - glTexImage2D( target, level, components, w, h, 0, format, type, image ); + glTexImage2D(target, level, components, w, h, 0, format, type, image); - if (w==1 && h==1) break; + if (w == 1 && h == 1) + break; - neww = (w<2) ? 1 : w/2; - newh = (h<2) ? 1 : h/2; - newimage = malloc( (neww+4) * newh * bpp ); + neww = (w < 2) ? 1 : w / 2; + newh = (h < 2) ? 1 : h / 2; + newimage = malloc((neww + 4) * newh * bpp); if (!newimage) { return GLU_OUT_OF_MEMORY; } - error = gluScaleImage( format, w, h, type, image, - neww, newh, type, newimage ); + error = gluScaleImage(format, w, h, type, image, + neww, newh, type, newimage); if (error) { - retval = error; - done = GL_TRUE; + retval = error; + done = GL_TRUE; } - if (image!=data) { - free( image ); + if (image != data) { + free(image); } image = newimage; @@ -763,20 +806,19 @@ GLint GLAPIENTRY gluBuild2DMipmaps( GLenum target, GLint components, level++; } - if (image!=data) { - free( image ); + if (image != data) { + free(image); } /* Restore original glPixelStore state */ - glPixelStorei( GL_UNPACK_ROW_LENGTH, unpackrowlength ); - glPixelStorei( GL_UNPACK_ALIGNMENT, unpackalignment ); - glPixelStorei( GL_UNPACK_SKIP_ROWS, unpackskiprows ); - glPixelStorei( GL_UNPACK_SKIP_PIXELS, unpackskippixels ); - glPixelStorei( GL_PACK_ROW_LENGTH, packrowlength ); - glPixelStorei( GL_PACK_ALIGNMENT, packalignment ); - glPixelStorei( GL_PACK_SKIP_ROWS, packskiprows ); - glPixelStorei( GL_PACK_SKIP_PIXELS, packskippixels ); + glPixelStorei(GL_UNPACK_ROW_LENGTH, unpackrowlength); + glPixelStorei(GL_UNPACK_ALIGNMENT, unpackalignment); + glPixelStorei(GL_UNPACK_SKIP_ROWS, unpackskiprows); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, unpackskippixels); + glPixelStorei(GL_PACK_ROW_LENGTH, packrowlength); + glPixelStorei(GL_PACK_ALIGNMENT, packalignment); + glPixelStorei(GL_PACK_SKIP_ROWS, packskiprows); + glPixelStorei(GL_PACK_SKIP_PIXELS, packskippixels); return retval; } - diff --git a/src/glu/mesa/nurbs.c b/src/glu/mesa/nurbs.c index fdf0991651e..c93dc3cae68 100644 --- a/src/glu/mesa/nurbs.c +++ b/src/glu/mesa/nurbs.c @@ -1,4 +1,4 @@ -/* $Id: nurbs.c,v 1.3 2000/02/10 17:45:52 brianp Exp $ */ +/* $Id: nurbs.c,v 1.4 2000/07/11 14:11:04 brianp Exp $ */ /* * Mesa 3-D graphics library @@ -26,6 +26,7 @@ * See README2 for more info. */ + #ifdef PC_HEADER #include "all.h" #else @@ -37,414 +38,398 @@ void -call_user_error( GLUnurbsObj *nobj, GLenum error ) +call_user_error(GLUnurbsObj * nobj, GLenum error) { - nobj->error=error; - if(nobj->error_callback != NULL) { - (*(nobj->error_callback))(error); - } - else { - printf("NURBS error %d %s\n", error, (char *) gluErrorString(error) ); - } + nobj->error = error; + if (nobj->error_callback != NULL) { + (*(nobj->error_callback)) (error); + } + else { + printf("NURBS error %d %s\n", error, (char *) gluErrorString(error)); + } } -GLUnurbsObj * GLAPIENTRY gluNewNurbsRenderer( void ) +GLUnurbsObj *GLAPIENTRY +gluNewNurbsRenderer(void) { GLUnurbsObj *n; GLfloat tmp_viewport[4]; - GLint i,j; + GLint i, j; - n = (GLUnurbsObj *) malloc( sizeof(GLUnurbsObj) ); + n = (GLUnurbsObj *) malloc(sizeof(GLUnurbsObj)); if (n) { /* init */ - n->culling=GL_FALSE; - n->nurbs_type=GLU_NURBS_NONE; - n->error=GLU_NO_ERROR; - n->error_callback=NULL; - n->auto_load_matrix=GL_TRUE; - n->sampling_tolerance=50.0; - n->parametric_tolerance=0.5; + n->culling = GL_FALSE; + n->nurbs_type = GLU_NURBS_NONE; + n->error = GLU_NO_ERROR; + n->error_callback = NULL; + n->auto_load_matrix = GL_TRUE; + n->sampling_tolerance = 50.0; + n->parametric_tolerance = 0.5; n->u_step = n->v_step = 100; n->sampling_method = GLU_PATH_LENGTH; - n->display_mode=GLU_FILL; + n->display_mode = GLU_FILL; /* in case the user doesn't supply the sampling matrices */ /* set projection and modelview to identity */ - for(i=0;i<4;i++) - for(j=0;j<4;j++) - if(i==j) - { - n->sampling_matrices.model[i*4+j]=1.0; - n->sampling_matrices.proj[i*4+j]=1.0; - } - else - { - n->sampling_matrices.model[i*4+j]=0.0; - n->sampling_matrices.proj[i*4+j]=0.0; - } + for (i = 0; i < 4; i++) + for (j = 0; j < 4; j++) + if (i == j) { + n->sampling_matrices.model[i * 4 + j] = 1.0; + n->sampling_matrices.proj[i * 4 + j] = 1.0; + } + else { + n->sampling_matrices.model[i * 4 + j] = 0.0; + n->sampling_matrices.proj[i * 4 + j] = 0.0; + } /* and set the viewport sampling matrix to current ciewport */ - glGetFloatv(GL_VIEWPORT,tmp_viewport); - for(i=0;i<4;i++) - n->sampling_matrices.viewport[i]=tmp_viewport[i]; - n->trim=NULL; + glGetFloatv(GL_VIEWPORT, tmp_viewport); + for (i = 0; i < 4; i++) + n->sampling_matrices.viewport[i] = tmp_viewport[i]; + n->trim = NULL; } return n; } -void GLAPIENTRY gluDeleteNurbsRenderer( GLUnurbsObj *nobj ) +void GLAPIENTRY +gluDeleteNurbsRenderer(GLUnurbsObj * nobj) { if (nobj) { - free( nobj ); + free(nobj); } } -void GLAPIENTRY gluLoadSamplingMatrices( GLUnurbsObj *nobj, - const GLfloat modelMatrix[16], - const GLfloat projMatrix[16], - const GLint viewport[4] ) +void GLAPIENTRY +gluLoadSamplingMatrices(GLUnurbsObj * nobj, + const GLfloat modelMatrix[16], + const GLfloat projMatrix[16], const GLint viewport[4]) { - GLint i; - - for(i=0;i<16;i++) - { - nobj->sampling_matrices.model[i]=modelMatrix[i]; - nobj->sampling_matrices.proj[i]=projMatrix[i]; - } - for(i=0;i<4;i++) - nobj->sampling_matrices.viewport[i]=viewport[i]; + GLint i; + + for (i = 0; i < 16; i++) { + nobj->sampling_matrices.model[i] = modelMatrix[i]; + nobj->sampling_matrices.proj[i] = projMatrix[i]; + } + for (i = 0; i < 4; i++) + nobj->sampling_matrices.viewport[i] = viewport[i]; } -void GLAPIENTRY gluNurbsProperty( GLUnurbsObj *nobj, GLenum property, GLfloat value ) +void GLAPIENTRY +gluNurbsProperty(GLUnurbsObj * nobj, GLenum property, GLfloat value) { GLenum val; switch (property) { - case GLU_SAMPLING_TOLERANCE: - if(value <= 0.0) - { - call_user_error(nobj,GLU_INVALID_VALUE); - return; - } - nobj->sampling_tolerance=value; - break; - case GLU_PARAMETRIC_TOLERANCE: - if(value <= 0.0) - { - call_user_error(nobj,GLU_INVALID_VALUE); - return; - } - nobj->parametric_tolerance=value; - break; - case GLU_U_STEP: - if(value <= 0.0) - { - call_user_error(nobj,GLU_INVALID_VALUE); - return; - } - nobj->u_step=(GLint)value; - break; - case GLU_V_STEP: - if(value <= 0.0) - { - call_user_error(nobj,GLU_INVALID_VALUE); - return; - } - nobj->v_step=(GLint)value; - break; - case GLU_SAMPLING_METHOD: - val = (GLenum)value; - if(val!=GLU_PATH_LENGTH && val!=GLU_PARAMETRIC_ERROR && val!=GLU_DOMAIN_DISTANCE) - { - call_user_error(nobj,GLU_INVALID_ENUM); - return; - } - nobj->sampling_method=val; - break; - case GLU_DISPLAY_MODE: - val=(GLenum)value; - if(val!=GLU_FILL && val!=GLU_OUTLINE_POLYGON && val!=GLU_OUTLINE_PATCH) - { - call_user_error(nobj,GLU_INVALID_ENUM); - return; - } - if(nobj->nurbs_type==GLU_NURBS_CURVE) - { - call_user_error(nobj,GLU_NURBS_ERROR26); - return; - } - nobj->display_mode=val; -if(val==GLU_OUTLINE_PATCH) - fprintf(stderr,"NURBS, for the moment, can display only in POLYGON mode\n"); - break; - case GLU_CULLING: - val=(GLenum)value; - if(val!=GL_TRUE && val!=GL_FALSE) - { - call_user_error(nobj,GLU_INVALID_ENUM); - return; - } - nobj->culling = (GLboolean) value; - break; - case GLU_AUTO_LOAD_MATRIX: - val=(GLenum)value; - if(val!=GL_TRUE && val!=GL_FALSE) - { - call_user_error(nobj,GLU_INVALID_ENUM); - return; - } - nobj->auto_load_matrix = (GLboolean) value; - break; - default: - call_user_error(nobj,GLU_NURBS_ERROR26); + case GLU_SAMPLING_TOLERANCE: + if (value <= 0.0) { + call_user_error(nobj, GLU_INVALID_VALUE); + return; + } + nobj->sampling_tolerance = value; + break; + case GLU_PARAMETRIC_TOLERANCE: + if (value <= 0.0) { + call_user_error(nobj, GLU_INVALID_VALUE); + return; + } + nobj->parametric_tolerance = value; + break; + case GLU_U_STEP: + if (value <= 0.0) { + call_user_error(nobj, GLU_INVALID_VALUE); + return; + } + nobj->u_step = (GLint) value; + break; + case GLU_V_STEP: + if (value <= 0.0) { + call_user_error(nobj, GLU_INVALID_VALUE); + return; + } + nobj->v_step = (GLint) value; + break; + case GLU_SAMPLING_METHOD: + val = (GLenum) value; + if (val != GLU_PATH_LENGTH && val != GLU_PARAMETRIC_ERROR + && val != GLU_DOMAIN_DISTANCE) { + call_user_error(nobj, GLU_INVALID_ENUM); + return; + } + nobj->sampling_method = val; + break; + case GLU_DISPLAY_MODE: + val = (GLenum) value; + if (val != GLU_FILL && val != GLU_OUTLINE_POLYGON + && val != GLU_OUTLINE_PATCH) { + call_user_error(nobj, GLU_INVALID_ENUM); + return; + } + if (nobj->nurbs_type == GLU_NURBS_CURVE) { + call_user_error(nobj, GLU_NURBS_ERROR26); + return; + } + nobj->display_mode = val; + if (val == GLU_OUTLINE_PATCH) + fprintf(stderr, + "NURBS, for the moment, can display only in POLYGON mode\n"); + break; + case GLU_CULLING: + val = (GLenum) value; + if (val != GL_TRUE && val != GL_FALSE) { + call_user_error(nobj, GLU_INVALID_ENUM); + return; + } + nobj->culling = (GLboolean) value; + break; + case GLU_AUTO_LOAD_MATRIX: + val = (GLenum) value; + if (val != GL_TRUE && val != GL_FALSE) { + call_user_error(nobj, GLU_INVALID_ENUM); + return; + } + nobj->auto_load_matrix = (GLboolean) value; + break; + default: + call_user_error(nobj, GLU_NURBS_ERROR26); } } -void GLAPIENTRY gluGetNurbsProperty( GLUnurbsObj *nobj, GLenum property, GLfloat *value ) +void GLAPIENTRY +gluGetNurbsProperty(GLUnurbsObj * nobj, GLenum property, GLfloat * value) { switch (property) { - case GLU_SAMPLING_TOLERANCE: - *value = nobj->sampling_tolerance; - break; - case GLU_DISPLAY_MODE: - *value = (GLfloat) (GLint) nobj->display_mode; - break; - case GLU_CULLING: - *value = nobj->culling ? 1.0 : 0.0; - break; - case GLU_AUTO_LOAD_MATRIX: - *value = nobj->auto_load_matrix ? 1.0 : 0.0; - break; - default: - call_user_error(nobj,GLU_INVALID_ENUM); + case GLU_SAMPLING_TOLERANCE: + *value = nobj->sampling_tolerance; + break; + case GLU_DISPLAY_MODE: + *value = (GLfloat) (GLint) nobj->display_mode; + break; + case GLU_CULLING: + *value = nobj->culling ? 1.0 : 0.0; + break; + case GLU_AUTO_LOAD_MATRIX: + *value = nobj->auto_load_matrix ? 1.0 : 0.0; + break; + default: + call_user_error(nobj, GLU_INVALID_ENUM); } } -void GLAPIENTRY gluBeginCurve( GLUnurbsObj *nobj ) +void GLAPIENTRY +gluBeginCurve(GLUnurbsObj * nobj) { - if(nobj->nurbs_type==GLU_NURBS_CURVE) - { - call_user_error(nobj,GLU_NURBS_ERROR6); - return; - } - nobj->nurbs_type=GLU_NURBS_CURVE; - nobj->curve.geom.type=GLU_INVALID_ENUM; - nobj->curve.color.type=GLU_INVALID_ENUM; - nobj->curve.texture.type=GLU_INVALID_ENUM; - nobj->curve.normal.type=GLU_INVALID_ENUM; + if (nobj->nurbs_type == GLU_NURBS_CURVE) { + call_user_error(nobj, GLU_NURBS_ERROR6); + return; + } + nobj->nurbs_type = GLU_NURBS_CURVE; + nobj->curve.geom.type = GLU_INVALID_ENUM; + nobj->curve.color.type = GLU_INVALID_ENUM; + nobj->curve.texture.type = GLU_INVALID_ENUM; + nobj->curve.normal.type = GLU_INVALID_ENUM; } -void GLAPIENTRY gluEndCurve( GLUnurbsObj * nobj ) +void GLAPIENTRY +gluEndCurve(GLUnurbsObj * nobj) { - if(nobj->nurbs_type==GLU_NURBS_NONE) - { - call_user_error(nobj,GLU_NURBS_ERROR7); - return; - } - if(nobj->curve.geom.type==GLU_INVALID_ENUM) - { - call_user_error(nobj,GLU_NURBS_ERROR8); - nobj->nurbs_type=GLU_NURBS_NONE; - return; - } - glPushAttrib( (GLbitfield) (GL_EVAL_BIT | GL_ENABLE_BIT) ); - glDisable(GL_MAP1_VERTEX_3); - glDisable(GL_MAP1_VERTEX_4); - glDisable(GL_MAP1_INDEX); - glDisable(GL_MAP1_COLOR_4); - glDisable(GL_MAP1_NORMAL); - glDisable(GL_MAP1_TEXTURE_COORD_1); - glDisable(GL_MAP1_TEXTURE_COORD_2); - glDisable(GL_MAP1_TEXTURE_COORD_3); - glDisable(GL_MAP1_TEXTURE_COORD_4); - glDisable(GL_MAP2_VERTEX_3); - glDisable(GL_MAP2_VERTEX_4); - glDisable(GL_MAP2_INDEX); - glDisable(GL_MAP2_COLOR_4); - glDisable(GL_MAP2_NORMAL); - glDisable(GL_MAP2_TEXTURE_COORD_1); - glDisable(GL_MAP2_TEXTURE_COORD_2); - glDisable(GL_MAP2_TEXTURE_COORD_3); - glDisable(GL_MAP2_TEXTURE_COORD_4); - do_nurbs_curve(nobj); - glPopAttrib(); - nobj->nurbs_type=GLU_NURBS_NONE; + if (nobj->nurbs_type == GLU_NURBS_NONE) { + call_user_error(nobj, GLU_NURBS_ERROR7); + return; + } + if (nobj->curve.geom.type == GLU_INVALID_ENUM) { + call_user_error(nobj, GLU_NURBS_ERROR8); + nobj->nurbs_type = GLU_NURBS_NONE; + return; + } + glPushAttrib((GLbitfield) (GL_EVAL_BIT | GL_ENABLE_BIT)); + glDisable(GL_MAP1_VERTEX_3); + glDisable(GL_MAP1_VERTEX_4); + glDisable(GL_MAP1_INDEX); + glDisable(GL_MAP1_COLOR_4); + glDisable(GL_MAP1_NORMAL); + glDisable(GL_MAP1_TEXTURE_COORD_1); + glDisable(GL_MAP1_TEXTURE_COORD_2); + glDisable(GL_MAP1_TEXTURE_COORD_3); + glDisable(GL_MAP1_TEXTURE_COORD_4); + glDisable(GL_MAP2_VERTEX_3); + glDisable(GL_MAP2_VERTEX_4); + glDisable(GL_MAP2_INDEX); + glDisable(GL_MAP2_COLOR_4); + glDisable(GL_MAP2_NORMAL); + glDisable(GL_MAP2_TEXTURE_COORD_1); + glDisable(GL_MAP2_TEXTURE_COORD_2); + glDisable(GL_MAP2_TEXTURE_COORD_3); + glDisable(GL_MAP2_TEXTURE_COORD_4); + do_nurbs_curve(nobj); + glPopAttrib(); + nobj->nurbs_type = GLU_NURBS_NONE; } -void GLAPIENTRY gluNurbsCurve( GLUnurbsObj *nobj, GLint nknots, GLfloat *knot, - GLint stride, GLfloat *ctlarray, GLint order, GLenum type ) +void GLAPIENTRY +gluNurbsCurve(GLUnurbsObj * nobj, GLint nknots, GLfloat * knot, + GLint stride, GLfloat * ctlarray, GLint order, GLenum type) { - if(nobj->nurbs_type==GLU_NURBS_TRIM) - { + if (nobj->nurbs_type == GLU_NURBS_TRIM) { #if 0 /* TODO: NOT IMPLEMENTED YET */ - nurbs_trim *ptr1; - trim_list *ptr2; - - if(type!=GLU_MAP1_TRIM_2 && type!=GLU_MAP1_TRIM_3) - { - call_user_error(nobj,GLU_NURBS_ERROR14); - return; - } - for(ptr1=nobj->trim;ptr1->next;ptr1=ptr1->next); - if(ptr1->trim_loop) - { - for(ptr2=ptr1->trim_loop;ptr2->next;ptr2=ptr2->next); - if((ptr2->next=(trim_list *)malloc(sizeof(trim_list)))==NULL) - { - call_user_error(nobj,GLU_OUT_OF_MEMORY); - return; - } - ptr2=ptr2->next; - } - else - { - if((ptr2=(trim_list *)malloc(sizeof(trim_list)))==NULL) - { - call_user_error(nobj,GLU_OUT_OF_MEMORY); - return; - } - ptr1->trim_loop=ptr2; - } - ptr2->trim_type=GLU_TRIM_NURBS; - ptr2->curve.nurbs_curve.knot_count=nknots; - ptr2->curve.nurbs_curve.knot=knot; - ptr2->curve.nurbs_curve.stride=stride; - ptr2->curve.nurbs_curve.ctrlarray=ctlarray; - ptr2->curve.nurbs_curve.order=order; - ptr2->curve.nurbs_curve.dim= (type==GLU_MAP1_TRIM_2 ? 2 : 3 ); - ptr2->curve.nurbs_curve.type=type; - ptr2->next=NULL; + nurbs_trim *ptr1; + trim_list *ptr2; + + if (type != GLU_MAP1_TRIM_2 && type != GLU_MAP1_TRIM_3) { + call_user_error(nobj, GLU_NURBS_ERROR14); + return; + } + for (ptr1 = nobj->trim; ptr1->next; ptr1 = ptr1->next); + if (ptr1->trim_loop) { + for (ptr2 = ptr1->trim_loop; ptr2->next; ptr2 = ptr2->next); + if ((ptr2->next = (trim_list *) malloc(sizeof(trim_list))) == NULL) { + call_user_error(nobj, GLU_OUT_OF_MEMORY); + return; + } + ptr2 = ptr2->next; + } + else { + if ((ptr2 = (trim_list *) malloc(sizeof(trim_list))) == NULL) { + call_user_error(nobj, GLU_OUT_OF_MEMORY); + return; + } + ptr1->trim_loop = ptr2; + } + ptr2->trim_type = GLU_TRIM_NURBS; + ptr2->curve.nurbs_curve.knot_count = nknots; + ptr2->curve.nurbs_curve.knot = knot; + ptr2->curve.nurbs_curve.stride = stride; + ptr2->curve.nurbs_curve.ctrlarray = ctlarray; + ptr2->curve.nurbs_curve.order = order; + ptr2->curve.nurbs_curve.dim = (type == GLU_MAP1_TRIM_2 ? 2 : 3); + ptr2->curve.nurbs_curve.type = type; + ptr2->next = NULL; #endif - } - else - { - if(type==GLU_MAP1_TRIM_2 || type==GLU_MAP1_TRIM_3) - { - call_user_error(nobj,GLU_NURBS_ERROR22); - return; - } - if(nobj->nurbs_type!=GLU_NURBS_CURVE) - { - call_user_error(nobj,GLU_NURBS_ERROR10); - return; - } - switch(type) - { - case GL_MAP1_VERTEX_3: - case GL_MAP1_VERTEX_4: - if(nobj->curve.geom.type!=GLU_INVALID_ENUM) - { - call_user_error(nobj,GLU_NURBS_ERROR8); - return; - } - nobj->curve.geom.type=type; - nobj->curve.geom.knot_count=nknots; - nobj->curve.geom.knot=knot; - nobj->curve.geom.stride=stride; - nobj->curve.geom.ctrlarray=ctlarray; - nobj->curve.geom.order=order; - break; - case GL_MAP1_INDEX: - case GL_MAP1_COLOR_4: - nobj->curve.color.type=type; - nobj->curve.color.knot_count=nknots; - nobj->curve.color.knot=knot; - nobj->curve.color.stride=stride; - nobj->curve.color.ctrlarray=ctlarray; - nobj->curve.color.order=order; - break; - case GL_MAP1_NORMAL: - nobj->curve.normal.type=type; - nobj->curve.normal.knot_count=nknots; - nobj->curve.normal.knot=knot; - nobj->curve.normal.stride=stride; - nobj->curve.normal.ctrlarray=ctlarray; - nobj->curve.normal.order=order; - break; - case GL_MAP1_TEXTURE_COORD_1: - case GL_MAP1_TEXTURE_COORD_2: - case GL_MAP1_TEXTURE_COORD_3: - case GL_MAP1_TEXTURE_COORD_4: - nobj->curve.texture.type=type; - nobj->curve.texture.knot_count=nknots; - nobj->curve.texture.knot=knot; - nobj->curve.texture.stride=stride; - nobj->curve.texture.ctrlarray=ctlarray; - nobj->curve.texture.order=order; - break; - default: - call_user_error(nobj,GLU_INVALID_ENUM); - } - } + } + else { + if (type == GLU_MAP1_TRIM_2 || type == GLU_MAP1_TRIM_3) { + call_user_error(nobj, GLU_NURBS_ERROR22); + return; + } + if (nobj->nurbs_type != GLU_NURBS_CURVE) { + call_user_error(nobj, GLU_NURBS_ERROR10); + return; + } + switch (type) { + case GL_MAP1_VERTEX_3: + case GL_MAP1_VERTEX_4: + if (nobj->curve.geom.type != GLU_INVALID_ENUM) { + call_user_error(nobj, GLU_NURBS_ERROR8); + return; + } + nobj->curve.geom.type = type; + nobj->curve.geom.knot_count = nknots; + nobj->curve.geom.knot = knot; + nobj->curve.geom.stride = stride; + nobj->curve.geom.ctrlarray = ctlarray; + nobj->curve.geom.order = order; + break; + case GL_MAP1_INDEX: + case GL_MAP1_COLOR_4: + nobj->curve.color.type = type; + nobj->curve.color.knot_count = nknots; + nobj->curve.color.knot = knot; + nobj->curve.color.stride = stride; + nobj->curve.color.ctrlarray = ctlarray; + nobj->curve.color.order = order; + break; + case GL_MAP1_NORMAL: + nobj->curve.normal.type = type; + nobj->curve.normal.knot_count = nknots; + nobj->curve.normal.knot = knot; + nobj->curve.normal.stride = stride; + nobj->curve.normal.ctrlarray = ctlarray; + nobj->curve.normal.order = order; + break; + case GL_MAP1_TEXTURE_COORD_1: + case GL_MAP1_TEXTURE_COORD_2: + case GL_MAP1_TEXTURE_COORD_3: + case GL_MAP1_TEXTURE_COORD_4: + nobj->curve.texture.type = type; + nobj->curve.texture.knot_count = nknots; + nobj->curve.texture.knot = knot; + nobj->curve.texture.stride = stride; + nobj->curve.texture.ctrlarray = ctlarray; + nobj->curve.texture.order = order; + break; + default: + call_user_error(nobj, GLU_INVALID_ENUM); + } + } } -void GLAPIENTRY gluBeginSurface( GLUnurbsObj *nobj ) +void GLAPIENTRY +gluBeginSurface(GLUnurbsObj * nobj) { - switch(nobj->nurbs_type) - { - case GLU_NURBS_NONE: - nobj->nurbs_type=GLU_NURBS_SURFACE; - nobj->surface.geom.type=GLU_INVALID_ENUM; - nobj->surface.color.type=GLU_INVALID_ENUM; - nobj->surface.texture.type=GLU_INVALID_ENUM; - nobj->surface.normal.type=GLU_INVALID_ENUM; - break; - case GLU_NURBS_TRIM: - call_user_error(nobj,GLU_NURBS_ERROR16); - break; - case GLU_NURBS_SURFACE: - case GLU_NURBS_NO_TRIM: - case GLU_NURBS_TRIM_DONE: - call_user_error(nobj,GLU_NURBS_ERROR27); - break; - case GLU_NURBS_CURVE: - call_user_error(nobj,GLU_NURBS_ERROR6); - break; - } + switch (nobj->nurbs_type) { + case GLU_NURBS_NONE: + nobj->nurbs_type = GLU_NURBS_SURFACE; + nobj->surface.geom.type = GLU_INVALID_ENUM; + nobj->surface.color.type = GLU_INVALID_ENUM; + nobj->surface.texture.type = GLU_INVALID_ENUM; + nobj->surface.normal.type = GLU_INVALID_ENUM; + break; + case GLU_NURBS_TRIM: + call_user_error(nobj, GLU_NURBS_ERROR16); + break; + case GLU_NURBS_SURFACE: + case GLU_NURBS_NO_TRIM: + case GLU_NURBS_TRIM_DONE: + call_user_error(nobj, GLU_NURBS_ERROR27); + break; + case GLU_NURBS_CURVE: + call_user_error(nobj, GLU_NURBS_ERROR6); + break; + } } -void GLAPIENTRY gluEndSurface( GLUnurbsObj * nobj ) +void GLAPIENTRY +gluEndSurface(GLUnurbsObj * nobj) { - switch(nobj->nurbs_type) - { - case GLU_NURBS_NONE: - call_user_error(nobj,GLU_NURBS_ERROR13); - break; - case GLU_NURBS_TRIM: - call_user_error(nobj,GLU_NURBS_ERROR12); - break; - case GLU_NURBS_TRIM_DONE: + switch (nobj->nurbs_type) { + case GLU_NURBS_NONE: + call_user_error(nobj, GLU_NURBS_ERROR13); + break; + case GLU_NURBS_TRIM: + call_user_error(nobj, GLU_NURBS_ERROR12); + break; + case GLU_NURBS_TRIM_DONE: /* if(nobj->trim->trim_loop==NULL) { call_user_error(nobj,GLU_NURBS_ERROR18); return; }*/ - /* no break - fallthrough */ - case GLU_NURBS_NO_TRIM: - glPushAttrib( (GLbitfield) - (GL_EVAL_BIT | GL_ENABLE_BIT | GL_POLYGON_BIT) ); - glDisable(GL_MAP2_VERTEX_3); - glDisable(GL_MAP2_VERTEX_4); - glDisable(GL_MAP2_INDEX); - glDisable(GL_MAP2_COLOR_4); - glDisable(GL_MAP2_NORMAL); - glDisable(GL_MAP2_TEXTURE_COORD_1); - glDisable(GL_MAP2_TEXTURE_COORD_2); - glDisable(GL_MAP2_TEXTURE_COORD_3); - glDisable(GL_MAP2_TEXTURE_COORD_4); + /* no break - fallthrough */ + case GLU_NURBS_NO_TRIM: + glPushAttrib((GLbitfield) + (GL_EVAL_BIT | GL_ENABLE_BIT | GL_POLYGON_BIT)); + glDisable(GL_MAP2_VERTEX_3); + glDisable(GL_MAP2_VERTEX_4); + glDisable(GL_MAP2_INDEX); + glDisable(GL_MAP2_COLOR_4); + glDisable(GL_MAP2_NORMAL); + glDisable(GL_MAP2_TEXTURE_COORD_1); + glDisable(GL_MAP2_TEXTURE_COORD_2); + glDisable(GL_MAP2_TEXTURE_COORD_3); + glDisable(GL_MAP2_TEXTURE_COORD_4); /* glDisable(GL_MAP1_VERTEX_3); glDisable(GL_MAP1_VERTEX_4); glDisable(GL_MAP1_INDEX); @@ -454,208 +439,191 @@ void GLAPIENTRY gluEndSurface( GLUnurbsObj * nobj ) glDisable(GL_MAP1_TEXTURE_COORD_2); glDisable(GL_MAP1_TEXTURE_COORD_3); glDisable(GL_MAP1_TEXTURE_COORD_4);*/ - do_nurbs_surface(nobj); - glPopAttrib(); - break; - default: - call_user_error(nobj,GLU_NURBS_ERROR8); - } - nobj->nurbs_type=GLU_NURBS_NONE; + do_nurbs_surface(nobj); + glPopAttrib(); + break; + default: + call_user_error(nobj, GLU_NURBS_ERROR8); + } + nobj->nurbs_type = GLU_NURBS_NONE; } -void GLAPIENTRY gluNurbsSurface( GLUnurbsObj *nobj, - GLint sknot_count, GLfloat *sknot, - GLint tknot_count, GLfloat *tknot, - GLint s_stride, GLint t_stride, - GLfloat *ctrlarray, - GLint sorder, GLint torder, - GLenum type ) +void GLAPIENTRY +gluNurbsSurface(GLUnurbsObj * nobj, + GLint sknot_count, GLfloat * sknot, + GLint tknot_count, GLfloat * tknot, + GLint s_stride, GLint t_stride, + GLfloat * ctrlarray, GLint sorder, GLint torder, GLenum type) { - if(nobj->nurbs_type==GLU_NURBS_NO_TRIM || nobj->nurbs_type==GLU_NURBS_TRIM || - nobj->nurbs_type==GLU_NURBS_TRIM_DONE) - { - if(type==GL_MAP2_VERTEX_3 || type==GL_MAP2_VERTEX_4) - { - call_user_error(nobj,GLU_NURBS_ERROR8); - return; - } - } - else - if(nobj->nurbs_type!=GLU_NURBS_SURFACE) - { - call_user_error(nobj,GLU_NURBS_ERROR11); - return; - } - switch(type) - { - case GL_MAP2_VERTEX_3: - case GL_MAP2_VERTEX_4: - nobj->surface.geom.sknot_count=sknot_count; - nobj->surface.geom.sknot=sknot; - nobj->surface.geom.tknot_count=tknot_count; - nobj->surface.geom.tknot=tknot; - nobj->surface.geom.s_stride=s_stride; - nobj->surface.geom.t_stride=t_stride; - nobj->surface.geom.ctrlarray=ctrlarray; - nobj->surface.geom.sorder=sorder; - nobj->surface.geom.torder=torder; - nobj->surface.geom.type=type; - nobj->nurbs_type=GLU_NURBS_NO_TRIM; - break; - case GL_MAP2_INDEX: - case GL_MAP2_COLOR_4: - nobj->surface.color.sknot_count=sknot_count; - nobj->surface.color.sknot=sknot; - nobj->surface.color.tknot_count=tknot_count; - nobj->surface.color.tknot=tknot; - nobj->surface.color.s_stride=s_stride; - nobj->surface.color.t_stride=t_stride; - nobj->surface.color.ctrlarray=ctrlarray; - nobj->surface.color.sorder=sorder; - nobj->surface.color.torder=torder; - nobj->surface.color.type=type; - break; - case GL_MAP2_NORMAL: - nobj->surface.normal.sknot_count=sknot_count; - nobj->surface.normal.sknot=sknot; - nobj->surface.normal.tknot_count=tknot_count; - nobj->surface.normal.tknot=tknot; - nobj->surface.normal.s_stride=s_stride; - nobj->surface.normal.t_stride=t_stride; - nobj->surface.normal.ctrlarray=ctrlarray; - nobj->surface.normal.sorder=sorder; - nobj->surface.normal.torder=torder; - nobj->surface.normal.type=type; - break; - case GL_MAP2_TEXTURE_COORD_1: - case GL_MAP2_TEXTURE_COORD_2: - case GL_MAP2_TEXTURE_COORD_3: - case GL_MAP2_TEXTURE_COORD_4: - nobj->surface.texture.sknot_count=sknot_count; - nobj->surface.texture.sknot=sknot; - nobj->surface.texture.tknot_count=tknot_count; - nobj->surface.texture.tknot=tknot; - nobj->surface.texture.s_stride=s_stride; - nobj->surface.texture.t_stride=t_stride; - nobj->surface.texture.ctrlarray=ctrlarray; - nobj->surface.texture.sorder=sorder; - nobj->surface.texture.torder=torder; - nobj->surface.texture.type=type; - break; - default: - call_user_error(nobj,GLU_INVALID_ENUM); - } + if (nobj->nurbs_type == GLU_NURBS_NO_TRIM + || nobj->nurbs_type == GLU_NURBS_TRIM + || nobj->nurbs_type == GLU_NURBS_TRIM_DONE) { + if (type == GL_MAP2_VERTEX_3 || type == GL_MAP2_VERTEX_4) { + call_user_error(nobj, GLU_NURBS_ERROR8); + return; + } + } + else if (nobj->nurbs_type != GLU_NURBS_SURFACE) { + call_user_error(nobj, GLU_NURBS_ERROR11); + return; + } + switch (type) { + case GL_MAP2_VERTEX_3: + case GL_MAP2_VERTEX_4: + nobj->surface.geom.sknot_count = sknot_count; + nobj->surface.geom.sknot = sknot; + nobj->surface.geom.tknot_count = tknot_count; + nobj->surface.geom.tknot = tknot; + nobj->surface.geom.s_stride = s_stride; + nobj->surface.geom.t_stride = t_stride; + nobj->surface.geom.ctrlarray = ctrlarray; + nobj->surface.geom.sorder = sorder; + nobj->surface.geom.torder = torder; + nobj->surface.geom.type = type; + nobj->nurbs_type = GLU_NURBS_NO_TRIM; + break; + case GL_MAP2_INDEX: + case GL_MAP2_COLOR_4: + nobj->surface.color.sknot_count = sknot_count; + nobj->surface.color.sknot = sknot; + nobj->surface.color.tknot_count = tknot_count; + nobj->surface.color.tknot = tknot; + nobj->surface.color.s_stride = s_stride; + nobj->surface.color.t_stride = t_stride; + nobj->surface.color.ctrlarray = ctrlarray; + nobj->surface.color.sorder = sorder; + nobj->surface.color.torder = torder; + nobj->surface.color.type = type; + break; + case GL_MAP2_NORMAL: + nobj->surface.normal.sknot_count = sknot_count; + nobj->surface.normal.sknot = sknot; + nobj->surface.normal.tknot_count = tknot_count; + nobj->surface.normal.tknot = tknot; + nobj->surface.normal.s_stride = s_stride; + nobj->surface.normal.t_stride = t_stride; + nobj->surface.normal.ctrlarray = ctrlarray; + nobj->surface.normal.sorder = sorder; + nobj->surface.normal.torder = torder; + nobj->surface.normal.type = type; + break; + case GL_MAP2_TEXTURE_COORD_1: + case GL_MAP2_TEXTURE_COORD_2: + case GL_MAP2_TEXTURE_COORD_3: + case GL_MAP2_TEXTURE_COORD_4: + nobj->surface.texture.sknot_count = sknot_count; + nobj->surface.texture.sknot = sknot; + nobj->surface.texture.tknot_count = tknot_count; + nobj->surface.texture.tknot = tknot; + nobj->surface.texture.s_stride = s_stride; + nobj->surface.texture.t_stride = t_stride; + nobj->surface.texture.ctrlarray = ctrlarray; + nobj->surface.texture.sorder = sorder; + nobj->surface.texture.torder = torder; + nobj->surface.texture.type = type; + break; + default: + call_user_error(nobj, GLU_INVALID_ENUM); + } } void GLAPIENTRY -gluNurbsCallback( GLUnurbsObj *nobj, GLenum which, void (GLCALLBACKP fn)()) +gluNurbsCallback(GLUnurbsObj * nobj, GLenum which, void (GLCALLBACK * fn) ()) { - nobj->error_callback = (void(GLCALLBACKPCAST)(GLenum))fn; + nobj->error_callback = (void (GLCALLBACKPCAST) (GLenum)) fn; - if(which!=GLU_ERROR) - call_user_error(nobj,GLU_INVALID_ENUM); + if (which != GLU_ERROR) + call_user_error(nobj, GLU_INVALID_ENUM); } void GLAPIENTRY -gluBeginTrim( GLUnurbsObj *nobj ) +gluBeginTrim(GLUnurbsObj * nobj) { #if 0 - nurbs_trim *ptr; + nurbs_trim *ptr; #endif - if(nobj->nurbs_type!=GLU_NURBS_TRIM_DONE) - if(nobj->nurbs_type!=GLU_NURBS_NO_TRIM) - { - call_user_error(nobj,GLU_NURBS_ERROR15); - return; - } - nobj->nurbs_type=GLU_NURBS_TRIM; -fprintf(stderr,"NURBS - trimming not supported yet\n"); + if (nobj->nurbs_type != GLU_NURBS_TRIM_DONE) + if (nobj->nurbs_type != GLU_NURBS_NO_TRIM) { + call_user_error(nobj, GLU_NURBS_ERROR15); + return; + } + nobj->nurbs_type = GLU_NURBS_TRIM; + fprintf(stderr, "NURBS - trimming not supported yet\n"); #if 0 - if((ptr=(nurbs_trim *)malloc(sizeof(nurbs_trim)))==NULL) - { - call_user_error(nobj,GLU_OUT_OF_MEMORY); - return; - } - if(nobj->trim) - { - nurbs_trim *tmp_ptr; - - for(tmp_ptr=nobj->trim;tmp_ptr->next;tmp_ptr=tmp_ptr->next); - tmp_ptr->next=ptr; - } - else - nobj->trim=ptr; - ptr->trim_loop=NULL; - ptr->segments=NULL; - ptr->next=NULL; + if ((ptr = (nurbs_trim *) malloc(sizeof(nurbs_trim))) == NULL) { + call_user_error(nobj, GLU_OUT_OF_MEMORY); + return; + } + if (nobj->trim) { + nurbs_trim *tmp_ptr; + + for (tmp_ptr = nobj->trim; tmp_ptr->next; tmp_ptr = tmp_ptr->next); + tmp_ptr->next = ptr; + } + else + nobj->trim = ptr; + ptr->trim_loop = NULL; + ptr->segments = NULL; + ptr->next = NULL; #endif } void GLAPIENTRY -gluPwlCurve( GLUnurbsObj *nobj, GLint count, GLfloat *array, GLint stride, - GLenum type) +gluPwlCurve(GLUnurbsObj * nobj, GLint count, GLfloat * array, GLint stride, + GLenum type) { #if 0 - nurbs_trim *ptr1; - trim_list *ptr2; + nurbs_trim *ptr1; + trim_list *ptr2; #endif - if(nobj->nurbs_type==GLU_NURBS_CURVE) - { - call_user_error(nobj,GLU_NURBS_ERROR9); - return; - } - if(nobj->nurbs_type==GLU_NURBS_NONE) - { - call_user_error(nobj,GLU_NURBS_ERROR19); - return; - } - if(type!=GLU_MAP1_TRIM_2 && type!=GLU_MAP1_TRIM_3) - { - call_user_error(nobj,GLU_NURBS_ERROR14); - return; - } + if (nobj->nurbs_type == GLU_NURBS_CURVE) { + call_user_error(nobj, GLU_NURBS_ERROR9); + return; + } + if (nobj->nurbs_type == GLU_NURBS_NONE) { + call_user_error(nobj, GLU_NURBS_ERROR19); + return; + } + if (type != GLU_MAP1_TRIM_2 && type != GLU_MAP1_TRIM_3) { + call_user_error(nobj, GLU_NURBS_ERROR14); + return; + } #if 0 - for(ptr1=nobj->trim;ptr1->next;ptr1=ptr1->next); - if(ptr1->trim_loop) - { - for(ptr2=ptr1->trim_loop;ptr2->next;ptr2=ptr2->next); - if((ptr2->next=(trim_list *)malloc(sizeof(trim_list)))==NULL) - { - call_user_error(nobj,GLU_OUT_OF_MEMORY); - return; - } - ptr2=ptr2->next; - } - else - { - if((ptr2=(trim_list *)malloc(sizeof(trim_list)))==NULL) - { - call_user_error(nobj,GLU_OUT_OF_MEMORY); - return; - } - ptr1->trim_loop=ptr2; - } - ptr2->trim_type=GLU_TRIM_PWL; - ptr2->curve.pwl_curve.pt_count=count; - ptr2->curve.pwl_curve.ctrlarray=array; - ptr2->curve.pwl_curve.stride=stride; - ptr2->curve.pwl_curve.dim= (type==GLU_MAP1_TRIM_2 ? 2 : 3 ); - ptr2->curve.pwl_curve.type=type; - ptr2->next=NULL; + for (ptr1 = nobj->trim; ptr1->next; ptr1 = ptr1->next); + if (ptr1->trim_loop) { + for (ptr2 = ptr1->trim_loop; ptr2->next; ptr2 = ptr2->next); + if ((ptr2->next = (trim_list *) malloc(sizeof(trim_list))) == NULL) { + call_user_error(nobj, GLU_OUT_OF_MEMORY); + return; + } + ptr2 = ptr2->next; + } + else { + if ((ptr2 = (trim_list *) malloc(sizeof(trim_list))) == NULL) { + call_user_error(nobj, GLU_OUT_OF_MEMORY); + return; + } + ptr1->trim_loop = ptr2; + } + ptr2->trim_type = GLU_TRIM_PWL; + ptr2->curve.pwl_curve.pt_count = count; + ptr2->curve.pwl_curve.ctrlarray = array; + ptr2->curve.pwl_curve.stride = stride; + ptr2->curve.pwl_curve.dim = (type == GLU_MAP1_TRIM_2 ? 2 : 3); + ptr2->curve.pwl_curve.type = type; + ptr2->next = NULL; #endif } void GLAPIENTRY -gluEndTrim( GLUnurbsObj *nobj ) +gluEndTrim(GLUnurbsObj * nobj) { - if(nobj->nurbs_type!=GLU_NURBS_TRIM) - { - call_user_error(nobj,GLU_NURBS_ERROR17); - return; - } - nobj->nurbs_type=GLU_NURBS_TRIM_DONE; + if (nobj->nurbs_type != GLU_NURBS_TRIM) { + call_user_error(nobj, GLU_NURBS_ERROR17); + return; + } + nobj->nurbs_type = GLU_NURBS_TRIM_DONE; } - diff --git a/src/glu/mesa/nurbs.h b/src/glu/mesa/nurbs.h index 3e38ea40068..c80cacf57af 100644 --- a/src/glu/mesa/nurbs.h +++ b/src/glu/mesa/nurbs.h @@ -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); diff --git a/src/glu/mesa/nurbscrv.c b/src/glu/mesa/nurbscrv.c index 022818b73ca..a9ff4f28671 100644 --- a/src/glu/mesa/nurbscrv.c +++ b/src/glu/mesa/nurbscrv.c @@ -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])open_at_begin=GL_TRUE; - } - else - geom_knot->open_at_begin=GL_FALSE; - if(fabs(knot[t_max]-knot[nknots-1])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])open_at_begin=GL_TRUE; - } - else - color_knot->open_at_begin=GL_FALSE; - if(fabs(knot[t_max]-knot[nknots-1])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])open_at_begin=GL_TRUE; - } - else - normal_knot->open_at_begin=GL_FALSE; - if(fabs(knot[t_max]-knot[nknots-1])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])open_at_begin=GL_TRUE; - } - else - texture_knot->open_at_begin=GL_FALSE; - if(fabs(knot[t_max]-knot[nknots-1])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; - icurve.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); } - - diff --git a/src/glu/mesa/nurbssrf.c b/src/glu/mesa/nurbssrf.c index 57eb9569862..c8d44bec0df 100644 --- a/src/glu/mesa/nurbssrf.c +++ b/src/glu/mesa/nurbssrf.c @@ -1,9 +1,9 @@ -/* $Id: nurbssrf.c,v 1.1 1999/08/19 00:55:42 jtg Exp $ */ +/* $Id: nurbssrf.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,35 +21,6 @@ */ -/* - * $Log: nurbssrf.c,v $ - * Revision 1.1 1999/08/19 00:55:42 jtg - * Initial revision - * - * Revision 1.7 1997/07/24 01:28:44 brianp - * changed precompiled header symbol from PCH to PC_HEADER - * - * Revision 1.6 1997/06/23 00:22:07 brianp - * include - * - * 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:20:35 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:13:02 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. @@ -70,1119 +41,1048 @@ static int get_surface_dim(GLenum type) { - switch(type) - { - case GL_MAP2_VERTEX_3: return 3; - case GL_MAP2_VERTEX_4: return 4; - case GL_MAP2_INDEX: return 1; - case GL_MAP2_COLOR_4: return 4; - case GL_MAP2_NORMAL: return 3; - case GL_MAP2_TEXTURE_COORD_1: return 1; - case GL_MAP2_TEXTURE_COORD_2: return 2; - case GL_MAP2_TEXTURE_COORD_3: return 3; - case GL_MAP2_TEXTURE_COORD_4: return 4; - default: abort(); /* TODO: is this OK? */ - } - return 0; /*never get here*/ + switch (type) { + case GL_MAP2_VERTEX_3: + return 3; + case GL_MAP2_VERTEX_4: + return 4; + case GL_MAP2_INDEX: + return 1; + case GL_MAP2_COLOR_4: + return 4; + case GL_MAP2_NORMAL: + return 3; + case GL_MAP2_TEXTURE_COORD_1: + return 1; + case GL_MAP2_TEXTURE_COORD_2: + return 2; + case GL_MAP2_TEXTURE_COORD_3: + return 3; + case GL_MAP2_TEXTURE_COORD_4: + return 4; + default: + abort(); /* TODO: is this OK? */ + } + return 0; /*never get here */ } static GLenum -test_nurbs_surface(GLUnurbsObj *nobj, surface_attribs *attrib) +test_nurbs_surface(GLUnurbsObj * nobj, surface_attribs * attrib) { - GLenum err; - GLint tmp_int; + GLenum err; + GLint tmp_int; - if(attrib->sorder < 0 || attrib->torder < 0) - { - call_user_error(nobj,GLU_INVALID_VALUE); - return GLU_ERROR; - } - glGetIntegerv(GL_MAX_EVAL_ORDER,&tmp_int); - if(attrib->sorder > tmp_int || attrib->sorder < 2) - { - call_user_error(nobj,GLU_NURBS_ERROR1); - return GLU_ERROR; - } - if(attrib->torder > tmp_int || attrib->torder < 2) - { - call_user_error(nobj,GLU_NURBS_ERROR1); - return GLU_ERROR; - } - if(attrib->sknot_count < attrib->sorder +2) - { - call_user_error(nobj,GLU_NURBS_ERROR2); - return GLU_ERROR; - } - if(attrib->tknot_count < attrib->torder +2) - { - call_user_error(nobj,GLU_NURBS_ERROR2); - return GLU_ERROR; - } - if(attrib->s_stride < 0 || attrib->t_stride < 0) - { - call_user_error(nobj,GLU_NURBS_ERROR34); - return GLU_ERROR; - } - if(attrib->sknot==NULL || attrib->tknot==NULL || attrib->ctrlarray==NULL) - { - call_user_error(nobj,GLU_NURBS_ERROR36); - return GLU_ERROR; - } - if((err=test_knot(attrib->tknot_count,attrib->tknot,attrib->torder)) - !=GLU_NO_ERROR) - { - call_user_error(nobj,err); - return GLU_ERROR; - } - if((err=test_knot(attrib->sknot_count,attrib->sknot,attrib->sorder)) - !=GLU_NO_ERROR) - { - call_user_error(nobj,err); - return GLU_ERROR; - } - return GLU_NO_ERROR; + if (attrib->sorder < 0 || attrib->torder < 0) { + call_user_error(nobj, GLU_INVALID_VALUE); + return GLU_ERROR; + } + glGetIntegerv(GL_MAX_EVAL_ORDER, &tmp_int); + if (attrib->sorder > tmp_int || attrib->sorder < 2) { + call_user_error(nobj, GLU_NURBS_ERROR1); + return GLU_ERROR; + } + if (attrib->torder > tmp_int || attrib->torder < 2) { + call_user_error(nobj, GLU_NURBS_ERROR1); + return GLU_ERROR; + } + if (attrib->sknot_count < attrib->sorder + 2) { + call_user_error(nobj, GLU_NURBS_ERROR2); + return GLU_ERROR; + } + if (attrib->tknot_count < attrib->torder + 2) { + call_user_error(nobj, GLU_NURBS_ERROR2); + return GLU_ERROR; + } + if (attrib->s_stride < 0 || attrib->t_stride < 0) { + call_user_error(nobj, GLU_NURBS_ERROR34); + return GLU_ERROR; + } + if (attrib->sknot == NULL || attrib->tknot == NULL + || attrib->ctrlarray == NULL) { + call_user_error(nobj, GLU_NURBS_ERROR36); + return GLU_ERROR; + } + if ((err = test_knot(attrib->tknot_count, attrib->tknot, attrib->torder)) + != GLU_NO_ERROR) { + call_user_error(nobj, err); + return GLU_ERROR; + } + if ((err = test_knot(attrib->sknot_count, attrib->sknot, attrib->sorder)) + != GLU_NO_ERROR) { + call_user_error(nobj, err); + return GLU_ERROR; + } + return GLU_NO_ERROR; } static GLenum -test_nurbs_surfaces(GLUnurbsObj *nobj) +test_nurbs_surfaces(GLUnurbsObj * nobj) { - /* test the geometric data */ - if(test_nurbs_surface(nobj,&(nobj->surface.geom))!=GLU_NO_ERROR) - return GLU_ERROR; - /* now test the attributive data */ - /* color */ - if(nobj->surface.color.type!=GLU_INVALID_ENUM) - if(test_nurbs_surface(nobj,&(nobj->surface.color))!=GLU_NO_ERROR) - return GLU_ERROR; - /* normal */ - if(nobj->surface.normal.type!=GLU_INVALID_ENUM) - if(test_nurbs_surface(nobj,&(nobj->surface.normal))!=GLU_NO_ERROR) - return GLU_ERROR; - /* texture */ - if(nobj->surface.texture.type!=GLU_INVALID_ENUM) - if(test_nurbs_surface(nobj,&(nobj->surface.texture))!=GLU_NO_ERROR) - return GLU_ERROR; - return GLU_NO_ERROR; + /* test the geometric data */ + if (test_nurbs_surface(nobj, &(nobj->surface.geom)) != GLU_NO_ERROR) + return GLU_ERROR; + /* now test the attributive data */ + /* color */ + if (nobj->surface.color.type != GLU_INVALID_ENUM) + if (test_nurbs_surface(nobj, &(nobj->surface.color)) != GLU_NO_ERROR) + return GLU_ERROR; + /* normal */ + if (nobj->surface.normal.type != GLU_INVALID_ENUM) + if (test_nurbs_surface(nobj, &(nobj->surface.normal)) != GLU_NO_ERROR) + return GLU_ERROR; + /* texture */ + if (nobj->surface.texture.type != GLU_INVALID_ENUM) + if (test_nurbs_surface(nobj, &(nobj->surface.texture)) != GLU_NO_ERROR) + return GLU_ERROR; + return GLU_NO_ERROR; } static GLenum -convert_surf(knot_str_type *s_knot, knot_str_type *t_knot, - surface_attribs *attrib, GLfloat **new_ctrl, - GLint *s_n_ctrl, GLint *t_n_ctrl) +convert_surf(knot_str_type * s_knot, knot_str_type * t_knot, + surface_attribs * attrib, GLfloat ** new_ctrl, + GLint * s_n_ctrl, GLint * t_n_ctrl) { - GLfloat **tmp_ctrl; - GLfloat *ctrl_offset; - GLint tmp_n_control; - GLint i,j,t_cnt,s_cnt; - GLint tmp_stride; - GLint dim; - GLenum err; + GLfloat **tmp_ctrl; + GLfloat *ctrl_offset; + GLint tmp_n_control; + GLint i, j, t_cnt, s_cnt; + GLint tmp_stride; + GLint dim; + GLenum err; - /* valid range is empty? */ - if((s_knot->unified_knot !=NULL && s_knot->unified_nknots==0) || - (t_knot->unified_knot !=NULL && t_knot->unified_nknots==0)) - { - if(s_knot->unified_knot) - { - free(s_knot->unified_knot); - s_knot->unified_knot=NULL; - } - if(t_knot->unified_knot) - { - free(t_knot->unified_knot); - t_knot->unified_knot=NULL; - } - *s_n_ctrl=0; - *t_n_ctrl=0; - return GLU_NO_ERROR; - } - t_cnt=attrib->tknot_count-attrib->torder; - s_cnt=attrib->sknot_count-attrib->sorder; - if((tmp_ctrl=(GLfloat **)malloc(sizeof(GLfloat *)*t_cnt))==NULL) - return GLU_OUT_OF_MEMORY; - if((err=explode_knot(s_knot))!=GLU_NO_ERROR) - { - free(tmp_ctrl); - if(s_knot->unified_knot) - { - free(s_knot->unified_knot); - s_knot->unified_knot=NULL; - } - return err; - } - if(s_knot->unified_knot) - { - free(s_knot->unified_knot); - s_knot->unified_knot=NULL; - } - if((err=calc_alphas(s_knot))!=GLU_NO_ERROR) - { - free(tmp_ctrl); - free(s_knot->new_knot); - return err; - } - free(s_knot->new_knot); - ctrl_offset=attrib->ctrlarray; - dim=attrib->dim; - for(i=0;is_stride,s_knot, - dim,&(tmp_ctrl[i]),&tmp_n_control))!=GLU_NO_ERROR) - { - for(--i;i<=0;i--) - free(tmp_ctrl[i]); - free(tmp_ctrl); - free(s_knot->alpha); - return err; - } - ctrl_offset+=attrib->t_stride; - } - free(s_knot->alpha); - tmp_stride=dim*tmp_n_control; - if((*new_ctrl=(GLfloat *)malloc(sizeof(GLfloat)*tmp_stride*t_cnt)) - ==NULL) - { - for(i=0;iunified_knot) - { - free(t_knot->unified_knot); - t_knot->unified_knot=NULL; - } - return err; - } - if(t_knot->unified_knot) - { - free(t_knot->unified_knot); - t_knot->unified_knot=NULL; - } - if((err=calc_alphas(t_knot))!=GLU_NO_ERROR) - { - free(tmp_ctrl); - free(t_knot->new_knot); - return err; - } - free(t_knot->new_knot); - ctrl_offset=*new_ctrl; - for(i=0;i<(*s_n_ctrl);i++) - { - if((err=calc_new_ctrl_pts(ctrl_offset,dim,t_knot, - dim,&(tmp_ctrl[i]),&tmp_n_control))!=GLU_NO_ERROR) - { - for(--i;i<=0;i--) - free(tmp_ctrl[i]); - free(tmp_ctrl); - free(t_knot->alpha); - return err; - } - ctrl_offset+=dim*t_cnt; - } - free(t_knot->alpha); - free(*new_ctrl); - tmp_stride=dim*tmp_n_control; - if((*new_ctrl=(GLfloat *)malloc(sizeof(GLfloat)*tmp_stride*(*s_n_ctrl))) - ==NULL) - { - for(i=0;i<(*s_n_ctrl);i++) - free(tmp_ctrl[i]); - free(tmp_ctrl); - return GLU_OUT_OF_MEMORY; - } - for(i=0;i<(*s_n_ctrl);i++) - { - MEMCPY(*new_ctrl+i*tmp_stride,tmp_ctrl[i],sizeof(GLfloat)*tmp_stride); - free(tmp_ctrl[i]); - } - free(tmp_ctrl); - *t_n_ctrl=tmp_n_control; - return GLU_NO_ERROR; + /* valid range is empty? */ + if ((s_knot->unified_knot != NULL && s_knot->unified_nknots == 0) || + (t_knot->unified_knot != NULL && t_knot->unified_nknots == 0)) { + if (s_knot->unified_knot) { + free(s_knot->unified_knot); + s_knot->unified_knot = NULL; + } + if (t_knot->unified_knot) { + free(t_knot->unified_knot); + t_knot->unified_knot = NULL; + } + *s_n_ctrl = 0; + *t_n_ctrl = 0; + return GLU_NO_ERROR; + } + t_cnt = attrib->tknot_count - attrib->torder; + s_cnt = attrib->sknot_count - attrib->sorder; + if ((tmp_ctrl = (GLfloat **) malloc(sizeof(GLfloat *) * t_cnt)) == NULL) + return GLU_OUT_OF_MEMORY; + if ((err = explode_knot(s_knot)) != GLU_NO_ERROR) { + free(tmp_ctrl); + if (s_knot->unified_knot) { + free(s_knot->unified_knot); + s_knot->unified_knot = NULL; + } + return err; + } + if (s_knot->unified_knot) { + free(s_knot->unified_knot); + s_knot->unified_knot = NULL; + } + if ((err = calc_alphas(s_knot)) != GLU_NO_ERROR) { + free(tmp_ctrl); + free(s_knot->new_knot); + return err; + } + free(s_knot->new_knot); + ctrl_offset = attrib->ctrlarray; + dim = attrib->dim; + for (i = 0; i < t_cnt; i++) { + if ((err = calc_new_ctrl_pts(ctrl_offset, attrib->s_stride, s_knot, + dim, &(tmp_ctrl[i]), + &tmp_n_control)) != GLU_NO_ERROR) { + for (--i; i <= 0; i--) + free(tmp_ctrl[i]); + free(tmp_ctrl); + free(s_knot->alpha); + return err; + } + ctrl_offset += attrib->t_stride; + } + free(s_knot->alpha); + tmp_stride = dim * tmp_n_control; + if ((*new_ctrl = (GLfloat *) malloc(sizeof(GLfloat) * tmp_stride * t_cnt)) + == NULL) { + for (i = 0; i < t_cnt; i++) + free(tmp_ctrl[i]); + free(tmp_ctrl); + return GLU_OUT_OF_MEMORY; + } + for (i = 0; i < tmp_n_control; i++) + for (j = 0; j < t_cnt; j++) + MEMCPY(*new_ctrl + j * dim + i * dim * t_cnt, tmp_ctrl[j] + dim * i, + sizeof(GLfloat) * dim); + for (i = 0; i < t_cnt; i++) + free(tmp_ctrl[i]); + free(tmp_ctrl); + *s_n_ctrl = tmp_n_control; + + if ((tmp_ctrl = (GLfloat **) malloc(sizeof(GLfloat *) * (*s_n_ctrl))) == + NULL) { + return GLU_OUT_OF_MEMORY; + } + if ((err = explode_knot(t_knot)) != GLU_NO_ERROR) { + free(tmp_ctrl); + if (t_knot->unified_knot) { + free(t_knot->unified_knot); + t_knot->unified_knot = NULL; + } + return err; + } + if (t_knot->unified_knot) { + free(t_knot->unified_knot); + t_knot->unified_knot = NULL; + } + if ((err = calc_alphas(t_knot)) != GLU_NO_ERROR) { + free(tmp_ctrl); + free(t_knot->new_knot); + return err; + } + free(t_knot->new_knot); + ctrl_offset = *new_ctrl; + for (i = 0; i < (*s_n_ctrl); i++) { + if ((err = calc_new_ctrl_pts(ctrl_offset, dim, t_knot, + dim, &(tmp_ctrl[i]), + &tmp_n_control)) != GLU_NO_ERROR) { + for (--i; i <= 0; i--) + free(tmp_ctrl[i]); + free(tmp_ctrl); + free(t_knot->alpha); + return err; + } + ctrl_offset += dim * t_cnt; + } + free(t_knot->alpha); + free(*new_ctrl); + tmp_stride = dim * tmp_n_control; + if ( + (*new_ctrl = + (GLfloat *) malloc(sizeof(GLfloat) * tmp_stride * (*s_n_ctrl))) == + NULL) { + for (i = 0; i < (*s_n_ctrl); i++) + free(tmp_ctrl[i]); + free(tmp_ctrl); + return GLU_OUT_OF_MEMORY; + } + for (i = 0; i < (*s_n_ctrl); i++) { + MEMCPY(*new_ctrl + i * tmp_stride, tmp_ctrl[i], + sizeof(GLfloat) * tmp_stride); + free(tmp_ctrl[i]); + } + free(tmp_ctrl); + *t_n_ctrl = tmp_n_control; + return GLU_NO_ERROR; } /* prepare the knot information structures */ static GLenum -fill_knot_structures(GLUnurbsObj *nobj, - knot_str_type *geom_s_knot, knot_str_type *geom_t_knot, - knot_str_type *color_s_knot, knot_str_type *color_t_knot, - knot_str_type *normal_s_knot, knot_str_type *normal_t_knot, - knot_str_type *texture_s_knot, knot_str_type *texture_t_knot) +fill_knot_structures(GLUnurbsObj * nobj, + knot_str_type * geom_s_knot, knot_str_type * geom_t_knot, + knot_str_type * color_s_knot, + knot_str_type * color_t_knot, + knot_str_type * normal_s_knot, + knot_str_type * normal_t_knot, + knot_str_type * texture_s_knot, + knot_str_type * texture_t_knot) { - GLint order; - GLfloat *knot; - GLint nknots; - GLint t_min,t_max; + GLint order; + GLfloat *knot; + GLint nknots; + GLint t_min, t_max; - geom_s_knot->unified_knot=NULL; - knot=geom_s_knot->knot=nobj->surface.geom.sknot; - nknots=geom_s_knot->nknots=nobj->surface.geom.sknot_count; - order=geom_s_knot->order=nobj->surface.geom.sorder; - geom_s_knot->delta_nknots=0; - t_min=geom_s_knot->t_min=order-1; - t_max=geom_s_knot->t_max=nknots-order; - if(fabs(knot[t_min]-knot[t_max])open_at_begin=GL_TRUE; - } - else - geom_s_knot->open_at_begin=GL_FALSE; - if(fabs(knot[t_max]-knot[nknots-1])open_at_end=GL_TRUE; - } - else - geom_s_knot->open_at_end=GL_FALSE; - geom_t_knot->unified_knot=NULL; - knot=geom_t_knot->knot=nobj->surface.geom.tknot; - nknots=geom_t_knot->nknots=nobj->surface.geom.tknot_count; - order=geom_t_knot->order=nobj->surface.geom.torder; - geom_t_knot->delta_nknots=0; - t_min=geom_t_knot->t_min=order-1; - t_max=geom_t_knot->t_max=nknots-order; - if(fabs(knot[t_min]-knot[t_max])open_at_begin=GL_TRUE; - } - else - geom_t_knot->open_at_begin=GL_FALSE; - if(fabs(knot[t_max]-knot[nknots-1])open_at_end=GL_TRUE; - } - else - geom_t_knot->open_at_end=GL_FALSE; + geom_s_knot->unified_knot = NULL; + knot = geom_s_knot->knot = nobj->surface.geom.sknot; + nknots = geom_s_knot->nknots = nobj->surface.geom.sknot_count; + order = geom_s_knot->order = nobj->surface.geom.sorder; + geom_s_knot->delta_nknots = 0; + t_min = geom_s_knot->t_min = order - 1; + t_max = geom_s_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_s_knot->open_at_begin = GL_TRUE; + } + else + geom_s_knot->open_at_begin = GL_FALSE; + if (fabs(knot[t_max] - knot[nknots - 1]) < EPSILON) { + /* knot open at end */ + geom_s_knot->open_at_end = GL_TRUE; + } + else + geom_s_knot->open_at_end = GL_FALSE; + geom_t_knot->unified_knot = NULL; + knot = geom_t_knot->knot = nobj->surface.geom.tknot; + nknots = geom_t_knot->nknots = nobj->surface.geom.tknot_count; + order = geom_t_knot->order = nobj->surface.geom.torder; + geom_t_knot->delta_nknots = 0; + t_min = geom_t_knot->t_min = order - 1; + t_max = geom_t_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_t_knot->open_at_begin = GL_TRUE; + } + else + geom_t_knot->open_at_begin = GL_FALSE; + if (fabs(knot[t_max] - knot[nknots - 1]) < EPSILON) { + /* knot open at end */ + geom_t_knot->open_at_end = GL_TRUE; + } + else + geom_t_knot->open_at_end = GL_FALSE; - if(nobj->surface.color.type!=GLU_INVALID_ENUM) - { - color_s_knot->unified_knot=(GLfloat *)1; - knot=color_s_knot->knot=nobj->surface.color.sknot; - nknots=color_s_knot->nknots=nobj->surface.color.sknot_count; - order=color_s_knot->order=nobj->surface.color.sorder; - color_s_knot->delta_nknots=0; - t_min=color_s_knot->t_min=order-1; - t_max=color_s_knot->t_max=nknots-order; - if(fabs(knot[t_min]-knot[t_max])open_at_begin=GL_TRUE; - } - else - color_s_knot->open_at_begin=GL_FALSE; - if(fabs(knot[t_max]-knot[nknots-1])open_at_end=GL_TRUE; - } - else - color_s_knot->open_at_end=GL_FALSE; - color_t_knot->unified_knot=(GLfloat *)1; - knot=color_t_knot->knot=nobj->surface.color.tknot; - nknots=color_t_knot->nknots=nobj->surface.color.tknot_count; - order=color_t_knot->order=nobj->surface.color.torder; - color_t_knot->delta_nknots=0; - t_min=color_t_knot->t_min=order-1; - t_max=color_t_knot->t_max=nknots-order; - if(fabs(knot[t_min]-knot[t_max])open_at_begin=GL_TRUE; - } - else - color_t_knot->open_at_begin=GL_FALSE; - if(fabs(knot[t_max]-knot[nknots-1])open_at_end=GL_TRUE; - } - else - color_t_knot->open_at_end=GL_FALSE; - } - else - { - color_s_knot->unified_knot=NULL; - color_t_knot->unified_knot=NULL; - } + if (nobj->surface.color.type != GLU_INVALID_ENUM) { + color_s_knot->unified_knot = (GLfloat *) 1; + knot = color_s_knot->knot = nobj->surface.color.sknot; + nknots = color_s_knot->nknots = nobj->surface.color.sknot_count; + order = color_s_knot->order = nobj->surface.color.sorder; + color_s_knot->delta_nknots = 0; + t_min = color_s_knot->t_min = order - 1; + t_max = color_s_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_s_knot->open_at_begin = GL_TRUE; + } + else + color_s_knot->open_at_begin = GL_FALSE; + if (fabs(knot[t_max] - knot[nknots - 1]) < EPSILON) { + /* knot open at end */ + color_s_knot->open_at_end = GL_TRUE; + } + else + color_s_knot->open_at_end = GL_FALSE; + color_t_knot->unified_knot = (GLfloat *) 1; + knot = color_t_knot->knot = nobj->surface.color.tknot; + nknots = color_t_knot->nknots = nobj->surface.color.tknot_count; + order = color_t_knot->order = nobj->surface.color.torder; + color_t_knot->delta_nknots = 0; + t_min = color_t_knot->t_min = order - 1; + t_max = color_t_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_t_knot->open_at_begin = GL_TRUE; + } + else + color_t_knot->open_at_begin = GL_FALSE; + if (fabs(knot[t_max] - knot[nknots - 1]) < EPSILON) { + /* knot open at end */ + color_t_knot->open_at_end = GL_TRUE; + } + else + color_t_knot->open_at_end = GL_FALSE; + } + else { + color_s_knot->unified_knot = NULL; + color_t_knot->unified_knot = NULL; + } - if(nobj->surface.normal.type!=GLU_INVALID_ENUM) - { - normal_s_knot->unified_knot=(GLfloat *)1; - knot=normal_s_knot->knot=nobj->surface.normal.sknot; - nknots=normal_s_knot->nknots=nobj->surface.normal.sknot_count; - order=normal_s_knot->order=nobj->surface.normal.sorder; - normal_s_knot->delta_nknots=0; - t_min=normal_s_knot->t_min=order-1; - t_max=normal_s_knot->t_max=nknots-order; - if(fabs(knot[t_min]-knot[t_max])open_at_begin=GL_TRUE; - } - else - normal_s_knot->open_at_begin=GL_FALSE; - if(fabs(knot[t_max]-knot[nknots-1])open_at_end=GL_TRUE; - } - else - normal_s_knot->open_at_end=GL_FALSE; - normal_t_knot->unified_knot=(GLfloat *)1; - knot=normal_t_knot->knot=nobj->surface.normal.tknot; - nknots=normal_t_knot->nknots=nobj->surface.normal.tknot_count; - order=normal_t_knot->order=nobj->surface.normal.torder; - normal_t_knot->delta_nknots=0; - t_min=normal_t_knot->t_min=order-1; - t_max=normal_t_knot->t_max=nknots-order; - if(fabs(knot[t_min]-knot[t_max])open_at_begin=GL_TRUE; - } - else - normal_t_knot->open_at_begin=GL_FALSE; - if(fabs(knot[t_max]-knot[nknots-1])open_at_end=GL_TRUE; - } - else - normal_t_knot->open_at_end=GL_FALSE; - } - else - { - normal_s_knot->unified_knot=NULL; - normal_t_knot->unified_knot=NULL; - } + if (nobj->surface.normal.type != GLU_INVALID_ENUM) { + normal_s_knot->unified_knot = (GLfloat *) 1; + knot = normal_s_knot->knot = nobj->surface.normal.sknot; + nknots = normal_s_knot->nknots = nobj->surface.normal.sknot_count; + order = normal_s_knot->order = nobj->surface.normal.sorder; + normal_s_knot->delta_nknots = 0; + t_min = normal_s_knot->t_min = order - 1; + t_max = normal_s_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_s_knot->open_at_begin = GL_TRUE; + } + else + normal_s_knot->open_at_begin = GL_FALSE; + if (fabs(knot[t_max] - knot[nknots - 1]) < EPSILON) { + /* knot open at end */ + normal_s_knot->open_at_end = GL_TRUE; + } + else + normal_s_knot->open_at_end = GL_FALSE; + normal_t_knot->unified_knot = (GLfloat *) 1; + knot = normal_t_knot->knot = nobj->surface.normal.tknot; + nknots = normal_t_knot->nknots = nobj->surface.normal.tknot_count; + order = normal_t_knot->order = nobj->surface.normal.torder; + normal_t_knot->delta_nknots = 0; + t_min = normal_t_knot->t_min = order - 1; + t_max = normal_t_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_t_knot->open_at_begin = GL_TRUE; + } + else + normal_t_knot->open_at_begin = GL_FALSE; + if (fabs(knot[t_max] - knot[nknots - 1]) < EPSILON) { + /* knot open at end */ + normal_t_knot->open_at_end = GL_TRUE; + } + else + normal_t_knot->open_at_end = GL_FALSE; + } + else { + normal_s_knot->unified_knot = NULL; + normal_t_knot->unified_knot = NULL; + } - if(nobj->surface.texture.type!=GLU_INVALID_ENUM) - { - texture_s_knot->unified_knot=(GLfloat *)1; - knot=texture_s_knot->knot=nobj->surface.texture.sknot; - nknots=texture_s_knot->nknots=nobj->surface.texture.sknot_count; - order=texture_s_knot->order=nobj->surface.texture.sorder; - texture_s_knot->delta_nknots=0; - t_min=texture_s_knot->t_min=order-1; - t_max=texture_s_knot->t_max=nknots-order; - if(fabs(knot[t_min]-knot[t_max])open_at_begin=GL_TRUE; - } - else - texture_s_knot->open_at_begin=GL_FALSE; - if(fabs(knot[t_max]-knot[nknots-1])open_at_end=GL_TRUE; - } - else - texture_s_knot->open_at_end=GL_FALSE; - texture_t_knot->unified_knot=(GLfloat *)1; - knot=texture_t_knot->knot=nobj->surface.texture.tknot; - nknots=texture_t_knot->nknots=nobj->surface.texture.tknot_count; - order=texture_t_knot->order=nobj->surface.texture.torder; - texture_t_knot->delta_nknots=0; - t_min=texture_t_knot->t_min=order-1; - t_max=texture_t_knot->t_max=nknots-order; - if(fabs(knot[t_min]-knot[t_max])open_at_begin=GL_TRUE; - } - else - texture_t_knot->open_at_begin=GL_FALSE; - if(fabs(knot[t_max]-knot[nknots-1])open_at_end=GL_TRUE; - } - else - texture_t_knot->open_at_end=GL_FALSE; - } - else - { - texture_s_knot->unified_knot=NULL; - texture_t_knot->unified_knot=NULL; - } - return GLU_NO_ERROR; + if (nobj->surface.texture.type != GLU_INVALID_ENUM) { + texture_s_knot->unified_knot = (GLfloat *) 1; + knot = texture_s_knot->knot = nobj->surface.texture.sknot; + nknots = texture_s_knot->nknots = nobj->surface.texture.sknot_count; + order = texture_s_knot->order = nobj->surface.texture.sorder; + texture_s_knot->delta_nknots = 0; + t_min = texture_s_knot->t_min = order - 1; + t_max = texture_s_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_s_knot->open_at_begin = GL_TRUE; + } + else + texture_s_knot->open_at_begin = GL_FALSE; + if (fabs(knot[t_max] - knot[nknots - 1]) < EPSILON) { + /* knot open at end */ + texture_s_knot->open_at_end = GL_TRUE; + } + else + texture_s_knot->open_at_end = GL_FALSE; + texture_t_knot->unified_knot = (GLfloat *) 1; + knot = texture_t_knot->knot = nobj->surface.texture.tknot; + nknots = texture_t_knot->nknots = nobj->surface.texture.tknot_count; + order = texture_t_knot->order = nobj->surface.texture.torder; + texture_t_knot->delta_nknots = 0; + t_min = texture_t_knot->t_min = order - 1; + t_max = texture_t_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_t_knot->open_at_begin = GL_TRUE; + } + else + texture_t_knot->open_at_begin = GL_FALSE; + if (fabs(knot[t_max] - knot[nknots - 1]) < EPSILON) { + /* knot open at end */ + texture_t_knot->open_at_end = GL_TRUE; + } + else + texture_t_knot->open_at_end = GL_FALSE; + } + else { + texture_s_knot->unified_knot = NULL; + texture_t_knot->unified_knot = NULL; + } + return GLU_NO_ERROR; } -void -free_new_ctrl(new_ctrl_type *p) + +static void +free_new_ctrl(new_ctrl_type * p) { - if(p->geom_ctrl) - free(p->geom_ctrl); - if(p->geom_offsets) - free(p->geom_offsets); - if(p->color_ctrl) - { - free(p->color_ctrl); - if(p->color_offsets) - free(p->color_offsets); - } - if(p->normal_ctrl) - { - free(p->normal_ctrl); - if(p->normal_offsets) - free(p->normal_offsets); - } - if(p->texture_ctrl) - { - free(p->texture_ctrl); - if(p->texture_offsets) - free(p->texture_offsets); - } + if (p->geom_ctrl) + free(p->geom_ctrl); + if (p->geom_offsets) + free(p->geom_offsets); + if (p->color_ctrl) { + free(p->color_ctrl); + if (p->color_offsets) + free(p->color_offsets); + } + if (p->normal_ctrl) { + free(p->normal_ctrl); + if (p->normal_offsets) + free(p->normal_offsets); + } + if (p->texture_ctrl) { + free(p->texture_ctrl); + if (p->texture_offsets) + free(p->texture_offsets); + } } /* convert surfaces - geometry and possible attribute ones into equivalent */ /* sequence of adjacent Bezier patches */ static GLenum -convert_surfs(GLUnurbsObj *nobj, new_ctrl_type *new_ctrl) +convert_surfs(GLUnurbsObj * nobj, new_ctrl_type * new_ctrl) { - knot_str_type geom_s_knot,color_s_knot,normal_s_knot,texture_s_knot; - knot_str_type geom_t_knot,color_t_knot,normal_t_knot,texture_t_knot; - GLenum err; + knot_str_type geom_s_knot, color_s_knot, normal_s_knot, texture_s_knot; + knot_str_type geom_t_knot, color_t_knot, normal_t_knot, texture_t_knot; + GLenum err; - if((err=fill_knot_structures(nobj,&geom_s_knot,&geom_t_knot, - &color_s_knot,&color_t_knot,&normal_s_knot,&normal_t_knot, - &texture_s_knot,&texture_t_knot)) !=GLU_NO_ERROR) - { - return err; - } - /* unify knots - all knots should have the same working range */ - if((err=select_knot_working_range(nobj,&geom_s_knot,&color_s_knot, - &normal_s_knot,&texture_s_knot)) !=GLU_NO_ERROR) - { - call_user_error(nobj,err); - return err; - } - if((err=select_knot_working_range(nobj,&geom_t_knot,&color_t_knot, - &normal_t_knot,&texture_t_knot)) !=GLU_NO_ERROR) - { - free_unified_knots(&geom_s_knot,&color_s_knot,&normal_s_knot, - &texture_s_knot); - call_user_error(nobj,err); - return err; - } + if ((err = fill_knot_structures(nobj, &geom_s_knot, &geom_t_knot, + &color_s_knot, &color_t_knot, + &normal_s_knot, &normal_t_knot, + &texture_s_knot, + &texture_t_knot)) != GLU_NO_ERROR) { + return err; + } + /* unify knots - all knots should have the same working range */ + if ((err = select_knot_working_range(nobj, &geom_s_knot, &color_s_knot, + &normal_s_knot, + &texture_s_knot)) != GLU_NO_ERROR) { + call_user_error(nobj, err); + return err; + } + if ((err = select_knot_working_range(nobj, &geom_t_knot, &color_t_knot, + &normal_t_knot, + &texture_t_knot)) != GLU_NO_ERROR) { + free_unified_knots(&geom_s_knot, &color_s_knot, &normal_s_knot, + &texture_s_knot); + call_user_error(nobj, err); + return err; + } - /* convert the geometry surface */ - nobj->surface.geom.dim=get_surface_dim(nobj->surface.geom.type); - if((err=convert_surf(&geom_s_knot,&geom_t_knot,&(nobj->surface.geom), - &(new_ctrl->geom_ctrl),&(new_ctrl->geom_s_pt_cnt), - &(new_ctrl->geom_t_pt_cnt)))!=GLU_NO_ERROR) - { - free_unified_knots(&geom_s_knot,&color_s_knot,&normal_s_knot, - &texture_s_knot); - free_unified_knots(&geom_t_knot,&color_t_knot,&normal_t_knot, - &texture_t_knot); - call_user_error(nobj,err); - return err; - } - /* if additional attributive surfaces are given convert them as well */ - if(color_s_knot.unified_knot) - { - nobj->surface.color.dim=get_surface_dim(nobj->surface.color.type); - if((err=convert_surf(&color_s_knot,&color_t_knot,&(nobj->surface.color), - &(new_ctrl->color_ctrl),&(new_ctrl->color_s_pt_cnt), - &(new_ctrl->color_t_pt_cnt)))!=GLU_NO_ERROR) - { - free_unified_knots(&color_s_knot,&color_s_knot,&normal_s_knot, - &texture_s_knot); - free_unified_knots(&color_t_knot,&color_t_knot,&normal_t_knot, - &texture_t_knot); - free_new_ctrl(new_ctrl); - call_user_error(nobj,err); - return err; - } - } - if(normal_s_knot.unified_knot) - { - nobj->surface.normal.dim=get_surface_dim(nobj->surface.normal.type); - if((err=convert_surf(&normal_s_knot,&normal_t_knot, - &(nobj->surface.normal), - &(new_ctrl->normal_ctrl),&(new_ctrl->normal_s_pt_cnt), - &(new_ctrl->normal_t_pt_cnt)))!=GLU_NO_ERROR) - { - free_unified_knots(&normal_s_knot,&normal_s_knot,&normal_s_knot, - &texture_s_knot); - free_unified_knots(&normal_t_knot,&normal_t_knot,&normal_t_knot, - &texture_t_knot); - free_new_ctrl(new_ctrl); - call_user_error(nobj,err); - return err; - } - } - if(texture_s_knot.unified_knot) - { - nobj->surface.texture.dim=get_surface_dim(nobj->surface.texture.type); - if((err=convert_surf(&texture_s_knot,&texture_t_knot, - &(nobj->surface.texture), - &(new_ctrl->texture_ctrl),&(new_ctrl->texture_s_pt_cnt), - &(new_ctrl->texture_t_pt_cnt)))!=GLU_NO_ERROR) - { - free_unified_knots(&texture_s_knot,&texture_s_knot,&texture_s_knot, - &texture_s_knot); - free_unified_knots(&texture_t_knot,&texture_t_knot,&texture_t_knot, - &texture_t_knot); - free_new_ctrl(new_ctrl); - call_user_error(nobj,err); - return err; - } - } - return GLU_NO_ERROR; + /* convert the geometry surface */ + nobj->surface.geom.dim = get_surface_dim(nobj->surface.geom.type); + if ((err = convert_surf(&geom_s_knot, &geom_t_knot, &(nobj->surface.geom), + &(new_ctrl->geom_ctrl), &(new_ctrl->geom_s_pt_cnt), + &(new_ctrl->geom_t_pt_cnt))) != GLU_NO_ERROR) { + free_unified_knots(&geom_s_knot, &color_s_knot, &normal_s_knot, + &texture_s_knot); + free_unified_knots(&geom_t_knot, &color_t_knot, &normal_t_knot, + &texture_t_knot); + call_user_error(nobj, err); + return err; + } + /* if additional attributive surfaces are given convert them as well */ + if (color_s_knot.unified_knot) { + nobj->surface.color.dim = get_surface_dim(nobj->surface.color.type); + if ( + (err = + convert_surf(&color_s_knot, &color_t_knot, &(nobj->surface.color), + &(new_ctrl->color_ctrl), &(new_ctrl->color_s_pt_cnt), + &(new_ctrl->color_t_pt_cnt))) != GLU_NO_ERROR) { + free_unified_knots(&color_s_knot, &color_s_knot, &normal_s_knot, + &texture_s_knot); + free_unified_knots(&color_t_knot, &color_t_knot, &normal_t_knot, + &texture_t_knot); + free_new_ctrl(new_ctrl); + call_user_error(nobj, err); + return err; + } + } + if (normal_s_knot.unified_knot) { + nobj->surface.normal.dim = get_surface_dim(nobj->surface.normal.type); + if ((err = convert_surf(&normal_s_knot, &normal_t_knot, + &(nobj->surface.normal), + &(new_ctrl->normal_ctrl), + &(new_ctrl->normal_s_pt_cnt), + &(new_ctrl->normal_t_pt_cnt))) != + GLU_NO_ERROR) { + free_unified_knots(&normal_s_knot, &normal_s_knot, &normal_s_knot, + &texture_s_knot); + free_unified_knots(&normal_t_knot, &normal_t_knot, &normal_t_knot, + &texture_t_knot); + free_new_ctrl(new_ctrl); + call_user_error(nobj, err); + return err; + } + } + if (texture_s_knot.unified_knot) { + nobj->surface.texture.dim = get_surface_dim(nobj->surface.texture.type); + if ((err = convert_surf(&texture_s_knot, &texture_t_knot, + &(nobj->surface.texture), + &(new_ctrl->texture_ctrl), + &(new_ctrl->texture_s_pt_cnt), + &(new_ctrl->texture_t_pt_cnt))) != + GLU_NO_ERROR) { + free_unified_knots(&texture_s_knot, &texture_s_knot, &texture_s_knot, + &texture_s_knot); + free_unified_knots(&texture_t_knot, &texture_t_knot, &texture_t_knot, + &texture_t_knot); + free_new_ctrl(new_ctrl); + call_user_error(nobj, err); + return err; + } + } + return GLU_NO_ERROR; } /* tesselate the "boundary" Bezier edge strips */ -void -tesselate_strip_t_line(GLint top_start,GLint top_end,GLint top_z, - GLint bottom_start,GLint bottom_end,GLint bottom_z,GLint bottom_domain) +static void +tesselate_strip_t_line(GLint top_start, GLint top_end, GLint top_z, + GLint bottom_start, GLint bottom_end, GLint bottom_z, + GLint bottom_domain) { - GLint top_cnt,bottom_cnt,tri_cnt,k; - GLint direction; + GLint top_cnt, bottom_cnt, tri_cnt, k; + GLint direction; - top_cnt=top_end-top_start; - direction= (top_cnt>=0 ? 1: -1); - bottom_cnt=bottom_end-bottom_start; - glBegin(GL_LINES); - while(top_cnt) - { - if(bottom_cnt) - tri_cnt=top_cnt/bottom_cnt; - else - tri_cnt=abs(top_cnt); - for(k=0;k<=tri_cnt;k++ , top_start+=direction) - { - glEvalCoord2f((GLfloat)bottom_z/bottom_domain, - (GLfloat)bottom_start/bottom_domain); - glEvalPoint2(top_z,top_start); - } - if(bottom_cnt) - { - glEvalCoord2f((GLfloat)bottom_z/bottom_domain, - (GLfloat)bottom_start/bottom_domain); - bottom_start+=direction; - top_start-=direction; - glEvalCoord2f((GLfloat)bottom_z/bottom_domain, - (GLfloat)bottom_start/bottom_domain); - glEvalCoord2f((GLfloat)bottom_z/bottom_domain, - (GLfloat)bottom_start/bottom_domain); - glEvalPoint2(top_z,top_start); - } - top_cnt-=direction*tri_cnt; - bottom_cnt-=direction; - } - glEnd(); + top_cnt = top_end - top_start; + direction = (top_cnt >= 0 ? 1 : -1); + bottom_cnt = bottom_end - bottom_start; + glBegin(GL_LINES); + while (top_cnt) { + if (bottom_cnt) + tri_cnt = top_cnt / bottom_cnt; + else + tri_cnt = abs(top_cnt); + for (k = 0; k <= tri_cnt; k++, top_start += direction) { + glEvalCoord2f((GLfloat) bottom_z / bottom_domain, + (GLfloat) bottom_start / bottom_domain); + glEvalPoint2(top_z, top_start); + } + if (bottom_cnt) { + glEvalCoord2f((GLfloat) bottom_z / bottom_domain, + (GLfloat) bottom_start / bottom_domain); + bottom_start += direction; + top_start -= direction; + glEvalCoord2f((GLfloat) bottom_z / bottom_domain, + (GLfloat) bottom_start / bottom_domain); + glEvalCoord2f((GLfloat) bottom_z / bottom_domain, + (GLfloat) bottom_start / bottom_domain); + glEvalPoint2(top_z, top_start); + } + top_cnt -= direction * tri_cnt; + bottom_cnt -= direction; + } + glEnd(); } -void -tesselate_strip_t_fill(GLint top_start,GLint top_end,GLint top_z, - GLint bottom_start,GLint bottom_end,GLint bottom_z,GLint bottom_domain) + +static void +tesselate_strip_t_fill(GLint top_start, GLint top_end, GLint top_z, + GLint bottom_start, GLint bottom_end, GLint bottom_z, + GLint bottom_domain) { - GLint top_cnt,bottom_cnt,tri_cnt,k; - GLint direction; + GLint top_cnt, bottom_cnt, tri_cnt, k; + GLint direction; - top_cnt=top_end-top_start; - direction= (top_cnt>=0 ? 1: -1); - bottom_cnt=bottom_end-bottom_start; - while(top_cnt) - { - if(bottom_cnt) - tri_cnt=top_cnt/bottom_cnt; - else - tri_cnt=abs(top_cnt); - glBegin(GL_TRIANGLE_FAN); - glEvalCoord2f((GLfloat)bottom_z/bottom_domain, - (GLfloat)bottom_start/bottom_domain); - for(k=0;k<=tri_cnt;k++ , top_start+=direction) - glEvalPoint2(top_z,top_start); - if(bottom_cnt) - { - bottom_start+=direction; - top_start-=direction; - glEvalCoord2f((GLfloat)bottom_z/bottom_domain, - (GLfloat)bottom_start/bottom_domain); - } - glEnd(); - top_cnt-=direction*tri_cnt; - bottom_cnt-=direction; - } + top_cnt = top_end - top_start; + direction = (top_cnt >= 0 ? 1 : -1); + bottom_cnt = bottom_end - bottom_start; + while (top_cnt) { + if (bottom_cnt) + tri_cnt = top_cnt / bottom_cnt; + else + tri_cnt = abs(top_cnt); + glBegin(GL_TRIANGLE_FAN); + glEvalCoord2f((GLfloat) bottom_z / bottom_domain, + (GLfloat) bottom_start / bottom_domain); + for (k = 0; k <= tri_cnt; k++, top_start += direction) + glEvalPoint2(top_z, top_start); + if (bottom_cnt) { + bottom_start += direction; + top_start -= direction; + glEvalCoord2f((GLfloat) bottom_z / bottom_domain, + (GLfloat) bottom_start / bottom_domain); + } + glEnd(); + top_cnt -= direction * tri_cnt; + bottom_cnt -= direction; + } } -void -tesselate_strip_t(GLenum display_mode, GLint top_start, GLint top_end, - GLint top_z, GLint bottom_start, GLint bottom_end, GLint bottom_z, - GLint bottom_domain) + +static void +tesselate_strip_t(GLenum display_mode, GLint top_start, GLint top_end, + GLint top_z, GLint bottom_start, GLint bottom_end, + GLint bottom_z, GLint bottom_domain) { - if(display_mode==GL_FILL) - tesselate_strip_t_fill(top_start,top_end,top_z,bottom_start, - bottom_end,bottom_z,bottom_domain); - else - tesselate_strip_t_line(top_start,top_end,top_z,bottom_start, - bottom_end,bottom_z,bottom_domain); + if (display_mode == GL_FILL) + tesselate_strip_t_fill(top_start, top_end, top_z, bottom_start, + bottom_end, bottom_z, bottom_domain); + else + tesselate_strip_t_line(top_start, top_end, top_z, bottom_start, + bottom_end, bottom_z, bottom_domain); } - -void + +static void tesselate_strip_s_fill(GLint top_start, GLint top_end, GLint top_z, - GLint bottom_start, GLint bottom_end, GLint bottom_z, GLfloat bottom_domain) + GLint bottom_start, GLint bottom_end, GLint bottom_z, + GLfloat bottom_domain) { - GLint top_cnt,bottom_cnt,tri_cnt,k; - GLint direction; + GLint top_cnt, bottom_cnt, tri_cnt, k; + GLint direction; - top_cnt=top_end-top_start; - direction= (top_cnt>=0 ? 1: -1); - bottom_cnt=bottom_end-bottom_start; - while(top_cnt) - { - if(bottom_cnt) - tri_cnt=top_cnt/bottom_cnt; - else - tri_cnt=abs(top_cnt); - glBegin(GL_TRIANGLE_FAN); - glEvalCoord2f((GLfloat)bottom_start/bottom_domain, - (GLfloat)bottom_z/bottom_domain); - for(k=0;k<=tri_cnt;k++ , top_start+=direction) - glEvalPoint2(top_start,top_z); - if(bottom_cnt) - { - bottom_start+=direction; - top_start-=direction; - glEvalCoord2f((GLfloat)bottom_start/bottom_domain, - (GLfloat)bottom_z/bottom_domain); - } - glEnd(); - top_cnt-=direction*tri_cnt; - bottom_cnt-=direction; - } + top_cnt = top_end - top_start; + direction = (top_cnt >= 0 ? 1 : -1); + bottom_cnt = bottom_end - bottom_start; + while (top_cnt) { + if (bottom_cnt) + tri_cnt = top_cnt / bottom_cnt; + else + tri_cnt = abs(top_cnt); + glBegin(GL_TRIANGLE_FAN); + glEvalCoord2f((GLfloat) bottom_start / bottom_domain, + (GLfloat) bottom_z / bottom_domain); + for (k = 0; k <= tri_cnt; k++, top_start += direction) + glEvalPoint2(top_start, top_z); + if (bottom_cnt) { + bottom_start += direction; + top_start -= direction; + glEvalCoord2f((GLfloat) bottom_start / bottom_domain, + (GLfloat) bottom_z / bottom_domain); + } + glEnd(); + top_cnt -= direction * tri_cnt; + bottom_cnt -= direction; + } } -void + +static void tesselate_strip_s_line(GLint top_start, GLint top_end, GLint top_z, - GLint bottom_start, GLint bottom_end, GLint bottom_z, GLfloat bottom_domain) + GLint bottom_start, GLint bottom_end, GLint bottom_z, + GLfloat bottom_domain) { - GLint top_cnt,bottom_cnt,tri_cnt,k; - GLint direction; + GLint top_cnt, bottom_cnt, tri_cnt, k; + GLint direction; - top_cnt=top_end-top_start; - direction= (top_cnt>=0 ? 1: -1); - bottom_cnt=bottom_end-bottom_start; - glBegin(GL_LINES); - while(top_cnt) - { - if(bottom_cnt) - tri_cnt=top_cnt/bottom_cnt; - else - tri_cnt=abs(top_cnt); - for(k=0;k<=tri_cnt;k++ , top_start+=direction) - { - glEvalCoord2f((GLfloat)bottom_start/bottom_domain, - (GLfloat)bottom_z/bottom_domain); - glEvalPoint2(top_start,top_z); - } - if(bottom_cnt) - { - glEvalCoord2f((GLfloat)bottom_start/bottom_domain, - (GLfloat)bottom_z/bottom_domain); - bottom_start+=direction; - top_start-=direction; - glEvalCoord2f((GLfloat)bottom_start/bottom_domain, - (GLfloat)bottom_z/bottom_domain); - glEvalPoint2(top_start,top_z); - glEvalCoord2f((GLfloat)bottom_start/bottom_domain, - (GLfloat)bottom_z/bottom_domain); - } - top_cnt-=direction*tri_cnt; - bottom_cnt-=direction; - } - glEnd(); + top_cnt = top_end - top_start; + direction = (top_cnt >= 0 ? 1 : -1); + bottom_cnt = bottom_end - bottom_start; + glBegin(GL_LINES); + while (top_cnt) { + if (bottom_cnt) + tri_cnt = top_cnt / bottom_cnt; + else + tri_cnt = abs(top_cnt); + for (k = 0; k <= tri_cnt; k++, top_start += direction) { + glEvalCoord2f((GLfloat) bottom_start / bottom_domain, + (GLfloat) bottom_z / bottom_domain); + glEvalPoint2(top_start, top_z); + } + if (bottom_cnt) { + glEvalCoord2f((GLfloat) bottom_start / bottom_domain, + (GLfloat) bottom_z / bottom_domain); + bottom_start += direction; + top_start -= direction; + glEvalCoord2f((GLfloat) bottom_start / bottom_domain, + (GLfloat) bottom_z / bottom_domain); + glEvalPoint2(top_start, top_z); + glEvalCoord2f((GLfloat) bottom_start / bottom_domain, + (GLfloat) bottom_z / bottom_domain); + } + top_cnt -= direction * tri_cnt; + bottom_cnt -= direction; + } + glEnd(); } -void + +static void tesselate_strip_s(GLenum display_mode, GLint top_start, GLint top_end, - GLint top_z, GLint bottom_start, GLint bottom_end, GLint bottom_z, - GLfloat bottom_domain) + GLint top_z, GLint bottom_start, GLint bottom_end, + GLint bottom_z, GLfloat bottom_domain) { - if(display_mode==GL_FILL) - tesselate_strip_s_fill(top_start,top_end,top_z,bottom_start, - bottom_end,bottom_z,bottom_domain); - else - tesselate_strip_s_line(top_start,top_end,top_z,bottom_start, - bottom_end,bottom_z,bottom_domain); + if (display_mode == GL_FILL) + tesselate_strip_s_fill(top_start, top_end, top_z, bottom_start, + bottom_end, bottom_z, bottom_domain); + else + tesselate_strip_s_line(top_start, top_end, top_z, bottom_start, + bottom_end, bottom_z, bottom_domain); } -void +static void tesselate_bottom_left_corner(GLenum display_mode, GLfloat s_1, GLfloat t_1) { - if(display_mode==GL_FILL) - { - glBegin(GL_TRIANGLE_FAN); - glEvalPoint2(1,1); - glEvalCoord2f(s_1,0.0); - glEvalCoord2f(0.0,0.0); - glEvalCoord2f(0.0,t_1); - } - else - { - glBegin(GL_LINES); - glEvalCoord2f(0.0,0.0); - glEvalCoord2f(0.0,t_1); - glEvalCoord2f(0.0,0.0); - glEvalPoint2(1,1); - glEvalCoord2f(0.0,0.0); - glEvalCoord2f(s_1,0.0); - } - glEnd(); + if (display_mode == GL_FILL) { + glBegin(GL_TRIANGLE_FAN); + glEvalPoint2(1, 1); + glEvalCoord2f(s_1, 0.0); + glEvalCoord2f(0.0, 0.0); + glEvalCoord2f(0.0, t_1); + } + else { + glBegin(GL_LINES); + glEvalCoord2f(0.0, 0.0); + glEvalCoord2f(0.0, t_1); + glEvalCoord2f(0.0, 0.0); + glEvalPoint2(1, 1); + glEvalCoord2f(0.0, 0.0); + glEvalCoord2f(s_1, 0.0); + } + glEnd(); } -void -tesselate_bottom_right_corner(GLenum display_mode, GLint v_top,GLint v_bottom, - GLfloat s_1, GLfloat t_1) +static void +tesselate_bottom_right_corner(GLenum display_mode, GLint v_top, + GLint v_bottom, GLfloat s_1, GLfloat t_1) { - if(display_mode==GL_FILL) - { - glBegin(GL_TRIANGLE_FAN); - glEvalPoint2(1,v_top); - glEvalCoord2f(0.0,v_bottom*t_1); - glEvalCoord2f(0.0,(v_bottom+1)*t_1); - glEvalCoord2f(s_1,(v_bottom+1)*t_1); - } - else - { - glBegin(GL_LINES); - glEvalCoord2f(0.0,(v_bottom+1)*t_1); - glEvalPoint2(1,v_top); - glEvalCoord2f(0.0,(v_bottom+1)*t_1); - glEvalCoord2f(0.0,v_bottom*t_1); - glEvalCoord2f(0.0,(v_bottom+1)*t_1); - glEvalCoord2f(s_1,(v_bottom+1)*t_1); - } - glEnd(); + if (display_mode == GL_FILL) { + glBegin(GL_TRIANGLE_FAN); + glEvalPoint2(1, v_top); + glEvalCoord2f(0.0, v_bottom * t_1); + glEvalCoord2f(0.0, (v_bottom + 1) * t_1); + glEvalCoord2f(s_1, (v_bottom + 1) * t_1); + } + else { + glBegin(GL_LINES); + glEvalCoord2f(0.0, (v_bottom + 1) * t_1); + glEvalPoint2(1, v_top); + glEvalCoord2f(0.0, (v_bottom + 1) * t_1); + glEvalCoord2f(0.0, v_bottom * t_1); + glEvalCoord2f(0.0, (v_bottom + 1) * t_1); + glEvalCoord2f(s_1, (v_bottom + 1) * t_1); + } + glEnd(); } -void +static void tesselate_top_left_corner(GLenum display_mode, GLint u_right, GLint u_left, - GLfloat s_1, GLfloat t_1) + GLfloat s_1, GLfloat t_1) { - if(display_mode==GL_FILL) - { - glBegin(GL_TRIANGLE_FAN); - glEvalPoint2(u_right,1); - glEvalCoord2f((u_left+1)*s_1,t_1); - glEvalCoord2f((u_left+1)*s_1,0.0); - glEvalCoord2f(u_left*s_1,0.0); - } - else - { - glBegin(GL_LINES); - glEvalCoord2f((u_left+1)*s_1,0.0); - glEvalPoint2(u_right,1); - glEvalCoord2f((u_left+1)*s_1,0.0); - glEvalCoord2f(u_left*s_1,0.0); - glEvalCoord2f((u_left+1)*s_1,0.0); - glEvalCoord2f((u_left+1)*s_1,t_1); - } - glEnd(); + if (display_mode == GL_FILL) { + glBegin(GL_TRIANGLE_FAN); + glEvalPoint2(u_right, 1); + glEvalCoord2f((u_left + 1) * s_1, t_1); + glEvalCoord2f((u_left + 1) * s_1, 0.0); + glEvalCoord2f(u_left * s_1, 0.0); + } + else { + glBegin(GL_LINES); + glEvalCoord2f((u_left + 1) * s_1, 0.0); + glEvalPoint2(u_right, 1); + glEvalCoord2f((u_left + 1) * s_1, 0.0); + glEvalCoord2f(u_left * s_1, 0.0); + glEvalCoord2f((u_left + 1) * s_1, 0.0); + glEvalCoord2f((u_left + 1) * s_1, t_1); + } + glEnd(); } -void +static void tesselate_top_right_corner(GLenum display_mode, GLint u_left, GLint v_bottom, - GLint u_right, GLint v_top, GLfloat s_1, GLfloat t_1) + GLint u_right, GLint v_top, GLfloat s_1, + GLfloat t_1) { - if(display_mode==GL_FILL) - { - glBegin(GL_TRIANGLE_FAN); - glEvalPoint2(u_left,v_bottom); - glEvalCoord2f((u_right-1)*s_1,v_top*t_1); - glEvalCoord2f(u_right*s_1,v_top*t_1); - glEvalCoord2f(u_right*s_1,(v_top-1)*t_1); - } - else - { - glBegin(GL_LINES); - glEvalCoord2f(u_right*s_1,v_top*t_1); - glEvalPoint2(u_left,v_bottom); - glEvalCoord2f(u_right*s_1,v_top*t_1); - glEvalCoord2f(u_right*s_1,(v_top-1)*t_1); - glEvalCoord2f(u_right*s_1,v_top*t_1); - glEvalCoord2f((u_right-1)*s_1,v_top*t_1); - } - glEnd(); + if (display_mode == GL_FILL) { + glBegin(GL_TRIANGLE_FAN); + glEvalPoint2(u_left, v_bottom); + glEvalCoord2f((u_right - 1) * s_1, v_top * t_1); + glEvalCoord2f(u_right * s_1, v_top * t_1); + glEvalCoord2f(u_right * s_1, (v_top - 1) * t_1); + } + else { + glBegin(GL_LINES); + glEvalCoord2f(u_right * s_1, v_top * t_1); + glEvalPoint2(u_left, v_bottom); + glEvalCoord2f(u_right * s_1, v_top * t_1); + glEvalCoord2f(u_right * s_1, (v_top - 1) * t_1); + glEvalCoord2f(u_right * s_1, v_top * t_1); + glEvalCoord2f((u_right - 1) * s_1, v_top * t_1); + } + glEnd(); } /* do mesh mapping of Bezier */ static void -nurbs_map_bezier(GLenum display_mode,GLint *sfactors,GLint *tfactors, - GLint s_bezier_cnt, GLint t_bezier_cnt, GLint s, GLint t) +nurbs_map_bezier(GLenum display_mode, GLint * sfactors, GLint * tfactors, + GLint s_bezier_cnt, GLint t_bezier_cnt, GLint s, GLint t) { - GLint top,bottom,right,left; + GLint top, bottom, right, left; - if(s==0) - { - top=*(tfactors+t*3); - bottom=*(tfactors+t*3+1); - } - else - if(s==s_bezier_cnt-1) - { - top=*(tfactors+t*3+2); - bottom=*(tfactors+t*3); - } - else - { - top=bottom=*(tfactors+t*3); - } - if(t==0) - { - left=*(sfactors+s*3+1); - right=*(sfactors+s*3); - } - else - if(t==t_bezier_cnt-1) - { - left=*(sfactors+s*3); - right=*(sfactors+s*3+2); - } - else - { - left=right=*(sfactors+s*3); - } + if (s == 0) { + top = *(tfactors + t * 3); + bottom = *(tfactors + t * 3 + 1); + } + else if (s == s_bezier_cnt - 1) { + top = *(tfactors + t * 3 + 2); + bottom = *(tfactors + t * 3); + } + else { + top = bottom = *(tfactors + t * 3); + } + if (t == 0) { + left = *(sfactors + s * 3 + 1); + right = *(sfactors + s * 3); + } + else if (t == t_bezier_cnt - 1) { + left = *(sfactors + s * 3); + right = *(sfactors + s * 3 + 2); + } + else { + left = right = *(sfactors + s * 3); + } - if(top>bottom) - { - if(left bottom) { + if (left < right) { + glMapGrid2f(right, 0.0, 1.0, top, 0.0, 1.0); + glEvalMesh2(display_mode, 1, right, 1, top); + tesselate_strip_s(display_mode, 1, right, 1, 1, left, 0, + (GLfloat) left); + tesselate_bottom_left_corner(display_mode, (GLfloat) (1.0 / left), + (GLfloat) (1.0 / bottom)); /* tesselate_strip_t(display_mode,1,top,1,1,bottom,0,(GLfloat)bottom);*/ - tesselate_strip_t(display_mode,top,1,1,bottom,1,0,(GLfloat)bottom); - } - else - if(left==right) - { - glMapGrid2f(right, 0.0, 1.0, top, 0.0, 1.0); - glEvalMesh2(display_mode,1,right, 0, top); + tesselate_strip_t(display_mode, top, 1, 1, bottom, 1, 0, + (GLfloat) bottom); + } + else if (left == right) { + glMapGrid2f(right, 0.0, 1.0, top, 0.0, 1.0); + glEvalMesh2(display_mode, 1, right, 0, top); /* tesselate_strip_t(display_mode,0,top,1,0,bottom,0,(GLfloat)bottom);*/ - tesselate_strip_t(display_mode,top,0,1,bottom,0,0,(GLfloat)bottom); - } - else - { - glMapGrid2f(left, 0.0, 1.0, top, 0.0, 1.0); - glEvalMesh2(display_mode,1,left, 0, top-1); + tesselate_strip_t(display_mode, top, 0, 1, bottom, 0, 0, + (GLfloat) bottom); + } + else { + glMapGrid2f(left, 0.0, 1.0, top, 0.0, 1.0); + glEvalMesh2(display_mode, 1, left, 0, top - 1); /* tesselate_strip_t(display_mode,0,top-1,1,0,bottom-1,0, (GLfloat)bottom);*/ - tesselate_strip_t(display_mode,top-1,0,1,bottom-1,0,0, - (GLfloat)bottom); - tesselate_bottom_right_corner(display_mode,top-1,bottom-1, - (GLfloat)(1.0/right),(GLfloat)(1.0/bottom)); + tesselate_strip_t(display_mode, top - 1, 0, 1, bottom - 1, 0, 0, + (GLfloat) bottom); + tesselate_bottom_right_corner(display_mode, top - 1, bottom - 1, + (GLfloat) (1.0 / right), + (GLfloat) (1.0 / bottom)); /* tesselate_strip_s(display_mode,1,left,top-1,1,right,right, (GLfloat)right);*/ - tesselate_strip_s(display_mode,left,1,top-1,right,1,right, - (GLfloat)right); - } - } - else - if(top==bottom) - { - if(leftt_bezier_cnt; - s_bezier_cnt=new_ctrl->s_bezier_cnt; - glEnable(nobj->surface.geom.type); - if(new_ctrl->color_ctrl) - { - glEnable(nobj->surface.color.type); - do_color=GL_TRUE; - } - else - do_color=GL_FALSE; - if(new_ctrl->normal_ctrl) - { - glEnable(nobj->surface.normal.type); - do_normal=GL_TRUE; - } - else - do_normal=GL_FALSE; - if(new_ctrl->texture_ctrl) - { - glEnable(nobj->surface.texture.type); - do_texture=GL_TRUE; - } - else - do_texture=GL_FALSE; - for(j=0; jgeom_offsets + offset), - nobj->surface.geom.sorder,nobj->surface.geom.torder, - new_ctrl->geom_s_stride,new_ctrl->geom_t_stride, - nobj->surface.geom.dim)) - continue; - glMap2f(nobj->surface.geom.type,0.0,1.0,new_ctrl->geom_s_stride, - nobj->surface.geom.sorder,0.0,1.0,new_ctrl->geom_t_stride, - nobj->surface.geom.torder,*(new_ctrl->geom_offsets + offset)); - if(do_color) - { - glMap2f(nobj->surface.color.type,0.0,1.0, - new_ctrl->color_s_stride,nobj->surface.color.sorder, - 0.0,1.0,new_ctrl->color_t_stride,nobj->surface.color.torder, - *(new_ctrl->color_offsets + offset)); - } - if(do_normal) - { - glMap2f(nobj->surface.normal.type,0.0,1.0, - new_ctrl->normal_s_stride,nobj->surface.normal.sorder, - 0.0,1.0,new_ctrl->normal_t_stride, - nobj->surface.normal.torder, - *(new_ctrl->normal_offsets+offset)); - } - if(do_texture) - { - glMap2f(nobj->surface.texture.type,0.0,1.0, - new_ctrl->texture_s_stride,nobj->surface.texture.sorder, - 0.0,1.0,new_ctrl->texture_t_stride, - nobj->surface.texture.torder, - *(new_ctrl->texture_offsets+offset)); - } + t_bezier_cnt = new_ctrl->t_bezier_cnt; + s_bezier_cnt = new_ctrl->s_bezier_cnt; + glEnable(nobj->surface.geom.type); + if (new_ctrl->color_ctrl) { + glEnable(nobj->surface.color.type); + do_color = GL_TRUE; + } + else + do_color = GL_FALSE; + if (new_ctrl->normal_ctrl) { + glEnable(nobj->surface.normal.type); + do_normal = GL_TRUE; + } + else + do_normal = GL_FALSE; + if (new_ctrl->texture_ctrl) { + glEnable(nobj->surface.texture.type); + do_texture = GL_TRUE; + } + else + do_texture = GL_FALSE; + for (j = 0; j < s_bezier_cnt; j++) { + for (i = 0; i < t_bezier_cnt; i++) { + offset = j * t_bezier_cnt + i; + if (fine_culling_test_3D(nobj, *(new_ctrl->geom_offsets + offset), + nobj->surface.geom.sorder, + nobj->surface.geom.torder, + new_ctrl->geom_s_stride, + new_ctrl->geom_t_stride, + nobj->surface.geom.dim)) continue; + glMap2f(nobj->surface.geom.type, 0.0, 1.0, new_ctrl->geom_s_stride, + nobj->surface.geom.sorder, 0.0, 1.0, new_ctrl->geom_t_stride, + nobj->surface.geom.torder, + *(new_ctrl->geom_offsets + offset)); + if (do_color) { + glMap2f(nobj->surface.color.type, 0.0, 1.0, + new_ctrl->color_s_stride, nobj->surface.color.sorder, + 0.0, 1.0, new_ctrl->color_t_stride, + nobj->surface.color.torder, + *(new_ctrl->color_offsets + offset)); + } + if (do_normal) { + glMap2f(nobj->surface.normal.type, 0.0, 1.0, + new_ctrl->normal_s_stride, nobj->surface.normal.sorder, + 0.0, 1.0, new_ctrl->normal_t_stride, + nobj->surface.normal.torder, + *(new_ctrl->normal_offsets + offset)); + } + if (do_texture) { + glMap2f(nobj->surface.texture.type, 0.0, 1.0, + new_ctrl->texture_s_stride, nobj->surface.texture.sorder, + 0.0, 1.0, new_ctrl->texture_t_stride, + nobj->surface.texture.torder, + *(new_ctrl->texture_offsets + offset)); + } /* glMapGrid2f(sfactors[j*3+0],0.0,1.0,tfactors[i*3+0],0.0,1.0); glEvalMesh2(display_mode,0,sfactors[j*3+0],0,tfactors[i*3+0]);*/ - nurbs_map_bezier(display_mode,sfactors,tfactors,s_bezier_cnt, - t_bezier_cnt,j,i); - } - } + nurbs_map_bezier(display_mode, sfactors, tfactors, s_bezier_cnt, + t_bezier_cnt, j, i); + } + } } @@ -1190,233 +1090,229 @@ draw_polygon_mode( GLenum display_mode, GLUnurbsObj *nobj, /* draw NURBS surface in OUTLINE POLYGON mode */ #if 0 static void -draw_patch_mode( GLenum display_mode, GLUnurbsObj *nobj, - new_ctrl_type *new_ctrl, GLint *sfactors, GLint *tfactors ) +draw_patch_mode(GLenum display_mode, GLUnurbsObj * nobj, + new_ctrl_type * new_ctrl, GLint * sfactors, GLint * tfactors) { - GLsizei offset; - GLint t_bezier_cnt,s_bezier_cnt; - GLboolean do_color,do_normal,do_texture; - GLint i,j; + GLsizei offset; + GLint t_bezier_cnt, s_bezier_cnt; + GLboolean do_color, do_normal, do_texture; + GLint i, j; - t_bezier_cnt=new_ctrl->t_bezier_cnt; - s_bezier_cnt=new_ctrl->s_bezier_cnt; - glEnable(nobj->surface.geom.type); - if(new_ctrl->color_ctrl) - { - glEnable(nobj->surface.color.type); - do_color=GL_TRUE; - } - else - do_color=GL_FALSE; - if(new_ctrl->normal_ctrl) - { - glEnable(nobj->surface.normal.type); - do_normal=GL_TRUE; - } - else - do_normal=GL_FALSE; - if(new_ctrl->texture_ctrl) - { - glEnable(nobj->surface.texture.type); - do_texture=GL_TRUE; - } - else - do_texture=GL_FALSE; - for(j=0; jgeom_offsets + offset), - nobj->surface.geom.sorder,nobj->surface.geom.torder, - new_ctrl->geom_s_stride,new_ctrl->geom_t_stride, - nobj->surface.geom.dim)) - continue; - glMap2f(nobj->surface.geom.type,0.0,1.0,new_ctrl->geom_s_stride, - nobj->surface.geom.sorder,0.0,1.0,new_ctrl->geom_t_stride, - nobj->surface.geom.torder,*(new_ctrl->geom_offsets + offset)); - if(do_color) - { - glMap2f(nobj->surface.color.type,0.0,1.0, - new_ctrl->color_s_stride,nobj->surface.color.sorder, - 0.0,1.0,new_ctrl->color_t_stride,nobj->surface.color.torder, - *(new_ctrl->color_offsets + offset)); - } - if(do_normal) - { - glMap2f(nobj->surface.normal.type,0.0,1.0, - new_ctrl->normal_s_stride,nobj->surface.normal.sorder, - 0.0,1.0,new_ctrl->normal_t_stride, - nobj->surface.normal.torder, - *(new_ctrl->normal_offsets+offset)); - } - if(do_texture) - { - glMap2f(nobj->surface.texture.type,0.0,1.0, - new_ctrl->texture_s_stride,nobj->surface.texture.sorder, - 0.0,1.0,new_ctrl->texture_t_stride, - nobj->surface.texture.torder, - *(new_ctrl->texture_offsets+offset)); - } - nurbs_map_bezier(display_mode,sfactors,tfactors,s_bezier_cnt, - t_bezier_cnt,i,j); + t_bezier_cnt = new_ctrl->t_bezier_cnt; + s_bezier_cnt = new_ctrl->s_bezier_cnt; + glEnable(nobj->surface.geom.type); + if (new_ctrl->color_ctrl) { + glEnable(nobj->surface.color.type); + do_color = GL_TRUE; + } + else + do_color = GL_FALSE; + if (new_ctrl->normal_ctrl) { + glEnable(nobj->surface.normal.type); + do_normal = GL_TRUE; + } + else + do_normal = GL_FALSE; + if (new_ctrl->texture_ctrl) { + glEnable(nobj->surface.texture.type); + do_texture = GL_TRUE; + } + else + do_texture = GL_FALSE; + for (j = 0; j < s_bezier_cnt; j++) { + for (i = 0; i < t_bezier_cnt; i++) { + offset = j * t_bezier_cnt + i; + if (fine_culling_test_3D(nobj, *(new_ctrl->geom_offsets + offset), + nobj->surface.geom.sorder, + nobj->surface.geom.torder, + new_ctrl->geom_s_stride, + new_ctrl->geom_t_stride, + nobj->surface.geom.dim)) continue; + glMap2f(nobj->surface.geom.type, 0.0, 1.0, new_ctrl->geom_s_stride, + nobj->surface.geom.sorder, 0.0, 1.0, new_ctrl->geom_t_stride, + nobj->surface.geom.torder, + *(new_ctrl->geom_offsets + offset)); + if (do_color) { + glMap2f(nobj->surface.color.type, 0.0, 1.0, + new_ctrl->color_s_stride, nobj->surface.color.sorder, + 0.0, 1.0, new_ctrl->color_t_stride, + nobj->surface.color.torder, + *(new_ctrl->color_offsets + offset)); + } + if (do_normal) { + glMap2f(nobj->surface.normal.type, 0.0, 1.0, + new_ctrl->normal_s_stride, nobj->surface.normal.sorder, + 0.0, 1.0, new_ctrl->normal_t_stride, + nobj->surface.normal.torder, + *(new_ctrl->normal_offsets + offset)); + } + if (do_texture) { + glMap2f(nobj->surface.texture.type, 0.0, 1.0, + new_ctrl->texture_s_stride, nobj->surface.texture.sorder, + 0.0, 1.0, new_ctrl->texture_t_stride, + nobj->surface.texture.torder, + *(new_ctrl->texture_offsets + offset)); + } + nurbs_map_bezier(display_mode, sfactors, tfactors, s_bezier_cnt, + t_bezier_cnt, i, j); /* glMapGrid2f(sfactors[j],0.0,1.0,tfactors[i],0.0,1.0); glEvalMesh2(display_mode,0,sfactors[j],0,tfactors[i]);*/ - } - } + } + } } #endif -void -init_new_ctrl(new_ctrl_type *p) +static void +init_new_ctrl(new_ctrl_type * p) { - p->geom_ctrl=p->color_ctrl=p->normal_ctrl=p->texture_ctrl=NULL; - p->geom_offsets=p->color_offsets=p->normal_offsets=p->texture_offsets=NULL; - p->s_bezier_cnt=p->t_bezier_cnt=0; + p->geom_ctrl = p->color_ctrl = p->normal_ctrl = p->texture_ctrl = NULL; + p->geom_offsets = p->color_offsets = p->normal_offsets = + p->texture_offsets = NULL; + p->s_bezier_cnt = p->t_bezier_cnt = 0; } -GLenum -augment_new_ctrl(GLUnurbsObj *nobj, new_ctrl_type *p) + +static GLenum +augment_new_ctrl(GLUnurbsObj * nobj, new_ctrl_type * p) { - GLsizei offset_size; - GLint i,j; + GLsizei offset_size; + GLint i, j; - p->s_bezier_cnt=(p->geom_s_pt_cnt)/(nobj->surface.geom.sorder); - p->t_bezier_cnt=(p->geom_t_pt_cnt)/(nobj->surface.geom.torder); - offset_size=(p->s_bezier_cnt)*(p->t_bezier_cnt); - p->geom_t_stride=nobj->surface.geom.dim; - p->geom_s_stride=(p->geom_t_pt_cnt)*(nobj->surface.geom.dim); - p->color_t_stride=nobj->surface.color.dim; - p->color_s_stride=(p->color_t_pt_cnt)*(nobj->surface.color.dim); - p->normal_t_stride=nobj->surface.normal.dim; - p->normal_s_stride=(p->normal_t_pt_cnt)*(nobj->surface.normal.dim); - p->texture_t_stride=nobj->surface.texture.dim; - p->texture_s_stride=(p->texture_t_pt_cnt)*(nobj->surface.texture.dim); - if((p->geom_offsets=(GLfloat **)malloc(sizeof(GLfloat *)*offset_size))==NULL) - { - call_user_error(nobj,GLU_OUT_OF_MEMORY); - return GLU_ERROR; - } - if(p->color_ctrl) - if((p->color_offsets=(GLfloat **)malloc(sizeof(GLfloat *)*offset_size))==NULL) - { - free_new_ctrl(p); - call_user_error(nobj,GLU_OUT_OF_MEMORY); - return GLU_ERROR; - } - if(p->normal_ctrl) - if((p->normal_offsets=(GLfloat **)malloc(sizeof(GLfloat *)*offset_size))==NULL) - { - free_new_ctrl(p); - call_user_error(nobj,GLU_OUT_OF_MEMORY); - return GLU_ERROR; - } - if(p->texture_ctrl) - if((p->texture_offsets=(GLfloat **)malloc(sizeof(GLfloat *)*offset_size))==NULL) - { - free_new_ctrl(p); - call_user_error(nobj,GLU_OUT_OF_MEMORY); - return GLU_ERROR; - } - for(i=0;is_bezier_cnt;i++) - for(j=0;jt_bezier_cnt;j++) - *(p->geom_offsets + i*(p->t_bezier_cnt) + j) = - p->geom_ctrl + i*(nobj->surface.geom.sorder)* - (nobj->surface.geom.dim)*(p->geom_t_pt_cnt) + - j*(nobj->surface.geom.dim)*(nobj->surface.geom.torder); - if(p->color_ctrl) - for(i=0;is_bezier_cnt;i++) - for(j=0;jt_bezier_cnt;j++) - *(p->color_offsets + i*(p->t_bezier_cnt) + j) = - p->color_ctrl + i*(nobj->surface.color.sorder)* - (nobj->surface.color.dim)*(p->color_t_pt_cnt) + - j*(nobj->surface.color.dim)*(nobj->surface.color.torder); - if(p->normal_ctrl) - for(i=0;is_bezier_cnt;i++) - for(j=0;jt_bezier_cnt;j++) - *(p->normal_offsets + i*(p->t_bezier_cnt) + j) = - p->normal_ctrl + i*(nobj->surface.normal.sorder)* - (nobj->surface.normal.dim)*(p->normal_t_pt_cnt) + - j*(nobj->surface.normal.dim)*(nobj->surface.normal.torder); - if(p->texture_ctrl) - for(i=0;is_bezier_cnt;i++) - for(j=0;jt_bezier_cnt;j++) - *(p->texture_offsets + i*(p->t_bezier_cnt) + j) = - p->texture_ctrl + i*(nobj->surface.texture.sorder)* - (nobj->surface.texture.dim)*(p->texture_t_pt_cnt) + - j*(nobj->surface.texture.dim)*(nobj->surface.texture.torder); - return GLU_NO_ERROR; + p->s_bezier_cnt = (p->geom_s_pt_cnt) / (nobj->surface.geom.sorder); + p->t_bezier_cnt = (p->geom_t_pt_cnt) / (nobj->surface.geom.torder); + offset_size = (p->s_bezier_cnt) * (p->t_bezier_cnt); + p->geom_t_stride = nobj->surface.geom.dim; + p->geom_s_stride = (p->geom_t_pt_cnt) * (nobj->surface.geom.dim); + p->color_t_stride = nobj->surface.color.dim; + p->color_s_stride = (p->color_t_pt_cnt) * (nobj->surface.color.dim); + p->normal_t_stride = nobj->surface.normal.dim; + p->normal_s_stride = (p->normal_t_pt_cnt) * (nobj->surface.normal.dim); + p->texture_t_stride = nobj->surface.texture.dim; + p->texture_s_stride = (p->texture_t_pt_cnt) * (nobj->surface.texture.dim); + if ( + (p->geom_offsets = + (GLfloat **) malloc(sizeof(GLfloat *) * offset_size)) == NULL) { + call_user_error(nobj, GLU_OUT_OF_MEMORY); + return GLU_ERROR; + } + if (p->color_ctrl) + if ( + (p->color_offsets = + (GLfloat **) malloc(sizeof(GLfloat *) * offset_size)) == NULL) { + free_new_ctrl(p); + call_user_error(nobj, GLU_OUT_OF_MEMORY); + return GLU_ERROR; + } + if (p->normal_ctrl) + if ( + (p->normal_offsets = + (GLfloat **) malloc(sizeof(GLfloat *) * offset_size)) == NULL) { + free_new_ctrl(p); + call_user_error(nobj, GLU_OUT_OF_MEMORY); + return GLU_ERROR; + } + if (p->texture_ctrl) + if ( + (p->texture_offsets = + (GLfloat **) malloc(sizeof(GLfloat *) * offset_size)) == NULL) { + free_new_ctrl(p); + call_user_error(nobj, GLU_OUT_OF_MEMORY); + return GLU_ERROR; + } + for (i = 0; i < p->s_bezier_cnt; i++) + for (j = 0; j < p->t_bezier_cnt; j++) + *(p->geom_offsets + i * (p->t_bezier_cnt) + j) = + p->geom_ctrl + i * (nobj->surface.geom.sorder) * + (nobj->surface.geom.dim) * (p->geom_t_pt_cnt) + + j * (nobj->surface.geom.dim) * (nobj->surface.geom.torder); + if (p->color_ctrl) + for (i = 0; i < p->s_bezier_cnt; i++) + for (j = 0; j < p->t_bezier_cnt; j++) + *(p->color_offsets + i * (p->t_bezier_cnt) + j) = + p->color_ctrl + i * (nobj->surface.color.sorder) * + (nobj->surface.color.dim) * (p->color_t_pt_cnt) + + j * (nobj->surface.color.dim) * (nobj->surface.color.torder); + if (p->normal_ctrl) + for (i = 0; i < p->s_bezier_cnt; i++) + for (j = 0; j < p->t_bezier_cnt; j++) + *(p->normal_offsets + i * (p->t_bezier_cnt) + j) = + p->normal_ctrl + i * (nobj->surface.normal.sorder) * + (nobj->surface.normal.dim) * (p->normal_t_pt_cnt) + + j * (nobj->surface.normal.dim) * (nobj->surface.normal.torder); + if (p->texture_ctrl) + for (i = 0; i < p->s_bezier_cnt; i++) + for (j = 0; j < p->t_bezier_cnt; j++) + *(p->texture_offsets + i * (p->t_bezier_cnt) + j) = + p->texture_ctrl + i * (nobj->surface.texture.sorder) * + (nobj->surface.texture.dim) * (p->texture_t_pt_cnt) + + j * (nobj->surface.texture.dim) * + (nobj->surface.texture.torder); + return GLU_NO_ERROR; } /* main NURBS surface procedure */ void -do_nurbs_surface( GLUnurbsObj *nobj ) +do_nurbs_surface(GLUnurbsObj * nobj) { - GLint *sfactors,*tfactors; - new_ctrl_type new_ctrl; + GLint *sfactors, *tfactors; + new_ctrl_type new_ctrl; - /* test user supplied data */ - if(test_nurbs_surfaces(nobj)!=GLU_NO_ERROR) - return; + /* test user supplied data */ + if (test_nurbs_surfaces(nobj) != GLU_NO_ERROR) + return; - init_new_ctrl(&new_ctrl); + init_new_ctrl(&new_ctrl); - if(convert_surfs(nobj,&new_ctrl)!=GLU_NO_ERROR) - return; - if(augment_new_ctrl(nobj,&new_ctrl)!=GLU_NO_ERROR) - return; - switch(nobj->sampling_method) - { - case GLU_PATH_LENGTH: - if(glu_do_sampling_3D(nobj,&new_ctrl,&sfactors,&tfactors)!= - GLU_NO_ERROR) - { - free_new_ctrl(&new_ctrl); - return; - } - break; - case GLU_DOMAIN_DISTANCE: - if(glu_do_sampling_uv(nobj,&new_ctrl,&sfactors,&tfactors)!= - GLU_NO_ERROR) - { - free_new_ctrl(&new_ctrl); - return; - } - break; - case GLU_PARAMETRIC_ERROR: - if(glu_do_sampling_param_3D(nobj,&new_ctrl,&sfactors,&tfactors)!= - GLU_NO_ERROR) - { - free_new_ctrl(&new_ctrl); - return; - } - break; - default: - abort(); - } - glFrontFace(GL_CW); - switch(nobj->display_mode) - { - case GLU_FILL: + if (convert_surfs(nobj, &new_ctrl) != GLU_NO_ERROR) + return; + if (augment_new_ctrl(nobj, &new_ctrl) != GLU_NO_ERROR) + return; + switch (nobj->sampling_method) { + case GLU_PATH_LENGTH: + if (glu_do_sampling_3D(nobj, &new_ctrl, &sfactors, &tfactors) != + GLU_NO_ERROR) { + free_new_ctrl(&new_ctrl); + return; + } + break; + case GLU_DOMAIN_DISTANCE: + if (glu_do_sampling_uv(nobj, &new_ctrl, &sfactors, &tfactors) != + GLU_NO_ERROR) { + free_new_ctrl(&new_ctrl); + return; + } + break; + case GLU_PARAMETRIC_ERROR: + if (glu_do_sampling_param_3D(nobj, &new_ctrl, &sfactors, &tfactors) != + GLU_NO_ERROR) { + free_new_ctrl(&new_ctrl); + return; + } + break; + default: + abort(); + } + glFrontFace(GL_CW); + switch (nobj->display_mode) { + case GLU_FILL: /* if(polygon_trimming(nobj,&new_ctrl,sfactors,tfactors)==GLU_NO_ERROR)*/ - draw_polygon_mode(GL_FILL,nobj,&new_ctrl,sfactors,tfactors); - break; - case GLU_OUTLINE_POLYGON: - /* TODO - missing trimming handeling */ + draw_polygon_mode(GL_FILL, nobj, &new_ctrl, sfactors, tfactors); + break; + case GLU_OUTLINE_POLYGON: + /* TODO - missing trimming handeling */ /* just for now - no OUTLINE_PATCH mode draw_patch_mode(GL_LINE,nobj,&new_ctrl,sfactors,tfactors); break; */ - case GLU_OUTLINE_PATCH: + case GLU_OUTLINE_PATCH: /* if(polygon_trimming(nobj,&new_ctrl,sfactors,tfactors)==GLU_NO_ERROR)*/ - draw_polygon_mode(GL_LINE,nobj,&new_ctrl,sfactors,tfactors); - break; - default: - abort(); /* TODO: is this OK? */ - } - free(sfactors); - free(tfactors); - free_new_ctrl(&new_ctrl); + draw_polygon_mode(GL_LINE, nobj, &new_ctrl, sfactors, tfactors); + break; + default: + abort(); /* TODO: is this OK? */ + } + free(sfactors); + free(tfactors); + free_new_ctrl(&new_ctrl); } - diff --git a/src/glu/mesa/nurbsutl.c b/src/glu/mesa/nurbsutl.c index f0f166cb647..b28825858e7 100644 --- a/src/glu/mesa/nurbsutl.c +++ b/src/glu/mesa/nurbsutl.c @@ -1,9 +1,9 @@ -/* $Id: nurbsutl.c,v 1.1 1999/08/19 00:55:42 jtg Exp $ */ +/* $Id: nurbsutl.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,38 +21,6 @@ */ -/* - * $Log: nurbsutl.c,v $ - * Revision 1.1 1999/08/19 00:55:42 jtg - * Initial revision - * - * Revision 1.8 1999/06/08 00:44:51 brianp - * OpenStep updates (pete@ohm.york.ac.uk) - * - * Revision 1.7 1998/07/26 02:07:59 brianp - * updated for Windows compilation per Ted Jump - * - * Revision 1.6 1997/10/29 02:02:20 brianp - * various MS Windows compiler changes (David Bucciarelli, v20 3dfx driver) - * - * 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/05/27 03:19:54 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. @@ -69,562 +37,516 @@ #endif -GLenum -test_knot(GLint nknots, GLfloat *knot, GLint order) +GLenum test_knot(GLint nknots, GLfloat * knot, GLint order) { - GLsizei i; - GLint knot_mult; - GLfloat tmp_knot; - - tmp_knot=knot[0]; - knot_mult=1; - for(i=1;i EPSILON) - { - if(knot_mult>order) - return GLU_NURBS_ERROR5; - knot_mult=1; - tmp_knot=knot[i]; - } - else - ++knot_mult; - } - return GLU_NO_ERROR; + GLsizei i; + GLint knot_mult; + GLfloat tmp_knot; + + tmp_knot = knot[0]; + knot_mult = 1; + for (i = 1; i < nknots; i++) { + if (knot[i] < tmp_knot) + return GLU_NURBS_ERROR4; + if (fabs(tmp_knot - knot[i]) > EPSILON) { + if (knot_mult > order) + return GLU_NURBS_ERROR5; + knot_mult = 1; + tmp_knot = knot[i]; + } + else + ++knot_mult; + } + return GLU_NO_ERROR; } static int /* qsort function */ #if defined(WIN32) && !defined(OPENSTEP) -__cdecl + __cdecl #endif knot_sort(const void *a, const void *b) { - GLfloat x,y; - - x=*((GLfloat *)a); - y=*((GLfloat *)b); - if(fabs(x-y) < EPSILON) - return 0; - if(x > y) - return 1; - return -1; + GLfloat x, y; + + x = *((GLfloat *) a); + y = *((GLfloat *) b); + if (fabs(x - y) < EPSILON) + return 0; + if (x > y) + return 1; + return -1; } /* insert into dest knot all values within the valid range from src knot */ /* that do not appear in dest */ void -collect_unified_knot(knot_str_type *dest, knot_str_type *src, - GLfloat maximal_min_knot, GLfloat minimal_max_knot) +collect_unified_knot(knot_str_type * dest, knot_str_type * src, + GLfloat maximal_min_knot, GLfloat minimal_max_knot) { - GLfloat *src_knot,*dest_knot; - GLint src_t_min,src_t_max,dest_t_min,dest_t_max; - GLint src_nknots,dest_nknots; - GLint i,j,k,new_cnt; - GLboolean not_found_flag; - - src_knot=src->unified_knot; - dest_knot=dest->unified_knot; - src_t_min=src->t_min; - src_t_max=src->t_max; - dest_t_min=dest->t_min; - dest_t_max=dest->t_max; - src_nknots=src->unified_nknots; - dest_nknots=dest->unified_nknots; - - k=new_cnt=dest_nknots; - for(i=src_t_min;i<=src_t_max;i++) - if(src_knot[i] - maximal_min_knot > -EPSILON && - src_knot[i] - minimal_max_knot < EPSILON) - { - not_found_flag=GL_TRUE; - for(j=dest_t_min;j<=dest_t_max;j++) - if(fabs(dest_knot[j]-src_knot[i]) < EPSILON) - { - not_found_flag=GL_FALSE; - break; - } - if(not_found_flag) - { - /* knot from src is not in dest - add this knot to dest */ - dest_knot[k++]=src_knot[i]; - ++new_cnt; - ++(dest->t_max); /* the valid range widens */ - ++(dest->delta_nknots); /* increment the extra knot value counter */ - } - } - dest->unified_nknots=new_cnt; - qsort((void *)dest_knot,(size_t)new_cnt,(size_t)sizeof(GLfloat), - &knot_sort); + GLfloat *src_knot, *dest_knot; + GLint src_t_min, src_t_max, dest_t_min, dest_t_max; + GLint src_nknots, dest_nknots; + GLint i, j, k, new_cnt; + GLboolean not_found_flag; + + src_knot = src->unified_knot; + dest_knot = dest->unified_knot; + src_t_min = src->t_min; + src_t_max = src->t_max; + dest_t_min = dest->t_min; + dest_t_max = dest->t_max; + src_nknots = src->unified_nknots; + dest_nknots = dest->unified_nknots; + + k = new_cnt = dest_nknots; + for (i = src_t_min; i <= src_t_max; i++) + if (src_knot[i] - maximal_min_knot > -EPSILON && + src_knot[i] - minimal_max_knot < EPSILON) { + not_found_flag = GL_TRUE; + for (j = dest_t_min; j <= dest_t_max; j++) + if (fabs(dest_knot[j] - src_knot[i]) < EPSILON) { + not_found_flag = GL_FALSE; + break; + } + if (not_found_flag) { + /* knot from src is not in dest - add this knot to dest */ + dest_knot[k++] = src_knot[i]; + ++new_cnt; + ++(dest->t_max); /* the valid range widens */ + ++(dest->delta_nknots); /* increment the extra knot value counter */ + } + } + dest->unified_nknots = new_cnt; + qsort((void *) dest_knot, (size_t) new_cnt, (size_t) sizeof(GLfloat), + &knot_sort); } /* basing on the new common knot range for all attributes set */ /* t_min and t_max values for each knot - they will be used later on */ /* by explode_knot() and calc_new_ctrl_pts */ static void -set_new_t_min_t_max(knot_str_type *geom_knot, knot_str_type *color_knot, - knot_str_type *normal_knot, knot_str_type *texture_knot, - GLfloat maximal_min_knot, GLfloat minimal_max_knot) +set_new_t_min_t_max(knot_str_type * geom_knot, knot_str_type * color_knot, + knot_str_type * normal_knot, knot_str_type * texture_knot, + GLfloat maximal_min_knot, GLfloat minimal_max_knot) { - GLuint t_min,t_max,cnt; - - if(minimal_max_knot-maximal_min_knot < EPSILON) - { - /* knot common range empty */ - geom_knot->t_min=geom_knot->t_max=0; - color_knot->t_min=color_knot->t_max=0; - normal_knot->t_min=normal_knot->t_max=0; - texture_knot->t_min=texture_knot->t_max=0; - } - else - { - if(geom_knot->unified_knot!=NULL) - { - cnt=geom_knot->unified_nknots; - for(t_min=0;t_minunified_knot)[t_min] - maximal_min_knot) < - EPSILON) - break; - for(t_max=cnt-1;t_max;t_max--) - if(fabs((geom_knot->unified_knot)[t_max] - minimal_max_knot) < - EPSILON) - break; - } - else - if(geom_knot->nknots) - { - cnt=geom_knot->nknots; - for(t_min=0;t_minknot)[t_min] - maximal_min_knot) < EPSILON) - break; - for(t_max=cnt-1;t_max;t_max--) - if(fabs((geom_knot->knot)[t_max] - minimal_max_knot) < EPSILON) - break; - } - geom_knot->t_min=t_min; - geom_knot->t_max=t_max; - if(color_knot->unified_knot!=NULL) - { - cnt=color_knot->unified_nknots; - for(t_min=0;t_minunified_knot)[t_min] - maximal_min_knot) < - EPSILON) - break; - for(t_max=cnt-1;t_max;t_max--) - if(fabs((color_knot->unified_knot)[t_max] - minimal_max_knot) < - EPSILON) - break; - color_knot->t_min=t_min; - color_knot->t_max=t_max; - } - if(normal_knot->unified_knot!=NULL) - { - cnt=normal_knot->unified_nknots; - for(t_min=0;t_minunified_knot)[t_min] - maximal_min_knot) < - EPSILON) - break; - for(t_max=cnt-1;t_max;t_max--) - if(fabs((normal_knot->unified_knot)[t_max] - minimal_max_knot) < - EPSILON) - break; - normal_knot->t_min=t_min; - normal_knot->t_max=t_max; - } - if(texture_knot->unified_knot!=NULL) - { - cnt=texture_knot->unified_nknots; - for(t_min=0;t_minunified_knot)[t_min] - maximal_min_knot) - < EPSILON) - break; - for(t_max=cnt-1;t_max;t_max--) - if(fabs((texture_knot->unified_knot)[t_max] - minimal_max_knot) - < EPSILON) - break; - texture_knot->t_min=t_min; - texture_knot->t_max=t_max; - } - } + GLuint t_min, t_max, cnt; + + if (minimal_max_knot - maximal_min_knot < EPSILON) { + /* knot common range empty */ + geom_knot->t_min = geom_knot->t_max = 0; + color_knot->t_min = color_knot->t_max = 0; + normal_knot->t_min = normal_knot->t_max = 0; + texture_knot->t_min = texture_knot->t_max = 0; + } + else { + if (geom_knot->unified_knot != NULL) { + cnt = geom_knot->unified_nknots; + for (t_min = 0; t_min < cnt; t_min++) + if (fabs((geom_knot->unified_knot)[t_min] - maximal_min_knot) < + EPSILON) break; + for (t_max = cnt - 1; t_max; t_max--) + if (fabs((geom_knot->unified_knot)[t_max] - minimal_max_knot) < + EPSILON) break; + } + else if (geom_knot->nknots) { + cnt = geom_knot->nknots; + for (t_min = 0; t_min < cnt; t_min++) + if (fabs((geom_knot->knot)[t_min] - maximal_min_knot) < EPSILON) + break; + for (t_max = cnt - 1; t_max; t_max--) + if (fabs((geom_knot->knot)[t_max] - minimal_max_knot) < EPSILON) + break; + } + geom_knot->t_min = t_min; + geom_knot->t_max = t_max; + if (color_knot->unified_knot != NULL) { + cnt = color_knot->unified_nknots; + for (t_min = 0; t_min < cnt; t_min++) + if (fabs((color_knot->unified_knot)[t_min] - maximal_min_knot) < + EPSILON) break; + for (t_max = cnt - 1; t_max; t_max--) + if (fabs((color_knot->unified_knot)[t_max] - minimal_max_knot) < + EPSILON) break; + color_knot->t_min = t_min; + color_knot->t_max = t_max; + } + if (normal_knot->unified_knot != NULL) { + cnt = normal_knot->unified_nknots; + for (t_min = 0; t_min < cnt; t_min++) + if (fabs((normal_knot->unified_knot)[t_min] - maximal_min_knot) < + EPSILON) break; + for (t_max = cnt - 1; t_max; t_max--) + if (fabs((normal_knot->unified_knot)[t_max] - minimal_max_knot) < + EPSILON) break; + normal_knot->t_min = t_min; + normal_knot->t_max = t_max; + } + if (texture_knot->unified_knot != NULL) { + cnt = texture_knot->unified_nknots; + for (t_min = 0; t_min < cnt; t_min++) + if (fabs((texture_knot->unified_knot)[t_min] - maximal_min_knot) + < EPSILON) + break; + for (t_max = cnt - 1; t_max; t_max--) + if (fabs((texture_knot->unified_knot)[t_max] - minimal_max_knot) + < EPSILON) + break; + texture_knot->t_min = t_min; + texture_knot->t_max = t_max; + } + } } /* modify all knot valid ranges in such a way that all have the same */ /* range, common to all knots */ /* do this by knot insertion */ 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) +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) { - GLint max_nknots; - GLfloat maximal_min_knot,minimal_max_knot; - GLint i; - - /* find the maximum modified knot length */ - max_nknots=geom_knot->nknots; - if(color_knot->unified_knot) - max_nknots+=color_knot->nknots; - if(normal_knot->unified_knot) - max_nknots+=normal_knot->nknots; - if(texture_knot->unified_knot) - max_nknots+=texture_knot->nknots; - maximal_min_knot=(geom_knot->knot)[geom_knot->t_min]; - minimal_max_knot=(geom_knot->knot)[geom_knot->t_max]; - /* any attirb data ? */ - if(max_nknots!=geom_knot->nknots) - { - /* allocate space for the unified knots */ - if((geom_knot->unified_knot= - (GLfloat *)malloc(sizeof(GLfloat)*max_nknots))==NULL) - { - call_user_error(nobj,GLU_OUT_OF_MEMORY); - return GLU_ERROR; - } - /* copy the original knot to the unified one */ - geom_knot->unified_nknots=geom_knot->nknots; - for(i=0;inknots;i++) - (geom_knot->unified_knot)[i]=(geom_knot->knot)[i]; - if(color_knot->unified_knot) - { - if((color_knot->knot)[color_knot->t_min] - maximal_min_knot > - EPSILON) - maximal_min_knot=(color_knot->knot)[color_knot->t_min]; - if(minimal_max_knot - (color_knot->knot)[color_knot->t_max] > - EPSILON) - minimal_max_knot=(color_knot->knot)[color_knot->t_max]; - if((color_knot->unified_knot= - (GLfloat *)malloc(sizeof(GLfloat)*max_nknots))==NULL) - { - free(geom_knot->unified_knot); - call_user_error(nobj,GLU_OUT_OF_MEMORY); - return GLU_ERROR; - } - /* copy the original knot to the unified one */ - color_knot->unified_nknots=color_knot->nknots; - for(i=0;inknots;i++) - (color_knot->unified_knot)[i]=(color_knot->knot)[i]; - } - if(normal_knot->unified_knot) - { - if((normal_knot->knot)[normal_knot->t_min] - maximal_min_knot > - EPSILON) - maximal_min_knot=(normal_knot->knot)[normal_knot->t_min]; - if(minimal_max_knot - (normal_knot->knot)[normal_knot->t_max] > - EPSILON) - minimal_max_knot=(normal_knot->knot)[normal_knot->t_max]; - if((normal_knot->unified_knot= - (GLfloat *)malloc(sizeof(GLfloat)*max_nknots))==NULL) - { - free(geom_knot->unified_knot); - free(color_knot->unified_knot); - call_user_error(nobj,GLU_OUT_OF_MEMORY); - return GLU_ERROR; - } - /* copy the original knot to the unified one */ - normal_knot->unified_nknots=normal_knot->nknots; - for(i=0;inknots;i++) - (normal_knot->unified_knot)[i]=(normal_knot->knot)[i]; - } - if(texture_knot->unified_knot) - { - if((texture_knot->knot)[texture_knot->t_min] - maximal_min_knot > - EPSILON) - maximal_min_knot=(texture_knot->knot)[texture_knot->t_min]; - if(minimal_max_knot - (texture_knot->knot)[texture_knot->t_max] > - EPSILON) - minimal_max_knot=(texture_knot->knot)[texture_knot->t_max]; - if((texture_knot->unified_knot= - (GLfloat *)malloc(sizeof(GLfloat)*max_nknots))==NULL) - { - free(geom_knot->unified_knot); - free(color_knot->unified_knot); - free(normal_knot->unified_knot); - call_user_error(nobj,GLU_OUT_OF_MEMORY); - return GLU_ERROR; - } - /* copy the original knot to the unified one */ - texture_knot->unified_nknots=texture_knot->nknots; - for(i=0;inknots;i++) - (texture_knot->unified_knot)[i]=(texture_knot->knot)[i]; - } - /* work on the geometry knot with all additional knot values */ - /* appearing in attirbutive knots */ - if(minimal_max_knot-maximal_min_knot < EPSILON) - { - /* empty working range */ - geom_knot->unified_nknots=0; - color_knot->unified_nknots=0; - normal_knot->unified_nknots=0; - texture_knot->unified_nknots=0; - } - else - { - if(color_knot->unified_knot) - collect_unified_knot(geom_knot,color_knot,maximal_min_knot, - minimal_max_knot); - if(normal_knot->unified_knot) - collect_unified_knot(geom_knot,normal_knot,maximal_min_knot, - minimal_max_knot); - if(texture_knot->unified_knot) - collect_unified_knot(geom_knot,texture_knot,maximal_min_knot, - minimal_max_knot); - /* since we have now built the "unified" geometry knot */ - /* add same knot values to all attributive knots */ - if(color_knot->unified_knot) - collect_unified_knot(color_knot,geom_knot,maximal_min_knot, - minimal_max_knot); - if(normal_knot->unified_knot) - collect_unified_knot(normal_knot,geom_knot,maximal_min_knot, - minimal_max_knot); - if(texture_knot->unified_knot) - collect_unified_knot(texture_knot,geom_knot,maximal_min_knot, - minimal_max_knot); - } - } - set_new_t_min_t_max(geom_knot,color_knot,normal_knot,texture_knot, - maximal_min_knot,minimal_max_knot); - return GLU_NO_ERROR; + GLint max_nknots; + GLfloat maximal_min_knot, minimal_max_knot; + GLint i; + + /* find the maximum modified knot length */ + max_nknots = geom_knot->nknots; + if (color_knot->unified_knot) + max_nknots += color_knot->nknots; + if (normal_knot->unified_knot) + max_nknots += normal_knot->nknots; + if (texture_knot->unified_knot) + max_nknots += texture_knot->nknots; + maximal_min_knot = (geom_knot->knot)[geom_knot->t_min]; + minimal_max_knot = (geom_knot->knot)[geom_knot->t_max]; + /* any attirb data ? */ + if (max_nknots != geom_knot->nknots) { + /* allocate space for the unified knots */ + if ((geom_knot->unified_knot = + (GLfloat *) malloc(sizeof(GLfloat) * max_nknots)) == NULL) { + call_user_error(nobj, GLU_OUT_OF_MEMORY); + return GLU_ERROR; + } + /* copy the original knot to the unified one */ + geom_knot->unified_nknots = geom_knot->nknots; + for (i = 0; i < geom_knot->nknots; i++) + (geom_knot->unified_knot)[i] = (geom_knot->knot)[i]; + if (color_knot->unified_knot) { + if ((color_knot->knot)[color_knot->t_min] - maximal_min_knot > + EPSILON) + maximal_min_knot = (color_knot->knot)[color_knot->t_min]; + if (minimal_max_knot - (color_knot->knot)[color_knot->t_max] > + EPSILON) + minimal_max_knot = (color_knot->knot)[color_knot->t_max]; + if ((color_knot->unified_knot = + (GLfloat *) malloc(sizeof(GLfloat) * max_nknots)) == NULL) { + free(geom_knot->unified_knot); + call_user_error(nobj, GLU_OUT_OF_MEMORY); + return GLU_ERROR; + } + /* copy the original knot to the unified one */ + color_knot->unified_nknots = color_knot->nknots; + for (i = 0; i < color_knot->nknots; i++) + (color_knot->unified_knot)[i] = (color_knot->knot)[i]; + } + if (normal_knot->unified_knot) { + if ((normal_knot->knot)[normal_knot->t_min] - maximal_min_knot > + EPSILON) + maximal_min_knot = (normal_knot->knot)[normal_knot->t_min]; + if (minimal_max_knot - (normal_knot->knot)[normal_knot->t_max] > + EPSILON) + minimal_max_knot = (normal_knot->knot)[normal_knot->t_max]; + if ((normal_knot->unified_knot = + (GLfloat *) malloc(sizeof(GLfloat) * max_nknots)) == NULL) { + free(geom_knot->unified_knot); + free(color_knot->unified_knot); + call_user_error(nobj, GLU_OUT_OF_MEMORY); + return GLU_ERROR; + } + /* copy the original knot to the unified one */ + normal_knot->unified_nknots = normal_knot->nknots; + for (i = 0; i < normal_knot->nknots; i++) + (normal_knot->unified_knot)[i] = (normal_knot->knot)[i]; + } + if (texture_knot->unified_knot) { + if ((texture_knot->knot)[texture_knot->t_min] - maximal_min_knot > + EPSILON) + maximal_min_knot = (texture_knot->knot)[texture_knot->t_min]; + if (minimal_max_knot - (texture_knot->knot)[texture_knot->t_max] > + EPSILON) + minimal_max_knot = (texture_knot->knot)[texture_knot->t_max]; + if ((texture_knot->unified_knot = + (GLfloat *) malloc(sizeof(GLfloat) * max_nknots)) == NULL) { + free(geom_knot->unified_knot); + free(color_knot->unified_knot); + free(normal_knot->unified_knot); + call_user_error(nobj, GLU_OUT_OF_MEMORY); + return GLU_ERROR; + } + /* copy the original knot to the unified one */ + texture_knot->unified_nknots = texture_knot->nknots; + for (i = 0; i < texture_knot->nknots; i++) + (texture_knot->unified_knot)[i] = (texture_knot->knot)[i]; + } + /* work on the geometry knot with all additional knot values */ + /* appearing in attirbutive knots */ + if (minimal_max_knot - maximal_min_knot < EPSILON) { + /* empty working range */ + geom_knot->unified_nknots = 0; + color_knot->unified_nknots = 0; + normal_knot->unified_nknots = 0; + texture_knot->unified_nknots = 0; + } + else { + if (color_knot->unified_knot) + collect_unified_knot(geom_knot, color_knot, maximal_min_knot, + minimal_max_knot); + if (normal_knot->unified_knot) + collect_unified_knot(geom_knot, normal_knot, maximal_min_knot, + minimal_max_knot); + if (texture_knot->unified_knot) + collect_unified_knot(geom_knot, texture_knot, maximal_min_knot, + minimal_max_knot); + /* since we have now built the "unified" geometry knot */ + /* add same knot values to all attributive knots */ + if (color_knot->unified_knot) + collect_unified_knot(color_knot, geom_knot, maximal_min_knot, + minimal_max_knot); + if (normal_knot->unified_knot) + collect_unified_knot(normal_knot, geom_knot, maximal_min_knot, + minimal_max_knot); + if (texture_knot->unified_knot) + collect_unified_knot(texture_knot, geom_knot, maximal_min_knot, + minimal_max_knot); + } + } + set_new_t_min_t_max(geom_knot, color_knot, normal_knot, texture_knot, + maximal_min_knot, minimal_max_knot); + return GLU_NO_ERROR; } void -free_unified_knots(knot_str_type *geom_knot, knot_str_type *color_knot, - knot_str_type *normal_knot, knot_str_type *texture_knot) +free_unified_knots(knot_str_type * geom_knot, knot_str_type * color_knot, + knot_str_type * normal_knot, knot_str_type * texture_knot) { - if(geom_knot->unified_knot) - free(geom_knot->unified_knot); - if(color_knot->unified_knot) - free(color_knot->unified_knot); - if(normal_knot->unified_knot) - free(normal_knot->unified_knot); - if(texture_knot->unified_knot) - free(texture_knot->unified_knot); + if (geom_knot->unified_knot) + free(geom_knot->unified_knot); + if (color_knot->unified_knot) + free(color_knot->unified_knot); + if (normal_knot->unified_knot) + free(normal_knot->unified_knot); + if (texture_knot->unified_knot) + free(texture_knot->unified_knot); } -GLenum -explode_knot(knot_str_type *the_knot) +GLenum explode_knot(knot_str_type * the_knot) { - GLfloat *knot,*new_knot; - GLint nknots,n_new_knots=0; - GLint t_min,t_max; - GLint ord; - GLsizei i,j,k; - GLfloat tmp_float; - - if(the_knot->unified_knot) - { - knot=the_knot->unified_knot; - nknots=the_knot->unified_nknots; - } - else - { - knot=the_knot->knot; - nknots=the_knot->nknots; - } - ord=the_knot->order; - t_min=the_knot->t_min; - t_max=the_knot->t_max; - - for(i=t_min;i<=t_max;) - { - tmp_float=knot[i]; - for(j=0;jEPSILON) - break; - n_new_knots+=ord-j; - i+=j; - } - /* alloc space for new_knot */ - if((new_knot=(GLfloat *)malloc(sizeof(GLfloat)*(nknots+n_new_knots)))==NULL) - { - return GLU_OUT_OF_MEMORY; - } - /* fill in new knot */ - for(j=0;jnew_knot=new_knot; - the_knot->delta_nknots+=n_new_knots; - the_knot->t_max+=n_new_knots; - return GLU_NO_ERROR; + GLfloat *knot, *new_knot; + GLint nknots, n_new_knots = 0; + GLint t_min, t_max; + GLint ord; + GLsizei i, j, k; + GLfloat tmp_float; + + if (the_knot->unified_knot) { + knot = the_knot->unified_knot; + nknots = the_knot->unified_nknots; + } + else { + knot = the_knot->knot; + nknots = the_knot->nknots; + } + ord = the_knot->order; + t_min = the_knot->t_min; + t_max = the_knot->t_max; + + for (i = t_min; i <= t_max;) { + tmp_float = knot[i]; + for (j = 0; j < ord && (i + j) <= t_max; j++) + if (fabs(tmp_float - knot[i + j]) > EPSILON) + break; + n_new_knots += ord - j; + i += j; + } + /* alloc space for new_knot */ + if ( + (new_knot = + (GLfloat *) malloc(sizeof(GLfloat) * (nknots + n_new_knots))) == NULL) { + return GLU_OUT_OF_MEMORY; + } + /* fill in new knot */ + for (j = 0; j < t_min; j++) + new_knot[j] = knot[j]; + for (i = j; i <= t_max; i++) { + tmp_float = knot[i]; + for (k = 0; k < ord; k++) { + new_knot[j++] = knot[i]; + if (tmp_float == knot[i + 1]) + i++; + } + } + for (i = t_max + 1; i < (int) nknots; i++) + new_knot[j++] = knot[i]; + /* fill in the knot structure */ + the_knot->new_knot = new_knot; + the_knot->delta_nknots += n_new_knots; + the_knot->t_max += n_new_knots; + return GLU_NO_ERROR; } -GLenum -calc_alphas(knot_str_type *the_knot) +GLenum calc_alphas(knot_str_type * the_knot) { - GLfloat tmp_float; - int i,j,k,m,n; - int order; - GLfloat *alpha,*alpha_new,*tmp_alpha; - GLfloat denom; - GLfloat *knot,*new_knot; - - - knot=the_knot->knot; - order=the_knot->order; - new_knot=the_knot->new_knot; - n=the_knot->nknots-the_knot->order; - m=n+the_knot->delta_nknots; - if((alpha=(GLfloat *)malloc(sizeof(GLfloat)*n*m))==NULL) - { - return GLU_OUT_OF_MEMORY; - } - if((alpha_new=(GLfloat *)malloc(sizeof(GLfloat)*n*m))==NULL) - { - free(alpha); - return GLU_OUT_OF_MEMORY; - } - for(j=0;jEPSILON) - tmp_float+=(knot[i+k+1]-new_knot[j+k])/denom* - alpha[(i+1)+j*n]; - alpha_new[i+j*n]=tmp_float; - } - tmp_alpha=alpha_new; - alpha_new=alpha; - alpha=tmp_alpha; - } - the_knot->alpha=alpha; - free(alpha_new); - return GLU_NO_ERROR; + GLfloat tmp_float; + int i, j, k, m, n; + int order; + GLfloat *alpha, *alpha_new, *tmp_alpha; + GLfloat denom; + GLfloat *knot, *new_knot; + + + knot = the_knot->knot; + order = the_knot->order; + new_knot = the_knot->new_knot; + n = the_knot->nknots - the_knot->order; + m = n + the_knot->delta_nknots; + if ((alpha = (GLfloat *) malloc(sizeof(GLfloat) * n * m)) == NULL) { + return GLU_OUT_OF_MEMORY; + } + if ((alpha_new = (GLfloat *) malloc(sizeof(GLfloat) * n * m)) == NULL) { + free(alpha); + return GLU_OUT_OF_MEMORY; + } + for (j = 0; j < m; j++) { + for (i = 0; i < n; i++) { + if ((knot[i] <= new_knot[j]) && (new_knot[j] < knot[i + 1])) + tmp_float = 1.0; + else + tmp_float = 0.0; + alpha[i + j * n] = tmp_float; + } + } + for (k = 1; k < order; k++) { + for (j = 0; j < m; j++) + for (i = 0; i < n; i++) { + denom = knot[i + k] - knot[i]; + if (fabs(denom) < EPSILON) + tmp_float = 0.0; + else + tmp_float = (new_knot[j + k] - knot[i]) / denom * + alpha[i + j * n]; + denom = knot[i + k + 1] - knot[i + 1]; + if (fabs(denom) > EPSILON) + tmp_float += (knot[i + k + 1] - new_knot[j + k]) / denom * + alpha[(i + 1) + j * n]; + alpha_new[i + j * n] = tmp_float; + } + tmp_alpha = alpha_new; + alpha_new = alpha; + alpha = tmp_alpha; + } + the_knot->alpha = alpha; + free(alpha_new); + return GLU_NO_ERROR; } GLenum -calc_new_ctrl_pts(GLfloat *ctrl,GLint stride,knot_str_type *the_knot, - GLint dim,GLfloat **new_ctrl,GLint *ncontrol) +calc_new_ctrl_pts(GLfloat * ctrl, GLint stride, knot_str_type * the_knot, + GLint dim, GLfloat ** new_ctrl, GLint * ncontrol) { - GLsizei i,j,k,l,m,n; - GLsizei index1,index2; - GLfloat *alpha; - GLfloat *new_knot; - - new_knot=the_knot->new_knot; - n=the_knot->nknots-the_knot->order; - alpha=the_knot->alpha; - - m=the_knot->t_max+1-the_knot->t_min-the_knot->order; - k=the_knot->t_min; - /* allocate space for new control points */ - if((*new_ctrl=(GLfloat *)malloc(sizeof(GLfloat)*dim*m))==NULL) - { - return GLU_OUT_OF_MEMORY; - } - for(j=0;jnew_knot; + n = the_knot->nknots - the_knot->order; + alpha = the_knot->alpha; + + m = the_knot->t_max + 1 - the_knot->t_min - the_knot->order; + k = the_knot->t_min; + /* allocate space for new control points */ + if ((*new_ctrl = (GLfloat *) malloc(sizeof(GLfloat) * dim * m)) == NULL) { + return GLU_OUT_OF_MEMORY; + } + for (j = 0; j < m; j++) { + for (l = 0; l < dim; l++) + (*new_ctrl)[j * dim + l] = 0.0; + for (i = 0; i < n; i++) { + index1 = i + (j + k) * n; + index2 = i * stride; + for (l = 0; l < dim; l++) + (*new_ctrl)[j * dim + l] += alpha[index1] * ctrl[index2 + l]; + } + } + *ncontrol = (GLint) m; + return GLU_NO_ERROR; } static GLint -calc_factor(GLfloat *pts,GLint order,GLint indx,GLint stride,GLfloat tolerance, - GLint dim) +calc_factor(GLfloat * pts, GLint order, GLint indx, GLint stride, + GLfloat tolerance, GLint dim) { - GLdouble model[16],proj[16]; - GLint viewport[4]; - GLdouble x,y,z,w,winx1,winy1,winz,winx2,winy2; - GLint i; - GLdouble len,dx,dy; - - glGetDoublev(GL_MODELVIEW_MATRIX,model); - glGetDoublev(GL_PROJECTION_MATRIX,proj); - glGetIntegerv(GL_VIEWPORT,viewport); - if(dim==4) - { - w=(GLdouble)pts[indx+3]; - x=(GLdouble)pts[indx]/w; - y=(GLdouble)pts[indx+1]/w; - z=(GLdouble)pts[indx+2]/w; - gluProject(x,y,z,model,proj,viewport,&winx1,&winy1,&winz); - len=0.0; - for(i=1;i= 2) - { - bincoeff = order-1; - s = 1.0-t; - - for(k=0; k constant curve */ - { - for(k=0; k= 2) { + bincoeff = order - 1; + s = 1.0 - t; + + for (k = 0; k < dim; k++) + out[k] = s * cp[k] + bincoeff * t * cp[offset + k]; + + for (i = 2, cp += 2 * offset, powert = t * t; i < order; + i++, powert *= t, cp += offset) { + bincoeff *= order - i; + bincoeff /= i; + + for (k = 0; k < dim; k++) + out[k] = s * out[k] + bincoeff * powert * cp[k]; + } + } + else { /* order=1 -> constant curve */ + + for (k = 0; k < dim; k++) + out[k] = cp[k]; + } } static GLint -calc_parametric_factor(GLfloat *pts,GLint order,GLint indx,GLint stride, - GLfloat tolerance,GLint dim) +calc_parametric_factor(GLfloat * pts, GLint order, GLint indx, GLint stride, + GLfloat tolerance, GLint dim) { - GLdouble model[16],proj[16]; - GLint viewport[4]; - GLdouble x,y,z,w,x1,y1,z1,x2,y2,z2,x3,y3,z3; - GLint i; - GLint P; - GLfloat bez_pt[4]; - GLdouble len=0.0,tmp,z_med; - - P = 2*(order+2); - glGetDoublev(GL_MODELVIEW_MATRIX,model); - glGetDoublev(GL_PROJECTION_MATRIX,proj); - glGetIntegerv(GL_VIEWPORT,viewport); - z_med = (viewport[2] + viewport[3]) * 0.5; - switch(dim) - { - case 4: - for(i=1;i */ - x = x2-x1; - y = y2-y1; - z = z2-z1; - tmp = sqrt(x*x+y*y+z*z); - x /= tmp; - y /= tmp; - z /= tmp; - tmp = x3*x+y3*y+z3*z-x1*x-y1*y-z1*z; - x = x1+x*tmp-x3; - y = y1+y*tmp-y3; - z = z1+z*tmp-z3; - tmp = sqrt(x*x+y*y+z*z); - if(tmp > len) - len = tmp; - } - break; - case 3: - for(i=1;i */ - x = x2-x1; - y = y2-y1; - z = z2-z1; - tmp = sqrt(x*x+y*y+z*z); - x /= tmp; - y /= tmp; - z /= tmp; - tmp = x3*x+y3*y+z3*z-x1*x-y1*y-z1*z; - x = x1+x*tmp-x3; - y = y1+y*tmp-y3; - z = z1+z*tmp-z3; - tmp = sqrt(x*x+y*y+z*z); - if(tmp > len) - len = tmp; - } - break; - case 2: - for(i=1;i */ - x = x2-x1; - y = y2-y1; - z = z2-z1; - tmp = sqrt(x*x+y*y+z*z); - x /= tmp; - y /= tmp; - z /= tmp; - tmp = x3*x+y3*y+z3*z-x1*x-y1*y-z1*z; - x = x1+x*tmp-x3; - y = y1+y*tmp-y3; - z = z1+z*tmp-z3; - tmp = sqrt(x*x+y*y+z*z); - if(tmp > len) - len = tmp; - } - break; - - } - if(len < tolerance) - return (order); - else - return (GLint)(sqrt(len/tolerance)*(order+2)+1); + GLdouble model[16], proj[16]; + GLint viewport[4]; + GLdouble x, y, z, w, x1, y1, z1, x2, y2, z2, x3, y3, z3; + GLint i; + GLint P; + GLfloat bez_pt[4]; + GLdouble len = 0.0, tmp, z_med; + + P = 2 * (order + 2); + glGetDoublev(GL_MODELVIEW_MATRIX, model); + glGetDoublev(GL_PROJECTION_MATRIX, proj); + glGetIntegerv(GL_VIEWPORT, viewport); + z_med = (viewport[2] + viewport[3]) * 0.5; + switch (dim) { + case 4: + for (i = 1; i < P; i++) { + bezier_curve(pts + indx, bez_pt, (GLfloat) i / (GLfloat) P, 4, + order, stride); + w = (GLdouble) bez_pt[3]; + x = (GLdouble) bez_pt[0] / w; + y = (GLdouble) bez_pt[1] / w; + z = (GLdouble) bez_pt[2] / w; + gluProject(x, y, z, model, proj, viewport, &x3, &y3, &z3); + z3 *= z_med; + bezier_curve(pts + indx, bez_pt, (GLfloat) (i - 1) / (GLfloat) P, 4, + order, stride); + w = (GLdouble) bez_pt[3]; + x = (GLdouble) bez_pt[0] / w; + y = (GLdouble) bez_pt[1] / w; + z = (GLdouble) bez_pt[2] / w; + gluProject(x, y, z, model, proj, viewport, &x1, &y1, &z1); + z1 *= z_med; + bezier_curve(pts + indx, bez_pt, (GLfloat) (i + 1) / (GLfloat) P, 4, + order, stride); + w = (GLdouble) bez_pt[3]; + x = (GLdouble) bez_pt[0] / w; + y = (GLdouble) bez_pt[1] / w; + z = (GLdouble) bez_pt[2] / w; + gluProject(x, y, z, model, proj, viewport, &x2, &y2, &z2); + z2 *= z_med; + /* calc distance between point (x3,y3,z3) and line segment */ + /* */ + x = x2 - x1; + y = y2 - y1; + z = z2 - z1; + tmp = sqrt(x * x + y * y + z * z); + x /= tmp; + y /= tmp; + z /= tmp; + tmp = x3 * x + y3 * y + z3 * z - x1 * x - y1 * y - z1 * z; + x = x1 + x * tmp - x3; + y = y1 + y * tmp - y3; + z = z1 + z * tmp - z3; + tmp = sqrt(x * x + y * y + z * z); + if (tmp > len) + len = tmp; + } + break; + case 3: + for (i = 1; i < P; i++) { + bezier_curve(pts + indx, bez_pt, (GLfloat) i / (GLfloat) P, 3, + order, stride); + x = (GLdouble) bez_pt[0]; + y = (GLdouble) bez_pt[1]; + z = (GLdouble) bez_pt[2]; + gluProject(x, y, z, model, proj, viewport, &x3, &y3, &z3); + z3 *= z_med; + bezier_curve(pts + indx, bez_pt, (GLfloat) (i - 1) / (GLfloat) P, 3, + order, stride); + x = (GLdouble) bez_pt[0]; + y = (GLdouble) bez_pt[1]; + z = (GLdouble) bez_pt[2]; + gluProject(x, y, z, model, proj, viewport, &x1, &y1, &z1); + z1 *= z_med; + bezier_curve(pts + indx, bez_pt, (GLfloat) (i + 1) / (GLfloat) P, 3, + order, stride); + x = (GLdouble) bez_pt[0]; + y = (GLdouble) bez_pt[1]; + z = (GLdouble) bez_pt[2]; + gluProject(x, y, z, model, proj, viewport, &x2, &y2, &z2); + z2 *= z_med; + /* calc distance between point (x3,y3,z3) and line segment */ + /* */ + x = x2 - x1; + y = y2 - y1; + z = z2 - z1; + tmp = sqrt(x * x + y * y + z * z); + x /= tmp; + y /= tmp; + z /= tmp; + tmp = x3 * x + y3 * y + z3 * z - x1 * x - y1 * y - z1 * z; + x = x1 + x * tmp - x3; + y = y1 + y * tmp - y3; + z = z1 + z * tmp - z3; + tmp = sqrt(x * x + y * y + z * z); + if (tmp > len) + len = tmp; + } + break; + case 2: + for (i = 1; i < P; i++) { + bezier_curve(pts + indx, bez_pt, (GLfloat) i / (GLfloat) P, 2, + order, stride); + x = (GLdouble) bez_pt[0]; + y = (GLdouble) bez_pt[1]; + z = 0.0; + gluProject(x, y, z, model, proj, viewport, &x3, &y3, &z3); + z3 *= z_med; + bezier_curve(pts + indx, bez_pt, (GLfloat) (i - 1) / (GLfloat) P, 2, + order, stride); + x = (GLdouble) bez_pt[0]; + y = (GLdouble) bez_pt[1]; + z = 0.0; + gluProject(x, y, z, model, proj, viewport, &x1, &y1, &z1); + z1 *= z_med; + bezier_curve(pts + indx, bez_pt, (GLfloat) (i + 1) / (GLfloat) P, 2, + order, stride); + x = (GLdouble) bez_pt[0]; + y = (GLdouble) bez_pt[1]; + z = 0.0; + gluProject(x, y, z, model, proj, viewport, &x2, &y2, &z2); + z2 *= z_med; + /* calc distance between point (x3,y3,z3) and line segment */ + /* */ + x = x2 - x1; + y = y2 - y1; + z = z2 - z1; + tmp = sqrt(x * x + y * y + z * z); + x /= tmp; + y /= tmp; + z /= tmp; + tmp = x3 * x + y3 * y + z3 * z - x1 * x - y1 * y - z1 * z; + x = x1 + x * tmp - x3; + y = y1 + y * tmp - y3; + z = z1 + z * tmp - z3; + tmp = sqrt(x * x + y * y + z * z); + if (tmp > len) + len = tmp; + } + break; + + } + if (len < tolerance) + return (order); + else + return (GLint) (sqrt(len / tolerance) * (order + 2) + 1); } static GLenum -calc_sampling_3D(new_ctrl_type *new_ctrl, GLfloat tolerance, GLint dim, - GLint uorder, GLint vorder, GLint **ufactors, GLint **vfactors) +calc_sampling_3D(new_ctrl_type * new_ctrl, GLfloat tolerance, GLint dim, + GLint uorder, GLint vorder, GLint ** ufactors, + GLint ** vfactors) { - GLfloat *ctrl; - GLint tmp_factor1,tmp_factor2; - GLint ufactor_cnt,vfactor_cnt; - GLint offset1,offset2,offset3; - GLint i,j; - - ufactor_cnt=new_ctrl->s_bezier_cnt; - vfactor_cnt=new_ctrl->t_bezier_cnt; - if((*ufactors=(GLint *)malloc(sizeof(GLint)*ufactor_cnt*3)) - ==NULL) - { - return GLU_OUT_OF_MEMORY; - } - if((*vfactors=(GLint *)malloc(sizeof(GLint)*vfactor_cnt*3)) - ==NULL) - { - free(*ufactors); - return GLU_OUT_OF_MEMORY; - } - ctrl=new_ctrl->geom_ctrl; - offset1=new_ctrl->geom_t_stride*vorder; - offset2=new_ctrl->geom_s_stride*uorder; - for(j=0;jtmp_factor1) - tmp_factor1=tmp_factor2; - } - /* last time for the opposite edge */ - *(*vfactors+j*3+2)=tmp_factor2=calc_factor(ctrl,vorder, - j*offset1+i*offset2-new_ctrl->geom_s_stride, - dim,tolerance,dim); - if(tmp_factor2>tmp_factor1) - *(*vfactors+j*3)=tmp_factor2; - else - *(*vfactors+j*3)=tmp_factor1; - } - offset3=new_ctrl->geom_s_stride; - offset2=new_ctrl->geom_s_stride*uorder; - for(j=0;jtmp_factor1) - tmp_factor1=tmp_factor2; - } - /* last time for the opposite edge */ - *(*ufactors+j*3+2)=tmp_factor2=calc_factor(ctrl,uorder, - j*offset2+i*offset1-new_ctrl->geom_t_stride, - offset3,tolerance,dim); - if(tmp_factor2>tmp_factor1) - *(*ufactors+j*3)=tmp_factor2; - else - *(*ufactors+j*3)=tmp_factor1; - } - return GL_NO_ERROR; + GLfloat *ctrl; + GLint tmp_factor1, tmp_factor2; + GLint ufactor_cnt, vfactor_cnt; + GLint offset1, offset2, offset3; + GLint i, j; + + ufactor_cnt = new_ctrl->s_bezier_cnt; + vfactor_cnt = new_ctrl->t_bezier_cnt; + if ((*ufactors = (GLint *) malloc(sizeof(GLint) * ufactor_cnt * 3)) + == NULL) { + return GLU_OUT_OF_MEMORY; + } + if ((*vfactors = (GLint *) malloc(sizeof(GLint) * vfactor_cnt * 3)) + == NULL) { + free(*ufactors); + return GLU_OUT_OF_MEMORY; + } + ctrl = new_ctrl->geom_ctrl; + offset1 = new_ctrl->geom_t_stride * vorder; + offset2 = new_ctrl->geom_s_stride * uorder; + for (j = 0; j < vfactor_cnt; j++) { + *(*vfactors + j * 3 + 1) = tmp_factor1 = calc_factor(ctrl, vorder, + j * offset1, dim, + tolerance, dim); + /* loop ufactor_cnt-1 times */ + for (i = 1; i < ufactor_cnt; i++) { + tmp_factor2 = calc_factor(ctrl, vorder, + j * offset1 + i * offset2, dim, tolerance, + dim); + if (tmp_factor2 > tmp_factor1) + tmp_factor1 = tmp_factor2; + } + /* last time for the opposite edge */ + *(*vfactors + j * 3 + 2) = tmp_factor2 = calc_factor(ctrl, vorder, + j * offset1 + + i * offset2 - + new_ctrl-> + geom_s_stride, dim, + tolerance, dim); + if (tmp_factor2 > tmp_factor1) + *(*vfactors + j * 3) = tmp_factor2; + else + *(*vfactors + j * 3) = tmp_factor1; + } + offset3 = new_ctrl->geom_s_stride; + offset2 = new_ctrl->geom_s_stride * uorder; + for (j = 0; j < ufactor_cnt; j++) { + *(*ufactors + j * 3 + 1) = tmp_factor1 = calc_factor(ctrl, uorder, + j * offset2, + offset3, tolerance, + dim); + /* loop vfactor_cnt-1 times */ + for (i = 1; i < vfactor_cnt; i++) { + tmp_factor2 = calc_factor(ctrl, uorder, + j * offset2 + i * offset1, offset3, + tolerance, dim); + if (tmp_factor2 > tmp_factor1) + tmp_factor1 = tmp_factor2; + } + /* last time for the opposite edge */ + *(*ufactors + j * 3 + 2) = tmp_factor2 = calc_factor(ctrl, uorder, + j * offset2 + + i * offset1 - + new_ctrl-> + geom_t_stride, + offset3, tolerance, + dim); + if (tmp_factor2 > tmp_factor1) + *(*ufactors + j * 3) = tmp_factor2; + else + *(*ufactors + j * 3) = tmp_factor1; + } + return GL_NO_ERROR; } static GLenum -calc_sampling_param_3D(new_ctrl_type *new_ctrl, GLfloat tolerance, GLint dim, - GLint uorder, GLint vorder, GLint **ufactors, GLint **vfactors) +calc_sampling_param_3D(new_ctrl_type * new_ctrl, GLfloat tolerance, GLint dim, + GLint uorder, GLint vorder, GLint ** ufactors, + GLint ** vfactors) { - GLfloat *ctrl; - GLint tmp_factor1,tmp_factor2; - GLint ufactor_cnt,vfactor_cnt; - GLint offset1,offset2,offset3; - GLint i,j; - - ufactor_cnt=new_ctrl->s_bezier_cnt; - vfactor_cnt=new_ctrl->t_bezier_cnt; - if((*ufactors=(GLint *)malloc(sizeof(GLint)*ufactor_cnt*3)) - ==NULL) - { - return GLU_OUT_OF_MEMORY; - } - if((*vfactors=(GLint *)malloc(sizeof(GLint)*vfactor_cnt*3)) - ==NULL) - { - free(*ufactors); - return GLU_OUT_OF_MEMORY; - } - ctrl=new_ctrl->geom_ctrl; - offset1=new_ctrl->geom_t_stride*vorder; - offset2=new_ctrl->geom_s_stride*uorder; - for(j=0;jtmp_factor1) - tmp_factor1=tmp_factor2; - } - /* last time for the opposite edge */ - *(*vfactors+j*3+2)=tmp_factor2=calc_parametric_factor(ctrl,vorder, - j*offset1+i*offset2-new_ctrl->geom_s_stride, - dim,tolerance,dim); - if(tmp_factor2>tmp_factor1) - *(*vfactors+j*3)=tmp_factor2; - else - *(*vfactors+j*3)=tmp_factor1; - } - offset3=new_ctrl->geom_s_stride; - offset2=new_ctrl->geom_s_stride*uorder; - for(j=0;jtmp_factor1) - tmp_factor1=tmp_factor2; - } - /* last time for the opposite edge */ - *(*ufactors+j*3+2)=tmp_factor2=calc_parametric_factor(ctrl,uorder, - j*offset2+i*offset1-new_ctrl->geom_t_stride, - offset3,tolerance,dim); - if(tmp_factor2>tmp_factor1) - *(*ufactors+j*3)=tmp_factor2; - else - *(*ufactors+j*3)=tmp_factor1; - } - return GL_NO_ERROR; + GLfloat *ctrl; + GLint tmp_factor1, tmp_factor2; + GLint ufactor_cnt, vfactor_cnt; + GLint offset1, offset2, offset3; + GLint i, j; + + ufactor_cnt = new_ctrl->s_bezier_cnt; + vfactor_cnt = new_ctrl->t_bezier_cnt; + if ((*ufactors = (GLint *) malloc(sizeof(GLint) * ufactor_cnt * 3)) + == NULL) { + return GLU_OUT_OF_MEMORY; + } + if ((*vfactors = (GLint *) malloc(sizeof(GLint) * vfactor_cnt * 3)) + == NULL) { + free(*ufactors); + return GLU_OUT_OF_MEMORY; + } + ctrl = new_ctrl->geom_ctrl; + offset1 = new_ctrl->geom_t_stride * vorder; + offset2 = new_ctrl->geom_s_stride * uorder; + for (j = 0; j < vfactor_cnt; j++) { + *(*vfactors + j * 3 + 1) = tmp_factor1 = + calc_parametric_factor(ctrl, vorder, j * offset1, dim, tolerance, + dim); + /* loop ufactor_cnt-1 times */ + for (i = 1; i < ufactor_cnt; i++) { + tmp_factor2 = calc_parametric_factor(ctrl, vorder, + j * offset1 + i * offset2, dim, + tolerance, dim); + if (tmp_factor2 > tmp_factor1) + tmp_factor1 = tmp_factor2; + } + /* last time for the opposite edge */ + *(*vfactors + j * 3 + 2) = tmp_factor2 = + calc_parametric_factor(ctrl, vorder, + j * offset1 + i * offset2 - + new_ctrl->geom_s_stride, dim, tolerance, dim); + if (tmp_factor2 > tmp_factor1) + *(*vfactors + j * 3) = tmp_factor2; + else + *(*vfactors + j * 3) = tmp_factor1; + } + offset3 = new_ctrl->geom_s_stride; + offset2 = new_ctrl->geom_s_stride * uorder; + for (j = 0; j < ufactor_cnt; j++) { + *(*ufactors + j * 3 + 1) = tmp_factor1 = + calc_parametric_factor(ctrl, uorder, j * offset2, offset3, tolerance, + dim); + /* loop vfactor_cnt-1 times */ + for (i = 1; i < vfactor_cnt; i++) { + tmp_factor2 = calc_parametric_factor(ctrl, uorder, + j * offset2 + i * offset1, + offset3, tolerance, dim); + if (tmp_factor2 > tmp_factor1) + tmp_factor1 = tmp_factor2; + } + /* last time for the opposite edge */ + *(*ufactors + j * 3 + 2) = tmp_factor2 = + calc_parametric_factor(ctrl, uorder, + j * offset2 + i * offset1 - + new_ctrl->geom_t_stride, offset3, tolerance, + dim); + if (tmp_factor2 > tmp_factor1) + *(*ufactors + j * 3) = tmp_factor2; + else + *(*ufactors + j * 3) = tmp_factor1; + } + return GL_NO_ERROR; } static GLenum -calc_sampling_2D(GLfloat *ctrl, GLint cnt, GLint order, - GLfloat tolerance, GLint dim, GLint **factors) +calc_sampling_2D(GLfloat * ctrl, GLint cnt, GLint order, + GLfloat tolerance, GLint dim, GLint ** factors) { - GLint factor_cnt; - GLint tmp_factor; - GLint offset; - GLint i; - - factor_cnt=cnt/order; - if((*factors=(GLint *)malloc(sizeof(GLint)*factor_cnt))==NULL) - { - return GLU_OUT_OF_MEMORY; - } - offset=order*dim; - for(i=0;iauto_load_matrix==GL_FALSE) - { - GLint i; - GLfloat m[4]; - - glPushAttrib( (GLbitfield) (GL_VIEWPORT_BIT | GL_TRANSFORM_BIT)); - for(i=0;i<4;i++) - m[i]=nobj->sampling_matrices.viewport[i]; - glViewport(m[0],m[1],m[2],m[3]); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadMatrixf(nobj->sampling_matrices.proj); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadMatrixf(nobj->sampling_matrices.model); - } + if (nobj->auto_load_matrix == GL_FALSE) { + GLint i; + GLfloat m[4]; + + glPushAttrib((GLbitfield) (GL_VIEWPORT_BIT | GL_TRANSFORM_BIT)); + for (i = 0; i < 4; i++) + m[i] = nobj->sampling_matrices.viewport[i]; + glViewport(m[0], m[1], m[2], m[3]); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadMatrixf(nobj->sampling_matrices.proj); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadMatrixf(nobj->sampling_matrices.model); + } } static void -revert_sampling_and_culling( GLUnurbsObj *nobj ) +revert_sampling_and_culling(GLUnurbsObj * nobj) { - if(nobj->auto_load_matrix==GL_FALSE) - { - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glPopAttrib(); - } + if (nobj->auto_load_matrix == GL_FALSE) { + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glPopAttrib(); + } } GLenum -glu_do_sampling_3D( GLUnurbsObj *nobj, new_ctrl_type *new_ctrl, - GLint **sfactors, GLint **tfactors) +glu_do_sampling_3D(GLUnurbsObj * nobj, new_ctrl_type * new_ctrl, + GLint ** sfactors, GLint ** tfactors) { - GLint dim; - GLenum err; - - *sfactors=NULL; - *tfactors=NULL; - dim=nobj->surface.geom.dim; - set_sampling_and_culling(nobj); - if((err=calc_sampling_3D(new_ctrl,nobj->sampling_tolerance,dim, - nobj->surface.geom.sorder,nobj->surface.geom.torder, - sfactors,tfactors))==GLU_ERROR) - { - revert_sampling_and_culling(nobj); - call_user_error(nobj,err); - return GLU_ERROR; - } - revert_sampling_and_culling(nobj); - return GLU_NO_ERROR; + GLint dim; + GLenum err; + + *sfactors = NULL; + *tfactors = NULL; + dim = nobj->surface.geom.dim; + set_sampling_and_culling(nobj); + if ((err = calc_sampling_3D(new_ctrl, nobj->sampling_tolerance, dim, + nobj->surface.geom.sorder, + nobj->surface.geom.torder, sfactors, + tfactors)) == GLU_ERROR) { + revert_sampling_and_culling(nobj); + call_user_error(nobj, err); + return GLU_ERROR; + } + revert_sampling_and_culling(nobj); + return GLU_NO_ERROR; } GLenum -glu_do_sampling_uv( GLUnurbsObj *nobj, new_ctrl_type *new_ctrl, - GLint **sfactors, GLint **tfactors) +glu_do_sampling_uv(GLUnurbsObj * nobj, new_ctrl_type * new_ctrl, + GLint ** sfactors, GLint ** tfactors) { - GLint s_cnt, t_cnt, i; - GLint u_steps, v_steps; - - s_cnt = new_ctrl->s_bezier_cnt; - t_cnt = new_ctrl->t_bezier_cnt; - *sfactors=NULL; - *tfactors=NULL; - if((*sfactors=(GLint *)malloc(sizeof(GLint)*s_cnt*3)) - ==NULL) - { - return GLU_OUT_OF_MEMORY; - } - if((*tfactors=(GLint *)malloc(sizeof(GLint)*t_cnt*3)) - ==NULL) - { - free(*sfactors); - return GLU_OUT_OF_MEMORY; - } - u_steps = nobj->u_step; - v_steps = nobj->v_step; - for(i=0; is_bezier_cnt; + t_cnt = new_ctrl->t_bezier_cnt; + *sfactors = NULL; + *tfactors = NULL; + if ((*sfactors = (GLint *) malloc(sizeof(GLint) * s_cnt * 3)) + == NULL) { + return GLU_OUT_OF_MEMORY; + } + if ((*tfactors = (GLint *) malloc(sizeof(GLint) * t_cnt * 3)) + == NULL) { + free(*sfactors); + return GLU_OUT_OF_MEMORY; + } + u_steps = nobj->u_step; + v_steps = nobj->v_step; + for (i = 0; i < s_cnt; i++) { + *(*sfactors + i * 3) = u_steps; + *(*sfactors + i * 3 + 1) = u_steps; + *(*sfactors + i * 3 + 2) = u_steps; + } + for (i = 0; i < t_cnt; i++) { + *(*tfactors + i * 3) = v_steps; + *(*tfactors + i * 3 + 1) = v_steps; + *(*tfactors + i * 3 + 2) = v_steps; + } + return GLU_NO_ERROR; } -GLenum -glu_do_sampling_param_3D( GLUnurbsObj *nobj, new_ctrl_type *new_ctrl, - GLint **sfactors, GLint **tfactors) -{ - GLint dim; - GLenum err; - - *sfactors=NULL; - *tfactors=NULL; - dim=nobj->surface.geom.dim; - set_sampling_and_culling(nobj); - if((err=calc_sampling_param_3D(new_ctrl,nobj->parametric_tolerance,dim, - nobj->surface.geom.sorder,nobj->surface.geom.torder, - sfactors,tfactors))==GLU_ERROR) - { - revert_sampling_and_culling(nobj); - call_user_error(nobj,err); - return GLU_ERROR; - } - revert_sampling_and_culling(nobj); - return GLU_NO_ERROR; -} GLenum -glu_do_sampling_2D( GLUnurbsObj *nobj, GLfloat *ctrl, GLint cnt, GLint order, - GLint dim, GLint **factors) +glu_do_sampling_param_3D(GLUnurbsObj * nobj, new_ctrl_type * new_ctrl, + GLint ** sfactors, GLint ** tfactors) { - GLenum err; - - set_sampling_and_culling(nobj); - err=calc_sampling_2D(ctrl,cnt,order,nobj->sampling_tolerance,dim, - factors); - revert_sampling_and_culling(nobj); - return err; + GLint dim; + GLenum err; + + *sfactors = NULL; + *tfactors = NULL; + dim = nobj->surface.geom.dim; + set_sampling_and_culling(nobj); + if ( + (err = + calc_sampling_param_3D(new_ctrl, nobj->parametric_tolerance, dim, + nobj->surface.geom.sorder, + nobj->surface.geom.torder, sfactors, + tfactors)) == GLU_ERROR) { + revert_sampling_and_culling(nobj); + call_user_error(nobj, err); + return GLU_ERROR; + } + revert_sampling_and_culling(nobj); + return GLU_NO_ERROR; } -GLenum -glu_do_sampling_u( GLUnurbsObj *nobj, GLfloat *ctrl, GLint cnt, GLint order, - GLint dim, GLint **factors) +static GLenum +glu_do_sampling_2D(GLUnurbsObj * nobj, GLfloat * ctrl, GLint cnt, GLint order, + GLint dim, GLint ** factors) { - GLint i; - GLint u_steps; + GLenum err; - cnt /= order; - if((*factors=(GLint *)malloc(sizeof(GLint)*cnt)) - ==NULL) - { - return GLU_OUT_OF_MEMORY; - } - u_steps = nobj->u_step; - for(i=0; isampling_tolerance, dim, + factors); + revert_sampling_and_culling(nobj); + return err; } -GLenum -glu_do_sampling_param_2D( GLUnurbsObj *nobj, GLfloat *ctrl, GLint cnt, - GLint order, GLint dim, GLint **factors) + +static GLenum +glu_do_sampling_u(GLUnurbsObj * nobj, GLfloat * ctrl, GLint cnt, GLint order, + GLint dim, GLint ** factors) { - GLint i; - GLint u_steps; - GLfloat tolerance; + GLint i; + GLint u_steps; + + cnt /= order; + if ((*factors = (GLint *) malloc(sizeof(GLint) * cnt)) + == NULL) { + return GLU_OUT_OF_MEMORY; + } + u_steps = nobj->u_step; + for (i = 0; i < cnt; i++) + (*factors)[i] = u_steps; + return GLU_NO_ERROR; +} - set_sampling_and_culling(nobj); - tolerance = nobj->parametric_tolerance; - cnt /= order; - if((*factors=(GLint *)malloc(sizeof(GLint)*cnt)) - ==NULL) - { - revert_sampling_and_culling(nobj); - return GLU_OUT_OF_MEMORY; - } - u_steps = nobj->u_step; - for(i=0; iparametric_tolerance; + cnt /= order; + if ((*factors = (GLint *) malloc(sizeof(GLint) * cnt)) + == NULL) { + revert_sampling_and_culling(nobj); + return GLU_OUT_OF_MEMORY; + } + u_steps = nobj->u_step; + for (i = 0; i < cnt; i++) { + (*factors)[i] = calc_parametric_factor(ctrl, order, 0, + dim, tolerance, dim); + + } + revert_sampling_and_culling(nobj); + return GLU_NO_ERROR; } GLenum -glu_do_sampling_crv( GLUnurbsObj *nobj, GLfloat *ctrl, GLint cnt, GLint order, - GLint dim, GLint **factors) +glu_do_sampling_crv(GLUnurbsObj * nobj, GLfloat * ctrl, GLint cnt, + GLint order, GLint dim, GLint ** factors) { - GLenum err; - - *factors=NULL; - switch(nobj->sampling_method) - { - case GLU_PATH_LENGTH: - if((err=glu_do_sampling_2D(nobj,ctrl,cnt,order,dim,factors))!= - GLU_NO_ERROR) - { - call_user_error(nobj,err); - return GLU_ERROR; - } - break; - case GLU_DOMAIN_DISTANCE: - if((err=glu_do_sampling_u(nobj,ctrl,cnt,order,dim,factors))!= - GLU_NO_ERROR) - { - call_user_error(nobj,err); - return GLU_ERROR; - } - break; - case GLU_PARAMETRIC_ERROR: - if((err=glu_do_sampling_param_2D(nobj,ctrl,cnt,order,dim,factors))!= - GLU_NO_ERROR) - { - call_user_error(nobj,err); - return GLU_ERROR; - } - break; - default: - abort(); - } - - return GLU_NO_ERROR; + GLenum err; + + *factors = NULL; + switch (nobj->sampling_method) { + case GLU_PATH_LENGTH: + if ((err = glu_do_sampling_2D(nobj, ctrl, cnt, order, dim, factors)) != + GLU_NO_ERROR) { + call_user_error(nobj, err); + return GLU_ERROR; + } + break; + case GLU_DOMAIN_DISTANCE: + if ((err = glu_do_sampling_u(nobj, ctrl, cnt, order, dim, factors)) != + GLU_NO_ERROR) { + call_user_error(nobj, err); + return GLU_ERROR; + } + break; + case GLU_PARAMETRIC_ERROR: + if ( + (err = + glu_do_sampling_param_2D(nobj, ctrl, cnt, order, dim, + factors)) != GLU_NO_ERROR) { + call_user_error(nobj, err); + return GLU_ERROR; + } + break; + default: + abort(); + } + + return GLU_NO_ERROR; } /* TODO - i don't like this culling - this one just tests if at least one */ @@ -1215,68 +1133,62 @@ glu_do_sampling_crv( GLUnurbsObj *nobj, GLfloat *ctrl, GLint cnt, GLint order, /* should be included in the fnctions for efficiency reasons */ static GLboolean -point_in_viewport(GLfloat *pt, GLint dim) +point_in_viewport(GLfloat * pt, GLint dim) { - GLdouble model[16],proj[16]; - GLint viewport[4]; - GLdouble x,y,z,w,winx,winy,winz; - - glGetDoublev(GL_MODELVIEW_MATRIX,model); - glGetDoublev(GL_PROJECTION_MATRIX,proj); - glGetIntegerv(GL_VIEWPORT,viewport); - if(dim==3) - { - x=(GLdouble)pt[0]; - y=(GLdouble)pt[1]; - z=(GLdouble)pt[2]; - gluProject(x,y,z,model,proj,viewport,&winx,&winy,&winz); - } - else - { - w=(GLdouble)pt[3]; - x=(GLdouble)pt[0]/w; - y=(GLdouble)pt[1]/w; - z=(GLdouble)pt[2]/w; - gluProject(x,y,z,model,proj,viewport,&winx,&winy,&winz); - } - if((GLint)winx >= viewport[0] && (GLint)winx < viewport[2] && - (GLint)winy >= viewport[1] && (GLint)winy < viewport[3]) - return GL_TRUE; - return GL_FALSE; + GLdouble model[16], proj[16]; + GLint viewport[4]; + GLdouble x, y, z, w, winx, winy, winz; + + glGetDoublev(GL_MODELVIEW_MATRIX, model); + glGetDoublev(GL_PROJECTION_MATRIX, proj); + glGetIntegerv(GL_VIEWPORT, viewport); + if (dim == 3) { + x = (GLdouble) pt[0]; + y = (GLdouble) pt[1]; + z = (GLdouble) pt[2]; + gluProject(x, y, z, model, proj, viewport, &winx, &winy, &winz); + } + else { + w = (GLdouble) pt[3]; + x = (GLdouble) pt[0] / w; + y = (GLdouble) pt[1] / w; + z = (GLdouble) pt[2] / w; + gluProject(x, y, z, model, proj, viewport, &winx, &winy, &winz); + } + if ((GLint) winx >= viewport[0] && (GLint) winx < viewport[2] && + (GLint) winy >= viewport[1] && (GLint) winy < viewport[3]) + return GL_TRUE; + return GL_FALSE; } GLboolean -fine_culling_test_3D(GLUnurbsObj *nobj,GLfloat *pts,GLint s_cnt,GLint t_cnt, - GLint s_stride,GLint t_stride, GLint dim) +fine_culling_test_3D(GLUnurbsObj * nobj, GLfloat * pts, GLint s_cnt, + GLint t_cnt, GLint s_stride, GLint t_stride, GLint dim) { - GLint i,j; - - if(nobj->culling==GL_FALSE) - return GL_FALSE; - set_sampling_and_culling(nobj); - - if(dim==3) - { - for(i=0;iculling == GL_FALSE) + return GL_FALSE; + set_sampling_and_culling(nobj); + + if (dim == 3) { + for (i = 0; i < s_cnt; i++) + for (j = 0; j < t_cnt; j++) + if (point_in_viewport(pts + i * s_stride + j * t_stride, dim)) { + revert_sampling_and_culling(nobj); + return GL_FALSE; + } + } + else { + for (i = 0; i < s_cnt; i++) + for (j = 0; j < t_cnt; j++) + if (point_in_viewport(pts + i * s_stride + j * t_stride, dim)) { + revert_sampling_and_culling(nobj); + return GL_FALSE; + } + } + revert_sampling_and_culling(nobj); + return GL_TRUE; } /*GLboolean @@ -1336,35 +1248,31 @@ fine_culling_test_3D(GLUnurbsObj *nobj,GLfloat *pts,GLint s_cnt,GLint t_cnt, }*/ GLboolean -fine_culling_test_2D(GLUnurbsObj *nobj,GLfloat *pts,GLint cnt, - GLint stride, GLint dim) +fine_culling_test_2D(GLUnurbsObj * nobj, GLfloat * pts, GLint cnt, + GLint stride, GLint dim) { - GLint i; - - if(nobj->culling==GL_FALSE) - return GL_FALSE; - set_sampling_and_culling(nobj); - - if(dim==3) - { - for(i=0;iculling == GL_FALSE) + return GL_FALSE; + set_sampling_and_culling(nobj); + + if (dim == 3) { + for (i = 0; i < cnt; i++) + if (point_in_viewport(pts + i * stride, dim)) { + revert_sampling_and_culling(nobj); + return GL_FALSE; + } + } + else { + for (i = 0; i < cnt; i++) + if (point_in_viewport(pts + i * stride, dim)) { + revert_sampling_and_culling(nobj); + return GL_FALSE; + } + } + revert_sampling_and_culling(nobj); + return GL_TRUE; } /*GLboolean @@ -1400,4 +1308,3 @@ fine_culling_test_2D(GLUnurbsObj *nobj,GLfloat *pts,GLint cnt, revert_sampling_and_culling(nobj); return (GLboolean)(visible_cnt==0); }*/ - diff --git a/src/glu/mesa/polytest.c b/src/glu/mesa/polytest.c new file mode 100644 index 00000000000..0995cb032f0 --- /dev/null +++ b/src/glu/mesa/polytest.c @@ -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 +#include +#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; +} diff --git a/src/glu/mesa/project.c b/src/glu/mesa/project.c index 6aa75a5d572..c8ab95992af 100644 --- a/src/glu/mesa/project.c +++ b/src/glu/mesa/project.c @@ -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 diff --git a/src/glu/mesa/quadric.c b/src/glu/mesa/quadric.c index 943c885a598..5d7bc8f5c61 100644 --- a/src/glu/mesa/quadric.c +++ b/src/glu/mesa/quadric.c @@ -1,4 +1,4 @@ -/* $Id: quadric.c,v 1.7 2000/02/10 17:45:52 brianp Exp $ */ +/* $Id: quadric.c,v 1.8 2000/07/11 14:11:04 brianp Exp $ */ /* * Mesa 3-D graphics library @@ -36,11 +36,21 @@ #include #include #include "gluP.h" -#include "tess_macros.h" #endif +#ifndef M_PI +# define M_PI (3.1415926) +#endif + + +/* + * Convert degrees to radians: + */ +#define DEG_TO_RAD(A) ((A)*(M_PI/180.0)) + + /* * Sin and Cos for degree angles: */ @@ -55,12 +65,13 @@ -struct GLUquadric { - GLenum DrawStyle; /* GLU_FILL, LINE, SILHOUETTE, or POINT */ - GLenum Orientation; /* GLU_INSIDE or GLU_OUTSIDE */ - GLboolean TextureFlag; /* Generate texture coords? */ - GLenum Normals; /* GLU_NONE, GLU_FLAT, or GLU_SMOOTH */ - void (GLCALLBACKP ErrorFunc)(GLenum err); /* Error handler callback function */ +struct GLUquadric +{ + GLenum DrawStyle; /* GLU_FILL, LINE, SILHOUETTE, or POINT */ + GLenum Orientation; /* GLU_INSIDE or GLU_OUTSIDE */ + GLboolean TextureFlag; /* Generate texture coords? */ + GLenum Normals; /* GLU_NONE, GLU_FLAT, or GLU_SMOOTH */ + void (GLCALLBACK * ErrorFunc) (GLenum err); /* Error handler callback function */ }; @@ -68,26 +79,29 @@ struct GLUquadric { /* * Process a GLU error. */ -static void quadric_error( GLUquadricObj *qobj, GLenum error, const char *msg ) +static void +quadric_error(GLUquadricObj * qobj, GLenum error, const char *msg) { /* Call the error call back function if any */ if (qobj->ErrorFunc) { - (*qobj->ErrorFunc)( error ); + (*qobj->ErrorFunc) (error); } /* Print a message to stdout if MESA_DEBUG variable is defined */ if (getenv("MESA_DEBUG")) { - fprintf(stderr,"GLUError: %s: %s\n", (char*) gluErrorString(error), msg); + fprintf(stderr, "GLUError: %s: %s\n", (char *) gluErrorString(error), + msg); } } -GLUquadricObj * GLAPIENTRY gluNewQuadric( void ) +GLUquadricObj *GLAPIENTRY +gluNewQuadric(void) { GLUquadricObj *q; - q = (GLUquadricObj *) malloc( sizeof(struct GLUquadric) ); + q = (GLUquadricObj *) malloc(sizeof(struct GLUquadric)); if (q) { q->DrawStyle = GLU_FILL; q->Orientation = GLU_OUTSIDE; @@ -100,10 +114,11 @@ GLUquadricObj * GLAPIENTRY gluNewQuadric( void ) -void GLAPIENTRY gluDeleteQuadric( GLUquadricObj *state ) +void GLAPIENTRY +gluDeleteQuadric(GLUquadricObj * state) { if (state) { - free( (void *) state ); + free((void *) state); } } @@ -113,14 +128,16 @@ void GLAPIENTRY gluDeleteQuadric( GLUquadricObj *state ) * Set the drawing style to be GLU_FILL, GLU_LINE, GLU_SILHOUETTE, * or GLU_POINT. */ -void GLAPIENTRY gluQuadricDrawStyle( GLUquadricObj *quadObject, GLenum drawStyle ) +void GLAPIENTRY +gluQuadricDrawStyle(GLUquadricObj * quadObject, GLenum drawStyle) { - if (quadObject && (drawStyle==GLU_FILL || drawStyle==GLU_LINE - || drawStyle==GLU_SILHOUETTE || drawStyle==GLU_POINT)) { + if (quadObject && (drawStyle == GLU_FILL || drawStyle == GLU_LINE + || drawStyle == GLU_SILHOUETTE + || drawStyle == GLU_POINT)) { quadObject->DrawStyle = drawStyle; } else { - quadric_error( quadObject, GLU_INVALID_ENUM, "qluQuadricDrawStyle" ); + quadric_error(quadObject, GLU_INVALID_ENUM, "qluQuadricDrawStyle"); } } @@ -129,14 +146,15 @@ void GLAPIENTRY gluQuadricDrawStyle( GLUquadricObj *quadObject, GLenum drawStyle /* * Set the orientation to GLU_INSIDE or GLU_OUTSIDE. */ -void GLAPIENTRY gluQuadricOrientation( GLUquadricObj *quadObject, - GLenum orientation ) +void GLAPIENTRY +gluQuadricOrientation(GLUquadricObj * quadObject, GLenum orientation) { - if (quadObject && (orientation==GLU_INSIDE || orientation==GLU_OUTSIDE)) { + if (quadObject + && (orientation == GLU_INSIDE || orientation == GLU_OUTSIDE)) { quadObject->Orientation = orientation; } else { - quadric_error( quadObject, GLU_INVALID_ENUM, "qluQuadricOrientation" ); + quadric_error(quadObject, GLU_INVALID_ENUM, "qluQuadricOrientation"); } } @@ -145,41 +163,44 @@ void GLAPIENTRY gluQuadricOrientation( GLUquadricObj *quadObject, /* * Set the error handler callback function. */ -void GLAPIENTRY gluQuadricCallback( GLUquadricObj *qobj, - GLenum which, void (GLCALLBACKP fn)() ) +void GLAPIENTRY +gluQuadricCallback(GLUquadricObj * qobj, + GLenum which, void (GLCALLBACK * fn) ()) { /* * UGH, this is a mess! I thought ANSI was a standard. */ - if (qobj && which==GLU_ERROR) { + if (qobj && which == GLU_ERROR) { #ifdef __CYGWIN32__ - qobj->ErrorFunc = (void(GLCALLBACKPCAST)(GLenum))fn; + qobj->ErrorFunc = (void (GLCALLBACKPCAST) (GLenum)) fn; #elif defined(OPENSTEP) - qobj->ErrorFunc = (void(*)(GLenum))fn; + qobj->ErrorFunc = (void (*)(GLenum)) fn; #elif defined(_WIN32) - qobj->ErrorFunc = (void(GLCALLBACKP)(int))fn; + qobj->ErrorFunc = (void (GLCALLBACK *) (int)) fn; #elif defined(__STORM__) - qobj->ErrorFunc = (void(GLCALLBACKP)(GLenum))fn; + qobj->ErrorFunc = (void (GLCALLBACK *) (GLenum)) fn; #elif defined(__BEOS__) - qobj->ErrorFunc = (void(*)(GLenum))fn; + qobj->ErrorFunc = (void (*)(GLenum)) fn; #else - qobj->ErrorFunc = (void(GLCALLBACKP)())fn; + qobj->ErrorFunc = (void (GLCALLBACK *) ()) fn; #endif } } -void GLAPIENTRY gluQuadricNormals( GLUquadricObj *quadObject, GLenum normals ) +void GLAPIENTRY +gluQuadricNormals(GLUquadricObj * quadObject, GLenum normals) { if (quadObject - && (normals==GLU_NONE || normals==GLU_FLAT || normals==GLU_SMOOTH)) { + && (normals == GLU_NONE || normals == GLU_FLAT + || normals == GLU_SMOOTH)) { quadObject->Normals = normals; } } -void GLAPIENTRY gluQuadricTexture( GLUquadricObj *quadObject, - GLboolean textureCoords ) +void GLAPIENTRY +gluQuadricTexture(GLUquadricObj * quadObject, GLboolean textureCoords) { if (quadObject) { quadObject->TextureFlag = textureCoords; @@ -192,70 +213,72 @@ void GLAPIENTRY gluQuadricTexture( GLUquadricObj *quadObject, /* * Call glNormal3f after scaling normal to unit length. */ -static void normal3f( GLfloat x, GLfloat y, GLfloat z ) +static void +normal3f(GLfloat x, GLfloat y, GLfloat z) { GLdouble mag; - mag = sqrt( x*x + y*y + z*z ); - if (mag>0.00001F) { + mag = sqrt(x * x + y * y + z * z); + if (mag > 0.00001F) { x /= mag; y /= mag; z /= mag; } - glNormal3f( x, y, z ); + glNormal3f(x, y, z); } -void GLAPIENTRY gluCylinder( GLUquadricObj *qobj, - GLdouble baseRadius, GLdouble topRadius, - GLdouble height, GLint slices, GLint stacks ) +void GLAPIENTRY +gluCylinder(GLUquadricObj * qobj, + GLdouble baseRadius, GLdouble topRadius, + GLdouble height, GLint slices, GLint stacks) { GLdouble da, r, dr, dz; GLfloat x, y, z, nz, nsign; GLint i, j; - if (qobj->Orientation==GLU_INSIDE) { + if (qobj->Orientation == GLU_INSIDE) { nsign = -1.0; } else { nsign = 1.0; } - da = 2.0*M_PI / slices; - dr = (topRadius-baseRadius) / stacks; + da = 2.0 * M_PI / slices; + dr = (topRadius - baseRadius) / stacks; dz = height / stacks; - nz = (baseRadius-topRadius) / height; /* Z component of normal vectors */ + nz = (baseRadius - topRadius) / height; /* Z component of normal vectors */ - if (qobj->DrawStyle==GLU_POINT) { - glBegin( GL_POINTS ); - for (i=0;iDrawStyle == GLU_POINT) { + glBegin(GL_POINTS); + for (i = 0; i < slices; i++) { + x = cos(i * da); + y = sin(i * da); + normal3f(x * nsign, y * nsign, nz * nsign); z = 0.0; r = baseRadius; - for (j=0;j<=stacks;j++) { - glVertex3f( x*r, y*r, z ); + for (j = 0; j <= stacks; j++) { + glVertex3f(x * r, y * r, z); z += dz; r += dr; } } glEnd(); } - else if (qobj->DrawStyle==GLU_LINE || qobj->DrawStyle==GLU_SILHOUETTE) { + else if (qobj->DrawStyle == GLU_LINE || qobj->DrawStyle == GLU_SILHOUETTE) { /* Draw rings */ - if (qobj->DrawStyle==GLU_LINE) { + if (qobj->DrawStyle == GLU_LINE) { z = 0.0; r = baseRadius; - for (j=0;j<=stacks;j++) { - glBegin( GL_LINE_LOOP ); - for (i=0;iDrawStyle==GLU_FILL) { + else if (qobj->DrawStyle == GLU_FILL) { GLfloat ds = 1.0 / slices; GLfloat dt = 1.0 / stacks; GLfloat t = 0.0; z = 0.0; r = baseRadius; - for (j=0;jNormals==GLU_NONE) { + if (qobj->Normals == GLU_NONE) { normals = GL_FALSE; } else { normals = GL_TRUE; } - if (qobj->Orientation==GLU_INSIDE) { + if (qobj->Orientation == GLU_INSIDE) { nsign = -1.0; } else { @@ -373,131 +396,140 @@ void GLAPIENTRY gluSphere( GLUquadricObj *qobj, /* t goes from -1.0/+1.0 at z = -radius/+radius (linear along longitudes) */ /* cannot use triangle fan on texturing (s coord. at top/bottom tip varies) */ - if (qobj->DrawStyle==GLU_FILL) { - if (!qobj->TextureFlag) { - /* draw +Z end as a triangle fan */ - glBegin( GL_TRIANGLE_FAN ); - glNormal3f( 0.0, 0.0, 1.0 ); - TXTR_COORD(0.5,1.0); - glVertex3f( 0.0, 0.0, nsign * radius ); - for (j=0;j<=slices;j++) { - theta = (j==slices) ? 0.0 : j * dtheta; - x = -sin(theta) * sin(drho); - y = cos(theta) * sin(drho); - z = nsign * cos(drho); - if (normals) glNormal3f( x*nsign, y*nsign, z*nsign ); - glVertex3f( x*radius, y*radius, z*radius ); + if (qobj->DrawStyle == GLU_FILL) { + if (!qobj->TextureFlag) { + /* draw +Z end as a triangle fan */ + glBegin(GL_TRIANGLE_FAN); + glNormal3f(0.0, 0.0, 1.0); + TXTR_COORD(0.5, 1.0); + glVertex3f(0.0, 0.0, nsign * radius); + for (j = 0; j <= slices; j++) { + theta = (j == slices) ? 0.0 : j * dtheta; + x = -sin(theta) * sin(drho); + y = cos(theta) * sin(drho); + z = nsign * cos(drho); + if (normals) + glNormal3f(x * nsign, y * nsign, z * nsign); + glVertex3f(x * radius, y * radius, z * radius); + } + glEnd(); } - glEnd(); - } ds = 1.0 / slices; dt = 1.0 / stacks; - t = 1.0; /* because loop now runs from 0 */ + t = 1.0; /* because loop now runs from 0 */ if (qobj->TextureFlag) { - imin = 0; - imax = stacks; + imin = 0; + imax = stacks; } else { - imin = 1; - imax = stacks-1; + imin = 1; + imax = stacks - 1; } /* draw intermediate stacks as quad strips */ - for (i=imin;iTextureFlag) { - /* draw -Z end as a triangle fan */ - glBegin( GL_TRIANGLE_FAN ); - glNormal3f( 0.0, 0.0, -1.0 ); - TXTR_COORD(0.5,0.0); - glVertex3f( 0.0, 0.0, -radius*nsign ); - rho = M_PI - drho; - s = 1.0; - t = dt; - for (j=slices;j>=0;j--) { - theta = (j==slices) ? 0.0 : j * dtheta; - x = -sin(theta) * sin(rho); - y = cos(theta) * sin(rho); - z = nsign * cos(rho); - if (normals) glNormal3f( x*nsign, y*nsign, z*nsign ); - TXTR_COORD(s,t); - s -= ds; - glVertex3f( x*radius, y*radius, z*radius ); + if (!qobj->TextureFlag) { + /* draw -Z end as a triangle fan */ + glBegin(GL_TRIANGLE_FAN); + glNormal3f(0.0, 0.0, -1.0); + TXTR_COORD(0.5, 0.0); + glVertex3f(0.0, 0.0, -radius * nsign); + rho = M_PI - drho; + s = 1.0; + t = dt; + for (j = slices; j >= 0; j--) { + theta = (j == slices) ? 0.0 : j * dtheta; + x = -sin(theta) * sin(rho); + y = cos(theta) * sin(rho); + z = nsign * cos(rho); + if (normals) + glNormal3f(x * nsign, y * nsign, z * nsign); + TXTR_COORD(s, t); + s -= ds; + glVertex3f(x * radius, y * radius, z * radius); + } + glEnd(); } - glEnd(); - } } - else if (qobj->DrawStyle==GLU_LINE || qobj->DrawStyle==GLU_SILHOUETTE) { + else if (qobj->DrawStyle == GLU_LINE || qobj->DrawStyle == GLU_SILHOUETTE) { /* draw stack lines */ - for (i=1;iDrawStyle==GLU_POINT) { + else if (qobj->DrawStyle == GLU_POINT) { /* top and bottom-most points */ - glBegin( GL_POINTS ); - if (normals) glNormal3f( 0.0, 0.0, nsign ); - glVertex3d( 0.0, 0.0, radius ); - if (normals) glNormal3f( 0.0, 0.0, -nsign ); - glVertex3d( 0.0, 0.0, -radius ); + glBegin(GL_POINTS); + if (normals) + glNormal3f(0.0, 0.0, nsign); + glVertex3d(0.0, 0.0, radius); + if (normals) + glNormal3f(0.0, 0.0, -nsign); + glVertex3d(0.0, 0.0, -radius); /* loop over stacks */ - for (i=1;iNormals!=GLU_NONE) { - if (qobj->Orientation==GLU_OUTSIDE) { - glNormal3f( 0.0, 0.0, +1.0 ); + if (qobj->Normals != GLU_NONE) { + if (qobj->Orientation == GLU_OUTSIDE) { + glNormal3f(0.0, 0.0, +1.0); } else { - glNormal3f( 0.0, 0.0, -1.0 ); + glNormal3f(0.0, 0.0, -1.0); } } - da = 2.0*M_PI / slices; - dr = (outerRadius-innerRadius) / (GLfloat) loops; + da = 2.0 * M_PI / slices; + dr = (outerRadius - innerRadius) / (GLfloat) loops; switch (qobj->DrawStyle) { - case GLU_FILL: + case GLU_FILL: { - /* texture of a gluDisk is a cut out of the texture unit square - * x, y in [-outerRadius, +outerRadius]; s, t in [0, 1] - * (linear mapping) - */ - GLfloat dtc = 2.0f * outerRadius; - GLfloat sa,ca; - GLfloat r1 = innerRadius; - GLint l; - for (l=0; lOrientation==GLU_OUTSIDE) { - GLint s; - glBegin( GL_QUAD_STRIP ); - for (s=0;s<=slices;s++) { - GLfloat a; - if (s==slices) a = 0.0; - else a = s * da; - sa = sin(a); ca = cos(a); - TXTR_COORD(0.5+sa*r2/dtc,0.5+ca*r2/dtc); - glVertex2f( r2*sa, r2*ca ); - TXTR_COORD(0.5+sa*r1/dtc,0.5+ca*r1/dtc); - glVertex2f( r1*sa, r1*ca ); + if (qobj->Orientation == GLU_OUTSIDE) { + GLint s; + glBegin(GL_QUAD_STRIP); + for (s = 0; s <= slices; s++) { + GLfloat a; + if (s == slices) + a = 0.0; + else + a = s * da; + sa = sin(a); + ca = cos(a); + TXTR_COORD(0.5 + sa * r2 / dtc, 0.5 + ca * r2 / dtc); + glVertex2f(r2 * sa, r2 * ca); + TXTR_COORD(0.5 + sa * r1 / dtc, 0.5 + ca * r1 / dtc); + glVertex2f(r1 * sa, r1 * ca); } glEnd(); } else { - GLint s; - glBegin( GL_QUAD_STRIP ); - for (s=slices;s>=0;s--) { - GLfloat a; - if (s==slices) a = 0.0; - else a = s * da; - sa = sin(a); ca = cos(a); - TXTR_COORD(0.5-sa*r2/dtc,0.5+ca*r2/dtc); - glVertex2f( r2*sa, r2*ca ); - TXTR_COORD(0.5-sa*r1/dtc,0.5+ca*r1/dtc); - glVertex2f( r1*sa, r1*ca ); + GLint s; + glBegin(GL_QUAD_STRIP); + for (s = slices; s >= 0; s--) { + GLfloat a; + if (s == slices) + a = 0.0; + else + a = s * da; + sa = sin(a); + ca = cos(a); + TXTR_COORD(0.5 - sa * r2 / dtc, 0.5 + ca * r2 / dtc); + glVertex2f(r2 * sa, r2 * ca); + TXTR_COORD(0.5 - sa * r1 / dtc, 0.5 + ca * r1 / dtc); + glVertex2f(r1 * sa, r1 * ca); } glEnd(); } r1 = r2; } - break; + break; } - case GLU_LINE: + case GLU_LINE: { - GLint l, s; + GLint l, s; /* draw loops */ - for (l=0; l<=loops; l++) { - GLfloat r = innerRadius + l * dr; - glBegin( GL_LINE_LOOP ); - for (s=0; sNormals!=GLU_NONE) { - if (qobj->Orientation==GLU_OUTSIDE) { - glNormal3f( 0.0, 0.0, +1.0 ); + if (qobj->Normals != GLU_NONE) { + if (qobj->Orientation == GLU_OUTSIDE) { + glNormal3f(0.0, 0.0, +1.0); } else { - glNormal3f( 0.0, 0.0, -1.0 ); + glNormal3f(0.0, 0.0, -1.0); } } - if (qobj->DrawStyle==GLU_POINT) { + if (qobj->DrawStyle == GLU_POINT) { GLint loop, slice; GLdouble radius, delta_radius; GLdouble angle, delta_angle; - delta_radius = (outerRadius - innerRadius) / (loops-1); - delta_angle = DEG_TO_RAD((sweepAngle) / (slices-1)); - glBegin( GL_POINTS ); + delta_radius = (outerRadius - innerRadius) / (loops - 1); + delta_angle = DEG_TO_RAD((sweepAngle) / (slices - 1)); + glBegin(GL_POINTS); radius = innerRadius; - for (loop=0; loopDrawStyle==GLU_LINE) { + else if (qobj->DrawStyle == GLU_LINE) { GLint loop, slice; GLdouble radius, delta_radius; GLdouble angle, delta_angle; @@ -694,11 +733,11 @@ void GLAPIENTRY gluPartialDisk( GLUquadricObj *qobj, GLdouble innerRadius, delta_angle = DEG_TO_RAD(sweepAngle / slices); /* draw rings */ radius = innerRadius; - for (loop=0; loopDrawStyle==GLU_SILHOUETTE) { + else if (qobj->DrawStyle == GLU_SILHOUETTE) { GLint slice; GLdouble angle, delta_angle; delta_angle = DEG_TO_RAD(sweepAngle / slices); /* draw outer ring */ - glBegin( GL_LINE_STRIP ); + glBegin(GL_LINE_STRIP); angle = DEG_TO_RAD(startAngle); - for (slice=0; slice<=slices; slice++) { - glVertex2d( outerRadius * sin(angle), outerRadius * cos(angle) ); + for (slice = 0; slice <= slices; slice++) { + glVertex2d(outerRadius * sin(angle), outerRadius * cos(angle)); angle += delta_angle; } glEnd(); /* draw inner ring */ - if (innerRadius>0.0) { - glBegin( GL_LINE_STRIP ); + if (innerRadius > 0.0) { + glBegin(GL_LINE_STRIP); angle = DEG_TO_RAD(startAngle); - for (slice=0; sliceDrawStyle==GLU_FILL) { + else if (qobj->DrawStyle == GLU_FILL) { GLint loop, slice; GLdouble radius, delta_radius; GLdouble angle, delta_angle; delta_radius = (outerRadius - innerRadius) / loops; delta_angle = DEG_TO_RAD(sweepAngle / slices); radius = innerRadius; - for (loop=0; loopOrientation==GLU_OUTSIDE) { - glVertex2d( (radius+delta_radius)*sin(angle), - (radius+delta_radius)*cos(angle) ); - glVertex2d( radius * sin(angle), radius * cos(angle) ); + for (slice = 0; slice <= slices; slice++) { + if (qobj->Orientation == GLU_OUTSIDE) { + glVertex2d((radius + delta_radius) * sin(angle), + (radius + delta_radius) * cos(angle)); + glVertex2d(radius * sin(angle), radius * cos(angle)); } else { - glVertex2d( radius * sin(angle), radius * cos(angle) ); - glVertex2d( (radius+delta_radius)*sin(angle), - (radius+delta_radius)*cos(angle) ); + glVertex2d(radius * sin(angle), radius * cos(angle)); + glVertex2d((radius + delta_radius) * sin(angle), + (radius + delta_radius) * cos(angle)); } angle += delta_angle; } @@ -778,6 +821,3 @@ void GLAPIENTRY gluPartialDisk( GLUquadricObj *qobj, GLdouble innerRadius, } } } - - - diff --git a/src/glu/mesa/tess.c b/src/glu/mesa/tess.c index 919643cb8e2..7e05dbb0d08 100644 --- a/src/glu/mesa/tess.c +++ b/src/glu/mesa/tess.c @@ -1,1038 +1,317 @@ -/* $Id: tess.c,v 1.24 2000/02/10 17:45:52 brianp Exp $ */ +/* $Id: tess.c,v 1.25 2000/07/11 14:11:04 brianp Exp $ */ /* * Mesa 3-D graphics library * Version: 3.3 + * Copyright (C) 1995-2000 Brian Paul * - * Copyright (C) 1999-2000 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 - * - *****************************************************************************/ -#include -#include -#include -#include +/* + * This file is part of the polygon tesselation code contributed by + * Bogdan Sikorski + */ -#include "gluP.h" +#ifdef PC_HEADER +#include "all.h" +#else +#include +#include #include "tess.h" -#include "tess_macros.h" -#include "tess_fist.h" -#if 0 -#include "tess_grid.h" #endif -#define TESS_CHECK_ERRORS(t) if ( (t)->error != GLU_NO_ERROR ) goto cleanup - -#ifdef DEBUG -GLint tess_dbg_level; -#endif - - -/***************************************************************************** - * tess_error_callback - * - * Internal error handler. Call the user-registered error callback. - * - * 2nd arg changed from 'errno' to 'errnum' since MSVC defines errnum as - * a macro (of all things) and thus breaks the build -tjump - *****************************************************************************/ -void tess_error_callback( GLUtesselator *tobj, GLenum errnum ) -{ - if ( tobj->error == GLU_NO_ERROR ) - { - tobj->error = errnum; - } - - if ( tobj->callbacks.errorData != NULL ) - { - ( tobj->callbacks.errorData )( errnum, tobj->data ); - } - else if ( tobj->callbacks.error != NULL ) - { - ( tobj->callbacks.error )( errnum ); - } -} - - -/***************************************************************************** - * init_callbacks - *****************************************************************************/ -static void init_callbacks( tess_callbacks_t *callbacks ) -{ - callbacks->begin = ( void (GLCALLBACKPCAST)(GLenum) ) NULL; - callbacks->beginData = ( void (GLCALLBACKPCAST)(GLenum, void *) ) NULL; - callbacks->edgeFlag = ( void (GLCALLBACKPCAST)(GLboolean) ) NULL; - callbacks->edgeFlagData = ( void (GLCALLBACKPCAST)(GLboolean, void *) ) NULL; - callbacks->vertex = ( void (GLCALLBACKPCAST)(void *) ) NULL; - callbacks->vertexData = ( void (GLCALLBACKPCAST)(void *, void *) ) NULL; - callbacks->end = ( void (GLCALLBACKPCAST)(void) ) NULL; - callbacks->endData = ( void (GLCALLBACKPCAST)(void *) ) NULL; - callbacks->error = ( void (GLCALLBACKPCAST)(GLenum) ) NULL; - callbacks->errorData = ( void (GLCALLBACKPCAST)(GLenum, void *) ) NULL; - callbacks->combine = ( void (GLCALLBACKPCAST)(GLdouble [3], void *[4], - GLfloat [4], void **) ) NULL; - callbacks->combineData = ( void (GLCALLBACKPCAST)(GLdouble [3], void *[4], - GLfloat [4], void **, - void *) ) NULL; -} - - -/***************************************************************************** - * find_normal - *****************************************************************************/ -static GLenum find_normal( GLUtesselator *tobj ) -{ - tess_contour_t *contour = tobj->current_contour; - tess_vertex_t *va, *vb, *vc; - GLdouble a[3], b[3], c[3]; - - MSG( 15, " --> find_normal( tobj:%p )\n", tobj ); - - if ( contour == NULL ) { return GLU_ERROR; } - - va = contour->vertices; - vb = va->next; - - /* If va and vb are the same point, keep looking for a different vertex. */ - - while ( IS_EQUAL_3DV( va->coords, vb->coords ) && ( vb != va ) ) { - vb = vb->next; - } - - if ( vb == va ) { - /* FIXME: What error is this? */ - tess_error_callback( tobj, GLU_TESS_ERROR7 ); - } - - SUB_3V( a, vb->coords, va->coords ); - - for ( vc = vb->next; vc != va; vc = vc->next ) - { - SUB_3V( b, vc->coords, va->coords ); - - CROSS_3V( c, a, b ); - - if ( ! IS_ZERO_3DV( c ) ) - { - MSG( 15, " using (%.2f,%.2f) -> (%.2f,%.2f) -> (%.2f,%.2f)\n", - va->coords[X], va->coords[Y], - vb->coords[X], vb->coords[Y], - vc->coords[X], vc->coords[Y] ); - - COPY_3V( contour->plane.normal, c ); - NORMALIZE_3DV( contour->plane.normal ); - - contour->plane.dist = - DOT_3V( contour->plane.normal, - va->coords ); - - MSG( 15, " <-- find_normal( tobj:%p ) n: (%.2f, %.2f, %.2f)\n", tobj, contour->plane.normal[X], contour->plane.normal[Y], contour->plane.normal[Z] ); - return GLU_NO_ERROR; - } - } - /* FIXME: What error is this? */ - tess_error_callback( tobj, GLU_TESS_ERROR7 ); - - return GLU_ERROR; -} - -/***************************************************************************** - * twice_contour_area - * - * Calculate the twice the signed area of the given contour. Used to - * determine the contour's orientation amongst other things. - *****************************************************************************/ -GLdouble twice_contour_area( tess_contour_t *contour ) -{ - tess_vertex_t *vertex = contour->vertices; - GLdouble area, x, y; - - area = 0.0; - - x = vertex->v[X]; - y = vertex->v[Y]; - - vertex = vertex->next; - - do - { - area += ( (vertex->v[X] - x) * (vertex->next->v[Y] - y) - - (vertex->v[Y] - y) * (vertex->next->v[X] - x) ); - vertex = vertex->next; - } - while ( vertex != contour->vertices ); - - return area; -} - -/***************************************************************************** - * project_current_contour - * - * Project the contour's vertices onto the tessellation plane. We perform - * a complex rotation here to allow non-axis-aligned tessellation normals. - *****************************************************************************/ -static void project_current_contour( GLUtesselator *tobj ) -{ - tess_contour_t *current = tobj->current_contour; - tess_vertex_t *vertex; - GLdouble zaxis[3] = { 0.0, 0.0, 1.0 }, znormal[3], xnormal[3]; - GLdouble dot, rotx, roty; - GLint i; - - MSG( 15, " --> project_current_contour( tobj:%p )\n", tobj ); - - if ( current == NULL ) { return; } - - /* Rotate the plane normal around the y-axis. */ - - znormal[X] = current->plane.normal[X]; - znormal[Y] = 0.0; - znormal[Z] = current->plane.normal[Z]; - - dot = DOT_3V( znormal, zaxis ); - current->roty = roty = acos( dot ); - - /* Rotate the plane normal around the x-axis. */ - - xnormal[X] = cos( roty ) * znormal[X] - sin( roty ) * znormal[Z]; - xnormal[Y] = znormal[Y]; - xnormal[Z] = sin( roty ) * znormal[X] + cos( roty ) * znormal[Z]; - - dot = DOT_3V( xnormal, zaxis ); - current->rotx = rotx = acos( dot ); - - for ( vertex = current->vertices, i = 0; - i < current->num_vertices; vertex = vertex->next, i++ ) - { - tess_plane_t *plane = ¤t->plane; - GLdouble proj[3], yrot[3], xrot[3]; - - /* FIXME: This needs a cleanup, 'cos I'm sure it's inefficient. */ - - proj[X] = vertex->coords[X] - plane->dist * plane->normal[X]; - proj[Y] = vertex->coords[Y] - plane->dist * plane->normal[Y]; - proj[Z] = vertex->coords[Z] - plane->dist * plane->normal[Z]; - - yrot[X] = cos( roty ) * proj[X] - sin( roty ) * proj[Z]; - yrot[Y] = proj[Y]; - yrot[Z] = sin( roty ) * proj[X] + cos( roty ) * proj[Z]; - - xrot[X] = yrot[X]; - xrot[Y] = cos( rotx ) * yrot[Y] - sin( rotx ) * yrot[Z]; - xrot[Z] = sin( rotx ) * yrot[Y] + cos( rotx ) * yrot[Z]; - - vertex->v[X] = xrot[X]; - vertex->v[Y] = xrot[Y]; - - ACC_BBOX_2V( vertex->v, tobj->mins, tobj->maxs ); - ACC_BBOX_2V( vertex->v, current->mins, current->maxs ); - } - - current->area = twice_contour_area( current ); - current->orientation = ( current->area >= 0.0 ) ? GLU_CCW : GLU_CW; - - MSG( 15, " area: %.2f orientation: %s\n", - current->area, ( current->orientation == GLU_CCW ) ? "CCW" : "CW" ); - - MSG( 15, " <-- project_current_contour( tobj:%p )\n", tobj ); -} - -/***************************************************************************** - * save_current_contour - *****************************************************************************/ -static GLenum save_current_contour( GLUtesselator *tobj ) -{ - tess_contour_t *current = tobj->current_contour; - tess_vertex_t *vertex; - GLint i; - - if ( current == NULL ) { return GLU_ERROR; } - - if ( tobj->contours == NULL ) - { - tobj->contours = tobj->last_contour = current; - current->next = current->prev = NULL; - - tobj->orientation = current->orientation; - } - else - { - current->prev = tobj->last_contour; - - tobj->last_contour->next = current; - tobj->last_contour = current; - - current->next = NULL; - } - - for ( vertex = current->vertices, i = 0; - i < current->num_vertices; vertex = vertex->next, i++ ) - { - vertex->edge_flag = GL_TRUE; - } - - current->type = GLU_UNKNOWN; - - tobj->num_contours++; - tobj->current_contour = NULL; - - return GLU_NO_ERROR; -} - -/***************************************************************************** - * inspect_current_contour - *****************************************************************************/ -static void inspect_current_contour( GLUtesselator *tobj ) -{ - tess_contour_t *current = tobj->current_contour; - GLdouble origin[3] = { 0.0, 0.0, 0.0 }; - GLboolean calc_normal = GL_FALSE; - - MSG( 15, " --> inspect_current_contour( tobj:%p )\n", tobj ); - - if ( current->num_vertices < 3 ) - { - MSG( 15, " count %d < 3, deleting\n", current->num_vertices ); - delete_contour( &tobj->current_contour ); - return; - } - - current->last_vertex->next = current->vertices; - current->vertices->prev = current->last_vertex; - - MSG( 15, " current normal: (%.2f, %.2f, %.2f)\n", current->plane.normal[X], current->plane.normal[Y], current->plane.normal[Z] ); - - if ( IS_EQUAL_3DV( current->plane.normal, origin ) ) - { - /* We haven't been given a normal, so let's take a guess. */ - if ( find_normal( tobj ) == GLU_ERROR ) { - return; - } - - COPY_3V( tobj->plane.normal, current->plane.normal ); - tobj->plane.dist = current->plane.dist; - - calc_normal = GL_TRUE; - } - - project_current_contour( tobj ); - - if ( calc_normal && ( tobj->current_contour->orientation == GLU_CW ) ) - { - MSG( 15, " oops, let's try that again...\n" ); - - /* - * FIXME: We've used a reflex angle to calculate the normal. At - * the moment, we simply reverse the normal and re-project the - * contour, but this is sloooow... - */ - NEG_3V( tobj->plane.normal ); - NEG_3V( tobj->current_contour->plane.normal ); - - project_current_contour( tobj ); - } - - if ( save_current_contour( tobj ) == GLU_ERROR ) { - return; - } - - MSG( 15, " <-- inspect_current_contour( tobj:%p )\n", tobj ); -} - -/***************************************************************************** - * reverse_contour - *****************************************************************************/ -void reverse_contour( tess_contour_t *contour ) -{ - tess_vertex_t *current = contour->vertices; - GLint i; - - for ( i = 0 ; i < contour->num_vertices ; i++ ) - { - tess_vertex_t *next = current->next; - tess_vertex_t *prev = current->prev; - - current->next = prev; - current->prev = next; - - current = next; - } - - contour->orientation = - ( contour->orientation == GLU_CCW ) ? GLU_CW : GLU_CCW; - - contour->last_vertex = contour->vertices->prev; -} - -/***************************************************************************** - * orient_contours - * - * Sum the signed areas of the contours, and orient the contours such that - * this sum is nonnegative. - *****************************************************************************/ -static void orient_contours( GLUtesselator *tobj ) -{ - tess_contour_t *contour = tobj->contours; - GLdouble sum = 0.0; - GLint i; - - MSG( 15, " --> orient_contours( tobj:%p )\n", tobj ); - - /* Sum the signed areas of all contours */ - for ( i = 0 ; i < tobj->num_contours ; i++ ) - { - sum += contour->area; - contour = contour->next; - } - - MSG( 15, " signed area: %.2f\n", sum ); - - if ( sum < -GLU_TESS_EPSILON ) - { - for ( i = 0 ; i < tobj->num_contours ; i++ ) - { - contour->area = ABSD( contour->area ); - reverse_contour( contour ); - - contour = contour->next; - } - } - else - { - for ( i = 0 ; i < tobj->num_contours ; i++ ) - { - contour->area = ABSD( contour->area ); - - contour = contour->next; - } - } - - tobj->orientation = tobj->contours->orientation; - - MSG( 15, " <-- orient_contours( tobj:%p ) orient: %s\n", - tobj, ( tobj->orientation == GLU_CCW ) ? "GLU_CCW" : "GLU_CW" ); -} - - -/***************************************************************************** - * delete_contour - * - * Delete the given contour and set the pointer to NULL. - *****************************************************************************/ -void delete_contour( tess_contour_t **contour ) -{ - tess_vertex_t *vertex, *next; - GLint i; - - if ( *contour == NULL ) { return; } - - vertex = (*contour)->vertices; - - for ( i = 0 ; i < (*contour)->num_vertices ; i++ ) - { - next = vertex->next; - free( vertex ); - vertex = next; - } - - free( *contour ); - *contour = NULL; -} - -/***************************************************************************** - * delete_all_contours - *****************************************************************************/ -static void delete_all_contours( GLUtesselator *tobj ) -{ - tess_contour_t *current, *next_contour; - GLint i; - - if ( tobj->current_contour != NULL ) { - delete_contour( &tobj->current_contour ); - } - - for ( current = tobj->contours, i = 0 ; i < tobj->num_contours ; i++ ) - { - tess_vertex_t *vertex = current->vertices, *next_vertex; - GLint j; - - for ( j = 0 ; j < current->num_vertices ; j ++ ) - { - next_vertex = vertex->next; - free( vertex ); - vertex = next_vertex; - } - next_contour = current->next; - - free( current ); - current = next_contour; - } - - tobj->num_contours = tobj->num_vertices = 0; - tobj->contours = tobj->last_contour = NULL; - - CLEAR_BBOX_2DV( tobj->mins, tobj->maxs ); -} - - -/***************************************************************************** - * tess_cleanup - *****************************************************************************/ -static void tess_cleanup( GLUtesselator *tobj ) -{ - MSG( 15, " -> tess_cleanup( tobj:%p )\n", tobj ); - - if ( tobj->current_contour != NULL ) { - delete_contour( &tobj->current_contour ); - } - if ( tobj->contours != NULL ) { - delete_all_contours( tobj ); - } - - MSG( 15, " <- tess_cleanup( tobj:%p )\n", tobj ); -} - - -/***************************************************************************** - * tess_msg - *****************************************************************************/ -INLINE void tess_msg( GLint level, char *format, ... ) -{ -#ifdef DEBUG - va_list ap; - va_start( ap, format ); - - if ( level <= tess_dbg_level ) { - vfprintf( DBG_STREAM, format, ap ); - fflush( DBG_STREAM ); - } - - va_end( ap ); -#endif -} - -INLINE void tess_info( char *file, GLint line ) -{ -#ifdef DEBUG - fprintf( DBG_STREAM, "%9.9s:%d:\t ", file, line ); -#endif -} - - - -/***************************************************************************** - * - * GLU TESSELLATION FUNCTIONS - * - *****************************************************************************/ - - -/***************************************************************************** - * gluNewTess - *****************************************************************************/ -GLUtesselator* GLAPIENTRY gluNewTess( void ) -{ - GLUtesselator *tobj; - -#ifdef DEBUG - if ( getenv( "MESA_TESS_DBG_LEVEL" ) ) { - tess_dbg_level = atoi( getenv( "MESA_TESS_DBG_LEVEL" ) ); - } else { - tess_dbg_level = DBG_LEVEL_BASE; - } +/* + * This is ugly, but seems the easiest way to do things to make the + * code work under YellowBox for Windows + */ +#if defined(OPENSTEP) && defined(CALLBACK) +#undef CALLBACK +#define CALLBACK #endif - MSG( 15, "-> gluNewTess()\n" ); - - tobj = malloc( sizeof(GLUtesselator) ); - if ( tobj == NULL ) { - return NULL; - } - - init_callbacks( &tobj->callbacks ); - - tobj->winding_rule = GLU_TESS_WINDING_ODD; - tobj->boundary_only = GL_FALSE; - tobj->tolerance = GLU_TESS_EPSILON; - tobj->orientation = GLU_UNKNOWN; - - tobj->data = NULL; - tobj->num_contours = 0; - tobj->contours = tobj->last_contour = NULL; - tobj->current_contour = NULL; +static void delete_contours(GLUtriangulatorObj *); - CLEAR_BBOX_2DV( tobj->mins, tobj->maxs ); - - tobj->num_vertices = 0; - tobj->sorted_vertices = NULL; -#if 0 - tobj->grid = NULL; +#ifdef __CYGWIN32__ +#define _CALLBACK +#else +#define _CALLBACK GLCALLBACK #endif - tobj->edge_flag = GL_FALSE; - tobj->label = 0; - - ZERO_3V( tobj->plane.normal ); - tobj->plane.dist = 0.0; - - tobj->error = GLU_NO_ERROR; - - MSG( 15, "<- gluNewTess() tobj:%p\n", tobj ); - return tobj; -} - - -/***************************************************************************** - * gluDeleteTess - *****************************************************************************/ -void GLAPIENTRY gluDeleteTess( GLUtesselator *tobj ) -{ - MSG( 15, "-> gluDeleteTess( tobj:%p )\n", tobj ); - if ( ( tobj->error == GLU_NO_ERROR ) && ( tobj->num_contours > 0 ) ) - { - /* gluEndPolygon was not called. */ - tess_error_callback( tobj, GLU_TESS_ERROR3 ); - } - /* Delete all internal structures. */ - tess_cleanup( tobj ); - free( tobj ); - - MSG( 15, "<- gluDeleteTess()\n" ); -} - - -/***************************************************************************** - * gluTessBeginPolygon - *****************************************************************************/ -void GLAPIENTRY gluTessBeginPolygon( GLUtesselator *tobj, void *polygon_data ) +static void +init_callbacks(tess_callbacks * callbacks) { - MSG( 15, "-> gluTessBeginPolygon( tobj:%p data:%p )\n", tobj, polygon_data ); - - tobj->error = GLU_NO_ERROR; - - if ( tobj->current_contour != NULL ) - { - /* gluEndPolygon was not called. */ - tess_error_callback( tobj, GLU_TESS_ERROR3 ); - tess_cleanup( tobj ); - } - - tobj->data = polygon_data; - tobj->num_vertices = 0; - tobj->edge_flag = GL_FALSE; - tobj->label = 0; - - MSG( 15, "<- gluTessBeginPolygon( tobj:%p data:%p )\n", tobj, polygon_data ); + callbacks->begin = (void (_CALLBACK *) (GLenum)) 0; + callbacks->edgeFlag = (void (_CALLBACK *) (GLboolean)) 0; + callbacks->vertex = (void (_CALLBACK *) (void *)) 0; + callbacks->end = (void (_CALLBACK *) (void)) 0; + callbacks->error = (void (_CALLBACK *) (GLenum)) 0; } - -/***************************************************************************** - * gluTessBeginContour - *****************************************************************************/ -void GLAPIENTRY gluTessBeginContour( GLUtesselator *tobj ) +void +tess_call_user_error(GLUtriangulatorObj * tobj, GLenum gluerr) { - MSG( 15, " -> gluTessBeginContour( tobj:%p )\n", tobj ); - TESS_CHECK_ERRORS( tobj ); - - if ( tobj->current_contour != NULL ) - { - /* gluTessEndContour was not called. */ - tess_error_callback( tobj, GLU_TESS_ERROR4 ); - return; - } - - tobj->current_contour = malloc( sizeof(tess_contour_t) ); - if ( tobj->current_contour == NULL ) { - tess_error_callback( tobj, GLU_OUT_OF_MEMORY ); - return; - } - - COPY_3V( tobj->current_contour->plane.normal, tobj->plane.normal ); - tobj->current_contour->plane.dist = tobj->plane.dist; - - tobj->current_contour->area = 0.0; - tobj->current_contour->orientation = GLU_UNKNOWN; - - tobj->current_contour->label = 0; - tobj->current_contour->winding = 0; - - /*tobj->current_contour->rotx = tobj->current_contour->roty = 0.0;*/ - - CLEAR_BBOX_2DV( tobj->current_contour->mins, - tobj->current_contour->maxs ); - - tobj->current_contour->num_vertices = 0; - tobj->current_contour->vertices = - tobj->current_contour->last_vertex = NULL; - - tobj->current_contour->reflex_vertices = NULL; - - cleanup: - MSG( 15, " <- gluTessBeginContour( tobj:%p )\n", tobj ); - return; + if (tobj->error == GLU_NO_ERROR) + tobj->error = gluerr; + if (tobj->callbacks.error != NULL) + (tobj->callbacks.error) (gluerr); } - -/***************************************************************************** - * gluTessVertex - *****************************************************************************/ -void GLAPIENTRY gluTessVertex( GLUtesselator *tobj, GLdouble coords[3], - void *vertex_data ) +GLUtriangulatorObj *GLAPIENTRY +gluNewTess(void) { - tess_contour_t *current = tobj->current_contour; - tess_vertex_t *last_vertex; - - MSG( 15, " -> gluTessVertex( tobj:%p coords:(%.2f,%.2f,%.2f) )\n", tobj, coords[0], coords[1], coords[2] ); - TESS_CHECK_ERRORS( tobj ); - - if ( current == NULL ) - { - /* gluTessBeginContour was not called. */ - tess_error_callback( tobj, GLU_TESS_ERROR2 ); - return; - } - - tobj->num_vertices++; - - last_vertex = current->last_vertex; - - if ( last_vertex == NULL ) - { - last_vertex = malloc( sizeof(tess_vertex_t) ); - if ( last_vertex == NULL ) { - tess_error_callback( tobj, GLU_OUT_OF_MEMORY ); - return; - } - - current->vertices = last_vertex; - current->last_vertex = last_vertex; - - last_vertex->index = -1; - last_vertex->data = vertex_data; - - last_vertex->coords[X] = coords[X]; - last_vertex->coords[Y] = coords[Y]; - last_vertex->coords[Z] = coords[Z]; - - last_vertex->v[X] = 0.0; - last_vertex->v[Y] = 0.0; - - last_vertex->edge_flag = GL_TRUE; - - last_vertex->side = 0.0; - - last_vertex->next = NULL; - last_vertex->prev = NULL; - - current->num_vertices++; - } - else - { - tess_vertex_t *vertex; - - vertex = malloc( sizeof(tess_vertex_t) ); - if ( vertex == NULL ) { - tess_error_callback( tobj, GLU_OUT_OF_MEMORY ); - return; - } - - vertex->index = -1; - vertex->data = vertex_data; - - vertex->coords[X] = coords[X]; - vertex->coords[Y] = coords[Y]; - vertex->coords[Z] = coords[Z]; - - vertex->v[X] = 0.0; - vertex->v[Y] = 0.0; - - vertex->edge_flag = GL_TRUE; - - vertex->side = 0.0; - - vertex->next = NULL; - vertex->prev = last_vertex; - - current->num_vertices++; - - last_vertex->next = vertex; - current->last_vertex = vertex; - } - - cleanup: - MSG( 15, " <- gluTessVertex( tobj:%p )\n", tobj ); - return; + GLUtriangulatorObj *tobj; + + if ((tobj = (GLUtriangulatorObj *) + malloc(sizeof(struct GLUtriangulatorObj))) == NULL) + return NULL; + tobj->contours = tobj->last_contour = NULL; + init_callbacks(&tobj->callbacks); + tobj->error = GLU_NO_ERROR; + tobj->current_polygon = NULL; + tobj->contour_cnt = 0; + return tobj; } -/***************************************************************************** - * gluTessEndContour - *****************************************************************************/ -void GLAPIENTRY gluTessEndContour( GLUtesselator *tobj ) +void GLAPIENTRY +gluTessCallback(GLUtriangulatorObj * tobj, GLenum which, + void (GLCALLBACK * fn) ()) { - MSG( 15, " -> gluTessEndContour( tobj:%p )\n", tobj ); - TESS_CHECK_ERRORS( tobj ); - - if ( tobj->current_contour == NULL ) - { - /* gluTessBeginContour was not called. */ - tess_error_callback( tobj, GLU_TESS_ERROR2 ); - return; - } - - if ( tobj->current_contour->num_vertices > 0 ) { - inspect_current_contour( tobj ); - } else { - delete_contour( &tobj->current_contour ); - } - - cleanup: - MSG( 15, " <- gluTessEndContour( tobj:%p )\n", tobj ); - return; + switch (which) { + case GLU_BEGIN: + tobj->callbacks.begin = (void (_CALLBACK *) (GLenum)) fn; + break; + case GLU_EDGE_FLAG: + tobj->callbacks.edgeFlag = (void (_CALLBACK *) (GLboolean)) fn; + break; + case GLU_VERTEX: + tobj->callbacks.vertex = (void (_CALLBACK *) (void *)) fn; + break; + case GLU_END: + tobj->callbacks.end = (void (_CALLBACK *) (void)) fn; + break; + case GLU_ERROR: + tobj->callbacks.error = (void (_CALLBACK *) (GLenum)) fn; + break; + default: + tobj->error = GLU_INVALID_ENUM; + break; + } } -/***************************************************************************** - * gluTessEndPolygon - *****************************************************************************/ -void GLAPIENTRY gluTessEndPolygon( GLUtesselator *tobj ) -{ - MSG( 15, "-> gluTessEndPolygon( tobj:%p )\n", tobj ); - TESS_CHECK_ERRORS( tobj ); - - if ( tobj->current_contour != NULL ) - { - /* gluTessBeginPolygon was not called. */ - tess_error_callback( tobj, GLU_TESS_ERROR1 ); - return; - } - TESS_CHECK_ERRORS( tobj ); - - /* - * Ensure we have at least one contour to tessellate. If we have none, - * clean up and exit gracefully. - */ - if ( tobj->num_contours == 0 ) { - tess_cleanup( tobj ); - return; - } - - /* Wrap the contour list. */ - - tobj->last_contour->next = tobj->contours; - tobj->contours->prev = tobj->last_contour; - - TESS_CHECK_ERRORS( tobj ); - - /* Orient the contours correctly */ - orient_contours( tobj ); - - /* - * Before we tessellate the contours, ensure we have the appropriate - * callbacks registered. We at least need the begin, vertex and end - * callbacks to do any meaningful work. - */ - if ( ( ( tobj->callbacks.begin != NULL ) || - ( tobj->callbacks.beginData != NULL ) ) && - ( ( tobj->callbacks.vertex != NULL ) || - ( tobj->callbacks.vertexData != NULL ) ) && - ( ( tobj->callbacks.end != NULL ) || - ( tobj->callbacks.endData != NULL ) ) ) - { - fist_tessellation( tobj ); - } - - cleanup: - delete_all_contours( tobj ); - MSG( 15, "<- gluTessEndPolygon( tobj:%p )\n", tobj ); -} - -/***************************************************************************** - * gluTessCallback - *****************************************************************************/ -void GLAPIENTRY gluTessCallback( GLUtesselator *tobj, GLenum which, - void (GLCALLBACKP fn)() ) +void GLAPIENTRY +gluDeleteTess(GLUtriangulatorObj * tobj) { - switch ( which ) - { - /* Register the begin callbacks. */ - case GLU_TESS_BEGIN: - tobj->callbacks.begin = (void (GLCALLBACKPCAST)(GLenum)) fn; - break; - case GLU_TESS_BEGIN_DATA: - tobj->callbacks.beginData = (void (GLCALLBACKPCAST)(GLenum, void *)) fn; - break; - - /* Register the edge flag callbacks. */ - case GLU_TESS_EDGE_FLAG: - tobj->callbacks.edgeFlag = (void (GLCALLBACKPCAST)(GLboolean)) fn; - break; - case GLU_TESS_EDGE_FLAG_DATA: - tobj->callbacks.edgeFlagData = (void (GLCALLBACKPCAST)(GLboolean, void *)) fn; - break; - - /* Register the vertex callbacks. */ - case GLU_TESS_VERTEX: - tobj->callbacks.vertex = (void (GLCALLBACKPCAST)(void *)) fn; - break; - case GLU_TESS_VERTEX_DATA: - tobj->callbacks.vertexData = (void (GLCALLBACKPCAST)(void *, void *)) fn; - break; - - /* Register the end callbacks. */ - case GLU_TESS_END: - tobj->callbacks.end = (void (GLCALLBACKPCAST)(void)) fn; - break; - case GLU_TESS_END_DATA: - tobj->callbacks.endData = (void (GLCALLBACKPCAST)(void *)) fn; - break; - - /* Register the error callbacks. */ - case GLU_TESS_ERROR: - tobj->callbacks.error = (void (GLCALLBACKPCAST)(GLenum)) fn; - break; - case GLU_TESS_ERROR_DATA: - tobj->callbacks.errorData = (void (GLCALLBACKPCAST)(GLenum, void *)) fn; - break; - - /* Register the combine callbacks. */ - case GLU_TESS_COMBINE: - tobj->callbacks.combine = (void (GLCALLBACKPCAST)(GLdouble[3], void *[4], GLfloat [4], void **)) fn; - break; - case GLU_TESS_COMBINE_DATA: - tobj->callbacks.combineData = (void (GLCALLBACKPCAST)(GLdouble[3], void *[4], GLfloat [4], void **, void *)) fn; - break; - - default: - MSG( 1, " gluTessCallback( tobj:%p which:%d ) invalid enum\n", tobj, which ); - tobj->error = GLU_INVALID_ENUM; - break; - } + if (tobj->error == GLU_NO_ERROR && tobj->contour_cnt) + /* was gluEndPolygon called? */ + tess_call_user_error(tobj, GLU_TESS_ERROR1); + /* delete all internal structures */ + delete_contours(tobj); + free(tobj); } -/***************************************************************************** - * gluTessProperty - * - * Set the current value of the given property. - *****************************************************************************/ -void GLAPIENTRY gluTessProperty( GLUtesselator *tobj, GLenum which, - GLdouble value ) +void GLAPIENTRY +gluBeginPolygon(GLUtriangulatorObj * tobj) { - switch ( which ) - { - case GLU_TESS_BOUNDARY_ONLY: - tobj->boundary_only = (GLboolean) value; - break; - - case GLU_TESS_TOLERANCE: - MSG( 15, " gluTessProperty( tobj:%p ) tolerance: %0.9f\n", tobj, value ); - tobj->tolerance = value; - break; - - case GLU_TESS_WINDING_RULE: - tobj->winding_rule = (GLenum) value; - break; - - default: - MSG( 1, " gluTessProperty( tobj:%p which:%d ) invalid enum\n", tobj, which ); - tobj->error = GLU_INVALID_ENUM; - break; - } +/* + if(tobj->error!=GLU_NO_ERROR) + return; +*/ + tobj->error = GLU_NO_ERROR; + if (tobj->current_polygon != NULL) { + /* gluEndPolygon was not called */ + tess_call_user_error(tobj, GLU_TESS_ERROR1); + /* delete all internal structures */ + delete_contours(tobj); + } + else { + if ((tobj->current_polygon = + (tess_polygon *) malloc(sizeof(tess_polygon))) == NULL) { + tess_call_user_error(tobj, GLU_OUT_OF_MEMORY); + return; + } + tobj->current_polygon->vertex_cnt = 0; + tobj->current_polygon->vertices = + tobj->current_polygon->last_vertex = NULL; + } } -/***************************************************************************** - * gluGetTessProperty - * - * Return the current value of the given property. - *****************************************************************************/ -void GLAPIENTRY gluGetTessProperty( GLUtesselator *tobj, GLenum which, - GLdouble *value ) +void GLAPIENTRY +gluEndPolygon(GLUtriangulatorObj * tobj) { - switch ( which ) - { - case GLU_TESS_BOUNDARY_ONLY: - *value = tobj->boundary_only; - break; - - case GLU_TESS_TOLERANCE: - *value = tobj->tolerance; - break; - - case GLU_TESS_WINDING_RULE: - *value = tobj->winding_rule; - break; - - default: - MSG( 1, " gluGetTessProperty( tobj:%p which:%d ) invalid enum\n", tobj, which ); - tobj->error = GLU_INVALID_ENUM; - break; - } + /*tess_contour *contour_ptr; */ + + /* there was an error */ + if (tobj->error != GLU_NO_ERROR) + goto end; + + /* check if gluBeginPolygon was called */ + if (tobj->current_polygon == NULL) { + tess_call_user_error(tobj, GLU_TESS_ERROR2); + return; + } + tess_test_polygon(tobj); + /* there was an error */ + if (tobj->error != GLU_NO_ERROR) + goto end; + + /* any real contours? */ + if (tobj->contour_cnt == 0) { + /* delete all internal structures */ + delete_contours(tobj); + return; + } + tess_find_contour_hierarchies(tobj); + /* there was an error */ + if (tobj->error != GLU_NO_ERROR) + goto end; + + tess_handle_holes(tobj); + /* there was an error */ + if (tobj->error != GLU_NO_ERROR) + goto end; + + /* if no callbacks, nothing to do */ + if (tobj->callbacks.begin != NULL && tobj->callbacks.vertex != NULL && + tobj->callbacks.end != NULL) { + if (tobj->callbacks.edgeFlag == NULL) + tess_tesselate(tobj); + else + tess_tesselate_with_edge_flag(tobj); + } + + end: + /* delete all internal structures */ + delete_contours(tobj); } -/***************************************************************************** - * gluTessNormal - * - * Set the current tessellation normal. - *****************************************************************************/ -void GLAPIENTRY gluTessNormal( GLUtesselator *tobj, GLdouble x, - GLdouble y, GLdouble z ) +void GLAPIENTRY +gluNextContour(GLUtriangulatorObj * tobj, GLenum type) { - MSG( 15, " gluTessNormal( tobj:%p n:(%.2f,%.2f,%.2f) )\n", tobj, x, y, z ); - - ASSIGN_3V( tobj->plane.normal, x, y, z ); + if (tobj->error != GLU_NO_ERROR) + return; + if (tobj->current_polygon == NULL) { + tess_call_user_error(tobj, GLU_TESS_ERROR2); + return; + } + /* first contour? */ + if (tobj->current_polygon->vertex_cnt) + tess_test_polygon(tobj); } - -/***************************************************************************** - * - * OBSOLETE TESSELLATION FUNCTIONS - * - *****************************************************************************/ - -void GLAPIENTRY gluBeginPolygon( GLUtesselator *tobj ) +void GLAPIENTRY +gluTessVertex(GLUtriangulatorObj * tobj, GLdouble v[3], void *data) { - gluTessBeginPolygon( tobj, NULL ); - gluTessBeginContour( tobj ); + tess_polygon *polygon = tobj->current_polygon; + tess_vertex *last_vertex_ptr; + + if (tobj->error != GLU_NO_ERROR) + return; + if (polygon == NULL) { + tess_call_user_error(tobj, GLU_TESS_ERROR2); + return; + } + last_vertex_ptr = polygon->last_vertex; + if (last_vertex_ptr == NULL) { + if ((last_vertex_ptr = (tess_vertex *) + malloc(sizeof(tess_vertex))) == NULL) { + tess_call_user_error(tobj, GLU_OUT_OF_MEMORY); + return; + } + polygon->vertices = last_vertex_ptr; + polygon->last_vertex = last_vertex_ptr; + last_vertex_ptr->data = data; + last_vertex_ptr->location[0] = v[0]; + last_vertex_ptr->location[1] = v[1]; + last_vertex_ptr->location[2] = v[2]; + last_vertex_ptr->next = NULL; + last_vertex_ptr->previous = NULL; + ++(polygon->vertex_cnt); + } + else { + tess_vertex *vertex_ptr; + + /* same point twice? */ + if (fabs(last_vertex_ptr->location[0] - v[0]) < EPSILON && + fabs(last_vertex_ptr->location[1] - v[1]) < EPSILON && + fabs(last_vertex_ptr->location[2] - v[2]) < EPSILON) { + tess_call_user_error(tobj, GLU_TESS_ERROR6); + return; + } + if ((vertex_ptr = (tess_vertex *) + malloc(sizeof(tess_vertex))) == NULL) { + tess_call_user_error(tobj, GLU_OUT_OF_MEMORY); + return; + } + vertex_ptr->data = data; + vertex_ptr->location[0] = v[0]; + vertex_ptr->location[1] = v[1]; + vertex_ptr->location[2] = v[2]; + vertex_ptr->next = NULL; + vertex_ptr->previous = last_vertex_ptr; + ++(polygon->vertex_cnt); + last_vertex_ptr->next = vertex_ptr; + polygon->last_vertex = vertex_ptr; + } } -void GLAPIENTRY gluNextContour( GLUtesselator *tobj, GLenum type ) -{ - gluTessEndContour( tobj ); - gluTessBeginContour( tobj ); -} -void GLAPIENTRY gluEndPolygon( GLUtesselator *tobj ) +static void +delete_contours(GLUtriangulatorObj * tobj) { - gluTessEndContour( tobj ); - gluTessEndPolygon( tobj ); + tess_polygon *polygon = tobj->current_polygon; + tess_contour *contour, *contour_tmp; + tess_vertex *vertex, *vertex_tmp; + + /* remove current_polygon list - if exists due to detected error */ + if (polygon != NULL) { + if (polygon->vertices) { + for (vertex = polygon->vertices; vertex != polygon->last_vertex;) { + vertex_tmp = vertex->next; + free(vertex); + vertex = vertex_tmp; + } + free(vertex); + } + free(polygon); + tobj->current_polygon = NULL; + } + /* remove all contour data */ + for (contour = tobj->contours; contour != NULL;) { + for (vertex = contour->vertices; vertex != contour->last_vertex;) { + vertex_tmp = vertex->next; + free(vertex); + vertex = vertex_tmp; + } + free(vertex); + contour_tmp = contour->next; + free(contour); + contour = contour_tmp; + } + tobj->contours = tobj->last_contour = NULL; + tobj->contour_cnt = 0; } diff --git a/src/glu/mesa/tess.h b/src/glu/mesa/tess.h index 55681830735..ddb9b30cb20 100644 --- a/src/glu/mesa/tess.h +++ b/src/glu/mesa/tess.h @@ -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 - * - *****************************************************************************/ -#ifndef __GLU_TESS_H__ -#define __GLU_TESS_H__ +/* + * This file is part of the polygon tesselation code contributed by + * Bogdan Sikorski + */ -#include -#include -#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__ */ diff --git a/src/glu/mesa/tesselat.c b/src/glu/mesa/tesselat.c new file mode 100644 index 00000000000..60754d7f174 --- /dev/null +++ b/src/glu/mesa/tesselat.c @@ -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 +#include +#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) (); +} -- cgit v1.2.3