/**
* Copyright 2013 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
package com.jogamp.opengl.test.junit.jogl.demos.gl2.awt;
import java.awt.ComponentOrientation;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import com.jogamp.opengl.GL;
import com.jogamp.opengl.GL2;
import com.jogamp.opengl.GL2ES1;
import com.jogamp.opengl.GL2GL3;
import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.awt.GLCanvas;
import com.jogamp.opengl.awt.GLJPanel;
import com.jogamp.opengl.fixedfunc.GLLightingFunc;
import com.jogamp.opengl.fixedfunc.GLMatrixFunc;
import com.jogamp.opengl.fixedfunc.GLPointerFunc;
import javax.swing.JApplet;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JFrame;
import javax.swing.SwingConstants;
import com.jogamp.common.util.VersionUtil;
import com.jogamp.opengl.JoglVersion;
import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.util.texture.Texture;
import com.jogamp.opengl.util.texture.TextureIO;
/**
* Bug 818: OSX GLJPanel [and GLCanvas] Crash
* <pre>
* - NVIDIA GeForce GT 330M
* - GL_VENDOR: "NVIDIA Corporation"
* - GL_RENDERER: "NVIDIA GeForce GT 330M OpenGL Engine"
* - GL_VERSION: "2.1 NVIDIA-8.12.47 310.40.00.05f01"
* - Mac OSX 10.6.8
* </pre>
*/
public class Bug818GLJPanelAndGLCanvasApplet extends JApplet {
private static final long serialVersionUID = 1L;
private Animator animatorCanvas;
private Animator animatorPanel;
public static JFrame frame;
public static JPanel appletHolder;
public static boolean isApplet = true;
static public void main(final String args[]) {
isApplet = false;
final JApplet myApplet = new Bug818GLJPanelAndGLCanvasApplet();
appletHolder = new JPanel();
frame = new JFrame("Bug818GLJPanelApplet");
frame.getContentPane().add(myApplet);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(final WindowEvent e) {
System.exit(0);
}
});
try {
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
myApplet.init();
frame.validate();
frame.pack();
frame.setVisible(true);
} } );
} catch( final Throwable throwable ) {
throwable.printStackTrace();
}
myApplet.start();
}
@Override
public void init() {
final JPanel panel = new JPanel();
panel.setLayout(new GridLayout(2, 2));
System.err.println("Pre Orientation L2R: "+panel.getComponentOrientation().isLeftToRight());
panel.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
System.err.println("Post Orientation L2R: "+panel.getComponentOrientation().isLeftToRight());
setContentPane(panel);
panel.add(new JLabel("GLJPanel", SwingConstants.CENTER));
panel.add(new JLabel("GLCanvas", SwingConstants.CENTER));
final GLJPanel gljPanel = new GLJPanel();
gljPanel.addGLEventListener(new JOGLQuad(false));
animatorPanel = new Animator(gljPanel);
gljPanel.setPreferredSize(new Dimension(300, 300));
panel.add(gljPanel);
final GLCanvas glCanvas = new GLCanvas();
glCanvas.addGLEventListener(new JOGLQuad(true));
animatorCanvas = new Animator(glCanvas);
glCanvas.setPreferredSize(new Dimension(300, 300));
panel.add(glCanvas);
}
@Override
public void start() {
animatorCanvas.start();
animatorCanvas.setUpdateFPSFrames(60, System.err);
animatorPanel.start();
animatorPanel.setUpdateFPSFrames(60, System.err);
}
@Override
public void stop() {
animatorCanvas.stop();
animatorPanel.stop();
}
@Override
public void destroy() {}
/**
* Self-contained example (within a single class only to keep it simple) displaying a rotating quad
*/
static class JOGLQuad implements GLEventListener {
private static final float[] VERTEX_DATA = {
-1.0f, 1.0f, 0.0f, // Top Left
1.0f, 1.0f, 0.0f, // Top Right
1.0f, -1.0f, 0.0f, // Bottom Right
-1.0f, -1.0f, 0.0f // Bottom Left
};
private static final float[] TEXCOORD_DATA = {
0.0f, 1.0f, // Top Left
1.0f, 1.0f, // Top Right
1.0f, 0.0f, // Bottom Right
0.0f, 0.0f // Bottom Left
};
private final FloatBuffer vertexBuf;
private final FloatBuffer texCoordBuf;
private int vertexVBO;
private int texCoordVBO;
private float rotateT = 0.0f;
private final boolean canvas;
private Texture texture;
JOGLQuad(final boolean canvas) {
this.canvas = canvas;
ByteBuffer bb = ByteBuffer.allocateDirect(VERTEX_DATA.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuf = bb.asFloatBuffer();
vertexBuf.put(VERTEX_DATA);
vertexBuf.rewind();
bb = ByteBuffer.allocateDirect(TEXCOORD_DATA.length * 4);
bb.order(ByteOrder.nativeOrder());
texCoordBuf = bb.asFloatBuffer();
texCoordBuf.put(TEXCOORD_DATA);
texCoordBuf.rewind();
}
@Override
public void init(final GLAutoDrawable glDrawable) {
final GL2 gl = glDrawable.getGL().getGL2();
System.err.println(VersionUtil.getPlatformInfo());
System.err.println(JoglVersion.getGLInfo(gl, null, false /* withCapabilitiesAndExtensionInfo */).toString());
gl.glShadeModel(GLLightingFunc.GL_SMOOTH);
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
gl.glClearDepth(1.0f);
gl.glEnable(GL.GL_DEPTH_TEST);
gl.glDepthFunc(GL.GL_LEQUAL);
gl.glHint(GL2ES1.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);
final int[] tmp = new int[2];
gl.glGenBuffers(tmp.length, tmp, 0);
vertexVBO = tmp[0];
texCoordVBO = tmp[1];
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vertexVBO);
gl.glBufferData(GL.GL_ARRAY_BUFFER, VERTEX_DATA.length * 4, vertexBuf, GL.GL_STATIC_DRAW);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, texCoordVBO);
gl.glBufferData(GL.GL_ARRAY_BUFFER, TEXCOORD_DATA.length * 4, texCoordBuf, GL.GL_STATIC_DRAW);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
try {
final InputStream stream = getClass().getClassLoader().getResourceAsStream("com/jogamp/opengl/test/junit/jogl/util/texture/test-ntscN_3-01-160x90-90pct-yuv444-base.jpg");
texture = TextureIO.newTexture(stream, true, TextureIO.JPG);
} catch (final Exception exc) {
exc.printStackTrace(System.err);
}
}
@Override
public void dispose(final GLAutoDrawable drawable) {
final GL2 gl = drawable.getGL().getGL2();
final int[] tmp = new int[] {vertexVBO, texCoordVBO};
gl.glGenBuffers(tmp.length, tmp, 0);
}
@Override
public void reshape(final GLAutoDrawable gLDrawable, final int x, final int y, final int width, final int height) {
final GL2 gl = gLDrawable.getGL().getGL2();
final float aspect = (float) width / (float) height;
gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
gl.glLoadIdentity();
final float fh = 0.5f;
final float fw = fh * aspect;
gl.glFrustumf(-fw, fw, -fh, fh, 1.0f, 1000.0f);
gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
gl.glLoadIdentity();
}
@Override
public void display(final GLAutoDrawable gLDrawable) {
final GL2 gl = gLDrawable.getGL().getGL2();
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
gl.glTranslatef(0.0f, 0.0f, -5.0f);
// rotate about the three axes
gl.glRotatef(rotateT, 1.0f, 0.0f, 0.0f);
gl.glRotatef(rotateT, 0.0f, 1.0f, 0.0f);
gl.glRotatef(rotateT, 0.0f, 0.0f, 1.0f);
// set the color of the quad
if (canvas) {
gl.glColor3f(0.2f, 0.2f, 1.0f);
} else {
gl.glColor3f(1.0f, 0.2f, 0.2f);
}
if (texture != null) {
texture.bind(gl);
texture.enable(gl);
} else {
System.err.println("no texture");
}
// Draw A Quad
gl.glEnableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
gl.glEnableClientState(GLPointerFunc.GL_TEXTURE_COORD_ARRAY);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vertexVBO);
gl.glVertexPointer(3, GL.GL_FLOAT, 0, 0);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, texCoordVBO);
gl.glTexCoordPointer(2, GL.GL_FLOAT, 0, 0);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
gl.glDrawArrays(GL2GL3.GL_QUADS, 0, 4);
gl.glDisableClientState(GLPointerFunc.GL_TEXTURE_COORD_ARRAY);
gl.glDisableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
if (texture != null) {
texture.disable(gl);
}
// increasing rotation for the next iteration
rotateT += 0.2f;
}
}
}