mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-02-25 18:00:52 +01:00
Remove unused mini and mesa glu subdirectories
This commit is contained in:
parent
b15fe60ba5
commit
44f78eb18e
34 changed files with 0 additions and 13732 deletions
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
|
|
@ -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)
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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.
|
||||
|
||||
|
|
@ -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.
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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) ();
|
||||
}
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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) ();
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue