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 12ALL RIGHTS RESERVED 13 14Permission to use, copy, modify, and distribute this software 15for any purpose and without fee is hereby granted, provided 16that the above copyright notice appear in all copies and that 17both the copyright notice and this permission notice appear in 18supporting documentation, and that the name of Silicon 19Graphics, Inc. not be used in advertising or publicity 20pertaining to distribution of the software without specific, 21written prior permission. 22 23THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU 24"AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR 25OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF 26MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO 27EVENT SHALL SILICON GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE 28ELSE FOR ANY DIRECT, SPECIAL, INCIDENTAL, INDIRECT OR 29CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER, 30INCLUDING WITHOUT LIMITATION, LOSS OF PROFIT, LOSS OF USE, 31SAVINGS OR REVENUE, OR THE CLAIMS OF THIRD PARTIES, WHETHER OR 32NOT SILICON GRAPHICS, INC. HAS BEEN ADVISED OF THE POSSIBILITY 33OF SUCH LOSS, HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 34ARISING OUT OF OR IN CONNECTION WITH THE POSSESSION, USE OR 35PERFORMANCE OF THIS SOFTWARE. 36 37US Government Users Restricted Rights 38 39Use, duplication, or disclosure by the Government is subject to 40restrictions set forth in FAR 52.227.19(c)(2) or subparagraph 41(c)(1)(ii) of the Rights in Technical Data and Computer 42Software clause at DFARS 252.227-7013 and/or in similar or 43successor clauses in the FAR or the DOD or NASA FAR 44Supplement. Unpublished-- rights reserved under the copyright 45laws of the United States. Contractor/manufacturer is Silicon 46Graphics, Inc., 2011 N. Shoreline Blvd., Mountain View, CA 4794039-7311. 48 49OpenGL(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 60static GLUquadricObj *quadObj; 61 62#define QUAD_OBJ_INIT() { if(!quadObj) initQuadObj(); } 63 64static void 65initQuadObj(void) 66{ 67 quadObj = gluNewQuadric(); 68 if (!quadObj) 69 __glutFatalError("out of memory."); 70} 71 72/* CENTRY */ 73void APIENTRY 74glutWireSphere(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 85void APIENTRY 86glutSolidSphere(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 97void APIENTRY 98glutWireCone(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 110void APIENTRY 111glutSolidCone(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 125static void 126drawBox(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 */ 168void APIENTRY 169glutWireCube(GLdouble size) 170{ 171 drawBox(size, GL_LINE_LOOP); 172} 173 174void APIENTRY 175glutSolidCube(GLdouble size) 176{ 177 drawBox(size, GL_QUADS); 178} 179 180/* ENDCENTRY */ 181 182static void 183doughnut(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 */ 224void APIENTRY 225glutWireTorus(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 234void APIENTRY 235glutSolidTorus(GLdouble innerRadius, GLdouble outerRadius, 236 GLint nsides, GLint rings) 237{ 238 doughnut(innerRadius, outerRadius, nsides, rings); 239} 240 241/* ENDCENTRY */ 242 243static GLfloat dodec[20][3]; 244 245static void 246initDodecahedron(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 284static void 285crossprod(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 297static void 298normalize(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 313static void 314pentagon(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 333static void 334dodecahedron(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 */ 357void APIENTRY 358glutWireDodecahedron(void) 359{ 360 dodecahedron(GL_LINE_LOOP); 361} 362 363void APIENTRY 364glutSolidDodecahedron(void) 365{ 366 dodecahedron(GL_TRIANGLE_FAN); 367} 368 369/* ENDCENTRY */ 370 371static void 372recorditem(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 390static void 391subdivide(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 427static void 428drawtriangle(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 */ 441static 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 451static 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 463static void 464octahedron(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 */ 474void APIENTRY 475glutWireOctahedron(void) 476{ 477 octahedron(GL_LINE_LOOP); 478} 479 480void APIENTRY 481glutSolidOctahedron(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 494static 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 510static 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 534static void 535icosahedron(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 */ 545void APIENTRY 546glutWireIcosahedron(void) 547{ 548 icosahedron(GL_LINE_LOOP); 549} 550 551void APIENTRY 552glutSolidIcosahedron(void) 553{ 554 icosahedron(GL_TRIANGLES); 555} 556 557/* ENDCENTRY */ 558 559/* tetrahedron data: */ 560 561#define T 1.73205080756887729 562 563static GLfloat tdata[4][3] = 564{ 565 {T, T, T}, 566 {T, -T, -T}, 567 {-T, T, -T}, 568 {-T, -T, T} 569}; 570 571static int tndex[4][3] = 572{ 573 {0, 1, 3}, 574 {2, 1, 0}, 575 {3, 2, 0}, 576 {1, 2, 3} 577}; 578 579static void 580tetrahedron(GLenum shadeType) 581{ 582 int i; 583 584 for (i = 3; i >= 0; i--) 585 drawtriangle(i, tdata, tndex, shadeType); 586} 587 588/* CENTRY */ 589void APIENTRY 590glutWireTetrahedron(void) 591{ 592 tetrahedron(GL_LINE_LOOP); 593} 594 595void APIENTRY 596glutSolidTetrahedron(void) 597{ 598 tetrahedron(GL_TRIANGLES); 599} 600 601/* ENDCENTRY */ 602