1 /* 2 * Copyright 1994-1997 Mark Kilgard, All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Mark Kilgard 7 */ 8 9 /** 10 (c) Copyright 1993, Silicon Graphics, Inc. 11 12 ALL RIGHTS RESERVED 13 14 Permission to use, copy, modify, and distribute this software 15 for any purpose and without fee is hereby granted, provided 16 that the above copyright notice appear in all copies and that 17 both the copyright notice and this permission notice appear in 18 supporting documentation, and that the name of Silicon 19 Graphics, Inc. not be used in advertising or publicity 20 pertaining to distribution of the software without specific, 21 written prior permission. 22 23 THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU 24 "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR 25 OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF 26 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO 27 EVENT SHALL SILICON GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE 28 ELSE FOR ANY DIRECT, SPECIAL, INCIDENTAL, INDIRECT OR 29 CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER, 30 INCLUDING WITHOUT LIMITATION, LOSS OF PROFIT, LOSS OF USE, 31 SAVINGS OR REVENUE, OR THE CLAIMS OF THIRD PARTIES, WHETHER OR 32 NOT SILICON GRAPHICS, INC. HAS BEEN ADVISED OF THE POSSIBILITY 33 OF SUCH LOSS, HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 34 ARISING OUT OF OR IN CONNECTION WITH THE POSSESSION, USE OR 35 PERFORMANCE OF THIS SOFTWARE. 36 37 US Government Users Restricted Rights 38 39 Use, duplication, or disclosure by the Government is subject to 40 restrictions set forth in FAR 52.227.19(c)(2) or subparagraph 41 (c)(1)(ii) of the Rights in Technical Data and Computer 42 Software clause at DFARS 252.227-7013 and/or in similar or 43 successor clauses in the FAR or the DOD or NASA FAR 44 Supplement. Unpublished-- rights reserved under the copyright 45 laws of the United States. Contractor/manufacturer is Silicon 46 Graphics, Inc., 2011 N. Shoreline Blvd., Mountain View, CA 47 94039-7311. 48 49 OpenGL(TM) is a trademark of Silicon Graphics, Inc. 50 */ 51 52 #include <math.h> 53 #include "glutint.h" 54 55 /* Some <math.h> files do not define M_PI... */ 56 #ifndef M_PI 57 #define M_PI 3.14159265358979323846 58 #endif 59 60 static GLUquadricObj *quadObj; 61 62 #define QUAD_OBJ_INIT() { if(!quadObj) initQuadObj(); } 63 64 static void 65 initQuadObj(void) 66 { 67 quadObj = gluNewQuadric(); 68 if (!quadObj) 69 __glutFatalError("out of memory."); 70 } 71 72 /* CENTRY */ 73 void APIENTRY 74 glutWireSphere(GLdouble radius, GLint slices, GLint stacks) 75 { 76 QUAD_OBJ_INIT(); 77 gluQuadricDrawStyle(quadObj, GLU_LINE); 78 gluQuadricNormals(quadObj, GLU_SMOOTH); 79 /* If we ever changed/used the texture or orientation state 80 of quadObj, we'd need to change it to the defaults here 81 with gluQuadricTexture and/or gluQuadricOrientation. */ 82 gluSphere(quadObj, radius, slices, stacks); 83 } 84 85 void APIENTRY 86 glutSolidSphere(GLdouble radius, GLint slices, GLint stacks) 87 { 88 QUAD_OBJ_INIT(); 89 gluQuadricDrawStyle(quadObj, GLU_FILL); 90 gluQuadricNormals(quadObj, GLU_SMOOTH); 91 /* If we ever changed/used the texture or orientation state 92 of quadObj, we'd need to change it to the defaults here 93 with gluQuadricTexture and/or gluQuadricOrientation. */ 94 gluSphere(quadObj, radius, slices, stacks); 95 } 96 97 void APIENTRY 98 glutWireCone(GLdouble base, GLdouble height, 99 GLint slices, GLint stacks) 100 { 101 QUAD_OBJ_INIT(); 102 gluQuadricDrawStyle(quadObj, GLU_LINE); 103 gluQuadricNormals(quadObj, GLU_SMOOTH); 104 /* If we ever changed/used the texture or orientation state 105 of quadObj, we'd need to change it to the defaults here 106 with gluQuadricTexture and/or gluQuadricOrientation. */ 107 gluCylinder(quadObj, base, 0.0, height, slices, stacks); 108 } 109 110 void APIENTRY 111 glutSolidCone(GLdouble base, GLdouble height, 112 GLint slices, GLint stacks) 113 { 114 QUAD_OBJ_INIT(); 115 gluQuadricDrawStyle(quadObj, GLU_FILL); 116 gluQuadricNormals(quadObj, GLU_SMOOTH); 117 /* If we ever changed/used the texture or orientation state 118 of quadObj, we'd need to change it to the defaults here 119 with gluQuadricTexture and/or gluQuadricOrientation. */ 120 gluCylinder(quadObj, base, 0.0, height, slices, stacks); 121 } 122 123 /* ENDCENTRY */ 124 125 static void 126 drawBox(GLfloat size, GLenum type) 127 { 128 static GLfloat n[6][3] = 129 { 130 {-1.0, 0.0, 0.0}, 131 {0.0, 1.0, 0.0}, 132 {1.0, 0.0, 0.0}, 133 {0.0, -1.0, 0.0}, 134 {0.0, 0.0, 1.0}, 135 {0.0, 0.0, -1.0} 136 }; 137 static GLint faces[6][4] = 138 { 139 {0, 1, 2, 3}, 140 {3, 2, 6, 7}, 141 {7, 6, 5, 4}, 142 {4, 5, 1, 0}, 143 {5, 6, 2, 1}, 144 {7, 4, 0, 3} 145 }; 146 GLfloat v[8][3]; 147 GLint i; 148 149 v[0][0] = v[1][0] = v[2][0] = v[3][0] = -size / 2; 150 v[4][0] = v[5][0] = v[6][0] = v[7][0] = size / 2; 151 v[0][1] = v[1][1] = v[4][1] = v[5][1] = -size / 2; 152 v[2][1] = v[3][1] = v[6][1] = v[7][1] = size / 2; 153 v[0][2] = v[3][2] = v[4][2] = v[7][2] = -size / 2; 154 v[1][2] = v[2][2] = v[5][2] = v[6][2] = size / 2; 155 156 for (i = 5; i >= 0; i--) { 157 glBegin(type); 158 glNormal3fv(&n[i][0]); 159 glVertex3fv(&v[faces[i][0]][0]); 160 glVertex3fv(&v[faces[i][1]][0]); 161 glVertex3fv(&v[faces[i][2]][0]); 162 glVertex3fv(&v[faces[i][3]][0]); 163 glEnd(); 164 } 165 } 166 167 /* CENTRY */ 168 void APIENTRY 169 glutWireCube(GLdouble size) 170 { 171 drawBox(size, GL_LINE_LOOP); 172 } 173 174 void APIENTRY 175 glutSolidCube(GLdouble size) 176 { 177 drawBox(size, GL_QUADS); 178 } 179 180 /* ENDCENTRY */ 181 182 static void 183 doughnut(GLfloat r, GLfloat R, GLint nsides, GLint rings) 184 { 185 int i, j; 186 GLfloat theta, phi, theta1; 187 GLfloat cosTheta, sinTheta; 188 GLfloat cosTheta1, sinTheta1; 189 GLfloat ringDelta, sideDelta; 190 191 ringDelta = 2.0 * M_PI / rings; 192 sideDelta = 2.0 * M_PI / nsides; 193 194 theta = 0.0; 195 cosTheta = 1.0; 196 sinTheta = 0.0; 197 for (i = rings - 1; i >= 0; i--) { 198 theta1 = theta + ringDelta; 199 cosTheta1 = cos(theta1); 200 sinTheta1 = sin(theta1); 201 glBegin(GL_QUAD_STRIP); 202 phi = 0.0; 203 for (j = nsides; j >= 0; j--) { 204 GLfloat cosPhi, sinPhi, dist; 205 206 phi += sideDelta; 207 cosPhi = cos(phi); 208 sinPhi = sin(phi); 209 dist = R + r * cosPhi; 210 211 glNormal3f(cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi); 212 glVertex3f(cosTheta1 * dist, -sinTheta1 * dist, r * sinPhi); 213 glNormal3f(cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi); 214 glVertex3f(cosTheta * dist, -sinTheta * dist, r * sinPhi); 215 } 216 glEnd(); 217 theta = theta1; 218 cosTheta = cosTheta1; 219 sinTheta = sinTheta1; 220 } 221 } 222 223 /* CENTRY */ 224 void APIENTRY 225 glutWireTorus(GLdouble innerRadius, GLdouble outerRadius, 226 GLint nsides, GLint rings) 227 { 228 glPushAttrib(GL_POLYGON_BIT); 229 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 230 doughnut(innerRadius, outerRadius, nsides, rings); 231 glPopAttrib(); 232 } 233 234 void APIENTRY 235 glutSolidTorus(GLdouble innerRadius, GLdouble outerRadius, 236 GLint nsides, GLint rings) 237 { 238 doughnut(innerRadius, outerRadius, nsides, rings); 239 } 240 241 /* ENDCENTRY */ 242 243 static GLfloat dodec[20][3]; 244 245 static void 246 initDodecahedron(void) 247 { 248 GLfloat alpha, beta; 249 250 alpha = sqrt(2.0 / (3.0 + sqrt(5.0))); 251 beta = 1.0 + sqrt(6.0 / (3.0 + sqrt(5.0)) - 252 2.0 + 2.0 * sqrt(2.0 / (3.0 + sqrt(5.0)))); 253 /* *INDENT-OFF* */ 254 dodec[0][0] = -alpha; dodec[0][1] = 0; dodec[0][2] = beta; 255 dodec[1][0] = alpha; dodec[1][1] = 0; dodec[1][2] = beta; 256 dodec[2][0] = -1; dodec[2][1] = -1; dodec[2][2] = -1; 257 dodec[3][0] = -1; dodec[3][1] = -1; dodec[3][2] = 1; 258 dodec[4][0] = -1; dodec[4][1] = 1; dodec[4][2] = -1; 259 dodec[5][0] = -1; dodec[5][1] = 1; dodec[5][2] = 1; 260 dodec[6][0] = 1; dodec[6][1] = -1; dodec[6][2] = -1; 261 dodec[7][0] = 1; dodec[7][1] = -1; dodec[7][2] = 1; 262 dodec[8][0] = 1; dodec[8][1] = 1; dodec[8][2] = -1; 263 dodec[9][0] = 1; dodec[9][1] = 1; dodec[9][2] = 1; 264 dodec[10][0] = beta; dodec[10][1] = alpha; dodec[10][2] = 0; 265 dodec[11][0] = beta; dodec[11][1] = -alpha; dodec[11][2] = 0; 266 dodec[12][0] = -beta; dodec[12][1] = alpha; dodec[12][2] = 0; 267 dodec[13][0] = -beta; dodec[13][1] = -alpha; dodec[13][2] = 0; 268 dodec[14][0] = -alpha; dodec[14][1] = 0; dodec[14][2] = -beta; 269 dodec[15][0] = alpha; dodec[15][1] = 0; dodec[15][2] = -beta; 270 dodec[16][0] = 0; dodec[16][1] = beta; dodec[16][2] = alpha; 271 dodec[17][0] = 0; dodec[17][1] = beta; dodec[17][2] = -alpha; 272 dodec[18][0] = 0; dodec[18][1] = -beta; dodec[18][2] = alpha; 273 dodec[19][0] = 0; dodec[19][1] = -beta; dodec[19][2] = -alpha; 274 /* *INDENT-ON* */ 275 276 } 277 278 #define DIFF3(_a,_b,_c) { \ 279 (_c)[0] = (_a)[0] - (_b)[0]; \ 280 (_c)[1] = (_a)[1] - (_b)[1]; \ 281 (_c)[2] = (_a)[2] - (_b)[2]; \ 282 } 283 284 static void 285 crossprod(GLfloat v1[3], GLfloat v2[3], GLfloat prod[3]) 286 { 287 GLfloat p[3]; /* in case prod == v1 or v2 */ 288 289 p[0] = v1[1] * v2[2] - v2[1] * v1[2]; 290 p[1] = v1[2] * v2[0] - v2[2] * v1[0]; 291 p[2] = v1[0] * v2[1] - v2[0] * v1[1]; 292 prod[0] = p[0]; 293 prod[1] = p[1]; 294 prod[2] = p[2]; 295 } 296 297 static void 298 normalize(GLfloat v[3]) 299 { 300 GLfloat d; 301 302 d = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); 303 if (d == 0.0) { 304 __glutWarning("normalize: zero length vector"); 305 v[0] = d = 1.0; 306 } 307 d = 1 / d; 308 v[0] *= d; 309 v[1] *= d; 310 v[2] *= d; 311 } 312 313 static void 314 pentagon(int a, int b, int c, int d, int e, GLenum shadeType) 315 { 316 GLfloat n0[3], d1[3], d2[3]; 317 318 DIFF3(dodec[a], dodec[b], d1); 319 DIFF3(dodec[b], dodec[c], d2); 320 crossprod(d1, d2, n0); 321 normalize(n0); 322 323 glBegin(shadeType); 324 glNormal3fv(n0); 325 glVertex3fv(&dodec[a][0]); 326 glVertex3fv(&dodec[b][0]); 327 glVertex3fv(&dodec[c][0]); 328 glVertex3fv(&dodec[d][0]); 329 glVertex3fv(&dodec[e][0]); 330 glEnd(); 331 } 332 333 static void 334 dodecahedron(GLenum type) 335 { 336 static int inited = 0; 337 338 if (inited == 0) { 339 inited = 1; 340 initDodecahedron(); 341 } 342 pentagon(0, 1, 9, 16, 5, type); 343 pentagon(1, 0, 3, 18, 7, type); 344 pentagon(1, 7, 11, 10, 9, type); 345 pentagon(11, 7, 18, 19, 6, type); 346 pentagon(8, 17, 16, 9, 10, type); 347 pentagon(2, 14, 15, 6, 19, type); 348 pentagon(2, 13, 12, 4, 14, type); 349 pentagon(2, 19, 18, 3, 13, type); 350 pentagon(3, 0, 5, 12, 13, type); 351 pentagon(6, 15, 8, 10, 11, type); 352 pentagon(4, 17, 8, 15, 14, type); 353 pentagon(4, 12, 5, 16, 17, type); 354 } 355 356 /* CENTRY */ 357 void APIENTRY 358 glutWireDodecahedron(void) 359 { 360 dodecahedron(GL_LINE_LOOP); 361 } 362 363 void APIENTRY 364 glutSolidDodecahedron(void) 365 { 366 dodecahedron(GL_TRIANGLE_FAN); 367 } 368 369 /* ENDCENTRY */ 370 371 static void 372 recorditem(GLfloat * n1, GLfloat * n2, GLfloat * n3, 373 GLenum shadeType) 374 { 375 GLfloat q0[3], q1[3]; 376 377 DIFF3(n1, n2, q0); 378 DIFF3(n2, n3, q1); 379 crossprod(q0, q1, q1); 380 normalize(q1); 381 382 glBegin(shadeType); 383 glNormal3fv(q1); 384 glVertex3fv(n1); 385 glVertex3fv(n2); 386 glVertex3fv(n3); 387 glEnd(); 388 } 389 390 static void 391 subdivide(GLfloat * v0, GLfloat * v1, GLfloat * v2, 392 GLenum shadeType) 393 { 394 int depth; 395 GLfloat w0[3], w1[3], w2[3]; 396 GLfloat l; 397 int i, j, k, n; 398 399 depth = 1; 400 for (i = 0; i < depth; i++) { 401 for (j = 0; i + j < depth; j++) { 402 k = depth - i - j; 403 for (n = 0; n < 3; n++) { 404 w0[n] = (i * v0[n] + j * v1[n] + k * v2[n]) / depth; 405 w1[n] = ((i + 1) * v0[n] + j * v1[n] + (k - 1) * v2[n]) 406 / depth; 407 w2[n] = (i * v0[n] + (j + 1) * v1[n] + (k - 1) * v2[n]) 408 / depth; 409 } 410 l = sqrt(w0[0] * w0[0] + w0[1] * w0[1] + w0[2] * w0[2]); 411 w0[0] /= l; 412 w0[1] /= l; 413 w0[2] /= l; 414 l = sqrt(w1[0] * w1[0] + w1[1] * w1[1] + w1[2] * w1[2]); 415 w1[0] /= l; 416 w1[1] /= l; 417 w1[2] /= l; 418 l = sqrt(w2[0] * w2[0] + w2[1] * w2[1] + w2[2] * w2[2]); 419 w2[0] /= l; 420 w2[1] /= l; 421 w2[2] /= l; 422 recorditem(w1, w0, w2, shadeType); 423 } 424 } 425 } 426 427 static void 428 drawtriangle(int i, GLfloat data[][3], int ndx[][3], 429 GLenum shadeType) 430 { 431 GLfloat *x0, *x1, *x2; 432 433 x0 = data[ndx[i][0]]; 434 x1 = data[ndx[i][1]]; 435 x2 = data[ndx[i][2]]; 436 subdivide(x0, x1, x2, shadeType); 437 } 438 439 /* octahedron data: The octahedron produced is centered at the 440 origin and has radius 1.0 */ 441 static GLfloat odata[6][3] = 442 { 443 {1.0, 0.0, 0.0}, 444 {-1.0, 0.0, 0.0}, 445 {0.0, 1.0, 0.0}, 446 {0.0, -1.0, 0.0}, 447 {0.0, 0.0, 1.0}, 448 {0.0, 0.0, -1.0} 449 }; 450 451 static int ondex[8][3] = 452 { 453 {0, 4, 2}, 454 {1, 2, 4}, 455 {0, 3, 4}, 456 {1, 4, 3}, 457 {0, 2, 5}, 458 {1, 5, 2}, 459 {0, 5, 3}, 460 {1, 3, 5} 461 }; 462 463 static void 464 octahedron(GLenum shadeType) 465 { 466 int i; 467 468 for (i = 7; i >= 0; i--) { 469 drawtriangle(i, odata, ondex, shadeType); 470 } 471 } 472 473 /* CENTRY */ 474 void APIENTRY 475 glutWireOctahedron(void) 476 { 477 octahedron(GL_LINE_LOOP); 478 } 479 480 void APIENTRY 481 glutSolidOctahedron(void) 482 { 483 octahedron(GL_TRIANGLES); 484 } 485 486 /* ENDCENTRY */ 487 488 /* icosahedron data: These numbers are rigged to make an 489 icosahedron of radius 1.0 */ 490 491 #define X .525731112119133606 492 #define Z .850650808352039932 493 494 static GLfloat idata[12][3] = 495 { 496 {-X, 0, Z}, 497 {X, 0, Z}, 498 {-X, 0, -Z}, 499 {X, 0, -Z}, 500 {0, Z, X}, 501 {0, Z, -X}, 502 {0, -Z, X}, 503 {0, -Z, -X}, 504 {Z, X, 0}, 505 {-Z, X, 0}, 506 {Z, -X, 0}, 507 {-Z, -X, 0} 508 }; 509 510 static int iIndex[20][3] = 511 { 512 {0, 4, 1}, 513 {0, 9, 4}, 514 {9, 5, 4}, 515 {4, 5, 8}, 516 {4, 8, 1}, 517 {8, 10, 1}, 518 {8, 3, 10}, 519 {5, 3, 8}, 520 {5, 2, 3}, 521 {2, 7, 3}, 522 {7, 10, 3}, 523 {7, 6, 10}, 524 {7, 11, 6}, 525 {11, 0, 6}, 526 {0, 1, 6}, 527 {6, 1, 10}, 528 {9, 0, 11}, 529 {9, 11, 2}, 530 {9, 2, 5}, 531 {7, 2, 11}, 532 }; 533 534 static void 535 icosahedron(GLenum shadeType) 536 { 537 int i; 538 539 for (i = 19; i >= 0; i--) { 540 drawtriangle(i, idata, iIndex, shadeType); 541 } 542 } 543 544 /* CENTRY */ 545 void APIENTRY 546 glutWireIcosahedron(void) 547 { 548 icosahedron(GL_LINE_LOOP); 549 } 550 551 void APIENTRY 552 glutSolidIcosahedron(void) 553 { 554 icosahedron(GL_TRIANGLES); 555 } 556 557 /* ENDCENTRY */ 558 559 /* tetrahedron data: */ 560 561 #define T 1.73205080756887729 562 563 static GLfloat tdata[4][3] = 564 { 565 {T, T, T}, 566 {T, -T, -T}, 567 {-T, T, -T}, 568 {-T, -T, T} 569 }; 570 571 static int tndex[4][3] = 572 { 573 {0, 1, 3}, 574 {2, 1, 0}, 575 {3, 2, 0}, 576 {1, 2, 3} 577 }; 578 579 static void 580 tetrahedron(GLenum shadeType) 581 { 582 int i; 583 584 for (i = 3; i >= 0; i--) 585 drawtriangle(i, tdata, tndex, shadeType); 586 } 587 588 /* CENTRY */ 589 void APIENTRY 590 glutWireTetrahedron(void) 591 { 592 tetrahedron(GL_LINE_LOOP); 593 } 594 595 void APIENTRY 596 glutSolidTetrahedron(void) 597 { 598 tetrahedron(GL_TRIANGLES); 599 } 600 601 /* ENDCENTRY */ 602