Procházet zdrojové kódy

reverted to old tessellator (GLU 1.1)

tags/mesa_3_3
Brian Paul před 25 roky
rodič
revize
f88602394d

+ 53
- 63
include/GL/glu.h Zobrazit soubor

@@ -1,10 +1,9 @@
/* $Id: glu.h,v 1.21 2000/05/22 19:40:43 brianp Exp $ */
/* $Id: glu.h,v 1.22 2000/07/11 14:11:44 brianp Exp $ */

/*
* Mesa 3-D graphics library
* Version: 3.3
*
* Copyright (C) 1995-1999 Brian Paul
* Copyright (C) 1995-2000 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -22,22 +21,23 @@
*/


#ifndef __glu_h__
#define __glu_h__
#ifndef GLU_H
#define GLU_H


#if defined(USE_MGL_NAMESPACE)
#include "glu_mangle.h"
#endif

#include "GL/gl.h"


#ifdef __cplusplus
extern "C" {
#endif


#include <GL/gl.h>


/* to facilitate clean DLL building ... */
#if !defined(OPENSTEP) && (defined(__WIN32__) || defined(__CYGWIN__))
# if defined(_MSC_VER) && defined(BUILD_GLU32) /* tag specify we're building mesa as a DLL */
@@ -61,7 +61,6 @@ extern "C" {
#endif



#ifdef macintosh
#pragma enumsalwaysint on
#if PRAGMA_IMPORT_SUPPORTED
@@ -83,7 +82,7 @@ extern "C" {


#define GLU_VERSION_1_1 1
#define GLU_VERSION_1_2 1


#define GLU_TRUE 1
@@ -215,8 +214,7 @@ extern "C" {
#define GLU_EXTENSIONS 100801



/*** GLU 1.0 tessellation - obsolete! ***/
/*** GLU 1.0 tessellation ***/

/* Contour types */
#define GLU_CW 100120
@@ -233,20 +231,26 @@ extern "C" {
#define GLU_EDGE_FLAG GLU_TESS_EDGE_FLAG


/*
* These are the GLU 1.1 typedefs. GLU 1.3 has different ones!
*/

#if defined(__BEOS__)
/* The BeOS does something funky and makes these typedefs in one
* of its system headers.
*/
#else

#if defined GLU_VERSION_1_2
typedef struct GLUquadric GLUquadricObj;
typedef struct GLUnurbs GLUnurbsObj;

/* FIXME: We need to implement the other 1.3 typedefs - GH */
typedef struct GLUtesselator GLUtesselator;
typedef GLUtesselator GLUtriangulatorObj;
#else
/* GLU 1.1 and older */
typedef struct GLUquadric GLUquadricObj;
typedef struct GLUtriangulatorObj GLUtriangulatorObj;
typedef struct GLUnurbs GLUnurbsObj;
#endif

#endif


@@ -306,17 +310,17 @@ GLUAPI const GLubyte* GLAPIENTRY gluErrorString( GLenum errorCode );
*/

GLUAPI GLint GLAPIENTRY gluScaleImage( GLenum format,
GLint widthin, GLint heightin,
GLsizei widthin, GLsizei heightin,
GLenum typein, const void *datain,
GLint widthout, GLint heightout,
GLsizei widthout, GLsizei heightout,
GLenum typeout, void *dataout );

GLUAPI GLint GLAPIENTRY gluBuild1DMipmaps( GLenum target, GLint components,
GLint width, GLenum format,
GLsizei width, GLenum format,
GLenum type, const void *data );

GLUAPI GLint GLAPIENTRY gluBuild2DMipmaps( GLenum target, GLint components,
GLint width, GLint height,
GLsizei width, GLsizei height,
GLenum format,
GLenum type, const void *data );

@@ -355,14 +359,15 @@ GLUAPI void GLAPIENTRY gluCylinder( GLUquadricObj *qobj,
GLint slices, GLint stacks );

GLUAPI void GLAPIENTRY gluSphere( GLUquadricObj *qobj,
GLdouble radius, GLint slices,
GLint stacks );
GLdouble radius,
GLint slices, GLint stacks );

GLUAPI void GLAPIENTRY gluDisk( GLUquadricObj *qobj,
GLdouble innerRadius, GLdouble outerRadius,
GLint slices, GLint loops );

GLUAPI void GLAPIENTRY gluPartialDisk( GLUquadricObj *qobj, GLdouble innerRadius,
GLUAPI void GLAPIENTRY gluPartialDisk( GLUquadricObj *qobj,
GLdouble innerRadius,
GLdouble outerRadius, GLint slices,
GLint loops, GLdouble startAngle,
GLdouble sweepAngle );
@@ -416,8 +421,8 @@ GLUAPI void GLAPIENTRY gluBeginTrim( GLUnurbsObj *nobj );
GLUAPI void GLAPIENTRY gluEndTrim( GLUnurbsObj *nobj );

GLUAPI void GLAPIENTRY gluPwlCurve( GLUnurbsObj *nobj, GLint count,
GLfloat *array, GLint stride,
GLenum type );
GLfloat *array,
GLint stride, GLenum type );

GLUAPI void GLAPIENTRY gluNurbsCallback( GLUnurbsObj *nobj, GLenum which,
void (GLCALLBACK *fn)() );
@@ -430,6 +435,8 @@ GLUAPI void GLAPIENTRY gluNurbsCallback( GLUnurbsObj *nobj, GLenum which,
*
*/

#ifdef GLU_VERSION_1_2

GLUAPI GLUtesselator* GLAPIENTRY gluNewTess( void );

GLUAPI void GLAPIENTRY gluDeleteTess( GLUtesselator *tobj );
@@ -458,17 +465,26 @@ GLUAPI void GLAPIENTRY gluTessCallback( GLUtesselator *tobj, GLenum which,
GLUAPI void GLAPIENTRY gluGetTessProperty( GLUtesselator *tobj, GLenum which,
GLdouble *value );

/*
*
* Obsolete 1.0 tessellation functions
*
*/
#else

GLUAPI GLUtriangulatorObj* GLAPIENTRY gluNewTess( void );

GLUAPI void GLAPIENTRY gluBeginPolygon( GLUtesselator *tobj );
GLUAPI void GLAPIENTRY gluTessCallback( GLUtriangulatorObj *tobj, GLenum which,
void (GLCALLBACK *fn)() );

GLUAPI void GLAPIENTRY gluNextContour( GLUtesselator *tobj, GLenum type );
GLUAPI void GLAPIENTRY gluDeleteTess( GLUtriangulatorObj *tobj );

GLUAPI void GLAPIENTRY gluBeginPolygon( GLUtriangulatorObj *tobj );

GLUAPI void GLAPIENTRY gluEndPolygon( GLUtriangulatorObj *tobj );

GLUAPI void GLAPIENTRY gluNextContour( GLUtriangulatorObj *tobj, GLenum type );

GLUAPI void GLAPIENTRY gluTessVertex( GLUtriangulatorObj *tobj, GLdouble v[3],
void *data );

#endif

GLUAPI void GLAPIENTRY gluEndPolygon( GLUtesselator *tobj );



@@ -488,38 +504,12 @@ GLUAPI const GLubyte* GLAPIENTRY gluGetString( GLenum name );
*
*/

GLUAPI GLboolean GLAPIENTRY
gluCheckExtension(const char *extName, const GLubyte *extString);


GLUAPI GLint GLAPIENTRY
gluBuild3DMipmaps( GLenum target, GLint internalFormat, GLsizei width,
GLsizei height, GLsizei depth, GLenum format,
GLenum type, const void *data );

GLUAPI GLint GLAPIENTRY
gluBuild1DMipmapLevels( GLenum target, GLint internalFormat, GLsizei width,
GLenum format, GLenum type, GLint level, GLint base,
GLint max, const void *data );
#ifdef GLU_VERSION_1_3

GLUAPI GLint GLAPIENTRY
gluBuild2DMipmapLevels( GLenum target, GLint internalFormat, GLsizei width,
GLsizei height, GLenum format, GLenum type,
GLint level, GLint base, GLint max,
const void *data );

GLUAPI GLint GLAPIENTRY
gluBuild3DMipmapLevels( GLenum target, GLint internalFormat, GLsizei width,
GLsizei height, GLsizei depth, GLenum format,
GLenum type, GLint level, GLint base, GLint max,
const void *data );
GLUAPI GLboolean GLAPIENTRY
gluCheckExtension( const char *extName, const GLubyte *extString );

GLUAPI GLint GLAPIENTRY
gluUnProject4( GLdouble winx, GLdouble winy, GLdouble winz, GLdouble clipw,
const GLdouble modelMatrix[16], const GLdouble projMatrix[16],
const GLint viewport[4], GLclampd zNear, GLclampd zFar,
GLdouble *objx, GLdouble *objy, GLdouble *objz,
GLdouble *objw );
#endif



@@ -541,4 +531,4 @@ gluUnProject4( GLdouble winx, GLdouble winy, GLdouble winz, GLdouble clipw,
#endif


#endif /* __glu_h__ */
#endif

+ 3
- 4
src/glu/mesa/Makefile.BeOS Zobrazit soubor

@@ -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)


+ 5
- 35
src/glu/mesa/Makefile.BeOS-R4 Zobrazit soubor

@@ -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)


+ 5
- 6
src/glu/mesa/Makefile.X11 Zobrazit soubor

@@ -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)


+ 1
- 2
src/glu/mesa/Makefile.m32 Zobrazit soubor

@@ -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)

+ 5
- 19
src/glu/mesa/all.h Zobrazit soubor

@@ -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 */

+ 111
- 183
src/glu/mesa/glu.c Zobrazit soubor

@@ -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

+ 6
- 45
src/glu/mesa/gluP.h Zobrazit soubor

@@ -1,9 +1,9 @@
/* $Id: gluP.h,v 1.4 2000/05/22 19:41:11 brianp Exp $ */
/* $Id: gluP.h,v 1.5 2000/07/11 14:11:04 brianp Exp $ */

/*
* Mesa 3-D graphics library
* Version: 3.1
* Copyright (C) 1995-1999 Brian Paul
* Version: 3.3
* Copyright (C) 1995-2000 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -21,43 +21,6 @@
*/


/*
* $Log: gluP.h,v $
* Revision 1.4 2000/05/22 19:41:11 brianp
* replaced __CYGWIN32__ with __CYGWIN__
*
* Revision 1.3 2000/05/22 16:25:37 brianp
* added some Window-isms formerly in gl.h
*
* Revision 1.2 1999/12/07 09:02:12 joukj
*
* Committing in .
*
* Make supportupdate for VMS
*
* Modified Files:
* Mesa/src-glu/descrip.mms Mesa/src-glu/gluP.h
* ----------------------------------------------------------------------
*
* Revision 1.1.1.1 1999/08/19 00:55:42 jtg
* Imported sources
*
* Revision 1.4 1999/01/03 03:23:15 brianp
* now using GLAPIENTRY and GLCALLBACK keywords (Ted Jump)
*
* Revision 1.3 1997/08/01 22:25:27 brianp
* check for Cygnus Win32 (Stephen Rehel)
*
* Revision 1.2 1997/05/27 02:59:46 brianp
* added defines for APIENTRY and CALLBACK if not compiling on Win32
*
* Revision 1.1 1996/09/27 01:19:39 brianp
* Initial revision
*
*/



/*
* This file allows the GLU code to be compiled either with the Mesa
* headers or with the real OpenGL headers.
@@ -68,12 +31,11 @@
#define GLUP_H


#include "GL/gl.h"
#include "GL/glu.h"
#include <GL/gl.h>
#include <GL/glu.h>
#include <string.h>



#if defined(_WIN32) && !defined(__WIN32__)
# define __WIN32__
#endif
@@ -153,8 +115,7 @@ typedef struct tagPIXELFORMATDESCRIPTOR PIXELFORMATDESCRIPTOR, *PPIXELFORMATDESC




#ifndef MESA
#ifndef GLU_TESS_ERROR9
/* If we're using the real OpenGL header files... */
# define GLU_TESS_ERROR9 100159
#endif

+ 440
- 398
src/glu/mesa/mipmap.c
Diff nebyl zobrazen, protože je příliš veliký
Zobrazit soubor


+ 477
- 509
src/glu/mesa/nurbs.c
Diff nebyl zobrazen, protože je příliš veliký
Zobrazit soubor


+ 179
- 195
src/glu/mesa/nurbs.h Zobrazit soubor

@@ -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);




+ 367
- 422
src/glu/mesa/nurbscrv.c Zobrazit soubor

@@ -1,9 +1,9 @@
/* $Id: nurbscrv.c,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
/* $Id: nurbscrv.c,v 1.2 2000/07/11 14:11:04 brianp Exp $ */

/*
* Mesa 3-D graphics library
* Version: 2.4
* Copyright (C) 1995-1997 Brian Paul
* Version: 3.3
* Copyright (C) 1995-2000 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -21,32 +21,6 @@
*/


/*
* $Log: nurbscrv.c,v $
* Revision 1.1 1999/08/19 00:55:42 jtg
* Initial revision
*
* Revision 1.6 1997/07/24 01:28:44 brianp
* changed precompiled header symbol from PCH to PC_HEADER
*
* Revision 1.5 1997/05/28 02:29:38 brianp
* added support for precompiled headers (PCH), inserted APIENTRY keyword
*
* Revision 1.4 1997/05/27 03:21:22 brianp
* minor clean-up
*
* Revision 1.3 1997/05/27 03:00:16 brianp
* incorporated Bogdan's new NURBS code
*
* Revision 1.2 1996/09/27 23:12:22 brianp
* added return 0 to get_surface_dim() to silence warning
*
* Revision 1.1 1996/09/27 01:19:39 brianp
* Initial revision
*
*/


/*
* NURBS implementation written by Bogdan Sikorski (bogdan@cira.it)
* See README2 for more info.
@@ -66,435 +40,406 @@
static int
get_curve_dim(GLenum type)
{
switch(type)
{
case GL_MAP1_VERTEX_3: return 3;
case GL_MAP1_VERTEX_4: return 4;
case GL_MAP1_INDEX: return 1;
case GL_MAP1_COLOR_4: return 4;
case GL_MAP1_NORMAL: return 3;
case GL_MAP1_TEXTURE_COORD_1: return 1;
case GL_MAP1_TEXTURE_COORD_2: return 2;
case GL_MAP1_TEXTURE_COORD_3: return 3;
case GL_MAP1_TEXTURE_COORD_4: return 4;
default: abort(); /* TODO: is this OK? */
}
return 0; /*never get here*/
switch (type) {
case GL_MAP1_VERTEX_3:
return 3;
case GL_MAP1_VERTEX_4:
return 4;
case GL_MAP1_INDEX:
return 1;
case GL_MAP1_COLOR_4:
return 4;
case GL_MAP1_NORMAL:
return 3;
case GL_MAP1_TEXTURE_COORD_1:
return 1;
case GL_MAP1_TEXTURE_COORD_2:
return 2;
case GL_MAP1_TEXTURE_COORD_3:
return 3;
case GL_MAP1_TEXTURE_COORD_4:
return 4;
default:
abort(); /* TODO: is this OK? */
}
return 0; /*never get here */
}

