1/*
2 * Copyright (c) 1991, 1992, 1993 Silicon Graphics, Inc.
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that (i) the above copyright notices and this permission notice appear in
7 * all copies of the software and related documentation, and (ii) the name of
8 * Silicon Graphics may not be used in any advertising or
9 * publicity relating to the software without the specific, prior written
10 * permission of Silicon Graphics.
11 *
12 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF
13 * ANY KIND,
14 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
15 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
16 *
17 * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR
18 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
19 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
21 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
22 * OF THIS SOFTWARE.
23 */
24
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <math.h>
29#include "glut_wrap.h"
30
31
32#define INREAL float
33
34#define S_NUMPOINTS 13
35#define S_ORDER     3
36#define S_NUMKNOTS  (S_NUMPOINTS + S_ORDER)
37#define T_NUMPOINTS 3
38#define T_ORDER     3
39#define T_NUMKNOTS  (T_NUMPOINTS + T_ORDER)
40#define SQRT_TWO    1.41421356237309504880
41
42
43typedef INREAL Point[4];
44
45
46GLenum doubleBuffer;
47
48GLenum expectedError;
49GLint rotX = 40, rotY = 40;
50INREAL sknots[S_NUMKNOTS] = {
51    -1.0, -1.0, -1.0, 0.0, 1.0, 2.0, 3.0, 4.0,
52    4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 9.0, 9.0
53};
54INREAL tknots[T_NUMKNOTS] = {
55    1.0, 1.0, 1.0, 2.0, 2.0, 2.0
56};
57Point ctlpoints[S_NUMPOINTS][T_NUMPOINTS] = {
58    {
59	{
60	    4.0, 2.0, 2.0, 1.0
61	},
62	{
63	    4.0, 1.6, 2.5, 1.0
64	},
65	{
66	    4.0, 2.0, 3.0, 1.0
67	}
68    },
69    {
70	{
71	    5.0, 4.0, 2.0, 1.0
72	},
73	{
74	    5.0, 4.0, 2.5, 1.0
75	},
76	{
77	    5.0, 4.0, 3.0, 1.0
78	}
79    },
80    {
81	{
82	    6.0, 5.0, 2.0, 1.0
83	},
84	{
85	    6.0, 5.0, 2.5, 1.0
86	},
87	{
88	    6.0, 5.0, 3.0, 1.0
89	}
90    },
91    {
92	{
93	    SQRT_TWO*6.0, SQRT_TWO*6.0, SQRT_TWO*2.0, SQRT_TWO
94	},
95	{
96	    SQRT_TWO*6.0, SQRT_TWO*6.0, SQRT_TWO*2.5, SQRT_TWO
97	},
98	{
99	    SQRT_TWO*6.0, SQRT_TWO*6.0, SQRT_TWO*3.0, SQRT_TWO
100	}
101    },
102    {
103	{
104	    5.2, 6.7, 2.0, 1.0
105	},
106	{
107	    5.2, 6.7, 2.5, 1.0
108	},
109	{
110	    5.2, 6.7, 3.0, 1.0
111	}
112    },
113    {
114	{
115	    SQRT_TWO*4.0, SQRT_TWO*6.0, SQRT_TWO*2.0, SQRT_TWO
116	},
117	{
118	    SQRT_TWO*4.0, SQRT_TWO*6.0, SQRT_TWO*2.5, SQRT_TWO
119	},
120	{
121	    SQRT_TWO*4.0, SQRT_TWO*6.0, SQRT_TWO*3.0, SQRT_TWO
122	}
123    },
124    {
125	{
126	    4.0, 5.2, 2.0, 1.0
127	},
128	{
129	    4.0, 4.6, 2.5, 1.0
130	},
131	{
132	    4.0, 5.2, 3.0, 1.0
133	}
134    },
135    {
136	{
137	    SQRT_TWO*4.0, SQRT_TWO*6.0, SQRT_TWO*2.0, SQRT_TWO
138	},
139	{
140	    SQRT_TWO*4.0, SQRT_TWO*6.0, SQRT_TWO*2.5, SQRT_TWO
141	},
142	{
143	    SQRT_TWO*4.0, SQRT_TWO*6.0, SQRT_TWO*3.0, SQRT_TWO
144	}
145    },
146    {
147	{
148	    2.8, 6.7, 2.0, 1.0
149	},
150	{
151	    2.8, 6.7, 2.5, 1.0
152	},
153	{
154	    2.8, 6.7, 3.0, 1.0
155	}
156    },
157    {
158	{
159	    SQRT_TWO*2.0, SQRT_TWO*6.0, SQRT_TWO*2.0, SQRT_TWO
160	},
161	{
162	    SQRT_TWO*2.0, SQRT_TWO*6.0, SQRT_TWO*2.5, SQRT_TWO
163	},
164	{
165	    SQRT_TWO*2.0, SQRT_TWO*6.0, SQRT_TWO*3.0, SQRT_TWO
166	}
167    },
168    {
169	{
170	    2.0, 5.0, 2.0, 1.0
171	},
172	{
173	    2.0, 5.0, 2.5, 1.0
174	},
175	{
176	    2.0, 5.0, 3.0, 1.0
177	}
178    },
179    {
180	{
181	    3.0, 4.0, 2.0, 1.0
182	},
183	{
184	    3.0, 4.0, 2.5, 1.0
185	},
186	{
187	    3.0, 4.0, 3.0, 1.0
188	}
189    },
190    {
191	{
192	    4.0, 2.0, 2.0, 1.0
193	},
194	{
195	    4.0, 1.6, 2.5, 1.0
196	},
197	{
198	    4.0, 2.0, 3.0, 1.0
199	}
200    }
201};
202GLUnurbsObj *theNurbs;
203
204
205static void GLAPIENTRY ErrorCallback(GLenum which)
206{
207
208    if (which != expectedError) {
209	fprintf(stderr, "Unexpected error occured (%d):\n", which);
210	fprintf(stderr, "    %s\n", (char *) gluErrorString(which));
211    }
212}
213
214static void Init(void)
215{
216
217    theNurbs = gluNewNurbsRenderer();
218    gluNurbsCallback(theNurbs, GLU_ERROR, ErrorCallback);
219
220    gluNurbsProperty(theNurbs, GLU_SAMPLING_TOLERANCE, 15.0);
221    gluNurbsProperty(theNurbs, GLU_DISPLAY_MODE, GLU_OUTLINE_PATCH);
222
223    expectedError = GLU_INVALID_ENUM;
224    gluNurbsProperty(theNurbs, ~0, 15.0);
225    expectedError = GLU_NURBS_ERROR13;
226    gluEndSurface(theNurbs);
227    expectedError = 0;
228
229    glColor3f(1.0, 1.0, 1.0);
230}
231
232static void Reshape(int width, int height)
233{
234
235    glViewport(0, 0, (GLint)width, (GLint)height);
236
237    glMatrixMode(GL_PROJECTION);
238    glLoadIdentity();
239    glFrustum(-2.0, 2.0, -2.0, 2.0, 0.8, 10.0);
240    gluLookAt(7.0, 4.5, 4.0, 4.5, 4.5, 2.5, 6.0, -3.0, 2.0);
241    glMatrixMode(GL_MODELVIEW);
242}
243
244static void Key2(int key, int x, int y)
245{
246
247    switch (key) {
248      case GLUT_KEY_DOWN:
249	rotX -= 5;
250	break;
251      case GLUT_KEY_UP:
252	rotX += 5;
253	break;
254      case GLUT_KEY_LEFT:
255	rotY -= 5;
256	break;
257      case GLUT_KEY_RIGHT:
258	rotY += 5;
259	break;
260      default:
261	return;
262    }
263
264    glutPostRedisplay();
265}
266
267static void Key(unsigned char key, int x, int y)
268{
269
270    switch (key) {
271      case 27:
272	exit(1);
273    }
274}
275
276static void Draw(void)
277{
278
279    glClear(GL_COLOR_BUFFER_BIT);
280
281    glPushMatrix();
282
283    glTranslatef(4.0, 4.5, 2.5);
284    glRotatef(rotY, 1, 0, 0);
285    glRotatef(rotX, 0, 1, 0);
286    glTranslatef(-4.0, -4.5, -2.5);
287
288    gluBeginSurface(theNurbs);
289    gluNurbsSurface(theNurbs, S_NUMKNOTS, sknots, T_NUMKNOTS, tknots,
290		    4*T_NUMPOINTS, 4, &ctlpoints[0][0][0], S_ORDER,
291		    T_ORDER, GL_MAP2_VERTEX_4);
292    gluEndSurface(theNurbs);
293
294    glPopMatrix();
295
296    glFlush();
297
298    if (doubleBuffer) {
299	glutSwapBuffers();
300    }
301}
302
303static GLenum Args(int argc, char **argv)
304{
305    GLint i;
306
307    doubleBuffer = GL_FALSE;
308
309    for (i = 1; i < argc; i++) {
310	if (strcmp(argv[i], "-sb") == 0) {
311	    doubleBuffer = GL_FALSE;
312	} else if (strcmp(argv[i], "-db") == 0) {
313	    doubleBuffer = GL_TRUE;
314	} else {
315	    printf("%s (Bad option).\n", argv[i]);
316	    return GL_FALSE;
317	}
318    }
319    return GL_TRUE;
320}
321
322int main(int argc, char **argv)
323{
324    GLenum type;
325
326    glutInit(&argc, argv);
327
328    if (Args(argc, argv) == GL_FALSE) {
329	exit(1);
330    }
331
332    glutInitWindowPosition(0, 0); glutInitWindowSize( 300, 300);
333
334    type = GLUT_RGB;
335    type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
336    glutInitDisplayMode(type);
337
338    if (glutCreateWindow("NURBS Test") == GL_FALSE) {
339	exit(1);
340    }
341
342    Init();
343
344    glutReshapeFunc(Reshape);
345    glutKeyboardFunc(Key);
346    glutSpecialFunc(Key2);
347    glutDisplayFunc(Draw);
348    glutMainLoop();
349	return 0;
350}
351