1 
2 package com.jogamp.opengl.test.junit.jogl.demos.gl2;
3 
4 import com.jogamp.opengl.GL;
5 import com.jogamp.opengl.GL2;
6 import com.jogamp.opengl.GL2GL3;
7 import com.jogamp.opengl.GLAutoDrawable;
8 import com.jogamp.opengl.GLEventListener;
9 import com.jogamp.opengl.GLProfile;
10 import com.jogamp.opengl.fixedfunc.GLLightingFunc;
11 import com.jogamp.opengl.fixedfunc.GLMatrixFunc;
12 
13 import com.jogamp.newt.Window;
14 import com.jogamp.newt.event.InputEvent;
15 import com.jogamp.newt.event.KeyAdapter;
16 import com.jogamp.newt.event.KeyEvent;
17 import com.jogamp.newt.event.KeyListener;
18 import com.jogamp.newt.event.MouseAdapter;
19 import com.jogamp.newt.event.MouseEvent;
20 import com.jogamp.newt.event.MouseListener;
21 import com.jogamp.newt.event.awt.AWTKeyAdapter;
22 import com.jogamp.newt.event.awt.AWTMouseAdapter;
23 import com.jogamp.opengl.GLRendererQuirks;
24 import com.jogamp.opengl.JoglVersion;
25 import com.jogamp.opengl.util.TileRendererBase;
26 
27 /**
28  * Gears.java <BR>
29  * author: Brian Paul (converted to Java by Ron Cemer and Sven Gothel) <P>
30  *
31  * This version is equal to Brian Paul's version 1.2 1999/10/21
32  */
33 public class Gears implements GLEventListener, TileRendererBase.TileRendererListener {
34   private float view_rotx = 20.0f, view_roty = 30.0f;
35   private final float view_rotz = 0.0f;
36   private int gear1=0, gear2=0, gear3=0;
37   private Gears sharedGears = null;
38   private Object syncObjects = null;
39   private float angle = 0.0f;
40   private boolean doRotate = true;
41   private final int swapInterval;
42   private final MouseListener gearsMouse = new GearsMouseAdapter();
43   private final KeyListener gearsKeys = new GearsKeyAdapter();
44   private TileRendererBase tileRendererInUse = null;
45   private boolean doRotateBeforePrinting;
46   private boolean verbose = true;
47   private boolean flipVerticalInGLOrientation = false;
48   private volatile boolean isInit = false;
49 
50   // private boolean mouseRButtonDown = false;
51   private int prevMouseX, prevMouseY;
52 
Gears(final int swapInterval)53   public Gears(final int swapInterval) {
54     this.swapInterval = swapInterval;
55   }
56 
Gears()57   public Gears() {
58     this.swapInterval = 1;
59   }
60 
61   @Override
addTileRendererNotify(final TileRendererBase tr)62   public void addTileRendererNotify(final TileRendererBase tr) {
63       tileRendererInUse = tr;
64       doRotateBeforePrinting = doRotate;
65       setDoRotation(false);
66   }
67   @Override
removeTileRendererNotify(final TileRendererBase tr)68   public void removeTileRendererNotify(final TileRendererBase tr) {
69       tileRendererInUse = null;
70       setDoRotation(doRotateBeforePrinting);
71   }
72   @Override
startTileRendering(final TileRendererBase tr)73   public void startTileRendering(final TileRendererBase tr) {
74       System.err.println("Gears.startTileRendering: "+tr);
75   }
76   @Override
endTileRendering(final TileRendererBase tr)77   public void endTileRendering(final TileRendererBase tr) {
78       System.err.println("Gears.endTileRendering: "+tr);
79   }
80 
setDoRotation(final boolean rotate)81   public void setDoRotation(final boolean rotate) { doRotate = rotate; }
setVerbose(final boolean v)82   public void setVerbose(final boolean v) { verbose = v; }
setFlipVerticalInGLOrientation(final boolean v)83   public void setFlipVerticalInGLOrientation(final boolean v) { flipVerticalInGLOrientation=v; }
84 
setSharedGears(final Gears shared)85   public void setSharedGears(final Gears shared) {
86       sharedGears = shared;
87   }
88 
89   /**
90    * @return display list gear1
91    */
getGear1()92   public int getGear1() { return gear1; }
93 
94   /**
95    * @return display list gear2
96    */
getGear2()97   public int getGear2() { return gear2; }
98 
99   /**
100    * @return display list gear3
101    */
getGear3()102   public int getGear3() { return gear3; }
103 
104   @Override
init(final GLAutoDrawable drawable)105   public void init(final GLAutoDrawable drawable) {
106     final GL2 gl = drawable.getGL().getGL2();
107 
108     if( init(gl) ) {
109         final Object upstreamWidget = drawable.getUpstreamWidget();
110         if (upstreamWidget instanceof Window) {
111             final Window window = (Window) upstreamWidget;
112             window.addMouseListener(gearsMouse);
113             window.addKeyListener(gearsKeys);
114         } else if (GLProfile.isAWTAvailable() && upstreamWidget instanceof java.awt.Component) {
115             final java.awt.Component comp = (java.awt.Component) upstreamWidget;
116             new AWTMouseAdapter(gearsMouse, drawable).addTo(comp);
117             new AWTKeyAdapter(gearsKeys, drawable).addTo(comp);
118         }
119     } else {
120         drawable.setGLEventListenerInitState(this, false);
121     }
122   }
123 
124   boolean enableCullFace = false;
125 
enableStates(final GL gl, final boolean enable)126   private void enableStates(final GL gl, final boolean enable) {
127     final boolean msaa = gl.getContext().getGLDrawable().getChosenGLCapabilities().getSampleBuffers();
128     if( enable ) {
129         if( enableCullFace ) {
130             gl.glEnable(GL.GL_CULL_FACE);
131         }
132         gl.glEnable(GLLightingFunc.GL_LIGHTING);
133         gl.glEnable(GLLightingFunc.GL_LIGHT0);
134         gl.glEnable(GL.GL_DEPTH_TEST);
135         gl.glDepthFunc(GL.GL_LESS); // default
136         gl.glEnable(GLLightingFunc.GL_NORMALIZE);
137         if( msaa ) {
138             gl.glEnable(GL.GL_MULTISAMPLE);
139         }
140     } else {
141         if( enableCullFace ) {
142             gl.glDisable(GL.GL_CULL_FACE);
143         }
144         gl.glDisable(GLLightingFunc.GL_LIGHTING);
145         gl.glDisable(GLLightingFunc.GL_LIGHT0);
146         gl.glDisable(GL.GL_DEPTH_TEST);
147         gl.glDisable(GLLightingFunc.GL_NORMALIZE);
148         if( msaa ) {
149             gl.glDisable(GL.GL_MULTISAMPLE);
150         }
151     }
152   }
153 
init(final GL2 gl)154   public boolean init(final GL2 gl) {
155     if(null != sharedGears && !sharedGears.isInit() ) {
156       System.err.println(Thread.currentThread()+" GearsES1.init.0: pending shared Gears .. re-init later XXXXX");
157       return false;
158     }
159     final float lightPos[] = { 5.0f, 5.0f, 10.0f, 0.0f };
160     final float red[] = { 0.8f, 0.1f, 0.0f, 0.7f };
161     final float green[] = { 0.0f, 0.8f, 0.2f, 0.7f };
162     final float blue[] = { 0.2f, 0.2f, 1.0f, 0.7f };
163 
164     System.err.println(Thread.currentThread()+" Gears.init: tileRendererInUse "+tileRendererInUse);
165     if(verbose) {
166         System.err.println("GearsES2 init on "+Thread.currentThread());
167         System.err.println("Chosen GLCapabilities: " + gl.getContext().getGLDrawable().getChosenGLCapabilities());
168         System.err.println("INIT GL IS: " + gl.getClass().getName());
169         System.err.println(JoglVersion.getGLStrings(gl, null, false).toString());
170     }
171 
172     gl.glLightfv(GLLightingFunc.GL_LIGHT0, GLLightingFunc.GL_POSITION, lightPos, 0);
173     if( ! ( flipVerticalInGLOrientation && gl.getContext().getGLDrawable().isGLOriented() ) ) {
174         // Only possible if we do not flip the projection matrix
175         enableCullFace = true;
176     } else {
177         enableCullFace = false;
178     }
179     enableStates(gl, true);
180 
181     /* make the gears */
182     if( null != sharedGears ) {
183         gear1 = sharedGears.getGear1();
184         gear2 = sharedGears.getGear2();
185         gear3 = sharedGears.getGear3();
186         System.err.println("gear1 list reused: "+gear1);
187         System.err.println("gear2 list reused: "+gear2);
188         System.err.println("gear3 list reused: "+gear3);
189         if( gl.getContext().hasRendererQuirk(GLRendererQuirks.NeedSharedObjectSync) ) {
190             syncObjects = sharedGears;
191             System.err.println("Shared Gears: Synchronized Objects due to quirk "+GLRendererQuirks.toString(GLRendererQuirks.NeedSharedObjectSync));
192         } else {
193             syncObjects = new Object();
194             System.err.println("Shared Gears: Unsynchronized Objects");
195         }
196     } else {
197         gear1 = gl.glGenLists(1);
198         gl.glNewList(gear1, GL2.GL_COMPILE);
199         gl.glMaterialfv(GL.GL_FRONT, GLLightingFunc.GL_AMBIENT_AND_DIFFUSE, red, 0);
200         gear(gl, 1.0f, 4.0f, 1.0f, 20, 0.7f);
201         gl.glEndList();
202         System.err.println("gear1 list created: "+gear1);
203 
204         gear2 = gl.glGenLists(1);
205         gl.glNewList(gear2, GL2.GL_COMPILE);
206         gl.glMaterialfv(GL.GL_FRONT, GLLightingFunc.GL_AMBIENT_AND_DIFFUSE, green, 0);
207         gear(gl, 0.5f, 2.0f, 2.0f, 10, 0.7f);
208         gl.glEndList();
209         System.err.println("gear2 list created: "+gear2);
210 
211         gear3 = gl.glGenLists(1);
212         gl.glNewList(gear3, GL2.GL_COMPILE);
213         gl.glMaterialfv(GL.GL_FRONT, GLLightingFunc.GL_AMBIENT_AND_DIFFUSE, blue, 0);
214         gear(gl, 1.3f, 2.0f, 0.5f, 10, 0.7f);
215         gl.glEndList();
216         System.err.println("gear3 list created: "+gear3);
217 
218         syncObjects = new Object();
219     }
220 
221     enableStates(gl, false);
222 
223     isInit = true;
224     return true;
225   }
226 
isInit()227   public final boolean isInit() { return isInit; }
228 
229   @Override
reshape(final GLAutoDrawable glad, final int x, final int y, final int width, final int height)230   public void reshape(final GLAutoDrawable glad, final int x, final int y, final int width, final int height) {
231       if( !isInit ) { return; }
232       final GL2 gl = glad.getGL().getGL2();
233       gl.setSwapInterval(swapInterval);
234       reshape(gl, x, y, width, height, width, height);
235   }
236 
237   @Override
reshapeTile(final TileRendererBase tr, final int tileX, final int tileY, final int tileWidth, final int tileHeight, final int imageWidth, final int imageHeight)238   public void reshapeTile(final TileRendererBase tr,
239           final int tileX, final int tileY, final int tileWidth, final int tileHeight,
240           final int imageWidth, final int imageHeight) {
241       if( !isInit ) { return; }
242       final GL2 gl = tr.getAttachedDrawable().getGL().getGL2();
243       gl.setSwapInterval(0);
244       reshape(gl, tileX, tileY, tileWidth, tileHeight, imageWidth, imageHeight);
245   }
246 
reshape(final GL2 gl, final int tileX, final int tileY, final int tileWidth, final int tileHeight, final int imageWidth, final int imageHeight)247   public void reshape(final GL2 gl, final int tileX, final int tileY, final int tileWidth, final int tileHeight, final int imageWidth, final int imageHeight) {
248     System.err.println(Thread.currentThread()+" Gears.reshape "+tileX+"/"+tileY+" "+tileWidth+"x"+tileHeight+" of "+imageWidth+"x"+imageHeight+", swapInterval "+swapInterval+", drawable 0x"+Long.toHexString(gl.getContext().getGLDrawable().getHandle())+", tileRendererInUse "+tileRendererInUse);
249 
250     // compute projection parameters 'normal'
251     float left, right, bottom, top;
252     if( imageHeight > imageWidth ) {
253         final float a = (float)imageHeight / (float)imageWidth;
254         left = -1.0f;
255         right = 1.0f;
256         bottom = -a;
257         top = a;
258     } else {
259         final float a = (float)imageWidth / (float)imageHeight;
260         left = -a;
261         right = a;
262         bottom = -1.0f;
263         top = 1.0f;
264     }
265     final float w = right - left;
266     final float h = top - bottom;
267 
268     // compute projection parameters 'tiled'
269     final float l = left + tileX * w / imageWidth;
270     final float r = l + tileWidth * w / imageWidth;
271 
272     final float b = bottom + tileY * h / imageHeight;
273     final float t = b + tileHeight * h / imageHeight;
274 
275     final float _w = r - l;
276     final float _h = t - b;
277     if(verbose) {
278         System.err.println(">> Gears angle "+angle+", [l "+left+", r "+right+", b "+bottom+", t "+top+"] "+w+"x"+h+" -> [l "+l+", r "+r+", b "+b+", t "+t+"] "+_w+"x"+_h+", v-flip "+flipVerticalInGLOrientation);
279     }
280 
281     gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
282     gl.glLoadIdentity();
283     if( flipVerticalInGLOrientation && gl.getContext().getGLDrawable().isGLOriented() ) {
284         gl.glScalef(1f, -1f, 1f);
285     }
286     gl.glFrustum(l, r, b, t, 5.0f, 60.0f);
287 
288     gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
289     gl.glLoadIdentity();
290     gl.glTranslatef(0.0f, 0.0f, -40.0f);
291   }
292 
293   @Override
dispose(final GLAutoDrawable drawable)294   public void dispose(final GLAutoDrawable drawable) {
295     if( !isInit ) { return; }
296     isInit = false;
297     System.err.println(Thread.currentThread()+" Gears.dispose: tileRendererInUse "+tileRendererInUse);
298     try {
299         final Object upstreamWidget = drawable.getUpstreamWidget();
300         if (upstreamWidget instanceof Window) {
301             final Window window = (Window) upstreamWidget;
302             window.removeMouseListener(gearsMouse);
303             window.removeKeyListener(gearsKeys);
304         }
305     } catch (final Exception e) { System.err.println("Caught: "); e.printStackTrace(); }
306     gear1 = 0;
307     gear2 = 0;
308     gear3 = 0;
309     sharedGears = null;
310     syncObjects = null;
311   }
312 
313   @Override
display(final GLAutoDrawable drawable)314   public void display(final GLAutoDrawable drawable) {
315     if( !isInit ) { return; }
316 
317     // Get the GL corresponding to the drawable we are animating
318     final GL2 gl = drawable.getGL().getGL2();
319 
320     enableStates(gl, true);
321 
322     if( null == tileRendererInUse ) {
323         gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
324     } else {
325         gl.glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
326     }
327 
328     // Special handling for the case where the GLJPanel is translucent
329     // and wants to be composited with other Java 2D content
330     if (GLProfile.isAWTAvailable() &&
331         (drawable instanceof com.jogamp.opengl.awt.GLJPanel) &&
332         !((com.jogamp.opengl.awt.GLJPanel) drawable).isOpaque() &&
333         ((com.jogamp.opengl.awt.GLJPanel) drawable).shouldPreserveColorBufferIfTranslucent()) {
334       gl.glClear(GL.GL_DEPTH_BUFFER_BIT);
335     } else {
336       gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
337     }
338     displayImpl(gl);
339 
340     enableStates(gl, false);
341   }
342 
display(final GL2 gl)343   public void display(final GL2 gl) {
344     if( !isInit ) { return; }
345     enableStates(gl, true);
346 
347     if( null == tileRendererInUse ) {
348         gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
349     } else {
350         gl.glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
351     }
352     gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
353     displayImpl(gl);
354 
355     enableStates(gl, false);
356   }
357 
displayImpl(final GL2 gl)358   private void displayImpl(final GL2 gl) {
359     if( doRotate ) {
360         // Turn the gears' teeth
361         angle += 0.5f;
362     }
363     // Rotate the entire assembly of gears based on how the user
364     // dragged the mouse around
365     gl.glPushMatrix();
366     gl.glRotatef(view_rotx, 1.0f, 0.0f, 0.0f);
367     gl.glRotatef(view_roty, 0.0f, 1.0f, 0.0f);
368     gl.glRotatef(view_rotz, 0.0f, 0.0f, 1.0f);
369 
370     // Place the first gear and call its display list
371     synchronized ( syncObjects ) {
372         gl.glPushMatrix();
373         gl.glTranslatef(-3.0f, -2.0f, 0.0f);
374         gl.glRotatef(angle, 0.0f, 0.0f, 1.0f);
375         gl.glCallList(gear1);
376         gl.glPopMatrix();
377 
378         // Place the second gear and call its display list
379         gl.glPushMatrix();
380         gl.glTranslatef(3.1f, -2.0f, 0.0f);
381         gl.glRotatef(-2.0f * angle - 9.0f, 0.0f, 0.0f, 1.0f);
382         gl.glCallList(gear2);
383         gl.glPopMatrix();
384 
385         // Place the third gear and call its display list
386         gl.glPushMatrix();
387         gl.glTranslatef(-3.1f, 4.2f, 0.0f);
388         gl.glRotatef(-2.0f * angle - 25.0f, 0.0f, 0.0f, 1.0f);
389         gl.glCallList(gear3);
390         gl.glPopMatrix();
391     }
392 
393     // Remember that every push needs a pop; this one is paired with
394     // rotating the entire gear assembly
395     gl.glPopMatrix();
396   }
397 
gear(final GL2 gl, final float inner_radius, final float outer_radius, final float width, final int teeth, final float tooth_depth)398   public static void gear(final GL2 gl,
399                           final float inner_radius,
400                           final float outer_radius,
401                           final float width,
402                           final int teeth,
403                           final float tooth_depth)
404   {
405     int i;
406     float r0, r1, r2;
407     float angle, da;
408     float u, v, len;
409 
410     r0 = inner_radius;
411     r1 = outer_radius - tooth_depth / 2.0f;
412     r2 = outer_radius + tooth_depth / 2.0f;
413 
414     da = 2.0f * (float) Math.PI / teeth / 4.0f;
415 
416     gl.glShadeModel(GLLightingFunc.GL_FLAT);
417 
418     gl.glNormal3f(0.0f, 0.0f, 1.0f);
419 
420     /* draw front face */
421     gl.glBegin(GL2.GL_QUAD_STRIP);
422     for (i = 0; i <= teeth; i++)
423       {
424         angle = i * 2.0f * (float) Math.PI / teeth;
425         gl.glVertex3f(r0 * (float)Math.cos(angle), r0 * (float)Math.sin(angle), width * 0.5f);
426         gl.glVertex3f(r1 * (float)Math.cos(angle), r1 * (float)Math.sin(angle), width * 0.5f);
427         if(i < teeth)
428           {
429             gl.glVertex3f(r0 * (float)Math.cos(angle), r0 * (float)Math.sin(angle), width * 0.5f);
430             gl.glVertex3f(r1 * (float)Math.cos(angle + 3.0f * da), r1 * (float)Math.sin(angle + 3.0f * da), width * 0.5f);
431           }
432       }
433     gl.glEnd();
434 
435     /* draw front sides of teeth */
436     gl.glBegin(GL2GL3.GL_QUADS);
437     for (i = 0; i < teeth; i++)
438       {
439         angle = i * 2.0f * (float) Math.PI / teeth;
440         gl.glVertex3f(r1 * (float)Math.cos(angle), r1 * (float)Math.sin(angle), width * 0.5f);
441         gl.glVertex3f(r2 * (float)Math.cos(angle + da), r2 * (float)Math.sin(angle + da), width * 0.5f);
442         gl.glVertex3f(r2 * (float)Math.cos(angle + 2.0f * da), r2 * (float)Math.sin(angle + 2.0f * da), width * 0.5f);
443         gl.glVertex3f(r1 * (float)Math.cos(angle + 3.0f * da), r1 * (float)Math.sin(angle + 3.0f * da), width * 0.5f);
444       }
445     gl.glEnd();
446 
447     /* draw back face */
448     gl.glBegin(GL2.GL_QUAD_STRIP);
449     for (i = 0; i <= teeth; i++)
450       {
451         angle = i * 2.0f * (float) Math.PI / teeth;
452         gl.glVertex3f(r1 * (float)Math.cos(angle), r1 * (float)Math.sin(angle), -width * 0.5f);
453         gl.glVertex3f(r0 * (float)Math.cos(angle), r0 * (float)Math.sin(angle), -width * 0.5f);
454         gl.glVertex3f(r1 * (float)Math.cos(angle + 3 * da), r1 * (float)Math.sin(angle + 3 * da), -width * 0.5f);
455         gl.glVertex3f(r0 * (float)Math.cos(angle), r0 * (float)Math.sin(angle), -width * 0.5f);
456       }
457     gl.glEnd();
458 
459     /* draw back sides of teeth */
460     gl.glBegin(GL2GL3.GL_QUADS);
461     for (i = 0; i < teeth; i++)
462       {
463         angle = i * 2.0f * (float) Math.PI / teeth;
464         gl.glVertex3f(r1 * (float)Math.cos(angle + 3 * da), r1 * (float)Math.sin(angle + 3 * da), -width * 0.5f);
465         gl.glVertex3f(r2 * (float)Math.cos(angle + 2 * da), r2 * (float)Math.sin(angle + 2 * da), -width * 0.5f);
466         gl.glVertex3f(r2 * (float)Math.cos(angle + da), r2 * (float)Math.sin(angle + da), -width * 0.5f);
467         gl.glVertex3f(r1 * (float)Math.cos(angle), r1 * (float)Math.sin(angle), -width * 0.5f);
468       }
469     gl.glEnd();
470 
471     /* draw outward faces of teeth */
472     gl.glBegin(GL2.GL_QUAD_STRIP);
473     for (i = 0; i < teeth; i++)
474       {
475         angle = i * 2.0f * (float) Math.PI / teeth;
476         gl.glVertex3f(r1 * (float)Math.cos(angle), r1 * (float)Math.sin(angle), width * 0.5f);
477         gl.glVertex3f(r1 * (float)Math.cos(angle), r1 * (float)Math.sin(angle), -width * 0.5f);
478         u = r2 * (float)Math.cos(angle + da) - r1 * (float)Math.cos(angle);
479         v = r2 * (float)Math.sin(angle + da) - r1 * (float)Math.sin(angle);
480         len = (float)Math.sqrt(u * u + v * v);
481         u /= len;
482         v /= len;
483         gl.glNormal3f(v, -u, 0.0f);
484         gl.glVertex3f(r2 * (float)Math.cos(angle + da), r2 * (float)Math.sin(angle + da), width * 0.5f);
485         gl.glVertex3f(r2 * (float)Math.cos(angle + da), r2 * (float)Math.sin(angle + da), -width * 0.5f);
486         gl.glNormal3f((float)Math.cos(angle), (float)Math.sin(angle), 0.0f);
487         gl.glVertex3f(r2 * (float)Math.cos(angle + 2 * da), r2 * (float)Math.sin(angle + 2 * da), width * 0.5f);
488         gl.glVertex3f(r2 * (float)Math.cos(angle + 2 * da), r2 * (float)Math.sin(angle + 2 * da), -width * 0.5f);
489         u = r1 * (float)Math.cos(angle + 3 * da) - r2 * (float)Math.cos(angle + 2 * da);
490         v = r1 * (float)Math.sin(angle + 3 * da) - r2 * (float)Math.sin(angle + 2 * da);
491         gl.glNormal3f(v, -u, 0.0f);
492         gl.glVertex3f(r1 * (float)Math.cos(angle + 3 * da), r1 * (float)Math.sin(angle + 3 * da), width * 0.5f);
493         gl.glVertex3f(r1 * (float)Math.cos(angle + 3 * da), r1 * (float)Math.sin(angle + 3 * da), -width * 0.5f);
494         gl.glNormal3f((float)Math.cos(angle), (float)Math.sin(angle), 0.0f);
495       }
496     gl.glVertex3f(r1 * (float)Math.cos(0), r1 * (float)Math.sin(0), width * 0.5f);
497     gl.glVertex3f(r1 * (float)Math.cos(0), r1 * (float)Math.sin(0), -width * 0.5f);
498     gl.glEnd();
499 
500     gl.glShadeModel(GLLightingFunc.GL_SMOOTH); // default
501 
502     /* draw inside radius cylinder */
503     gl.glBegin(GL2.GL_QUAD_STRIP);
504     for (i = 0; i <= teeth; i++)
505       {
506         angle = i * 2.0f * (float) Math.PI / teeth;
507         gl.glNormal3f(-(float)Math.cos(angle), -(float)Math.sin(angle), 0.0f);
508         gl.glVertex3f(r0 * (float)Math.cos(angle), r0 * (float)Math.sin(angle), -width * 0.5f);
509         gl.glVertex3f(r0 * (float)Math.cos(angle), r0 * (float)Math.sin(angle), width * 0.5f);
510       }
511     gl.glEnd();
512   }
513 
514   class GearsKeyAdapter extends KeyAdapter {
keyPressed(final KeyEvent e)515     public void keyPressed(final KeyEvent e) {
516         final int kc = e.getKeyCode();
517         if(KeyEvent.VK_LEFT == kc) {
518             view_roty -= 1;
519         } else if(KeyEvent.VK_RIGHT == kc) {
520             view_roty += 1;
521         } else if(KeyEvent.VK_UP == kc) {
522             view_rotx -= 1;
523         } else if(KeyEvent.VK_DOWN == kc) {
524             view_rotx += 1;
525         }
526     }
527   }
528 
529   class GearsMouseAdapter extends MouseAdapter {
mousePressed(final MouseEvent e)530       public void mousePressed(final MouseEvent e) {
531         prevMouseX = e.getX();
532         prevMouseY = e.getY();
533         if ((e.getModifiers() & InputEvent.BUTTON3_MASK) != 0) {
534           // mouseRButtonDown = true;
535         }
536       }
537 
mouseReleased(final MouseEvent e)538       public void mouseReleased(final MouseEvent e) {
539         if ((e.getModifiers() & InputEvent.BUTTON3_MASK) != 0) {
540           // mouseRButtonDown = false;
541         }
542       }
543 
mouseDragged(final MouseEvent e)544       public void mouseDragged(final MouseEvent e) {
545         final int x = e.getX();
546         final int y = e.getY();
547         int width=0, height=0;
548         final Object source = e.getSource();
549         if(source instanceof Window) {
550             final Window window = (Window) source;
551             width=window.getSurfaceWidth();
552             height=window.getSurfaceHeight();
553         } else if (source instanceof GLAutoDrawable) {
554             final GLAutoDrawable glad = (GLAutoDrawable) source;
555             width = glad.getSurfaceWidth();
556             height = glad.getSurfaceHeight();
557         } else if (GLProfile.isAWTAvailable() && source instanceof java.awt.Component) {
558             final java.awt.Component comp = (java.awt.Component) source;
559             width=comp.getWidth(); // FIXME HiDPI: May need to convert window units -> pixel units!
560             height=comp.getHeight();
561         } else {
562             throw new RuntimeException("Event source neither Window nor Component: "+source);
563         }
564         final float thetaY = 360.0f * ( (float)(x-prevMouseX)/(float)width);
565         final float thetaX = 360.0f * ( (float)(prevMouseY-y)/(float)height);
566 
567         prevMouseX = x;
568         prevMouseY = y;
569 
570         view_rotx += thetaX;
571         view_roty += thetaY;
572       }
573   }
574 }
575