static GLenum
test_nurbs_curve(GLUnurbsObj *nobj, curve_attribs *attribs)
test_nurbs_curve(GLUnurbsObj * nobj, curve_attribs * attribs)
{
GLenum err;
GLint tmp_int;
GLenum err;
GLint tmp_int;

if(attribs->order < 0)
{
call_user_error(nobj,GLU_INVALID_VALUE);
return GLU_ERROR;
}
glGetIntegerv(GL_MAX_EVAL_ORDER,&tmp_int);
if(attribs->order > tmp_int || attribs->order < 2)
{
call_user_error(nobj,GLU_NURBS_ERROR1);
return GLU_ERROR;
}
if(attribs->knot_count < attribs->order +2)
{
call_user_error(nobj,GLU_NURBS_ERROR2);
return GLU_ERROR;
}
if(attribs->stride < 0)
{
call_user_error(nobj,GLU_NURBS_ERROR34);
return GLU_ERROR;
}
if(attribs->knot==NULL || attribs->ctrlarray==NULL)
{
call_user_error(nobj,GLU_NURBS_ERROR36);
return GLU_ERROR;
}
if((err=test_knot(attribs->knot_count,attribs->knot,attribs->order))
!=GLU_NO_ERROR)
{
call_user_error(nobj,err);
return GLU_ERROR;
}
return GLU_NO_ERROR;
if (attribs->order < 0) {
call_user_error(nobj, GLU_INVALID_VALUE);
return GLU_ERROR;
}
glGetIntegerv(GL_MAX_EVAL_ORDER, &tmp_int);
if (attribs->order > tmp_int || attribs->order < 2) {
call_user_error(nobj, GLU_NURBS_ERROR1);
return GLU_ERROR;
}
if (attribs->knot_count < attribs->order + 2) {
call_user_error(nobj, GLU_NURBS_ERROR2);
return GLU_ERROR;
}
if (attribs->stride < 0) {
call_user_error(nobj, GLU_NURBS_ERROR34);
return GLU_ERROR;
}
if (attribs->knot == NULL || attribs->ctrlarray == NULL) {
call_user_error(nobj, GLU_NURBS_ERROR36);
return GLU_ERROR;
}
if ((err = test_knot(attribs->knot_count, attribs->knot, attribs->order))
!= GLU_NO_ERROR) {
call_user_error(nobj, err);
return GLU_ERROR;
}
return GLU_NO_ERROR;
}

static GLenum
test_nurbs_curves(GLUnurbsObj *nobj)
test_nurbs_curves(GLUnurbsObj * nobj)
{
/* test the geometric data */
if(test_nurbs_curve(nobj,&(nobj->curve.geom))!=GLU_NO_ERROR)
return GLU_ERROR;
/* now test the attributive data */
/* color */
if(nobj->curve.color.type!=GLU_INVALID_ENUM)
if(test_nurbs_curve(nobj,&(nobj->curve.color))!=GLU_NO_ERROR)
return GLU_ERROR;
/* normal */
if(nobj->curve.normal.type!=GLU_INVALID_ENUM)
if(test_nurbs_curve(nobj,&(nobj->curve.normal))!=GLU_NO_ERROR)
return GLU_ERROR;
/* texture */
if(nobj->curve.texture.type!=GLU_INVALID_ENUM)
if(test_nurbs_curve(nobj,&(nobj->curve.texture))!=GLU_NO_ERROR)
return GLU_ERROR;
return GLU_NO_ERROR;
/* test the geometric data */
if (test_nurbs_curve(nobj, &(nobj->curve.geom)) != GLU_NO_ERROR)
return GLU_ERROR;
/* now test the attributive data */
/* color */
if (nobj->curve.color.type != GLU_INVALID_ENUM)
if (test_nurbs_curve(nobj, &(nobj->curve.color)) != GLU_NO_ERROR)
return GLU_ERROR;
/* normal */
if (nobj->curve.normal.type != GLU_INVALID_ENUM)
if (test_nurbs_curve(nobj, &(nobj->curve.normal)) != GLU_NO_ERROR)
return GLU_ERROR;
/* texture */
if (nobj->curve.texture.type != GLU_INVALID_ENUM)
if (test_nurbs_curve(nobj, &(nobj->curve.texture)) != GLU_NO_ERROR)
return GLU_ERROR;
return GLU_NO_ERROR;
}

