Remove unused mini and mesa glu subdirectories

This commit is contained in:
Kristian Høgsberg 2010-02-25 16:20:03 -05:00
parent b15fe60ba5
commit 44f78eb18e
34 changed files with 0 additions and 13732 deletions

View file

@ -1,56 +0,0 @@
# src/glu/mesa/Makefile
TOP = ../../..
include $(TOP)/configs/current
GLU_MAJOR = 1
GLU_MINOR = 1
GLU_TINY = 0$(MESA_MAJOR)0$(MESA_MINOR)0$(MESA_TINY)
C_SOURCES = \
glu.c \
mipmap.c \
nurbs.c \
nurbscrv.c \
nurbssrf.c \
nurbsutl.c \
polytest.c \
project.c \
quadric.c \
tess.c \
tesselat.c
OBJECTS = $(C_SOURCES:.c=.o)
INCLUDES = -I. -I$(TOP)/include
##### RULES #####
.c.o:
$(CC) -c $(INCLUDES) $(CFLAGS) $< -o $@
##### TARGETS #####
default:
@if [ "${CONFIG_NAME}" = "beos" ] ; then \
echo "$(GLU_LIB_NAME) not build under BeOS, but integrated into ${GL_LIB_NAME}." ; \
exit 0 ; \
else \
$(MAKE) $(TOP)/$(LIB_DIR)/$(GLU_LIB_NAME) || exit 1 ; \
fi
$(TOP)/$(LIB_DIR):
-mkdir $(TOP)/$(LIB_DIR)
# Make the library:
$(TOP)/$(LIB_DIR)/$(GLU_LIB_NAME): $(OBJECTS)
@ $(MKLIB) -o $(GLU_LIB) -linker '$(CC)' -ldflags '$(LDFLAGS)' \
-major $(GLU_MAJOR) -minor $(GLU_MINOR) -patch $(GLU_TINY) \
$(MKLIB_OPTIONS) -install $(TOP)/$(LIB_DIR) \
$(GLU_LIB_DEPS) $(OBJECTS)
clean:
-rm -f *.o */*.o */*/*.o
-rm -f *.lo */*.lo */*/*.lo
-rm -f *.la */*.la */*/*.la

View file

@ -1,63 +0,0 @@
# Makefile for GLU for GCC-2.95.2/Mingw32 contributed by
# Paul Garceau <pgarceau@teleport.com>
# Mesa 3-D graphics library
# Version: 3.3
# Copyright (C) 1995-1999 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.
MESA_MAJOR=3
MESA_MINOR=3
MESA_TINY=0
VERSION=$(MESA_MAJOR).$(MESA_MINOR)
CFLAGS = -I. -DWIN32 -D__WIN32__ -D_WINDOWS \
-O2 -funroll-loops \
-fexpensive-optimizations -fomit-frame-pointer -ffast-math \
-malign-loops=2 -malign-jumps=2 -malign-functions=2 \
-mwindows
CC = gcc
MAKELIB = ar ru
GLU_LIB = libGLU.a
##### MACROS #####
VPATH = RCS
INCDIR = ../include
LIBDIR = ../lib
SOURCES = glu.c mipmap.c nurbs.c nurbscrv.c nurbssrf.c nurbsutl.c \
polytest.c project.c quadric.c tess.c tesselat.c
OBJECTS = $(SOURCES:.c=.o)
##### RULES #####
.c.o:
$(CC) -c -I$(INCDIR) $(CFLAGS) $<
##### TARGETS #####
# Make the library:
$(LIBDIR)/$(GLU_LIB): $(OBJECTS)
$(MAKELIB) $(GLU_LIB) $(MAJOR) $(MINOR) $(TINY) $(OBJECTS)

View file

@ -1,96 +0,0 @@
# Mesa 3-D graphics library
# Version: 3.5
#
# Copyright (C) 2001 Wind River Systems, Inc
# The MIT License
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS 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.
# Makefile for GLU library
##### MACROS #####
GLU_MAJOR = 1
GLU_MINOR = 3
GLU_TINY = 0$(MESA_MAJOR)0$(MESA_MINOR)0$(MESA_TINY)
##### RULES #####
include ../rules.windml
GLU_SOURCES = \
glu.c \
mipmap.c \
nurbs.c \
nurbscrv.c \
nurbssrf.c \
nurbsutl.c \
polytest.c \
project.c \
quadric.c \
tess.c \
tesselat.c \
../src/windml/tornado/torMesaGLUInit.c
GLU_OBJECTS = $(GLU_SOURCES:.c=.o)
GLU_OBJNAME = $(MESA_LIBDIR)/objMesaGLU.o
SOURCES = $(GLU_SOURCES)
##### TARGETS #####
all: depend.$(CPU)$(TOOL) $(GLU_OBJNAME)
# Make the GLU library
$(GLU_OBJNAME): $(GLU_OBJECTS)
# $(LD) -r $(GLU_OBJECTS) -o $(MESA_OBJNAME)
$(LD) -r $(GLU_OBJECTS) -o $(GLU_OBJNAME)
# $(AR) rus $(MESA_LIBNAME) $(GLU_OBJNAME)
# $(AR) rus $(VX_LIBNAME) $(GLU_OBJNAME)
depend.$(CPU)$(TOOL):
ifeq ($(WIND_HOST_TYPE),x86-win32)
@ $(RM) $@
@ $(ECHO) Creating depend.$(CPU)$(TOOL)
ifneq ($(SOURCES),)
@ for %f in ($(SOURCES)) do \
$(CC) -MM $(CFLAGS) %f >>$@
endif
else
Makefile
@ $(RM) $@
@ $(ECHO) "Creating depend.$(CPU)$(TOOL)"
ifneq ($(SOURCES),)
@ for FILE in $(filter-out $(NODEPENDOBJS), $(SOURCES)); \
do \
$(CC) -MM $(CFLAGS) $$FILE \
| $(TCL) $(BIN_DIR)/depend.tcl $(TGT_DIR) >>$@; \
done
endif
endif
.PHONY = clean
clean:
# $(AR) d $(MESA_LIBNAME) $(GLU_OBJNAME)
# $(AR) d $(VX_LIBNAME) $(GLU_OBJNAME)
$(RM) $(GLU_OBJNAME)
$(RM) $(GLU_OBJECTS)
$(RM) depend.$(CPU)$(TOOL)
include depend.$(CPU)$(TOOL)

View file

@ -1,62 +0,0 @@
LIBRARY GLU32
DESCRIPTION 'GLU for Windows Mesa'
EXETYPE WINDOWS
CODE MOVEABLE DISCARDABLE
DATA MOVEABLE SINGLE
HEAPSIZE 256000
STACKSIZE 4096
EXPORTS
gluLookAt
gluOrtho2D
gluPerspective
gluPickMatrix
gluProject
gluUnProject
gluErrorString
gluScaleImage
gluBuild1DMipmaps
gluBuild2DMipmaps
gluNewQuadric
gluDeleteQuadric
gluQuadricDrawStyle
gluQuadricOrientation
gluQuadricNormals
gluQuadricTexture
gluQuadricCallback
gluCylinder
gluSphere
gluDisk
gluPartialDisk
gluNewNurbsRenderer
gluDeleteNurbsRenderer
gluLoadSamplingMatrices
gluNurbsProperty
gluGetNurbsProperty
gluBeginCurve
gluEndCurve
gluNurbsCurve
gluBeginSurface
gluEndSurface
gluNurbsSurface
gluBeginTrim
gluEndTrim
gluPwlCurve
gluNurbsCallback
gluNewTess
gluDeleteTess
; gluTessBeginPolygon
; gluTessBeginContour
gluTessVertex
; gluTessEndContour
; gluTessEndPolygon
; gluTessProperty
; gluTessNormal
gluTessCallback
; gluGetTessProperty
gluBeginPolygon
gluNextContour
gluEndPolygon
gluGetString

View file

@ -1,195 +0,0 @@
Notes on the GLU polygon tesselation facility implemented by Bogdan Sikorski...
The tesselation module is provided under the same terms as the Mesa
package.
This is the first release of polygon tesselation code for Mesa.
It was written during my very little free time, so lets name it:
"its not perfect". If someone hates pointers, don't look at the code.
I preffer dynamic allocation versus static. But _all_ ideas, suggestions,
bug reports and fixes are welcome (if You want, also flames). I am aware
that many things could have been written using better techniques, but time
that I could devote to this library was very limited. It is not well commented,
excuse me. Also I am thinking of continuing working on this code to improve,
fix and polish it. And make it as compliant as possible to the OpenGL, so
software ports from OpenGL to Mesa will work correctly. If You know of any
differences in behaviour, expected input/output between Mesa tesselation library
and OpenGL, please send me a note. I explain later on why I am not
confident with this code.
I tried to be fully compliant with the OpenGL routines. By "tried" I mean that
up to my knowledge it behaves as OpenGL tesselation routines. Just recently
I began to experiment with OpenGL (actually only Mesa), and also have
no access to any machine providing official implementation of OpenGL,
nor access to books (particulary Addison-Wesley publications). Thus my
knowledge on how the original tesselation code works, what kind of data
it expects etc. is based _only_ on the publicly available documentation
provided by SGI. Namely:
* "The OpenGL Graphics System Utility Library" by K.P.Smith
(Silicon Graphics, 1992)
* "The OpenGL Graphics Interface" by M.Segal and K.Akeley
(Silicon Graphics, 19??)
* "OpenGL and X, Part 1: Introduction" by M.J.Kilgard
(Silicon Graphics, 1994)
* "OpenGL and X, Part 2: Using OpenGL with Xlib" by M.J.Kilgard
(Silicon Graphics, 1994)
* "OpenGL Graphics with the X Window System" by P.Karlton
(Silicon Graphics, 1993)
* Online Docs - Appendix C of OpenGL Programming Guide, Polygon Tesselation
(partial text cut and sent by e-mail)
The tesselation routines use slightly different prototypes than the ones
specified in the mentioned above publications. The _only_ differences are
the enumeration types which are not GLenum, but are GLUenum. So the
implemented routines have following prototypes:
GLUtringulatorObj *gluNewTess(void);
void gluTessCallback(GLUtriangulatorObj *,GLUenum,void (*)());
^^^^^^^
void gluBeginPolygon(GLUtriangulatorObj *);
void gluTessVertex(GLUtriangulatorObj *,GLdouble [3],void *);
void gluNextContour(GLUtriangulatorObj *,GLUenum);
^^^^^^^
void gluEndPolygon(GLUtriangulatorObj *);
const GLubyte *gluErrorString(GLUenum);
^^^^^^^
prototypes for callback functions:
void <begin>(GLUenum);
^^^^^^^
void <edgeFlag>(GLboolean);
void <vertex>(void *);
void <end>(void);
void <error>(GLUenum);
^^^^^^^
The begin callback will be called only with GLU_TRIANGLES. No support
for traingle fans or strips yet.
In case of errors an internal error variable is set to the appropiate
error enum values (GLU_TESS_ERROR?). Initially it is set to GLU_NO_ERROR.
The OpenGL library provides 8 error conditions, the tesselation code
of Mesa provides 9. They are:
GLU_TESS_ERROR1: missing gluEndPolygon /* same as OpenGL */
GLU_TESS_ERROR2: missing gluBeginPolygon /* same as OpenGL */
GLU_TESS_ERROR3: misoriented contour /* not used in Mesa
in OpenGL is bad orientation or intersecting edges */
GLU_TESS_ERROR4: vertex/edge intersection /* same as OpenGL */
GLU_TESS_ERROR5: misoriented or self-intersecting loops /* same as OpenGL */
GLU_TESS_ERROR6: coincident vertices /* same as OpenGL */
GLU_TESS_ERROR7: colinear vertices /* OpenGL's illegal data */
GLU_TESS_ERROR8: intersecting edges /* same as OpenGL */
GLU_TESS_ERROR9: not coplanar contours /* new for Mesa */
The Mesa tesselation code ignores all data and calls after detecting an error
codition. This means that a _new_ tesselation object must be used for further
triangulations. Maybe this is too restrictive, and will be lifted in
future versions.
The tesselation code completely ignores the type parameter passed in
gluNextContour. It also doesn't check if the passed parameter is a legal
enum value - ignores silently (maybe at least this should be checked).
The reason I chose this behaviour is based on what I read in the
beforementioned documents. I cite:
"....
void gluNextContour(GLUtriangulatorObj *tessobj, GLenum type);
Marks the beginning of the next contour when multiple contours make up the
boundary of the polygon to be tessellated. type can be GLU_EXTERIOR,
GLU_INTERIOR, GLU_CCW, GLU_CW, or GLU_UNKNOWN. These serve only as
to the tessellation. If you get them right, the tessellation might
go faster. If you get them wrong, they're ignored, and the tesselation still
works.
....."
I hope You agree with me that my decision was correct. Mesa tesselation
_always_ checks by itself the interrelations between contours. Just as if
all contours were specified with the type GLU_UNKNOWN.
One of OpenGL's policy is not to check all error conditions - rely sometimes
that the user "got things right". This is justified, since exhausting
error checking is timeconsuming, and would significantly slow down
a correct application. The Mesa tesselation code assumes only _one_ condition
when triangulating - all vertices in a contour are planar. This is _not_
checked for correctness. Trying to tesselate such objects will lead to
unpredictable output.
And now we arrive to the moment where I would like to list the required
(but checked for) conditions for triangulation, as well as summarize the
library:
* all contours in a single tesselation cycle _must_ be coplanar - if not
an error is raised (and if provided a call to the error callback
is made)
* the contours can be passed in _any_ order, exteriors and holes can be
intermixed within a tesselation cycle and the correct hierarchy
will be determined by the library; thus specifying first holes then
exteriors, then holes within holes form a valid input.
* a hole within a hole is consider to be a yet another exterior contour
* multiple exterior contours (polygons) can be tesselated in one cycle;
_but_ this significantly degrades performance since many tests will be
performed for every contour pair; if You want triangulation to be fast
tesselate a single polygon (with possible holes) one at a time.
* orientation of exterior contours is arbitray, but if it has holes,
all interior holes of this particular exterior contour _must_ have an
opposite orientation.
* the output triangles have the same orientation as the exterior contour
that forms them
* each triangle is "enclosed" within the begin and end callbacks;
this is not efficent, but was made on purpose; so if triangulation
results in 2 triangles the following callbacks will be made in such
order:
<begin>(GLU_TRAINGLES)
<vertex>(...) /* 3 vertices of first triangle */
<vertex>(...)
<vertex>(...)
<end>()
<begin>(GLU_TRAINGLES)
<vertex>(...) /* 3 vertices of second triangle */
<vertex>(...)
<vertex>(...)
<end>()
Of course only when begin, vertex, and end callback were provided,
otherwise no output is done (actually tesselation does not take place).
* You will notice that some output traingles are very "thin"; there
exist possible several ways to traingulate a polygon, but "smart" code
avoiding such cases would require time to write, and will impact on
execution speed.
* like OpenGL, no new vertices are introduced during triangulation
* if the edgeflag callback is provided it will be called whenever
the just-about-to be output vertex begins a different type of edge
than the previous vertices; always before the first output a call
is made with GL_TRUE, to allow synchronization.
* all intermediate computations are done using GLdouble type, and comparisons
are biased with a precision value (EPSILON defined in tess.h)
* the point_in_poly function is my adaptation of code from the
comp.graphics.alg newsgroup FAQ (originally written by Mr. Wm. Randolph
Franklin, modified by Scott Anguish).
* the edge_edge_intersect test is also an adopted code from comp.graphics.alg
newsgroup FAQ
* the general idea for traingulation used in this library is described in
the book "Computational Geometry in C" by Joseph O'Rourke.
Excuse my English, its not my mother tongue. I should be available for some
time uner the following e-mail address. But For how long I am not certain.
Once I am settled in my new place, I'll post on the Mesa mailing list
my new address.
(PS: today is my last day of work here, I'm changing my job).
Bogdan. ( bogdan@dia.unisa.it )
Apr 28, 1995.

View file

@ -1,43 +0,0 @@
The current NURBS implementation has no trimming facilities yet.
The code is not well commented.
1) Normal calculus fails for special cases of NURBS (independent
of the NURBS modules)
Those cases arise when for u or v, some control points
for a fixed value of that parameter form the same point.
Imagine a Bezier patch degenerated into a "triangle".
v ^ 0,1,2 order=3
| *
|
| 3* 4* 5*
|
| 6* 7* 8*
|
|
+------------------------> u
The calculus of du derivative at triple point (0,1 and 2) will fail.
As a result, the normal vector will be 0.
The eval2.c code has to be changed to handle the above situation.
2) Adjacent NURBS surfaces ("sharing" the same control points along
the "joining" edge) will be sampled with the same factor.
This prevents the formation of "cracks".
When the control polygon of the "shared" edge is not the same,
cracks might appear.
The sampling tolerance is sometimes not respected!
A NURBS object is broken into Bezier curves/surfaces. If one of such
Bezier objects has a local high curvature with other portions of it
relatively flat then the high curvature part will be sampled more dense that
its flatter regions.
The flat regions might be tesselated into quads having sides of length
greater than the current sampling tolernace setting.
I believe such behaviour is acceptable, though not along the concept of
sampling tolerance.
February 20, 1996.
Bogdan.

View file

@ -1,54 +0,0 @@
/*
* 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 includes all .h files needed for the GLU source code for
* the purpose of precompiled headers.
*
* If the preprocessor symbol PCH is defined at compile time then each
* of the .c files will #include "all.h" only, instead of a bunch of
* individual .h files.
*/
#ifndef GLU_ALL_H
#define GLU_ALL_H
#ifndef PC_HEADER
This is an error. all.h should be included only if PCH is defined.
#endif
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "GL/gl.h"
#include "GL/glu.h"
#include "gluP.h"
#include "nurbs.h"
#include "tess.h"
#endif /*GLU_ALL_H */

View file

