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