/* prepare the knot information structures */
static GLenum
fill_knot_structures(GLUnurbsObj *nobj,knot_str_type *geom_knot,
knot_str_type *color_knot, knot_str_type *normal_knot,
knot_str_type *texture_knot)
fill_knot_structures(GLUnurbsObj * nobj, knot_str_type * geom_knot,
knot_str_type * color_knot, knot_str_type * normal_knot,
knot_str_type * texture_knot)
{
GLint order;
GLfloat *knot;
GLint nknots;
GLint t_min,t_max;
GLint order;
GLfloat *knot;
GLint nknots;
GLint t_min, t_max;

geom_knot->unified_knot=NULL;
knot=geom_knot->knot=nobj->curve.geom.knot;
nknots=geom_knot->nknots=nobj->curve.geom.knot_count;
order=geom_knot->order=nobj->curve.geom.order;
geom_knot->delta_nknots=0;
t_min=geom_knot->t_min=order-1;
t_max=geom_knot->t_max=nknots-order;
if(fabs(knot[t_min]-knot[t_max])<EPSILON)
{
call_user_error(nobj,GLU_NURBS_ERROR3);
return GLU_ERROR;
}
if(fabs(knot[0]-knot[t_min])<EPSILON)
{
/* knot open at beggining */
geom_knot->open_at_begin=GL_TRUE;
}
else
geom_knot->open_at_begin=GL_FALSE;
if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
{
/* knot open at end */
geom_knot->open_at_end=GL_TRUE;
}
else
geom_knot->open_at_end=GL_FALSE;
if(nobj->curve.color.type!=GLU_INVALID_ENUM)
{
color_knot->unified_knot=(GLfloat *)1;
knot=color_knot->knot=nobj->curve.color.knot;
nknots=color_knot->nknots=nobj->curve.color.knot_count;
order=color_knot->order=nobj->curve.color.order;
color_knot->delta_nknots=0;
t_min=color_knot->t_min=order-1;
t_max=color_knot->t_max=nknots-order;
if(fabs(knot[t_min]-knot[t_max])<EPSILON)
{
call_user_error(nobj,GLU_NURBS_ERROR3);
return GLU_ERROR;
}
if(fabs(knot[0]-knot[t_min])<EPSILON)
{
/* knot open at beggining */
color_knot->open_at_begin=GL_TRUE;
}
else
color_knot->open_at_begin=GL_FALSE;
if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
{
/* knot open at end */
color_knot->open_at_end=GL_TRUE;
}
else
color_knot->open_at_end=GL_FALSE;
}
else
color_knot->unified_knot=NULL;
if(nobj->curve.normal.type!=GLU_INVALID_ENUM)
{
normal_knot->unified_knot=(GLfloat *)1;
knot=normal_knot->knot=nobj->curve.normal.knot;
nknots=normal_knot->nknots=nobj->curve.normal.knot_count;
order=normal_knot->order=nobj->curve.normal.order;
normal_knot->delta_nknots=0;
t_min=normal_knot->t_min=order-1;
t_max=normal_knot->t_max=nknots-order;
if(fabs(knot[t_min]-knot[t_max])<EPSILON)
{
call_user_error(nobj,GLU_NURBS_ERROR3);
return GLU_ERROR;
}
if(fabs(knot[0]-knot[t_min])<EPSILON)
{
/* knot open at beggining */
normal_knot->open_at_begin=GL_TRUE;
}
else
normal_knot->open_at_begin=GL_FALSE;
if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
{
/* knot open at end */
normal_knot->open_at_end=GL_TRUE;
}
else
normal_knot->open_at_end=GL_FALSE;
}
else
normal_knot->unified_knot=NULL;
if(nobj->curve.texture.type!=GLU_INVALID_ENUM)
{
texture_knot->unified_knot=(GLfloat *)1;
knot=texture_knot->knot=nobj->curve.texture.knot;
nknots=texture_knot->nknots=nobj->curve.texture.knot_count;
order=texture_knot->order=nobj->curve.texture.order;
texture_knot->delta_nknots=0;
t_min=texture_knot->t_min=order-1;
t_max=texture_knot->t_max=nknots-order;
if(fabs(knot[t_min]-knot[t_max])<EPSILON)
{
call_user_error(nobj,GLU_NURBS_ERROR3);
return GLU_ERROR;
}
if(fabs(knot[0]-knot[t_min])<EPSILON)
{
/* knot open at beggining */
texture_knot->open_at_begin=GL_TRUE;
}
else
texture_knot->open_at_begin=GL_FALSE;
if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
{
/* knot open at end */
texture_knot->open_at_end=GL_TRUE;
}
else
texture_knot->open_at_end=GL_FALSE;
}
else
texture_knot->unified_knot=NULL;
return GLU_NO_ERROR;
geom_knot->unified_knot = NULL;
knot = geom_knot->knot = nobj->curve.geom.knot;
nknots = geom_knot->nknots = nobj->curve.geom.knot_count;
order = geom_knot->order = nobj->curve.geom.order;
geom_knot->delta_nknots = 0;
t_min = geom_knot->t_min = order - 1;
t_max = geom_knot->t_max = nknots - order;
if (fabs(knot[t_min] - knot[t_max]) < EPSILON) {
call_user_error(nobj, GLU_NURBS_ERROR3);
return GLU_ERROR;
}
if (fabs(knot[0] - knot[t_min]) < EPSILON) {
/* knot open at beggining */
geom_knot->open_at_begin = GL_TRUE;
}
else
geom_knot->open_at_begin = GL_FALSE;
if (fabs(knot[t_max] - knot[nknots - 1]) < EPSILON) {
/* knot open at end */
geom_knot->open_at_end = GL_TRUE;
}
else
geom_knot->open_at_end = GL_FALSE;
if (nobj->curve.color.type != GLU_INVALID_ENUM) {
color_knot->unified_knot = (GLfloat *) 1;
knot = color_knot->knot = nobj->curve.color.knot;
nknots = color_knot->nknots = nobj->curve.color.knot_count;
order = color_knot->order = nobj->curve.color.order;
color_knot->delta_nknots = 0;
t_min = color_knot->t_min = order - 1;
t_max = color_knot->t_max = nknots - order;
if (fabs(knot[t_min] - knot[t_max]) < EPSILON) {
call_user_error(nobj, GLU_NURBS_ERROR3);
return GLU_ERROR;
}
if (fabs(knot[0] - knot[t_min]) < EPSILON) {
/* knot open at beggining */
color_knot->open_at_begin = GL_TRUE;
}
else
color_knot->open_at_begin = GL_FALSE;
if (fabs(knot[t_max] - knot[nknots - 1]) < EPSILON) {
/* knot open at end */
color_knot->open_at_end = GL_TRUE;
}
else
color_knot->open_at_end = GL_FALSE;
}
else
color_knot->unified_knot = NULL;
if (nobj->curve.normal.type != GLU_INVALID_ENUM) {
normal_knot->unified_knot = (GLfloat *) 1;
knot = normal_knot->knot = nobj->curve.normal.knot;
nknots = normal_knot->nknots = nobj->curve.normal.knot_count;
order = normal_knot->order = nobj->curve.normal.order;
normal_knot->delta_nknots = 0;
t_min = normal_knot->t_min = order - 1;
t_max = normal_knot->t_max = nknots - order;
if (fabs(knot[t_min] - knot[t_max]) < EPSILON) {
call_user_error(nobj, GLU_NURBS_ERROR3);
return GLU_ERROR;
}
if (fabs(knot[0] - knot[t_min]) < EPSILON) {
/* knot open at beggining */
normal_knot->open_at_begin = GL_TRUE;
}
else
normal_knot->open_at_begin = GL_FALSE;
if (fabs(knot[t_max] - knot[nknots - 1]) < EPSILON) {
/* knot open at end */
normal_knot->open_at_end = GL_TRUE;
}
else
normal_knot->open_at_end = GL_FALSE;
}
else
normal_knot->unified_knot = NULL;
if (nobj->curve.texture.type != GLU_INVALID_ENUM) {
texture_knot->unified_knot = (GLfloat *) 1;
knot = texture_knot->knot = nobj->curve.texture.knot;
nknots = texture_knot->nknots = nobj->curve.texture.knot_count;
order = texture_knot->order = nobj->curve.texture.order;
texture_knot->delta_nknots = 0;
t_min = texture_knot->t_min = order - 1;
t_max = texture_knot->t_max = nknots - order;
if (fabs(knot[t_min] - knot[t_max]) < EPSILON) {
call_user_error(nobj, GLU_NURBS_ERROR3);
return GLU_ERROR;
}
if (fabs(knot[0] - knot[t_min]) < EPSILON) {
/* knot open at beggining */
texture_knot->open_at_begin = GL_TRUE;
}
else
texture_knot->open_at_begin = GL_FALSE;
if (fabs(knot[t_max] - knot[nknots - 1]) < EPSILON) {
/* knot open at end */
texture_knot->open_at_end = GL_TRUE;
}
else
texture_knot->open_at_end = GL_FALSE;
}
else
texture_knot->unified_knot = NULL;
return GLU_NO_ERROR;
}

/* covert the NURBS curve into a series of adjacent Bezier curves */
static GLenum
convert_curve(knot_str_type *the_knot, curve_attribs *attrib,
GLfloat **new_ctrl,GLint *ncontrol)
convert_curve(knot_str_type * the_knot, curve_attribs * attrib,
GLfloat ** new_ctrl, GLint * ncontrol)
{
GLenum err;
GLenum err;

if((err=explode_knot(the_knot))!=GLU_NO_ERROR)
{
if(the_knot->unified_knot)
{
free(the_knot->unified_knot);
the_knot->unified_knot=NULL;
}
return err;
}
if(the_knot->unified_knot)
{
free(the_knot->unified_knot);
the_knot->unified_knot=NULL;
}
if((err=calc_alphas(the_knot))!=GLU_NO_ERROR)
{
free(the_knot->new_knot);
return err;
}
free(the_knot->new_knot);
if((err=calc_new_ctrl_pts(attrib->ctrlarray,attrib->stride,the_knot,
attrib->dim,new_ctrl,ncontrol))
!=GLU_NO_ERROR)
{
free(the_knot->alpha);
return err;
}
free(the_knot->alpha);
return GLU_NO_ERROR;
if ((err = explode_knot(the_knot)) != GLU_NO_ERROR) {
if (the_knot->unified_knot) {
free(the_knot->unified_knot);
the_knot->unified_knot = NULL;
}
return err;
}
if (the_knot->unified_knot) {
free(the_knot->unified_knot);
the_knot->unified_knot = NULL;
}
if ((err = calc_alphas(the_knot)) != GLU_NO_ERROR) {
free(the_knot->new_knot);
return err;
}
free(the_knot->new_knot);
if ((err = calc_new_ctrl_pts(attrib->ctrlarray, attrib->stride, the_knot,
attrib->dim, new_ctrl, ncontrol))
!= GLU_NO_ERROR) {
free(the_knot->alpha);
return err;
}
free(the_knot->alpha);
return GLU_NO_ERROR;
}

/* covert curves - geometry and possible attribute ones into equivalent */
/* sequence of adjacent Bezier curves */
static GLenum
convert_curves(GLUnurbsObj *nobj, GLfloat **new_geom_ctrl,
GLint *ncontrol, GLfloat **new_color_ctrl, GLfloat **new_normal_ctrl,
GLfloat **new_texture_ctrl)
convert_curves(GLUnurbsObj * nobj, GLfloat ** new_geom_ctrl,
GLint * ncontrol, GLfloat ** new_color_ctrl,
GLfloat ** new_normal_ctrl, GLfloat ** new_texture_ctrl)
{
knot_str_type geom_knot,color_knot,normal_knot,texture_knot;
GLint junk;
GLenum err;
knot_str_type geom_knot, color_knot, normal_knot, texture_knot;
GLint junk;
GLenum err;

*new_color_ctrl=*new_normal_ctrl=*new_texture_ctrl=NULL;
*new_color_ctrl = *new_normal_ctrl = *new_texture_ctrl = NULL;

if(fill_knot_structures(nobj,&geom_knot,&color_knot,&normal_knot,
&texture_knot)!=GLU_NO_ERROR)
return GLU_ERROR;
if (fill_knot_structures(nobj, &geom_knot, &color_knot, &normal_knot,
&texture_knot) != GLU_NO_ERROR)
return GLU_ERROR;

/* unify knots - all knots should have the same number of working */
/* ranges */
if((err=select_knot_working_range(nobj,&geom_knot,&color_knot,&normal_knot,
&texture_knot))!=GLU_NO_ERROR)
{
return err;
}
/* convert the geometry curve */
nobj->curve.geom.dim=get_curve_dim(nobj->curve.geom.type);
if((err=convert_curve(&geom_knot,&(nobj->curve.geom),new_geom_ctrl,
ncontrol))!=GLU_NO_ERROR)
{
free_unified_knots(&geom_knot,&color_knot,&normal_knot,&texture_knot);
call_user_error(nobj,err);
return err;
}
/* if additional attributive curves are given convert them as well */
if(color_knot.unified_knot)
{
nobj->curve.color.dim=get_curve_dim(nobj->curve.color.type);
if((err=convert_curve(&color_knot,&(nobj->curve.color),
new_color_ctrl,&junk))!=GLU_NO_ERROR)
{
free_unified_knots(&geom_knot,&color_knot,&normal_knot,&texture_knot);
free(*new_geom_ctrl);
call_user_error(nobj,err);
return err;
}
}
if(normal_knot.unified_knot)
{
nobj->curve.normal.dim=get_curve_dim(nobj->curve.normal.type);
if((err=convert_curve(&normal_knot,&(nobj->curve.normal),
new_normal_ctrl,&junk))!=GLU_NO_ERROR)
{
free_unified_knots(&geom_knot,&color_knot,&normal_knot,&texture_knot);
free(*new_geom_ctrl);
if(*new_color_ctrl)
free(*new_color_ctrl);
call_user_error(nobj,err);
return err;
}
}
if(texture_knot.unified_knot)
{
nobj->curve.texture.dim=get_curve_dim(nobj->curve.texture.type);
if((err=convert_curve(&texture_knot,&(nobj->curve.texture),
new_texture_ctrl,&junk))!=GLU_NO_ERROR)
{
free_unified_knots(&geom_knot,&color_knot,&normal_knot,&texture_knot);
free(*new_geom_ctrl);
if(*new_color_ctrl)
free(*new_color_ctrl);
if(*new_normal_ctrl)
free(*new_normal_ctrl);
call_user_error(nobj,err);
return err;
}
}
return GLU_NO_ERROR;
/* unify knots - all knots should have the same number of working */
/* ranges */
if (
(err =
select_knot_working_range(nobj, &geom_knot, &color_knot, &normal_knot,
&texture_knot)) != GLU_NO_ERROR) {
return err;
}
/* convert the geometry curve */
nobj->curve.geom.dim = get_curve_dim(nobj->curve.geom.type);
if ((err = convert_curve(&geom_knot, &(nobj->curve.geom), new_geom_ctrl,
ncontrol)) != GLU_NO_ERROR) {
free_unified_knots(&geom_knot, &color_knot, &normal_knot,
&texture_knot);
call_user_error(nobj, err);
return err;
}
/* if additional attributive curves are given convert them as well */
if (color_knot.unified_knot) {
nobj->curve.color.dim = get_curve_dim(nobj->curve.color.type);
if ((err = convert_curve(&color_knot, &(nobj->curve.color),
new_color_ctrl, &junk)) != GLU_NO_ERROR) {
free_unified_knots(&geom_knot, &color_knot, &normal_knot,
&texture_knot);
free(*new_geom_ctrl);
call_user_error(nobj, err);
return err;
}
}
if (normal_knot.unified_knot) {
nobj->curve.normal.dim = get_curve_dim(nobj->curve.normal.type);
if ((err = convert_curve(&normal_knot, &(nobj->curve.normal),
new_normal_ctrl, &junk)) != GLU_NO_ERROR) {
free_unified_knots(&geom_knot, &color_knot, &normal_knot,
&texture_knot);
free(*new_geom_ctrl);
if (*new_color_ctrl)
free(*new_color_ctrl);
call_user_error(nobj, err);
return err;
}
}
if (texture_knot.unified_knot) {
nobj->curve.texture.dim = get_curve_dim(nobj->curve.texture.type);
if ((err = convert_curve(&texture_knot, &(nobj->curve.texture),
new_texture_ctrl, &junk)) != GLU_NO_ERROR) {
free_unified_knots(&geom_knot, &color_knot, &normal_knot,
&texture_knot);
free(*new_geom_ctrl);
if (*new_color_ctrl)
free(*new_color_ctrl);
if (*new_normal_ctrl)
free(*new_normal_ctrl);
call_user_error(nobj, err);
return err;
}
}
return GLU_NO_ERROR;
}