@ -1,416 +0,0 @@
/*
* Mesa 3-D graphics library
* Version: 3.5
* Copyright (C) 1995-2001 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.
*/
#ifdef PC_HEADER
#include "all.h"
#else
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "gluP.h"
#endif
/*
* Miscellaneous utility functions
*/
#ifndef M_PI
#define M_PI 3.1415926536
#endif
#define EPS 0.00001
#ifndef GLU_INCOMPATIBLE_GL_VERSION
#define GLU_INCOMPATIBLE_GL_VERSION 100903
#endif
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];
GLdouble mag;
/* Make rotation matrix */
/* Z vector */
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 */
z[0] /= mag;
z[1] /= mag;
z[2] /= mag;
}
/* Y vector */
y[0] = upx;
y[1] = upy;
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];
/* 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];
/* 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]);
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]);
if (mag) {
y[0] /= mag;
y[1] /= mag;
y[2] /= mag;
}
#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;
#undef M
glMultMatrixd(m);
/* Translate Eye to Origin */
glTranslated(-eyex, -eyey, -eyez);
}
void GLAPIENTRY
gluOrtho2D(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top)
{
glOrtho(left, right, bottom, top, -1.0, 1.0);
}
static void
frustum(GLdouble left, GLdouble right,
GLdouble bottom, GLdouble top,
GLdouble nearval, GLdouble farval)
{
GLdouble x, y, a, b, c, d;
GLdouble m[16];
x = (2.0 * nearval) / (right - left);
y = (2.0 * nearval) / (top - bottom);
a = (right + left) / (right - left);
b = (top + bottom) / (top - bottom);
c = -(farval + nearval) / ( farval - nearval);
d = -(2.0 * farval * nearval) / (farval - nearval);
#define M(row,col) m[col*4+row]
M(0,0) = x; M(0,1) = 0.0F; M(0,2) = a; M(0,3) = 0.0F;
M(1,0) = 0.0F; M(1,1) = y; M(1,2) = b; M(1,3) = 0.0F;
M(2,0) = 0.0F; M(2,1) = 0.0F; M(2,2) = c; M(2,3) = d;
M(3,0) = 0.0F; M(3,1) = 0.0F; M(3,2) = -1.0F; M(3,3) = 0.0F;
#undef M
glMultMatrixd(m);
}
void GLAPIENTRY
gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar)
{
GLdouble xmin, xmax, ymin, ymax;
ymax = zNear * tan(fovy * M_PI / 360.0);
ymin = -ymax;
xmin = ymin * aspect;
xmax = ymax * aspect;
/* don't call glFrustum() because of error semantics (covglu) */
frustum(xmin, xmax, ymin, ymax, zNear, zFar);
}
void GLAPIENTRY
gluPickMatrix(GLdouble x, GLdouble y,
GLdouble width, GLdouble height, GLint viewport[4])
{
GLfloat m[16];
GLfloat sx, sy;
GLfloat tx, ty;
sx = viewport[2] / width;
sy = viewport[3] / height;
tx = (viewport[2] + 2.0 * (viewport[0] - x)) / width;
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;
#undef M
glMultMatrixf(m);
}
const GLubyte *GLAPIENTRY
gluErrorString(GLenum errorCode)
{
static char *tess_error[] = {
"missing gluBeginPolygon",
"missing gluBeginContour",
"missing gluEndPolygon",
"missing gluEndContour",
"misoriented or self-intersecting loops",
"coincident vertices",
"colinear vertices",
"FIST recovery process fatal error"
};
static char *nurbs_error[] = {
"spline order un-supported",
"too few knots",
"valid knot range is empty",
"decreasing knot sequence knot",
"knot multiplicity greater than order of spline",
"endcurve() must follow bgncurve()",
"bgncurve() must precede endcurve()",
"missing or extra geometric data",
"can't draw pwlcurves",
"missing bgncurve()",
"missing bgnsurface()",
"endtrim() must precede endsurface()",
"bgnsurface() must precede endsurface()",
"curve of improper type passed as trim curve",
"bgnsurface() must precede bgntrim()",
"endtrim() must follow bgntrim()",
"bgntrim() must precede endtrim()",
"invalid or missing trim curve",
"bgntrim() must precede pwlcurve()",
"pwlcurve referenced twice",
"pwlcurve and nurbscurve mixed",
"improper usage of trim data type",
"nurbscurve referenced twice",
"nurbscurve and pwlcurve mixed",
"nurbssurface referenced twice",
"invalid property",
"endsurface() must follow bgnsurface()",
"misoriented trim curves",
"intersecting trim curves",
"UNUSED",
"unconnected trim curves",
"unknown knot error",
"negative vertex count encountered",
"negative byte-stride encountered",
"unknown type descriptor",
"null control array or knot vector",
"duplicate point on pwlcurve"
};
/* GL Errors */
if (errorCode == GL_NO_ERROR) {
return (GLubyte *) "no error";
}
else if (errorCode == GL_INVALID_VALUE) {
return (GLubyte *) "invalid value";
}
else if (errorCode == GL_INVALID_ENUM) {
return (GLubyte *) "invalid enum";
}
else if (errorCode == GL_INVALID_OPERATION) {
return (GLubyte *) "invalid operation";
}
else if (errorCode == GL_STACK_OVERFLOW) {
return (GLubyte *) "stack overflow";
}
else if (errorCode == GL_STACK_UNDERFLOW) {
return (GLubyte *) "stack underflow";
}
else if (errorCode == GL_OUT_OF_MEMORY) {
return (GLubyte *) "out of memory";
}
/* GLU Errors */
else if (errorCode == GLU_NO_ERROR) {
return (GLubyte *) "no error";
}
else if (errorCode == GLU_INVALID_ENUM) {
return (GLubyte *) "invalid enum";
}
else if (errorCode == GLU_INVALID_VALUE) {
return (GLubyte *) "invalid value";
}
else if (errorCode == GLU_OUT_OF_MEMORY) {
return (GLubyte *) "out of memory";
}
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_NURBS_ERROR1 && errorCode <= GLU_NURBS_ERROR37) {
return (GLubyte *) nurbs_error[errorCode - GLU_NURBS_ERROR1];
}
else {
return NULL;
}
}
/*
* New in GLU 1.1
*/
const GLubyte *GLAPIENTRY
gluGetString(GLenum name)
{
static char *extensions = "GL_EXT_abgr";
static char *version = "1.1 Mesa 3.5";
switch (name) {
case GLU_EXTENSIONS:
return (GLubyte *) extensions;
case GLU_VERSION:
return (GLubyte *) version;
default:
return NULL;
}
}
#if 0 /* gluGetProcAddressEXT not finalized yet! */
#ifdef __cplusplus
/* for BeOS R4.5 */
void GLAPIENTRY(*gluGetProcAddressEXT(const GLubyte * procName)) (...)
#else
void (GLAPIENTRY * gluGetProcAddressEXT(const GLubyte * procName)) ()
#endif
{
struct proc
{
const char *name;
void *address;
};
static struct proc procTable[] = {
{"gluGetProcAddressEXT", (void *) gluGetProcAddressEXT}, /* me! */
/* new 1.1 functions */
{"gluGetString", (void *) gluGetString},
/* new 1.2 functions */
{"gluTessBeginPolygon", (void *) gluTessBeginPolygon},
{"gluTessBeginContour", (void *) gluTessBeginContour},
{"gluTessEndContour", (void *) gluTessEndContour},
{"gluTessEndPolygon", (void *) gluTessEndPolygon},
{"gluGetTessProperty", (void *) gluGetTessProperty},
/* new 1.3 functions */
{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 NULL;
}
#endif
/*
* New in GLU 1.3
*/
#ifdef GLU_VERSION_1_3
GLboolean GLAPIENTRY
gluCheckExtension(const GLubyte *extName, const GLubyte * extString)
{
assert(extName);
assert(extString);
{
const int len = strlen((const char *) extName);
const char *start = (const char *) extString;
while (1) {
const char *c = strstr(start, (const char *) extName);
if (!c)
return GL_FALSE;
if ((c == start || c[-1] == ' ') && (c[len] == ' ' || c[len] == 0))
return GL_TRUE;
start = c + len;
}
}
}
#endif

View file

@ -1,97 +0,0 @@
/*
* Mesa 3-D graphics library
* Version: 6.3
* Copyright (C) 1995-2004 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 allows the GLU code to be compiled either with the Mesa
* headers or with the real OpenGL headers.
*/
#ifndef GLUP_H
#define GLUP_H
#include <GL/gl.h>
#include <GL/glu.h>
#include <string.h>
#if defined(_WIN32) && !defined(__WIN32__)
# define __WIN32__
#endif
#if !defined(OPENSTEP) && (defined(__WIN32__) || defined(__CYGWIN__))
# pragma warning( disable : 4068 ) /* unknown pragma */
# pragma warning( disable : 4710 ) /* function 'foo' not inlined */
# pragma warning( disable : 4711 ) /* function 'foo' selected for automatic inline expansion */
# pragma warning( disable : 4127 ) /* conditional expression is constant */
# if defined(MESA_MINWARN)
# pragma warning( disable : 4244 ) /* '=' : conversion from 'const double ' to 'float ', possible loss of data */
# pragma warning( disable : 4018 ) /* '<' : signed/unsigned mismatch */
# pragma warning( disable : 4305 ) /* '=' : truncation from 'const double ' to 'float ' */
# pragma warning( disable : 4550 ) /* 'function' undefined; assuming extern returning int */
# pragma warning( disable : 4761 ) /* integral size mismatch in argument; conversion supplied */
# endif
# define GLCALLBACK __stdcall
# if defined(__CYGWIN__)
# define GLCALLBACKPCAST *
# else
# define GLCALLBACKPCAST __stdcall *
# endif
#else
/* non-Windows compilation */
# define GLCALLBACK
# define GLCALLBACKPCAST *
#endif /* WIN32 / CYGWIN bracket */
/* compatability guard so we don't need to change client code */
#if defined(_WIN32) && !defined(_WINDEF_) && !defined(_GNU_H_WINDOWS32_BASE) && !defined(OPENSTEP)
# define CALLBACK GLCALLBACK
#endif
#ifndef GLU_TESS_ERROR9
/* If we're using the real OpenGL header files... */
# define GLU_TESS_ERROR9 100159
#endif
#define GLU_NO_ERROR GL_NO_ERROR
/* for Sun: */
#ifdef SUNOS4
#define MEMCPY( DST, SRC, BYTES) \
memcpy( (char *) (DST), (char *) (SRC), (int) (BYTES) )
#else
#define MEMCPY( DST, SRC, BYTES) \
memcpy( (void *) (DST), (void *) (SRC), (size_t) (BYTES) )
#endif
#ifndef NULL
# define NULL 0
#endif
#endif

View file

@ -1,829 +0,0 @@
/*
* Mesa 3-D graphics library
* Version: 3.4
* 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.
*/
#ifdef PC_HEADER
#include "all.h"
#else
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "gluP.h"
#endif
/*
* Compute ceiling of integer quotient of A divided by B:
*/
#define CEILING( A, B ) ( (A) % (B) == 0 ? (A)/(B) : (A)/(B)+1 )
#ifdef EPSILON
#undef EPSILON
#endif
#define EPSILON 0.001
/* To work around optimizer bug in MSVC4.1 */
#if defined(__WIN32__) && !defined(OPENSTEP)
void
dummy(GLuint j, GLuint k)
{
}
#else
#define dummy(J, K)
#endif
GLint GLAPIENTRY
gluScaleImage(GLenum format,
GLsizei widthin, GLsizei heightin,
GLenum typein, const void *datain,
GLsizei widthout, GLsizei heightout,
GLenum typeout, void *dataout)
{
GLint components, i, j, k;
GLfloat *tempin, *tempout;
GLfloat sx, sy;
GLint unpackrowlength, unpackalignment, unpackskiprows, unpackskippixels;
GLint packrowlength, packalignment, packskiprows, packskippixels;
GLint sizein, sizeout;
GLint rowstride, rowlen;
/* Determine number of components per pixel */
switch (format) {
case GL_COLOR_INDEX:
case GL_STENCIL_INDEX:
case GL_DEPTH_COMPONENT:
case GL_RED:
case GL_GREEN:
case GL_BLUE:
case GL_ALPHA:
case GL_LUMINANCE:
components = 1;
break;
case GL_LUMINANCE_ALPHA:
components = 2;
break;
case GL_RGB:
case GL_BGR:
components = 3;
break;
case GL_RGBA:
case GL_BGRA:
#ifdef GL_EXT_abgr
case GL_ABGR_EXT:
#endif
components = 4;
break;
default:
return GLU_INVALID_ENUM;
}
/* Determine bytes per input datum */
switch (typein) {
case GL_UNSIGNED_BYTE:
sizein = sizeof(GLubyte);
break;
case GL_BYTE:
sizein = sizeof(GLbyte);
break;
case GL_UNSIGNED_SHORT:
sizein = sizeof(GLushort);
break;
case GL_SHORT:
sizein = sizeof(GLshort);
break;
case GL_UNSIGNED_INT:
sizein = sizeof(GLuint);
break;
case GL_INT:
sizein = sizeof(GLint);
break;
case GL_FLOAT:
sizein = sizeof(GLfloat);
break;
case GL_BITMAP:
/* not implemented yet */
default:
return GL_INVALID_ENUM;
}
/* Determine bytes per output datum */
switch (typeout) {
case GL_UNSIGNED_BYTE:
sizeout = sizeof(GLubyte);
break;
case GL_BYTE:
sizeout = sizeof(GLbyte);
break;
case GL_UNSIGNED_SHORT:
sizeout = sizeof(GLushort);
break;
case GL_SHORT:
sizeout = sizeof(GLshort);
break;
case GL_UNSIGNED_INT:
sizeout = sizeof(GLuint);
break;
case GL_INT:
sizeout = sizeof(GLint);
break;
case GL_FLOAT:
sizeout = sizeof(GLfloat);
break;
case GL_BITMAP:
/* not implemented yet */
default:
return GL_INVALID_ENUM;
}
/* Get glPixelStore state */
glGetIntegerv(GL_UNPACK_ROW_LENGTH, &unpackrowlength);
glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpackalignment);
glGetIntegerv(GL_UNPACK_SKIP_ROWS, &unpackskiprows);
glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &unpackskippixels);
glGetIntegerv(GL_PACK_ROW_LENGTH, &packrowlength);
glGetIntegerv(GL_PACK_ALIGNMENT, &packalignment);
glGetIntegerv(GL_PACK_SKIP_ROWS, &packskiprows);
glGetIntegerv(GL_PACK_SKIP_PIXELS, &packskippixels);
/* Allocate storage for intermediate images */
tempin = (GLfloat *) malloc(widthin * heightin
* components * sizeof(GLfloat));
if (!tempin) {
return GLU_OUT_OF_MEMORY;
}
tempout = (GLfloat *) malloc(widthout * heightout
* components * sizeof(GLfloat));
if (!tempout) {
free(tempin);
return GLU_OUT_OF_MEMORY;
}
/*
* Unpack the pixel data and convert to floating point
*/
if (unpackrowlength > 0) {
rowlen = unpackrowlength;
}
else {
rowlen = widthin;
}
if (sizein >= unpackalignment) {
rowstride = components * rowlen;
}
else {
rowstride = unpackalignment / sizein
* CEILING(components * rowlen * sizein, unpackalignment);
}
switch (typein) {
case GL_UNSIGNED_BYTE:
k = 0;
for (i = 0; i < heightin; i++) {
GLubyte *ubptr = (GLubyte *) datain
+ i * rowstride
+ unpackskiprows * rowstride + unpackskippixels * components;
for (j = 0; j < widthin * components; j++) {
dummy(j, k);
tempin[k++] = (GLfloat) * ubptr++;
}
}
break;
case GL_BYTE:
k = 0;
for (i = 0; i < heightin; i++) {
GLbyte *bptr = (GLbyte *) datain
+ i * rowstride
+ unpackskiprows * rowstride + unpackskippixels * components;
for (j = 0; j < widthin * components; j++) {
dummy(j, k);
tempin[k++] = (GLfloat) * bptr++;
}
}
break;
case GL_UNSIGNED_SHORT:
k = 0;
for (i = 0; i < heightin; i++) {
GLushort *usptr = (GLushort *) datain
+ i * rowstride
+ unpackskiprows * rowstride + unpackskippixels * components;
for (j = 0; j < widthin * components; j++) {
dummy(j, k);
tempin[k++] = (GLfloat) * usptr++;
}
}
break;
case GL_SHORT:
k = 0;
for (i = 0; i < heightin; i++) {
GLshort *sptr = (GLshort *) datain
+ i * rowstride
+ unpackskiprows * rowstride + unpackskippixels * components;
for (j = 0; j < widthin * components; j++) {
dummy(j, k);
tempin[k++] = (GLfloat) * sptr++;
}
}
break;
case GL_UNSIGNED_INT:
k = 0;
for (i = 0; i < heightin; i++) {
GLuint *uiptr = (GLuint *) datain
+ i * rowstride
+ unpackskiprows * rowstride + unpackskippixels * components;
for (j = 0; j < widthin * components; j++) {
dummy(j, k);
tempin[k++] = (GLfloat) * uiptr++;
}
}
break;
case GL_INT:
k = 0;
for (i = 0; i < heightin; i++) {
GLint *iptr = (GLint *) datain
+ i * rowstride
+ unpackskiprows * rowstride + unpackskippixels * components;
for (j = 0; j < widthin * components; j++) {
dummy(j, k);
tempin[k++] = (GLfloat) * iptr++;
}
}
break;
case GL_FLOAT:
k = 0;
for (i = 0; i < heightin; i++) {
GLfloat *fptr = (GLfloat *) datain
+ i * rowstride
+ unpackskiprows * rowstride + unpackskippixels * components;
for (j = 0; j < widthin * components; j++) {
dummy(j, k);
tempin[k++] = *fptr++;
}
}
break;
default:
{
free(tempin);
free(tempout);
return GLU_INVALID_ENUM;
}
}
/*
* Scale the image!
*/
if (widthout > 1)
sx = (GLfloat) (widthin - 1) / (GLfloat) (widthout - 1);
else
sx = (GLfloat) (widthin - 1);
if (heightout > 1)
sy = (GLfloat) (heightin - 1) / (GLfloat) (heightout - 1);
else
sy = (GLfloat) (heightin - 1);
/*#define POINT_SAMPLE*/
#ifdef POINT_SAMPLE
for (i = 0; i < heightout; i++) {
GLint ii = i * sy;
for (j = 0; j < widthout; j++) {
GLint jj = j * sx;
GLfloat *src = tempin + (ii * widthin + jj) * components;
GLfloat *dst = tempout + (i * widthout + j) * components;
for (k = 0; k < components; k++) {
*dst++ = *src++;
}
}
}
#else
if (sx < 1.0 && sy < 1.0) {
/* magnify both width and height: use weighted sample of 4 pixels */
GLint i0, i1, j0, j1;
GLfloat alpha, beta;
GLfloat *src00, *src01, *src10, *src11;
GLfloat s1, s2;
GLfloat *dst;
for (i = 0; i < heightout; i++) {
i0 = i * sy;
i1 = i0 + 1;
if (i1 >= heightin)
i1 = heightin - 1;
/* i1 = (i+1) * sy - EPSILON;*/
alpha = i * sy - i0;
for (j = 0; j < widthout; j++) {
j0 = j * sx;
j1 = j0 + 1;
if (j1 >= widthin)
j1 = widthin - 1;
/* j1 = (j+1) * sx - EPSILON; */
beta = j * sx - j0;
/* compute weighted average of pixels in rect (i0,j0)-(i1,j1) */
src00 = tempin + (i0 * widthin + j0) * components;
src01 = tempin + (i0 * widthin + j1) * components;
src10 = tempin + (i1 * widthin + j0) * components;
src11 = tempin + (i1 * widthin + j1) * components;
dst = tempout + (i * widthout + j) * components;
for (k = 0; k < components; k++) {
s1 = *src00++ * (1.0 - beta) + *src01++ * beta;
s2 = *src10++ * (1.0 - beta) + *src11++ * beta;
*dst++ = s1 * (1.0 - alpha) + s2 * alpha;
}
}
}
}
else {
/* shrink width and/or height: use an unweighted box filter */
GLint i0, i1;
GLint j0, j1;
GLint ii, jj;
GLfloat sum, *dst;
for (i = 0; i < heightout; i++) {
i0 = i * sy;
i1 = i0 + 1;
if (i1 >= heightin)
i1 = heightin - 1;
/* i1 = (i+1) * sy - EPSILON; */
for (j = 0; j < widthout; j++) {
j0 = j * sx;
j1 = j0 + 1;
if (j1 >= widthin)
j1 = widthin - 1;
/* j1 = (j+1) * sx - EPSILON; */
dst = tempout + (i * widthout + j) * components;
/* compute average of pixels in the rectangle (i0,j0)-(i1,j1) */
for (k = 0; k < components; k++) {
sum = 0.0;
for (ii = i0; ii <= i1; ii++) {
for (jj = j0; jj <= j1; jj++) {
sum += *(tempin + (ii * widthin + jj) * components + k);
}
}
sum /= (j1 - j0 + 1) * (i1 - i0 + 1);
*dst++ = sum;
}
}
}
}
#endif
/*
* Return output image
*/
if (packrowlength > 0) {
rowlen = packrowlength;
}
else {
rowlen = widthout;
}
if (sizeout >= packalignment) {
rowstride = components * rowlen;
}
else {
rowstride = packalignment / sizeout
* CEILING(components * rowlen * sizeout, packalignment);
}
switch (typeout) {
case GL_UNSIGNED_BYTE:
k = 0;
for (i = 0; i < heightout; i++) {
GLubyte *ubptr = (GLubyte *) dataout
+ i * rowstride
+ packskiprows * rowstride + packskippixels * components;
for (j = 0; j < widthout * components; j++) {
dummy(j, k + i);
*ubptr++ = (GLubyte) tempout[k++];
}
}
break;
case GL_BYTE:
k = 0;
for (i = 0; i < heightout; i++) {
GLbyte *bptr = (GLbyte *) dataout
+ i * rowstride
+ packskiprows * rowstride + packskippixels * components;
for (j = 0; j < widthout * components; j++) {
dummy(j, k + i);
*bptr++ = (GLbyte) tempout[k++];
}
}
break;
case GL_UNSIGNED_SHORT:
k = 0;
for (i = 0; i < heightout; i++) {
GLushort *usptr = (GLushort *) dataout
+ i * rowstride
+ packskiprows * rowstride + packskippixels * components;
for (j = 0; j < widthout * components; j++) {
dummy(j, k + i);
*usptr++ = (GLushort) tempout[k++];
}
}
break;
case GL_SHORT:
k = 0;
for (i = 0; i < heightout; i++) {
GLshort *sptr = (GLshort *) dataout
+ i * rowstride
+ packskiprows * rowstride + packskippixels * components;
for (j = 0; j < widthout * components; j++) {
dummy(j, k + i);
*sptr++ = (GLshort) tempout[k++];
}
}
break;
case GL_UNSIGNED_INT:
k = 0;
for (i = 0; i < heightout; i++) {
GLuint *uiptr = (GLuint *) dataout
+ i * rowstride
+ packskiprows * rowstride + packskippixels * components;
for (j = 0; j < widthout * components; j++) {
dummy(j, k + i);
*uiptr++ = (GLuint) tempout[k++];
}
}
break;
case GL_INT:
k = 0;
for (i = 0; i < heightout; i++) {
GLint *iptr = (GLint *) dataout
+ i * rowstride
+ packskiprows * rowstride + packskippixels * components;
for (j = 0; j < widthout * components; j++) {
dummy(j, k + i);
*iptr++ = (GLint) tempout[k++];
}
}
break;
case GL_FLOAT:
k = 0;
for (i = 0; i < heightout; i++) {
GLfloat *fptr = (GLfloat *) dataout
+ i * rowstride
+ packskiprows * rowstride + packskippixels * components;
for (j = 0; j < widthout * components; j++) {
dummy(j, k + i);
*fptr++ = tempout[k++];
}
}
break;
default:
return GLU_INVALID_ENUM;
}
/* free temporary image storage */
free(tempin);
free(tempout);
return 0;
}
/*
* Return the largest k such that 2^k <= n.
*/
static GLint
ilog2(GLint n)
{
GLint k;
if (n <= 0)
return 0;
for (k = 0; n >>= 1; k++);
return k;
}
/*
* Find the value nearest to n which is also a power of two.
*/
static GLint
round2(GLint n)
{
GLint m;
for (m = 1; m < n; m *= 2);
/* m>=n */
if (m - n <= n - m / 2) {
return m;
}
else {
return m / 2;
}
}
/*
* Given an pixel format and datatype, return the number of bytes to
* store one pixel.
*/
static GLint
bytes_per_pixel(GLenum format, GLenum type)
{
GLint n, m;
switch (format) {
case GL_COLOR_INDEX:
case GL_STENCIL_INDEX:
case GL_DEPTH_COMPONENT:
case GL_RED:
case GL_GREEN:
case GL_BLUE:
case GL_ALPHA:
case GL_LUMINANCE:
n = 1;
break;
case GL_LUMINANCE_ALPHA:
n = 2;
break;
case GL_RGB:
case GL_BGR:
n = 3;
break;
case GL_RGBA:
case GL_BGRA:
#ifdef GL_EXT_abgr
case GL_ABGR_EXT:
#endif
n = 4;
break;
default:
n = 0;
}
switch (type) {
case GL_UNSIGNED_BYTE:
m = sizeof(GLubyte);
break;
case GL_BYTE:
m = sizeof(GLbyte);
break;
case GL_BITMAP:
m = 1;
break;
case GL_UNSIGNED_SHORT:
m = sizeof(GLushort);
break;
case GL_SHORT:
m = sizeof(GLshort);
break;
case GL_UNSIGNED_INT:
m = sizeof(GLuint);
break;
case GL_INT:
m = sizeof(GLint);
break;
case GL_FLOAT:
m = sizeof(GLfloat);
break;
default:
m = 0;
}
return n * m;
}
/*
* WARNING: This function isn't finished and has never been tested!!!!
*/
GLint GLAPIENTRY
gluBuild1DMipmaps(GLenum target, GLint components,
GLsizei width, GLenum format, GLenum type, const void *data)
{
GLubyte *texture;
GLint levels, max_levels;
GLint new_width, max_width;
GLint i, j, k, l;
if (width < 1)
return GLU_INVALID_VALUE;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_width);
max_levels = ilog2(max_width) + 1;
/* Compute how many mipmap images to make */
levels = ilog2(width) + 1;
if (levels > max_levels) {
levels = max_levels;
}
new_width = 1 << (levels - 1);
texture = (GLubyte *) malloc(new_width * components);
if (!texture) {
return GLU_OUT_OF_MEMORY;
}
if (width != new_width) {
/* initial rescaling */
switch (type) {
case GL_UNSIGNED_BYTE:
{
GLubyte *ub_data = (GLubyte *) data;
for (i = 0; i < new_width; i++) {
j = i * width / new_width;
for (k = 0; k < components; k++) {
texture[i * components + k] = ub_data[j * components + k];
}
}
}
break;
default:
/* Not implemented */
free(texture);
return GLU_ERROR;
}
}
/* generate and load mipmap images */
for (l = 0; l < levels; l++) {
glTexImage1D(GL_TEXTURE_1D, l, components, new_width, 0,
format, GL_UNSIGNED_BYTE, texture);
/* Scale image down to 1/2 size */
new_width = new_width / 2;
for (i = 0; i < new_width; i++) {
for (k = 0; k < components; k++) {
GLint sample1, sample2;
sample1 = (GLint) texture[i * 2 * components + k];
sample2 = (GLint) texture[(i * 2 + 1) * components + k];
texture[i * components + k] = (GLubyte) ((sample1 + sample2) / 2);
}
}
}
free(texture);
return 0;
}
GLint GLAPIENTRY
gluBuild2DMipmaps(GLenum target, GLint components,
GLsizei width, GLsizei height, GLenum format,
GLenum type, const void *data)
{
GLint w, h, maxsize;
void *image, *newimage;
GLint neww, newh, level, bpp;
int error;
GLboolean done;
GLint retval = 0;
GLint unpackrowlength, unpackalignment, unpackskiprows, unpackskippixels;
GLint packrowlength, packalignment, packskiprows, packskippixels;
if (width < 1 || height < 1)
return GLU_INVALID_VALUE;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxsize);
w = round2(width);
if (w > maxsize) {
w = maxsize;
}
h = round2(height);
if (h > maxsize) {
h = maxsize;
}
bpp = bytes_per_pixel(format, type);
if (bpp == 0) {
/* probably a bad format or type enum */
return GLU_INVALID_ENUM;
}
/* Get current glPixelStore values */
glGetIntegerv(GL_UNPACK_ROW_LENGTH, &unpackrowlength);
glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpackalignment);
glGetIntegerv(GL_UNPACK_SKIP_ROWS, &unpackskiprows);
glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &unpackskippixels);
glGetIntegerv(GL_PACK_ROW_LENGTH, &packrowlength);
glGetIntegerv(GL_PACK_ALIGNMENT, &packalignment);
glGetIntegerv(GL_PACK_SKIP_ROWS, &packskiprows);
glGetIntegerv(GL_PACK_SKIP_PIXELS, &packskippixels);
/* set pixel packing */
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glPixelStorei(GL_PACK_SKIP_ROWS, 0);
glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
done = GL_FALSE;
if (w != width || h != height) {
/* must rescale image to get "top" mipmap texture image */
image = malloc((w + 4) * h * bpp);
if (!image) {
return GLU_OUT_OF_MEMORY;
}
error = gluScaleImage(format, width, height, type, data,
w, h, type, image);
if (error) {
retval = error;
done = GL_TRUE;
}
}
else {
image = (void *) data;
}
level = 0;
while (!done) {
if (image != data) {
/* set pixel unpacking */
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
}
glTexImage2D(target, level, components, w, h, 0, format, type, image);
if (w == 1 && h == 1)
break;
neww = (w < 2) ? 1 : w / 2;
newh = (h < 2) ? 1 : h / 2;
newimage = malloc((neww + 4) * newh * bpp);
if (!newimage) {
return GLU_OUT_OF_MEMORY;
}
error = gluScaleImage(format, w, h, type, image,
neww, newh, type, newimage);
if (error) {
retval = error;
done = GL_TRUE;
}
if (image != data) {
free(image);
}
image = newimage;
w = neww;
h = newh;
level++;
}
if (image != data) {
free(image);
}
/* Restore original glPixelStore state */
glPixelStorei(GL_UNPACK_ROW_LENGTH, unpackrowlength);
glPixelStorei(GL_UNPACK_ALIGNMENT, unpackalignment);
glPixelStorei(GL_UNPACK_SKIP_ROWS, unpackskiprows);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, unpackskippixels);
glPixelStorei(GL_PACK_ROW_LENGTH, packrowlength);
glPixelStorei(GL_PACK_ALIGNMENT, packalignment);
glPixelStorei(GL_PACK_SKIP_ROWS, packskiprows);
glPixelStorei(GL_PACK_SKIP_PIXELS, packskippixels);
return retval;
}

