aboutsummaryrefslogtreecommitdiffstats
path: root/src/test/com
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/com')
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java14
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSBSStereo.java859
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java14
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/stereo/StereoDemo01.java307
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/stereo/ovr/OVRDemo01.java236
5 files changed, 1182 insertions, 248 deletions
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java
index 2709aa608..84cd8936e 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java
@@ -35,7 +35,7 @@ import com.jogamp.opengl.math.FloatUtil;
import com.jogamp.opengl.math.Quaternion;
import com.jogamp.opengl.math.VectorUtil;
import com.jogamp.opengl.test.junit.jogl.demos.GearsObject;
-import com.jogamp.opengl.util.CustomRendererListener;
+import com.jogamp.opengl.util.CustomGLEventListener;
import com.jogamp.opengl.util.PMVMatrix;
import com.jogamp.opengl.util.TileRendererBase;
import com.jogamp.opengl.util.glsl.ShaderCode;
@@ -43,7 +43,7 @@ import com.jogamp.opengl.util.glsl.ShaderProgram;
import com.jogamp.opengl.util.glsl.ShaderState;
import com.jogamp.opengl.util.stereo.EyeParameter;
import com.jogamp.opengl.util.stereo.EyePose;
-import com.jogamp.opengl.util.stereo.StereoRendererListener;
+import com.jogamp.opengl.util.stereo.StereoGLEventListener;
import java.nio.FloatBuffer;
@@ -60,7 +60,7 @@ import javax.media.opengl.fixedfunc.GLMatrixFunc;
* GearsES2.java <BR>
* @author Brian Paul (converted to Java by Ron Cemer and Sven Gothel) <P>
*/
-public class GearsES2 implements StereoRendererListener, TileRendererBase.TileRendererListener {
+public class GearsES2 implements StereoGLEventListener, TileRendererBase.TileRendererListener {
private final FloatBuffer lightPos = Buffers.newDirectFloatBuffer( new float[] { 5.0f, 5.0f, 10.0f } );
private ShaderState st = null;
@@ -419,8 +419,8 @@ public class GearsES2 implements StereoRendererListener, TileRendererBase.TileRe
private final float[] vec3Tmp3 = new float[3];
@Override
- public void reshapeEye(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height,
- final EyeParameter eyeParam, final EyePose eyePose) {
+ public void reshapeForEye(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height,
+ final EyeParameter eyeParam, final EyePose eyePose) {
final GL2ES2 gl = drawable.getGL().getGL2ES2();
pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
final float[] mat4Projection = FloatUtil.makePerspective(mat4Tmp1, 0, true, eyeParam.fovhv, zNear, zFar);
@@ -507,8 +507,8 @@ public class GearsES2 implements StereoRendererListener, TileRendererBase.TileRe
System.err.println(Thread.currentThread()+" GearsES2.display "+sid()+" "+drawable.getSurfaceWidth()+"x"+drawable.getSurfaceHeight()+", swapInterval "+swapInterval+", drawable 0x"+Long.toHexString(drawable.getHandle()));
}
- final boolean repeatedFrame = 0 != ( CustomRendererListener.DISPLAY_REPEAT & flags );
- final boolean dontClear = 0 != ( CustomRendererListener.DISPLAY_DONTCLEAR & flags );
+ final boolean repeatedFrame = 0 != ( CustomGLEventListener.DISPLAY_REPEAT & flags );
+ final boolean dontClear = 0 != ( CustomGLEventListener.DISPLAY_DONTCLEAR & flags );
// Turn the gears' teeth
if( doRotate && !repeatedFrame ) {
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSBSStereo.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSBSStereo.java
new file mode 100644
index 000000000..a2a39d631
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSBSStereo.java
@@ -0,0 +1,859 @@
+/**
+ * Copyright 2012 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.es2.av;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.FloatBuffer;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GLAnimatorControl;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLES2;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLUniformData;
+import javax.media.opengl.fixedfunc.GLMatrixFunc;
+
+import com.jogamp.common.os.Platform;
+import com.jogamp.graph.curve.Region;
+import com.jogamp.graph.curve.opengl.GLRegion;
+import com.jogamp.graph.curve.opengl.RegionRenderer;
+import com.jogamp.graph.font.Font;
+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.newt.opengl.GLWindow;
+import com.jogamp.opengl.GLExtensions;
+import com.jogamp.opengl.JoglVersion;
+import com.jogamp.opengl.math.FloatUtil;
+import com.jogamp.opengl.math.Quaternion;
+import com.jogamp.opengl.math.VectorUtil;
+import com.jogamp.opengl.test.junit.graph.TextRendererGLELBase;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.CustomGLEventListener;
+import com.jogamp.opengl.util.GLArrayDataServer;
+import com.jogamp.opengl.util.PMVMatrix;
+import com.jogamp.opengl.util.av.GLMediaPlayer;
+import com.jogamp.opengl.util.av.GLMediaPlayer.GLMediaEventListener;
+import com.jogamp.opengl.util.av.GLMediaPlayerFactory;
+import com.jogamp.opengl.util.glsl.ShaderCode;
+import com.jogamp.opengl.util.glsl.ShaderProgram;
+import com.jogamp.opengl.util.glsl.ShaderState;
+import com.jogamp.opengl.util.stereo.EyeParameter;
+import com.jogamp.opengl.util.stereo.EyePose;
+import com.jogamp.opengl.util.stereo.StereoClientRenderer;
+import com.jogamp.opengl.util.stereo.StereoGLEventListener;
+import com.jogamp.opengl.util.texture.Texture;
+import com.jogamp.opengl.util.texture.TextureCoords;
+import com.jogamp.opengl.util.texture.TextureSequence;
+import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame;
+
+/**
+ * Side-By-Side (SBS) 3D Movie Player for {@link StereoClientRenderer}
+ * <p>
+ * The movie is assumed to be symmetrical SBS,
+ * the left-eye receives the left-part of the texture
+ * and the right-eye the right-part.
+ * </p>
+ */
+public class MovieSBSStereo implements StereoGLEventListener {
+ public static final String WINDOW_KEY = "window";
+ public static final String STEREO_RENDERER_KEY = "stereo";
+ public static final String PLAYER = "player";
+
+ private static boolean waitForKey = false;
+ private int surfWidth, surfHeight;
+ private int prevMouseX; // , prevMouseY;
+ private int rotate = 0;
+ private float zoom0;
+ private float zoom1;
+ private float zoom;
+ private long startTime;
+ private final float alpha = 1.0f;
+
+ private GLMediaPlayer mPlayer;
+ private boolean mPlayerScaleOrig;
+ private float[] verts = null;
+ private GLArrayDataServer interleavedVBOLeft;
+ private GLArrayDataServer interleavedVBORight;
+ private volatile boolean resetGLState = false;
+ private StereoClientRenderer stereoClientRenderer;
+
+ private ShaderState st;
+ private PMVMatrix pmvMatrix;
+ private GLUniformData pmvMatrixUniform;
+ private static final String shaderBasename = "texsequence_xxx";
+ private static final String myTextureLookupName = "myTexture2D";
+
+ /** Blender's Big Buck Bunny: 24f 416p H.264, AAC 48000 Hz, 2 ch, mpeg stream. */
+ public static final URI defURI;
+ static {
+ URI _defURI = null;
+ try {
+ // Blender's Big Buck Bunny Trailer: 24f 640p VP8, Vorbis 44100Hz mono, WebM/Matroska Stream.
+ // _defURI = new URI("http://video.webmfiles.org/big-buck-bunny_trailer.webm");
+ _defURI = new URI("http://archive.org/download/BigBuckBunny_328/BigBuckBunny_512kb.mp4");
+ } catch (final URISyntaxException e) {
+ e.printStackTrace();
+ }
+ defURI = _defURI;
+ }
+
+ final int[] textSampleCount = { 4 };
+
+ private final class InfoTextRendererGLELBase extends TextRendererGLELBase {
+ private final Font font = getFont(0, 0, 0);
+ private final float fontSize = 1f; // 0.01f;
+ private final GLRegion regionFPS;
+
+ InfoTextRendererGLELBase(final int rmode, final boolean lowPerfDevice) {
+ // FIXME: Graph TextRenderer does not AA well w/o MSAA and FBO
+ super(rmode, textSampleCount);
+ this.setRendererCallbacks(RegionRenderer.defaultBlendEnable, RegionRenderer.defaultBlendDisable);
+ if( lowPerfDevice ) {
+ regionFPS = null;
+ } else {
+ regionFPS = GLRegion.create(renderModes, null);
+ System.err.println("RegionFPS "+Region.getRenderModeString(renderModes)+", sampleCount "+textSampleCount[0]+", class "+regionFPS.getClass().getName());
+ }
+ staticRGBAColor[0] = 0.9f;
+ staticRGBAColor[1] = 0.9f;
+ staticRGBAColor[2] = 0.9f;
+ staticRGBAColor[3] = 1.0f;
+ }
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ super.init(drawable);
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ if( null != regionFPS ) {
+ regionFPS.destroy(drawable.getGL().getGL2ES2());
+ }
+ super.dispose(drawable);
+ }
+
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ final GLAnimatorControl anim = drawable.getAnimator();
+ final float lfps = null != anim ? anim.getLastFPS() : 0f;
+ final float tfps = null != anim ? anim.getTotalFPS() : 0f;
+ final boolean hasVideo = GLMediaPlayer.STREAM_ID_NONE != mPlayer.getVID();
+ final float pts = ( hasVideo ? mPlayer.getVideoPTS() : mPlayer.getAudioPTS() ) / 1000f;
+
+ // Note: MODELVIEW is from [ 0 .. height ]
+
+ final int height = 0; // drawable.getSurfaceHeight();
+
+ final float aspect = (float)mPlayer.getWidth() / (float)mPlayer.getHeight();
+
+ final String ptsPrec = null != regionFPS ? "3.1" : "3.0";
+ final String text1 = String.format("%0"+ptsPrec+"f/%0"+ptsPrec+"f s, %s (%01.2fx, vol %01.2f), a %01.2f, fps %02.1f -> %02.1f / %02.1f",
+ pts, mPlayer.getDuration() / 1000f,
+ mPlayer.getState().toString().toLowerCase(), mPlayer.getPlaySpeed(), mPlayer.getAudioVolume(),
+ aspect, mPlayer.getFramerate(), lfps, tfps);
+ final String text2 = String.format("audio: id %d, kbps %d, codec %s",
+ mPlayer.getAID(), mPlayer.getAudioBitrate()/1000, mPlayer.getAudioCodec());
+ final String text3 = String.format("video: id %d, kbps %d, codec %s",
+ mPlayer.getVID(), mPlayer.getVideoBitrate()/1000, mPlayer.getVideoCodec());
+ final String text4 = mPlayer.getURI().getRawPath();
+ if( displayOSD && null != renderer ) {
+ // We share ClearColor w/ MovieSimple's init !
+ final float pixelSize = font.getPixelSize(fontSize, dpiH);
+ if( null != regionFPS ) {
+ renderString(drawable, font, pixelSize, text1, 1 /* col */, 1 /* row */, 0, 0, -1, regionFPS); // no-cache
+ } else {
+ renderString(drawable, font, pixelSize, text1, 1 /* col */, 1 /* row */, 0, 0, -1, true);
+ }
+ renderString(drawable, font, pixelSize, text2, 1 /* col */, -4 /* row */, 0, height, -1, true);
+ renderString(drawable, font, pixelSize, text3, 1 /* col */, -3 /* row */, 0, height, 0, true);
+ renderString(drawable, font, pixelSize, text4, 1 /* col */, -2 /* row */, 0, height, 1, true);
+ }
+ } };
+ private InfoTextRendererGLELBase textRendererGLEL = null;
+ private boolean displayOSD = false;
+
+ private final MouseListener mouseAction = new MouseAdapter() {
+ public void mousePressed(final MouseEvent e) {
+ if(e.getY()<=surfHeight/2 && null!=mPlayer && 1 == e.getClickCount()) {
+ if(GLMediaPlayer.State.Playing == mPlayer.getState()) {
+ mPlayer.pause(false);
+ } else {
+ mPlayer.play();
+ }
+ }
+ }
+ public void mouseReleased(final MouseEvent e) {
+ if(e.getY()<=surfHeight/2) {
+ rotate = -1;
+ zoom = zoom0;
+ System.err.println("zoom: "+zoom);
+ }
+ }
+ public void mouseMoved(final MouseEvent e) {
+ prevMouseX = e.getX();
+ // prevMouseY = e.getY();
+ }
+ public void mouseDragged(final MouseEvent e) {
+ final int x = e.getX();
+ final int y = e.getY();
+
+ if(y>surfHeight/2) {
+ final float dp = (float)(x-prevMouseX)/(float)surfWidth;
+ final int pts0 = GLMediaPlayer.STREAM_ID_NONE != mPlayer.getVID() ? mPlayer.getVideoPTS() : mPlayer.getAudioPTS();
+ mPlayer.seek(pts0 + (int) (mPlayer.getDuration() * dp));
+ } else {
+ mPlayer.play();
+ rotate = 1;
+ zoom = zoom1;
+ }
+
+ prevMouseX = x;
+ // prevMouseY = y;
+ }
+ public void mouseWheelMoved(final MouseEvent e) {
+ if( !e.isShiftDown() ) {
+ zoom += e.getRotation()[1]/10f; // vertical: wheel
+ System.err.println("zoom: "+zoom);
+ }
+ } };
+
+ private final KeyListener keyAction = new KeyAdapter() {
+ public void keyReleased(final KeyEvent e) {
+ if( e.isAutoRepeat() ) {
+ return;
+ }
+ System.err.println("MC "+e);
+ final int pts0 = GLMediaPlayer.STREAM_ID_NONE != mPlayer.getVID() ? mPlayer.getVideoPTS() : mPlayer.getAudioPTS();
+ int pts1 = 0;
+ switch(e.getKeySymbol()) {
+ case KeyEvent.VK_O: displayOSD = !displayOSD; break;
+ case KeyEvent.VK_RIGHT: pts1 = pts0 + 1000; break;
+ case KeyEvent.VK_UP: pts1 = pts0 + 10000; break;
+ case KeyEvent.VK_PAGE_UP: pts1 = pts0 + 30000; break;
+ case KeyEvent.VK_LEFT: pts1 = pts0 - 1000; break;
+ case KeyEvent.VK_DOWN: pts1 = pts0 - 10000; break;
+ case KeyEvent.VK_PAGE_DOWN: pts1 = pts0 - 30000; break;
+ case KeyEvent.VK_ESCAPE:
+ case KeyEvent.VK_HOME:
+ case KeyEvent.VK_BACK_SPACE: {
+ mPlayer.seek(0);
+ break;
+ }
+ case KeyEvent.VK_SPACE: {
+ if(GLMediaPlayer.State.Paused == mPlayer.getState()) {
+ mPlayer.play();
+ } else {
+ mPlayer.pause(false);
+ }
+ break;
+ }
+ case KeyEvent.VK_MULTIPLY:
+ mPlayer.setPlaySpeed(1.0f);
+ break;
+ case KeyEvent.VK_SUBTRACT: {
+ float playSpeed = mPlayer.getPlaySpeed();
+ if( e.isShiftDown() ) {
+ playSpeed /= 2.0f;
+ } else {
+ playSpeed -= 0.1f;
+ }
+ mPlayer.setPlaySpeed(playSpeed);
+ } break;
+ case KeyEvent.VK_ADD: {
+ float playSpeed = mPlayer.getPlaySpeed();
+ if( e.isShiftDown() ) {
+ playSpeed *= 2.0f;
+ } else {
+ playSpeed += 0.1f;
+ }
+ mPlayer.setPlaySpeed(playSpeed);
+ } break;
+ case KeyEvent.VK_M: {
+ float audioVolume = mPlayer.getAudioVolume();
+ if( audioVolume > 0.5f ) {
+ audioVolume = 0f;
+ } else {
+ audioVolume = 1f;
+ }
+ mPlayer.setAudioVolume(audioVolume);
+ } break;
+ }
+
+ if( 0 != pts1 ) {
+ mPlayer.seek(pts1);
+ }
+ } };
+
+ /** user needs to issue {@link #initStream(URI, int, int, int)} afterwards. */
+ public MovieSBSStereo() throws IllegalStateException {
+ mPlayerScaleOrig = false;
+ mPlayer = GLMediaPlayerFactory.createDefault();
+ mPlayer.attachObject(PLAYER, this);
+ System.out.println("pC.1a "+mPlayer);
+ }
+
+ public void initStream(final URI streamLoc, final int vid, final int aid, final int textureCount) {
+ mPlayer.initStream(streamLoc, vid, aid, textureCount);
+ System.out.println("pC.1b "+mPlayer);
+ }
+
+ public GLMediaPlayer getGLMediaPlayer() { return mPlayer; }
+
+ public void setScaleOrig(final boolean v) {
+ mPlayerScaleOrig = v;
+ }
+
+ public void setStereoClientRenderer(final StereoClientRenderer scr) {
+ stereoClientRenderer = scr;
+ }
+ public StereoClientRenderer getStereoClientRenderer() { return stereoClientRenderer; }
+
+ public void resetGLState() {
+ resetGLState = true;
+ }
+
+ private void initShader(final GL2ES2 gl) {
+ // Create & Compile the shader objects
+ final ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, MovieSBSStereo.class,
+ "../shader", "../shader/bin", shaderBasename, true);
+ final ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, MovieSBSStereo.class,
+ "../shader", "../shader/bin", shaderBasename, true);
+
+ boolean preludeGLSLVersion = true;
+ if( GLES2.GL_TEXTURE_EXTERNAL_OES == mPlayer.getTextureTarget() ) {
+ if( !gl.isExtensionAvailable(GLExtensions.OES_EGL_image_external) ) {
+ throw new GLException(GLExtensions.OES_EGL_image_external+" requested but not available");
+ }
+ if( Platform.OSType.ANDROID == Platform.getOSType() && gl.isGLES3() ) {
+ // Bug on Nexus 10, ES3 - Android 4.3, where
+ // GL_OES_EGL_image_external extension directive leads to a failure _with_ '#version 300 es' !
+ // P0003: Extension 'GL_OES_EGL_image_external' not supported
+ preludeGLSLVersion = false;
+ }
+ }
+ rsVp.defaultShaderCustomization(gl, preludeGLSLVersion, true);
+
+ int rsFpPos = preludeGLSLVersion ? rsFp.addGLSLVersion(gl) : 0;
+ rsFpPos = rsFp.insertShaderSource(0, rsFpPos, mPlayer.getRequiredExtensionsShaderStub());
+ rsFpPos = rsFp.addDefaultShaderPrecision(gl, rsFpPos);
+
+ final String texLookupFuncName = mPlayer.getTextureLookupFunctionName(myTextureLookupName);
+ rsFp.replaceInShaderSource(myTextureLookupName, texLookupFuncName);
+
+ // Inject TextureSequence shader details
+ final StringBuilder sFpIns = new StringBuilder();
+ sFpIns.append("uniform ").append(mPlayer.getTextureSampler2DType()).append(" mgl_ActiveTexture;\n");
+ sFpIns.append(mPlayer.getTextureLookupFragmentShaderImpl());
+ rsFp.insertShaderSource(0, "TEXTURE-SEQUENCE-CODE-BEGIN", 0, sFpIns);
+
+ // Create & Link the shader program
+ final ShaderProgram sp = new ShaderProgram();
+ sp.add(rsVp);
+ sp.add(rsFp);
+ if(!sp.link(gl, System.err)) {
+ throw new GLException("Couldn't link program: "+sp);
+ }
+
+ // Let's manage all our states using ShaderState.
+ st = new ShaderState();
+ st.attachShaderProgram(gl, sp, false);
+ }
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ if(null == mPlayer) {
+ throw new InternalError("mPlayer null");
+ }
+ if( GLMediaPlayer.State.Uninitialized == mPlayer.getState() ) {
+ throw new IllegalStateException("mPlayer in uninitialized state: "+mPlayer);
+ }
+ final boolean hasVideo = GLMediaPlayer.STREAM_ID_NONE != mPlayer.getVID();
+ resetGLState = false;
+
+ zoom0 = -2.1f;
+ zoom1 = -5f;
+ zoom = 0f;
+
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ System.err.println(JoglVersion.getGLInfo(gl, null));
+ System.err.println("Alpha: "+alpha+", opaque "+drawable.getChosenGLCapabilities().isBackgroundOpaque()+
+ ", "+drawable.getClass().getName()+", "+drawable);
+
+ if(waitForKey) {
+ UITestCase.waitForKey("Init>");
+ }
+ final Texture tex;
+ try {
+ System.out.println("p0 "+mPlayer);
+ if(GLMediaPlayer.State.Initialized == mPlayer.getState() ) {
+ mPlayer.initGL(gl);
+ }
+ System.out.println("p1 "+mPlayer);
+ final TextureFrame frame = mPlayer.getLastTexture();
+ if( null != frame ) {
+ if( !hasVideo ) {
+ throw new InternalError("XXX: "+mPlayer);
+ }
+ tex = frame.getTexture();
+ if( null == tex ) {
+ throw new InternalError("XXX: "+mPlayer);
+ }
+ } else {
+ tex = null;
+ if( hasVideo ) {
+ throw new InternalError("XXX: "+mPlayer);
+ }
+ }
+ mPlayer.setTextureMinMagFilter( new int[] { GL.GL_NEAREST, GL.GL_NEAREST } );
+ } catch (final Exception glex) {
+ glex.printStackTrace();
+ if(null != mPlayer) {
+ mPlayer.destroy(gl);
+ mPlayer = null;
+ }
+ throw new GLException(glex);
+ }
+
+ if( hasVideo ) {
+ initShader(gl);
+
+ // Push the 1st uniform down the path
+ st.useProgram(gl, true);
+
+ final int[] viewPort = new int[] { 0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight()};
+ pmvMatrix = new PMVMatrix();
+ reshapePMV(viewPort[2], viewPort[3]);
+ pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf());
+ if(!st.uniform(gl, pmvMatrixUniform)) {
+ throw new GLException("Error setting PMVMatrix in shader: "+st);
+ }
+ if(!st.uniform(gl, new GLUniformData("mgl_ActiveTexture", mPlayer.getTextureUnit()))) {
+ throw new GLException("Error setting mgl_ActiveTexture in shader: "+st);
+ }
+
+ final float dWidth = drawable.getSurfaceWidth();
+ final float dHeight = drawable.getSurfaceHeight();
+ final float mWidth = mPlayer.getWidth();
+ final float mHeight = mPlayer.getHeight();
+ final float mAspect = mWidth/mHeight;
+ System.err.println("XXX0: mov aspect: "+mAspect);
+ float xs, ys;
+ if(mPlayerScaleOrig && mWidth < dWidth && mHeight < dHeight) {
+ xs = mAspect * ( mWidth / dWidth ) ; ys = xs / mAspect ;
+ } else {
+ xs = mAspect; ys = 1f; // b>h
+ }
+ verts = new float[] { -1f*xs, -1f*ys, 0f, // LB
+ 1f*xs, 1f*ys, 0f // RT
+ };
+ {
+ System.err.println("XXX0: pixel LB: "+verts[0]+", "+verts[1]+", "+verts[2]);
+ System.err.println("XXX0: pixel RT: "+verts[3]+", "+verts[4]+", "+verts[5]);
+ final float[] winLB = new float[3];
+ final float[] winRT = new float[3];
+ pmvMatrix.gluProject(verts[0], verts[1], verts[2], viewPort, 0, winLB, 0);
+ pmvMatrix.gluProject(verts[3], verts[4], verts[5], viewPort, 0, winRT, 0);
+ System.err.println("XXX0: win LB: "+winLB[0]+", "+winLB[1]+", "+winLB[2]);
+ System.err.println("XXX0: win RT: "+winRT[0]+", "+winRT[1]+", "+winRT[2]);
+ }
+
+ interleavedVBOLeft = GLArrayDataServer.createGLSLInterleaved(3+4+2, GL.GL_FLOAT, false, 3*4, GL.GL_STATIC_DRAW);
+ {
+ interleavedVBOLeft.addGLSLSubArray("mgl_Vertex", 3, GL.GL_ARRAY_BUFFER);
+ interleavedVBOLeft.addGLSLSubArray("mgl_Color", 4, GL.GL_ARRAY_BUFFER);
+ interleavedVBOLeft.addGLSLSubArray("mgl_MultiTexCoord", 2, GL.GL_ARRAY_BUFFER);
+ }
+ interleavedVBORight = GLArrayDataServer.createGLSLInterleaved(3+4+2, GL.GL_FLOAT, false, 3*4, GL.GL_STATIC_DRAW);
+ {
+ interleavedVBORight.addGLSLSubArray("mgl_Vertex", 3, GL.GL_ARRAY_BUFFER);
+ interleavedVBORight.addGLSLSubArray("mgl_Color", 4, GL.GL_ARRAY_BUFFER);
+ interleavedVBORight.addGLSLSubArray("mgl_MultiTexCoord", 2, GL.GL_ARRAY_BUFFER);
+ }
+ updateInterleavedVBO(gl, interleavedVBOLeft, tex, 0);
+ updateInterleavedVBO(gl, interleavedVBORight, tex, 1);
+
+ st.ownAttribute(interleavedVBOLeft, true);
+ st.ownAttribute(interleavedVBORight, true);
+ gl.glClearColor(0.3f, 0.3f, 0.3f, 0.3f);
+
+ gl.glEnable(GL.GL_DEPTH_TEST);
+
+ st.useProgram(gl, false);
+
+ // Let's show the completed shader state ..
+ System.out.println("iVBOLeft : "+interleavedVBOLeft);
+ System.out.println("iVBORight: "+interleavedVBORight);
+ System.out.println(st);
+ }
+
+ mPlayer.play();
+ System.out.println("play.0 "+mPlayer);
+ startTime = System.currentTimeMillis();
+
+ final Object upstreamWidget = drawable.getUpstreamWidget();
+ if (upstreamWidget instanceof Window) {
+ final Window window = (Window) upstreamWidget;
+ window.addMouseListener(mouseAction);
+ window.addKeyListener(keyAction);
+ surfWidth = window.getSurfaceWidth();
+ surfHeight = window.getSurfaceHeight();
+ }
+ final int rmode = drawable.getChosenGLCapabilities().getSampleBuffers() ? 0 : Region.VBAA_RENDERING_BIT;
+ final boolean lowPerfDevice = gl.isGLES();
+ textRendererGLEL = new InfoTextRendererGLELBase(rmode, lowPerfDevice);
+ textRendererGLEL.init(drawable);
+ }
+
+ protected void updateInterleavedVBO(final GL gl, final GLArrayDataServer iVBO, final Texture tex, final int eyeNum) {
+ final boolean wasEnabled = iVBO.enabled();
+ iVBO.seal(gl, false);
+ iVBO.rewind();
+ {
+ final FloatBuffer ib = (FloatBuffer)iVBO.getBuffer();
+ final TextureCoords tc = tex.getImageTexCoords();
+ final float texHalfWidth = tc.right()/2f;
+ System.err.println("XXX0: "+tc+", texHalfWidth "+texHalfWidth);
+ System.err.println("XXX0: tex aspect: "+tex.getAspectRatio());
+ System.err.println("XXX0: tex y-flip: "+tex.getMustFlipVertically());
+
+ // left-bottom
+ ib.put(verts[0]); ib.put(verts[1]); ib.put(verts[2]);
+ ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha);
+ if( 0 == eyeNum ) {
+ ib.put( tc.left() ); ib.put( tc.bottom() );
+ } else {
+ ib.put( tc.left() + texHalfWidth ); ib.put( tc.bottom() );
+ }
+
+ // right-bottom
+ ib.put(verts[3]); ib.put(verts[1]); ib.put(verts[2]);
+ ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha);
+ if( 0 == eyeNum ) {
+ ib.put( texHalfWidth ); ib.put( tc.bottom() );
+ } else {
+ ib.put( tc.right() ); ib.put( tc.bottom() );
+ }
+
+ // left-top
+ ib.put(verts[0]); ib.put(verts[4]); ib.put(verts[2]);
+ ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha);
+ if( 0 == eyeNum ) {
+ ib.put( tc.left() ); ib.put( tc.top() );
+ } else {
+ ib.put( tc.left() + texHalfWidth ); ib.put( tc.top() );
+ }
+
+ // right-top
+ ib.put(verts[3]); ib.put(verts[4]); ib.put(verts[2]);
+ ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha);
+ if( 0 == eyeNum ) {
+ ib.put( texHalfWidth ); ib.put( tc.top() );
+ } else {
+ ib.put( tc.right() ); ib.put( tc.top() );
+ }
+ }
+ iVBO.seal(gl, true);
+ if( !wasEnabled ) {
+ iVBO.enableBuffer(gl, false);
+ }
+ }
+
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ surfWidth = width;
+ surfHeight = height;
+
+ if(null == mPlayer) { return; }
+
+ if(null != st) {
+ reshapePMV(width, height);
+ st.useProgram(gl, true);
+ st.uniform(gl, pmvMatrixUniform);
+ st.useProgram(gl, false);
+ }
+
+ System.out.println("pR "+mPlayer);
+ textRendererGLEL.reshape(drawable, x, y, width, height);
+ }
+
+ private final float zNear = 0.1f;
+ private final float zFar = 10000f;
+
+ private void reshapePMV(final int width, final int height) {
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrix.gluPerspective(45.0f, (float)width / (float)height, zNear, zFar);
+
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrix.glTranslatef(0, 0, zoom0);
+ }
+
+ private final float[] mat4Tmp1 = new float[16];
+ private final float[] mat4Tmp2 = new float[16];
+ private final float[] vec3Tmp1 = new float[3];
+ private final float[] vec3Tmp2 = new float[3];
+ private final float[] vec3Tmp3 = new float[3];
+
+ GLArrayDataServer interleavedVBOCurrent = null;
+
+ @Override
+ public void reshapeForEye(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height,
+ final EyeParameter eyeParam, final EyePose eyePose) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ interleavedVBOCurrent = 0 == eyeParam.number ? interleavedVBOLeft : interleavedVBORight;
+
+ surfWidth = drawable.getSurfaceWidth();
+ surfHeight = drawable.getSurfaceHeight();
+
+ if(null == mPlayer) { return; }
+ if(null == st) { return; }
+
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ final float[] mat4Projection = FloatUtil.makePerspective(mat4Tmp1, 0, true, eyeParam.fovhv, zNear, zFar);
+ pmvMatrix.glLoadMatrixf(mat4Projection, 0);
+
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ final Quaternion rollPitchYaw = new Quaternion();
+ final float[] shiftedEyePos = rollPitchYaw.rotateVector(vec3Tmp1, 0, eyePose.position, 0);
+ VectorUtil.addVec3(shiftedEyePos, shiftedEyePos, eyeParam.positionOffset);
+
+ rollPitchYaw.mult(eyePose.orientation);
+ final float[] up = rollPitchYaw.rotateVector(vec3Tmp2, 0, VectorUtil.VEC3_UNIT_Y, 0);
+ final float[] forward = rollPitchYaw.rotateVector(vec3Tmp3, 0, VectorUtil.VEC3_UNIT_Z_NEG, 0);
+ final float[] center = VectorUtil.addVec3(forward, shiftedEyePos, forward);
+
+ final float[] mLookAt = FloatUtil.makeLookAt(mat4Tmp1, 0, shiftedEyePos, 0, center, 0, up, 0, mat4Tmp2);
+ final float[] mViewAdjust = FloatUtil.makeTranslation(mat4Tmp2, true, eyeParam.distNoseToPupilX, eyeParam.distMiddleToPupilY, eyeParam.eyeReliefZ);
+ final float[] mat4Modelview = FloatUtil.multMatrix(mViewAdjust, mLookAt);
+ pmvMatrix.glLoadMatrixf(mat4Modelview, 0);
+ pmvMatrix.glTranslatef(0, 0, zoom0);
+ st.useProgram(gl, true);
+ st.uniform(gl, pmvMatrixUniform);
+ st.useProgram(gl, false);
+ textRendererGLEL.reshape(drawable, x, y, width, height);
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ textRendererGLEL.dispose(drawable);
+ textRendererGLEL = null;
+ disposeImpl(drawable, true);
+ }
+
+ private void disposeImpl(final GLAutoDrawable drawable, final boolean disposePlayer) {
+ if(null == mPlayer) { return; }
+
+ final Object upstreamWidget = drawable.getUpstreamWidget();
+ if (upstreamWidget instanceof Window) {
+ final Window window = (Window) upstreamWidget;
+ window.removeMouseListener(mouseAction);
+ window.removeKeyListener(keyAction);
+ }
+
+ System.out.println("pD.1 "+mPlayer+", disposePlayer "+disposePlayer);
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ if( disposePlayer ) {
+ mPlayer.destroy(gl);
+ System.out.println("pD.X "+mPlayer);
+ mPlayer=null;
+ }
+ pmvMatrixUniform = null;
+ if(null != pmvMatrix) {
+ pmvMatrix=null;
+ }
+ if(null != st) {
+ st.destroy(gl);
+ st=null;
+ }
+ }
+
+ long lastPerfPos = 0;
+
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ display(drawable, 0);
+ }
+
+ @Override
+ public void display(final GLAutoDrawable drawable, final int flags) {
+ // TODO Auto-generated method stub
+ final boolean repeatedFrame = 0 != ( CustomGLEventListener.DISPLAY_REPEAT & flags );
+ final boolean dontClear = 0 != ( CustomGLEventListener.DISPLAY_DONTCLEAR & flags );
+ final GLArrayDataServer iVBO = null != interleavedVBOCurrent ? interleavedVBOCurrent : interleavedVBOLeft;
+
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ if(null == mPlayer) { return; }
+
+ if( resetGLState ) {
+ resetGLState = false;
+ System.err.println("XXX resetGLState");
+ disposeImpl(drawable, false);
+ init(drawable);
+ reshape(drawable, 0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
+ }
+
+ final long currentPos = System.currentTimeMillis();
+ if( currentPos - lastPerfPos > 2000 ) {
+ System.err.println( mPlayer.getPerfString() );
+ lastPerfPos = currentPos;
+ }
+
+ if( !dontClear ) {
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ }
+
+ if(null == st) {
+ return;
+ }
+
+ st.useProgram(gl, true);
+
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmvMatrix.glPushMatrix();
+ pmvMatrix.glTranslatef(0, 0, zoom);
+ if(rotate > 0) {
+ final float ang = ((System.currentTimeMillis() - startTime) * 360.0f) / 8000.0f;
+ pmvMatrix.glRotatef(ang, 0, 0, 1);
+ } else {
+ rotate = 0;
+ }
+ st.uniform(gl, pmvMatrixUniform);
+ iVBO.enableBuffer(gl, true);
+ Texture tex = null;
+ if(null!=mPlayer) {
+ final TextureSequence.TextureFrame texFrame;
+ if( repeatedFrame ) {
+ texFrame=mPlayer.getLastTexture();
+ } else {
+ texFrame=mPlayer.getNextTexture(gl);
+ }
+ if(null != texFrame) {
+ tex = texFrame.getTexture();
+ gl.glActiveTexture(GL.GL_TEXTURE0+mPlayer.getTextureUnit());
+ tex.enable(gl);
+ tex.bind(gl);
+ }
+ }
+ gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
+ if(null != tex) {
+ tex.disable(gl);
+ }
+ iVBO.enableBuffer(gl, false);
+ st.useProgram(gl, false);
+ pmvMatrix.glPopMatrix();
+
+ textRendererGLEL.display(drawable);
+ }
+
+ static class StereoGLMediaEventListener implements GLMediaEventListener {
+ void destroyWindow(final Window window) {
+ new Thread() {
+ public void run() {
+ window.destroy();
+ } }.start();
+ }
+
+ @Override
+ public void newFrameAvailable(final GLMediaPlayer ts, final TextureFrame newFrame, final long when) {
+ }
+
+ @Override
+ public void attributesChanged(final GLMediaPlayer mp, final int event_mask, final long when) {
+ System.err.println("MovieSimple AttributesChanges: events_mask 0x"+Integer.toHexString(event_mask)+", when "+when);
+ System.err.println("MovieSimple State: "+mp);
+ final GLWindow window = (GLWindow) mp.getAttachedObject(WINDOW_KEY);
+ final MovieSBSStereo ms = (MovieSBSStereo)mp.getAttachedObject(PLAYER);
+ final StereoClientRenderer stereoClientRenderer = (StereoClientRenderer) mp.getAttachedObject(STEREO_RENDERER_KEY);
+
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_SIZE & event_mask ) ) {
+ System.err.println("MovieSimple State: CHANGE_SIZE");
+ // window.disposeGLEventListener(ms, false /* remove */ );
+ ms.resetGLState();
+ }
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_INIT & event_mask ) ) {
+ System.err.println("MovieSimple State: INIT");
+ // Use GLEventListener in all cases [A+V, V, A]
+ stereoClientRenderer.addGLEventListener(ms);
+ final GLAnimatorControl anim = window.getAnimator();
+ anim.setUpdateFPSFrames(60, null);
+ anim.resetFPSCounter();
+ ms.setStereoClientRenderer(stereoClientRenderer);
+ }
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_PLAY & event_mask ) ) {
+ window.getAnimator().resetFPSCounter();
+ }
+
+ boolean destroy = false;
+ Throwable err = null;
+
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_EOS & event_mask ) ) {
+ err = ms.mPlayer.getStreamException();
+ if( null != err ) {
+ System.err.println("MovieSimple State: EOS + Exception");
+ destroy = true;
+ } else {
+ System.err.println("MovieSimple State: EOS");
+ new Thread() {
+ public void run() {
+ mp.setPlaySpeed(1f);
+ mp.seek(0);
+ mp.play();
+ }
+ }.start();
+ }
+ }
+ if( 0 != ( GLMediaEventListener.EVENT_CHANGE_ERR & event_mask ) ) {
+ err = ms.mPlayer.getStreamException();
+ if( null != err ) {
+ System.err.println("MovieSimple State: ERR + Exception");
+ } else {
+ System.err.println("MovieSimple State: ERR");
+ }
+ destroy = true;
+ }
+ if( destroy ) {
+ if( null != err ) {
+ err.printStackTrace();
+ }
+ destroyWindow(window);
+ }
+ }
+ };
+ public final static StereoGLMediaEventListener stereoGLMediaEventListener = new StereoGLMediaEventListener();
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java
index 8760cd2c3..5918e4e6b 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java
@@ -90,8 +90,8 @@ public class MovieSimple implements GLEventListener {
public static final int EFFECT_GRADIENT_BOTTOM2TOP = 1<<1;
public static final int EFFECT_TRANSPARENT = 1<<3;
- private static final String WINDOW_KEY = "window";
- private static final String PLAYER = "player";
+ public static final String WINDOW_KEY = "window";
+ public static final String PLAYER = "player";
private static boolean waitForKey = false;
private int surfWidth, surfHeight;
@@ -682,6 +682,9 @@ public class MovieSimple implements GLEventListener {
System.out.println("pR "+mPlayer);
}
+ private final float zNear = 1f;
+ private final float zFar = 10f;
+
private void reshapePMV(final int width, final int height) {
pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
pmvMatrix.glLoadIdentity();
@@ -691,7 +694,7 @@ public class MovieSimple implements GLEventListener {
pmvMatrix.glOrthof(-fw, fw, -fh, fh, -1.0f, 1.0f);
nearPlaneNormalized = 0f;
} else {
- pmvMatrix.gluPerspective(45.0f, (float)width / (float)height, 1f, 10.0f);
+ pmvMatrix.gluPerspective(45.0f, (float)width / (float)height, zNear, zFar);
nearPlaneNormalized = 1f/(10f-1f);
}
System.err.println("XXX0: Perspective nearPlaneNormalized: "+nearPlaneNormalized);
@@ -786,7 +789,7 @@ public class MovieSimple implements GLEventListener {
Texture tex = null;
if(null!=mPlayer) {
final TextureSequence.TextureFrame texFrame;
- if(mPlayerShared) {
+ if( mPlayerShared ) {
texFrame=mPlayer.getLastTexture();
} else {
texFrame=mPlayer.getNextTexture(gl);
@@ -903,7 +906,7 @@ public class MovieSimple implements GLEventListener {
}
}
};
- final static MyGLMediaEventListener myGLMediaEventListener = new MyGLMediaEventListener();
+ public final static MyGLMediaEventListener myGLMediaEventListener = new MyGLMediaEventListener();
static boolean loopEOS = false;
static boolean origSize;
@@ -1068,4 +1071,5 @@ public class MovieSimple implements GLEventListener {
mss[i].initStream(streamLocN, vid, aid, textureCount);
}
}
+
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/stereo/StereoDemo01.java b/src/test/com/jogamp/opengl/test/junit/jogl/stereo/StereoDemo01.java
new file mode 100644
index 000000000..c4db20f37
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/stereo/StereoDemo01.java
@@ -0,0 +1,307 @@
+/**
+ * Copyright 2014 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.stereo;
+
+import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.PointImmutable;
+import javax.media.opengl.GL;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLProfile;
+
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.common.util.ReflectionUtil;
+import com.jogamp.newt.event.KeyAdapter;
+import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.math.FovHVHalves;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSBSStereo;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSimple;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.AnimatorBase;
+import com.jogamp.opengl.util.av.GLMediaPlayer;
+import com.jogamp.opengl.util.stereo.StereoDevice;
+import com.jogamp.opengl.util.stereo.StereoDeviceRenderer;
+import com.jogamp.opengl.util.stereo.StereoDeviceFactory;
+import com.jogamp.opengl.util.stereo.StereoClientRenderer;
+import com.jogamp.opengl.util.stereo.StereoGLEventListener;
+
+/**
+ * All distortions, no multisampling, bilinear filtering, manual-swap and using two FBOs (default, good)
+ * <pre>
+ * java StereoDemo01 -time 10000000
+ * </pre>
+ * All distortions, 8x multisampling, bilinear filtering, manual-swap and using two FBOs (best - slowest)
+ * <pre>
+ * java StereoDemo01 -time 10000000 -samples 8
+ * </pre>
+ * All distortions, 8x multisampling, bilinear filtering, manual-swap and using one a big single FBO (w/ all commandline params)
+ * <pre>
+ * java StereoDemo01 -time 10000000 -vignette true -chromatic true -timewarp false -samples 8 -biLinear true -autoSwap false -singleFBO true -mainScreen false
+ * </pre>
+ * No distortions, no multisampling, no filtering, auto-swap and using a big single FBO (worst and fastest)
+ * <pre>
+ * java StereoDemo01 -time 10000000 -vignette false -chromatic false -timewarp false -samples 0 -biLinear false -autoSwap true -singleFBO true
+ * </pre>
+ * Test on main screen:
+ * <pre>
+ * java StereoDemo01 -time 10000000 -mainScreen true
+ * </pre>
+ * Test a 3D SBS Movie:
+ * <pre>
+ * java StereoDemo01 -time 10000000 -filmFile Some_SBS_3D_Movie.mkv
+ * java StereoDemo01 -time 10000000 -filmURI http://whoknows.not/Some_SBS_3D_Movie.mkv
+ * </pre>
+ * <p>
+ * Key 'R' enables/disables the VR's sensors, i.e. head rotation ..
+ * </p>
+ *
+ */
+public class StereoDemo01 {
+ static long duration = 10000; // ms
+
+ static boolean useStereoScreen = true;
+
+ static int numSamples = 0;
+ static boolean biLinear = true;
+ static boolean useSingleFBO = false;
+ static boolean useVignette = true;
+ static boolean useChromatic = true;
+ static boolean useTimewarp = true;
+ static boolean useAutoSwap = false;
+ static String useFilmFile = null;
+ static String useFilmURI = null;
+ static String stereoRendererListenerName = null;
+
+ public static void main(final String args[]) throws InterruptedException, URISyntaxException {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-time")) {
+ i++;
+ duration = MiscUtils.atol(args[i], duration);
+ } else if(args[i].equals("-samples")) {
+ i++;
+ numSamples = MiscUtils.atoi(args[i], numSamples);
+ } else if(args[i].equals("-biLinear")) {
+ i++;
+ biLinear = MiscUtils.atob(args[i], biLinear);
+ } else if(args[i].equals("-singleFBO")) {
+ i++;
+ useSingleFBO = MiscUtils.atob(args[i], useSingleFBO);
+ } else if(args[i].equals("-vignette")) {
+ i++;
+ useVignette = MiscUtils.atob(args[i], useVignette);
+ } else if(args[i].equals("-chromatic")) {
+ i++;
+ useChromatic = MiscUtils.atob(args[i], useChromatic);
+ } else if(args[i].equals("-timewarp")) {
+ i++;
+ useTimewarp = MiscUtils.atob(args[i], useTimewarp);
+ } else if(args[i].equals("-vignette")) {
+ i++;
+ useVignette = MiscUtils.atob(args[i], useVignette);
+ } else if(args[i].equals("-mainScreen")) {
+ i++;
+ useStereoScreen = !MiscUtils.atob(args[i], useStereoScreen);
+ } else if(args[i].equals("-autoSwap")) {
+ i++;
+ useAutoSwap = MiscUtils.atob(args[i], useAutoSwap);
+ } else if(args[i].equals("-test")) {
+ i++;
+ stereoRendererListenerName = args[i];
+ } else if(args[i].equals("-filmFile")) {
+ i++;
+ useFilmFile = args[i];
+ } else if(args[i].equals("-filmURI")) {
+ i++;
+ useFilmURI = args[i];
+ }
+ }
+ if( null != stereoRendererListenerName ) {
+ try {
+ final Object stereoRendererListener = ReflectionUtil.createInstance(stereoRendererListenerName, null);
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+ }
+ final StereoGLEventListener upstream;
+ final MovieSBSStereo movieSimple;
+ final URI movieURI;
+ if( null != useFilmFile ) {
+ movieSimple = new MovieSBSStereo();
+ movieURI = IOUtil.toURISimple(new File(useFilmFile));
+ upstream = movieSimple;
+ } else if( null != useFilmURI ) {
+ movieSimple = new MovieSBSStereo();
+ movieURI = new URI(useFilmURI);
+ upstream = movieSimple;
+ } else {
+ final GearsES2 demo = new GearsES2(0);
+ demo.setVerbose(false);
+ upstream = demo;
+ movieSimple = null;
+ movieURI = null;
+ }
+ final StereoDemo01 demo01 = new StereoDemo01();
+ demo01.doIt(0, upstream, movieSimple, movieURI, biLinear, numSamples, useSingleFBO, useVignette, useChromatic, useTimewarp,
+ useAutoSwap, true /* useAnimator */, false /* exclusiveContext*/);
+ }
+
+ public void doIt(final int stereoDeviceIndex,
+ final StereoGLEventListener upstream, final MovieSBSStereo movieSimple, final URI movieURI,
+ final boolean biLinear, final int numSamples, final boolean useSingleFBO,
+ final boolean useVignette, final boolean useChromatic, final boolean useTimewarp,
+ final boolean useAutoSwap, final boolean useAnimator, final boolean exclusiveContext) throws InterruptedException {
+
+ System.err.println("glob duration "+duration);
+ System.err.println("glob useStereoScreen "+useStereoScreen);
+ System.err.println("biLinear "+biLinear);
+ System.err.println("numSamples "+numSamples);
+ System.err.println("useSingleFBO "+useSingleFBO);
+ System.err.println("useVignette "+useVignette);
+ System.err.println("useChromatic "+useChromatic);
+ System.err.println("useTimewarp "+useTimewarp);
+ System.err.println("useAutoSwap "+useAutoSwap);
+
+ final StereoDeviceFactory stereoDeviceFactory = StereoDeviceFactory.createDefaultFactory();
+ if( null == stereoDeviceFactory ) {
+ System.err.println("No StereoDeviceFactory available");
+ return;
+ }
+
+ final StereoDevice stereoDevice = stereoDeviceFactory.createDevice(stereoDeviceIndex, true /* verbose */);
+ if( null == stereoDevice ) {
+ System.err.println("No StereoDevice.Context available for index "+stereoDeviceIndex);
+ return;
+ }
+
+ // Start the sensor which provides the Rift’s pose and motion.
+ if( !stereoDevice.startSensors(true) ) {
+ System.err.println("Could not start sensors on device "+stereoDeviceIndex);
+ }
+
+ //
+ //
+ //
+ final GLCapabilities caps = new GLCapabilities(GLProfile.getMaxProgrammable(true /* favorHardwareRasterizer */));
+ final GLWindow window = GLWindow.create(caps);
+
+ final PointImmutable devicePos = stereoDevice.getPosition();
+ final DimensionImmutable deviceRes = stereoDevice.getSurfaceSize();
+ window.setSize(deviceRes.getWidth(), deviceRes.getHeight());
+ if( useStereoScreen ) {
+ window.setPosition(devicePos.getX(), devicePos.getY());
+ }
+ window.setAutoSwapBufferMode(useAutoSwap);
+ window.setUndecorated(true);
+
+ final Animator animator = useAnimator ? new Animator() : null;
+ if( useAnimator ) {
+ animator.setModeBits(false, AnimatorBase.MODE_EXPECT_AWT_RENDERING_THREAD);
+ animator.setExclusiveContext(exclusiveContext);
+ }
+
+ //
+ // Oculus Rift setup
+ //
+ // EyePos.y = ovrHmd_GetFloat(HMD, OVR_KEY_EYE_HEIGHT, EyePos.y);
+ final FovHVHalves[] defaultEyeFov = stereoDevice.getDefaultFOV();
+ System.err.println("Default Fov[0]: "+defaultEyeFov[0]);
+ System.err.println("Default Fov[1]: "+defaultEyeFov[1]);
+
+ final float[] eyePositionOffset = null == movieSimple ? StereoDevice.DEFAULT_EYE_POSITION_OFFSET // default
+ : new float[] { 0f, 0.3f, 0f }; // better fixed movie position
+ final int textureUnit = 0;
+ final int distortionBits = ( useVignette ? StereoDeviceRenderer.DISTORTION_VIGNETTE : 0 ) |
+ ( useChromatic ? StereoDeviceRenderer.DISTORTION_CHROMATIC : 0 ) |
+ ( useTimewarp ? StereoDeviceRenderer.DISTORTION_TIMEWARP : 0 );
+ final float pixelsPerDisplayPixel = 1f;
+ final StereoDeviceRenderer stereoDeviceRenderer =
+ stereoDevice.createRenderer(distortionBits, useSingleFBO ? 1 : 2, eyePositionOffset,
+ defaultEyeFov, pixelsPerDisplayPixel, textureUnit);
+ System.err.println("StereoDeviceRenderer: "+stereoDeviceRenderer);
+
+ final int texFilter = biLinear ? GL.GL_LINEAR : GL.GL_NEAREST;
+ final StereoClientRenderer renderer = new StereoClientRenderer(stereoDeviceRenderer, true /* ownsDist */, texFilter, texFilter, numSamples);
+ if( null != movieSimple && null != movieURI) {
+ movieSimple.setScaleOrig(true);
+ final GLMediaPlayer mp = movieSimple.getGLMediaPlayer();
+ mp.attachObject(MovieSimple.WINDOW_KEY, window);
+ mp.attachObject(MovieSBSStereo.STEREO_RENDERER_KEY, renderer);
+ mp.addEventListener(MovieSBSStereo.stereoGLMediaEventListener);
+ movieSimple.initStream(movieURI, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, 3);
+ } else {
+ renderer.addGLEventListener(upstream);
+ }
+ window.addGLEventListener(renderer);
+
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ window.addKeyListener(quitAdapter);
+ window.addWindowListener(quitAdapter);
+
+ window.addKeyListener(new KeyAdapter() {
+ public void keyReleased(final KeyEvent e) {
+ if( e.isAutoRepeat() ) {
+ return;
+ }
+ switch(e.getKeySymbol()) {
+ case KeyEvent.VK_R: {
+ stereoDevice.startSensors(!stereoDevice.getSensorsStarted());
+ break;
+ }
+ }
+ } } );
+
+ if( useAnimator ) {
+ animator.add(window);
+ animator.start();
+ }
+ window.setVisible(true);
+ if( useAnimator ) {
+ animator.setUpdateFPSFrames(60, System.err);
+ }
+
+ final long t0 = System.currentTimeMillis();
+ long t1 = t0;
+ while(!quitAdapter.shouldQuit() && t1-t0<duration) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ if( useAnimator ) {
+ animator.stop();
+ }
+ window.destroy();
+ stereoDevice.dispose();
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/stereo/ovr/OVRDemo01.java b/src/test/com/jogamp/opengl/test/junit/jogl/stereo/ovr/OVRDemo01.java
deleted file mode 100644
index 1cc07ec22..000000000
--- a/src/test/com/jogamp/opengl/test/junit/jogl/stereo/ovr/OVRDemo01.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/**
- * Copyright 2014 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.stereo.ovr;
-
-import javax.media.opengl.GL;
-import javax.media.opengl.GLCapabilities;
-import javax.media.opengl.GLEventListener;
-import javax.media.opengl.GLProfile;
-
-import jogamp.opengl.oculusvr.OVRDistortion;
-
-import com.jogamp.newt.opengl.GLWindow;
-import com.jogamp.oculusvr.OVR;
-import com.jogamp.oculusvr.OVRException;
-import com.jogamp.oculusvr.OVRVersion;
-import com.jogamp.oculusvr.OvrHmdContext;
-import com.jogamp.oculusvr.ovrFovPort;
-import com.jogamp.oculusvr.ovrHmdDesc;
-import com.jogamp.oculusvr.ovrSizei;
-import com.jogamp.oculusvr.ovrVector2i;
-import com.jogamp.opengl.oculusvr.OVRSBSRendererDualFBO;
-import com.jogamp.opengl.oculusvr.OVRSBSRendererSingleFBO;
-import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
-import com.jogamp.opengl.test.junit.util.MiscUtils;
-import com.jogamp.opengl.test.junit.util.QuitAdapter;
-import com.jogamp.opengl.util.Animator;
-import com.jogamp.opengl.util.AnimatorBase;
-
-/**
- * All distortions, no multisampling, bilinear filtering, manual-swap and using two FBOs (default, good)
- * <pre>
- * java OVRDemo01 -time 10000000
- * </pre>
- * All distortions, 8x multisampling, bilinear filtering, manual-swap and using two FBOs (best - slowest)
- * <pre>
- * java OVRDemo01 -time 10000000 -samples 8
- * </pre>
- * All distortions, 8x multisampling, bilinear filtering, manual-swap and using one a big single FBO (w/ all commandline params)
- * <pre>
- * java OVRDemo01 -time 10000000 -vignette true -chromatic true -timewarp false -samples 8 -biLinear true -autoSwap false -singleFBO true -mainScreen false
- * </pre>
- * No distortions, no multisampling, no filtering, auto-swap and using a big single FBO (worst and fastest)
- * <pre>
- * java OVRDemo01 -time 10000000 -vignette false -chromatic false -timewarp false -samples 0 -biLinear false -autoSwap true -singleFBO true
- * </pre>
- * Test on main screen:
- * <pre>
- * java OVRDemo01 -time 10000000 -mainScreen true
- * </pre>
- *
- */
-public class OVRDemo01 {
- static long duration = 10000; // ms
-
- static boolean useOVRScreen = true;
-
- static int numSamples = 0;
- static boolean biLinear = true;
- static boolean useSingleFBO = false;
- static boolean useVignette = true;
- static boolean useChromatic = true;
- static boolean useTimewarp = true;
- static boolean useAutoSwap = false;
-
- public static void main(final String args[]) throws InterruptedException {
- for(int i=0; i<args.length; i++) {
- if(args[i].equals("-time")) {
- i++;
- duration = MiscUtils.atol(args[i], duration);
- } else if(args[i].equals("-samples")) {
- i++;
- numSamples = MiscUtils.atoi(args[i], numSamples);
- } else if(args[i].equals("-biLinear")) {
- i++;
- biLinear = MiscUtils.atob(args[i], biLinear);
- } else if(args[i].equals("-singleFBO")) {
- i++;
- useSingleFBO = MiscUtils.atob(args[i], useSingleFBO);
- } else if(args[i].equals("-vignette")) {
- i++;
- useVignette = MiscUtils.atob(args[i], useVignette);
- } else if(args[i].equals("-chromatic")) {
- i++;
- useChromatic = MiscUtils.atob(args[i], useChromatic);
- } else if(args[i].equals("-timewarp")) {
- i++;
- useTimewarp = MiscUtils.atob(args[i], useTimewarp);
- } else if(args[i].equals("-vignette")) {
- i++;
- useVignette = MiscUtils.atob(args[i], useVignette);
- } else if(args[i].equals("-mainScreen")) {
- i++;
- useOVRScreen = !MiscUtils.atob(args[i], useOVRScreen);
- } else if(args[i].equals("-autoSwap")) {
- i++;
- useAutoSwap = MiscUtils.atob(args[i], useAutoSwap);
- }
- }
- final OVRDemo01 demo01 = new OVRDemo01();
- demo01.doIt(0, biLinear, numSamples, useSingleFBO, useVignette, useChromatic, useTimewarp,
- useAutoSwap, true /* useAnimator */, false /* exclusiveContext*/);
- }
-
- public void doIt(final int ovrHmdIndex, final boolean biLinear, final int numSamples,
- final boolean useSingleFBO,
- final boolean useVignette, final boolean useChromatic, final boolean useTimewarp,
- final boolean useAutoSwap,
- final boolean useAnimator, final boolean exclusiveContext) throws InterruptedException {
-
- System.err.println("glob duration "+duration);
- System.err.println("glob useOVRScreen "+useOVRScreen);
- System.err.println("biLinear "+biLinear);
- System.err.println("numSamples "+numSamples);
- System.err.println("useSingleFBO "+useSingleFBO);
- System.err.println("useVignette "+useVignette);
- System.err.println("useChromatic "+useChromatic);
- System.err.println("useTimewarp "+useTimewarp);
- System.err.println("useAutoSwap "+useAutoSwap);
-
- // Initialize LibOVR...
- if( !OVR.ovr_Initialize() ) { // recursive ..
- throw new OVRException("OVR not available");
- }
- final OvrHmdContext hmdCtx = OVR.ovrHmd_Create(ovrHmdIndex);
- if( null == hmdCtx ) {
- throw new OVRException("OVR HMD #"+ovrHmdIndex+" not available");
- }
- final ovrHmdDesc hmdDesc = ovrHmdDesc.create();
- OVR.ovrHmd_GetDesc(hmdCtx, hmdDesc);
- System.err.println(OVRVersion.getAvailableCapabilitiesInfo(hmdDesc, ovrHmdIndex, null).toString());
-
- // Start the sensor which provides the Rift’s pose and motion.
- final int requiredSensorCaps = 0;
- final int supportedSensorCaps = requiredSensorCaps | OVR.ovrSensorCap_Orientation | OVR.ovrSensorCap_YawCorrection | OVR.ovrSensorCap_Position;
- if( !OVR.ovrHmd_StartSensor(hmdCtx, supportedSensorCaps, requiredSensorCaps) ) {
- throw new OVRException("OVR HMD #"+ovrHmdIndex+" required sensors not available");
- }
-
- //
- //
- //
-
- final GLCapabilities caps = new GLCapabilities(GLProfile.getMaxProgrammable(true /* favorHardwareRasterizer */));
- final GLWindow window = GLWindow.create(caps);
- final ovrVector2i ovrPos = hmdDesc.getWindowsPos();
- final ovrSizei ovrRes = hmdDesc.getResolution();
- window.setSize(ovrRes.getW(), ovrRes.getH());
- if( useOVRScreen ) {
- window.setPosition(ovrPos.getX(), ovrPos.getY());
- }
- window.setAutoSwapBufferMode(useAutoSwap);
- window.setUndecorated(true);
-
- final Animator animator = useAnimator ? new Animator() : null;
- if( useAnimator ) {
- animator.setModeBits(false, AnimatorBase.MODE_EXPECT_AWT_RENDERING_THREAD);
- animator.setExclusiveContext(exclusiveContext);
- }
-
- //
- // Oculus Rift setup
- //
- final float[] eyePositionOffset = { 0.0f, 1.6f, -5.0f };
- // EyePos.y = ovrHmd_GetFloat(HMD, OVR_KEY_EYE_HEIGHT, EyePos.y);
-
- final ovrFovPort[] defaultEyeFov = hmdDesc.getDefaultEyeFov(0, new ovrFovPort[2]);
- final int distortionCaps = ( useVignette ? OVR.ovrDistortionCap_Vignette : 0 ) |
- ( useChromatic ? OVR.ovrDistortionCap_Chromatic : 0 ) |
- ( useTimewarp ? OVR.ovrDistortionCap_TimeWarp : 0 );
- final float pixelsPerDisplayPixel = 1f;
- final OVRDistortion dist = OVRDistortion.create(hmdCtx, useSingleFBO, eyePositionOffset, defaultEyeFov, pixelsPerDisplayPixel, distortionCaps);
- System.err.println("OVRDistortion: "+dist);
-
- final int texFilter = biLinear ? GL.GL_LINEAR : GL.GL_NEAREST;
- final GearsES2 upstream = new GearsES2(0);
- upstream.setVerbose(false);
- final GLEventListener renderer;
- if( useSingleFBO ) {
- renderer = new OVRSBSRendererSingleFBO(dist, true /* ownsDist */, upstream, texFilter, texFilter, numSamples);
- } else {
- renderer = new OVRSBSRendererDualFBO(dist, true /* ownsDist */, upstream, texFilter, texFilter, numSamples);
- }
- window.addGLEventListener(renderer);
-
- final QuitAdapter quitAdapter = new QuitAdapter();
- window.addKeyListener(quitAdapter);
- window.addWindowListener(quitAdapter);
-
- if( useAnimator ) {
- animator.add(window);
- animator.start();
- }
- window.setVisible(true);
- if( useAnimator ) {
- animator.setUpdateFPSFrames(60, System.err);
- }
-
- final long t0 = System.currentTimeMillis();
- long t1 = t0;
- while(!quitAdapter.shouldQuit() && t1-t0<duration) {
- Thread.sleep(100);
- t1 = System.currentTimeMillis();
- }
-
- if( useAnimator ) {
- animator.stop();
- }
- window.destroy();
- // OVR.ovr_Shutdown();
- }
-}