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