View file

@ -1,628 +0,0 @@
/*
* 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.
*/
/*
* NURBS implementation written by Bogdan Sikorski (bogdan@cira.it)
* See README2 for more info.
*/
#ifdef PC_HEADER
#include "all.h"
#else
#include <stdio.h>
#include <stdlib.h>
#include "gluP.h"
#include "nurbs.h"
#endif
void
call_user_error(GLUnurbsObj * nobj, GLenum error)
{
nobj->error = error;
if (nobj->error_callback != NULL) {
(*(nobj->error_callback)) (error);
}
else {
printf("NURBS error %d %s\n", error, (char *) gluErrorString(error));
}
}
GLUnurbsObj *GLAPIENTRY
gluNewNurbsRenderer(void)
{
GLUnurbsObj *n;
GLfloat tmp_viewport[4];
GLint i, j;
n = (GLUnurbsObj *) malloc(sizeof(GLUnurbsObj));
if (n) {
/* init */
n->culling = GL_FALSE;
n->nurbs_type = GLU_NURBS_NONE;
n->error = GLU_NO_ERROR;
n->error_callback = NULL;
n->auto_load_matrix = GL_TRUE;
n->sampling_tolerance = 50.0;
n->parametric_tolerance = 0.5;
n->u_step = n->v_step = 100;
n->sampling_method = GLU_PATH_LENGTH;
n->display_mode = GLU_FILL;
/* in case the user doesn't supply the sampling matrices */
/* set projection and modelview to identity */
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
if (i == j) {
n->sampling_matrices.model[i * 4 + j] = 1.0;
n->sampling_matrices.proj[i * 4 + j] = 1.0;
}
else {
n->sampling_matrices.model[i * 4 + j] = 0.0;
n->sampling_matrices.proj[i * 4 + j] = 0.0;
}
/* and set the viewport sampling matrix to current ciewport */
glGetFloatv(GL_VIEWPORT, tmp_viewport);
for (i = 0; i < 4; i++)
n->sampling_matrices.viewport[i] = tmp_viewport[i];
n->trim = NULL;
}
return n;
}
void GLAPIENTRY
gluDeleteNurbsRenderer(GLUnurbsObj * nobj)
{
if (nobj) {
free(nobj);
}
}
void GLAPIENTRY
gluLoadSamplingMatrices(GLUnurbsObj * nobj,
const GLfloat modelMatrix[16],
const GLfloat projMatrix[16], const GLint viewport[4])
{
GLint i;
for (i = 0; i < 16; i++) {
nobj->sampling_matrices.model[i] = modelMatrix[i];
nobj->sampling_matrices.proj[i] = projMatrix[i];
}
for (i = 0; i < 4; i++)
nobj->sampling_matrices.viewport[i] = viewport[i];
}
void GLAPIENTRY
gluNurbsProperty(GLUnurbsObj * nobj, GLenum property, GLfloat value)
{
GLenum val;
switch (property) {
case GLU_SAMPLING_TOLERANCE:
if (value <= 0.0) {
call_user_error(nobj, GLU_INVALID_VALUE);
return;
}
nobj->sampling_tolerance = value;
break;
case GLU_PARAMETRIC_TOLERANCE:
if (value <= 0.0) {
call_user_error(nobj, GLU_INVALID_VALUE);
return;
}
nobj->parametric_tolerance = value;
break;
case GLU_U_STEP:
if (value <= 0.0) {
call_user_error(nobj, GLU_INVALID_VALUE);
return;
}
nobj->u_step = (GLint) value;
break;
case GLU_V_STEP:
if (value <= 0.0) {
call_user_error(nobj, GLU_INVALID_VALUE);
return;
}
nobj->v_step = (GLint) value;
break;
case GLU_SAMPLING_METHOD:
val = (GLenum) value;
if (val != GLU_PATH_LENGTH && val != GLU_PARAMETRIC_ERROR
&& val != GLU_DOMAIN_DISTANCE) {
call_user_error(nobj, GLU_INVALID_ENUM);
return;
}
nobj->sampling_method = val;
break;
case GLU_DISPLAY_MODE:
val = (GLenum) value;
if (val != GLU_FILL && val != GLU_OUTLINE_POLYGON
&& val != GLU_OUTLINE_PATCH) {
call_user_error(nobj, GLU_INVALID_ENUM);
return;
}
if (nobj->nurbs_type == GLU_NURBS_CURVE) {
call_user_error(nobj, GLU_NURBS_ERROR26);
return;
}
nobj->display_mode = val;
if (val == GLU_OUTLINE_PATCH)
fprintf(stderr,
"NURBS, for the moment, can display only in POLYGON mode\n");
break;
case GLU_CULLING:
val = (GLenum) value;
if (val != GL_TRUE && val != GL_FALSE) {
call_user_error(nobj, GLU_INVALID_ENUM);
return;
}
nobj->culling = (GLboolean) value;
break;
case GLU_AUTO_LOAD_MATRIX:
val = (GLenum) value;
if (val != GL_TRUE && val != GL_FALSE) {
call_user_error(nobj, GLU_INVALID_ENUM);
return;
}
nobj->auto_load_matrix = (GLboolean) value;
break;
default:
call_user_error(nobj, GLU_NURBS_ERROR26);
}
}
void GLAPIENTRY
gluGetNurbsProperty(GLUnurbsObj * nobj, GLenum property, GLfloat * value)
{
switch (property) {
case GLU_SAMPLING_TOLERANCE:
*value = nobj->sampling_tolerance;
break;
case GLU_DISPLAY_MODE:
*value = (GLfloat) (GLint) nobj->display_mode;
break;
case GLU_CULLING:
*value = nobj->culling ? 1.0 : 0.0;
break;
case GLU_AUTO_LOAD_MATRIX:
*value = nobj->auto_load_matrix ? 1.0 : 0.0;
break;
default:
call_user_error(nobj, GLU_INVALID_ENUM);
}
}
void GLAPIENTRY
gluBeginCurve(GLUnurbsObj * nobj)
{
if (nobj->nurbs_type == GLU_NURBS_CURVE) {
call_user_error(nobj, GLU_NURBS_ERROR6);
return;
}
nobj->nurbs_type = GLU_NURBS_CURVE;
nobj->curve.geom.type = GLU_INVALID_ENUM;
nobj->curve.color.type = GLU_INVALID_ENUM;
nobj->curve.texture.type = GLU_INVALID_ENUM;
nobj->curve.normal.type = GLU_INVALID_ENUM;
}
void GLAPIENTRY
gluEndCurve(GLUnurbsObj * nobj)
{
if (nobj->nurbs_type == GLU_NURBS_NONE) {
call_user_error(nobj, GLU_NURBS_ERROR7);
return;
}
if (nobj->curve.geom.type == GLU_INVALID_ENUM) {
call_user_error(nobj, GLU_NURBS_ERROR8);
nobj->nurbs_type = GLU_NURBS_NONE;
return;
}
glPushAttrib((GLbitfield) (GL_EVAL_BIT | GL_ENABLE_BIT));
glDisable(GL_MAP1_VERTEX_3);
glDisable(GL_MAP1_VERTEX_4);
glDisable(GL_MAP1_INDEX);
glDisable(GL_MAP1_COLOR_4);
glDisable(GL_MAP1_NORMAL);
glDisable(GL_MAP1_TEXTURE_COORD_1);
glDisable(GL_MAP1_TEXTURE_COORD_2);
glDisable(GL_MAP1_TEXTURE_COORD_3);
glDisable(GL_MAP1_TEXTURE_COORD_4);
glDisable(GL_MAP2_VERTEX_3);
glDisable(GL_MAP2_VERTEX_4);
glDisable(GL_MAP2_INDEX);
glDisable(GL_MAP2_COLOR_4);
glDisable(GL_MAP2_NORMAL);
glDisable(GL_MAP2_TEXTURE_COORD_1);
glDisable(GL_MAP2_TEXTURE_COORD_2);
glDisable(GL_MAP2_TEXTURE_COORD_3);
glDisable(GL_MAP2_TEXTURE_COORD_4);
do_nurbs_curve(nobj);
glPopAttrib();
nobj->nurbs_type = GLU_NURBS_NONE;
}
void GLAPIENTRY
gluNurbsCurve(GLUnurbsObj * nobj, GLint nknots, GLfloat * knot,
GLint stride, GLfloat * ctlarray, GLint order, GLenum type)
{
if (nobj->nurbs_type == GLU_NURBS_TRIM) {
#if 0
/* TODO: NOT IMPLEMENTED YET */
nurbs_trim *ptr1;
trim_list *ptr2;
if (type != GLU_MAP1_TRIM_2 && type != GLU_MAP1_TRIM_3) {
call_user_error(nobj, GLU_NURBS_ERROR14);
return;
}
for (ptr1 = nobj->trim; ptr1->next; ptr1 = ptr1->next);
if (ptr1->trim_loop) {
for (ptr2 = ptr1->trim_loop; ptr2->next; ptr2 = ptr2->next);
if ((ptr2->next = (trim_list *) malloc(sizeof(trim_list))) == NULL) {
call_user_error(nobj, GLU_OUT_OF_MEMORY);
return;
}
ptr2 = ptr2->next;
}
else {
if ((ptr2 = (trim_list *) malloc(sizeof(trim_list))) == NULL) {
call_user_error(nobj, GLU_OUT_OF_MEMORY);
return;
}
ptr1->trim_loop = ptr2;
}
ptr2->trim_type = GLU_TRIM_NURBS;
ptr2->curve.nurbs_curve.knot_count = nknots;
ptr2->curve.nurbs_curve.knot = knot;
ptr2->curve.nurbs_curve.stride = stride;
ptr2->curve.nurbs_curve.ctrlarray = ctlarray;
ptr2->curve.nurbs_curve.order = order;
ptr2->curve.nurbs_curve.dim = (type == GLU_MAP1_TRIM_2 ? 2 : 3);
ptr2->curve.nurbs_curve.type = type;
ptr2->next = NULL;
#endif
}
else {
if (type == GLU_MAP1_TRIM_2 || type == GLU_MAP1_TRIM_3) {
call_user_error(nobj, GLU_NURBS_ERROR22);
return;
}
if (nobj->nurbs_type != GLU_NURBS_CURVE) {
call_user_error(nobj, GLU_NURBS_ERROR10);
return;
}
switch (type) {
case GL_MAP1_VERTEX_3:
case GL_MAP1_VERTEX_4:
if (nobj->curve.geom.type != GLU_INVALID_ENUM) {
call_user_error(nobj, GLU_NURBS_ERROR8);
return;
}
nobj->curve.geom.type = type;
nobj->curve.geom.knot_count = nknots;
nobj->curve.geom.knot = knot;
nobj->curve.geom.stride = stride;
nobj->curve.geom.ctrlarray = ctlarray;
nobj->curve.geom.order = order;
break;
case GL_MAP1_INDEX:
case GL_MAP1_COLOR_4:
nobj->curve.color.type = type;
nobj->curve.color.knot_count = nknots;
nobj->curve.color.knot = knot;
nobj->curve.color.stride = stride;
nobj->curve.color.ctrlarray = ctlarray;
nobj->curve.color.order = order;
break;
case GL_MAP1_NORMAL:
nobj->curve.normal.type = type;
nobj->curve.normal.knot_count = nknots;
nobj->curve.normal.knot = knot;
nobj->curve.normal.stride = stride;
nobj->curve.normal.ctrlarray = ctlarray;
nobj->curve.normal.order = order;
break;
case GL_MAP1_TEXTURE_COORD_1:
case GL_MAP1_TEXTURE_COORD_2:
case GL_MAP1_TEXTURE_COORD_3:
case GL_MAP1_TEXTURE_COORD_4:
nobj->curve.texture.type = type;
nobj->curve.texture.knot_count = nknots;
nobj->curve.texture.knot = knot;
nobj->curve.texture.stride = stride;
nobj->curve.texture.ctrlarray = ctlarray;
nobj->curve.texture.order = order;
break;
default:
call_user_error(nobj, GLU_INVALID_ENUM);
}
}
}
void GLAPIENTRY
gluBeginSurface(GLUnurbsObj * nobj)
{
switch (nobj->nurbs_type) {
case GLU_NURBS_NONE:
nobj->nurbs_type = GLU_NURBS_SURFACE;
nobj->surface.geom.type = GLU_INVALID_ENUM;
nobj->surface.color.type = GLU_INVALID_ENUM;
nobj->surface.texture.type = GLU_INVALID_ENUM;
nobj->surface.normal.type = GLU_INVALID_ENUM;
break;
case GLU_NURBS_TRIM:
call_user_error(nobj, GLU_NURBS_ERROR16);
break;
case GLU_NURBS_SURFACE:
case GLU_NURBS_NO_TRIM:
case GLU_NURBS_TRIM_DONE:
call_user_error(nobj, GLU_NURBS_ERROR27);
break;
case GLU_NURBS_CURVE:
call_user_error(nobj, GLU_NURBS_ERROR6);
break;
}
}
void GLAPIENTRY
gluEndSurface(GLUnurbsObj * nobj)
{
switch (nobj->nurbs_type) {
case GLU_NURBS_NONE:
call_user_error(nobj, GLU_NURBS_ERROR13);
break;
case GLU_NURBS_TRIM:
call_user_error(nobj, GLU_NURBS_ERROR12);
break;
case GLU_NURBS_TRIM_DONE:
/* if(nobj->trim->trim_loop==NULL)
{
call_user_error(nobj,GLU_NURBS_ERROR18);
return;
}*/
/* no break - fallthrough */
case GLU_NURBS_NO_TRIM:
glPushAttrib((GLbitfield)
(GL_EVAL_BIT | GL_ENABLE_BIT | GL_POLYGON_BIT));
glDisable(GL_MAP2_VERTEX_3);
glDisable(GL_MAP2_VERTEX_4);
glDisable(GL_MAP2_INDEX);
glDisable(GL_MAP2_COLOR_4);
glDisable(GL_MAP2_NORMAL);
glDisable(GL_MAP2_TEXTURE_COORD_1);
glDisable(GL_MAP2_TEXTURE_COORD_2);
glDisable(GL_MAP2_TEXTURE_COORD_3);
glDisable(GL_MAP2_TEXTURE_COORD_4);
/* glDisable(GL_MAP1_VERTEX_3);
glDisable(GL_MAP1_VERTEX_4);
glDisable(GL_MAP1_INDEX);
glDisable(GL_MAP1_COLOR_4);
glDisable(GL_MAP1_NORMAL);
glDisable(GL_MAP1_TEXTURE_COORD_1);
glDisable(GL_MAP1_TEXTURE_COORD_2);
glDisable(GL_MAP1_TEXTURE_COORD_3);
glDisable(GL_MAP1_TEXTURE_COORD_4);*/
do_nurbs_surface(nobj);
glPopAttrib();
break;
default:
call_user_error(nobj, GLU_NURBS_ERROR8);
}
nobj->nurbs_type = GLU_NURBS_NONE;
}
void GLAPIENTRY
gluNurbsSurface(GLUnurbsObj * nobj,
GLint sknot_count, GLfloat * sknot,
GLint tknot_count, GLfloat * tknot,
GLint s_stride, GLint t_stride,
GLfloat * ctrlarray, GLint sorder, GLint torder, GLenum type)
{
if (nobj->nurbs_type == GLU_NURBS_NO_TRIM
|| nobj->nurbs_type == GLU_NURBS_TRIM
|| nobj->nurbs_type == GLU_NURBS_TRIM_DONE) {
if (type == GL_MAP2_VERTEX_3 || type == GL_MAP2_VERTEX_4) {
call_user_error(nobj, GLU_NURBS_ERROR8);
return;
}
}
else if (nobj->nurbs_type != GLU_NURBS_SURFACE) {
call_user_error(nobj, GLU_NURBS_ERROR11);
return;
}
switch (type) {
case GL_MAP2_VERTEX_3:
case GL_MAP2_VERTEX_4:
nobj->surface.geom.sknot_count = sknot_count;
nobj->surface.geom.sknot = sknot;
nobj->surface.geom.tknot_count = tknot_count;
nobj->surface.geom.tknot = tknot;
nobj->surface.geom.s_stride = s_stride;
nobj->surface.geom.t_stride = t_stride;
nobj->surface.geom.ctrlarray = ctrlarray;
nobj->surface.geom.sorder = sorder;
nobj->surface.geom.torder = torder;
nobj->surface.geom.type = type;
nobj->nurbs_type = GLU_NURBS_NO_TRIM;
break;
case GL_MAP2_INDEX:
case GL_MAP2_COLOR_4:
nobj->surface.color.sknot_count = sknot_count;
nobj->surface.color.sknot = sknot;
nobj->surface.color.tknot_count = tknot_count;
nobj->surface.color.tknot = tknot;
nobj->surface.color.s_stride = s_stride;
nobj->surface.color.t_stride = t_stride;
nobj->surface.color.ctrlarray = ctrlarray;
nobj->surface.color.sorder = sorder;
nobj->surface.color.torder = torder;
nobj->surface.color.type = type;
break;
case GL_MAP2_NORMAL:
nobj->surface.normal.sknot_count = sknot_count;
nobj->surface.normal.sknot = sknot;
nobj->surface.normal.tknot_count = tknot_count;
nobj->surface.normal.tknot = tknot;
nobj->surface.normal.s_stride = s_stride;
nobj->surface.normal.t_stride = t_stride;
nobj->surface.normal.ctrlarray = ctrlarray;
nobj->surface.normal.sorder = sorder;
nobj->surface.normal.torder = torder;
nobj->surface.normal.type = type;
break;
case GL_MAP2_TEXTURE_COORD_1:
case GL_MAP2_TEXTURE_COORD_2:
case GL_MAP2_TEXTURE_COORD_3:
case GL_MAP2_TEXTURE_COORD_4:
nobj->surface.texture.sknot_count = sknot_count;
nobj->surface.texture.sknot = sknot;
nobj->surface.texture.tknot_count = tknot_count;
nobj->surface.texture.tknot = tknot;
nobj->surface.texture.s_stride = s_stride;
nobj->surface.texture.t_stride = t_stride;
nobj->surface.texture.ctrlarray = ctrlarray;
nobj->surface.texture.sorder = sorder;
nobj->surface.texture.torder = torder;
nobj->surface.texture.type = type;
break;
default:
call_user_error(nobj, GLU_INVALID_ENUM);
}
}
void GLAPIENTRY
gluNurbsCallback(GLUnurbsObj * nobj, GLenum which, void (GLCALLBACK * fn) ())
{
nobj->error_callback = (void (GLCALLBACKPCAST) (GLenum)) fn;
if (which != GLU_ERROR)
call_user_error(nobj, GLU_INVALID_ENUM);
}
void GLAPIENTRY
gluBeginTrim(GLUnurbsObj * nobj)
{
#if 0
nurbs_trim *ptr;
#endif
if (nobj->nurbs_type != GLU_NURBS_TRIM_DONE)
if (nobj->nurbs_type != GLU_NURBS_NO_TRIM) {
call_user_error(nobj, GLU_NURBS_ERROR15);
return;
}
nobj->nurbs_type = GLU_NURBS_TRIM;
fprintf(stderr, "NURBS - trimming not supported yet\n");
#if 0
if ((ptr = (nurbs_trim *) malloc(sizeof(nurbs_trim))) == NULL) {
call_user_error(nobj, GLU_OUT_OF_MEMORY);
return;
}
if (nobj->trim) {
nurbs_trim *tmp_ptr;
for (tmp_ptr = nobj->trim; tmp_ptr->next; tmp_ptr = tmp_ptr->next);
tmp_ptr->next = ptr;
}
else
nobj->trim = ptr;
ptr->trim_loop = NULL;
ptr->segments = NULL;
ptr->next = NULL;
#endif
}
void GLAPIENTRY
gluPwlCurve(GLUnurbsObj * nobj, GLint count, GLfloat * array, GLint stride,
GLenum type)
{
#if 0
nurbs_trim *ptr1;
trim_list *ptr2;
#endif
if (nobj->nurbs_type == GLU_NURBS_CURVE) {
call_user_error(nobj, GLU_NURBS_ERROR9);
return;
}
if (nobj->nurbs_type == GLU_NURBS_NONE) {
call_user_error(nobj, GLU_NURBS_ERROR19);
return;
}
if (type != GLU_MAP1_TRIM_2 && type != GLU_MAP1_TRIM_3) {
call_user_error(nobj, GLU_NURBS_ERROR14);
return;
}
#if 0
for (ptr1 = nobj->trim; ptr1->next; ptr1 = ptr1->next);
if (ptr1->trim_loop) {
for (ptr2 = ptr1->trim_loop; ptr2->next; ptr2 = ptr2->next);
if ((ptr2->next = (trim_list *) malloc(sizeof(trim_list))) == NULL) {
call_user_error(nobj, GLU_OUT_OF_MEMORY);
return;
}
ptr2 = ptr2->next;
}
else {
if ((ptr2 = (trim_list *) malloc(sizeof(trim_list))) == NULL) {
call_user_error(nobj, GLU_OUT_OF_MEMORY);
return;
}
ptr1->trim_loop = ptr2;
}
ptr2->trim_type = GLU_TRIM_PWL;
ptr2->curve.pwl_curve.pt_count = count;
ptr2->curve.pwl_curve.ctrlarray = array;
ptr2->curve.pwl_curve.stride = stride;
ptr2->curve.pwl_curve.dim = (type == GLU_MAP1_TRIM_2 ? 2 : 3);
ptr2->curve.pwl_curve.type = type;
ptr2->next = NULL;
#endif
}
void GLAPIENTRY
gluEndTrim(GLUnurbsObj * nobj)
{
if (nobj->nurbs_type != GLU_NURBS_TRIM) {
call_user_error(nobj, GLU_NURBS_ERROR17);
return;
}
nobj->nurbs_type = GLU_NURBS_TRIM_DONE;
}