/* main NURBS curve procedure */
void do_nurbs_curve( GLUnurbsObj *nobj)
void
do_nurbs_curve(GLUnurbsObj * nobj)
{
GLint geom_order,color_order=0,normal_order=0,texture_order=0;
GLenum geom_type;
GLint n_ctrl;
GLfloat *new_geom_ctrl,*new_color_ctrl,*new_normal_ctrl,*new_texture_ctrl;
GLfloat *geom_ctrl,*color_ctrl,*normal_ctrl,*texture_ctrl;
GLint *factors;
GLint i,j;
GLint geom_dim,color_dim=0,normal_dim=0,texture_dim=0;
GLint geom_order, color_order = 0, normal_order = 0, texture_order = 0;
GLenum geom_type;
GLint n_ctrl;
GLfloat *new_geom_ctrl, *new_color_ctrl, *new_normal_ctrl,
*new_texture_ctrl;
GLfloat *geom_ctrl, *color_ctrl, *normal_ctrl, *texture_ctrl;
GLint *factors;
GLint i, j;
GLint geom_dim, color_dim = 0, normal_dim = 0, texture_dim = 0;

/* test the user supplied data */
if(test_nurbs_curves(nobj)!=GLU_NO_ERROR)
return;
/* test the user supplied data */
if (test_nurbs_curves(nobj) != GLU_NO_ERROR)
return;

if(convert_curves(nobj,&new_geom_ctrl,&n_ctrl,&new_color_ctrl,
&new_normal_ctrl,&new_texture_ctrl)!=GLU_NO_ERROR)
return;
if (convert_curves(nobj, &new_geom_ctrl, &n_ctrl, &new_color_ctrl,
&new_normal_ctrl, &new_texture_ctrl) != GLU_NO_ERROR)
return;

geom_order=nobj->curve.geom.order;
geom_type=nobj->curve.geom.type;
geom_dim=nobj->curve.geom.dim;
geom_order = nobj->curve.geom.order;
geom_type = nobj->curve.geom.type;
geom_dim = nobj->curve.geom.dim;

if(glu_do_sampling_crv(nobj,new_geom_ctrl,n_ctrl,geom_order,geom_dim,
&factors)
!=GLU_NO_ERROR)
{
free(new_geom_ctrl);
if(new_color_ctrl)
free(new_color_ctrl);
if(new_normal_ctrl)
free(new_normal_ctrl);
if(new_texture_ctrl)
free(new_texture_ctrl);
return;
}
glEnable(geom_type);
if(new_color_ctrl)
{
glEnable(nobj->curve.color.type);
color_dim=nobj->curve.color.dim;
color_ctrl=new_color_ctrl;
color_order=nobj->curve.color.order;
}
if(new_normal_ctrl)
{
glEnable(nobj->curve.normal.type);
normal_dim=nobj->curve.normal.dim;
normal_ctrl=new_normal_ctrl;
normal_order=nobj->curve.normal.order;
}
if(new_texture_ctrl)
{
glEnable(nobj->curve.texture.type);
texture_dim=nobj->curve.texture.dim;
texture_ctrl=new_texture_ctrl;
texture_order=nobj->curve.texture.order;
}
for(i=0 , j=0, geom_ctrl=new_geom_ctrl;
i<n_ctrl;
i+=geom_order , j++ , geom_ctrl+=geom_order*geom_dim)
{
if(fine_culling_test_2D(nobj,geom_ctrl,geom_order,geom_dim,geom_dim))
{
color_ctrl+=color_order*color_dim;
normal_ctrl+=normal_order*normal_dim;
texture_ctrl+=texture_order*texture_dim;
continue;
}
glMap1f(geom_type, 0.0, 1.0, geom_dim, geom_order, geom_ctrl);
if(new_color_ctrl)
{
glMap1f(nobj->curve.color.type, 0.0, 1.0, color_dim,
color_order,color_ctrl);
color_ctrl+=color_order*color_dim;
}
if(new_normal_ctrl)
{
glMap1f(nobj->curve.normal.type, 0.0, 1.0, normal_dim,
normal_order,normal_ctrl);
normal_ctrl+=normal_order*normal_dim;
}
if(new_texture_ctrl)
{
glMap1f(nobj->curve.texture.type, 0.0, 1.0, texture_dim,
texture_order,texture_ctrl);
texture_ctrl+=texture_order*texture_dim;
}
glMapGrid1f(factors[j],0.0,1.0);
glEvalMesh1(GL_LINE,0,factors[j]);
}
free(new_geom_ctrl);
free(factors);
if(new_color_ctrl)
free(new_color_ctrl);
if(new_normal_ctrl)
free(new_normal_ctrl);
if(new_texture_ctrl)
free(new_texture_ctrl);
if (glu_do_sampling_crv(nobj, new_geom_ctrl, n_ctrl, geom_order, geom_dim,
&factors) != GLU_NO_ERROR) {
free(new_geom_ctrl);
if (new_color_ctrl)
free(new_color_ctrl);
if (new_normal_ctrl)
free(new_normal_ctrl);
if (new_texture_ctrl)
free(new_texture_ctrl);
return;
}
glEnable(geom_type);
if (new_color_ctrl) {
glEnable(nobj->curve.color.type);
color_dim = nobj->curve.color.dim;
color_ctrl = new_color_ctrl;
color_order = nobj->curve.color.order;
}
if (new_normal_ctrl) {
glEnable(nobj->curve.normal.type);
normal_dim = nobj->curve.normal.dim;
normal_ctrl = new_normal_ctrl;
normal_order = nobj->curve.normal.order;
}
if (new_texture_ctrl) {
glEnable(nobj->curve.texture.type);
texture_dim = nobj->curve.texture.dim;
texture_ctrl = new_texture_ctrl;
texture_order = nobj->curve.texture.order;
}
for (i = 0, j = 0, geom_ctrl = new_geom_ctrl;
i < n_ctrl; i += geom_order, j++, geom_ctrl += geom_order * geom_dim) {
if (fine_culling_test_2D
(nobj, geom_ctrl, geom_order, geom_dim, geom_dim)) {
color_ctrl += color_order * color_dim;
normal_ctrl += normal_order * normal_dim;
texture_ctrl += texture_order * texture_dim;
continue;
}
glMap1f(geom_type, 0.0, 1.0, geom_dim, geom_order, geom_ctrl);
if (new_color_ctrl) {
glMap1f(nobj->curve.color.type, 0.0, 1.0, color_dim,
color_order, color_ctrl);
color_ctrl += color_order * color_dim;
}
if (new_normal_ctrl) {
glMap1f(nobj->curve.normal.type, 0.0, 1.0, normal_dim,
normal_order, normal_ctrl);
normal_ctrl += normal_order * normal_dim;
}
if (new_texture_ctrl) {
glMap1f(nobj->curve.texture.type, 0.0, 1.0, texture_dim,
texture_order, texture_ctrl);
texture_ctrl += texture_order * texture_dim;
}
glMapGrid1f(factors[j], 0.0, 1.0);
glEvalMesh1(GL_LINE, 0, factors[j]);
}
free(new_geom_ctrl);
free(factors);
if (new_color_ctrl)
free(new_color_ctrl);
if (new_normal_ctrl)
free(new_normal_ctrl);
if (new_texture_ctrl)
free(new_texture_ctrl);
}



+ 1142
- 1246
src/glu/mesa/nurbssrf.c
Diff nebyl zobrazen, protože je příliš veliký
Zobrazit soubor


+ 1061
- 1154
src/glu/mesa/nurbsutl.c
Diff nebyl zobrazen, protože je příliš veliký
Zobrazit soubor


+ 938
- 0
src/glu/mesa/polytest.c Zobrazit soubor

@@ -0,0 +1,938 @@
/* $Id: polytest.c,v 1.3 2000/07/11 14:11:04 brianp Exp $ */

/*
* Mesa 3-D graphics library
* Version: 3.3
* Copyright (C) 1995-2000 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/


/*
* This file is part of the polygon tesselation code contributed by
* Bogdan Sikorski
*/


#ifdef PC_HEADER
#include "all.h"
#else
#include <math.h>
#include <stdlib.h>
#include "gluP.h"
#include "tess.h"
#endif



static GLenum store_polygon_as_contour(GLUtriangulatorObj *);
static void free_current_polygon(tess_polygon *);
static void prepare_projection_info(GLUtriangulatorObj *);
static GLdouble twice_the_polygon_area(tess_vertex *, tess_vertex *);
static GLenum verify_edge_vertex_intersections(GLUtriangulatorObj *);
void tess_find_contour_hierarchies(GLUtriangulatorObj *);
static GLenum test_for_overlapping_contours(GLUtriangulatorObj *);
static GLenum contours_overlap(tess_contour *, tess_polygon *);
static GLenum is_contour_contained_in(tess_contour *, tess_contour *);
static void add_new_exterior(GLUtriangulatorObj *, tess_contour *);
static void add_new_interior(GLUtriangulatorObj *, tess_contour *,
tess_contour *);
static void add_interior_with_hierarchy_check(GLUtriangulatorObj *,
tess_contour *, tess_contour *);
static void reverse_hierarchy_and_add_exterior(GLUtriangulatorObj *,
tess_contour *,
tess_contour *);
static GLboolean point_in_polygon(tess_contour *, GLdouble, GLdouble);
static void shift_interior_to_exterior(GLUtriangulatorObj *, tess_contour *);
static void add_exterior_with_check(GLUtriangulatorObj *, tess_contour *,
tess_contour *);
static GLenum cut_out_hole(GLUtriangulatorObj *, tess_contour *,
tess_contour *);
static GLenum merge_hole_with_contour(GLUtriangulatorObj *,
tess_contour *, tess_contour *,
tess_vertex *, tess_vertex *);

