1f220fa62Smrg/*
2f220fa62Smrg** License Applicability. Except to the extent portions of this file are
3f220fa62Smrg** made subject to an alternative license as permitted in the SGI Free
4f220fa62Smrg** Software License B, Version 1.1 (the "License"), the contents of this
5f220fa62Smrg** file are subject only to the provisions of the License. You may not use
6f220fa62Smrg** this file except in compliance with the License. You may obtain a copy
7f220fa62Smrg** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
8f220fa62Smrg** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
9f220fa62Smrg**
10f220fa62Smrg** http://oss.sgi.com/projects/FreeB
11f220fa62Smrg**
12f220fa62Smrg** Note that, as provided in the License, the Software is distributed on an
13f220fa62Smrg** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
14f220fa62Smrg** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
15f220fa62Smrg** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
16f220fa62Smrg** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
17f220fa62Smrg**
18f220fa62Smrg** Original Code. The Original Code is: OpenGL Sample Implementation,
19f220fa62Smrg** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
20f220fa62Smrg** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
21f220fa62Smrg** Copyright in any portions created by third parties is as indicated
22f220fa62Smrg** elsewhere herein. All Rights Reserved.
23f220fa62Smrg**
24f220fa62Smrg** Additional Notice Provisions: The application programming interfaces
25f220fa62Smrg** established by SGI in conjunction with the Original Code are The
26f220fa62Smrg** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
27f220fa62Smrg** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
28f220fa62Smrg** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
29f220fa62Smrg** Window System(R) (Version 1.3), released October 19, 1998. This software
30f220fa62Smrg** was created using the OpenGL(R) version 1.2.1 Sample Implementation
31f220fa62Smrg** published by SGI, but has not been independently verified as being
32f220fa62Smrg** compliant with the OpenGL(R) version 1.2.1 Specification.
33f220fa62Smrg**
34f220fa62Smrg*/
35f220fa62Smrg/*
36f220fa62Smrg*/
37f220fa62Smrg
38f220fa62Smrg#include "gluos.h"
39f220fa62Smrg#include <GL/gl.h>
40f220fa62Smrg#include <GL/glu.h>
41f220fa62Smrg#include <stdio.h>
42f220fa62Smrg#include "glimports.h"
43f220fa62Smrg#include "glrenderer.h"
44f220fa62Smrg#include "nurbsconsts.h"
45f220fa62Smrg
46f220fa62Smrg//#define DOWN_LOAD_NURBS
47f220fa62Smrg#ifdef DOWN_LOAD_NURBS
48f220fa62Smrg
49f220fa62Smrg#include "oglTrimNurbs.h"
50f220fa62Smrgstatic int surfcount = 0;
51f220fa62Smrgstatic oglTrimNurbs* otn = NULL;
52f220fa62SmrgnurbSurf* tempNurb = NULL;
53f220fa62SmrgoglTrimLoops* tempTrim = NULL;
54f220fa62Smrg#endif
55f220fa62Smrg
56f220fa62Smrg
57f220fa62Smrg//for LOD
58f220fa62Smrgextern "C" {void glu_LOD_eval_list(GLUnurbs *nurb, int level);}
59f220fa62Smrg
60f220fa62Smrgvoid glu_LOD_eval_list(GLUnurbs *nurb, int level)
61f220fa62Smrg{
62f220fa62Smrg	nurb->LOD_eval_list(level);
63f220fa62Smrg}
64f220fa62Smrg
65f220fa62SmrgGLUnurbs * GLAPIENTRY
66f220fa62SmrggluNewNurbsRenderer(void)
67f220fa62Smrg{
68f220fa62Smrg  GLUnurbs *t;
69f220fa62Smrg
70f220fa62Smrg  t = new GLUnurbs();
71f220fa62Smrg  return t;
72f220fa62Smrg}
73f220fa62Smrg
74f220fa62Smrgvoid GLAPIENTRY
75f220fa62SmrggluDeleteNurbsRenderer(GLUnurbs *r)
76f220fa62Smrg{
77f220fa62Smrg    delete r;
78f220fa62Smrg}
79f220fa62Smrg
80f220fa62Smrgextern "C"
81f220fa62Smrgvoid GLAPIENTRY
82f220fa62Smrg
83f220fa62SmrggluDeleteNurbsTessellatorEXT(GLUnurbsObj *r)
84f220fa62Smrg{
85f220fa62Smrg  delete r;
86f220fa62Smrg}
87f220fa62Smrg
88f220fa62Smrgvoid GLAPIENTRY
89f220fa62SmrggluBeginSurface(GLUnurbs *r)
90f220fa62Smrg{
91f220fa62Smrg#ifdef DOWN_LOAD_NURBS
92f220fa62Smrgsurfcount++;
93f220fa62SmrgtempTrim = OTL_make(10,10);
94f220fa62Smrg#endif
95f220fa62Smrg    r->bgnsurface(0);
96f220fa62Smrg}
97f220fa62Smrg
98f220fa62Smrgvoid GLAPIENTRY
99f220fa62SmrggluBeginCurve(GLUnurbs *r)
100f220fa62Smrg{
101f220fa62Smrg    r->bgncurve(0);
102f220fa62Smrg}
103f220fa62Smrg
104f220fa62Smrgvoid GLAPIENTRY
105f220fa62SmrggluEndCurve(GLUnurbs *r)
106f220fa62Smrg{
107f220fa62Smrg    r->endcurve();
108f220fa62Smrg}
109f220fa62Smrg
110f220fa62Smrgvoid GLAPIENTRY
111f220fa62SmrggluEndSurface(GLUnurbs *r)
112f220fa62Smrg{
113f220fa62Smrg#ifdef DOWN_LOAD_NURBS
114f220fa62Smrgif(surfcount == 1)
115f220fa62Smrg  otn = OTN_make(1);
116f220fa62SmrgOTN_insert(otn, tempNurb, tempTrim);
117f220fa62Smrgif(surfcount  >= 1)
118f220fa62Smrg{
119f220fa62Smrg#ifdef DEBUG
120f220fa62Smrgprintf("write file\n");
121f220fa62Smrg#endif
122f220fa62SmrgOTN_write(otn, "out.otn");
123f220fa62Smrg
124f220fa62Smrg}
125f220fa62Smrg#endif
126f220fa62Smrg
127f220fa62Smrg    r->endsurface();
128f220fa62Smrg}
129f220fa62Smrg
130f220fa62Smrgvoid GLAPIENTRY
131f220fa62SmrggluBeginTrim(GLUnurbs *r)
132f220fa62Smrg{
133f220fa62Smrg#ifdef DOWN_LOAD_NURBS
134f220fa62SmrgOTL_bgnTrim(tempTrim);
135f220fa62Smrg#endif
136f220fa62Smrg
137f220fa62Smrg    r->bgntrim();
138f220fa62Smrg}
139f220fa62Smrg
140f220fa62Smrgvoid GLAPIENTRY
141f220fa62SmrggluEndTrim(GLUnurbs *r)
142f220fa62Smrg{
143f220fa62Smrg#ifdef DOWN_LOAD_NURBS
144f220fa62SmrgOTL_endTrim(tempTrim);
145f220fa62Smrg#endif
146f220fa62Smrg    r->endtrim();
147f220fa62Smrg}
148f220fa62Smrg
149f220fa62Smrgvoid GLAPIENTRY
150f220fa62SmrggluPwlCurve(GLUnurbs *r, GLint count, INREAL array[],
151f220fa62Smrg		GLint stride, GLenum type)
152f220fa62Smrg{
153f220fa62Smrg#ifdef DOWN_LOAD_NURBS
154f220fa62SmrgOTL_pwlCurve(tempTrim, count, array, stride, type);
155f220fa62Smrg#endif
156f220fa62Smrg
157f220fa62Smrg    int realType;
158f220fa62Smrg    switch(type) {
159f220fa62Smrg      case GLU_MAP1_TRIM_2:
160f220fa62Smrg	realType = N_P2D;
161f220fa62Smrg	break;
162f220fa62Smrg      case GLU_MAP1_TRIM_3:
163f220fa62Smrg	realType = N_P2DR;
164f220fa62Smrg	break;
165f220fa62Smrg      default:
166f220fa62Smrg	realType = type;
167f220fa62Smrg	break;
168f220fa62Smrg    }
169f220fa62Smrg    r->pwlcurve(count, array, sizeof(INREAL) * stride, realType);
170f220fa62Smrg}
171f220fa62Smrg
172f220fa62Smrgvoid GLAPIENTRY
173f220fa62SmrggluNurbsCurve(GLUnurbs *r, GLint nknots, INREAL knot[], GLint stride,
174f220fa62Smrg		  INREAL ctlarray[], GLint order, GLenum type)
175f220fa62Smrg{
176f220fa62Smrg#ifdef DOWN_LOAD_NURBS
177f220fa62SmrgOTL_nurbsCurve(tempTrim, nknots, knot, stride, ctlarray, order, type);
178f220fa62Smrg#endif
179f220fa62Smrg
180f220fa62Smrg    int realType;
181f220fa62Smrg
182f220fa62Smrg    switch(type) {
183f220fa62Smrg      case GLU_MAP1_TRIM_2:
184f220fa62Smrg	realType = N_P2D;
185f220fa62Smrg	break;
186f220fa62Smrg      case GLU_MAP1_TRIM_3:
187f220fa62Smrg	realType = N_P2DR;
188f220fa62Smrg	break;
189f220fa62Smrg      default:
190f220fa62Smrg	realType = type;
191f220fa62Smrg	break;
192f220fa62Smrg    }
193f220fa62Smrg
194f220fa62Smrg    r->nurbscurve(nknots, knot, sizeof(INREAL) * stride, ctlarray, order,
195f220fa62Smrg	    realType);
196f220fa62Smrg}
197f220fa62Smrg
198f220fa62Smrgvoid GLAPIENTRY
199f220fa62SmrggluNurbsSurface(GLUnurbs *r, GLint sknot_count, GLfloat *sknot,
200f220fa62Smrg			    GLint tknot_count, GLfloat *tknot,
201f220fa62Smrg			    GLint s_stride, GLint t_stride,
202f220fa62Smrg			    GLfloat *ctlarray, GLint sorder, GLint torder,
203f220fa62Smrg			    GLenum type)
204f220fa62Smrg{
205f220fa62Smrg#ifdef DOWN_LOAD_NURBS
206f220fa62Smrg  {
207f220fa62Smrg    int dimension;
208f220fa62Smrg    switch(type){
209f220fa62Smrg    case GL_MAP2_VERTEX_3:
210f220fa62Smrg      dimension = 3;
211f220fa62Smrg      break;
212f220fa62Smrg    case GL_MAP2_VERTEX_4:
213f220fa62Smrg      dimension = 4;
214f220fa62Smrg      break;
215f220fa62Smrg    default:
216f220fa62Smrg      fprintf(stderr, "error in glinterface.c++, type no implemented\n");
217f220fa62Smrg      exit(1);
218f220fa62Smrg    }
219f220fa62SmrgtempNurb = nurbSurfMake(sknot_count, sknot,
220f220fa62Smrg			tknot_count, tknot,
221f220fa62Smrg			sorder, torder,
222f220fa62Smrg			dimension,
223f220fa62Smrg			ctlarray,
224f220fa62Smrg			s_stride, t_stride);
225f220fa62Smrg
226f220fa62Smrg  }
227f220fa62Smrg#endif
228f220fa62Smrg
229f220fa62Smrg    r->nurbssurface(sknot_count, sknot, tknot_count, tknot,
230f220fa62Smrg	    sizeof(INREAL) * s_stride, sizeof(INREAL) * t_stride,
231f220fa62Smrg	    ctlarray, sorder, torder, type);
232f220fa62Smrg}
233f220fa62Smrg
234f220fa62Smrgvoid GLAPIENTRY
235f220fa62SmrggluLoadSamplingMatrices(GLUnurbs *r, const GLfloat modelMatrix[16],
236f220fa62Smrg			    const GLfloat projMatrix[16],
237f220fa62Smrg			    const GLint viewport[4])
238f220fa62Smrg{
239f220fa62Smrg    r->useGLMatrices(modelMatrix, projMatrix, viewport);
240f220fa62Smrg}
241f220fa62Smrg
242f220fa62Smrgvoid GLAPIENTRY
243f220fa62SmrggluNurbsProperty(GLUnurbs *r, GLenum property, GLfloat value)
244f220fa62Smrg{
245f220fa62Smrg    GLfloat nurbsValue;
246f220fa62Smrg
247f220fa62Smrg    switch (property) {
248f220fa62Smrg      case GLU_AUTO_LOAD_MATRIX:
249f220fa62Smrg        r->setautoloadmode(value);
250f220fa62Smrg	return;
251f220fa62Smrg
252f220fa62Smrg      case GLU_CULLING:
253f220fa62Smrg	if (value != 0.0) {
254f220fa62Smrg	    nurbsValue = N_CULLINGON;
255f220fa62Smrg	} else {
256f220fa62Smrg	    nurbsValue = N_NOCULLING;
257f220fa62Smrg	}
258f220fa62Smrg	r->setnurbsproperty(GL_MAP2_VERTEX_3, N_CULLING, nurbsValue);
259f220fa62Smrg	r->setnurbsproperty(GL_MAP2_VERTEX_4, N_CULLING, nurbsValue);
260f220fa62Smrg	r->setnurbsproperty(GL_MAP1_VERTEX_3, N_CULLING, nurbsValue);
261f220fa62Smrg	r->setnurbsproperty(GL_MAP1_VERTEX_4, N_CULLING, nurbsValue);
262f220fa62Smrg        return;
263f220fa62Smrg
264f220fa62Smrg      case GLU_SAMPLING_METHOD:
265f220fa62Smrg	if (value == GLU_PATH_LENGTH) {
266f220fa62Smrg	    nurbsValue = N_PATHLENGTH;
267f220fa62Smrg	} else if (value == GLU_PARAMETRIC_ERROR) {
268f220fa62Smrg	    nurbsValue = N_PARAMETRICDISTANCE;
269f220fa62Smrg	} else if (value == GLU_DOMAIN_DISTANCE) {
270f220fa62Smrg	    nurbsValue = N_DOMAINDISTANCE;
271f220fa62Smrg            r->set_is_domain_distance_sampling(1); //optimzing untrimmed case
272f220fa62Smrg
273f220fa62Smrg	} else if (value == GLU_OBJECT_PARAMETRIC_ERROR) {
274f220fa62Smrg	    nurbsValue = N_OBJECTSPACE_PARA;
275f220fa62Smrg	    r->setautoloadmode( 0.0 );
276f220fa62Smrg	    r->setSamplingMatrixIdentity();
277f220fa62Smrg	} else if (value == GLU_OBJECT_PATH_LENGTH) {
278f220fa62Smrg	    nurbsValue = N_OBJECTSPACE_PATH;
279f220fa62Smrg	    r->setautoloadmode( 0.0 );
280f220fa62Smrg	    r->setSamplingMatrixIdentity();
281f220fa62Smrg	} else {
282f220fa62Smrg            r->postError(GLU_INVALID_VALUE);
283f220fa62Smrg            return;
284f220fa62Smrg        }
285f220fa62Smrg
286f220fa62Smrg	r->setnurbsproperty(GL_MAP2_VERTEX_3, N_SAMPLINGMETHOD, nurbsValue);
287f220fa62Smrg	r->setnurbsproperty(GL_MAP2_VERTEX_4, N_SAMPLINGMETHOD, nurbsValue);
288f220fa62Smrg	r->setnurbsproperty(GL_MAP1_VERTEX_3, N_SAMPLINGMETHOD, nurbsValue);
289f220fa62Smrg	r->setnurbsproperty(GL_MAP1_VERTEX_4, N_SAMPLINGMETHOD, nurbsValue);
290f220fa62Smrg	return;
291f220fa62Smrg
292f220fa62Smrg      case GLU_SAMPLING_TOLERANCE:
293f220fa62Smrg	r->setnurbsproperty(GL_MAP2_VERTEX_3, N_PIXEL_TOLERANCE, value);
294f220fa62Smrg	r->setnurbsproperty(GL_MAP2_VERTEX_4, N_PIXEL_TOLERANCE, value);
295f220fa62Smrg	r->setnurbsproperty(GL_MAP1_VERTEX_3, N_PIXEL_TOLERANCE, value);
296f220fa62Smrg	r->setnurbsproperty(GL_MAP1_VERTEX_4, N_PIXEL_TOLERANCE, value);
297f220fa62Smrg	return;
298f220fa62Smrg
299f220fa62Smrg      case GLU_PARAMETRIC_TOLERANCE:
300f220fa62Smrg	r->setnurbsproperty(GL_MAP2_VERTEX_3, N_ERROR_TOLERANCE, value);
301f220fa62Smrg        r->setnurbsproperty(GL_MAP2_VERTEX_4, N_ERROR_TOLERANCE, value);
302f220fa62Smrg        r->setnurbsproperty(GL_MAP1_VERTEX_3, N_ERROR_TOLERANCE, value);
303f220fa62Smrg        r->setnurbsproperty(GL_MAP1_VERTEX_4, N_ERROR_TOLERANCE, value);
304f220fa62Smrg        return;
305f220fa62Smrg
306f220fa62Smrg
307f220fa62Smrg      case GLU_DISPLAY_MODE:
308f220fa62Smrg
309f220fa62Smrg	if (value == GLU_FILL) {
310f220fa62Smrg	  nurbsValue = N_FILL;
311f220fa62Smrg	} else if (value == GLU_OUTLINE_POLYGON) {
312f220fa62Smrg	  nurbsValue = N_OUTLINE_POLY;
313f220fa62Smrg	} else if (value == GLU_OUTLINE_PATCH) {
314f220fa62Smrg	  nurbsValue = N_OUTLINE_PATCH;
315f220fa62Smrg	} else {
316f220fa62Smrg	  r->postError(GLU_INVALID_VALUE);
317f220fa62Smrg	  return;
318f220fa62Smrg	}
319f220fa62Smrg	r->setnurbsproperty(N_DISPLAY, nurbsValue);
320f220fa62Smrg
321f220fa62Smrg	break;
322f220fa62Smrg
323f220fa62Smrg      case GLU_U_STEP:
324f220fa62Smrg    	r->setnurbsproperty(GL_MAP1_VERTEX_3, N_S_STEPS, value);
325f220fa62Smrg    	r->setnurbsproperty(GL_MAP1_VERTEX_4, N_S_STEPS, value);
326f220fa62Smrg    	r->setnurbsproperty(GL_MAP2_VERTEX_3, N_S_STEPS, value);
327f220fa62Smrg    	r->setnurbsproperty(GL_MAP2_VERTEX_4, N_S_STEPS, value);
328f220fa62Smrg
329f220fa62Smrg	//added for optimizing untrimmed case
330f220fa62Smrg        r->set_domain_distance_u_rate(value);
331f220fa62Smrg	break;
332f220fa62Smrg
333f220fa62Smrg      case GLU_V_STEP:
334f220fa62Smrg        r->setnurbsproperty(GL_MAP1_VERTEX_3, N_T_STEPS, value);
335f220fa62Smrg        r->setnurbsproperty(GL_MAP1_VERTEX_4, N_T_STEPS, value);
336f220fa62Smrg        r->setnurbsproperty(GL_MAP2_VERTEX_3, N_T_STEPS, value);
337f220fa62Smrg        r->setnurbsproperty(GL_MAP2_VERTEX_4, N_T_STEPS, value);
338f220fa62Smrg
339f220fa62Smrg	//added for optimizing untrimmed case
340f220fa62Smrg        r->set_domain_distance_v_rate(value);
341f220fa62Smrg	break;
342f220fa62Smrg
343f220fa62Smrg      case GLU_NURBS_MODE:
344f220fa62Smrg	if(value == GLU_NURBS_RENDERER)
345f220fa62Smrg	  r->put_callbackFlag(0);
346f220fa62Smrg	else if(value == GLU_NURBS_TESSELLATOR)
347f220fa62Smrg	  r->put_callbackFlag(1);
348f220fa62Smrg	else
349f220fa62Smrg	  r->postError(GLU_INVALID_ENUM);
350f220fa62Smrg	break;
351f220fa62Smrg
352f220fa62Smrg      default:
353f220fa62Smrg	r->postError(GLU_INVALID_ENUM);
354f220fa62Smrg	return;
355f220fa62Smrg    }
356f220fa62Smrg}
357f220fa62Smrg
358f220fa62Smrgvoid GLAPIENTRY
359f220fa62SmrggluGetNurbsProperty(GLUnurbs *r, GLenum property, GLfloat *value)
360f220fa62Smrg{
361f220fa62Smrg    GLfloat nurbsValue;
362f220fa62Smrg
363f220fa62Smrg    switch(property) {
364f220fa62Smrg      case GLU_AUTO_LOAD_MATRIX:
365f220fa62Smrg	if (r->getautoloadmode()) {
366f220fa62Smrg	    *value = GL_TRUE;
367f220fa62Smrg	} else {
368f220fa62Smrg	    *value = GL_FALSE;
369f220fa62Smrg	}
370f220fa62Smrg	break;
371f220fa62Smrg      case GLU_CULLING:
372f220fa62Smrg	r->getnurbsproperty(GL_MAP2_VERTEX_3, N_CULLING, &nurbsValue);
373f220fa62Smrg	if (nurbsValue == N_CULLINGON) {
374f220fa62Smrg	    *value = GL_TRUE;
375f220fa62Smrg	} else {
376f220fa62Smrg	    *value = GL_FALSE;
377f220fa62Smrg	}
378f220fa62Smrg	break;
379f220fa62Smrg      case GLU_SAMPLING_METHOD:
380f220fa62Smrg	r->getnurbsproperty(GL_MAP2_VERTEX_3, N_SAMPLINGMETHOD, value);
381f220fa62Smrg	if(*value == N_PATHLENGTH)
382f220fa62Smrg	  *value = GLU_PATH_LENGTH;
383f220fa62Smrg	else if(*value == N_PARAMETRICDISTANCE)
384f220fa62Smrg	  *value = GLU_PARAMETRIC_ERROR;
385f220fa62Smrg	else if(*value == N_DOMAINDISTANCE)
386f220fa62Smrg	  *value = GLU_DOMAIN_DISTANCE;
387f220fa62Smrg	else if(*value == N_OBJECTSPACE_PATH)
388f220fa62Smrg	  *value = GLU_OBJECT_PATH_LENGTH;
389f220fa62Smrg	else if(*value == N_OBJECTSPACE_PARA)
390f220fa62Smrg	  *value = GLU_OBJECT_PARAMETRIC_ERROR;
391f220fa62Smrg	break;
392f220fa62Smrg      case GLU_SAMPLING_TOLERANCE:
393f220fa62Smrg	r->getnurbsproperty(GL_MAP2_VERTEX_3, N_PIXEL_TOLERANCE, value);
394f220fa62Smrg	break;
395f220fa62Smrg      case GLU_PARAMETRIC_TOLERANCE:
396f220fa62Smrg	r->getnurbsproperty(GL_MAP2_VERTEX_3, N_ERROR_TOLERANCE, value);
397f220fa62Smrg        break;
398f220fa62Smrg
399f220fa62Smrg      case GLU_U_STEP:
400f220fa62Smrg    	r->getnurbsproperty(GL_MAP2_VERTEX_3, N_S_STEPS, value);
401f220fa62Smrg	break;
402f220fa62Smrg      case GLU_V_STEP:
403f220fa62Smrg    	r->getnurbsproperty(GL_MAP2_VERTEX_3, N_T_STEPS, value);
404f220fa62Smrg	break;
405f220fa62Smrg      case GLU_DISPLAY_MODE:
406f220fa62Smrg	r->getnurbsproperty(N_DISPLAY, &nurbsValue);
407f220fa62Smrg	if (nurbsValue == N_FILL) {
408f220fa62Smrg	    *value = GLU_FILL;
409f220fa62Smrg	} else if (nurbsValue == N_OUTLINE_POLY) {
410f220fa62Smrg	    *value = GLU_OUTLINE_POLYGON;
411f220fa62Smrg	} else {
412f220fa62Smrg	    *value = GLU_OUTLINE_PATCH;
413f220fa62Smrg	}
414f220fa62Smrg	break;
415f220fa62Smrg
416f220fa62Smrg      case GLU_NURBS_MODE:
417f220fa62Smrg	if(r->is_callback())
418f220fa62Smrg	  *value = GLU_NURBS_TESSELLATOR;
419f220fa62Smrg	else
420f220fa62Smrg	  *value = GLU_NURBS_RENDERER;
421f220fa62Smrg	break;
422f220fa62Smrg
423f220fa62Smrg      default:
424f220fa62Smrg	r->postError(GLU_INVALID_ENUM);
425f220fa62Smrg	return;
426f220fa62Smrg    }
427f220fa62Smrg}
428f220fa62Smrg
429f220fa62Smrgextern "C" void GLAPIENTRY
430f220fa62SmrggluNurbsCallback(GLUnurbs *r, GLenum which, _GLUfuncptr fn )
431f220fa62Smrg{
432f220fa62Smrg    switch (which) {
433f220fa62Smrg    case GLU_NURBS_BEGIN:
434f220fa62Smrg    case GLU_NURBS_END:
435f220fa62Smrg    case GLU_NURBS_VERTEX:
436f220fa62Smrg    case GLU_NURBS_NORMAL:
437f220fa62Smrg    case GLU_NURBS_TEXTURE_COORD:
438f220fa62Smrg    case GLU_NURBS_COLOR:
439f220fa62Smrg    case GLU_NURBS_BEGIN_DATA:
440f220fa62Smrg    case GLU_NURBS_END_DATA:
441f220fa62Smrg    case GLU_NURBS_VERTEX_DATA:
442f220fa62Smrg    case GLU_NURBS_NORMAL_DATA:
443f220fa62Smrg    case GLU_NURBS_TEXTURE_COORD_DATA:
444f220fa62Smrg    case GLU_NURBS_COLOR_DATA:
445f220fa62Smrg	r->putSurfCallBack(which, fn);
446f220fa62Smrg	break;
447f220fa62Smrg
448f220fa62Smrg    case GLU_NURBS_ERROR:
449f220fa62Smrg	r->errorCallback = (void (APIENTRY *)( GLenum e )) fn;
450f220fa62Smrg	break;
451f220fa62Smrg    default:
452f220fa62Smrg	r->postError(GLU_INVALID_ENUM);
453f220fa62Smrg	return;
454f220fa62Smrg    }
455f220fa62Smrg}
456f220fa62Smrg
457f220fa62Smrgextern "C"
458f220fa62Smrgvoid GLAPIENTRY
459f220fa62SmrggluNurbsCallbackDataEXT(GLUnurbs* r, void* userData)
460f220fa62Smrg{
461f220fa62Smrg  r->setNurbsCallbackData(userData);
462f220fa62Smrg}
463f220fa62Smrg
464f220fa62Smrgextern "C"
465f220fa62Smrgvoid GLAPIENTRY
466f220fa62SmrggluNurbsCallbackData(GLUnurbs* r, void* userData)
467f220fa62Smrg{
468f220fa62Smrg  gluNurbsCallbackDataEXT(r,userData);
469f220fa62Smrg}
470