/** * Copyright (C) 2011 JogAmp Community. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package com.jogamp.opengl.test.junit.jogl.demos.es1; import java.nio.FloatBuffer; import com.jogamp.nativewindow.NativeWindow; import com.jogamp.opengl.GL; import com.jogamp.opengl.GL2ES1; import com.jogamp.opengl.GL2ES2; import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.GLEventListener; import com.jogamp.opengl.GLPipelineFactory; import com.jogamp.opengl.GLProfile; import com.jogamp.opengl.fixedfunc.GLLightingFunc; import com.jogamp.opengl.fixedfunc.GLMatrixFunc; import com.jogamp.newt.Window; import com.jogamp.newt.event.KeyAdapter; import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.event.KeyListener; import com.jogamp.newt.event.MouseAdapter; import com.jogamp.newt.event.MouseEvent; import com.jogamp.newt.event.MouseListener; import com.jogamp.opengl.GLRendererQuirks; import com.jogamp.opengl.JoglVersion; import com.jogamp.opengl.test.junit.jogl.demos.GearsObject; import com.jogamp.opengl.util.glsl.fixedfunc.FixedFuncUtil; import com.jogamp.opengl.util.glsl.fixedfunc.ShaderSelectionMode; /** * GearsES1.java <BR> * @author Brian Paul (converted to Java by Ron Cemer and Sven Gothel) <P> */ public class GearsES1 implements GLEventListener { private boolean debugFFPEmu = false; private boolean verboseFFPEmu = false; private boolean traceFFPEmu = false; private boolean forceFFPEmu = false; private boolean debug = false ; private boolean trace = false ; private final float pos[] = { 5.0f, 5.0f, 10.0f, 0.0f }; private float view_rotx = 20.0f, view_roty = 30.0f; private final float view_rotz = 0.0f; private GearsObject gear1=null, gear2=null, gear3=null; private FloatBuffer gear1Color=GearsObject.red, gear2Color=GearsObject.green, gear3Color=GearsObject.blue; private GearsES1 sharedGears; private Object syncObjects; private volatile boolean usesSharedGears = false; private boolean useMappedBuffers = false; private boolean validateBuffers = false; private float angle = 0.0f; private final int swapInterval; private final MouseListener gearsMouse = new GearsMouseAdapter(); private final KeyListener gearsKeys = new GearsKeyAdapter(); private volatile boolean isInit = false; private int prevMouseX, prevMouseY; public GearsES1(final int swapInterval) { this.swapInterval = swapInterval; } public GearsES1() { this.swapInterval = 1; } public void setForceFFPEmu(final boolean forceFFPEmu, final boolean verboseFFPEmu, final boolean debugFFPEmu, final boolean traceFFPEmu) { this.forceFFPEmu = forceFFPEmu; this.verboseFFPEmu = verboseFFPEmu; this.debugFFPEmu = debugFFPEmu; this.traceFFPEmu = traceFFPEmu; } public void setGearsColors(final FloatBuffer gear1Color, final FloatBuffer gear2Color, final FloatBuffer gear3Color) { this.gear1Color = gear1Color; this.gear2Color = gear2Color; this.gear3Color = gear3Color; } public void setSharedGears(final GearsES1 shared) { sharedGears = shared; } /** * @return gear1 */ public GearsObject getGear1() { return gear1; } /** * @return gear2 */ public GearsObject getGear2() { return gear2; } /** * @return gear3 */ public GearsObject getGear3() { return gear3; } public boolean usesSharedGears() { return usesSharedGears; } public void setUseMappedBuffers(final boolean v) { useMappedBuffers = v; } public void setValidateBuffers(final boolean v) { validateBuffers = v; } public void init(final GLAutoDrawable drawable) { if(null != sharedGears && !sharedGears.isInit() ) { System.err.println(Thread.currentThread()+" GearsES1.init.0: pending shared Gears .. re-init later XXXXX"); drawable.setGLEventListenerInitState(this, false); return; } System.err.println(Thread.currentThread()+" GearsES1.init ..."); // Use debug pipeline // drawable.setGL(new DebugGL(drawable.getGL())); GL _gl = drawable.getGL(); if(debugFFPEmu) { // Debug .. _gl = _gl.getContext().setGL( GLPipelineFactory.create("com.jogamp.opengl.Debug", GL2ES2.class, _gl, null) ); debug = false; } if(traceFFPEmu) { // Trace .. _gl = _gl.getContext().setGL( GLPipelineFactory.create("com.jogamp.opengl.Trace", GL2ES2.class, _gl, new Object[] { System.err } ) ); trace = false; } GL2ES1 gl = FixedFuncUtil.wrapFixedFuncEmul(_gl, ShaderSelectionMode.AUTO, null, forceFFPEmu, verboseFFPEmu); if(debug) { try { // Debug .. gl = (GL2ES1) gl.getContext().setGL( GLPipelineFactory.create("com.jogamp.opengl.Debug", GL2ES1.class, gl, null) ); } catch (final Exception e) {e.printStackTrace();} } if(trace) { try { // Trace .. gl = (GL2ES1) gl.getContext().setGL( GLPipelineFactory.create("com.jogamp.opengl.Trace", GL2ES1.class, gl, new Object[] { System.err } ) ); } catch (final Exception e) {e.printStackTrace();} } System.err.println("GearsES1 init on "+Thread.currentThread()); System.err.println("Chosen GLCapabilities: " + drawable.getChosenGLCapabilities()); System.err.println("INIT GL IS: " + gl.getClass().getName()); System.err.println(JoglVersion.getGLStrings(gl, null, false).toString()); gl.glLightfv(GLLightingFunc.GL_LIGHT0, GLLightingFunc.GL_POSITION, pos, 0); gl.glEnable(GL.GL_CULL_FACE); gl.glEnable(GLLightingFunc.GL_LIGHTING); gl.glEnable(GLLightingFunc.GL_LIGHT0); gl.glEnable(GL.GL_DEPTH_TEST); /* make the gears */ if( null != sharedGears ) { gear1 = new GearsObjectES1(sharedGears.getGear1()); gear2 = new GearsObjectES1(sharedGears.getGear2()); gear3 = new GearsObjectES1(sharedGears.getGear3()); usesSharedGears = true; System.err.println("gear1 reuse: "+gear1); System.err.println("gear2 reuse: "+gear2); System.err.println("gear3 reuse: "+gear3); if( gl.getContext().hasRendererQuirk(GLRendererQuirks.NeedSharedObjectSync) ) { syncObjects = sharedGears; System.err.println("Shared GearsES1: Synchronized Objects due to quirk "+GLRendererQuirks.toString(GLRendererQuirks.NeedSharedObjectSync)); } else { syncObjects = new Object(); System.err.println("Shared GearsES1: Unsynchronized Objects"); } } else { gear1 = new GearsObjectES1(gl, useMappedBuffers, gear1Color, 1.0f, 4.0f, 1.0f, 20, 0.7f, validateBuffers); System.err.println("gear1 created: "+gear1); gear2 = new GearsObjectES1(gl, useMappedBuffers, gear2Color, 0.5f, 2.0f, 2.0f, 10, 0.7f, validateBuffers); System.err.println("gear2 created: "+gear2); gear3 = new GearsObjectES1(gl, useMappedBuffers, gear3Color, 1.3f, 2.0f, 0.5f, 10, 0.7f, validateBuffers); System.err.println("gear3 created: "+gear3); syncObjects = new Object(); } gl.glEnable(GLLightingFunc.GL_NORMALIZE); final Object upstreamWidget = drawable.getUpstreamWidget(); if (upstreamWidget instanceof Window) { final Window window = (Window) upstreamWidget; window.addMouseListener(gearsMouse); window.addKeyListener(gearsKeys); } else if (GLProfile.isAWTAvailable() && upstreamWidget instanceof java.awt.Component) { final java.awt.Component comp = (java.awt.Component) upstreamWidget; new com.jogamp.newt.event.awt.AWTMouseAdapter(gearsMouse, drawable).addTo(comp); new com.jogamp.newt.event.awt.AWTKeyAdapter(gearsKeys, drawable).addTo(comp); } isInit = true; System.err.println(Thread.currentThread()+" GearsES1.init FIN"); } public final boolean isInit() { return isInit; } public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { if( !isInit ) { return; } System.err.println(Thread.currentThread()+" GearsES1.reshape "+x+"/"+y+" "+width+"x"+height+", swapInterval "+swapInterval); final GL2ES1 gl = drawable.getGL().getGL2ES1(); gl.setSwapInterval(swapInterval); gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION); gl.glLoadIdentity(); if(height>width) { final float h = (float)height / (float)width; gl.glFrustumf(-1.0f, 1.0f, -h, h, 5.0f, 60.0f); } else { final float h = (float)width / (float)height; gl.glFrustumf(-h, h, -1.0f, 1.0f, 5.0f, 60.0f); } gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); gl.glLoadIdentity(); gl.glTranslatef(0.0f, 0.0f, -40.0f); System.err.println(Thread.currentThread()+" GearsES1.reshape FIN"); } public void dispose(final GLAutoDrawable drawable) { if( !isInit ) { return; } isInit = false; System.err.println(Thread.currentThread()+" GearsES1.dispose ... "); final Object upstreamWidget = drawable.getUpstreamWidget(); if (upstreamWidget instanceof Window) { final Window window = (Window) upstreamWidget; window.removeMouseListener(gearsMouse); window.removeKeyListener(gearsKeys); } final GL gl = drawable.getGL(); gear1.destroy(gl); gear1 = null; gear2.destroy(gl); gear2 = null; gear3.destroy(gl); gear3 = null; sharedGears = null; syncObjects = null; System.err.println(Thread.currentThread()+" GearsES1.dispose FIN"); } public void display(final GLAutoDrawable drawable) { if( !isInit ) { return; } // Turn the gears' teeth angle += 0.5f; // Get the GL corresponding to the drawable we are animating final GL2ES1 gl = drawable.getGL().getGL2ES1(); final boolean hasFocus; final Object upstreamWidget = drawable.getUpstreamWidget(); if(upstreamWidget instanceof NativeWindow) { hasFocus = ((NativeWindow)upstreamWidget).hasFocus(); } else { hasFocus = true; } if(hasFocus) { gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); } else { gl.glClearColor(0.2f, 0.2f, 0.2f, 0.0f); } // Special handling for the case where the GLJPanel is translucent // and wants to be composited with other Java 2D content if (GLProfile.isAWTAvailable() && (drawable instanceof com.jogamp.opengl.awt.GLJPanel) && !((com.jogamp.opengl.awt.GLJPanel) drawable).isOpaque() && ((com.jogamp.opengl.awt.GLJPanel) drawable).shouldPreserveColorBufferIfTranslucent()) { gl.glClear(GL.GL_DEPTH_BUFFER_BIT); } else { gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); } gl.glNormal3f(0.0f, 0.0f, 1.0f); // Rotate the entire assembly of gears based on how the user // dragged the mouse around gl.glPushMatrix(); gl.glRotatef(view_rotx, 1.0f, 0.0f, 0.0f); gl.glRotatef(view_roty, 0.0f, 1.0f, 0.0f); gl.glRotatef(view_rotz, 0.0f, 0.0f, 1.0f); synchronized ( syncObjects ) { gear1.draw(gl, -3.0f, -2.0f, angle); gear2.draw(gl, 3.1f, -2.0f, -2.0f * angle - 9.0f); gear3.draw(gl, -3.1f, 4.2f, -2.0f * angle - 25.0f); } // Remember that every push needs a pop; this one is paired with // rotating the entire gear assembly gl.glPopMatrix(); } class GearsKeyAdapter extends KeyAdapter { public void keyPressed(final KeyEvent e) { final int kc = e.getKeyCode(); if(KeyEvent.VK_LEFT == kc) { view_roty -= 1; } else if(KeyEvent.VK_RIGHT == kc) { view_roty += 1; } else if(KeyEvent.VK_UP == kc) { view_rotx -= 1; } else if(KeyEvent.VK_DOWN == kc) { view_rotx += 1; } } } class GearsMouseAdapter extends MouseAdapter { public void mousePressed(final MouseEvent e) { prevMouseX = e.getX(); prevMouseY = e.getY(); } public void mouseReleased(final MouseEvent e) { } public void mouseDragged(final MouseEvent e) { final int x = e.getX(); final int y = e.getY(); int width=0, height=0; final Object source = e.getSource(); if(source instanceof Window) { final Window window = (Window) source; width=window.getSurfaceWidth(); height=window.getSurfaceHeight(); } else if (source instanceof GLAutoDrawable) { final GLAutoDrawable glad = (GLAutoDrawable) source; width = glad.getSurfaceWidth(); height = glad.getSurfaceHeight(); } else if (GLProfile.isAWTAvailable() && source instanceof java.awt.Component) { final java.awt.Component comp = (java.awt.Component) source; width=comp.getWidth(); // FIXME HiDPI: May need to convert window units -> pixel units! height=comp.getHeight(); } else { throw new RuntimeException("Event source neither Window nor Component: "+source); } final float thetaY = 360.0f * ( (float)(x-prevMouseX)/(float)width); final float thetaX = 360.0f * ( (float)(prevMouseY-y)/(float)height); prevMouseX = x; prevMouseY = y; view_rotx += thetaX; view_roty += thetaY; } } }