static GLenum
find_normal(GLUtriangulatorObj * tobj)
{
tess_polygon *polygon = tobj->current_polygon;
tess_vertex *va, *vb, *vc;
GLdouble A, B, C;
GLdouble A0, A1, A2, B0, B1, B2;

va = polygon->vertices;
vb = va->next;
A0 = vb->location[0] - va->location[0];
A1 = vb->location[1] - va->location[1];
A2 = vb->location[2] - va->location[2];
for (vc = vb->next; vc != va; vc = vc->next) {
B0 = vc->location[0] - va->location[0];
B1 = vc->location[1] - va->location[1];
B2 = vc->location[2] - va->location[2];
A = A1 * B2 - A2 * B1;
B = A2 * B0 - A0 * B2;
C = A0 * B1 - A1 * B0;
if (fabs(A) > EPSILON || fabs(B) > EPSILON || fabs(C) > EPSILON) {
polygon->A = A;
polygon->B = B;
polygon->C = C;
polygon->D =
-A * va->location[0] - B * va->location[1] - C * va->location[2];
return GLU_NO_ERROR;
}
}
tess_call_user_error(tobj, GLU_TESS_ERROR7);
return GLU_ERROR;
}

void
tess_test_polygon(GLUtriangulatorObj * tobj)
{
tess_polygon *polygon = tobj->current_polygon;

/* any vertices defined? */
if (polygon->vertex_cnt < 3) {
free_current_polygon(polygon);
return;
}
/* wrap pointers */
polygon->last_vertex->next = polygon->vertices;
polygon->vertices->previous = polygon->last_vertex;
/* determine the normal */
if (find_normal(tobj) == GLU_ERROR)
return;
/* compare the normals of previously defined contours and this one */
/* first contour define ? */
if (tobj->contours == NULL) {
tobj->A = polygon->A;
tobj->B = polygon->B;
tobj->C = polygon->C;
tobj->D = polygon->D;
/* determine the best projection to use */
if (fabs(polygon->A) > fabs(polygon->B))
if (fabs(polygon->A) > fabs(polygon->C))
tobj->projection = OYZ;
else
tobj->projection = OXY;
else if (fabs(polygon->B) > fabs(polygon->C))
tobj->projection = OXZ;
else
tobj->projection = OXY;
}
else {
GLdouble a[3], b[3];
tess_vertex *vertex = polygon->vertices;

a[0] = tobj->A;
a[1] = tobj->B;
a[2] = tobj->C;
b[0] = polygon->A;
b[1] = polygon->B;
b[2] = polygon->C;

/* compare the normals */
if (fabs(a[1] * b[2] - a[2] * b[1]) > EPSILON ||
fabs(a[2] * b[0] - a[0] * b[2]) > EPSILON ||
fabs(a[0] * b[1] - a[1] * b[0]) > EPSILON) {
/* not coplanar */
tess_call_user_error(tobj, GLU_TESS_ERROR9);
return;
}
/* the normals are parallel - test for plane equation */
if (fabs(a[0] * vertex->location[0] + a[1] * vertex->location[1] +
a[2] * vertex->location[2] + tobj->D) > EPSILON) {
/* not the same plane */
tess_call_user_error(tobj, GLU_TESS_ERROR9);
return;
}
}
prepare_projection_info(tobj);
if (verify_edge_vertex_intersections(tobj) == GLU_ERROR)
return;
if (test_for_overlapping_contours(tobj) == GLU_ERROR)
return;
if (store_polygon_as_contour(tobj) == GLU_ERROR)
return;
}

static GLenum
test_for_overlapping_contours(GLUtriangulatorObj * tobj)
{
tess_contour *contour;
tess_polygon *polygon;

polygon = tobj->current_polygon;
for (contour = tobj->contours; contour != NULL; contour = contour->next)
if (contours_overlap(contour, polygon) != GLU_NO_ERROR) {
tess_call_user_error(tobj, GLU_TESS_ERROR5);
return GLU_ERROR;
}
return GLU_NO_ERROR;
}

static GLenum
store_polygon_as_contour(GLUtriangulatorObj * tobj)
{
tess_polygon *polygon = tobj->current_polygon;
tess_contour *contour = tobj->contours;

/* the first contour defined */
if (contour == NULL) {
if ((contour = (tess_contour *) malloc(sizeof(tess_contour))) == NULL) {
tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
free_current_polygon(polygon);
return GLU_ERROR;
}
tobj->contours = tobj->last_contour = contour;
contour->next = contour->previous = NULL;
}
else {
if ((contour = (tess_contour *) malloc(sizeof(tess_contour))) == NULL) {
tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
free_current_polygon(polygon);
return GLU_ERROR;
}
contour->previous = tobj->last_contour;
tobj->last_contour->next = contour;
tobj->last_contour = contour;
contour->next = NULL;
}
/* mark all vertices in new contour as not special */
/* and all are boundary edges */
{
tess_vertex *vertex;
GLuint vertex_cnt, i;

for (vertex = polygon->vertices, i = 0, vertex_cnt =
polygon->vertex_cnt; i < vertex_cnt; vertex = vertex->next, i++) {
vertex->shadow_vertex = NULL;
vertex->edge_flag = GL_TRUE;
}
}
contour->vertex_cnt = polygon->vertex_cnt;
contour->area = polygon->area;
contour->orientation = polygon->orientation;
contour->type = GLU_UNKNOWN;
contour->vertices = polygon->vertices;
contour->last_vertex = polygon->last_vertex;
polygon->vertices = polygon->last_vertex = NULL;
polygon->vertex_cnt = 0;
++(tobj->contour_cnt);
return GLU_NO_ERROR;
}

static void
free_current_polygon(tess_polygon * polygon)
{
tess_vertex *vertex, *vertex_tmp;
GLuint i;

/* free current_polygon structures */
for (vertex = polygon->vertices, i = 0; i < polygon->vertex_cnt; i++) {
vertex_tmp = vertex->next;
free(vertex);
vertex = vertex_tmp;
}
polygon->vertices = polygon->last_vertex = NULL;
polygon->vertex_cnt = 0;
}

static void
prepare_projection_info(GLUtriangulatorObj * tobj)
{
tess_polygon *polygon = tobj->current_polygon;
tess_vertex *vertex, *last_vertex_ptr;
GLdouble area;

last_vertex_ptr = polygon->last_vertex;
switch (tobj->projection) {
case OXY:
for (vertex = polygon->vertices; vertex != last_vertex_ptr;
vertex = vertex->next) {
vertex->x = vertex->location[0];
vertex->y = vertex->location[1];
}
last_vertex_ptr->x = last_vertex_ptr->location[0];
last_vertex_ptr->y = last_vertex_ptr->location[1];
break;
case OXZ:
for (vertex = polygon->vertices; vertex != last_vertex_ptr;
vertex = vertex->next) {
vertex->x = vertex->location[0];
vertex->y = vertex->location[2];
}
last_vertex_ptr->x = last_vertex_ptr->location[0];
last_vertex_ptr->y = last_vertex_ptr->location[2];
break;
case OYZ:
for (vertex = polygon->vertices; vertex != last_vertex_ptr;
vertex = vertex->next) {
vertex->x = vertex->location[1];
vertex->y = vertex->location[2];
}
last_vertex_ptr->x = last_vertex_ptr->location[1];
last_vertex_ptr->y = last_vertex_ptr->location[2];
break;
}
area = twice_the_polygon_area(polygon->vertices, polygon->last_vertex);
if (area >= 0.0) {
polygon->orientation = GLU_CCW;
polygon->area = area;
}
else {
polygon->orientation = GLU_CW;
polygon->area = -area;
}
}

static GLdouble
twice_the_polygon_area(tess_vertex * vertex, tess_vertex * last_vertex)
{
tess_vertex *next;
GLdouble area, x, y;

area = 0.0;
x = vertex->x;
y = vertex->y;
vertex = vertex->next;
for (; vertex != last_vertex; vertex = vertex->next) {
next = vertex->next;
area +=
(vertex->x - x) * (next->y - y) - (vertex->y - y) * (next->x - x);
}
return area;
}

/* test if edges ab and cd intersect */
/* if not return GLU_NO_ERROR, else if cross return GLU_TESS_ERROR8, */
/* else if adjacent return GLU_TESS_ERROR4 */
static GLenum
edge_edge_intersect(tess_vertex * a,
tess_vertex * b, tess_vertex * c, tess_vertex * d)
{
GLdouble denom, r, s;
GLdouble xba, ydc, yba, xdc, yac, xac;

xba = b->x - a->x;
yba = b->y - a->y;
xdc = d->x - c->x;
ydc = d->y - c->y;
xac = a->x - c->x;
yac = a->y - c->y;
denom = xba * ydc - yba * xdc;
r = yac * xdc - xac * ydc;
/* parallel? */
if (fabs(denom) < EPSILON) {
if (fabs(r) < EPSILON) {
/* colinear */
if (fabs(xba) < EPSILON) {
/* compare the Y coordinate */
if (yba > 0.0) {
if (
(fabs(a->y - c->y) < EPSILON
&& fabs(c->y - b->y) < EPSILON)
|| (fabs(a->y - d->y) < EPSILON
&& fabs(d->y - b->y) <
EPSILON)) return GLU_TESS_ERROR4;

}
else {
if (
(fabs(b->y - c->y) < EPSILON
&& fabs(c->y - a->y) < EPSILON)
|| (fabs(b->y - d->y) < EPSILON
&& fabs(d->y - a->y) <
EPSILON)) return GLU_TESS_ERROR4;
}
}
else {
/* compare the X coordinate */
if (xba > 0.0) {
if (
(fabs(a->x - c->x) < EPSILON
&& fabs(c->x - b->x) < EPSILON)
|| (fabs(a->x - d->x) < EPSILON
&& fabs(d->x - b->x) <
EPSILON)) return GLU_TESS_ERROR4;
}
else {
if (
(fabs(b->x - c->x) < EPSILON
&& fabs(c->x - a->x) < EPSILON)
|| (fabs(b->x - d->x) < EPSILON
&& fabs(d->x - a->x) <
EPSILON)) return GLU_TESS_ERROR4;
}
}
}
return GLU_NO_ERROR;
}
r /= denom;
s = (yac * xba - xac * yba) / denom;
/* test if one vertex lies on other edge */
if (((fabs(r) < EPSILON || (r < 1.0 + EPSILON && r > 1.0 - EPSILON)) &&
s > -EPSILON && s < 1.0 + EPSILON) ||
((fabs(s) < EPSILON || (s < 1.0 + EPSILON && s > 1.0 - EPSILON)) &&
r > -EPSILON && r < 1.0 + EPSILON)) {
return GLU_TESS_ERROR4;
}
/* test for crossing */
if (r > -EPSILON && r < 1.0 + EPSILON && s > -EPSILON && s < 1.0 + EPSILON) {
return GLU_TESS_ERROR8;
}
return GLU_NO_ERROR;
}

static GLenum
verify_edge_vertex_intersections(GLUtriangulatorObj * tobj)
{
tess_polygon *polygon = tobj->current_polygon;
tess_vertex *vertex1, *last_vertex, *vertex2;
GLenum test;

last_vertex = polygon->last_vertex;
vertex1 = last_vertex;
for (vertex2 = vertex1->next->next;
vertex2->next != last_vertex; vertex2 = vertex2->next) {
test = edge_edge_intersect(vertex1, vertex1->next, vertex2,
vertex2->next);
if (test != GLU_NO_ERROR) {
tess_call_user_error(tobj, test);
return GLU_ERROR;
}
}
for (vertex1 = polygon->vertices;
vertex1->next->next != last_vertex; vertex1 = vertex1->next) {
for (vertex2 = vertex1->next->next;
vertex2 != last_vertex; vertex2 = vertex2->next) {
test = edge_edge_intersect(vertex1, vertex1->next, vertex2,
vertex2->next);
if (test != GLU_NO_ERROR) {
tess_call_user_error(tobj, test);
return GLU_ERROR;
}
}
}
return GLU_NO_ERROR;
}

