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