View file

@ -1,252 +0,0 @@
/*
* 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.
*/
/*
* NURBS implementation written by Bogdan Sikorski (bogdan@cira.it)
* See README2 for more info.
*/
#ifndef NURBS_H
#define NURBS_H
#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;
typedef 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;
typedef struct
{
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;
typedef struct
{
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;
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;
typedef struct seg_trim_str
{
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;
typedef struct
{
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;
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);
#endif

View file

@ -1,444 +0,0 @@
/*
* 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.
*/
/*
* NURBS implementation written by Bogdan Sikorski (bogdan@cira.it)
* See README2 for more info.
*/
#ifdef PC_HEADER
#include "all.h"
#else
#include <math.h>
#include <stdlib.h>
#include "gluP.h"
#include "nurbs.h"
#endif
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 */
}
static GLenum
test_nurbs_curve(GLUnurbsObj * nobj, curve_attribs * attribs)
{
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;
}
static GLenum
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;
}
/* 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)
{
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;
}
/* 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)
{
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;
}
/* 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)
{
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;
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;
}
/* main NURBS curve procedure */
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 = 0, *color_ctrl = 0, *normal_ctrl = 0, *texture_ctrl = 0;
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;
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;
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);
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,937 +0,0 @@
/*
* 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 = 0;
/* 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;
}

View file

@ -1,403 +0,0 @@
/*
* 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.
*/
#ifdef PC_HEADER
#include "all.h"
#else
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "gluP.h"
#endif
/*
* This code was contributed by Marc Buffat (buffat@mecaflu.ec-lyon.fr).
* Thanks Marc!!!
*/
/* implementation de gluProject et gluUnproject */
/* M. Buffat 17/2/95 */
/*
* Transform a point (column vector) by a 4x4 matrix. I.e. out = m * in
* Input: m - the 4x4 matrix
* 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])
{
#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];
#undef M
}
/*
* Perform a 4x4 matrix multiplication (product = a x b).
* Input: a, b - matrices to multiply
* Output: product - product of a and b
*/
static void
matmul(GLdouble * product, const GLdouble * a, const GLdouble * b)
{
/* This matmul was contributed by Thomas Malik */
GLdouble temp[16];
GLint i;
#define A(row,col) a[(col<<2)+row]
#define B(row,col) b[(col<<2)+row]
#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);
}
#undef A
#undef B
#undef T
MEMCPY(product, temp, 16 * sizeof(GLdouble));
}
/*
* Compute inverse of 4x4 transformation matrix.
* 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)
{
/* 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;
#undef MAT
#undef SWAP_ROWS
}
/* 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)
{
/* 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)
{
/* 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);
if (!invert_matrix(A, m))
return GL_FALSE;
/* 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;
}
/*
* 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)
{
/* 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);
if (!invert_matrix(A, m))
return GL_FALSE;
/* 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

View file

@ -1,819 +0,0 @@
/*
* Mesa 3-D graphics library
* Version: 3.3
* Copyright (C) 1999-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.
*/
/* TODO:
* texture coordinate support
* flip normals according to orientation
* there's still some inside/outside orientation bugs in possibly all
* but the sphere function
*/
#ifdef PC_HEADER
#include "all.h"
#else
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "gluP.h"
#endif
#ifndef M_PI
# define M_PI (3.1415926)
#endif
/*
* Convert degrees to radians:
*/
#define DEG_TO_RAD(A) ((A)*(M_PI/180.0))
/*
* Sin and Cos for degree angles:
*/
#define SIND( A ) sin( (A)*(M_PI/180.0) )
#define COSD( A) cos( (A)*(M_PI/180.0) )
/*
* Texture coordinates if texture flag is set
*/
#define TXTR_COORD(x,y) if (qobj->TextureFlag) glTexCoord2f(x,y);
struct GLUquadric
{
GLenum DrawStyle; /* GLU_FILL, LINE, SILHOUETTE, or POINT */
GLenum Orientation; /* GLU_INSIDE or GLU_OUTSIDE */
GLboolean TextureFlag; /* Generate texture coords? */
GLenum Normals; /* GLU_NONE, GLU_FLAT, or GLU_SMOOTH */
void (GLCALLBACK * ErrorFunc) (GLenum err); /* Error handler callback function */
};
/*
* Process a GLU error.
*/
static void
quadric_error(GLUquadricObj * qobj, GLenum error, const char *msg)
{
/* Call the error call back function if any */
if (qobj->ErrorFunc) {
(*qobj->ErrorFunc) (error);
}
/* Print a message to stdout if MESA_DEBUG variable is defined */
if (getenv("MESA_DEBUG")) {
fprintf(stderr, "GLUError: %s: %s\n", (char *) gluErrorString(error),
msg);
}
}
GLUquadricObj *GLAPIENTRY
gluNewQuadric(void)
{
GLUquadricObj *q;
q = (GLUquadricObj *) malloc(sizeof(struct GLUquadric));
if (q) {
q->DrawStyle = GLU_FILL;
q->Orientation = GLU_OUTSIDE;
q->TextureFlag = GL_FALSE;
q->Normals = GLU_SMOOTH;
q->ErrorFunc = NULL;
}
return q;
}
void GLAPIENTRY
gluDeleteQuadric(GLUquadricObj * state)
{
if (state) {
free((void *) state);
}
}
/*
* Set the drawing style to be GLU_FILL, GLU_LINE, GLU_SILHOUETTE,
* or GLU_POINT.
*/
void GLAPIENTRY
gluQuadricDrawStyle(GLUquadricObj * quadObject, GLenum drawStyle)
{
if (quadObject && (drawStyle == GLU_FILL || drawStyle == GLU_LINE
|| drawStyle == GLU_SILHOUETTE
|| drawStyle == GLU_POINT)) {
quadObject->DrawStyle = drawStyle;
}
else {
quadric_error(quadObject, GLU_INVALID_ENUM, "qluQuadricDrawStyle");
}
}
/*
* Set the orientation to GLU_INSIDE or GLU_OUTSIDE.
*/
void GLAPIENTRY
gluQuadricOrientation(GLUquadricObj * quadObject, GLenum orientation)
{
if (quadObject
&& (orientation == GLU_INSIDE || orientation == GLU_OUTSIDE)) {
quadObject->Orientation = orientation;
}
else {
quadric_error(quadObject, GLU_INVALID_ENUM, "qluQuadricOrientation");
}
}
/*
* Set the error handler callback function.
*/
void GLAPIENTRY
gluQuadricCallback(GLUquadricObj * qobj,
GLenum which, void (GLCALLBACK * fn) ())
{
/*
* UGH, this is a mess! I thought ANSI was a standard.
*/
if (qobj && which == GLU_ERROR) {
#ifdef __CYGWIN32__
qobj->ErrorFunc = (void (GLCALLBACKPCAST) (GLenum)) fn;
#elif defined(OPENSTEP)
qobj->ErrorFunc = (void (*)(GLenum)) fn;
#elif defined(_WIN32)
qobj->ErrorFunc = (void (GLCALLBACK *) (int)) fn;
#elif defined(__STORM__)
qobj->ErrorFunc = (void (GLCALLBACK *) (GLenum)) fn;
#elif defined(__BEOS__)
qobj->ErrorFunc = (void (*)(GLenum)) fn;
#else
qobj->ErrorFunc = (void (GLCALLBACK *) ()) fn;
#endif
}
}
void GLAPIENTRY
gluQuadricNormals(GLUquadricObj * quadObject, GLenum normals)
{
if (quadObject
&& (normals == GLU_NONE || normals == GLU_FLAT
|| normals == GLU_SMOOTH)) {
quadObject->Normals = normals;
}
}
void GLAPIENTRY
gluQuadricTexture(GLUquadricObj * quadObject, GLboolean textureCoords)
{
if (quadObject) {
quadObject->TextureFlag = textureCoords;
}
}
/*
* Call glNormal3f after scaling normal to unit length.
*/
static void
normal3f(GLfloat x, GLfloat y, GLfloat z)
{
GLdouble mag;
mag = sqrt(x * x + y * y + z * z);
if (mag > 0.00001F) {
x /= mag;
y /= mag;
z /= mag;
}
glNormal3f(x, y, z);
}
void GLAPIENTRY
gluCylinder(GLUquadricObj * qobj,
GLdouble baseRadius, GLdouble topRadius,
GLdouble height, GLint slices, GLint stacks)
{
GLdouble da, r, dr, dz;
GLfloat x, y, z, nz, nsign;
GLint i, j;
if (qobj->Orientation == GLU_INSIDE) {
nsign = -1.0;
}
else {
nsign = 1.0;
}
da = 2.0 * M_PI / slices;
dr = (topRadius - baseRadius) / stacks;
dz = height / stacks;
nz = (baseRadius - topRadius) / height; /* Z component of normal vectors */
if (qobj->DrawStyle == GLU_POINT) {
glBegin(GL_POINTS);
for (i = 0; i < slices; i++) {
x = cos(i * da);
y = sin(i * da);
normal3f(x * nsign, y * nsign, nz * nsign);
z = 0.0;
r = baseRadius;
for (j = 0; j <= stacks; j++) {
glVertex3f(x * r, y * r, z);
z += dz;
r += dr;
}
}
glEnd();
}
else if (qobj->DrawStyle == GLU_LINE || qobj->DrawStyle == GLU_SILHOUETTE) {
/* Draw rings */
if (qobj->DrawStyle == GLU_LINE) {
z = 0.0;
r = baseRadius;
for (j = 0; j <= stacks; j++) {
glBegin(GL_LINE_LOOP);
for (i = 0; i < slices; i++) {
x = cos(i * da);
y = sin(i * da);
normal3f(x * nsign, y * nsign, nz * nsign);
glVertex3f(x * r, y * r, z);
}
glEnd();
z += dz;
r += dr;
}
}
else {
/* draw one ring at each end */
if (baseRadius != 0.0) {
glBegin(GL_LINE_LOOP);
for (i = 0; i < slices; i++) {
x = cos(i * da);
y = sin(i * da);
normal3f(x * nsign, y * nsign, nz * nsign);
glVertex3f(x * baseRadius, y * baseRadius, 0.0);
}
glEnd();
glBegin(GL_LINE_LOOP);
for (i = 0; i < slices; i++) {
x = cos(i * da);
y = sin(i * da);
normal3f(x * nsign, y * nsign, nz * nsign);
glVertex3f(x * topRadius, y * topRadius, height);
}
glEnd();
}
}
/* draw length lines */
glBegin(GL_LINES);
for (i = 0; i < slices; i++) {
x = cos(i * da);
y = sin(i * da);
normal3f(x * nsign, y * nsign, nz * nsign);
glVertex3f(x * baseRadius, y * baseRadius, 0.0);
glVertex3f(x * topRadius, y * topRadius, height);
}
glEnd();
}
else if (qobj->DrawStyle == GLU_FILL) {
GLfloat ds = 1.0 / slices;
GLfloat dt = 1.0 / stacks;
GLfloat t = 0.0;
z = 0.0;
r = baseRadius;
for (j = 0; j < stacks; j++) {
GLfloat s = 0.0;
glBegin(GL_QUAD_STRIP);
for (i = 0; i <= slices; i++) {
GLfloat x, y;
if (i == slices) {
x = sin(0.0);
y = cos(0.0);
}
else {
x = sin(i * da);
y = cos(i * da);
}
if (nsign == 1.0) {
normal3f(x * nsign, y * nsign, nz * nsign);
TXTR_COORD(s, t);
glVertex3f(x * r, y * r, z);
normal3f(x * nsign, y * nsign, nz * nsign);
TXTR_COORD(s, t + dt);
glVertex3f(x * (r + dr), y * (r + dr), z + dz);
}
else {
normal3f(x * nsign, y * nsign, nz * nsign);
TXTR_COORD(s, t);
glVertex3f(x * r, y * r, z);
normal3f(x * nsign, y * nsign, nz * nsign);
TXTR_COORD(s, t + dt);
glVertex3f(x * (r + dr), y * (r + dr), z + dz);
}
s += ds;
} /* for slices */
glEnd();
r += dr;
t += dt;
z += dz;
} /* for stacks */
}
}
void GLAPIENTRY
gluSphere(GLUquadricObj * qobj, GLdouble radius, GLint slices, GLint stacks)
{
GLfloat rho, drho, theta, dtheta;
GLfloat x, y, z;
GLfloat s, t, ds, dt;
GLint i, j, imin, imax;
GLboolean normals;
GLfloat nsign;
if (qobj->Normals == GLU_NONE) {
normals = GL_FALSE;
}
else {
normals = GL_TRUE;
}
if (qobj->Orientation == GLU_INSIDE) {
nsign = -1.0;
}
else {
nsign = 1.0;
}
drho = M_PI / (GLfloat) stacks;
dtheta = 2.0 * M_PI / (GLfloat) slices;
/* texturing: s goes from 0.0/0.25/0.5/0.75/1.0 at +y/+x/-y/-x/+y axis */
/* t goes from -1.0/+1.0 at z = -radius/+radius (linear along longitudes) */
/* cannot use triangle fan on texturing (s coord. at top/bottom tip varies) */
if (qobj->DrawStyle == GLU_FILL) {
if (!qobj->TextureFlag) {
/* draw +Z end as a triangle fan */
glBegin(GL_TRIANGLE_FAN);
glNormal3f(0.0, 0.0, 1.0);
glVertex3f(0.0, 0.0, nsign * radius);
for (j = 0; j <= slices; j++) {
theta = (j == slices) ? 0.0 : j * dtheta;
x = -sin(theta) * sin(drho);
y = cos(theta) * sin(drho);
z = nsign * cos(drho);
if (normals)
glNormal3f(x * nsign, y * nsign, z * nsign);
glVertex3f(x * radius, y * radius, z * radius);
}
glEnd();
}
ds = 1.0 / slices;
dt = 1.0 / stacks;
t = 1.0; /* because loop now runs from 0 */
if (qobj->TextureFlag) {
imin = 0;
imax = stacks;
}
else {
imin = 1;
imax = stacks - 1;
}
/* draw intermediate stacks as quad strips */
for (i = imin; i < imax; i++) {
rho = i * drho;
glBegin(GL_QUAD_STRIP);
s = 0.0;
for (j = 0; j <= slices; j++) {
theta = (j == slices) ? 0.0 : j * dtheta;
x = -sin(theta) * sin(rho);
y = cos(theta) * sin(rho);
z = nsign * cos(rho);
if (normals)
glNormal3f(x * nsign, y * nsign, z * nsign);
TXTR_COORD(s, t);
glVertex3f(x * radius, y * radius, z * radius);
x = -sin(theta) * sin(rho + drho);
y = cos(theta) * sin(rho + drho);
z = nsign * cos(rho + drho);
if (normals)
glNormal3f(x * nsign, y * nsign, z * nsign);
TXTR_COORD(s, t - dt);
s += ds;
glVertex3f(x * radius, y * radius, z * radius);
}
glEnd();
t -= dt;
}
if (!qobj->TextureFlag) {
/* draw -Z end as a triangle fan */
glBegin(GL_TRIANGLE_FAN);
glNormal3f(0.0, 0.0, -1.0);
glVertex3f(0.0, 0.0, -radius * nsign);
rho = M_PI - drho;
s = 1.0;
t = dt;
for (j = slices; j >= 0; j--) {
theta = (j == slices) ? 0.0 : j * dtheta;
x = -sin(theta) * sin(rho);
y = cos(theta) * sin(rho);
z = nsign * cos(rho);
if (normals)
glNormal3f(x * nsign, y * nsign, z * nsign);
s -= ds;
glVertex3f(x * radius, y * radius, z * radius);
}
glEnd();
}
}
else if (qobj->DrawStyle == GLU_LINE || qobj->DrawStyle == GLU_SILHOUETTE) {
/* draw stack lines */
for (i = 1; i < stacks; i++) { /* stack line at i==stacks-1 was missing here */
rho = i * drho;
glBegin(GL_LINE_LOOP);
for (j = 0; j < slices; j++) {
theta = j * dtheta;
x = cos(theta) * sin(rho);
y = sin(theta) * sin(rho);
z = cos(rho);
if (normals)
glNormal3f(x * nsign, y * nsign, z * nsign);
glVertex3f(x * radius, y * radius, z * radius);
}
glEnd();
}
/* draw slice lines */
for (j = 0; j < slices; j++) {
theta = j * dtheta;
glBegin(GL_LINE_STRIP);
for (i = 0; i <= stacks; i++) {
rho = i * drho;
x = cos(theta) * sin(rho);
y = sin(theta) * sin(rho);
z = cos(rho);
if (normals)
glNormal3f(x * nsign, y * nsign, z * nsign);
glVertex3f(x * radius, y * radius, z * radius);
}
glEnd();
}
}
else if (qobj->DrawStyle == GLU_POINT) {
/* top and bottom-most points */
glBegin(GL_POINTS);
if (normals)
glNormal3f(0.0, 0.0, nsign);
glVertex3d(0.0, 0.0, radius);
if (normals)
glNormal3f(0.0, 0.0, -nsign);
glVertex3d(0.0, 0.0, -radius);
/* loop over stacks */
for (i = 1; i < stacks - 1; i++) {
rho = i * drho;
for (j = 0; j < slices; j++) {
theta = j * dtheta;
x = cos(theta) * sin(rho);
y = sin(theta) * sin(rho);
z = cos(rho);
if (normals)
glNormal3f(x * nsign, y * nsign, z * nsign);
glVertex3f(x * radius, y * radius, z * radius);
}
}
glEnd();
}
}
void GLAPIENTRY
gluDisk(GLUquadricObj * qobj,
GLdouble innerRadius, GLdouble outerRadius, GLint slices, GLint loops)
{
GLfloat da, dr;
#if 0
GLdouble a, da;
GLfloat r, dr;
GLfloat x, y;
GLfloat r1, r2, dtc;
GLint s, l;
#endif
/* Normal vectors */
if (qobj->Normals != GLU_NONE) {
if (qobj->Orientation == GLU_OUTSIDE) {
glNormal3f(0.0, 0.0, +1.0);
}
else {
glNormal3f(0.0, 0.0, -1.0);
}
}
da = 2.0 * M_PI / slices;
dr = (outerRadius - innerRadius) / (GLfloat) loops;
switch (qobj->DrawStyle) {
case GLU_FILL:
{
/* texture of a gluDisk is a cut out of the texture unit square
* x, y in [-outerRadius, +outerRadius]; s, t in [0, 1]
* (linear mapping)
*/
GLfloat dtc = 2.0f * outerRadius;
GLfloat sa, ca;
GLfloat r1 = innerRadius;
GLint l;
for (l = 0; l < loops; l++) {
GLfloat r2 = r1 + dr;
if (qobj->Orientation == GLU_OUTSIDE) {
GLint s;
glBegin(GL_QUAD_STRIP);
for (s = 0; s <= slices; s++) {
GLfloat a;
if (s == slices)
a = 0.0;
else
a = s * da;
sa = sin(a);
ca = cos(a);
TXTR_COORD(0.5 + sa * r2 / dtc, 0.5 + ca * r2 / dtc);
glVertex2f(r2 * sa, r2 * ca);
TXTR_COORD(0.5 + sa * r1 / dtc, 0.5 + ca * r1 / dtc);
glVertex2f(r1 * sa, r1 * ca);
}
glEnd();
}
else {
GLint s;
glBegin(GL_QUAD_STRIP);
for (s = slices; s >= 0; s--) {
GLfloat a;
if (s == slices)
a = 0.0;
else
a = s * da;
sa = sin(a);
ca = cos(a);
TXTR_COORD(0.5 - sa * r2 / dtc, 0.5 + ca * r2 / dtc);
glVertex2f(r2 * sa, r2 * ca);
TXTR_COORD(0.5 - sa * r1 / dtc, 0.5 + ca * r1 / dtc);
glVertex2f(r1 * sa, r1 * ca);
}
glEnd();
}
r1 = r2;
}
break;
}
case GLU_LINE:
{
GLint l, s;
/* draw loops */
for (l = 0; l <= loops; l++) {
GLfloat r = innerRadius + l * dr;
glBegin(GL_LINE_LOOP);
for (s = 0; s < slices; s++) {
GLfloat a = s * da;
glVertex2f(r * sin(a), r * cos(a));
}
glEnd();
}
/* draw spokes */
for (s = 0; s < slices; s++) {
GLfloat a = s * da;
GLfloat x = sin(a);
GLfloat y = cos(a);
glBegin(GL_LINE_STRIP);
for (l = 0; l <= loops; l++) {
GLfloat r = innerRadius + l * dr;
glVertex2f(r * x, r * y);
}
glEnd();
}
break;
}
case GLU_POINT:
{
GLint s;
glBegin(GL_POINTS);
for (s = 0; s < slices; s++) {
GLfloat a = s * da;
GLfloat x = sin(a);
GLfloat y = cos(a);
GLint l;
for (l = 0; l <= loops; l++) {
GLfloat r = innerRadius * l * dr;
glVertex2f(r * x, r * y);
}
}
glEnd();
break;
}
case GLU_SILHOUETTE:
{
if (innerRadius != 0.0) {
GLfloat a;
glBegin(GL_LINE_LOOP);
for (a = 0.0; a < 2.0 * M_PI; a += da) {
GLfloat x = innerRadius * sin(a);
GLfloat y = innerRadius * cos(a);
glVertex2f(x, y);
}
glEnd();
}
{
GLfloat a;
glBegin(GL_LINE_LOOP);
for (a = 0; a < 2.0 * M_PI; a += da) {
GLfloat x = outerRadius * sin(a);
GLfloat y = outerRadius * cos(a);
glVertex2f(x, y);
}
glEnd();
}
break;
}
default:
abort();
}
}
void GLAPIENTRY
gluPartialDisk(GLUquadricObj * qobj, GLdouble innerRadius,
GLdouble outerRadius, GLint slices, GLint loops,
GLdouble startAngle, GLdouble sweepAngle)
{
if (qobj->Normals != GLU_NONE) {
if (qobj->Orientation == GLU_OUTSIDE) {
glNormal3f(0.0, 0.0, +1.0);
}
else {
glNormal3f(0.0, 0.0, -1.0);
}
}
if (qobj->DrawStyle == GLU_POINT) {
GLint loop, slice;
GLdouble radius, delta_radius;
GLdouble angle, delta_angle;
delta_radius = (outerRadius - innerRadius) / (loops - 1);
delta_angle = DEG_TO_RAD((sweepAngle) / (slices - 1));
glBegin(GL_POINTS);
radius = innerRadius;
for (loop = 0; loop < loops; loop++) {
angle = DEG_TO_RAD(startAngle);
for (slice = 0; slice < slices; slice++) {
glVertex2d(radius * sin(angle), radius * cos(angle));
angle += delta_angle;
}
radius += delta_radius;
}
glEnd();
}
else if (qobj->DrawStyle == GLU_LINE) {
GLint loop, slice;
GLdouble radius, delta_radius;
GLdouble angle, delta_angle;
delta_radius = (outerRadius - innerRadius) / loops;
delta_angle = DEG_TO_RAD(sweepAngle / slices);
/* draw rings */
radius = innerRadius;
for (loop = 0; loop < loops; loop++) {
angle = DEG_TO_RAD(startAngle);
glBegin(GL_LINE_STRIP);
for (slice = 0; slice <= slices; slice++) {
glVertex2d(radius * sin(angle), radius * cos(angle));
angle += delta_angle;
}
glEnd();
radius += delta_radius;
}
/* draw spokes */
angle = DEG_TO_RAD(startAngle);
for (slice = 0; slice <= slices; slice++) {
radius = innerRadius;
glBegin(GL_LINE_STRIP);
for (loop = 0; loop < loops; loop++) {
glVertex2d(radius * sin(angle), radius * cos(angle));
radius += delta_radius;
}
glEnd();
angle += delta_angle;
}
}
else if (qobj->DrawStyle == GLU_SILHOUETTE) {
GLint slice;
GLdouble angle, delta_angle;
delta_angle = DEG_TO_RAD(sweepAngle / slices);
/* draw outer ring */
glBegin(GL_LINE_STRIP);
angle = DEG_TO_RAD(startAngle);
for (slice = 0; slice <= slices; slice++) {
glVertex2d(outerRadius * sin(angle), outerRadius * cos(angle));
angle += delta_angle;
}
glEnd();
/* draw inner ring */
if (innerRadius > 0.0) {
glBegin(GL_LINE_STRIP);
angle = DEG_TO_RAD(startAngle);
for (slice = 0; slice < slices; slice++) {
glVertex2d(innerRadius * sin(angle), innerRadius * cos(angle));
angle += delta_angle;
}
glEnd();
}
/* draw spokes */
if (sweepAngle < 360.0) {
GLdouble stopAngle = startAngle + sweepAngle;
glBegin(GL_LINES);
glVertex2d(innerRadius * SIND(startAngle),
innerRadius * COSD(startAngle));
glVertex2d(outerRadius * SIND(startAngle),
outerRadius * COSD(startAngle));
glVertex2d(innerRadius * SIND(stopAngle),
innerRadius * COSD(stopAngle));
glVertex2d(outerRadius * SIND(stopAngle),
outerRadius * COSD(stopAngle));
glEnd();
}
}
else if (qobj->DrawStyle == GLU_FILL) {
GLint loop, slice;
GLdouble radius, delta_radius;
GLdouble angle, delta_angle;
delta_radius = (outerRadius - innerRadius) / loops;
delta_angle = DEG_TO_RAD(sweepAngle / slices);
radius = innerRadius;
for (loop = 0; loop < loops; loop++) {
glBegin(GL_QUAD_STRIP);
angle = DEG_TO_RAD(startAngle);
for (slice = 0; slice <= slices; slice++) {
if (qobj->Orientation == GLU_OUTSIDE) {
glVertex2d((radius + delta_radius) * sin(angle),
(radius + delta_radius) * cos(angle));
glVertex2d(radius * sin(angle), radius * cos(angle));
}
else {
glVertex2d(radius * sin(angle), radius * cos(angle));
glVertex2d((radius + delta_radius) * sin(angle),
(radius + delta_radius) * cos(angle));
}
angle += delta_angle;
}
glEnd();
radius += delta_radius;
}
}
}