static int
#ifdef WIN32
__cdecl
#endif
area_compare(const void *a, const void *b)
{
GLdouble area1, area2;

area1 = (*((tess_contour **) a))->area;
area2 = (*((tess_contour **) b))->area;
if (area1 < area2)
return 1;
if (area1 > area2)
return -1;
return 0;
}

void
tess_find_contour_hierarchies(GLUtriangulatorObj * tobj)
{
tess_contour **contours; /* dinamic array of pointers */
tess_contour *tmp_contour_ptr = tobj->contours;
GLuint cnt, i;
GLenum result;
GLboolean hierarchy_changed;

/* any contours? */
if (tobj->contour_cnt < 2) {
tobj->contours->type = GLU_EXTERIOR;
return;
}
if ((contours = (tess_contour **)
malloc(sizeof(tess_contour *) * (tobj->contour_cnt))) == NULL) {
tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
return;
}
for (tmp_contour_ptr = tobj->contours, cnt = 0;
tmp_contour_ptr != NULL; tmp_contour_ptr = tmp_contour_ptr->next)
contours[cnt++] = tmp_contour_ptr;
/* now sort the contours in decreasing area size order */
qsort((void *) contours, (size_t) cnt, (size_t) sizeof(tess_contour *),
area_compare);
/* we leave just the first contour - remove others from list */
tobj->contours = contours[0];
tobj->contours->next = tobj->contours->previous = NULL;
tobj->last_contour = tobj->contours;
tobj->contour_cnt = 1;
/* first contour is the one with greatest area */
/* must be EXTERIOR */
tobj->contours->type = GLU_EXTERIOR;
tmp_contour_ptr = tobj->contours;
/* now we play! */
for (i = 1; i < cnt; i++) {
hierarchy_changed = GL_FALSE;
for (tmp_contour_ptr = tobj->contours;
tmp_contour_ptr != NULL; tmp_contour_ptr = tmp_contour_ptr->next) {
if (tmp_contour_ptr->type == GLU_EXTERIOR) {
/* check if contour completely contained in EXTERIOR */
result = is_contour_contained_in(tmp_contour_ptr, contours[i]);
switch (result) {
case GLU_INTERIOR:
/* now we have to check if contour is inside interiors */
/* or not */
/* any interiors? */
if (tmp_contour_ptr->next != NULL &&
tmp_contour_ptr->next->type == GLU_INTERIOR) {
/* for all interior, check if inside any of them */
/* if not inside any of interiors, its another */
/* interior */
/* or it may contain some interiors, then change */
/* the contained interiors to exterior ones */
add_interior_with_hierarchy_check(tobj,
tmp_contour_ptr,
contours[i]);
}
else {
/* not in interior, add as new interior contour */
add_new_interior(tobj, tmp_contour_ptr, contours[i]);
}
hierarchy_changed = GL_TRUE;
break;
case GLU_EXTERIOR:
/* ooops, the marked as EXTERIOR (contours[i]) is */
/* actually an interior of tmp_contour_ptr */
/* reverse the local hierarchy */
reverse_hierarchy_and_add_exterior(tobj, tmp_contour_ptr,
contours[i]);
hierarchy_changed = GL_TRUE;
break;
case GLU_NO_ERROR:
break;
default:
abort();
}
}
if (hierarchy_changed)
break; /* break from for loop */
}
if (hierarchy_changed == GL_FALSE) {
/* disjoint with all contours, add to contour list */
add_new_exterior(tobj, contours[i]);
}
}
free(contours);
}

/* returns GLU_INTERIOR if inner is completey enclosed within outer */
/* returns GLU_EXTERIOR if outer is completely enclosed within inner */
/* returns GLU_NO_ERROR if contours are disjoint */
static GLenum
is_contour_contained_in(tess_contour * outer, tess_contour * inner)
{
GLenum relation_flag;

/* set relation_flag to relation of containment of first inner vertex */
/* regarding outer contour */
if (point_in_polygon(outer, inner->vertices->x, inner->vertices->y))
relation_flag = GLU_INTERIOR;
else
relation_flag = GLU_EXTERIOR;
if (relation_flag == GLU_INTERIOR)
return GLU_INTERIOR;
if (point_in_polygon(inner, outer->vertices->x, outer->vertices->y))
return GLU_EXTERIOR;
return GLU_NO_ERROR;
}

static GLboolean
point_in_polygon(tess_contour * contour, GLdouble x, GLdouble y)
{
tess_vertex *v1, *v2;
GLuint i, vertex_cnt;
GLdouble xp1, yp1, xp2, yp2;
GLboolean tst;

tst = GL_FALSE;
v1 = contour->vertices;
v2 = contour->vertices->previous;
for (i = 0, vertex_cnt = contour->vertex_cnt; i < vertex_cnt; i++) {
xp1 = v1->x;
yp1 = v1->y;
xp2 = v2->x;
yp2 = v2->y;
if ((((yp1 <= y) && (y < yp2)) || ((yp2 <= y) && (y < yp1))) &&
(x < (xp2 - xp1) * (y - yp1) / (yp2 - yp1) + xp1))
tst = (tst == GL_FALSE ? GL_TRUE : GL_FALSE);
v2 = v1;
v1 = v1->next;
}
return tst;
}

static GLenum
contours_overlap(tess_contour * contour, tess_polygon * polygon)
{
tess_vertex *vertex1, *vertex2;
GLuint vertex1_cnt, vertex2_cnt, i, j;
GLenum test;

vertex1 = contour->vertices;
vertex2 = polygon->vertices;
vertex1_cnt = contour->vertex_cnt;
vertex2_cnt = polygon->vertex_cnt;
for (i = 0; i < vertex1_cnt; vertex1 = vertex1->next, i++) {
for (j = 0; j < vertex2_cnt; vertex2 = vertex2->next, j++)
if ((test = edge_edge_intersect(vertex1, vertex1->next, vertex2,
vertex2->next)) != GLU_NO_ERROR)
return test;
}
return GLU_NO_ERROR;
}

static void
add_new_exterior(GLUtriangulatorObj * tobj, tess_contour * contour)
{
contour->type = GLU_EXTERIOR;
contour->next = NULL;
contour->previous = tobj->last_contour;
tobj->last_contour->next = contour;
tobj->last_contour = contour;
}

static void
add_new_interior(GLUtriangulatorObj * tobj,
tess_contour * outer, tess_contour * contour)
{
contour->type = GLU_INTERIOR;
contour->next = outer->next;
contour->previous = outer;
if (outer->next != NULL)
outer->next->previous = contour;
outer->next = contour;
if (tobj->last_contour == outer)
tobj->last_contour = contour;
}

static void
add_interior_with_hierarchy_check(GLUtriangulatorObj * tobj,
tess_contour * outer,
tess_contour * contour)
{
tess_contour *ptr;

/* for all interiors of outer check if they are interior of contour */
/* if so, change that interior to exterior and move it of of the */
/* interior sequence */
if (outer->next != NULL && outer->next->type == GLU_INTERIOR) {
GLenum test;

for (ptr = outer->next; ptr != NULL && ptr->type == GLU_INTERIOR;
ptr = ptr->next) {
test = is_contour_contained_in(ptr, contour);
switch (test) {
case GLU_INTERIOR:
/* contour is contained in one of the interiors */
/* check if possibly contained in other exteriors */
/* move ptr to first EXTERIOR */
for (; ptr != NULL && ptr->type == GLU_INTERIOR; ptr = ptr->next);
if (ptr == NULL)
/* another exterior */
add_new_exterior(tobj, contour);
else
add_exterior_with_check(tobj, ptr, contour);
return;
case GLU_EXTERIOR:
/* one of the interiors is contained in the contour */
/* change it to EXTERIOR, and shift it away from the */
/* interior sequence */
shift_interior_to_exterior(tobj, ptr);
break;
case GLU_NO_ERROR:
/* disjoint */
break;
default:
abort();
}
}
}
/* add contour to the interior sequence */
add_new_interior(tobj, outer, contour);
}

static void
reverse_hierarchy_and_add_exterior(GLUtriangulatorObj * tobj,
tess_contour * outer,
tess_contour * contour)
{
tess_contour *ptr;

/* reverse INTERIORS to EXTERIORS */
/* any INTERIORS? */
if (outer->next != NULL && outer->next->type == GLU_INTERIOR)
for (ptr = outer->next; ptr != NULL && ptr->type == GLU_INTERIOR;
ptr = ptr->next) ptr->type = GLU_EXTERIOR;
/* the outer now becomes inner */
outer->type = GLU_INTERIOR;
/* contour is the EXTERIOR */
contour->next = outer;
if (tobj->contours == outer) {
/* first contour beeing reversed */
contour->previous = NULL;
tobj->contours = contour;
}
else {
outer->previous->next = contour;
contour->previous = outer->previous;
}
outer->previous = contour;
}

static void
shift_interior_to_exterior(GLUtriangulatorObj * tobj, tess_contour * contour)
{
contour->previous->next = contour->next;
if (contour->next != NULL)
contour->next->previous = contour->previous;
else
tobj->last_contour = contour->previous;
}

static void
add_exterior_with_check(GLUtriangulatorObj * tobj,
tess_contour * outer, tess_contour * contour)
{
GLenum test;

/* this contour might be interior to further exteriors - check */
/* if not, just add as a new exterior */
for (; outer != NULL && outer->type == GLU_EXTERIOR; outer = outer->next) {
test = is_contour_contained_in(outer, contour);
switch (test) {
case GLU_INTERIOR:
/* now we have to check if contour is inside interiors */
/* or not */
/* any interiors? */
if (outer->next != NULL && outer->next->type == GLU_INTERIOR) {
/* for all interior, check if inside any of them */
/* if not inside any of interiors, its another */
/* interior */
/* or it may contain some interiors, then change */
/* the contained interiors to exterior ones */
add_interior_with_hierarchy_check(tobj, outer, contour);
}
else {
/* not in interior, add as new interior contour */
add_new_interior(tobj, outer, contour);
}
return;
case GLU_NO_ERROR:
/* disjoint */
break;
default:
abort();
}
}
/* add contour to the exterior sequence */
add_new_exterior(tobj, contour);
}

void
tess_handle_holes(GLUtriangulatorObj * tobj)
{
tess_contour *contour, *hole;
GLenum exterior_orientation;

/* verify hole orientation */
for (contour = tobj->contours; contour != NULL;) {
exterior_orientation = contour->orientation;
for (contour = contour->next;
contour != NULL && contour->type == GLU_INTERIOR;
contour = contour->next) {
if (contour->orientation == exterior_orientation) {
tess_call_user_error(tobj, GLU_TESS_ERROR5);
return;
}
}
}
/* now cut-out holes */
for (contour = tobj->contours; contour != NULL;) {
hole = contour->next;
while (hole != NULL && hole->type == GLU_INTERIOR) {
if (cut_out_hole(tobj, contour, hole) == GLU_ERROR)
return;
hole = contour->next;
}
contour = contour->next;
}
}

