Blame |
Last modification |
View Log
| RSS feed
/* $Id: nurbs.c,v 1.1 2003-02-28 11:42:07 pj Exp $ */
/*
* Mesa 3-D graphics library
* Version: 3.3
* Copyright (C) 1995-2000 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* 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
;
}