View file

@ -1,327 +0,0 @@
/*
* 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 "tess.h"
#endif
/*
* This is ugly, but seems the easiest way to do things to make the
* code work under YellowBox for Windows
*/
#if defined(OPENSTEP) && defined(CALLBACK)
#undef CALLBACK
#define CALLBACK
#endif
static void delete_contours(GLUtriangulatorObj *);
#ifdef __CYGWIN32__
#define _CALLBACK
#else
#define _CALLBACK GLCALLBACK
#endif
static void
init_callbacks(tess_callbacks * callbacks)
{
callbacks->begin = (void (_CALLBACK *) (GLenum)) 0;
callbacks->edgeFlag = (void (_CALLBACK *) (GLboolean)) 0;
callbacks->vertex = (void (_CALLBACK *) (void *)) 0;
callbacks->end = (void (_CALLBACK *) (void)) 0;
callbacks->error = (void (_CALLBACK *) (GLenum)) 0;
}
void
tess_call_user_error(GLUtriangulatorObj * tobj, GLenum gluerr)
{
if (tobj->error == GLU_NO_ERROR)
tobj->error = gluerr;
if (tobj->callbacks.error != NULL)
(tobj->callbacks.error) (gluerr);
}
GLUtriangulatorObj *GLAPIENTRY
gluNewTess(void)
{
GLUtriangulatorObj *tobj;
if ((tobj = (GLUtriangulatorObj *)
malloc(sizeof(struct GLUtesselator))) == NULL)
return NULL;
tobj->contours = tobj->last_contour = NULL;
init_callbacks(&tobj->callbacks);
tobj->error = GLU_NO_ERROR;
tobj->current_polygon = NULL;
tobj->contour_cnt = 0;
return tobj;
}
void GLAPIENTRY
gluTessCallback(GLUtriangulatorObj * tobj, GLenum which,
void (GLCALLBACK * fn) ())
{
switch (which) {
case GLU_BEGIN:
tobj->callbacks.begin = (void (_CALLBACK *) (GLenum)) fn;
break;
case GLU_EDGE_FLAG:
tobj->callbacks.edgeFlag = (void (_CALLBACK *) (GLboolean)) fn;
break;
case GLU_VERTEX:
tobj->callbacks.vertex = (void (_CALLBACK *) (void *)) fn;
break;
case GLU_END:
tobj->callbacks.end = (void (_CALLBACK *) (void)) fn;
break;
case GLU_ERROR:
tobj->callbacks.error = (void (_CALLBACK *) (GLenum)) fn;
break;
default:
tobj->error = GLU_INVALID_ENUM;
break;
}
}
void GLAPIENTRY
gluDeleteTess(GLUtriangulatorObj * tobj)
{
if (tobj->error == GLU_NO_ERROR && tobj->contour_cnt)
/* was gluEndPolygon called? */
tess_call_user_error(tobj, GLU_TESS_ERROR1);
/* delete all internal structures */
delete_contours(tobj);
free(tobj);
}
void GLAPIENTRY
gluBeginPolygon(GLUtriangulatorObj * tobj)
{
/*
if(tobj->error!=GLU_NO_ERROR)
return;
*/
tobj->error = GLU_NO_ERROR;
if (tobj->current_polygon != NULL) {
/* gluEndPolygon was not called */
tess_call_user_error(tobj, GLU_TESS_ERROR1);
/* delete all internal structures */
delete_contours(tobj);
}
else {
if ((tobj->current_polygon =
(tess_polygon *) malloc(sizeof(tess_polygon))) == NULL) {
tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
return;
}
tobj->current_polygon->vertex_cnt = 0;
tobj->current_polygon->vertices =
tobj->current_polygon->last_vertex = NULL;
}
}
void GLAPIENTRY
gluEndPolygon(GLUtriangulatorObj * tobj)
{
/*tess_contour *contour_ptr; */
/* there was an error */
if (tobj->error != GLU_NO_ERROR)
goto end;
/* check if gluBeginPolygon was called */
if (tobj->current_polygon == NULL) {
tess_call_user_error(tobj, GLU_TESS_ERROR2);
return;
}
tess_test_polygon(tobj);
/* there was an error */
if (tobj->error != GLU_NO_ERROR)
goto end;
/* any real contours? */
if (tobj->contour_cnt == 0) {
/* delete all internal structures */
delete_contours(tobj);
return;
}
tess_find_contour_hierarchies(tobj);
/* there was an error */
if (tobj->error != GLU_NO_ERROR)
goto end;
tess_handle_holes(tobj);
/* there was an error */
if (tobj->error != GLU_NO_ERROR)
goto end;
/* if no callbacks, nothing to do */
if (tobj->callbacks.begin != NULL && tobj->callbacks.vertex != NULL &&
tobj->callbacks.end != NULL) {
if (tobj->callbacks.edgeFlag == NULL)
tess_tesselate(tobj);
else
tess_tesselate_with_edge_flag(tobj);
}
end:
/* delete all internal structures */
delete_contours(tobj);
}
void GLAPIENTRY
gluNextContour(GLUtriangulatorObj * tobj, GLenum type)
{
if (tobj->error != GLU_NO_ERROR)
return;
if (tobj->current_polygon == NULL) {
tess_call_user_error(tobj, GLU_TESS_ERROR2);
return;
}
/* first contour? */
if (tobj->current_polygon->vertex_cnt)
tess_test_polygon(tobj);
}
void GLAPIENTRY
gluTessVertex(GLUtriangulatorObj * tobj, GLdouble v[3], void *data)
{
tess_polygon *polygon = tobj->current_polygon;
tess_vertex *last_vertex_ptr;
if (tobj->error != GLU_NO_ERROR)
return;
if (polygon == NULL) {
tess_call_user_error(tobj, GLU_TESS_ERROR2);
return;
}
last_vertex_ptr = polygon->last_vertex;
if (last_vertex_ptr == NULL) {
if ((last_vertex_ptr = (tess_vertex *)
malloc(sizeof(tess_vertex))) == NULL) {
tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
return;
}
polygon->vertices = last_vertex_ptr;
polygon->last_vertex = last_vertex_ptr;
last_vertex_ptr->data = data;
last_vertex_ptr->location[0] = v[0];
last_vertex_ptr->location[1] = v[1];
last_vertex_ptr->location[2] = v[2];
last_vertex_ptr->next = NULL;
last_vertex_ptr->previous = NULL;
++(polygon->vertex_cnt);
}
else {
tess_vertex *vertex_ptr;
/* same point twice? */
if (fabs(last_vertex_ptr->location[0] - v[0]) < EPSILON &&
fabs(last_vertex_ptr->location[1] - v[1]) < EPSILON &&
fabs(last_vertex_ptr->location[2] - v[2]) < EPSILON) {
tess_call_user_error(tobj, GLU_TESS_ERROR6);
return;
}
if ((vertex_ptr = (tess_vertex *)
malloc(sizeof(tess_vertex))) == NULL) {
tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
return;
}
vertex_ptr->data = data;
vertex_ptr->location[0] = v[0];
vertex_ptr->location[1] = v[1];
vertex_ptr->location[2] = v[2];
vertex_ptr->next = NULL;
vertex_ptr->previous = last_vertex_ptr;
++(polygon->vertex_cnt);
last_vertex_ptr->next = vertex_ptr;
polygon->last_vertex = vertex_ptr;
}
}
static void
delete_contours(GLUtriangulatorObj * tobj)
{
tess_polygon *polygon = tobj->current_polygon;
tess_contour *contour, *contour_tmp;
tess_vertex *vertex, *vertex_tmp;
/* remove current_polygon list - if exists due to detected error */
if (polygon != NULL) {
if (polygon->vertices) {
for (vertex = polygon->vertices; vertex != polygon->last_vertex;) {
vertex_tmp = vertex->next;
free(vertex);
vertex = vertex_tmp;
}
free(vertex);
}
free(polygon);
tobj->current_polygon = NULL;
}
/* remove all contour data */
for (contour = tobj->contours; contour != NULL;) {
for (vertex = contour->vertices; vertex != contour->last_vertex;) {
vertex_tmp = vertex->next;
free(vertex);
vertex = vertex_tmp;
}
free(vertex);
contour_tmp = contour->next;
free(contour);
contour = contour_tmp;
}
tobj->contours = tobj->last_contour = NULL;
tobj->contour_cnt = 0;
}
void GLAPIENTRY
gluTessNormal(GLUtesselator *tess, GLdouble valueX, GLdouble valueY, GLdouble valueZ)
{
/* dummy function */
(void) tess;
(void) valueX;
(void) valueY;
(void) valueZ;
}

View file

@ -1,107 +0,0 @@
/*
* 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
*/
#ifndef TESS_H
#define TESS_H
#include "gluP.h"
#define EPSILON 1e-06 /* epsilon for double precision compares */
typedef enum
{
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;
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;
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;
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 GLUtesselator
{
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;
};
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 *);
#endif

View file

@ -1,406 +0,0 @@
/*
* 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) ();
}

View file

@ -1,54 +0,0 @@
/*
* 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 includes all .h files needed for the GLU source code for
* the purpose of precompiled headers.
*
* If the preprocessor symbol PCH is defined at compile time then each
* of the .c files will #include "all.h" only, instead of a bunch of
* individual .h files.
*/
#ifndef GLU_ALL_H
#define GLU_ALL_H
#ifndef PC_HEADER
This is an error. all.h should be included only if PCH is defined.
#endif
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "GL/gl.h"
#include "GL/glu.h"
#include "gluP.h"
#include "nurbs.h"
#include "tess.h"
#endif /*GLU_ALL_H */

View file

@ -1,416 +0,0 @@
/*
* Mesa 3-D graphics library
* Version: 3.5
* Copyright (C) 1995-2001 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.
*/
#ifdef PC_HEADER
#include "all.h"
#else
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "gluP.h"
#endif
/*
* Miscellaneous utility functions
*/
#ifndef M_PI
#define M_PI 3.1415926536
#endif
#define EPS 0.00001
#ifndef GLU_INCOMPATIBLE_GL_VERSION
#define GLU_INCOMPATIBLE_GL_VERSION 100903
#endif
void GLAPIENTRY
gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez,
GLdouble centerx, GLdouble centery, GLdouble centerz,
GLdouble upx, GLdouble upy, GLdouble upz)
{
GLfloat m[16];
GLfloat x[3], y[3], z[3];
GLfloat mag;
/* Make rotation matrix */
/* Z vector */
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 */
z[0] /= mag;
z[1] /= mag;
z[2] /= mag;
}
/* Y vector */
y[0] = upx;
y[1] = upy;
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];
/* 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];
/* 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]);
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]);
if (mag) {
y[0] /= mag;
y[1] /= mag;
y[2] /= mag;
}
#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;
#undef M
glMultMatrixf(m);
/* Translate Eye to Origin */
glTranslatef(-eyex, -eyey, -eyez);
}
void GLAPIENTRY
gluOrtho2D(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top)
{
glOrtho(left, right, bottom, top, -1.0, 1.0);
}
static void
frustum(GLfloat left, GLfloat right,
GLfloat bottom, GLfloat top,
GLfloat nearval, GLfloat farval)
{
GLfloat x, y, a, b, c, d;
GLfloat m[16];
x = (2.0 * nearval) / (right - left);
y = (2.0 * nearval) / (top - bottom);
a = (right + left) / (right - left);
b = (top + bottom) / (top - bottom);
c = -(farval + nearval) / ( farval - nearval);
d = -(2.0 * farval * nearval) / (farval - nearval);
#define M(row,col) m[col*4+row]
M(0,0) = x; M(0,1) = 0.0F; M(0,2) = a; M(0,3) = 0.0F;
M(1,0) = 0.0F; M(1,1) = y; M(1,2) = b; M(1,3) = 0.0F;
M(2,0) = 0.0F; M(2,1) = 0.0F; M(2,2) = c; M(2,3) = d;
M(3,0) = 0.0F; M(3,1) = 0.0F; M(3,2) = -1.0F; M(3,3) = 0.0F;
#undef M
glMultMatrixf(m);
}
void GLAPIENTRY
gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar)
{
GLfloat xmin, xmax, ymin, ymax;
ymax = zNear * tan(fovy * M_PI / 360.0);
ymin = -ymax;
xmin = ymin * aspect;
xmax = ymax * aspect;
/* don't call glFrustum() because of error semantics (covglu) */
frustum(xmin, xmax, ymin, ymax, zNear, zFar);
}
void GLAPIENTRY
gluPickMatrix(GLdouble x, GLdouble y,
GLdouble width, GLdouble height, GLint viewport[4])
{
GLfloat m[16];
GLfloat sx, sy;
GLfloat tx, ty;
sx = viewport[2] / width;
sy = viewport[3] / height;
tx = (viewport[2] + 2.0 * (viewport[0] - x)) / width;
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;
#undef M
glMultMatrixf(m);
}
const GLubyte *GLAPIENTRY
gluErrorString(GLenum errorCode)
{
static char *tess_error[] = {
"missing gluBeginPolygon",
"missing gluBeginContour",
"missing gluEndPolygon",
"missing gluEndContour",
"misoriented or self-intersecting loops",
"coincident vertices",
"colinear vertices",
"FIST recovery process fatal error"
};
static char *nurbs_error[] = {
"spline order un-supported",
"too few knots",
"valid knot range is empty",
"decreasing knot sequence knot",
"knot multiplicity greater than order of spline",
"endcurve() must follow bgncurve()",
"bgncurve() must precede endcurve()",
"missing or extra geometric data",
"can't draw pwlcurves",
"missing bgncurve()",
"missing bgnsurface()",
"endtrim() must precede endsurface()",
"bgnsurface() must precede endsurface()",
"curve of improper type passed as trim curve",
"bgnsurface() must precede bgntrim()",
"endtrim() must follow bgntrim()",
"bgntrim() must precede endtrim()",
"invalid or missing trim curve",
"bgntrim() must precede pwlcurve()",
"pwlcurve referenced twice",
"pwlcurve and nurbscurve mixed",
"improper usage of trim data type",
"nurbscurve referenced twice",
"nurbscurve and pwlcurve mixed",
"nurbssurface referenced twice",
"invalid property",
"endsurface() must follow bgnsurface()",
"misoriented trim curves",
"intersecting trim curves",
"UNUSED",
"unconnected trim curves",
"unknown knot error",
"negative vertex count encountered",
"negative byte-stride encountered",
"unknown type descriptor",
"null control array or knot vector",
"duplicate point on pwlcurve"
};
/* GL Errors */
if (errorCode == GL_NO_ERROR) {
return (GLubyte *) "no error";
}
else if (errorCode == GL_INVALID_VALUE) {
return (GLubyte *) "invalid value";
}
else if (errorCode == GL_INVALID_ENUM) {
return (GLubyte *) "invalid enum";
}
else if (errorCode == GL_INVALID_OPERATION) {
return (GLubyte *) "invalid operation";
}
else if (errorCode == GL_STACK_OVERFLOW) {
return (GLubyte *) "stack overflow";
}
else if (errorCode == GL_STACK_UNDERFLOW) {
return (GLubyte *) "stack underflow";
}
else if (errorCode == GL_OUT_OF_MEMORY) {
return (GLubyte *) "out of memory";
}
/* GLU Errors */
else if (errorCode == GLU_NO_ERROR) {
return (GLubyte *) "no error";
}
else if (errorCode == GLU_INVALID_ENUM) {
return (GLubyte *) "invalid enum";
}
else if (errorCode == GLU_INVALID_VALUE) {
return (GLubyte *) "invalid value";
}
else if (errorCode == GLU_OUT_OF_MEMORY) {
return (GLubyte *) "out of memory";
}
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_NURBS_ERROR1 && errorCode <= GLU_NURBS_ERROR37) {
return (GLubyte *) nurbs_error[errorCode - GLU_NURBS_ERROR1];
}
else {
return NULL;
}
}
/*
* New in GLU 1.1
*/
const GLubyte *GLAPIENTRY
gluGetString(GLenum name)
{
static char *extensions = "GL_EXT_abgr";
static char *version = "1.1 Mesa 3.5";
switch (name) {
case GLU_EXTENSIONS:
return (GLubyte *) extensions;
case GLU_VERSION:
return (GLubyte *) version;
default:
return NULL;
}
}
#if 0 /* gluGetProcAddressEXT not finalized yet! */
#ifdef __cplusplus
/* for BeOS R4.5 */
void GLAPIENTRY(*gluGetProcAddressEXT(const GLubyte * procName)) (...)
#else
void (GLAPIENTRY * gluGetProcAddressEXT(const GLubyte * procName)) ()
#endif
{
struct proc
{
const char *name;
void *address;
};
static struct proc procTable[] = {
{"gluGetProcAddressEXT", (void *) gluGetProcAddressEXT}, /* me! */
/* new 1.1 functions */
{"gluGetString", (void *) gluGetString},
/* new 1.2 functions */
{"gluTessBeginPolygon", (void *) gluTessBeginPolygon},
{"gluTessBeginContour", (void *) gluTessBeginContour},
{"gluTessEndContour", (void *) gluTessEndContour},
{"gluTessEndPolygon", (void *) gluTessEndPolygon},
{"gluGetTessProperty", (void *) gluGetTessProperty},
/* new 1.3 functions */
{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 NULL;
}
#endif
/*
* New in GLU 1.3
*/
#ifdef GLU_VERSION_1_3
GLboolean GLAPIENTRY
gluCheckExtension(const GLubyte *extName, const GLubyte * extString)
{
assert(extName);
assert(extString);
{
const int len = strlen((const char *) extName);
const char *start = (const char *) extString;
while (1) {
const char *c = strstr(start, (const char *) extName);
if (!c)
return GL_FALSE;
if ((c == start || c[-1] == ' ') && (c[len] == ' ' || c[len] == 0))
return GL_TRUE;
start = c + len;
}
}
}
#endif

View file

@ -1,141 +0,0 @@
/*
* 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 allows the GLU code to be compiled either with the Mesa
* headers or with the real OpenGL headers.
*/
#ifndef GLUP_H
#define GLUP_H
#include <GL/gl.h>
#include <GL/glu.h>
#include <string.h>
#if defined(_WIN32) && !defined(__WIN32__)
# define __WIN32__
#endif
#if !defined(OPENSTEP) && (defined(__WIN32__) || defined(__CYGWIN__))
# pragma warning( disable : 4068 ) /* unknown pragma */
# pragma warning( disable : 4710 ) /* function 'foo' not inlined */
# pragma warning( disable : 4711 ) /* function 'foo' selected for automatic inline expansion */
# pragma warning( disable : 4127 ) /* conditional expression is constant */
# if defined(MESA_MINWARN)
# pragma warning( disable : 4244 ) /* '=' : conversion from 'const double ' to 'float ', possible loss of data */
# pragma warning( disable : 4018 ) /* '<' : signed/unsigned mismatch */
# pragma warning( disable : 4305 ) /* '=' : truncation from 'const double ' to 'float ' */
# pragma warning( disable : 4550 ) /* 'function' undefined; assuming extern returning int */
# pragma warning( disable : 4761 ) /* integral size mismatch in argument; conversion supplied */
# endif
# if defined(_MSC_VER) && defined(BUILD_GL32) /* tag specify we're building mesa as a DLL */
# define GLAPI __declspec(dllexport)
# define WGLAPI __declspec(dllexport)
# elif defined(_MSC_VER) && defined(_DLL) /* tag specifying we're building for DLL runtime support */
# define GLAPI __declspec(dllimport)
# define WGLAPI __declspec(dllimport)
# else /* for use with static link lib build of Win32 edition only */
# define GLAPI extern
# define WGLAPI __declspec(dllimport)
# endif /* _STATIC_MESA support */
# define GLAPIENTRY __stdcall
# define GLAPIENTRYP __stdcall *
# define GLCALLBACK __stdcall
# define GLCALLBACKP __stdcall *
# if defined(__CYGWIN__)
# define GLCALLBACKPCAST *
# else
# define GLCALLBACKPCAST __stdcall *
# endif
# define GLWINAPI __stdcall
# define GLWINAPIV __cdecl
#else
/* non-Windows compilation */
# define GLAPI extern
# define GLAPIENTRY
# define GLAPIENTRYP *
# define GLCALLBACK
# define GLCALLBACKP *
# define GLCALLBACKPCAST *
# define GLWINAPI
# define GLWINAPIV
#endif /* WIN32 / CYGWIN bracket */
/* compatibility guard so we don't need to change client code */
#if defined(_WIN32) && !defined(_WINDEF_) && !defined(_GNU_H_WINDOWS32_BASE) && !defined(OPENSTEP)
# define CALLBACK GLCALLBACK
typedef int (GLAPIENTRY *PROC)();
typedef void *HGLRC;
typedef void *HDC;
typedef unsigned long COLORREF;
#endif
#if defined(_WIN32) && !defined(_WINGDI_) && !defined(_GNU_H_WINDOWS32_DEFINES) && !defined(OPENSTEP)
# define WGL_FONT_LINES 0
# define WGL_FONT_POLYGONS 1
#ifndef _GNU_H_WINDOWS32_FUNCTIONS
# ifdef UNICODE
# define wglUseFontBitmaps wglUseFontBitmapsW
# define wglUseFontOutlines wglUseFontOutlinesW
# else
# define wglUseFontBitmaps wglUseFontBitmapsA
# define wglUseFontOutlines wglUseFontOutlinesA
# endif /* !UNICODE */
#endif /* _GNU_H_WINDOWS32_FUNCTIONS */
typedef struct tagLAYERPLANEDESCRIPTOR LAYERPLANEDESCRIPTOR, *PLAYERPLANEDESCRIPTOR, *LPLAYERPLANEDESCRIPTOR;
typedef struct _GLYPHMETRICSFLOAT GLYPHMETRICSFLOAT, *PGLYPHMETRICSFLOAT, *LPGLYPHMETRICSFLOAT;
typedef struct tagPIXELFORMATDESCRIPTOR PIXELFORMATDESCRIPTOR, *PPIXELFORMATDESCRIPTOR, *LPPIXELFORMATDESCRIPTOR;
#include <gl/mesa_wgl.h>
#endif
#ifndef GLU_TESS_ERROR9
/* If we're using the real OpenGL header files... */
# define GLU_TESS_ERROR9 100159
#endif
#define GLU_NO_ERROR GL_NO_ERROR
/* for Sun: */
#ifdef SUNOS4
#define MEMCPY( DST, SRC, BYTES) \
memcpy( (char *) (DST), (char *) (SRC), (int) (BYTES) )
#else
#define MEMCPY( DST, SRC, BYTES) \
memcpy( (void *) (DST), (void *) (SRC), (size_t) (BYTES) )
#endif
#ifndef NULL
# define NULL 0
#endif
#endif

View file

@ -1,767 +0,0 @@
/*
* Mesa 3-D graphics library
* Version: 3.4
* 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.
*/
#ifdef PC_HEADER
#include "all.h"
#else
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "gluP.h"
#endif
/*
* Compute ceiling of integer quotient of A divided by B:
*/
#define CEILING( A, B ) ( (A) % (B) == 0 ? (A)/(B) : (A)/(B)+1 )
#ifdef EPSILON
#undef EPSILON
#endif
#define EPSILON 0.001
/* To work around optimizer bug in MSVC4.1 */
#if defined(__WIN32__) && !defined(OPENSTEP)
void
dummy(GLuint j, GLuint k)
{
}
#else
#define dummy(J, K)
#endif
GLint GLAPIENTRY
gluScaleImage(GLenum format,
GLsizei widthin, GLsizei heightin,
GLenum typein, const void *datain,
GLsizei widthout, GLsizei heightout,
GLenum typeout, void *dataout)
{
GLint components, i, j, k;
GLfloat *tempin, *tempout, f;
GLfloat sx, sy;
GLint unpackrowlength, unpackalignment, unpackskiprows, unpackskippixels;
GLint packrowlength, packalignment, packskiprows, packskippixels;
GLint sizein, sizeout;
GLint rowstride, rowlen;
/* Determine number of components per pixel */
switch (format) {
case GL_COLOR_INDEX:
case GL_STENCIL_INDEX:
case GL_DEPTH_COMPONENT:
case GL_RED:
case GL_GREEN:
case GL_BLUE:
case GL_ALPHA:
case GL_LUMINANCE:
components = 1;
break;
case GL_LUMINANCE_ALPHA:
components = 2;
break;
case GL_RGB:
case GL_BGR:
components = 3;
break;
case GL_RGBA:
case GL_BGRA:
#ifdef GL_EXT_abgr
case GL_ABGR_EXT:
#endif
components = 4;
break;
default:
return GLU_INVALID_ENUM;
}
/* Determine bytes per input datum */
switch (typein) {
case GL_UNSIGNED_BYTE:
sizein = sizeof(GLubyte);
break;
case GL_BYTE:
sizein = sizeof(GLbyte);
break;
case GL_UNSIGNED_SHORT:
sizein = sizeof(GLushort);
break;
case GL_SHORT:
sizein = sizeof(GLshort);
break;
case GL_UNSIGNED_INT:
sizein = sizeof(GLuint);
break;
case GL_INT:
sizein = sizeof(GLint);
break;
case GL_FLOAT:
sizein = sizeof(GLfloat);
break;
case GL_BITMAP:
/* not implemented yet */
default:
return GL_INVALID_ENUM;
}
/* Determine bytes per output datum */
switch (typeout) {
case GL_UNSIGNED_BYTE:
sizeout = sizeof(GLubyte);
break;
case GL_BYTE:
sizeout = sizeof(GLbyte);
break;
case GL_UNSIGNED_SHORT:
sizeout = sizeof(GLushort);
break;
case GL_SHORT:
sizeout = sizeof(GLshort);
break;
case GL_UNSIGNED_INT:
sizeout = sizeof(GLuint);
break;
case GL_INT:
sizeout = sizeof(GLint);
break;
case GL_FLOAT:
sizeout = sizeof(GLfloat);
break;
case GL_BITMAP:
/* not implemented yet */
default:
return GL_INVALID_ENUM;
}
/* Get glPixelStore state */
glGetFloatv(GL_UNPACK_ROW_LENGTH, &f); unpackrowlength = (int)f;
glGetFloatv(GL_UNPACK_ALIGNMENT, &f); unpackalignment = (int)f;
glGetFloatv(GL_UNPACK_SKIP_ROWS, &f); unpackskiprows = (int)f;
glGetFloatv(GL_UNPACK_SKIP_PIXELS, &f); unpackskippixels = (int)f;
glGetFloatv(GL_PACK_ROW_LENGTH, &f); packrowlength = (int)f;
glGetFloatv(GL_PACK_ALIGNMENT, &f); packalignment = (int)f;
glGetFloatv(GL_PACK_SKIP_ROWS, &f); packskiprows = (int)f;
glGetFloatv(GL_PACK_SKIP_PIXELS, &f); packskippixels = (int)f;
/* Allocate storage for intermediate images */
tempin = (GLfloat *) malloc(widthin * heightin
* components * sizeof(GLfloat));
if (!tempin) {
return GLU_OUT_OF_MEMORY;
}
tempout = (GLfloat *) malloc(widthout * heightout
* components * sizeof(GLfloat));
if (!tempout) {
free(tempin);
return GLU_OUT_OF_MEMORY;
}
/*
* Unpack the pixel data and convert to floating point
*/
if (unpackrowlength > 0) {
rowlen = unpackrowlength;
}
else {
rowlen = widthin;
}
if (sizein >= unpackalignment) {
rowstride = components * rowlen;
}
else {
rowstride = unpackalignment / sizein
* CEILING(components * rowlen * sizein, unpackalignment);
}
switch (typein) {
case GL_UNSIGNED_BYTE:
k = 0;
for (i = 0; i < heightin; i++) {
GLubyte *ubptr = (GLubyte *) datain
+ i * rowstride
+ unpackskiprows * rowstride + unpackskippixels * components;
for (j = 0; j < widthin * components; j++) {
dummy(j, k);
tempin[k++] = (GLfloat) * ubptr++;
}
}
break;
case GL_BYTE:
k = 0;
for (i = 0; i < heightin; i++) {
GLbyte *bptr = (GLbyte *) datain
+ i * rowstride
+ unpackskiprows * rowstride + unpackskippixels * components;
for (j = 0; j < widthin * components; j++) {
dummy(j, k);
tempin[k++] = (GLfloat) * bptr++;
}
}
break;
case GL_UNSIGNED_SHORT:
k = 0;
for (i = 0; i < heightin; i++) {
GLushort *usptr = (GLushort *) datain
+ i * rowstride
+ unpackskiprows * rowstride + unpackskippixels * components;
for (j = 0; j < widthin * components; j++) {
dummy(j, k);
tempin[k++] = (GLfloat) * usptr++;
}
}
break;
case GL_SHORT:
k = 0;
for (i = 0; i < heightin; i++) {
GLshort *sptr = (GLshort *) datain
+ i * rowstride
+ unpackskiprows * rowstride + unpackskippixels * components;
for (j = 0; j < widthin * components; j++) {
dummy(j, k);
tempin[k++] = (GLfloat) * sptr++;
}
}
break;
case GL_UNSIGNED_INT:
k = 0;
for (i = 0; i < heightin; i++) {
GLuint *uiptr = (GLuint *) datain
+ i * rowstride
+ unpackskiprows * rowstride + unpackskippixels * components;
for (j = 0; j < widthin * components; j++) {
dummy(j, k);
tempin[k++] = (GLfloat) * uiptr++;
}
}
break;
case GL_INT:
k = 0;
for (i = 0; i < heightin; i++) {
GLint *iptr = (GLint *) datain
+ i * rowstride
+ unpackskiprows * rowstride + unpackskippixels * components;
for (j = 0; j < widthin * components; j++) {
dummy(j, k);
tempin[k++] = (GLfloat) * iptr++;
}
}
break;
case GL_FLOAT:
k = 0;
for (i = 0; i < heightin; i++) {
GLfloat *fptr = (GLfloat *) datain
+ i * rowstride
+ unpackskiprows * rowstride + unpackskippixels * components;
for (j = 0; j < widthin * components; j++) {
dummy(j, k);
tempin[k++] = *fptr++;
}
}
break;
default:
{
free(tempin);
free(tempout);
return GLU_INVALID_ENUM;
}
}
/*
* Scale the image!
*/
if (widthout > 1)
sx = (GLfloat) (widthin - 1) / (GLfloat) (widthout - 1);
else
sx = (GLfloat) (widthin - 1);
if (heightout > 1)
sy = (GLfloat) (heightin - 1) / (GLfloat) (heightout - 1);
else
sy = (GLfloat) (heightin - 1);
/*#define POINT_SAMPLE*/
#ifdef POINT_SAMPLE
for (i = 0; i < heightout; i++) {
GLint ii = i * sy;
for (j = 0; j < widthout; j++) {
GLint jj = j * sx;
GLfloat *src = tempin + (ii * widthin + jj) * components;
GLfloat *dst = tempout + (i * widthout + j) * components;
for (k = 0; k < components; k++) {
*dst++ = *src++;
}
}
}
#else
if (sx < 1.0 && sy < 1.0) {
/* magnify both width and height: use weighted sample of 4 pixels */
GLint i0, i1, j0, j1;
GLfloat alpha, beta;
GLfloat *src00, *src01, *src10, *src11;
GLfloat s1, s2;
GLfloat *dst;
for (i = 0; i < heightout; i++) {
i0 = i * sy;
i1 = i0 + 1;
if (i1 >= heightin)
i1 = heightin - 1;
/* i1 = (i+1) * sy - EPSILON;*/
alpha = i * sy - i0;
for (j = 0; j < widthout; j++) {
j0 = j * sx;
j1 = j0 + 1;
if (j1 >= widthin)
j1 = widthin - 1;
/* j1 = (j+1) * sx - EPSILON; */
beta = j * sx - j0;
/* compute weighted average of pixels in rect (i0,j0)-(i1,j1) */
src00 = tempin + (i0 * widthin + j0) * components;
src01 = tempin + (i0 * widthin + j1) * components;
src10 = tempin + (i1 * widthin + j0) * components;
src11 = tempin + (i1 * widthin + j1) * components;
dst = tempout + (i * widthout + j) * components;
for (k = 0; k < components; k++) {
s1 = *src00++ * (1.0 - beta) + *src01++ * beta;
s2 = *src10++ * (1.0 - beta) + *src11++ * beta;
*dst++ = s1 * (1.0 - alpha) + s2 * alpha;
}
}
}
}
else {
/* shrink width and/or height: use an unweighted box filter */
GLint i0, i1;
GLint j0, j1;
GLint ii, jj;
GLfloat sum, *dst;
for (i = 0; i < heightout; i++) {
i0 = i * sy;
i1 = i0 + 1;
if (i1 >= heightin)
i1 = heightin - 1;
/* i1 = (i+1) * sy - EPSILON; */
for (j = 0; j < widthout; j++) {
j0 = j * sx;
j1 = j0 + 1;
if (j1 >= widthin)
j1 = widthin - 1;
/* j1 = (j+1) * sx - EPSILON; */
dst = tempout + (i * widthout + j) * components;
/* compute average of pixels in the rectangle (i0,j0)-(i1,j1) */
for (k = 0; k < components; k++) {
sum = 0.0;
for (ii = i0; ii <= i1; ii++) {
for (jj = j0; jj <= j1; jj++) {
sum += *(tempin + (ii * widthin + jj) * components + k);
}
}
sum /= (j1 - j0 + 1) * (i1 - i0 + 1);
*dst++ = sum;
}
}
}
}
#endif
/*
* Return output image
*/
if (packrowlength > 0) {
rowlen = packrowlength;
}
else {
rowlen = widthout;
}
if (sizeout >= packalignment) {
rowstride = components * rowlen;
}
else {
rowstride = packalignment / sizeout
* CEILING(components * rowlen * sizeout, packalignment);
}
switch (typeout) {
case GL_UNSIGNED_BYTE:
k = 0;
for (i = 0; i < heightout; i++) {
GLubyte *ubptr = (GLubyte *) dataout
+ i * rowstride
+ packskiprows * rowstride + packskippixels * components;
for (j = 0; j < widthout * components; j++) {
dummy(j, k + i);
*ubptr++ = (GLubyte) tempout[k++];
}
}
break;
case GL_BYTE:
k = 0;
for (i = 0; i < heightout; i++) {
GLbyte *bptr = (GLbyte *) dataout
+ i * rowstride
+ packskiprows * rowstride + packskippixels * components;
for (j = 0; j < widthout * components; j++) {
dummy(j, k + i);
*bptr++ = (GLbyte) tempout[k++];
}
}
break;
case GL_UNSIGNED_SHORT:
k = 0;
for (i = 0; i < heightout; i++) {
GLushort *usptr = (GLushort *) dataout
+ i * rowstride
+ packskiprows * rowstride + packskippixels * components;
for (j = 0; j < widthout * components; j++) {
dummy(j, k + i);
*usptr++ = (GLushort) tempout[k++];
}
}
break;
case GL_SHORT:
k = 0;
for (i = 0; i < heightout; i++) {
GLshort *sptr = (GLshort *) dataout
+ i * rowstride
+ packskiprows * rowstride + packskippixels * components;
for (j = 0; j < widthout * components; j++) {
dummy(j, k + i);
*sptr++ = (GLshort) tempout[k++];
}
}
break;
case GL_UNSIGNED_INT:
k = 0;
for (i = 0; i < heightout; i++) {
GLuint *uiptr = (GLuint *) dataout
+ i * rowstride
+ packskiprows * rowstride + packskippixels * components;
for (j = 0; j < widthout * components; j++) {
dummy(j, k + i);
*uiptr++ = (GLuint) tempout[k++];
}
}
break;
case GL_INT:
k = 0;
for (i = 0; i < heightout; i++) {
GLint *iptr = (GLint *) dataout
+ i * rowstride
+ packskiprows * rowstride + packskippixels * components;
for (j = 0; j < widthout * components; j++) {
dummy(j, k + i);
*iptr++ = (GLint) tempout[k++];
}
}
break;
case GL_FLOAT:
k = 0;
for (i = 0; i < heightout; i++) {
GLfloat *fptr = (GLfloat *) dataout
+ i * rowstride
+ packskiprows * rowstride + packskippixels * components;
for (j = 0; j < widthout * components; j++) {
dummy(j, k + i);
*fptr++ = tempout[k++];
}
}
break;
default:
return GLU_INVALID_ENUM;
}
/* free temporary image storage */
free(tempin);
free(tempout);
return 0;
}
/*
* Return the largest k such that 2^k <= n.
*/
static GLint
ilog2(GLint n)
{
GLint k;
if (n <= 0)
return 0;
for (k = 0; n >>= 1; k++);
return k;
}
/*
* Find the value nearest to n which is also a power of two.
*/
static GLint
round2(GLint n)
{
GLint m;
for (m = 1; m < n; m *= 2);
/* m>=n */
if (m - n <= n - m / 2) {
return m;
}
else {
return m / 2;
}
}
/*
* Given an pixel format and data type, return the number of bytes to
* store one pixel.
*/
static GLint
bytes_per_pixel(GLenum format, GLenum type)
{
GLint n, m;
switch (format) {
case GL_COLOR_INDEX:
case GL_STENCIL_INDEX:
case GL_DEPTH_COMPONENT:
case GL_RED:
case GL_GREEN:
case GL_BLUE:
case GL_ALPHA:
case GL_LUMINANCE:
n = 1;
break;
case GL_LUMINANCE_ALPHA:
n = 2;
break;
case GL_RGB:
case GL_BGR:
n = 3;
break;
case GL_RGBA:
case GL_BGRA:
#ifdef GL_EXT_abgr
case GL_ABGR_EXT:
#endif
n = 4;
break;
default:
n = 0;
}
switch (type) {
case GL_UNSIGNED_BYTE:
m = sizeof(GLubyte);
break;
case GL_BYTE:
m = sizeof(GLbyte);
break;
case GL_BITMAP:
m = 1;
break;
case GL_UNSIGNED_SHORT:
m = sizeof(GLushort);
break;
case GL_SHORT:
m = sizeof(GLshort);
break;
case GL_UNSIGNED_INT:
m = sizeof(GLuint);
break;
case GL_INT:
m = sizeof(GLint);
break;
case GL_FLOAT:
m = sizeof(GLfloat);
break;
default:
m = 0;
}
return n * m;
}
/*
* WARNING: This function isn't finished and has never been tested!!!!
*/
GLint GLAPIENTRY
gluBuild1DMipmaps(GLenum target, GLint components,
GLsizei width, GLenum format, GLenum type, const void *data)
{
return 0;
}
GLint GLAPIENTRY
gluBuild2DMipmaps(GLenum target, GLint components,
GLsizei width, GLsizei height, GLenum format,
GLenum type, const void *data)
{
GLint w, h;
GLint maxsize;
void *image, *newimage;
GLint neww, newh, level, bpp;
int error;
GLboolean done;
GLint retval = 0;
GLint unpackrowlength, unpackalignment, unpackskiprows, unpackskippixels;
GLint packrowlength, packalignment, packskiprows, packskippixels;
GLfloat f;
if (width < 1 || height < 1)
return GLU_INVALID_VALUE;
glGetFloatv(GL_MAX_TEXTURE_SIZE, &f); maxsize = (int)f;
w = round2(width);
if (w > maxsize) {
w = maxsize;
}
h = round2(height);
if (h > maxsize) {
h = maxsize;
}
bpp = bytes_per_pixel(format, type);
if (bpp == 0) {
/* probably a bad format or type enum */
return GLU_INVALID_ENUM;
}
/* Get current glPixelStore values */
glGetFloatv(GL_UNPACK_ROW_LENGTH, &f); unpackrowlength = (int)f;
glGetFloatv(GL_UNPACK_ALIGNMENT, &f); unpackalignment = (int)f;
glGetFloatv(GL_UNPACK_SKIP_ROWS, &f); unpackskiprows = (int)f;
glGetFloatv(GL_UNPACK_SKIP_PIXELS, &f); unpackskippixels = (int)f;
glGetFloatv(GL_PACK_ROW_LENGTH, &f); packrowlength = (int)f;
glGetFloatv(GL_PACK_ALIGNMENT, &f); packalignment = (int)f;
glGetFloatv(GL_PACK_SKIP_ROWS, &f); packskiprows = (int)f;
glGetFloatv(GL_PACK_SKIP_PIXELS, &f); packskippixels = (int)f;
/* set pixel packing */
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glPixelStorei(GL_PACK_SKIP_ROWS, 0);
glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
done = GL_FALSE;
if (w != width || h != height) {
/* must rescale image to get "top" mipmap texture image */
image = malloc((w + 4) * h * bpp);
if (!image) {
return GLU_OUT_OF_MEMORY;
}
error = gluScaleImage(format, width, height, type, data,
w, h, type, image);
if (error) {
retval = error;
done = GL_TRUE;
}
}
else {
image = (void *) data;
}
level = 0;
while (!done) {
if (image != data) {
/* set pixel unpacking */
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
}
glTexImage2D(target, level, components, w, h, 0, format, type, image);
if (w == 1 && h == 1)
break;
neww = (w < 2) ? 1 : w / 2;
newh = (h < 2) ? 1 : h / 2;
newimage = malloc((neww + 4) * newh * bpp);
if (!newimage) {
return GLU_OUT_OF_MEMORY;
}
error = gluScaleImage(format, w, h, type, image,
neww, newh, type, newimage);
if (error) {
retval = error;
done = GL_TRUE;
}
if (image != data) {
free(image);
}
image = newimage;
w = neww;
h = newh;
level++;
}
if (image != data) {
free(image);
}
/* Restore original glPixelStore state */
glPixelStorei(GL_UNPACK_ROW_LENGTH, unpackrowlength);
glPixelStorei(GL_UNPACK_ALIGNMENT, unpackalignment);
glPixelStorei(GL_UNPACK_SKIP_ROWS, unpackskiprows);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, unpackskippixels);
glPixelStorei(GL_PACK_ROW_LENGTH, packrowlength);
glPixelStorei(GL_PACK_ALIGNMENT, packalignment);
glPixelStorei(GL_PACK_SKIP_ROWS, packskiprows);
glPixelStorei(GL_PACK_SKIP_PIXELS, packskippixels);
return retval;
}

View file

@ -1,157 +0,0 @@
/*
* 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.
*/
/*
* NURBS implementation written by Bogdan Sikorski (bogdan@cira.it)
* See README2 for more info.
*/
#ifdef PC_HEADER
#include "all.h"
#else
#include <stdio.h>
#include <stdlib.h>
#include "gluP.h"
#include "nurbs.h"
#endif
void
call_user_error(GLUnurbsObj * nobj, GLenum error)
{
nobj->error = error;
if (nobj->error_callback != NULL) {
(*(nobj->error_callback)) (error);
}
else {
printf("NURBS error %d %s\n", error, (char *) gluErrorString(error));
}
}
GLUnurbsObj *GLAPIENTRY
gluNewNurbsRenderer(void)
{
GLUnurbsObj *n;
GLfloat tmp_viewport[4];
GLint i, j;
n = (GLUnurbsObj *) malloc(sizeof(GLUnurbsObj));
return n;
}
void GLAPIENTRY
gluDeleteNurbsRenderer(GLUnurbsObj * nobj)
{
if (nobj) {
free(nobj);
}
}
void GLAPIENTRY
gluLoadSamplingMatrices(GLUnurbsObj * nobj,
const GLfloat modelMatrix[16],
const GLfloat projMatrix[16], const GLint viewport[4])
{
}
void GLAPIENTRY
gluNurbsProperty(GLUnurbsObj * nobj, GLenum property, GLfloat value)
{
}
void GLAPIENTRY
gluGetNurbsProperty(GLUnurbsObj * nobj, GLenum property, GLfloat * value)
{
}
void GLAPIENTRY
gluBeginCurve(GLUnurbsObj * nobj)
{
}
void GLAPIENTRY
gluEndCurve(GLUnurbsObj * nobj)
{
}
void GLAPIENTRY
gluNurbsCurve(GLUnurbsObj * nobj, GLint nknots, GLfloat * knot,
GLint stride, GLfloat * ctlarray, GLint order, GLenum type)
{
}
void GLAPIENTRY
gluBeginSurface(GLUnurbsObj * nobj)
{
}
void GLAPIENTRY
gluEndSurface(GLUnurbsObj * nobj)
{
}
void GLAPIENTRY
gluNurbsSurface(GLUnurbsObj * nobj,
GLint sknot_count, GLfloat * sknot,
GLint tknot_count, GLfloat * tknot,
GLint s_stride, GLint t_stride,
GLfloat * ctrlarray, GLint sorder, GLint torder, GLenum type)
{
}
void GLAPIENTRY
gluNurbsCallback(GLUnurbsObj * nobj, GLenum which, void (GLCALLBACK * fn) ())
{
}
void GLAPIENTRY
gluBeginTrim(GLUnurbsObj * nobj)
{
}
void GLAPIENTRY
gluPwlCurve(GLUnurbsObj * nobj, GLint count, GLfloat * array, GLint stride,
GLenum type)
{
}
void GLAPIENTRY
gluEndTrim(GLUnurbsObj * nobj)
{
}

View file

@ -1,252 +0,0 @@
/*
* 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.
*/
/*
* NURBS implementation written by Bogdan Sikorski (bogdan@cira.it)
* See README2 for more info.
*/
#ifndef NURBS_H
#define NURBS_H
#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;
typedef 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;
typedef struct
{
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;
typedef struct
{
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;
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;
typedef struct seg_trim_str
{
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;
typedef struct
{
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;
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);
#endif

View file

@ -1,132 +0,0 @@
/*
* 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.
*/
/*
* NURBS implementation written by Bogdan Sikorski (bogdan@cira.it)
* See README2 for more info.
*/
#ifdef PC_HEADER
#include "all.h"
#else
#include <math.h>
#include <stdlib.h>
#include "gluP.h"
#include "nurbs.h"
#endif
/* main NURBS curve procedure */
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 = 0, *color_ctrl = 0, *normal_ctrl = 0, *texture_ctrl = 0;
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;
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;
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);
}

View file

@ -1,937 +0,0 @@
/*
* 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 = 0;
/* 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;
}

View file

@ -1,403 +0,0 @@
/*
* 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.
*/
#ifdef PC_HEADER
#include "all.h"
#else
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "gluP.h"
#endif
/*
* This code was contributed by Marc Buffat (buffat@mecaflu.ec-lyon.fr).
* Thanks Marc!!!
*/
/* implementation de gluProject et gluUnproject */
/* M. Buffat 17/2/95 */
/*
* Transform a point (column vector) by a 4x4 matrix. I.e. out = m * in
* Input: m - the 4x4 matrix
* 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])
{
#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];
#undef M
}
/*
* Perform a 4x4 matrix multiplication (product = a x b).
* Input: a, b - matrices to multiply
* Output: product - product of a and b
*/
static void
matmul(GLdouble * product, const GLdouble * a, const GLdouble * b)
{
/* This matmul was contributed by Thomas Malik */
GLdouble temp[16];
GLint i;
#define A(row,col) a[(col<<2)+row]
#define B(row,col) b[(col<<2)+row]
#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);
}
#undef A
#undef B
#undef T
MEMCPY(product, temp, 16 * sizeof(GLdouble));
}
/*
* Compute inverse of 4x4 transformation matrix.
* 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)
{
/* 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;
#undef MAT
#undef SWAP_ROWS
}
/* 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)
{
/* 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)
{
/* 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);
if (!invert_matrix(A, m))
return GL_FALSE;
/* 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;
}
/*
* 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)
{
/* 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);
if (!invert_matrix(A, m))
return GL_FALSE;
/* 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

View file

@ -1,773 +0,0 @@
/*
* Mesa 3-D graphics library
* Version: 3.3
* Copyright (C) 1999-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.
*/
/* TODO:
* texture coordinate support
* flip normals according to orientation
* there's still some inside/outside orientation bugs in possibly all
* but the sphere function
*/
#ifdef PC_HEADER
#include "all.h"
#else
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "gluP.h"
#endif
#ifndef M_PI
# define M_PI (3.1415926)
#endif
/*
* Convert degrees to radians:
*/
#define DEG_TO_RAD(A) ((A)*(M_PI/180.0))
/*
* Sin and Cos for degree angles:
*/
#define SIND( A ) sin( (A)*(M_PI/180.0) )
#define COSD( A) cos( (A)*(M_PI/180.0) )
/*
* Texture coordinates if texture flag is set
*/
#define TXTR_COORD(x,y) if (qobj->TextureFlag) glTexCoord2f(x,y);
struct GLUquadric
{
GLenum DrawStyle; /* GLU_FILL, LINE, SILHOUETTE, or POINT */
GLenum Orientation; /* GLU_INSIDE or GLU_OUTSIDE */
GLboolean TextureFlag; /* Generate texture coords? */
GLenum Normals; /* GLU_NONE, GLU_FLAT, or GLU_SMOOTH */
void (GLCALLBACK * ErrorFunc) (GLenum err); /* Error handler callback function */
};
/*
* Process a GLU error.
*/
static void
quadric_error(GLUquadricObj * qobj, GLenum error, const char *msg)
{
/* Call the error call back function if any */
if (qobj->ErrorFunc) {
(*qobj->ErrorFunc) (error);
}
/* Print a message to stdout if MESA_DEBUG variable is defined */
if (getenv("MESA_DEBUG")) {
fprintf(stderr, "GLUError: %s: %s\n", (char *) gluErrorString(error),
msg);
}
}
GLUquadricObj *GLAPIENTRY
gluNewQuadric(void)
{
GLUquadricObj *q;
q = (GLUquadricObj *) malloc(sizeof(struct GLUquadric));
if (q) {
q->DrawStyle = GLU_FILL;
q->Orientation = GLU_OUTSIDE;
q->TextureFlag = GL_FALSE;
q->Normals = GLU_SMOOTH;
q->ErrorFunc = NULL;
}
return q;
}
void GLAPIENTRY
gluDeleteQuadric(GLUquadricObj * state)
{
if (state) {
free((void *) state);
}
}
/*
* Set the drawing style to be GLU_FILL, GLU_LINE, GLU_SILHOUETTE,
* or GLU_POINT.
*/
void GLAPIENTRY
gluQuadricDrawStyle(GLUquadricObj * quadObject, GLenum drawStyle)
{
if (quadObject && (drawStyle == GLU_FILL || drawStyle == GLU_LINE
|| drawStyle == GLU_SILHOUETTE
|| drawStyle == GLU_POINT)) {
quadObject->DrawStyle = drawStyle;
}
else {
quadric_error(quadObject, GLU_INVALID_ENUM, "qluQuadricDrawStyle");
}
}
/*
* Set the orientation to GLU_INSIDE or GLU_OUTSIDE.
*/
void GLAPIENTRY
gluQuadricOrientation(GLUquadricObj * quadObject, GLenum orientation)
{
if (quadObject
&& (orientation == GLU_INSIDE || orientation == GLU_OUTSIDE)) {
quadObject->Orientation = orientation;
}
else {
quadric_error(quadObject, GLU_INVALID_ENUM, "qluQuadricOrientation");
}
}
/*
* Set the error handler callback function.
*/
void GLAPIENTRY
gluQuadricCallback(GLUquadricObj * qobj,
GLenum which, void (GLCALLBACK * fn) ())
{
/*
* UGH, this is a mess! I thought ANSI was a standard.
*/
if (qobj && which == GLU_ERROR) {
#ifdef __CYGWIN32__
qobj->ErrorFunc = (void (GLCALLBACKPCAST) (GLenum)) fn;
#elif defined(OPENSTEP)
qobj->ErrorFunc = (void (*)(GLenum)) fn;
#elif defined(_WIN32)
qobj->ErrorFunc = (void (GLCALLBACK *) (int)) fn;
#elif defined(__STORM__)
qobj->ErrorFunc = (void (GLCALLBACK *) (GLenum)) fn;
#elif defined(__BEOS__)
qobj->ErrorFunc = (void (*)(GLenum)) fn;
#else
qobj->ErrorFunc = (void (GLCALLBACK *) ()) fn;
#endif
}
}
void GLAPIENTRY
gluQuadricNormals(GLUquadricObj * quadObject, GLenum normals)
{
if (quadObject
&& (normals == GLU_NONE || normals == GLU_FLAT
|| normals == GLU_SMOOTH)) {
quadObject->Normals = normals;
}
}
void GLAPIENTRY
gluQuadricTexture(GLUquadricObj * quadObject, GLboolean textureCoords)
{
if (quadObject) {
quadObject->TextureFlag = textureCoords;
}
}
/*
* Call glNormal3f after scaling normal to unit length.
*/
static void
normal3f(GLfloat x, GLfloat y, GLfloat z)
{
}
void GLAPIENTRY
gluCylinder(GLUquadricObj * qobj,
GLdouble baseRadius, GLdouble topRadius,
GLdouble height, GLint slices, GLint stacks)
{
GLdouble da, r, dr, dz;
GLfloat x, y, z, nz, nsign;
GLint i, j;
if (qobj->Orientation == GLU_INSIDE) {
nsign = -1.0;
}
else {
nsign = 1.0;
}
da = 2.0 * M_PI / slices;
dr = (topRadius - baseRadius) / stacks;
dz = height / stacks;
nz = (baseRadius - topRadius) / height; /* Z component of normal vectors */
if (qobj->DrawStyle == GLU_POINT) {
glBegin(GL_POINTS);
for (i = 0; i < slices; i++) {
x = cos(i * da);
y = sin(i * da);
normal3f(x * nsign, y * nsign, nz * nsign);
z = 0.0;
r = baseRadius;
for (j = 0; j <= stacks; j++) {
glVertex3f(x * r, y * r, z);
z += dz;
r += dr;
}
}
glEnd();
}
else if (qobj->DrawStyle == GLU_LINE || qobj->DrawStyle == GLU_SILHOUETTE) {
/* Draw rings */
if (qobj->DrawStyle == GLU_LINE) {
z = 0.0;
r = baseRadius;
for (j = 0; j <= stacks; j++) {
glBegin(GL_LINE_LOOP);
for (i = 0; i < slices; i++) {
x = cos(i * da);
y = sin(i * da);
normal3f(x * nsign, y * nsign, nz * nsign);
glVertex3f(x * r, y * r, z);
}
glEnd();
z += dz;
r += dr;
}
}
else {
/* draw one ring at each end */
if (baseRadius != 0.0) {
glBegin(GL_LINE_LOOP);
for (i = 0; i < slices; i++) {
x = cos(i * da);
y = sin(i * da);
normal3f(x * nsign, y * nsign, nz * nsign);
glVertex3f(x * baseRadius, y * baseRadius, 0.0);
}
glEnd();
glBegin(GL_LINE_LOOP);
for (i = 0; i < slices; i++) {
x = cos(i * da);
y = sin(i * da);
normal3f(x * nsign, y * nsign, nz * nsign);
glVertex3f(x * topRadius, y * topRadius, height);
}
glEnd();
}
}
/* draw length lines */
glBegin(GL_LINES);
for (i = 0; i < slices; i++) {
x = cos(i * da);
y = sin(i * da);
normal3f(x * nsign, y * nsign, nz * nsign);
glVertex3f(x * baseRadius, y * baseRadius, 0.0);
glVertex3f(x * topRadius, y * topRadius, height);
}
glEnd();
}
else if (qobj->DrawStyle == GLU_FILL) {
GLfloat ds = 1.0 / slices;
GLfloat dt = 1.0 / stacks;
GLfloat t = 0.0;
z = 0.0;
r = baseRadius;
for (j = 0; j < stacks; j++) {
GLfloat s = 0.0;
glBegin(GL_QUAD_STRIP);
for (i = 0; i <= slices; i++) {
GLfloat x, y;
if (i == slices) {
x = sin(0.0);
y = cos(0.0);
}
else {
x = sin(i * da);
y = cos(i * da);
}
if (nsign == 1.0) {
normal3f(x * nsign, y * nsign, nz * nsign);
TXTR_COORD(s, t);
glVertex3f(x * r, y * r, z);
normal3f(x * nsign, y * nsign, nz * nsign);
TXTR_COORD(s, t + dt);
glVertex3f(x * (r + dr), y * (r + dr), z + dz);
}
else {
normal3f(x * nsign, y * nsign, nz * nsign);
TXTR_COORD(s, t);
glVertex3f(x * r, y * r, z);
normal3f(x * nsign, y * nsign, nz * nsign);
TXTR_COORD(s, t + dt);
glVertex3f(x * (r + dr), y * (r + dr), z + dz);
}
s += ds;
} /* for slices */
glEnd();
r += dr;
t += dt;
z += dz;
} /* for stacks */
}
}
void GLAPIENTRY
gluSphere(GLUquadricObj * qobj, GLdouble radius, GLint slices, GLint stacks)
{
GLfloat rho, drho, theta, dtheta;
GLfloat x, y, z;
GLfloat s, t, ds, dt;
GLint i, j, imin, imax;
GLboolean normals;
GLfloat nsign;
if (qobj->Normals == GLU_NONE) {
normals = GL_FALSE;
}
else {
normals = GL_TRUE;
}
if (qobj->Orientation == GLU_INSIDE) {
nsign = -1.0;
}
else {
nsign = 1.0;
}
drho = M_PI / (GLfloat) stacks;
dtheta = 2.0 * M_PI / (GLfloat) slices;
/* texturing: s goes from 0.0/0.25/0.5/0.75/1.0 at +y/+x/-y/-x/+y axis */
/* t goes from -1.0/+1.0 at z = -radius/+radius (linear along longitudes) */
/* cannot use triangle fan on texturing (s coord. at top/bottom tip varies) */
if (qobj->DrawStyle == GLU_FILL) {
if (!qobj->TextureFlag) {
/* draw +Z end as a triangle fan */
glBegin(GL_TRIANGLE_FAN);
/* glNormal3f(0.0, 0.0, 1.0); */
glVertex3f(0.0, 0.0, nsign * radius);
for (j = 0; j <= slices; j++) {
theta = (j == slices) ? 0.0 : j * dtheta;
x = -sin(theta) * sin(drho);
y = cos(theta) * sin(drho);
z = nsign * cos(drho);
glVertex3f(x * radius, y * radius, z * radius);
}
glEnd();
}
ds = 1.0 / slices;
dt = 1.0 / stacks;
t = 1.0; /* because loop now runs from 0 */
if (qobj->TextureFlag) {
imin = 0;
imax = stacks;
}
else {
imin = 1;
imax = stacks - 1;
}
/* draw intermediate stacks as quad strips */
for (i = imin; i < imax; i++) {
rho = i * drho;
glBegin(GL_QUAD_STRIP);
s = 0.0;
for (j = 0; j <= slices; j++) {
theta = (j == slices) ? 0.0 : j * dtheta;
x = -sin(theta) * sin(rho);
y = cos(theta) * sin(rho);
z = nsign * cos(rho);
TXTR_COORD(s, t);
glVertex3f(x * radius, y * radius, z * radius);
x = -sin(theta) * sin(rho + drho);
y = cos(theta) * sin(rho + drho);
z = nsign * cos(rho + drho);
TXTR_COORD(s, t - dt);
s += ds;
glVertex3f(x * radius, y * radius, z * radius);
}
glEnd();
t -= dt;
}
if (!qobj->TextureFlag) {
/* draw -Z end as a triangle fan */
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.0, 0.0, -radius * nsign);
rho = M_PI - drho;
s = 1.0;
t = dt;
for (j = slices; j >= 0; j--) {
theta = (j == slices) ? 0.0 : j * dtheta;
x = -sin(theta) * sin(rho);
y = cos(theta) * sin(rho);
z = nsign * cos(rho);
s -= ds;
glVertex3f(x * radius, y * radius, z * radius);
}
glEnd();
}
}
else if (qobj->DrawStyle == GLU_LINE || qobj->DrawStyle == GLU_SILHOUETTE) {
/* draw stack lines */
for (i = 1; i < stacks; i++) { /* stack line at i==stacks-1 was missing here */
rho = i * drho;
glBegin(GL_LINE_LOOP);
for (j = 0; j < slices; j++) {
theta = j * dtheta;
x = cos(theta) * sin(rho);
y = sin(theta) * sin(rho);
z = cos(rho);
glVertex3f(x * radius, y * radius, z * radius);
}
glEnd();
}
/* draw slice lines */
for (j = 0; j < slices; j++) {
theta = j * dtheta;
glBegin(GL_LINE_STRIP);
for (i = 0; i <= stacks; i++) {
rho = i * drho;
x = cos(theta) * sin(rho);
y = sin(theta) * sin(rho);
z = cos(rho);
glVertex3f(x * radius, y * radius, z * radius);
}
glEnd();
}
}
else if (qobj->DrawStyle == GLU_POINT) {
/* top and bottom-most points */
glBegin(GL_POINTS);
glVertex3f(0.0, 0.0, radius);
glVertex3f(0.0, 0.0, -radius);
/* loop over stacks */
for (i = 1; i < stacks - 1; i++) {
rho = i * drho;
for (j = 0; j < slices; j++) {
theta = j * dtheta;
x = cos(theta) * sin(rho);
y = sin(theta) * sin(rho);
z = cos(rho);
glVertex3f(x * radius, y * radius, z * radius);
}
}
glEnd();
}
}
void GLAPIENTRY
gluDisk(GLUquadricObj * qobj,
GLdouble innerRadius, GLdouble outerRadius, GLint slices, GLint loops)
{
GLfloat da, dr;
#if 0
GLdouble a, da;
GLfloat r, dr;
GLfloat x, y;
GLfloat r1, r2, dtc;
GLint s, l;
#endif
da = 2.0 * M_PI / slices;
dr = (outerRadius - innerRadius) / (GLfloat) loops;
switch (qobj->DrawStyle) {
case GLU_FILL:
{
/* texture of a gluDisk is a cut out of the texture unit square
* x, y in [-outerRadius, +outerRadius]; s, t in [0, 1]
* (linear mapping)
*/
GLfloat dtc = 2.0f * outerRadius;
GLfloat sa, ca;
GLfloat r1 = innerRadius;
GLint l;
for (l = 0; l < loops; l++) {
GLfloat r2 = r1 + dr;
if (qobj->Orientation == GLU_OUTSIDE) {
GLint s;
glBegin(GL_QUAD_STRIP);
for (s = 0; s <= slices; s++) {
GLfloat a;
if (s == slices)
a = 0.0;
else
a = s * da;
sa = sin(a);
ca = cos(a);
TXTR_COORD(0.5 + sa * r2 / dtc, 0.5 + ca * r2 / dtc);
glVertex2f(r2 * sa, r2 * ca);
TXTR_COORD(0.5 + sa * r1 / dtc, 0.5 + ca * r1 / dtc);
glVertex2f(r1 * sa, r1 * ca);
}
glEnd();
}
else {
GLint s;
glBegin(GL_QUAD_STRIP);
for (s = slices; s >= 0; s--) {
GLfloat a;
if (s == slices)
a = 0.0;
else
a = s * da;
sa = sin(a);
ca = cos(a);
TXTR_COORD(0.5 - sa * r2 / dtc, 0.5 + ca * r2 / dtc);
glVertex2f(r2 * sa, r2 * ca);
TXTR_COORD(0.5 - sa * r1 / dtc, 0.5 + ca * r1 / dtc);
glVertex2f(r1 * sa, r1 * ca);
}
glEnd();
}
r1 = r2;
}
break;
}
case GLU_LINE:
{
GLint l, s;
/* draw loops */
for (l = 0; l <= loops; l++) {
GLfloat r = innerRadius + l * dr;
glBegin(GL_LINE_LOOP);
for (s = 0; s < slices; s++) {
GLfloat a = s * da;
glVertex2f(r * sin(a), r * cos(a));
}
glEnd();
}
/* draw spokes */
for (s = 0; s < slices; s++) {
GLfloat a = s * da;
GLfloat x = sin(a);
GLfloat y = cos(a);
glBegin(GL_LINE_STRIP);
for (l = 0; l <= loops; l++) {
GLfloat r = innerRadius + l * dr;
glVertex2f(r * x, r * y);
}
glEnd();
}
break;
}
case GLU_POINT:
{
GLint s;
glBegin(GL_POINTS);
for (s = 0; s < slices; s++) {
GLfloat a = s * da;
GLfloat x = sin(a);
GLfloat y = cos(a);
GLint l;
for (l = 0; l <= loops; l++) {
GLfloat r = innerRadius * l * dr;
glVertex2f(r * x, r * y);
}
}
glEnd();
break;
}
case GLU_SILHOUETTE:
{
if (innerRadius != 0.0) {
GLfloat a;
glBegin(GL_LINE_LOOP);
for (a = 0.0; a < 2.0 * M_PI; a += da) {
GLfloat x = innerRadius * sin(a);
GLfloat y = innerRadius * cos(a);
glVertex2f(x, y);
}
glEnd();
}
{
GLfloat a;
glBegin(GL_LINE_LOOP);
for (a = 0; a < 2.0 * M_PI; a += da) {
GLfloat x = outerRadius * sin(a);
GLfloat y = outerRadius * cos(a);
glVertex2f(x, y);
}
glEnd();
}
break;
}
default:
abort();
}
}
void GLAPIENTRY
gluPartialDisk(GLUquadricObj * qobj, GLdouble innerRadius,
GLdouble outerRadius, GLint slices, GLint loops,
GLdouble startAngle, GLdouble sweepAngle)
{
if (qobj->DrawStyle == GLU_POINT) {
GLint loop, slice;
GLdouble radius, delta_radius;
GLdouble angle, delta_angle;
delta_radius = (outerRadius - innerRadius) / (loops - 1);
delta_angle = DEG_TO_RAD((sweepAngle) / (slices - 1));
glBegin(GL_POINTS);
radius = innerRadius;
for (loop = 0; loop < loops; loop++) {
angle = DEG_TO_RAD(startAngle);
for (slice = 0; slice < slices; slice++) {
glVertex2f(radius * sin(angle), radius * cos(angle));
angle += delta_angle;
}
radius += delta_radius;
}
glEnd();
}
else if (qobj->DrawStyle == GLU_LINE) {
GLint loop, slice;
GLdouble radius, delta_radius;
GLdouble angle, delta_angle;
delta_radius = (outerRadius - innerRadius) / loops;
delta_angle = DEG_TO_RAD(sweepAngle / slices);
/* draw rings */
radius = innerRadius;
for (loop = 0; loop < loops; loop++) {
angle = DEG_TO_RAD(startAngle);
glBegin(GL_LINE_STRIP);
for (slice = 0; slice <= slices; slice++) {
glVertex2f(radius * sin(angle), radius * cos(angle));
angle += delta_angle;
}
glEnd();
radius += delta_radius;
}
/* draw spokes */
angle = DEG_TO_RAD(startAngle);
for (slice = 0; slice <= slices; slice++) {
radius = innerRadius;
glBegin(GL_LINE_STRIP);
for (loop = 0; loop < loops; loop++) {
glVertex2f(radius * sin(angle), radius * cos(angle));
radius += delta_radius;
}
glEnd();
angle += delta_angle;
}
}
else if (qobj->DrawStyle == GLU_SILHOUETTE) {
GLint slice;
GLdouble angle, delta_angle;
delta_angle = DEG_TO_RAD(sweepAngle / slices);
/* draw outer ring */
glBegin(GL_LINE_STRIP);
angle = DEG_TO_RAD(startAngle);
for (slice = 0; slice <= slices; slice++) {
glVertex2f(outerRadius * sin(angle), outerRadius * cos(angle));
angle += delta_angle;
}
glEnd();
/* draw inner ring */
if (innerRadius > 0.0) {
glBegin(GL_LINE_STRIP);
angle = DEG_TO_RAD(startAngle);
for (slice = 0; slice < slices; slice++) {
glVertex2f(innerRadius * sin(angle), innerRadius * cos(angle));
angle += delta_angle;
}
glEnd();
}
/* draw spokes */
if (sweepAngle < 360.0) {
GLdouble stopAngle = startAngle + sweepAngle;
glBegin(GL_LINES);
glVertex2f(innerRadius * SIND(startAngle),
innerRadius * COSD(startAngle));
glVertex2f(outerRadius * SIND(startAngle),
outerRadius * COSD(startAngle));
glVertex2f(innerRadius * SIND(stopAngle),
innerRadius * COSD(stopAngle));
glVertex2f(outerRadius * SIND(stopAngle),
outerRadius * COSD(stopAngle));
glEnd();
}
}
else if (qobj->DrawStyle == GLU_FILL) {
GLint loop, slice;
GLdouble radius, delta_radius;
GLdouble angle, delta_angle;
delta_radius = (outerRadius - innerRadius) / loops;
delta_angle = DEG_TO_RAD(sweepAngle / slices);
radius = innerRadius;
for (loop = 0; loop < loops; loop++) {
glBegin(GL_QUAD_STRIP);
angle = DEG_TO_RAD(startAngle);
for (slice = 0; slice <= slices; slice++) {
if (qobj->Orientation == GLU_OUTSIDE) {
glVertex2f((radius + delta_radius) * sin(angle),
(radius + delta_radius) * cos(angle));
glVertex2f(radius * sin(angle), radius * cos(angle));
}
else {
glVertex2f(radius * sin(angle), radius * cos(angle));
glVertex2f((radius + delta_radius) * sin(angle),
(radius + delta_radius) * cos(angle));
}
angle += delta_angle;
}
glEnd();
radius += delta_radius;
}
}
}