static GLenum
cut_out_hole(GLUtriangulatorObj * tobj,
tess_contour * contour, tess_contour * hole)
{
tess_contour *tmp_hole;
tess_vertex *v1, *v2, *tmp_vertex;
GLuint vertex1_cnt, vertex2_cnt, tmp_vertex_cnt;
GLuint i, j, k;
GLenum test;

/* find an edge connecting contour and hole not intersecting any other */
/* edge belonging to either the contour or any of the other holes */
for (v1 = contour->vertices, vertex1_cnt = contour->vertex_cnt, i = 0;
i < vertex1_cnt; i++, v1 = v1->next) {
for (v2 = hole->vertices, vertex2_cnt = hole->vertex_cnt, j = 0;
j < vertex2_cnt; j++, v2 = v2->next) {
/* does edge (v1,v2) intersect any edge of contour */
for (tmp_vertex = contour->vertices, tmp_vertex_cnt =
contour->vertex_cnt, k = 0; k < tmp_vertex_cnt;
tmp_vertex = tmp_vertex->next, k++) {
/* skip edge tests for edges directly connected */
if (v1 == tmp_vertex || v1 == tmp_vertex->next)
continue;
test = edge_edge_intersect(v1, v2, tmp_vertex, tmp_vertex->next);
if (test != GLU_NO_ERROR)
break;
}
if (test == GLU_NO_ERROR) {
/* does edge (v1,v2) intersect any edge of hole */
for (tmp_vertex = hole->vertices,
tmp_vertex_cnt = hole->vertex_cnt, k = 0;
k < tmp_vertex_cnt; tmp_vertex = tmp_vertex->next, k++) {
/* skip edge tests for edges directly connected */
if (v2 == tmp_vertex || v2 == tmp_vertex->next)
continue;
test =
edge_edge_intersect(v1, v2, tmp_vertex, tmp_vertex->next);
if (test != GLU_NO_ERROR)
break;
}
if (test == GLU_NO_ERROR) {
/* does edge (v1,v2) intersect any other hole? */
for (tmp_hole = hole->next;
tmp_hole != NULL && tmp_hole->type == GLU_INTERIOR;
tmp_hole = tmp_hole->next) {
/* does edge (v1,v2) intersect any edge of hole */
for (tmp_vertex = tmp_hole->vertices,
tmp_vertex_cnt = tmp_hole->vertex_cnt, k = 0;
k < tmp_vertex_cnt; tmp_vertex = tmp_vertex->next, k++) {
test = edge_edge_intersect(v1, v2, tmp_vertex,
tmp_vertex->next);
if (test != GLU_NO_ERROR)
break;
}
if (test != GLU_NO_ERROR)
break;
}
}
}
if (test == GLU_NO_ERROR) {
/* edge (v1,v2) is good for eliminating the hole */
if (merge_hole_with_contour(tobj, contour, hole, v1, v2)
== GLU_NO_ERROR)
return GLU_NO_ERROR;
else
return GLU_ERROR;
}
}
}
/* other holes are blocking all possible connections of hole */
/* with contour, we shift this hole as the last hole and retry */
for (tmp_hole = hole;
tmp_hole != NULL && tmp_hole->type == GLU_INTERIOR;
tmp_hole = tmp_hole->next);
contour->next = hole->next;
hole->next->previous = contour;
if (tmp_hole == NULL) {
/* last EXTERIOR contour, shift hole as last contour */
hole->next = NULL;
hole->previous = tobj->last_contour;
tobj->last_contour->next = hole;
tobj->last_contour = hole;
}
else {
tmp_hole->previous->next = hole;
hole->previous = tmp_hole->previous;
tmp_hole->previous = hole;
hole->next = tmp_hole;
}
hole = contour->next;
/* try once again - recurse */
return cut_out_hole(tobj, contour, hole);
}

static GLenum
merge_hole_with_contour(GLUtriangulatorObj * tobj,
tess_contour * contour,
tess_contour * hole,
tess_vertex * v1, tess_vertex * v2)
{
tess_vertex *v1_new, *v2_new;

/* make copies of v1 and v2, place them respectively after their originals */
if ((v1_new = (tess_vertex *) malloc(sizeof(tess_vertex))) == NULL) {
tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
return GLU_ERROR;
}
if ((v2_new = (tess_vertex *) malloc(sizeof(tess_vertex))) == NULL) {
tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
return GLU_ERROR;
}
v1_new->edge_flag = GL_TRUE;
v1_new->data = v1->data;
v1_new->location[0] = v1->location[0];
v1_new->location[1] = v1->location[1];
v1_new->location[2] = v1->location[2];
v1_new->x = v1->x;
v1_new->y = v1->y;
v1_new->shadow_vertex = v1;
v1->shadow_vertex = v1_new;
v1_new->next = v1->next;
v1_new->previous = v1;
v1->next->previous = v1_new;
v1->next = v1_new;
v2_new->edge_flag = GL_TRUE;
v2_new->data = v2->data;
v2_new->location[0] = v2->location[0];
v2_new->location[1] = v2->location[1];
v2_new->location[2] = v2->location[2];
v2_new->x = v2->x;
v2_new->y = v2->y;
v2_new->shadow_vertex = v2;
v2->shadow_vertex = v2_new;
v2_new->next = v2->next;
v2_new->previous = v2;
v2->next->previous = v2_new;
v2->next = v2_new;
/* link together the two lists */
v1->next = v2_new;
v2_new->previous = v1;
v2->next = v1_new;
v1_new->previous = v2;
/* update the vertex count of the contour */
contour->vertex_cnt += hole->vertex_cnt + 2;
/* remove the INTERIOR contour */
contour->next = hole->next;
if (hole->next != NULL)
hole->next->previous = contour;
free(hole);
/* update tobj structure */
--(tobj->contour_cnt);
if (contour->last_vertex == v1)
contour->last_vertex = v1_new;
/* mark two vertices with edge_flag */
v2->edge_flag = GL_FALSE;
v1->edge_flag = GL_FALSE;
return GLU_NO_ERROR;
}

+ 288
- 237
src/glu/mesa/project.c Zobrazit soubor

@@ -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

+ 378
- 338
src/glu/mesa/quadric.c
Diff nebyl zobrazen, protože je příliš veliký
Zobrazit soubor


+ 257
- 978
src/glu/mesa/tess.c
Diff nebyl zobrazen, protože je příliš veliký
Zobrazit soubor


+ 83
- 106
src/glu/mesa/tess.h Zobrazit soubor

@@ -1,131 +1,108 @@
/* $Id: tess.h,v 1.16 1999/12/06 09:39:34 gareth Exp $ */
/* $Id: tess.h,v 1.17 2000/07/11 14:11:04 brianp Exp $ */

/*
* Mesa 3-D graphics library
* Version: 3.1
* Version: 3.3
* Copyright (C) 1995-2000 Brian Paul
*
* Copyright (C) 1999 Brian Paul All Rights Reserved.
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/*****************************************************************************
*
* GLU 1.3 Polygon Tessellation by Gareth Hughes <garethh@bell-labs.com>
*
*****************************************************************************/

#ifndef __GLU_TESS_H__
#define __GLU_TESS_H__
/*
* This file is part of the polygon tesselation code contributed by
* Bogdan Sikorski
*/

#include <stdarg.h>
#include <stdio.h>

#include "gluP.h"
#ifndef TESS_H
#define TESS_H

#include "tess_typedefs.h"
#include "tess_macros.h"
#include "tess_hash.h"
#include "tess_heap.h"
#if 0
#include "tess_grid.h"
#endif

#ifdef __cplusplus
extern "C" {
#endif
#include "gluP.h"

#define EPSILON 1e-06 /* epsilon for double precision compares */

/*****************************************************************************
* The GLUtesselator structure:
*****************************************************************************/
struct GLUtesselator
typedef enum
{
tess_callbacks_t callbacks;
GLenum winding_rule;
GLboolean boundary_only;
GLdouble tolerance;
GLenum orientation;
void *data;
GLint num_contours;
tess_contour_t *contours, *last_contour;
tess_contour_t *current_contour;
GLdouble mins[2], maxs[2];
GLint num_vertices;
tess_vertex_t **sorted_vertices;
#if 0
tess_grid_t *grid; /* Not currently used... */
#endif
heap_t *ears;
GLboolean edge_flag;
GLuint label;
tess_plane_t plane;
GLenum error;
};
OXY,
OYZ,
OXZ
}
projection_type;

typedef struct callbacks_str
{
void (GLCALLBACK * begin) (GLenum mode);
void (GLCALLBACK * edgeFlag) (GLboolean flag);
void (GLCALLBACK * vertex) (GLvoid * v);
void (GLCALLBACK * end) (void);
void (GLCALLBACK * error) (GLenum err);
}
tess_callbacks;

/*****************************************************************************
* Common tessellation functions:
*****************************************************************************/
extern void tess_error_callback( GLUtesselator *, GLenum );
typedef struct vertex_str
{
void *data;
GLdouble location[3];
GLdouble x, y;
GLboolean edge_flag;
struct vertex_str *shadow_vertex;
struct vertex_str *next, *previous;
}
tess_vertex;

extern GLdouble twice_contour_area( tess_contour_t *contour );
extern void reverse_contour( tess_contour_t *contour );
extern void delete_contour( tess_contour_t **contour );
typedef struct contour_str
{
GLenum type;
GLuint vertex_cnt;
GLdouble area;
GLenum orientation;
struct vertex_str *vertices, *last_vertex;
struct contour_str *next, *previous;
}
tess_contour;

extern void contour_dump( tess_contour_t *contour );
typedef struct polygon_str
{
GLuint vertex_cnt;
GLdouble A, B, C, D;
GLdouble area;
GLenum orientation;
struct vertex_str *vertices, *last_vertex;
}
tess_polygon;

struct GLUtriangulatorObj
{
tess_contour *contours, *last_contour;
GLuint contour_cnt;
tess_callbacks callbacks;
tess_polygon *current_polygon;
GLenum error;
GLdouble A, B, C, D;
projection_type projection;
};

/*****************************************************************************
* Debugging output:
*****************************************************************************/
#ifdef DEBUG
extern int tess_dbg_level;

#define DBG_LEVEL_BASE 1
#define DBG_LEVEL_VERBOSE 10
#define DBG_LEVEL_ENTEREXIT 20
extern void tess_call_user_error(GLUtriangulatorObj *, GLenum);
extern void tess_test_polygon(GLUtriangulatorObj *);
extern void tess_find_contour_hierarchies(GLUtriangulatorObj *);
extern void tess_handle_holes(GLUtriangulatorObj *);
extern void tess_tesselate(GLUtriangulatorObj *);
extern void tess_tesselate_with_edge_flag(GLUtriangulatorObj *);

#ifdef _WIN32
#define DBG_STREAM stdout
#else
#define DBG_STREAM stderr
#endif

#ifdef __GNUC__
#define MSG( level, format, args... ) \
if ( level <= tess_dbg_level ) { \
fprintf( DBG_STREAM, "%9.9s:%d:\t ", __FILE__, __LINE__ ); \
fprintf( DBG_STREAM, format, ## args ); \
fflush( DBG_STREAM ); \
}
#else
#define MSG tess_msg
#endif /* __GNUC__ */

#else
#define MSG tess_msg
#endif /* DEBUG */

extern INLINE void tess_msg( GLint level, char *format, ... );
extern INLINE void tess_info( char *file, GLint line );

#ifdef __cplusplus
}
#endif

#endif /* __GLU_TESS_H__ */

+ 407
- 0
src/glu/mesa/tesselat.c Zobrazit soubor

@@ -0,0 +1,407 @@
/* $Id: tesselat.c,v 1.3 2000/07/11 14:11:04 brianp Exp $ */

/*
* Mesa 3-D graphics library
* Version: 3.3
* Copyright (C) 1995-2000 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/


/*
* This file is part of the polygon tesselation code contributed by
* Bogdan Sikorski
*/


