1 /* 2 * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * - Redistribution of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 11 * - Redistribution in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * Neither the name of Sun Microsystems, Inc. or the names of 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * This software is provided "AS IS," without a warranty of any kind. ALL 20 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, 21 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A 22 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN 23 * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR 24 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR 25 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR 26 * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR 27 * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE 28 * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, 29 * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF 30 * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 31 * 32 * You acknowledge that this software is not designed or intended for use 33 * in the design, construction, operation or maintenance of any nuclear 34 * facility. 35 * 36 * Sun gratefully acknowledges that this software was originally authored 37 * and developed by Kenneth Bradley Russell and Christopher John Kline. 38 */ 39 40 package com.sun.opengl.util; 41 42 import javax.media.opengl.*; 43 import javax.media.opengl.glu.*; 44 45 /** Subset of the routines provided by the GLUT interface. Note the 46 signatures of many of the methods are necessarily different than 47 the corresponding C version. A GLUT object must only be used from 48 one particular thread at a time. <P> 49 50 Copyright (c) Mark J. Kilgard, 1994, 1997. <P> 51 52 (c) Copyright 1993, Silicon Graphics, Inc. <P> 53 54 ALL RIGHTS RESERVED <P> 55 56 Permission to use, copy, modify, and distribute this software 57 for any purpose and without fee is hereby granted, provided 58 that the above copyright notice appear in all copies and that 59 both the copyright notice and this permission notice appear in 60 supporting documentation, and that the name of Silicon 61 Graphics, Inc. not be used in advertising or publicity 62 pertaining to distribution of the software without specific, 63 written prior permission. <P> 64 65 THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU 66 "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR 67 OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF 68 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO 69 EVENT SHALL SILICON GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE 70 ELSE FOR ANY DIRECT, SPECIAL, INCIDENTAL, INDIRECT OR 71 CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER, 72 INCLUDING WITHOUT LIMITATION, LOSS OF PROFIT, LOSS OF USE, 73 SAVINGS OR REVENUE, OR THE CLAIMS OF THIRD PARTIES, WHETHER OR 74 NOT SILICON GRAPHICS, INC. HAS BEEN ADVISED OF THE POSSIBILITY 75 OF SUCH LOSS, HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 76 ARISING OUT OF OR IN CONNECTION WITH THE POSSESSION, USE OR 77 PERFORMANCE OF THIS SOFTWARE. <P> 78 79 US Government Users Restricted Rights <P> 80 81 Use, duplication, or disclosure by the Government is subject to 82 restrictions set forth in FAR 52.227.19(c)(2) or subparagraph 83 (c)(1)(ii) of the Rights in Technical Data and Computer 84 Software clause at DFARS 252.227-7013 and/or in similar or 85 successor clauses in the FAR or the DOD or NASA FAR 86 Supplement. Unpublished-- rights reserved under the copyright 87 laws of the United States. Contractor/manufacturer is Silicon 88 Graphics, Inc., 2011 N. Shoreline Blvd., Mountain View, CA 89 94039-7311. <P> 90 91 OpenGL(TM) is a trademark of Silicon Graphics, Inc. <P> 92 */ 93 94 public class GLUT { 95 public static final int STROKE_ROMAN = 0; 96 public static final int STROKE_MONO_ROMAN = 1; 97 public static final int BITMAP_9_BY_15 = 2; 98 public static final int BITMAP_8_BY_13 = 3; 99 public static final int BITMAP_TIMES_ROMAN_10 = 4; 100 public static final int BITMAP_TIMES_ROMAN_24 = 5; 101 public static final int BITMAP_HELVETICA_10 = 6; 102 public static final int BITMAP_HELVETICA_12 = 7; 103 public static final int BITMAP_HELVETICA_18 = 8; 104 105 private GLU glu = new GLU(); 106 107 //---------------------------------------------------------------------- 108 // Shapes 109 // 110 glutWireSphere(double radius, int slices, int stacks)111 public void glutWireSphere(double radius, int slices, int stacks) { 112 quadObjInit(glu); 113 glu.gluQuadricDrawStyle(quadObj, GLU.GLU_LINE); 114 glu.gluQuadricNormals(quadObj, GLU.GLU_SMOOTH); 115 /* If we ever changed/used the texture or orientation state 116 of quadObj, we'd need to change it to the defaults here 117 with gluQuadricTexture and/or gluQuadricOrientation. */ 118 glu.gluSphere(quadObj, radius, slices, stacks); 119 } 120 glutSolidSphere(double radius, int slices, int stacks)121 public void glutSolidSphere(double radius, int slices, int stacks) { 122 quadObjInit(glu); 123 glu.gluQuadricDrawStyle(quadObj, GLU.GLU_FILL); 124 glu.gluQuadricNormals(quadObj, GLU.GLU_SMOOTH); 125 /* If we ever changed/used the texture or orientation state 126 of quadObj, we'd need to change it to the defaults here 127 with gluQuadricTexture and/or gluQuadricOrientation. */ 128 glu.gluSphere(quadObj, radius, slices, stacks); 129 } 130 glutWireCone(double base, double height, int slices, int stacks)131 public void glutWireCone(double base, double height, 132 int slices, int stacks) { 133 quadObjInit(glu); 134 glu.gluQuadricDrawStyle(quadObj, GLU.GLU_LINE); 135 glu.gluQuadricNormals(quadObj, GLU.GLU_SMOOTH); 136 /* If we ever changed/used the texture or orientation state 137 of quadObj, we'd need to change it to the defaults here 138 with gluQuadricTexture and/or gluQuadricOrientation. */ 139 glu.gluCylinder(quadObj, base, 0.0, height, slices, stacks); 140 } 141 glutSolidCone(double base, double height, int slices, int stacks)142 public void glutSolidCone(double base, double height, 143 int slices, int stacks) { 144 quadObjInit(glu); 145 glu.gluQuadricDrawStyle(quadObj, GLU.GLU_FILL); 146 glu.gluQuadricNormals(quadObj, GLU.GLU_SMOOTH); 147 /* If we ever changed/used the texture or orientation state 148 of quadObj, we'd need to change it to the defaults here 149 with gluQuadricTexture and/or gluQuadricOrientation. */ 150 glu.gluCylinder(quadObj, base, 0.0, height, slices, stacks); 151 } 152 glutWireCylinder(double radius, double height, int slices, int stacks)153 public void glutWireCylinder(double radius, double height, int slices, int stacks) { 154 quadObjInit(glu); 155 glu.gluQuadricDrawStyle(quadObj, GLU.GLU_LINE); 156 glu.gluQuadricNormals(quadObj, GLU.GLU_SMOOTH); 157 /* If we ever changed/used the texture or orientation state 158 of quadObj, we'd need to change it to the defaults here 159 with gluQuadricTexture and/or gluQuadricOrientation. */ 160 glu.gluCylinder(quadObj, radius, radius, height, slices, stacks); 161 } 162 glutSolidCylinder(double radius, double height, int slices, int stacks)163 public void glutSolidCylinder(double radius, double height, int slices, int stacks) { 164 GL gl = glu.getCurrentGL(); 165 166 // Prepare table of points for drawing end caps 167 double [] x = new double[slices]; 168 double [] y = new double[slices]; 169 double angleDelta = Math.PI * 2 / slices; 170 double angle = 0; 171 for (int i = 0 ; i < slices ; i ++) { 172 angle = i * angleDelta; 173 x[i] = Math.cos(angle) * radius; 174 y[i] = Math.sin(angle) * radius; 175 } 176 177 // Draw bottom cap 178 gl.glBegin(GL.GL_TRIANGLE_FAN); 179 gl.glNormal3d(0,0,-1); 180 gl.glVertex3d(0,0,0); 181 for (int i = 0 ; i < slices ; i ++) { 182 gl.glVertex3d(x[i], y[i], 0); 183 } 184 gl.glVertex3d(x[0], y[0], 0); 185 gl.glEnd(); 186 187 // Draw top cap 188 gl.glBegin(GL.GL_TRIANGLE_FAN); 189 gl.glNormal3d(0,0,1); 190 gl.glVertex3d(0,0,height); 191 for (int i = 0 ; i < slices ; i ++) { 192 gl.glVertex3d(x[i], y[i], height); 193 } 194 gl.glVertex3d(x[0], y[0], height); 195 gl.glEnd(); 196 197 // Draw walls 198 quadObjInit(glu); 199 glu.gluQuadricDrawStyle(quadObj, GLU.GLU_FILL); 200 glu.gluQuadricNormals(quadObj, GLU.GLU_SMOOTH); 201 /* If we ever changed/used the texture or orientation state 202 of quadObj, we'd need to change it to the defaults here 203 with gluQuadricTexture and/or gluQuadricOrientation. */ 204 glu.gluCylinder(quadObj, radius, radius, height, slices, stacks); 205 } 206 glutWireCube(float size)207 public void glutWireCube(float size) { 208 drawBox(GLU.getCurrentGL(), size, GL.GL_LINE_LOOP); 209 } 210 glutSolidCube(float size)211 public void glutSolidCube(float size) { 212 drawBox(GLU.getCurrentGL(), size, GL.GL_QUADS); 213 } 214 glutWireTorus(double innerRadius, double outerRadius, int nsides, int rings)215 public void glutWireTorus(double innerRadius, double outerRadius, 216 int nsides, int rings) { 217 GL gl = GLU.getCurrentGL(); 218 gl.glPushAttrib(GL.GL_POLYGON_BIT); 219 gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_LINE); 220 doughnut(gl, innerRadius, outerRadius, nsides, rings); 221 gl.glPopAttrib(); 222 } 223 glutSolidTorus(double innerRadius, double outerRadius, int nsides, int rings)224 public void glutSolidTorus(double innerRadius, double outerRadius, 225 int nsides, int rings) { 226 doughnut(GLU.getCurrentGL(), innerRadius, outerRadius, nsides, rings); 227 } 228 glutWireDodecahedron()229 public void glutWireDodecahedron() { 230 dodecahedron(GLU.getCurrentGL(), GL.GL_LINE_LOOP); 231 } 232 glutSolidDodecahedron()233 public void glutSolidDodecahedron() { 234 dodecahedron(GLU.getCurrentGL(), GL.GL_TRIANGLE_FAN); 235 } 236 glutWireOctahedron()237 public void glutWireOctahedron() { 238 octahedron(GLU.getCurrentGL(), GL.GL_LINE_LOOP); 239 } 240 glutSolidOctahedron()241 public void glutSolidOctahedron() { 242 octahedron(GLU.getCurrentGL(), GL.GL_TRIANGLES); 243 } 244 glutWireIcosahedron()245 public void glutWireIcosahedron() { 246 icosahedron(GLU.getCurrentGL(), GL.GL_LINE_LOOP); 247 } 248 glutSolidIcosahedron()249 public void glutSolidIcosahedron() { 250 icosahedron(GLU.getCurrentGL(), GL.GL_TRIANGLES); 251 } 252 glutWireTetrahedron()253 public void glutWireTetrahedron() { 254 tetrahedron(GLU.getCurrentGL(), GL.GL_LINE_LOOP); 255 } 256 glutSolidTetrahedron()257 public void glutSolidTetrahedron() { 258 tetrahedron(GLU.getCurrentGL(), GL.GL_TRIANGLES); 259 } 260 261 /** 262 * Renders the teapot as a solid shape of the specified size. The teapot is 263 * created in a way that replicates the C GLUT implementation. 264 * 265 * @param scale 266 * the factor by which to scale the teapot 267 */ glutSolidTeapot(double scale)268 public void glutSolidTeapot(double scale) { 269 glutSolidTeapot(scale, true); 270 } 271 272 /** 273 * Renders the teapot as a solid shape of the specified size. The teapot can 274 * either be created in a way that is backward-compatible with the standard 275 * C glut library (i.e. broken), or in a more pleasing way (i.e. with 276 * surfaces whose front-faces point outwards and standing on the z=0 plane, 277 * instead of the y=-1 plane). Both surface normals and texture coordinates 278 * for the teapot are generated. The teapot is generated with OpenGL 279 * evaluators. 280 * 281 * @param scale 282 * the factor by which to scale the teapot 283 * @param cStyle 284 * whether to create the teapot in exactly the same way as in the C 285 * implementation of GLUT 286 */ glutSolidTeapot(double scale, boolean cStyle)287 public void glutSolidTeapot(double scale, boolean cStyle) { 288 teapot(GLU.getCurrentGL(), 14, scale, GL.GL_FILL, cStyle); 289 } 290 291 /** 292 * Renders the teapot as a wireframe shape of the specified size. The teapot 293 * is created in a way that replicates the C GLUT implementation. 294 * 295 * @param scale 296 * the factor by which to scale the teapot 297 */ glutWireTeapot(double scale)298 public void glutWireTeapot(double scale) { 299 glutWireTeapot(scale, true); 300 } 301 302 /** 303 * Renders the teapot as a wireframe shape of the specified size. The teapot 304 * can either be created in a way that is backward-compatible with the 305 * standard C glut library (i.e. broken), or in a more pleasing way (i.e. 306 * with surfaces whose front-faces point outwards and standing on the z=0 307 * plane, instead of the y=-1 plane). Both surface normals and texture 308 * coordinates for the teapot are generated. The teapot is generated with 309 * OpenGL evaluators. 310 * 311 * @param scale 312 * the factor by which to scale the teapot 313 * @param cStyle 314 * whether to create the teapot in exactly the same way as in the C 315 * implementation of GLUT 316 */ glutWireTeapot(double scale, boolean cStyle)317 public void glutWireTeapot(double scale, boolean cStyle) { 318 teapot(GLU.getCurrentGL(), 10, scale, GL.GL_LINE, cStyle); 319 } 320 321 //---------------------------------------------------------------------- 322 // Fonts 323 // 324 glutBitmapCharacter(int font, char character)325 public void glutBitmapCharacter(int font, char character) { 326 GL gl = GLU.getCurrentGL(); 327 int[] swapbytes = new int[1]; 328 int[] lsbfirst = new int[1]; 329 int[] rowlength = new int[1]; 330 int[] skiprows = new int[1]; 331 int[] skippixels = new int[1]; 332 int[] alignment = new int[1]; 333 beginBitmap(gl, 334 swapbytes, 335 lsbfirst, 336 rowlength, 337 skiprows, 338 skippixels, 339 alignment); 340 bitmapCharacterImpl(gl, font, character); 341 endBitmap(gl, 342 swapbytes, 343 lsbfirst, 344 rowlength, 345 skiprows, 346 skippixels, 347 alignment); 348 } 349 glutBitmapString(int font, String string)350 public void glutBitmapString (int font, String string) { 351 GL gl = GLU.getCurrentGL(); 352 int[] swapbytes = new int[1]; 353 int[] lsbfirst = new int[1]; 354 int[] rowlength = new int[1]; 355 int[] skiprows = new int[1]; 356 int[] skippixels = new int[1]; 357 int[] alignment = new int[1]; 358 beginBitmap(gl, 359 swapbytes, 360 lsbfirst, 361 rowlength, 362 skiprows, 363 skippixels, 364 alignment); 365 int len = string.length(); 366 for (int i = 0; i < len; i++) { 367 bitmapCharacterImpl(gl, font, string.charAt(i)); 368 } 369 endBitmap(gl, 370 swapbytes, 371 lsbfirst, 372 rowlength, 373 skiprows, 374 skippixels, 375 alignment); 376 } 377 glutBitmapWidth(int font, char character)378 public int glutBitmapWidth (int font, char character) { 379 BitmapFontRec fontinfo = getBitmapFont(font); 380 int c = character & 0xFFFF; 381 if (c < fontinfo.first || c >= fontinfo.first + fontinfo.num_chars) 382 return 0; 383 BitmapCharRec ch = fontinfo.ch[c - fontinfo.first]; 384 if (ch != null) 385 return (int) ch.advance; 386 else 387 return 0; 388 } 389 glutStrokeCharacter(int font, char character)390 public void glutStrokeCharacter(int font, char character) { 391 GL gl = GLU.getCurrentGL(); 392 StrokeFontRec fontinfo = getStrokeFont(font); 393 int c = character & 0xFFFF; 394 if (c < 0 || c >= fontinfo.num_chars) 395 return; 396 StrokeCharRec ch = fontinfo.ch[c]; 397 if (ch != null) { 398 for (int i = 0; i < ch.num_strokes; i++) { 399 StrokeRec stroke = ch.stroke[i]; 400 gl.glBegin(GL.GL_LINE_STRIP); 401 for (int j = 0; j < stroke.num_coords; j++) { 402 CoordRec coord = stroke.coord[j]; 403 gl.glVertex2f(coord.x, coord.y); 404 } 405 gl.glEnd(); 406 } 407 gl.glTranslatef(ch.right, 0.0f, 0.0f); 408 } 409 } 410 glutStrokeString(int font, String string)411 public void glutStrokeString(int font, String string) { 412 GL gl = GLU.getCurrentGL(); 413 StrokeFontRec fontinfo = getStrokeFont(font); 414 int len = string.length(); 415 for (int pos = 0; pos < len; pos++) { 416 int c = string.charAt(pos) & 0xFFFF; 417 if (c < 0 || c >= fontinfo.num_chars) 418 continue; 419 StrokeCharRec ch = fontinfo.ch[c]; 420 if (ch != null) { 421 for (int i = 0; i < ch.num_strokes; i++) { 422 StrokeRec stroke = ch.stroke[i]; 423 gl.glBegin(GL.GL_LINE_STRIP); 424 for (int j = 0; j < stroke.num_coords; j++) { 425 CoordRec coord = stroke.coord[j]; 426 gl.glVertex2f(coord.x, coord.y); 427 } 428 gl.glEnd(); 429 } 430 gl.glTranslatef(ch.right, 0.0f, 0.0f); 431 } 432 } 433 } 434 glutStrokeWidth(int font, char character)435 public int glutStrokeWidth (int font, char character) { 436 return (int) glutStrokeWidthf(font, character); 437 } 438 glutStrokeWidthf(int font, char character)439 public float glutStrokeWidthf (int font, char character) { 440 StrokeFontRec fontinfo = getStrokeFont(font); 441 int c = character & 0xFFFF; 442 if (c < 0 || c >= fontinfo.num_chars) 443 return 0; 444 StrokeCharRec ch = fontinfo.ch[c]; 445 if (ch != null) 446 return ch.right; 447 else 448 return 0; 449 } 450 glutBitmapLength(int font, String string)451 public int glutBitmapLength (int font, String string) { 452 BitmapFontRec fontinfo = getBitmapFont(font); 453 int length = 0; 454 int len = string.length(); 455 for (int pos = 0; pos < len; pos++) { 456 int c = string.charAt(pos) & 0xFFFF; 457 if (c >= fontinfo.first && c < fontinfo.first + fontinfo.num_chars) { 458 BitmapCharRec ch = fontinfo.ch[c - fontinfo.first]; 459 if (ch != null) 460 length += ch.advance; 461 } 462 } 463 return length; 464 } 465 glutStrokeLength(int font, String string)466 public int glutStrokeLength (int font, String string) { 467 return (int) glutStrokeLengthf(font, string); 468 } 469 glutStrokeLengthf(int font, String string)470 public float glutStrokeLengthf (int font, String string) { 471 StrokeFontRec fontinfo = getStrokeFont(font); 472 float length = 0; 473 int len = string.length(); 474 for (int i = 0; i < len; i++) { 475 char c = string.charAt(i); 476 if (c >= 0 && c < fontinfo.num_chars) { 477 StrokeCharRec ch = fontinfo.ch[c]; 478 if (ch != null) 479 length += ch.right; 480 } 481 } 482 return length; 483 } 484 485 /** 486 This function draws a wireframe dodecahedron whose 487 facets are rhombic and 488 whose vertices are at unit radius. 489 No facet lies normal to any coordinate axes. 490 The polyhedron is centered at the origin. 491 */ glutWireRhombicDodecahedron()492 public void glutWireRhombicDodecahedron() { 493 GL gl = glu.getCurrentGL(); 494 for( int i = 0; i < 12; i++ ) { 495 gl.glBegin( GL.GL_LINE_LOOP ); 496 gl.glNormal3dv( rdod_n[ i ],0 ); 497 gl.glVertex3dv( rdod_r[ rdod_v[ i ][ 0 ] ],0 ); 498 gl.glVertex3dv( rdod_r[ rdod_v[ i ][ 1 ] ],0 ); 499 gl.glVertex3dv( rdod_r[ rdod_v[ i ][ 2 ] ],0 ); 500 gl.glVertex3dv( rdod_r[ rdod_v[ i ][ 3 ] ],0 ); 501 gl.glEnd( ); 502 } 503 } 504 505 /** 506 This function draws a solid-shaded dodecahedron 507 whose facets are rhombic and 508 whose vertices are at unit radius. 509 No facet lies normal to any coordinate axes. 510 The polyhedron is centered at the origin. 511 */ glutSolidRhombicDodecahedron()512 public void glutSolidRhombicDodecahedron() { 513 GL gl = glu.getCurrentGL(); 514 gl.glBegin( GL.GL_QUADS ); 515 for( int i = 0; i < 12; i++ ) { 516 gl.glNormal3dv( rdod_n[ i ],0 ); 517 gl.glVertex3dv( rdod_r[ rdod_v[ i ][ 0 ] ],0 ); 518 gl.glVertex3dv( rdod_r[ rdod_v[ i ][ 1 ] ],0 ); 519 gl.glVertex3dv( rdod_r[ rdod_v[ i ][ 2 ] ],0 ); 520 gl.glVertex3dv( rdod_r[ rdod_v[ i ][ 3 ] ],0 ); 521 } 522 gl.glEnd( ); 523 } 524 525 //---------------------------------------------------------------------- 526 // Internals only below this point 527 // 528 529 //---------------------------------------------------------------------- 530 // Shape implementation 531 // 532 533 private GLUquadric quadObj; quadObjInit(GLU glu)534 private void quadObjInit(GLU glu) { 535 if (quadObj == null) { 536 quadObj = glu.gluNewQuadric(); 537 } 538 if (quadObj == null) { 539 throw new GLException("Out of memory"); 540 } 541 } 542 doughnut(GL gl, double r, double R, int nsides, int rings)543 private static void doughnut(GL gl, double r, double R, int nsides, int rings) { 544 int i, j; 545 float theta, phi, theta1; 546 float cosTheta, sinTheta; 547 float cosTheta1, sinTheta1; 548 float ringDelta, sideDelta; 549 550 ringDelta = (float) (2.0 * Math.PI / rings); 551 sideDelta = (float) (2.0 * Math.PI / nsides); 552 553 theta = 0.0f; 554 cosTheta = 1.0f; 555 sinTheta = 0.0f; 556 for (i = rings - 1; i >= 0; i--) { 557 theta1 = theta + ringDelta; 558 cosTheta1 = (float) Math.cos(theta1); 559 sinTheta1 = (float) Math.sin(theta1); 560 gl.glBegin(GL.GL_QUAD_STRIP); 561 phi = 0.0f; 562 for (j = nsides; j >= 0; j--) { 563 float cosPhi, sinPhi, dist; 564 565 phi += sideDelta; 566 cosPhi = (float) Math.cos(phi); 567 sinPhi = (float) Math.sin(phi); 568 dist = (float) (R + r * cosPhi); 569 570 gl.glNormal3f(cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi); 571 gl.glVertex3f(cosTheta1 * dist, -sinTheta1 * dist, (float) r * sinPhi); 572 gl.glNormal3f(cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi); 573 gl.glVertex3f(cosTheta * dist, -sinTheta * dist, (float) r * sinPhi); 574 } 575 gl.glEnd(); 576 theta = theta1; 577 cosTheta = cosTheta1; 578 sinTheta = sinTheta1; 579 } 580 } 581 582 private static float[][] boxVertices; 583 private static final float[][] boxNormals = { 584 {-1.0f, 0.0f, 0.0f}, 585 {0.0f, 1.0f, 0.0f}, 586 {1.0f, 0.0f, 0.0f}, 587 {0.0f, -1.0f, 0.0f}, 588 {0.0f, 0.0f, 1.0f}, 589 {0.0f, 0.0f, -1.0f} 590 }; 591 private static final int[][] boxFaces = { 592 {0, 1, 2, 3}, 593 {3, 2, 6, 7}, 594 {7, 6, 5, 4}, 595 {4, 5, 1, 0}, 596 {5, 6, 2, 1}, 597 {7, 4, 0, 3} 598 }; drawBox(GL gl, float size, int type)599 private void drawBox(GL gl, float size, int type) { 600 if (boxVertices == null) { 601 float[][] v = new float[8][]; 602 for (int i = 0; i < 8; i++) { 603 v[i] = new float[3]; 604 } 605 v[0][0] = v[1][0] = v[2][0] = v[3][0] = -0.5f; 606 v[4][0] = v[5][0] = v[6][0] = v[7][0] = 0.5f; 607 v[0][1] = v[1][1] = v[4][1] = v[5][1] = -0.5f; 608 v[2][1] = v[3][1] = v[6][1] = v[7][1] = 0.5f; 609 v[0][2] = v[3][2] = v[4][2] = v[7][2] = -0.5f; 610 v[1][2] = v[2][2] = v[5][2] = v[6][2] = 0.5f; 611 boxVertices = v; 612 } 613 float[][] v = boxVertices; 614 float[][] n = boxNormals; 615 int[][] faces = boxFaces; 616 for (int i = 5; i >= 0; i--) { 617 gl.glBegin(type); 618 gl.glNormal3fv(n[i], 0); 619 float[] vt = v[faces[i][0]]; 620 gl.glVertex3f(vt[0] * size, vt[1] * size, vt[2] * size); 621 vt = v[faces[i][1]]; 622 gl.glVertex3f(vt[0] * size, vt[1] * size, vt[2] * size); 623 vt = v[faces[i][2]]; 624 gl.glVertex3f(vt[0] * size, vt[1] * size, vt[2] * size); 625 vt = v[faces[i][3]]; 626 gl.glVertex3f(vt[0] * size, vt[1] * size, vt[2] * size); 627 gl.glEnd(); 628 } 629 } 630 631 private float[][] dodec; 632 initDodecahedron()633 private void initDodecahedron() { 634 dodec = new float[20][]; 635 for (int i = 0; i < dodec.length; i++) { 636 dodec[i] = new float[3]; 637 } 638 639 float alpha, beta; 640 641 alpha = (float) Math.sqrt(2.0f / (3.0f + Math.sqrt(5.0))); 642 beta = 1.0f + (float) Math.sqrt(6.0 / (3.0 + Math.sqrt(5.0)) - 643 2.0 + 2.0 * Math.sqrt(2.0 / (3.0 + Math.sqrt(5.0)))); 644 dodec[0][0] = -alpha; dodec[0][1] = 0; dodec[0][2] = beta; 645 dodec[1][0] = alpha; dodec[1][1] = 0; dodec[1][2] = beta; 646 dodec[2][0] = -1; dodec[2][1] = -1; dodec[2][2] = -1; 647 dodec[3][0] = -1; dodec[3][1] = -1; dodec[3][2] = 1; 648 dodec[4][0] = -1; dodec[4][1] = 1; dodec[4][2] = -1; 649 dodec[5][0] = -1; dodec[5][1] = 1; dodec[5][2] = 1; 650 dodec[6][0] = 1; dodec[6][1] = -1; dodec[6][2] = -1; 651 dodec[7][0] = 1; dodec[7][1] = -1; dodec[7][2] = 1; 652 dodec[8][0] = 1; dodec[8][1] = 1; dodec[8][2] = -1; 653 dodec[9][0] = 1; dodec[9][1] = 1; dodec[9][2] = 1; 654 dodec[10][0] = beta; dodec[10][1] = alpha; dodec[10][2] = 0; 655 dodec[11][0] = beta; dodec[11][1] = -alpha; dodec[11][2] = 0; 656 dodec[12][0] = -beta; dodec[12][1] = alpha; dodec[12][2] = 0; 657 dodec[13][0] = -beta; dodec[13][1] = -alpha; dodec[13][2] = 0; 658 dodec[14][0] = -alpha; dodec[14][1] = 0; dodec[14][2] = -beta; 659 dodec[15][0] = alpha; dodec[15][1] = 0; dodec[15][2] = -beta; 660 dodec[16][0] = 0; dodec[16][1] = beta; dodec[16][2] = alpha; 661 dodec[17][0] = 0; dodec[17][1] = beta; dodec[17][2] = -alpha; 662 dodec[18][0] = 0; dodec[18][1] = -beta; dodec[18][2] = alpha; 663 dodec[19][0] = 0; dodec[19][1] = -beta; dodec[19][2] = -alpha; 664 } 665 diff3(float[] a, float[] b, float[] c)666 private static void diff3(float[] a, float[] b, float[] c) { 667 c[0] = a[0] - b[0]; 668 c[1] = a[1] - b[1]; 669 c[2] = a[2] - b[2]; 670 } 671 crossprod(float[] v1, float[] v2, float[] prod)672 private static void crossprod(float[] v1, float[] v2, float[] prod) { 673 float[] p = new float[3]; /* in case prod == v1 or v2 */ 674 675 p[0] = v1[1] * v2[2] - v2[1] * v1[2]; 676 p[1] = v1[2] * v2[0] - v2[2] * v1[0]; 677 p[2] = v1[0] * v2[1] - v2[0] * v1[1]; 678 prod[0] = p[0]; 679 prod[1] = p[1]; 680 prod[2] = p[2]; 681 } 682 normalize(float[] v)683 private static void normalize(float[] v) { 684 float d; 685 686 d = (float) Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); 687 if (d == 0.0) { 688 v[0] = d = 1.0f; 689 } 690 d = 1 / d; 691 v[0] *= d; 692 v[1] *= d; 693 v[2] *= d; 694 } 695 pentagon(GL gl, int a, int b, int c, int d, int e, int shadeType)696 private void pentagon(GL gl, int a, int b, int c, int d, int e, int shadeType) { 697 float[] n0 = new float[3]; 698 float[] d1 = new float[3]; 699 float[] d2 = new float[3]; 700 701 diff3(dodec[a], dodec[b], d1); 702 diff3(dodec[b], dodec[c], d2); 703 crossprod(d1, d2, n0); 704 normalize(n0); 705 706 gl.glBegin(shadeType); 707 gl.glNormal3fv(n0, 0); 708 gl.glVertex3fv(dodec[a], 0); 709 gl.glVertex3fv(dodec[b], 0); 710 gl.glVertex3fv(dodec[c], 0); 711 gl.glVertex3fv(dodec[d], 0); 712 gl.glVertex3fv(dodec[e], 0); 713 gl.glEnd(); 714 } 715 dodecahedron(GL gl, int type)716 private void dodecahedron(GL gl, int type) { 717 if (dodec == null) { 718 initDodecahedron(); 719 } 720 pentagon(gl, 0, 1, 9, 16, 5, type); 721 pentagon(gl, 1, 0, 3, 18, 7, type); 722 pentagon(gl, 1, 7, 11, 10, 9, type); 723 pentagon(gl, 11, 7, 18, 19, 6, type); 724 pentagon(gl, 8, 17, 16, 9, 10, type); 725 pentagon(gl, 2, 14, 15, 6, 19, type); 726 pentagon(gl, 2, 13, 12, 4, 14, type); 727 pentagon(gl, 2, 19, 18, 3, 13, type); 728 pentagon(gl, 3, 0, 5, 12, 13, type); 729 pentagon(gl, 6, 15, 8, 10, 11, type); 730 pentagon(gl, 4, 17, 8, 15, 14, type); 731 pentagon(gl, 4, 12, 5, 16, 17, type); 732 } 733 recorditem(GL gl, float[] n1, float[] n2, float[] n3, int shadeType)734 private static void recorditem(GL gl, float[] n1, float[] n2, float[] n3, int shadeType) { 735 float[] q0 = new float[3]; 736 float[] q1 = new float[3]; 737 738 diff3(n1, n2, q0); 739 diff3(n2, n3, q1); 740 crossprod(q0, q1, q1); 741 normalize(q1); 742 743 gl.glBegin(shadeType); 744 gl.glNormal3fv(q1, 0); 745 gl.glVertex3fv(n1, 0); 746 gl.glVertex3fv(n2, 0); 747 gl.glVertex3fv(n3, 0); 748 gl.glEnd(); 749 } 750 subdivide(GL gl, float[] v0, float[] v1, float[] v2, int shadeType)751 private static void subdivide(GL gl, float[] v0, float[] v1, float[] v2, int shadeType) { 752 int depth; 753 float[] w0 = new float[3]; 754 float[] w1 = new float[3]; 755 float[] w2 = new float[3]; 756 float l; 757 int i, j, k, n; 758 759 depth = 1; 760 for (i = 0; i < depth; i++) { 761 for (j = 0; i + j < depth; j++) { 762 k = depth - i - j; 763 for (n = 0; n < 3; n++) { 764 w0[n] = (i * v0[n] + j * v1[n] + k * v2[n]) / depth; 765 w1[n] = ((i + 1) * v0[n] + j * v1[n] + (k - 1) * v2[n]) 766 / depth; 767 w2[n] = (i * v0[n] + (j + 1) * v1[n] + (k - 1) * v2[n]) 768 / depth; 769 } 770 l = (float) Math.sqrt(w0[0] * w0[0] + w0[1] * w0[1] + w0[2] * w0[2]); 771 w0[0] /= l; 772 w0[1] /= l; 773 w0[2] /= l; 774 l = (float) Math.sqrt(w1[0] * w1[0] + w1[1] * w1[1] + w1[2] * w1[2]); 775 w1[0] /= l; 776 w1[1] /= l; 777 w1[2] /= l; 778 l = (float) Math.sqrt(w2[0] * w2[0] + w2[1] * w2[1] + w2[2] * w2[2]); 779 w2[0] /= l; 780 w2[1] /= l; 781 w2[2] /= l; 782 recorditem(gl, w1, w0, w2, shadeType); 783 } 784 } 785 } 786 drawtriangle(GL gl, int i, float[][] data, int[][] ndx, int shadeType)787 private static void drawtriangle(GL gl, int i, float[][] data, int[][] ndx, int shadeType) { 788 float[] x0 = data[ndx[i][0]]; 789 float[] x1 = data[ndx[i][1]]; 790 float[] x2 = data[ndx[i][2]]; 791 subdivide(gl, x0, x1, x2, shadeType); 792 } 793 794 /* octahedron data: The octahedron produced is centered at the 795 origin and has radius 1.0 */ 796 private static final float[][] odata = 797 { 798 {1.0f, 0.0f, 0.0f}, 799 {-1.0f, 0.0f, 0.0f}, 800 {0.0f, 1.0f, 0.0f}, 801 {0.0f, -1.0f, 0.0f}, 802 {0.0f, 0.0f, 1.0f}, 803 {0.0f, 0.0f, -1.0f} 804 }; 805 806 private static final int[][] ondex = 807 { 808 {0, 4, 2}, 809 {1, 2, 4}, 810 {0, 3, 4}, 811 {1, 4, 3}, 812 {0, 2, 5}, 813 {1, 5, 2}, 814 {0, 5, 3}, 815 {1, 3, 5} 816 }; 817 octahedron(GL gl, int shadeType)818 private static void octahedron(GL gl, int shadeType) { 819 int i; 820 821 for (i = 7; i >= 0; i--) { 822 drawtriangle(gl, i, odata, ondex, shadeType); 823 } 824 } 825 826 /* icosahedron data: These numbers are rigged to make an 827 icosahedron of radius 1.0 */ 828 829 private static final float X = .525731112119133606f; 830 private static final float Z = .850650808352039932f; 831 832 private static final float[][] idata = 833 { 834 {-X, 0, Z}, 835 {X, 0, Z}, 836 {-X, 0, -Z}, 837 {X, 0, -Z}, 838 {0, Z, X}, 839 {0, Z, -X}, 840 {0, -Z, X}, 841 {0, -Z, -X}, 842 {Z, X, 0}, 843 {-Z, X, 0}, 844 {Z, -X, 0}, 845 {-Z, -X, 0} 846 }; 847 848 private static final int[][] index = 849 { 850 {0, 4, 1}, 851 {0, 9, 4}, 852 {9, 5, 4}, 853 {4, 5, 8}, 854 {4, 8, 1}, 855 {8, 10, 1}, 856 {8, 3, 10}, 857 {5, 3, 8}, 858 {5, 2, 3}, 859 {2, 7, 3}, 860 {7, 10, 3}, 861 {7, 6, 10}, 862 {7, 11, 6}, 863 {11, 0, 6}, 864 {0, 1, 6}, 865 {6, 1, 10}, 866 {9, 0, 11}, 867 {9, 11, 2}, 868 {9, 2, 5}, 869 {7, 2, 11}, 870 }; 871 icosahedron(GL gl, int shadeType)872 private static void icosahedron(GL gl, int shadeType) { 873 int i; 874 875 for (i = 19; i >= 0; i--) { 876 drawtriangle(gl, i, idata, index, shadeType); 877 } 878 } 879 880 /* rhombic dodecahedron data: */ 881 882 private static final double rdod_r[][] = 883 { 884 { 0.0, 0.0, 1.0 }, 885 { 0.707106781187, 0.000000000000, 0.5 }, 886 { 0.000000000000, 0.707106781187, 0.5 }, 887 { -0.707106781187, 0.000000000000, 0.5 }, 888 { 0.000000000000, -0.707106781187, 0.5 }, 889 { 0.707106781187, 0.707106781187, 0.0 }, 890 { -0.707106781187, 0.707106781187, 0.0 }, 891 { -0.707106781187, -0.707106781187, 0.0 }, 892 { 0.707106781187, -0.707106781187, 0.0 }, 893 { 0.707106781187, 0.000000000000, -0.5 }, 894 { 0.000000000000, 0.707106781187, -0.5 }, 895 { -0.707106781187, 0.000000000000, -0.5 }, 896 { 0.000000000000, -0.707106781187, -0.5 }, 897 { 0.0, 0.0, -1.0 } 898 }; 899 900 private static final int rdod_v[][] = 901 { 902 { 0, 1, 5, 2 }, 903 { 0, 2, 6, 3 }, 904 { 0, 3, 7, 4 }, 905 { 0, 4, 8, 1 }, 906 { 5, 10, 6, 2 }, 907 { 6, 11, 7, 3 }, 908 { 7, 12, 8, 4 }, 909 { 8, 9, 5, 1 }, 910 { 5, 9, 13, 10 }, 911 { 6, 10, 13, 11 }, 912 { 7, 11, 13, 12 }, 913 { 8, 12, 13, 9 } 914 }; 915 916 private static final double rdod_n[][] = 917 { 918 { 0.353553390594, 0.353553390594, 0.5 }, 919 { -0.353553390594, 0.353553390594, 0.5 }, 920 { -0.353553390594, -0.353553390594, 0.5 }, 921 { 0.353553390594, -0.353553390594, 0.5 }, 922 { 0.000000000000, 1.000000000000, 0.0 }, 923 { -1.000000000000, 0.000000000000, 0.0 }, 924 { 0.000000000000, -1.000000000000, 0.0 }, 925 { 1.000000000000, 0.000000000000, 0.0 }, 926 { 0.353553390594, 0.353553390594, -0.5 }, 927 { -0.353553390594, 0.353553390594, -0.5 }, 928 { -0.353553390594, -0.353553390594, -0.5 }, 929 { 0.353553390594, -0.353553390594, -0.5 } 930 }; 931 932 /* tetrahedron data: */ 933 934 private static final float T = 1.73205080756887729f; 935 936 private static final float[][] tdata = 937 { 938 {T, T, T}, 939 {T, -T, -T}, 940 {-T, T, -T}, 941 {-T, -T, T} 942 }; 943 944 private static final int[][] tndex = 945 { 946 {0, 1, 3}, 947 {2, 1, 0}, 948 {3, 2, 0}, 949 {1, 2, 3} 950 }; 951 tetrahedron(GL gl, int shadeType)952 private static final void tetrahedron(GL gl, int shadeType) { 953 for (int i = 3; i >= 0; i--) 954 drawtriangle(gl, i, tdata, tndex, shadeType); 955 } 956 957 // Teapot implementation (a modified port of glut_teapot.c) 958 // 959 // Rim, body, lid, and bottom data must be reflected in x and 960 // y; handle and spout data across the y axis only. 961 private static final int[][] teapotPatchData = { 962 /* rim */ 963 {102, 103, 104, 105, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, 964 /* body */ 965 {12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}, 966 {24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40}, 967 /* lid */ 968 {96, 96, 96, 96, 97, 98, 99, 100, 101, 101, 101, 101, 0, 1, 2, 3,}, 969 {0, 1, 2, 3, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117}, 970 /* bottom */ 971 {118, 118, 118, 118, 124, 122, 119, 121, 123, 126, 125, 120, 40, 39, 38, 37}, 972 /* handle */ 973 {41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56}, 974 {53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 28, 65, 66, 67}, 975 /* spout */ 976 {68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83}, 977 {80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95} 978 }; 979 private static final float[][] teapotCPData = { 980 {0.2f, 0f, 2.7f}, 981 {0.2f, -0.112f, 2.7f}, 982 {0.112f, -0.2f, 2.7f}, 983 {0f, -0.2f, 2.7f}, 984 {1.3375f, 0f, 2.53125f}, 985 {1.3375f, -0.749f, 2.53125f}, 986 {0.749f, -1.3375f, 2.53125f}, 987 {0f, -1.3375f, 2.53125f}, 988 {1.4375f, 0f, 2.53125f}, 989 {1.4375f, -0.805f, 2.53125f}, 990 {0.805f, -1.4375f, 2.53125f}, 991 {0f, -1.4375f, 2.53125f}, 992 {1.5f, 0f, 2.4f}, 993 {1.5f, -0.84f, 2.4f}, 994 {0.84f, -1.5f, 2.4f}, 995 {0f, -1.5f, 2.4f}, 996 {1.75f, 0f, 1.875f}, 997 {1.75f, -0.98f, 1.875f}, 998 {0.98f, -1.75f, 1.875f}, 999 {0f, -1.75f, 1.875f}, 1000 {2f, 0f, 1.35f}, 1001 {2f, -1.12f, 1.35f}, 1002 {1.12f, -2f, 1.35f}, 1003 {0f, -2f, 1.35f}, 1004 {2f, 0f, 0.9f}, 1005 {2f, -1.12f, 0.9f}, 1006 {1.12f, -2f, 0.9f}, 1007 {0f, -2f, 0.9f}, 1008 {-2f, 0f, 0.9f}, 1009 {2f, 0f, 0.45f}, 1010 {2f, -1.12f, 0.45f}, 1011 {1.12f, -2f, 0.45f}, 1012 {0f, -2f, 0.45f}, 1013 {1.5f, 0f, 0.225f}, 1014 {1.5f, -0.84f, 0.225f}, 1015 {0.84f, -1.5f, 0.225f}, 1016 {0f, -1.5f, 0.225f}, 1017 {1.5f, 0f, 0.15f}, 1018 {1.5f, -0.84f, 0.15f}, 1019 {0.84f, -1.5f, 0.15f}, 1020 {0f, -1.5f, 0.15f}, 1021 {-1.6f, 0f, 2.025f}, 1022 {-1.6f, -0.3f, 2.025f}, 1023 {-1.5f, -0.3f, 2.25f}, 1024 {-1.5f, 0f, 2.25f}, 1025 {-2.3f, 0f, 2.025f}, 1026 {-2.3f, -0.3f, 2.025f}, 1027 {-2.5f, -0.3f, 2.25f}, 1028 {-2.5f, 0f, 2.25f}, 1029 {-2.7f, 0f, 2.025f}, 1030 {-2.7f, -0.3f, 2.025f}, 1031 {-3f, -0.3f, 2.25f}, 1032 {-3f, 0f, 2.25f}, 1033 {-2.7f, 0f, 1.8f}, 1034 {-2.7f, -0.3f, 1.8f}, 1035 {-3f, -0.3f, 1.8f}, 1036 {-3f, 0f, 1.8f}, 1037 {-2.7f, 0f, 1.575f}, 1038 {-2.7f, -0.3f, 1.575f}, 1039 {-3f, -0.3f, 1.35f}, 1040 {-3f, 0f, 1.35f}, 1041 {-2.5f, 0f, 1.125f}, 1042 {-2.5f, -0.3f, 1.125f}, 1043 {-2.65f, -0.3f, 0.9375f}, 1044 {-2.65f, 0f, 0.9375f}, 1045 {-2f, -0.3f, 0.9f}, 1046 {-1.9f, -0.3f, 0.6f}, 1047 {-1.9f, 0f, 0.6f}, 1048 {1.7f, 0f, 1.425f}, 1049 {1.7f, -0.66f, 1.425f}, 1050 {1.7f, -0.66f, 0.6f}, 1051 {1.7f, 0f, 0.6f}, 1052 {2.6f, 0f, 1.425f}, 1053 {2.6f, -0.66f, 1.425f}, 1054 {3.1f, -0.66f, 0.825f}, 1055 {3.1f, 0f, 0.825f}, 1056 {2.3f, 0f, 2.1f}, 1057 {2.3f, -0.25f, 2.1f}, 1058 {2.4f, -0.25f, 2.025f}, 1059 {2.4f, 0f, 2.025f}, 1060 {2.7f, 0f, 2.4f}, 1061 {2.7f, -0.25f, 2.4f}, 1062 {3.3f, -0.25f, 2.4f}, 1063 {3.3f, 0f, 2.4f}, 1064 {2.8f, 0f, 2.475f}, 1065 {2.8f, -0.25f, 2.475f}, 1066 {3.525f, -0.25f, 2.49375f}, 1067 {3.525f, 0f, 2.49375f}, 1068 {2.9f, 0f, 2.475f}, 1069 {2.9f, -0.15f, 2.475f}, 1070 {3.45f, -0.15f, 2.5125f}, 1071 {3.45f, 0f, 2.5125f}, 1072 {2.8f, 0f, 2.4f}, 1073 {2.8f, -0.15f, 2.4f}, 1074 {3.2f, -0.15f, 2.4f}, 1075 {3.2f, 0f, 2.4f}, 1076 {0f, 0f, 3.15f}, 1077 {0.8f, 0f, 3.15f}, 1078 {0.8f, -0.45f, 3.15f}, 1079 {0.45f, -0.8f, 3.15f}, 1080 {0f, -0.8f, 3.15f}, 1081 {0f, 0f, 2.85f}, 1082 {1.4f, 0f, 2.4f}, 1083 {1.4f, -0.784f, 2.4f}, 1084 {0.784f, -1.4f, 2.4f}, 1085 {0f, -1.4f, 2.4f}, 1086 {0.4f, 0f, 2.55f}, 1087 {0.4f, -0.224f, 2.55f}, 1088 {0.224f, -0.4f, 2.55f}, 1089 {0f, -0.4f, 2.55f}, 1090 {1.3f, 0f, 2.55f}, 1091 {1.3f, -0.728f, 2.55f}, 1092 {0.728f, -1.3f, 2.55f}, 1093 {0f, -1.3f, 2.55f}, 1094 {1.3f, 0f, 2.4f}, 1095 {1.3f, -0.728f, 2.4f}, 1096 {0.728f, -1.3f, 2.4f}, 1097 {0f, -1.3f, 2.4f}, 1098 {0f, 0f, 0f}, 1099 {1.425f, -0.798f, 0f}, 1100 {1.5f, 0f, 0.075f}, 1101 {1.425f, 0f, 0f}, 1102 {0.798f, -1.425f, 0f}, 1103 {0f, -1.5f, 0.075f}, 1104 {0f, -1.425f, 0f}, 1105 {1.5f, -0.84f, 0.075f}, 1106 {0.84f, -1.5f, 0.075f} 1107 }; 1108 // Since GL.glMap2f expects a packed array of floats, we must convert 1109 // from a 3-dimensional array to a 1-dimensional array 1110 private static final float[] teapotTex = { 1111 0, 0, 1, 0, 0, 1, 1, 1 1112 }; 1113 teapot(GL gl, int grid, double scale, int type, boolean backCompatible)1114 private static void teapot(GL gl, 1115 int grid, 1116 double scale, 1117 int type, 1118 boolean backCompatible) 1119 { 1120 // As mentioned above, GL.glMap2f expects a packed array of floats 1121 float[] p = new float[4*4*3]; 1122 float[] q = new float[4*4*3]; 1123 float[] r = new float[4*4*3]; 1124 float[] s = new float[4*4*3]; 1125 int i, j, k, l; 1126 1127 gl.glPushAttrib(GL.GL_ENABLE_BIT | GL.GL_EVAL_BIT | GL.GL_POLYGON_BIT); 1128 gl.glEnable(GL.GL_AUTO_NORMAL); 1129 gl.glEnable(GL.GL_NORMALIZE); 1130 gl.glEnable(GL.GL_MAP2_VERTEX_3); 1131 gl.glEnable(GL.GL_MAP2_TEXTURE_COORD_2); 1132 gl.glPushMatrix(); 1133 if (!backCompatible) { 1134 // The time has come to have the teapot no longer be inside out 1135 gl.glFrontFace(GL.GL_CW); 1136 gl.glScaled(0.5*scale, 0.5*scale, 0.5*scale); 1137 } else { 1138 // We want the teapot in it's backward compatible position and 1139 // orientation 1140 gl.glRotatef(270.0f, 1, 0, 0); 1141 gl.glScalef((float)(0.5 * scale), 1142 (float)(0.5 * scale), 1143 (float)(0.5 * scale)); 1144 gl.glTranslatef(0.0f, 0.0f, -1.5f); 1145 } 1146 for (i = 0; i < 10; i++) { 1147 for (j = 0; j < 4; j++) { 1148 for (k = 0; k < 4; k++) { 1149 for (l = 0; l < 3; l++) { 1150 p[(j*4+k)*3+l] = teapotCPData[teapotPatchData[i][j * 4 + k]][l]; 1151 q[(j*4+k)*3+l] = 1152 teapotCPData[teapotPatchData[i][j * 4 + (3 - k)]][l]; 1153 if (l == 1) 1154 q[(j*4+k)*3+l] *= -1.0; 1155 if (i < 6) { 1156 r[(j*4+k)*3+l] = 1157 teapotCPData[teapotPatchData[i][j * 4 + (3 - k)]][l]; 1158 if (l == 0) 1159 r[(j*4+k)*3+l] *= -1.0; 1160 s[(j*4+k)*3+l] = teapotCPData[teapotPatchData[i][j * 4 + k]][l]; 1161 if (l == 0) 1162 s[(j*4+k)*3+l] *= -1.0; 1163 if (l == 1) 1164 s[(j*4+k)*3+l] *= -1.0; 1165 } 1166 } 1167 } 1168 } 1169 gl.glMap2f(GL.GL_MAP2_TEXTURE_COORD_2, 0, 1, 2, 2, 0, 1, 4, 2, teapotTex, 0); 1170 gl.glMap2f(GL.GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, p, 0); 1171 gl.glMapGrid2f(grid, 0.0f, 1.0f, grid, 0.0f, 1.0f); 1172 evaluateTeapotMesh(gl, grid, type, i, !backCompatible); 1173 gl.glMap2f(GL.GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, q, 0); 1174 evaluateTeapotMesh(gl, grid, type, i, !backCompatible); 1175 if (i < 6) { 1176 gl.glMap2f(GL.GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, r, 0); 1177 evaluateTeapotMesh(gl, grid, type, i, !backCompatible); 1178 gl.glMap2f(GL.GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, s, 0); 1179 evaluateTeapotMesh(gl, grid, type, i, !backCompatible); 1180 } 1181 } 1182 gl.glPopMatrix(); 1183 gl.glPopAttrib(); 1184 } 1185 evaluateTeapotMesh(GL gl, int grid, int type, int partNum, boolean repairSingularities)1186 private static void evaluateTeapotMesh(GL gl, 1187 int grid, 1188 int type, 1189 int partNum, 1190 boolean repairSingularities) 1191 { 1192 if (repairSingularities && (partNum == 5 || partNum == 3)) { 1193 // Instead of using evaluators that give bad results at singularities, 1194 // evaluate by hand 1195 gl.glPolygonMode(GL.GL_FRONT_AND_BACK, type); 1196 for (int nv = 0; nv < grid; nv++) { 1197 if (nv == 0) { 1198 // Draw a small triangle-fan to fill the hole 1199 gl.glDisable(GL.GL_AUTO_NORMAL); 1200 gl.glNormal3f(0, 0, partNum == 3 ? 1 : -1); 1201 gl.glBegin(GL.GL_TRIANGLE_FAN); 1202 { 1203 gl.glEvalCoord2f(0, 0); 1204 // Note that we draw in clock-wise order to match the evaluator 1205 // method 1206 for (int nu = 0; nu <= grid; nu++) 1207 { 1208 gl.glEvalCoord2f(nu / (float)grid, (1f / grid) / (float)grid); 1209 } 1210 } 1211 gl.glEnd(); 1212 gl.glEnable(GL.GL_AUTO_NORMAL); 1213 } 1214 // Draw the rest of the piece as an evaluated quad-strip 1215 gl.glBegin(GL.GL_QUAD_STRIP); 1216 { 1217 // Note that we draw in clock-wise order to match the evaluator method 1218 for (int nu = grid; nu >= 0; nu--) { 1219 gl.glEvalCoord2f(nu / (float)grid, (nv + 1) / (float)grid); 1220 gl.glEvalCoord2f(nu / (float)grid, Math.max(nv, 1f / grid) 1221 / (float)grid); 1222 } 1223 } 1224 gl.glEnd(); 1225 } 1226 } else { 1227 gl.glEvalMesh2(type, 0, grid, 0, grid); 1228 } 1229 } 1230 1231 //---------------------------------------------------------------------- 1232 // Font implementation 1233 // 1234 bitmapCharacterImpl(GL gl, int font, char cin)1235 private static void bitmapCharacterImpl(GL gl, int font, char cin) { 1236 BitmapFontRec fontinfo = getBitmapFont(font); 1237 int c = cin & 0xFFFF; 1238 if (c < fontinfo.first || 1239 c >= fontinfo.first + fontinfo.num_chars) 1240 return; 1241 BitmapCharRec ch = fontinfo.ch[c - fontinfo.first]; 1242 if (ch != null) { 1243 gl.glBitmap(ch.width, ch.height, ch.xorig, ch.yorig, 1244 ch.advance, 0, ch.bitmap, 0); 1245 } 1246 } 1247 1248 private static final BitmapFontRec[] bitmapFonts = new BitmapFontRec[9]; 1249 private static final StrokeFontRec[] strokeFonts = new StrokeFontRec[9]; 1250 getBitmapFont(int font)1251 private static BitmapFontRec getBitmapFont(int font) { 1252 BitmapFontRec rec = bitmapFonts[font]; 1253 if (rec == null) { 1254 switch (font) { 1255 case BITMAP_9_BY_15: 1256 rec = GLUTBitmap9x15.glutBitmap9By15; 1257 break; 1258 case BITMAP_8_BY_13: 1259 rec = GLUTBitmap8x13.glutBitmap8By13; 1260 break; 1261 case BITMAP_TIMES_ROMAN_10: 1262 rec = GLUTBitmapTimesRoman10.glutBitmapTimesRoman10; 1263 break; 1264 case BITMAP_TIMES_ROMAN_24: 1265 rec = GLUTBitmapTimesRoman24.glutBitmapTimesRoman24; 1266 break; 1267 case BITMAP_HELVETICA_10: 1268 rec = GLUTBitmapHelvetica10.glutBitmapHelvetica10; 1269 break; 1270 case BITMAP_HELVETICA_12: 1271 rec = GLUTBitmapHelvetica12.glutBitmapHelvetica12; 1272 break; 1273 case BITMAP_HELVETICA_18: 1274 rec = GLUTBitmapHelvetica18.glutBitmapHelvetica18; 1275 break; 1276 default: 1277 throw new GLException("Unknown bitmap font number " + font); 1278 } 1279 bitmapFonts[font] = rec; 1280 } 1281 return rec; 1282 } 1283 getStrokeFont(int font)1284 private static StrokeFontRec getStrokeFont(int font) { 1285 StrokeFontRec rec = strokeFonts[font]; 1286 if (rec == null) { 1287 switch (font) { 1288 case STROKE_ROMAN: 1289 rec = GLUTStrokeRoman.glutStrokeRoman; 1290 break; 1291 case STROKE_MONO_ROMAN: 1292 rec = GLUTStrokeMonoRoman.glutStrokeMonoRoman; 1293 break; 1294 default: 1295 throw new GLException("Unknown stroke font number " + font); 1296 } 1297 } 1298 return rec; 1299 } 1300 beginBitmap(GL gl, int[] swapbytes, int[] lsbfirst, int[] rowlength, int[] skiprows, int[] skippixels, int[] alignment)1301 private static void beginBitmap(GL gl, 1302 int[] swapbytes, 1303 int[] lsbfirst, 1304 int[] rowlength, 1305 int[] skiprows, 1306 int[] skippixels, 1307 int[] alignment) { 1308 gl.glGetIntegerv(GL.GL_UNPACK_SWAP_BYTES, swapbytes, 0); 1309 gl.glGetIntegerv(GL.GL_UNPACK_LSB_FIRST, lsbfirst, 0); 1310 gl.glGetIntegerv(GL.GL_UNPACK_ROW_LENGTH, rowlength, 0); 1311 gl.glGetIntegerv(GL.GL_UNPACK_SKIP_ROWS, skiprows, 0); 1312 gl.glGetIntegerv(GL.GL_UNPACK_SKIP_PIXELS, skippixels, 0); 1313 gl.glGetIntegerv(GL.GL_UNPACK_ALIGNMENT, alignment, 0); 1314 /* Little endian machines (DEC Alpha for example) could 1315 benefit from setting GL_UNPACK_LSB_FIRST to GL_TRUE 1316 instead of GL_FALSE, but this would require changing the 1317 generated bitmaps too. */ 1318 gl.glPixelStorei(GL.GL_UNPACK_SWAP_BYTES, GL.GL_FALSE); 1319 gl.glPixelStorei(GL.GL_UNPACK_LSB_FIRST, GL.GL_FALSE); 1320 gl.glPixelStorei(GL.GL_UNPACK_ROW_LENGTH, 0); 1321 gl.glPixelStorei(GL.GL_UNPACK_SKIP_ROWS, 0); 1322 gl.glPixelStorei(GL.GL_UNPACK_SKIP_PIXELS, 0); 1323 gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1); 1324 } 1325 endBitmap(GL gl, int[] swapbytes, int[] lsbfirst, int[] rowlength, int[] skiprows, int[] skippixels, int[] alignment)1326 private static void endBitmap(GL gl, 1327 int[] swapbytes, 1328 int[] lsbfirst, 1329 int[] rowlength, 1330 int[] skiprows, 1331 int[] skippixels, 1332 int[] alignment) { 1333 /* Restore saved modes. */ 1334 gl.glPixelStorei(GL.GL_UNPACK_SWAP_BYTES, swapbytes[0]); 1335 gl.glPixelStorei(GL.GL_UNPACK_LSB_FIRST, lsbfirst[0]); 1336 gl.glPixelStorei(GL.GL_UNPACK_ROW_LENGTH, rowlength[0]); 1337 gl.glPixelStorei(GL.GL_UNPACK_SKIP_ROWS, skiprows[0]); 1338 gl.glPixelStorei(GL.GL_UNPACK_SKIP_PIXELS, skippixels[0]); 1339 gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, alignment[0]); 1340 } 1341 } 1342