View file

@ -1,327 +0,0 @@
/*
* 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 "tess.h"
#endif
/*
* This is ugly, but seems the easiest way to do things to make the
* code work under YellowBox for Windows
*/
#if defined(OPENSTEP) && defined(CALLBACK)
#undef CALLBACK
#define CALLBACK
#endif
static void delete_contours(GLUtriangulatorObj *);
#ifdef __CYGWIN32__
#define _CALLBACK
#else
#define _CALLBACK GLCALLBACK
#endif
static void
init_callbacks(tess_callbacks * callbacks)
{
callbacks->begin = (void (_CALLBACK *) (GLenum)) 0;
callbacks->edgeFlag = (void (_CALLBACK *) (GLboolean)) 0;
callbacks->vertex = (void (_CALLBACK *) (void *)) 0;
callbacks->end = (void (_CALLBACK *) (void)) 0;
callbacks->error = (void (_CALLBACK *) (GLenum)) 0;
}
void
tess_call_user_error(GLUtriangulatorObj * tobj, GLenum gluerr)
{
if (tobj->error == GLU_NO_ERROR)
tobj->error = gluerr;
if (tobj->callbacks.error != NULL)
(tobj->callbacks.error) (gluerr);
}
GLUtriangulatorObj *GLAPIENTRY
gluNewTess(void)
{
GLUtriangulatorObj *tobj;
if ((tobj = (GLUtriangulatorObj *)
malloc(sizeof(struct GLUtesselator))) == NULL)
return NULL;
tobj->contours = tobj->last_contour = NULL;
init_callbacks(&tobj->callbacks);
tobj->error = GLU_NO_ERROR;
tobj->current_polygon = NULL;
tobj->contour_cnt = 0;
return tobj;
}
void GLAPIENTRY
gluTessCallback(GLUtriangulatorObj * tobj, GLenum which,
void (GLCALLBACK * fn) ())
{
switch (which) {
case GLU_BEGIN:
tobj->callbacks.begin = (void (_CALLBACK *) (GLenum)) fn;
break;
case GLU_EDGE_FLAG:
tobj->callbacks.edgeFlag = (void (_CALLBACK *) (GLboolean)) fn;
break;
case GLU_VERTEX:
tobj->callbacks.vertex = (void (_CALLBACK *) (void *)) fn;
break;
case GLU_END:
tobj->callbacks.end = (void (_CALLBACK *) (void)) fn;
break;
case GLU_ERROR:
tobj->callbacks.error = (void (_CALLBACK *) (GLenum)) fn;
break;
default:
tobj->error = GLU_INVALID_ENUM;
break;
}
}
void GLAPIENTRY
gluDeleteTess(GLUtriangulatorObj * tobj)
{
if (tobj->error == GLU_NO_ERROR && tobj->contour_cnt)
/* was gluEndPolygon called? */
tess_call_user_error(tobj, GLU_TESS_ERROR1);
/* delete all internal structures */
delete_contours(tobj);
free(tobj);
}
void GLAPIENTRY
gluBeginPolygon(GLUtriangulatorObj * tobj)
{
/*
if(tobj->error!=GLU_NO_ERROR)
return;
*/
tobj->error = GLU_NO_ERROR;
if (tobj->current_polygon != NULL) {
/* gluEndPolygon was not called */
tess_call_user_error(tobj, GLU_TESS_ERROR1);
/* delete all internal structures */
delete_contours(tobj);
}
else {
if ((tobj->current_polygon =
(tess_polygon *) malloc(sizeof(tess_polygon))) == NULL) {
tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
return;
}
tobj->current_polygon->vertex_cnt = 0;
tobj->current_polygon->vertices =
tobj->current_polygon->last_vertex = NULL;
}
}
void GLAPIENTRY
gluEndPolygon(GLUtriangulatorObj * tobj)
{
/*tess_contour *contour_ptr; */
/* there was an error */
if (tobj->error != GLU_NO_ERROR)
goto end;
/* check if gluBeginPolygon was called */
if (tobj->current_polygon == NULL) {
tess_call_user_error(tobj, GLU_TESS_ERROR2);
return;
}
tess_test_polygon(tobj);
/* there was an error */
if (tobj->error != GLU_NO_ERROR)
goto end;
/* any real contours? */
if (tobj->contour_cnt == 0) {
/* delete all internal structures */
delete_contours(tobj);
return;
}
tess_find_contour_hierarchies(tobj);
/* there was an error */
if (tobj->error != GLU_NO_ERROR)
goto end;
tess_handle_holes(tobj);
/* there was an error */
if (tobj->error != GLU_NO_ERROR)
goto end;
/* if no callbacks, nothing to do */
if (tobj->callbacks.begin != NULL && tobj->callbacks.vertex != NULL &&
tobj->callbacks.end != NULL) {
if (tobj->callbacks.edgeFlag == NULL)
tess_tesselate(tobj);
else
tess_tesselate_with_edge_flag(tobj);
}
end:
/* delete all internal structures */
delete_contours(tobj);
}
void GLAPIENTRY
gluNextContour(GLUtriangulatorObj * tobj, GLenum type)
{
if (tobj->error != GLU_NO_ERROR)
return;
if (tobj->current_polygon == NULL) {
tess_call_user_error(tobj, GLU_TESS_ERROR2);
return;
}
/* first contour? */
if (tobj->current_polygon->vertex_cnt)
tess_test_polygon(tobj);
}
void GLAPIENTRY
gluTessVertex(GLUtriangulatorObj * tobj, GLdouble v[3], void *data)
{
tess_polygon *polygon = tobj->current_polygon;
tess_vertex *last_vertex_ptr;
if (tobj->error != GLU_NO_ERROR)
return;
if (polygon == NULL) {
tess_call_user_error(tobj, GLU_TESS_ERROR2);
return;
}
last_vertex_ptr = polygon->last_vertex;
if (last_vertex_ptr == NULL) {
if ((last_vertex_ptr = (tess_vertex *)
malloc(sizeof(tess_vertex))) == NULL) {
tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
return;
}
polygon->vertices = last_vertex_ptr;
polygon->last_vertex = last_vertex_ptr;
last_vertex_ptr->data = data;
last_vertex_ptr->location[0] = v[0];
last_vertex_ptr->location[1] = v[1];
last_vertex_ptr->location[2] = v[2];
last_vertex_ptr->next = NULL;
last_vertex_ptr->previous = NULL;
++(polygon->vertex_cnt);
}
else {
tess_vertex *vertex_ptr;
/* same point twice? */
if (fabs(last_vertex_ptr->location[0] - v[0]) < EPSILON &&
fabs(last_vertex_ptr->location[1] - v[1]) < EPSILON &&
fabs(last_vertex_ptr->location[2] - v[2]) < EPSILON) {
tess_call_user_error(tobj, GLU_TESS_ERROR6);
return;
}
if ((vertex_ptr = (tess_vertex *)
malloc(sizeof(tess_vertex))) == NULL) {
tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
return;
}
vertex_ptr->data = data;
vertex_ptr->location[0] = v[0];
vertex_ptr->location[1] = v[1];
vertex_ptr->location[2] = v[2];
vertex_ptr->next = NULL;
vertex_ptr->previous = last_vertex_ptr;
++(polygon->vertex_cnt);
last_vertex_ptr->next = vertex_ptr;
polygon->last_vertex = vertex_ptr;
}
}
static void
delete_contours(GLUtriangulatorObj * tobj)
{
tess_polygon *polygon = tobj->current_polygon;
tess_contour *contour, *contour_tmp;
tess_vertex *vertex, *vertex_tmp;
/* remove current_polygon list - if exists due to detected error */
if (polygon != NULL) {
if (polygon->vertices) {
for (vertex = polygon->vertices; vertex != polygon->last_vertex;) {
vertex_tmp = vertex->next;
free(vertex);
vertex = vertex_tmp;
}
free(vertex);
}
free(polygon);
tobj->current_polygon = NULL;
}
/* remove all contour data */
for (contour = tobj->contours; contour != NULL;) {
for (vertex = contour->vertices; vertex != contour->last_vertex;) {
vertex_tmp = vertex->next;
free(vertex);
vertex = vertex_tmp;
}
free(vertex);
contour_tmp = contour->next;
free(contour);
contour = contour_tmp;
}
tobj->contours = tobj->last_contour = NULL;
tobj->contour_cnt = 0;
}
void GLAPIENTRY
gluTessNormal(GLUtesselator *tess, GLdouble valueX, GLdouble valueY, GLdouble valueZ)
{
/* dummy function */
(void) tess;
(void) valueX;
(void) valueY;
(void) valueZ;
}

View file

@ -1,107 +0,0 @@
/*
* 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
*/
#ifndef TESS_H
#define TESS_H
#include "gluP.h"
#define EPSILON 1e-06 /* epsilon for double precision compares */
typedef enum
{
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;
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;
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;
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 GLUtesselator
{
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;
};
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 *);
#endif

View file

@ -1,406 +0,0 @@
/*
* 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) ();
}