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