#ifdef PC_HEADER
#include "all.h"
#else
#include <stdlib.h>
#include <math.h>
#include "tess.h"
#endif



static GLboolean edge_flag;

static void emit_triangle(GLUtriangulatorObj *, tess_vertex *,
tess_vertex *, tess_vertex *);

static void emit_triangle_with_edge_flag(GLUtriangulatorObj *,
tess_vertex *, GLboolean,
tess_vertex *, GLboolean,
tess_vertex *, GLboolean);

static GLdouble
twice_the_triangle_area(tess_vertex * va, tess_vertex * vb, tess_vertex * vc)
{
return (vb->x - va->x) * (vc->y - va->y) - (vb->y - va->y) * (vc->x -
va->x);
}

static GLboolean
left(GLdouble A, GLdouble B, GLdouble C, GLdouble x, GLdouble y)
{
if (A * x + B * y + C > -EPSILON)
return GL_TRUE;
else
return GL_FALSE;
}

static GLboolean
right(GLdouble A, GLdouble B, GLdouble C, GLdouble x, GLdouble y)
{
if (A * x + B * y + C < EPSILON)
return GL_TRUE;
else
return GL_FALSE;
}

static GLint
convex_ccw(tess_vertex * va,
tess_vertex * vb, tess_vertex * vc, GLUtriangulatorObj * tobj)
{
GLdouble d;

d = twice_the_triangle_area(va, vb, vc);

if (d > EPSILON) {
return 1;
}
else if (d < -EPSILON) {
return 0;
}
else {
return -1;
}
}

static GLint
convex_cw(tess_vertex * va,
tess_vertex * vb, tess_vertex * vc, GLUtriangulatorObj * tobj)
{
GLdouble d;

d = twice_the_triangle_area(va, vb, vc);

if (d < -EPSILON) {
return 1;
}
else if (d > EPSILON) {
return 0;
}
else {
return -1;
}
}

static GLboolean
diagonal_ccw(tess_vertex * va,
tess_vertex * vb,
GLUtriangulatorObj * tobj, tess_contour * contour)
{
tess_vertex *vc = va->next, *vertex, *shadow_vertex;
struct
{
GLdouble A, B, C;
}
ac, cb, ba;
GLdouble x, y;

GLint res = convex_ccw(va, vc, vb, tobj);
if (res == 0)
return GL_FALSE;
if (res == -1)
return GL_TRUE;

ba.A = vb->y - va->y;
ba.B = va->x - vb->x;
ba.C = -ba.A * va->x - ba.B * va->y;
ac.A = va->y - vc->y;
ac.B = vc->x - va->x;
ac.C = -ac.A * vc->x - ac.B * vc->y;
cb.A = vc->y - vb->y;
cb.B = vb->x - vc->x;
cb.C = -cb.A * vb->x - cb.B * vb->y;
for (vertex = vb->next; vertex != va; vertex = vertex->next) {
shadow_vertex = vertex->shadow_vertex;
if (shadow_vertex != NULL &&
(shadow_vertex == va || shadow_vertex == vb || shadow_vertex == vc))
continue;
x = vertex->x;
y = vertex->y;
if (left(ba.A, ba.B, ba.C, x, y) &&
left(ac.A, ac.B, ac.C, x, y) && left(cb.A, cb.B, cb.C, x, y))
return GL_FALSE;
}
return GL_TRUE;
}

static GLboolean
diagonal_cw(tess_vertex * va,
tess_vertex * vb,
GLUtriangulatorObj * tobj, tess_contour * contour)
{
tess_vertex *vc = va->next, *vertex, *shadow_vertex;
struct
{
GLdouble A, B, C;
}
ac, cb, ba;
GLdouble x, y;

GLint res = convex_cw(va, vc, vb, tobj);
if (res == 0)
return GL_FALSE;
if (res == -1)
return GL_TRUE;

ba.A = vb->y - va->y;
ba.B = va->x - vb->x;
ba.C = -ba.A * va->x - ba.B * va->y;
ac.A = va->y - vc->y;
ac.B = vc->x - va->x;
ac.C = -ac.A * vc->x - ac.B * vc->y;
cb.A = vc->y - vb->y;
cb.B = vb->x - vc->x;
cb.C = -cb.A * vb->x - cb.B * vb->y;
for (vertex = vb->next; vertex != va; vertex = vertex->next) {
shadow_vertex = vertex->shadow_vertex;
if (shadow_vertex != NULL &&
(shadow_vertex == va || shadow_vertex == vb || shadow_vertex == vc))
continue;
x = vertex->x;
y = vertex->y;
if (right(ba.A, ba.B, ba.C, x, y) &&
right(ac.A, ac.B, ac.C, x, y) && right(cb.A, cb.B, cb.C, x, y))
return GL_FALSE;
}
return GL_TRUE;
}

static void
clip_ear(GLUtriangulatorObj * tobj, tess_vertex * v, tess_contour * contour)
{
emit_triangle(tobj, v->previous, v, v->next);
/* the first in the list */
if (contour->vertices == v) {
contour->vertices = v->next;
contour->last_vertex->next = v->next;
v->next->previous = contour->last_vertex;
}
else
/* the last ? */
if (contour->last_vertex == v) {
contour->vertices->previous = v->previous;
v->previous->next = v->next;
contour->last_vertex = v->previous;
}
else {
v->next->previous = v->previous;
v->previous->next = v->next;
}
free(v);
--(contour->vertex_cnt);
}

static void
clip_ear_with_edge_flag(GLUtriangulatorObj * tobj,
tess_vertex * v, tess_contour * contour)
{
emit_triangle_with_edge_flag(tobj, v->previous, v->previous->edge_flag,
v, v->edge_flag, v->next, GL_FALSE);
v->previous->edge_flag = GL_FALSE;
/* the first in the list */
if (contour->vertices == v) {
contour->vertices = v->next;
contour->last_vertex->next = v->next;
v->next->previous = contour->last_vertex;
}
else
/* the last ? */
if (contour->last_vertex == v) {
contour->vertices->previous = v->previous;
v->previous->next = v->next;
contour->last_vertex = v->previous;
}
else {
v->next->previous = v->previous;
v->previous->next = v->next;
}
free(v);
--(contour->vertex_cnt);
}

static void
triangulate_ccw(GLUtriangulatorObj * tobj, tess_contour * contour)
{
tess_vertex *vertex;
GLuint vertex_cnt = contour->vertex_cnt;

while (vertex_cnt > 3) {
vertex = contour->vertices;
while (diagonal_ccw(vertex, vertex->next->next, tobj, contour) ==
GL_FALSE && tobj->error == GLU_NO_ERROR)
vertex = vertex->next;
if (tobj->error != GLU_NO_ERROR)
return;
clip_ear(tobj, vertex->next, contour);
--vertex_cnt;
}
}

static void
triangulate_cw(GLUtriangulatorObj * tobj, tess_contour * contour)
{
tess_vertex *vertex;
GLuint vertex_cnt = contour->vertex_cnt;

while (vertex_cnt > 3) {
vertex = contour->vertices;
while (diagonal_cw(vertex, vertex->next->next, tobj, contour) ==
GL_FALSE && tobj->error == GLU_NO_ERROR)
vertex = vertex->next;
if (tobj->error != GLU_NO_ERROR)
return;
clip_ear(tobj, vertex->next, contour);
--vertex_cnt;
}
}

static void
triangulate_ccw_with_edge_flag(GLUtriangulatorObj * tobj,
tess_contour * contour)
{
tess_vertex *vertex;
GLuint vertex_cnt = contour->vertex_cnt;

while (vertex_cnt > 3) {
vertex = contour->vertices;
while (diagonal_ccw(vertex, vertex->next->next, tobj, contour) ==
GL_FALSE && tobj->error == GLU_NO_ERROR)
vertex = vertex->next;
if (tobj->error != GLU_NO_ERROR)
return;
clip_ear_with_edge_flag(tobj, vertex->next, contour);
--vertex_cnt;
}
}

static void
triangulate_cw_with_edge_flag(GLUtriangulatorObj * tobj,
tess_contour * contour)
{
tess_vertex *vertex;
GLuint vertex_cnt = contour->vertex_cnt;

while (vertex_cnt > 3) {
vertex = contour->vertices;
while (diagonal_cw(vertex, vertex->next->next, tobj, contour) ==
GL_FALSE && tobj->error == GLU_NO_ERROR)
vertex = vertex->next;
if (tobj->error != GLU_NO_ERROR)
return;
clip_ear_with_edge_flag(tobj, vertex->next, contour);
--vertex_cnt;
}
}

void
tess_tesselate(GLUtriangulatorObj * tobj)
{
tess_contour *contour;

for (contour = tobj->contours; contour != NULL; contour = contour->next) {
if (contour->orientation == GLU_CCW) {
triangulate_ccw(tobj, contour);
}
else {
triangulate_cw(tobj, contour);
}
if (tobj->error != GLU_NO_ERROR)
return;

/* emit the last triangle */
emit_triangle(tobj, contour->vertices, contour->vertices->next,
contour->vertices->next->next);
}
}

void
tess_tesselate_with_edge_flag(GLUtriangulatorObj * tobj)
{
tess_contour *contour;

edge_flag = GL_TRUE;
/* first callback with edgeFlag set to GL_TRUE */
(tobj->callbacks.edgeFlag) (GL_TRUE);

for (contour = tobj->contours; contour != NULL; contour = contour->next) {
if (contour->orientation == GLU_CCW)
triangulate_ccw_with_edge_flag(tobj, contour);
else
triangulate_cw_with_edge_flag(tobj, contour);
if (tobj->error != GLU_NO_ERROR)
return;
/* emit the last triangle */
emit_triangle_with_edge_flag(tobj, contour->vertices,
contour->vertices->edge_flag,
contour->vertices->next,
contour->vertices->next->edge_flag,
contour->vertices->next->next,
contour->vertices->next->next->edge_flag);
}
}

static void
emit_triangle(GLUtriangulatorObj * tobj,
tess_vertex * v1, tess_vertex * v2, tess_vertex * v3)
{
(tobj->callbacks.begin) (GL_TRIANGLES);
(tobj->callbacks.vertex) (v1->data);
(tobj->callbacks.vertex) (v2->data);
(tobj->callbacks.vertex) (v3->data);
(tobj->callbacks.end) ();
}

static void
emit_triangle_with_edge_flag(GLUtriangulatorObj * tobj,
tess_vertex * v1,
GLboolean edge_flag1,
tess_vertex * v2,
GLboolean edge_flag2,
tess_vertex * v3, GLboolean edge_flag3)
{
(tobj->callbacks.begin) (GL_TRIANGLES);
if (edge_flag1 != edge_flag) {
edge_flag = (edge_flag == GL_TRUE ? GL_FALSE : GL_TRUE);
(tobj->callbacks.edgeFlag) (edge_flag);
}
(tobj->callbacks.vertex) (v1->data);
if (edge_flag2 != edge_flag) {
edge_flag = (edge_flag == GL_TRUE ? GL_FALSE : GL_TRUE);
(tobj->callbacks.edgeFlag) (edge_flag);
}
(tobj->callbacks.vertex) (v2->data);
if (edge_flag3 != edge_flag) {
edge_flag = (edge_flag == GL_TRUE ? GL_FALSE : GL_TRUE);
(tobj->callbacks.edgeFlag) (edge_flag);
}
(tobj->callbacks.vertex) (v3->data);
(tobj->callbacks.end) ();
}

Načítá se…
Zrušit
Uložit