From d27baa9f6980d6e2b570999607b003a11393ea95 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Sat, 11 Mar 2023 07:08:56 +0100 Subject: Cleanup Demos: Move demos to jogl-demos.jar (here Graph + AudioVideo), ready for easy deployment and test w/ junit/ant --- src/demos/com/jogamp/opengl/demos/Launcher0.java | 1 + src/demos/com/jogamp/opengl/demos/MiscUtils.java | 259 ----- .../jogamp/opengl/demos/android/LauncherUtil.java | 430 ++++++++ .../opengl/demos/android/MovieCubeActivity0a.java | 166 +++ .../opengl/demos/android/MovieCubeActivity0b.java | 168 +++ .../demos/android/MovieCubeActivityLauncher0a.java | 87 ++ .../demos/android/MovieCubeActivityLauncher0b.java | 87 ++ .../demos/android/MovieCubeActivityLauncher1a.java | 87 ++ .../demos/android/MovieCubeActivityLauncher1b.java | 87 ++ .../opengl/demos/android/MovieSimpleActivity0.java | 159 +++ .../opengl/demos/android/MovieSimpleActivity1.java | 262 +++++ .../android/MovieSimpleActivityLauncher00b.java | 84 ++ .../android/MovieSimpleActivityLauncher00c.java | 84 ++ .../android/MovieSimpleActivityLauncher01a.java | 87 ++ .../android/MovieSimpleActivityLauncher01b.java | 87 ++ .../android/MovieSimpleActivityLauncher02.java | 87 ++ .../opengl/demos/android/NEWTGearsES2Activity.java | 134 +++ .../android/NEWTGearsES2ActivityLauncher.java | 84 ++ .../android/NEWTGearsES2ECTActivityLauncher.java | 80 ++ .../NEWTGearsES2RGB565ActivityLauncher.java | 80 ++ .../demos/android/NEWTGearsES2TransActivity.java | 88 ++ .../android/NEWTGearsES2TransActivityLauncher.java | 58 + .../demos/android/NEWTGraphUI1pActivity.java | 80 ++ .../android/NEWTGraphUI1pActivityLauncher.java | 52 + .../demos/android/NEWTGraphUI2pActivity.java | 79 ++ .../android/NEWTGraphUI2pActivityLauncher.java | 52 + .../demos/android/NEWTRedSquareES2Activity.java | 99 ++ .../android/NEWTRedSquareES2ActivityLauncher.java | 21 + .../jogamp/opengl/demos/av/CrossFadePlayer.java | 212 ++++ .../com/jogamp/opengl/demos/av/MovieCube.java | 655 ++++++++++++ .../com/jogamp/opengl/demos/av/MovieSBSStereo.java | 887 ++++++++++++++++ .../com/jogamp/opengl/demos/av/MovieSimple.java | 1123 ++++++++++++++++++++ .../com/jogamp/opengl/demos/av/StereoDemo01.java | 403 +++++++ .../com/jogamp/opengl/demos/es2/GearsES2.java | 3 +- .../jogamp/opengl/demos/es2/GearsObjectES2.java | 4 +- .../opengl/demos/es2/TextureSequenceCubeES2.java | 491 +++++++++ .../jogamp/opengl/demos/graph/FontSetDemos.java | 35 + .../opengl/demos/graph/GPURegionGLListener00.java | 134 +++ .../opengl/demos/graph/GPURegionGLListener01.java | 299 ++++++ .../opengl/demos/graph/GPURegionGLListener10.java | 138 +++ .../opengl/demos/graph/GPURegionNewtDemo.java | 162 +++ .../demos/graph/GPURendererListenerBase01.java | 361 +++++++ .../opengl/demos/graph/GPUTextGLListener0A.java | 72 ++ .../jogamp/opengl/demos/graph/GPUTextNewtDemo.java | 193 ++++ .../demos/graph/GPUTextRendererListenerBase01.java | 588 ++++++++++ .../com/jogamp/opengl/demos/graph/MSAATool.java | 96 ++ .../opengl/demos/graph/TextRendererGLELBase.java | 291 +++++ .../opengl/demos/graph/fonts/freefont/FreeMono.ttf | Bin 0 -> 592632 bytes .../demos/graph/fonts/freefont/FreeMonoBold.ttf | Bin 0 -> 299136 bytes .../graph/fonts/freefont/FreeMonoBoldOblique.ttf | Bin 0 -> 298940 bytes .../demos/graph/fonts/freefont/FreeMonoOblique.ttf | Bin 0 -> 395188 bytes .../opengl/demos/graph/fonts/freefont/FreeSans.ttf | Bin 0 -> 1563256 bytes .../demos/graph/fonts/freefont/FreeSansBold.ttf | Bin 0 -> 416128 bytes .../graph/fonts/freefont/FreeSansBoldOblique.ttf | Bin 0 -> 342492 bytes .../demos/graph/fonts/freefont/FreeSansOblique.ttf | Bin 0 -> 763676 bytes .../demos/graph/fonts/freefont/FreeSerif.ttf | Bin 0 -> 3303588 bytes .../demos/graph/fonts/freefont/FreeSerifBold.ttf | Bin 0 -> 1310828 bytes .../graph/fonts/freefont/FreeSerifBoldItalic.ttf | Bin 0 -> 608676 bytes .../demos/graph/fonts/freefont/FreeSerifItalic.ttf | Bin 0 -> 922104 bytes .../demos/graph/ui/GPUUISceneGLListener0A.java | 973 +++++++++++++++++ .../opengl/demos/graph/ui/GPUUISceneNewtDemo.java | 201 ++++ .../demos/graph/ui/GPUUISceneTextAnim01.java | 351 ++++++ .../opengl/demos/graph/ui/UIShapeDemo01.java | 569 ++++++++++ .../jogamp/opengl/demos/graph/ui/UITypeDemo01.java | 617 +++++++++++ .../demos/graph/ui/button-pressed-145x53.png | Bin 0 -> 8603 bytes .../demos/graph/ui/button-released-145x53.png | Bin 0 -> 9429 bytes .../graph/ui/testshapes/Glyph01UbuntuLight_o.java | 316 ++++++ .../graph/ui/testshapes/Glyph02UbuntuLight_ae.java | 652 ++++++++++++ .../ui/testshapes/Glyph03FreeMonoRegular_M.java | 804 ++++++++++++++ .../graph/ui/testshapes/Glyph04FreeSans_0.java | 150 +++ .../testshapes/Glyph05FreeSerifBoldItalic_ae.java | 287 +++++ .../com/jogamp/opengl/demos/util/MiscUtils.java | 259 +++++ .../com/jogamp/opengl/demos/util/QuitAdapter.java | 64 ++ 73 files changed, 14255 insertions(+), 264 deletions(-) delete mode 100644 src/demos/com/jogamp/opengl/demos/MiscUtils.java create mode 100644 src/demos/com/jogamp/opengl/demos/android/LauncherUtil.java create mode 100644 src/demos/com/jogamp/opengl/demos/android/MovieCubeActivity0a.java create mode 100644 src/demos/com/jogamp/opengl/demos/android/MovieCubeActivity0b.java create mode 100644 src/demos/com/jogamp/opengl/demos/android/MovieCubeActivityLauncher0a.java create mode 100644 src/demos/com/jogamp/opengl/demos/android/MovieCubeActivityLauncher0b.java create mode 100644 src/demos/com/jogamp/opengl/demos/android/MovieCubeActivityLauncher1a.java create mode 100644 src/demos/com/jogamp/opengl/demos/android/MovieCubeActivityLauncher1b.java create mode 100644 src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivity0.java create mode 100644 src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivity1.java create mode 100644 src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivityLauncher00b.java create mode 100644 src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivityLauncher00c.java create mode 100644 src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivityLauncher01a.java create mode 100644 src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivityLauncher01b.java create mode 100644 src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivityLauncher02.java create mode 100644 src/demos/com/jogamp/opengl/demos/android/NEWTGearsES2Activity.java create mode 100644 src/demos/com/jogamp/opengl/demos/android/NEWTGearsES2ActivityLauncher.java create mode 100644 src/demos/com/jogamp/opengl/demos/android/NEWTGearsES2ECTActivityLauncher.java create mode 100644 src/demos/com/jogamp/opengl/demos/android/NEWTGearsES2RGB565ActivityLauncher.java create mode 100644 src/demos/com/jogamp/opengl/demos/android/NEWTGearsES2TransActivity.java create mode 100644 src/demos/com/jogamp/opengl/demos/android/NEWTGearsES2TransActivityLauncher.java create mode 100644 src/demos/com/jogamp/opengl/demos/android/NEWTGraphUI1pActivity.java create mode 100644 src/demos/com/jogamp/opengl/demos/android/NEWTGraphUI1pActivityLauncher.java create mode 100644 src/demos/com/jogamp/opengl/demos/android/NEWTGraphUI2pActivity.java create mode 100644 src/demos/com/jogamp/opengl/demos/android/NEWTGraphUI2pActivityLauncher.java create mode 100644 src/demos/com/jogamp/opengl/demos/android/NEWTRedSquareES2Activity.java create mode 100644 src/demos/com/jogamp/opengl/demos/android/NEWTRedSquareES2ActivityLauncher.java create mode 100644 src/demos/com/jogamp/opengl/demos/av/CrossFadePlayer.java create mode 100644 src/demos/com/jogamp/opengl/demos/av/MovieCube.java create mode 100644 src/demos/com/jogamp/opengl/demos/av/MovieSBSStereo.java create mode 100644 src/demos/com/jogamp/opengl/demos/av/MovieSimple.java create mode 100644 src/demos/com/jogamp/opengl/demos/av/StereoDemo01.java create mode 100644 src/demos/com/jogamp/opengl/demos/es2/TextureSequenceCubeES2.java create mode 100644 src/demos/com/jogamp/opengl/demos/graph/FontSetDemos.java create mode 100644 src/demos/com/jogamp/opengl/demos/graph/GPURegionGLListener00.java create mode 100644 src/demos/com/jogamp/opengl/demos/graph/GPURegionGLListener01.java create mode 100644 src/demos/com/jogamp/opengl/demos/graph/GPURegionGLListener10.java create mode 100644 src/demos/com/jogamp/opengl/demos/graph/GPURegionNewtDemo.java create mode 100644 src/demos/com/jogamp/opengl/demos/graph/GPURendererListenerBase01.java create mode 100644 src/demos/com/jogamp/opengl/demos/graph/GPUTextGLListener0A.java create mode 100644 src/demos/com/jogamp/opengl/demos/graph/GPUTextNewtDemo.java create mode 100644 src/demos/com/jogamp/opengl/demos/graph/GPUTextRendererListenerBase01.java create mode 100644 src/demos/com/jogamp/opengl/demos/graph/MSAATool.java create mode 100644 src/demos/com/jogamp/opengl/demos/graph/TextRendererGLELBase.java create mode 100644 src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeMono.ttf create mode 100644 src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeMonoBold.ttf create mode 100644 src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeMonoBoldOblique.ttf create mode 100644 src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeMonoOblique.ttf create mode 100644 src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeSans.ttf create mode 100644 src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeSansBold.ttf create mode 100644 src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeSansBoldOblique.ttf create mode 100644 src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeSansOblique.ttf create mode 100644 src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeSerif.ttf create mode 100644 src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeSerifBold.ttf create mode 100644 src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeSerifBoldItalic.ttf create mode 100644 src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeSerifItalic.ttf create mode 100644 src/demos/com/jogamp/opengl/demos/graph/ui/GPUUISceneGLListener0A.java create mode 100644 src/demos/com/jogamp/opengl/demos/graph/ui/GPUUISceneNewtDemo.java create mode 100644 src/demos/com/jogamp/opengl/demos/graph/ui/GPUUISceneTextAnim01.java create mode 100644 src/demos/com/jogamp/opengl/demos/graph/ui/UIShapeDemo01.java create mode 100644 src/demos/com/jogamp/opengl/demos/graph/ui/UITypeDemo01.java create mode 100644 src/demos/com/jogamp/opengl/demos/graph/ui/button-pressed-145x53.png create mode 100644 src/demos/com/jogamp/opengl/demos/graph/ui/button-released-145x53.png create mode 100644 src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph01UbuntuLight_o.java create mode 100644 src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph02UbuntuLight_ae.java create mode 100644 src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph03FreeMonoRegular_M.java create mode 100644 src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph04FreeSans_0.java create mode 100644 src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph05FreeSerifBoldItalic_ae.java create mode 100644 src/demos/com/jogamp/opengl/demos/util/MiscUtils.java create mode 100644 src/demos/com/jogamp/opengl/demos/util/QuitAdapter.java (limited to 'src/demos/com/jogamp/opengl') diff --git a/src/demos/com/jogamp/opengl/demos/Launcher0.java b/src/demos/com/jogamp/opengl/demos/Launcher0.java index 9f2e0d64e..d9d66d434 100644 --- a/src/demos/com/jogamp/opengl/demos/Launcher0.java +++ b/src/demos/com/jogamp/opengl/demos/Launcher0.java @@ -56,6 +56,7 @@ import com.jogamp.opengl.GLEventListener; import com.jogamp.opengl.GLPipelineFactory; import com.jogamp.opengl.GLProfile; import com.jogamp.opengl.demos.es2.RedSquareES2; +import com.jogamp.opengl.demos.util.MiscUtils; /** *

diff --git a/src/demos/com/jogamp/opengl/demos/MiscUtils.java b/src/demos/com/jogamp/opengl/demos/MiscUtils.java deleted file mode 100644 index 304e4f18a..000000000 --- a/src/demos/com/jogamp/opengl/demos/MiscUtils.java +++ /dev/null @@ -1,259 +0,0 @@ -/** - * Copyright 2010 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.demos; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.lang.reflect.*; -import java.nio.FloatBuffer; -import java.util.Iterator; -import java.util.List; - -import com.jogamp.opengl.GLContext; - -import com.jogamp.common.os.Platform; -import com.jogamp.common.util.InterruptSource; - -public class MiscUtils { - public static boolean atob(final String str, final boolean def) { - try { - return Boolean.parseBoolean(str); - } catch (final Exception ex) { - ex.printStackTrace(); - } - return def; - } - - public static int atoi(final String str, final int def) { - try { - return Integer.parseInt(str); - } catch (final Exception ex) { - ex.printStackTrace(); - } - return def; - } - - public static long atol(final String str, final long def) { - try { - return Long.parseLong(str); - } catch (final Exception ex) { - ex.printStackTrace(); - } - return def; - } - - public static float atof(final String str, final float def) { - try { - return Float.parseFloat(str); - } catch (final Exception ex) { - ex.printStackTrace(); - } - return def; - } - - public static String toHexString(final byte hex) { - return "0x" + Integer.toHexString( hex & 0x000000FF ); - } - - public static String toHexString(final short hex) { - return "0x" + Integer.toHexString( hex & 0x0000FFFF ); - } - - public static String toHexString(final int hex) { - return "0x" + Integer.toHexString( hex ); - } - - public static String toHexString(final long hex) { - return "0x" + Long.toHexString( hex ); - } - - public static void assertFloatBufferEquals(final String errmsg, final FloatBuffer expected, final FloatBuffer actual, final float delta) { - if(null == expected && null == actual) { - return; - } - final String msg = null != errmsg ? errmsg + " " : ""; - if(null == expected) { - throw new AssertionError(msg+"; Expected is null, but actual not: "+actual); - } - if(null == actual) { - throw new AssertionError(msg+"; Actual is null, but expected not: "+expected); - } - if(expected.remaining() != actual.remaining()) { - throw new AssertionError(msg+"; Expected has "+expected.remaining()+" remaining, but actual has "+actual.remaining()); - } - final int a0 = expected.position(); - final int b0 = actual.position(); - for(int i=0; i delta ) { - throw new AssertionError(msg+"; Expected @ ["+a0+"+"+i+"] has "+ai+", but actual @ ["+b0+"+"+i+"] has "+bi+", it's delta "+daibi+" > "+delta); - } - } - } - - public static void assertFloatBufferNotEqual(final String errmsg, final FloatBuffer expected, final FloatBuffer actual, final float delta) { - if(null == expected || null == actual) { - return; - } - if(expected.remaining() != actual.remaining()) { - return; - } - final String msg = null != errmsg ? errmsg + " " : ""; - final int a0 = expected.position(); - final int b0 = actual.position(); - for(int i=0; i delta ) { - return; - } - } - throw new AssertionError(msg+"; Expected and actual are equal."); - } - - public static boolean setFieldIfExists(final Object instance, final String fieldName, final Object value) { - try { - final Field f = instance.getClass().getField(fieldName); - if(value instanceof Boolean || f.getType().isInstance(value)) { - f.set(instance, value); - return true; - } else { - System.out.println(instance.getClass()+" '"+fieldName+"' field not assignable with "+value.getClass()+", it's a: "+f.getType()); - } - } catch (final IllegalAccessException ex) { - throw new RuntimeException(ex); - } catch (final NoSuchFieldException nsfe) { - // OK - throw new RuntimeException(instance.getClass()+" has no '"+fieldName+"' field", nsfe); - } - return false; - } - - public static void waitForKey(final String preMessage) { - final BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); - System.err.println(preMessage+"> Press enter to continue"); - try { - System.err.println(stdin.readLine()); - } catch (final IOException e) { e.printStackTrace(); } - } - - - public static class StreamDump extends InterruptSource.Thread { - final InputStream is; - final StringBuilder outString; - final OutputStream outStream; - final String prefix; - final Object sync; - volatile boolean eos = false; - - public StreamDump(final OutputStream out, final String prefix, final InputStream is, final Object sync) { - this.is = is; - this.outString = null; - this.outStream = out; - this.prefix = prefix; - this.sync = sync; - } - public StreamDump(final StringBuilder sb, final String prefix, final InputStream is, final Object sync) { - this.is = is; - this.outString = sb; - this.outStream = null; - this.prefix = prefix; - this.sync = sync; - } - public StreamDump(final StringBuilder sb, final InputStream is, final Object sync) { - this.is = is; - this.outString = sb; - this.outStream = null; - this.prefix = null; - this.sync = sync; - } - - public final boolean eos() { return eos; } - - @Override - public void run() { - synchronized ( sync ) { - try { - final BufferedReader in = new BufferedReader( new InputStreamReader(is) ); - String line = null; - while ((line = in.readLine()) != null) { - if( null != outString ) { - outString.append(line).append(Platform.getNewline()); - } else if( null != outStream ) { - if( null != prefix ) { - outStream.write(prefix.getBytes()); - } - outStream.write(line.getBytes()); - outStream.write(Platform.getNewline().getBytes()); - outStream.flush(); - } - } - } catch (final IOException ioe) { - System.err.println("Caught "+ioe.getClass().getName()+": "+ioe.getMessage()); - ioe.printStackTrace(); - } finally { - eos = true; - sync.notifyAll(); - } - } - } - } - - public static void dumpSharedGLContext(final String prefix, final GLContext self) { - int i = 0, j = 0; - final GLContext master = self.getSharedMaster(); - final int masterHash = null != master ? master.hashCode() : 0; - System.err.println(prefix+": hash 0x"+Integer.toHexString(self.hashCode())+", \t(isShared "+self.isShared()+", created "+self.isCreated()+", master 0x"+Integer.toHexString(masterHash)+")"); - { - final List set = self.getCreatedShares(); - for (final Iterator iter = set.iterator(); iter.hasNext(); ) { - final GLContext c = iter.next(); - System.err.println(" Created Ctx #"+(i++)+": hash 0x"+Integer.toHexString(c.hashCode())+", \t(created "+c.isCreated()+")"); - } - } - { - final List set = self.getDestroyedShares(); - for (final Iterator iter = set.iterator(); iter.hasNext(); ) { - final GLContext c = iter.next(); - System.err.println(" Destroyed Ctx #"+(j++)+": hash 0x"+Integer.toHexString(c.hashCode())+", \t(created "+c.isCreated()+")"); - } - } - System.err.println("\t Total created "+i+" + destroyed "+j+" = "+(i+j)); - System.err.println(); - } -} - - - diff --git a/src/demos/com/jogamp/opengl/demos/android/LauncherUtil.java b/src/demos/com/jogamp/opengl/demos/android/LauncherUtil.java new file mode 100644 index 000000000..f512e467e --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/android/LauncherUtil.java @@ -0,0 +1,430 @@ +/** + * 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.demos.android; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import android.app.Activity; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.util.Log; + +/** + * Helper class to parse Uri's and programmatically add package names and properties to create an Uri or Intend. + *

+ * The order of the Uri segments (any arguments) is preserved. + *

+ */ +public class LauncherUtil { + + /** Default launch mode. */ + public static final String LAUNCH_ACTIVITY_NORMAL = "org.jogamp.launcher.action.LAUNCH_ACTIVITY_NORMAL"; + + /** Transparent launch mode. Note: This seems to be required to achieve translucency, since setTheme(..) doesn't work. */ + public static final String LAUNCH_ACTIVITY_TRANSPARENT = "org.jogamp.launcher.action.LAUNCH_ACTIVITY_TRANSPARENT"; + + /** FIXME: TODO */ + public static final String LAUNCH_MAIN = "org.jogamp.launcher.action.LAUNCH_MAIN"; + + /** FIXME: TODO */ + public static final String LAUNCH_JUNIT = "org.jogamp.launcher.action.LAUNCH_JUNIT"; + + /** The protocol launch */ + public static final String SCHEME = "launch"; + + /** The host jogamp.org */ + public static final String HOST = "jogamp.org"; + + static final String SYS_PKG = "sys"; + + static final String USR_PKG = "pkg"; + + static final String ARG = "arg"; + + public static abstract class BaseActivityLauncher extends Activity { + final OrderedProperties props = new OrderedProperties(); + final ArrayList args = new ArrayList(); + /** + * Returns the default {@link LauncherUtil#LAUNCH_ACTIVITY_NORMAL} action. + *

+ * Should be overridden for other action, eg. {@link LauncherUtil#LAUNCH_ACTIVITY_TRANSPARENT}. + *

+ */ + public String getAction() { return LAUNCH_ACTIVITY_NORMAL; } + + /** + * Returns the properties, which are being propagated to the target activity. + *

+ * Maybe be used to set custom properties. + *

+ */ + public final OrderedProperties getProperties() { return props; } + + /** + * Returns the commandline arguments, which are being propagated to the target activity. + *

+ * Maybe be used to set custom commandline arguments. + *

+ */ + public final ArrayList getArguments() { return args; } + + /** Custom initialization hook which can be overriden to setup data, e.g. fill the properties retrieved by {@link #getProperties()}. */ + public void init() { } + + /** Returns true if this launcher activity shall end after starting the downstream activity. Defaults to true, override to change behavior. */ + public boolean finishAfterDelegate() { return true; } + + /** Must return the downstream Activity class name */ + public abstract String getActivityName(); + + /** Must return a list of required user packages, at least one containing the activity. */ + public abstract List getUsrPackages(); + + /** Return a list of required system packages w/ native libraries, may return null or a zero sized list. */ + public abstract List getSysPackages(); + + @Override + public void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + init(); + + final DataSet data = new DataSet(); + data.setActivityName(getActivityName()); + data.addAllSysPackages(getSysPackages()); + data.addAllUsrPackages(getUsrPackages()); + data.addAllProperties(props); + data.addAllArguments(args); + + final Intent intent = LauncherUtil.getIntent(getAction(), data); + Log.d(getClass().getSimpleName(), "Launching Activity: "+intent); + startActivity (intent); + + if(finishAfterDelegate()) { + finish(); // done + } + } + } + + public static class OrderedProperties { + HashMap map = new HashMap(); + ArrayList keyList = new ArrayList(); + + public final void setProperty(final String key, final String value) { + if(key.equals(SYS_PKG)) { + throw new IllegalArgumentException("Illegal property key, '"+SYS_PKG+"' is reserved"); + } + if(key.equals(USR_PKG)) { + throw new IllegalArgumentException("Illegal property key, '"+USR_PKG+"' is reserved"); + } + if(key.equals(ARG)) { + throw new IllegalArgumentException("Illegal property key, '"+ARG+"' is reserved"); + } + final String oval = map.put(key, value); + if(null != oval) { + map.put(key, oval); // restore + throw new IllegalArgumentException("Property overwriting not allowed: "+key+": "+oval+" -> "+value); + } + keyList.add(key); // new key + } + + public final void addAll(final OrderedProperties props) { + final Iterator argKeys = props.keyList.iterator(); + while(argKeys.hasNext()) { + final String key = argKeys.next(); + setProperty(key, props.map.get(key)); + } + } + + public final void setSystemProperties() { + final Iterator argKeys = keyList.iterator(); + while(argKeys.hasNext()) { + final String key = argKeys.next(); + System.setProperty(key, map.get(key)); + } + } + public final void clearSystemProperties() { + final Iterator argKeys = keyList.iterator(); + while(argKeys.hasNext()) { + System.clearProperty(argKeys.next()); + } + } + + public final String getProperty(final String key) { return map.get(key); } + public final Map getProperties() { return map; } + + /** Returns the list of property keys in the order, as they were added. */ + public final List getPropertyKeys() { return keyList; } + } + + /** + * Data set to transfer from and to launch URI consisting out of: + *
    + *
  • system packages w/ native libraries used on Android, which may use a cached ClassLoader, see {@link DataSet#getSysPackages()}.
  • + *
  • user packages w/o native libraries used on Android, which do not use a cached ClassLoader, see {@link DataSet#getUsrPackages()}.
  • + *
  • activity name, used to launch an Android activity, see {@link DataSet#getActivityName()}.
  • + *
  • properties, which will be added to the system properties, see {@link DataSet#getProperties()}.
  • + *
  • arguments, used to launch a class main-entry, see {@link DataSet#getArguments()}.
  • + *
+ * {@link DataSet#getUri()} returns a URI representation of all components. + */ + public static class DataSet { + static final char SLASH = '/'; + static final char QMARK = '?'; + static final char AMPER = '&'; + static final char ASSIG = '='; + static final String COLSLASH2 = "://"; + static final String EMPTY = ""; + + String activityName = null; + ArrayList sysPackages = new ArrayList(); + ArrayList usrPackages = new ArrayList(); + OrderedProperties properties = new OrderedProperties(); + ArrayList arguments = new ArrayList(); + + public final void setActivityName(final String name) { activityName = name; } + public final String getActivityName() { return activityName; } + + public final void addSysPackage(final String p) { + sysPackages.add(p); + } + public final void addAllSysPackages(final List plist) { + sysPackages.addAll(plist); + } + public final List getSysPackages() { return sysPackages; } + + public final void addUsrPackage(final String p) { + usrPackages.add(p); + } + public final void addAllUsrPackages(final List plist) { + usrPackages.addAll(plist); + } + public final List getUsrPackages() { return usrPackages; } + + public final void setProperty(final String key, final String value) { + properties.setProperty(key, value); + } + public final void addAllProperties(final OrderedProperties props) { + properties.addAll(props); + } + public final void setSystemProperties() { + properties.setSystemProperties(); + } + public final void clearSystemProperties() { + properties.clearSystemProperties(); + } + public final String getProperty(final String key) { return properties.getProperty(key); } + public final OrderedProperties getProperties() { return properties; } + public final List getPropertyKeys() { return properties.getPropertyKeys(); } + + public final void addArgument(final String arg) { arguments.add(arg); } + public final void addAllArguments(final List args) { + arguments.addAll(args); + } + public final ArrayList getArguments() { return arguments; } + + public final Uri getUri() { + final StringBuilder sb = new StringBuilder(); + sb.append(SCHEME).append(COLSLASH2).append(HOST).append(SLASH).append(getActivityName()); + boolean needsQMark = true; + boolean needsSep = false; + if(sysPackages.size()>0) { + if( needsQMark ) { + sb.append(QMARK); + needsQMark = false; + } + for(int i=0; i0) { + if( needsQMark ) { + sb.append(QMARK); + needsQMark = false; + } + for(int i=0; i propKeys = properties.keyList.iterator(); + while(propKeys.hasNext()) { + if( needsQMark ) { + sb.append(QMARK); + needsQMark = false; + } + if(needsSep) { + sb.append(AMPER); + } + final String key = propKeys.next(); + sb.append(key).append(ASSIG).append(properties.map.get(key)); + needsSep = true; + } + final Iterator args = arguments.iterator(); + while(args.hasNext()) { + if( needsQMark ) { + sb.append(QMARK); + needsQMark = false; + } + if(needsSep) { + sb.append(AMPER); + } + sb.append(ARG).append(ASSIG).append(args.next()); + needsSep = true; + } + return Uri.parse(sb.toString()); + } + + public static final DataSet create(final Uri uri) { + if(!uri.getScheme().equals(SCHEME)) { + return null; + } + if(!uri.getHost().equals(HOST)) { + return null; + } + final DataSet data = new DataSet(); + { + String an = uri.getPath(); + if(SLASH == an.charAt(0)) { + an = an.substring(1); + } + if(SLASH == an.charAt(an.length()-1)) { + an = an.substring(0, an.length()-1); + } + data.setActivityName(an); + } + + final String q = uri.getQuery(); + final int q_l = null != q ? q.length() : -1; + int q_e = -1; + while(q_e < q_l) { + final int q_b = q_e + 1; // next term + q_e = q.indexOf(AMPER, q_b); + if(0 == q_e) { + // single separator + continue; + } + if(0 > q_e) { + // end + q_e = q_l; + } + // n-part + final String part = q.substring(q_b, q_e); + final int assignment = part.indexOf(ASSIG); + if(0 < assignment) { + // assignment + final String k = part.substring(0, assignment); + final String v = part.substring(assignment+1); + if(k.equals(SYS_PKG)) { + if(v.length()==0) { + throw new IllegalArgumentException("Empty package name: part <"+part+">, query <"+q+"> of "+uri); + } + data.addSysPackage(v); + } else if(k.equals(USR_PKG)) { + if(v.length()==0) { + throw new IllegalArgumentException("Empty package name: part <"+part+">, query <"+q+"> of "+uri); + } + data.addUsrPackage(v); + } else if(k.equals(ARG)) { + if(v.length()==0) { + throw new IllegalArgumentException("Empty argument name: part <"+part+">, query <"+q+"> of "+uri); + } + data.addArgument(v); + } else { + data.setProperty(k, v); + } + } else { + // property key only + if( part.equals(USR_PKG) || part.equals(ARG) ) { + throw new IllegalArgumentException("Reserved key <"+part+"> in query <"+q+"> of "+uri); + } + data.setProperty(part, EMPTY); + } + } + data.validate(); + return data; + } + + public final void validate() { + if(null == activityName) { + throw new RuntimeException("Activity is not NULL"); + } + } + } + + public final static Intent getIntent(final String action, final DataSet data) { + data.validate(); + return new Intent(action, data.getUri()); + } + + public static void main(String[] args) { + if(args.length==0) { + args = new String[] { + SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+SYS_PKG+"=jogamp.pack1&"+SYS_PKG+"=javax.pack2&"+USR_PKG+"=com.jogamp.pack3&"+USR_PKG+"=com.jogamp.pack4&jogamp.common.debug=true&com.jogamp.test=false", + SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+SYS_PKG+"=jogamp.pack1&jogamp.common.debug=true&com.jogamp.test=false", + SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+USR_PKG+"=jogamp.pack1&jogamp.common.debug=true&com.jogamp.test=false", + SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+USR_PKG+"=jogamp.pack1&"+USR_PKG+"=com.jogamp.pack2", + SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+USR_PKG+"=jogamp.pack1&"+USR_PKG+"=javax.pack2&"+USR_PKG+"=com.jogamp.pack3&jogamp.common.debug=true&com.jogamp.test=false&"+ARG+"=arg1&"+ARG+"=arg2=arg2value&"+ARG+"=arg3", + SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+USR_PKG+"=jogamp.pack1&jogamp.common.debug=true&com.jogamp.test=false&"+ARG+"=arg1&"+ARG+"=arg2=arg2value&"+ARG+"=arg3", + SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+USR_PKG+"=jogamp.pack1&"+ARG+"=arg1&"+ARG+"=arg2=arg2value&"+ARG+"=arg3" + }; + } + int errors = 0; + for(int i=0; i -> "+uri0+" -> NULL"); + } else { + final Uri uri1 = data.getUri(); + if(!uri0.equals(uri1)) { + errors++; + System.err.println("Error: Not equal: <"+uri_s+"> -> "+uri0+" -> "+uri1); + } else { + System.err.println("OK: "+uri1); + } + } + } + System.err.println("LauncherUtil Self Test: Errors: "+errors); + } + +} diff --git a/src/demos/com/jogamp/opengl/demos/android/MovieCubeActivity0a.java b/src/demos/com/jogamp/opengl/demos/android/MovieCubeActivity0a.java new file mode 100644 index 000000000..cdbaa7872 --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/android/MovieCubeActivity0a.java @@ -0,0 +1,166 @@ +/** + * Copyright 2011 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.demos.android; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URISyntaxException; +import java.net.URLConnection; +import java.util.Arrays; + +import com.jogamp.opengl.GLCapabilities; +import com.jogamp.opengl.GLProfile; +import com.jogamp.opengl.demos.av.MovieCube; + +import jogamp.newt.driver.android.NewtBaseActivity; + +import com.jogamp.common.net.Uri; +import com.jogamp.common.util.IOUtil; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.event.MouseAdapter; +import com.jogamp.newt.event.MouseEvent; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.av.GLMediaPlayer; +import com.jogamp.opengl.util.av.GLMediaPlayer.GLMediaEventListener; +import com.jogamp.opengl.util.av.GLMediaPlayer.StreamException; +import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame; + +import android.os.Bundle; +import android.util.Log; + +public class MovieCubeActivity0a extends NewtBaseActivity { + static String TAG = "MovieCubeActivity0a"; + + MouseAdapter showKeyboardMouseListener = new MouseAdapter() { + @Override + public void mousePressed(final MouseEvent e) { + if( e.getPointerCount() == 4 && e.getPressure(0, true) > 0.7f ) { + ((com.jogamp.newt.Window) e.getSource()).setKeyboardVisible(true); + } + } + }; + + @Override + public void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + final String[] streamLocs = new String[] { + System.getProperty("jnlp.media0_url0"), + System.getProperty("jnlp.media0_url1"), + System.getProperty("jnlp.media0_url2") }; + final Uri streamLoc = getUri(streamLocs, 0, false); + if(null == streamLoc) { throw new RuntimeException("no media reachable: "+Arrays.asList(streamLocs)); } + + // also initializes JOGL + final GLCapabilities capsMain = new GLCapabilities(GLProfile.getGL2ES2()); + capsMain.setBackgroundOpaque(false); + + // screen for layout params .. + final com.jogamp.newt.Display dpy = NewtFactory.createDisplay(null); + final com.jogamp.newt.Screen scrn = NewtFactory.createScreen(dpy, 0); + scrn.addReference(); + + try { + final Animator anim = new Animator(); + + // Main + final GLWindow glWindowMain = GLWindow.create(scrn, capsMain); + glWindowMain.setFullscreen(true); + setContentView(getWindow(), glWindowMain); + anim.add(glWindowMain); + glWindowMain.setVisible(true); + glWindowMain.addMouseListener(showKeyboardMouseListener); + + final MovieCube demoMain = new MovieCube(MovieCube.zoom_def, 0f, 0f, false); + final GLMediaPlayer mPlayer = demoMain.getGLMediaPlayer(); + mPlayer.addEventListener(new GLMediaEventListener() { + @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("MovieCubeActivity0 AttributesChanges: events_mask 0x"+Integer.toHexString(event_mask)+", when "+when); + System.err.println("MovieCubeActivity0 State: "+mp); + if( 0 != ( GLMediaEventListener.EVENT_CHANGE_INIT & event_mask ) ) { + glWindowMain.addGLEventListener(demoMain); + anim.setUpdateFPSFrames(60*5, null); + anim.resetFPSCounter(); + } + if( 0 != ( GLMediaEventListener.EVENT_CHANGE_PLAY & event_mask ) ) { + anim.resetFPSCounter(); + } + if( 0 != ( ( GLMediaEventListener.EVENT_CHANGE_ERR | GLMediaEventListener.EVENT_CHANGE_EOS ) & event_mask ) ) { + final StreamException se = mPlayer.getStreamException(); + if( null != se ) { + se.printStackTrace(); + } + getActivity().finish(); + } + } + }); + demoMain.initStream(streamLoc, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, 0); + } catch (final IOException e) { + e.printStackTrace(); + } + + scrn.removeReference(); + + Log.d(TAG, "onCreate - X"); + } + + static Uri getUri(final String path[], final int off, final boolean checkAvail) { + Uri uri = null; + for(int i=off; null==uri && i0) { + if( checkAvail ) { + final URLConnection uc = IOUtil.getResource(path[i], null); + if( null != uc ) { + try { + uri = Uri.valueOf(uc.getURL()); + } catch (final URISyntaxException e) { + uri = null; + } + if( uc instanceof HttpURLConnection ) { + ((HttpURLConnection)uc).disconnect(); + } + } + } else { + try { + uri = Uri.cast(path[i]); + } catch (final URISyntaxException e) { + uri = null; + } + } + Log.d(TAG, "Stream: <"+path[i]+">: "+(null!=uri)); + } + } + return uri; + } +} diff --git a/src/demos/com/jogamp/opengl/demos/android/MovieCubeActivity0b.java b/src/demos/com/jogamp/opengl/demos/android/MovieCubeActivity0b.java new file mode 100644 index 000000000..b04487b5f --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/android/MovieCubeActivity0b.java @@ -0,0 +1,168 @@ +/** + * Copyright 2011 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.demos.android; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URISyntaxException; +import java.net.URLConnection; +import java.util.Arrays; + +import com.jogamp.opengl.GLCapabilities; +import com.jogamp.opengl.GLProfile; +import com.jogamp.opengl.demos.av.MovieCube; + +import jogamp.newt.driver.android.NewtBaseActivity; + +import com.jogamp.common.net.Uri; +import com.jogamp.common.util.IOUtil; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.event.MouseAdapter; +import com.jogamp.newt.event.MouseEvent; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.av.GLMediaPlayer; +import com.jogamp.opengl.util.av.GLMediaPlayer.GLMediaEventListener; +import com.jogamp.opengl.util.av.GLMediaPlayer.StreamException; +import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame; + +import android.os.Bundle; +import android.util.Log; + +public class MovieCubeActivity0b extends NewtBaseActivity { + static String TAG = "MovieCubeActivity0a"; + + MouseAdapter showKeyboardMouseListener = new MouseAdapter() { + @Override + public void mousePressed(final MouseEvent e) { + if( e.getPointerCount() == 4 && e.getPressure(0, true) > 0.7f ) { + ((com.jogamp.newt.Window) e.getSource()).setKeyboardVisible(true); + } + } + }; + + @Override + public void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + final String[] streamLocs = new String[] { + System.getProperty("jnlp.media0_url0"), + System.getProperty("jnlp.media0_url1"), + System.getProperty("jnlp.media0_url2") }; + final Uri streamLoc = getUri(streamLocs, 0, false); + if(null == streamLoc) { throw new RuntimeException("no media reachable: "+Arrays.asList(streamLocs)); } + + // also initializes JOGL + final GLCapabilities capsMain = new GLCapabilities(GLProfile.getGL2ES2()); + capsMain.setNumSamples(4); + capsMain.setSampleBuffers(true); + capsMain.setBackgroundOpaque(false); + + // screen for layout params .. + final com.jogamp.newt.Display dpy = NewtFactory.createDisplay(null); + final com.jogamp.newt.Screen scrn = NewtFactory.createScreen(dpy, 0); + scrn.addReference(); + + try { + final Animator anim = new Animator(); + + // Main + final GLWindow glWindowMain = GLWindow.create(scrn, capsMain); + glWindowMain.setFullscreen(true); + setContentView(getWindow(), glWindowMain); + anim.add(glWindowMain); + glWindowMain.setVisible(true); + glWindowMain.addMouseListener(showKeyboardMouseListener); + + final MovieCube demoMain = new MovieCube(MovieCube.zoom_def, 0f, 0f, true); + final GLMediaPlayer mPlayer = demoMain.getGLMediaPlayer(); + mPlayer.addEventListener(new GLMediaEventListener() { + @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("MovieCubeActivity0 AttributesChanges: events_mask 0x"+Integer.toHexString(event_mask)+", when "+when); + System.err.println("MovieCubeActivity0 State: "+mp); + if( 0 != ( GLMediaEventListener.EVENT_CHANGE_INIT & event_mask ) ) { + glWindowMain.addGLEventListener(demoMain); + anim.setUpdateFPSFrames(60*5, null); + anim.resetFPSCounter(); + } + if( 0 != ( GLMediaEventListener.EVENT_CHANGE_PLAY & event_mask ) ) { + anim.resetFPSCounter(); + } + if( 0 != ( ( GLMediaEventListener.EVENT_CHANGE_ERR | GLMediaEventListener.EVENT_CHANGE_EOS ) & event_mask ) ) { + final StreamException se = mPlayer.getStreamException(); + if( null != se ) { + se.printStackTrace(); + } + getActivity().finish(); + } + } + }); + demoMain.initStream(streamLoc, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, 0); + } catch (final IOException e) { + e.printStackTrace(); + } + + scrn.removeReference(); + + Log.d(TAG, "onCreate - X"); + } + + static Uri getUri(final String path[], final int off, final boolean checkAvail) { + Uri uri = null; + for(int i=off; null==uri && i0) { + if( checkAvail ) { + final URLConnection uc = IOUtil.getResource(path[i], null); + if( null != uc ) { + try { + uri = Uri.valueOf(uc.getURL()); + } catch (final URISyntaxException e) { + uri = null; + } + if( uc instanceof HttpURLConnection ) { + ((HttpURLConnection)uc).disconnect(); + } + } + } else { + try { + uri = Uri.cast(path[i]); + } catch (final URISyntaxException e) { + uri = null; + } + } + Log.d(TAG, "Stream: <"+path[i]+">: "+(null!=uri)); + } + } + return uri; + } +} diff --git a/src/demos/com/jogamp/opengl/demos/android/MovieCubeActivityLauncher0a.java b/src/demos/com/jogamp/opengl/demos/android/MovieCubeActivityLauncher0a.java new file mode 100644 index 000000000..4c9409b02 --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/android/MovieCubeActivityLauncher0a.java @@ -0,0 +1,87 @@ +/** + * 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.demos.android; + +import java.util.Arrays; +import java.util.List; + +import com.jogamp.opengl.demos.android.LauncherUtil.BaseActivityLauncher; +import com.jogamp.opengl.demos.android.LauncherUtil.OrderedProperties; + +public class MovieCubeActivityLauncher0a extends LauncherUtil.BaseActivityLauncher { + + static String demo = "com.jogamp.opengl.test.android.MovieCubeActivity0a"; + static String[] sys_pkgs = new String[] { "com.jogamp.common", "com.jogamp.opengl" }; + static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" }; + + @Override + public void init() { + final OrderedProperties props = getProperties(); + props.setProperty("jnlp.media0_url0", "http://archive.org/download/BigBuckBunny_328/BigBuckBunny_512kb.mp4"); + props.setProperty("jnlp.media1_url1", "http://archive.org/download/ElephantsDream/ed_1024_512kb.mp4"); + props.setProperty("jnlp.media0_url2", "file:///mnt/sdcard/Movies/BigBuckBunny_320x180.mp4"); + // props.setProperty("jogamp.debug.JNILibLoader", "true"); + // props.setProperty("jogamp.debug.NativeLibrary", "true"); + // props.setProperty("jogamp.debug.NativeLibrary.Lookup", "true"); + // props.setProperty("jogamp.debug.IOUtil", "true"); + // props.setProperty("jogamp.debug.Lock", "true"); + // props.setProperty("jogamp.debug.Lock.TraceLock", "true"); + // props.setProperty("nativewindow.debug", "all"); + // props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); + // props.setProperty("jogl.debug", "all"); + // props.setProperty("jogl.debug.GLProfile", "true"); + // props.setProperty("jogl.debug.GLDrawable", "true"); + // props.setProperty("jogl.debug.GLContext", "true"); + props.setProperty("jogl.debug.GLMediaPlayer", "true"); + props.setProperty("jogl.debug.GLSLCode", "true"); + // props.setProperty("jogl.debug.CapabilitiesChooser", "true"); + // props.setProperty("jogl.debug.GLSLState", "true"); + // props.setProperty("jogl.debug.DebugGL", "true"); + // props.setProperty("jogl.debug.TraceGL", "true"); + // props.setProperty("newt.debug", "all"); + // props.setProperty("newt.debug.Window", "true"); + // props.setProperty("newt.debug.Window.MouseEvent", "true"); + // props.setProperty("newt.debug.Window.KeyEvent", "true"); + props.setProperty("jogamp.debug.IOUtil", "true"); + } + + @Override + public String getActivityName() { + return demo; + } + + @Override + public List getSysPackages() { + return Arrays.asList(sys_pkgs); + } + + @Override + public List getUsrPackages() { + return Arrays.asList(usr_pkgs); + } +} diff --git a/src/demos/com/jogamp/opengl/demos/android/MovieCubeActivityLauncher0b.java b/src/demos/com/jogamp/opengl/demos/android/MovieCubeActivityLauncher0b.java new file mode 100644 index 000000000..548c0bc51 --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/android/MovieCubeActivityLauncher0b.java @@ -0,0 +1,87 @@ +/** + * 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.demos.android; + +import java.util.Arrays; +import java.util.List; + +import com.jogamp.opengl.demos.android.LauncherUtil.BaseActivityLauncher; +import com.jogamp.opengl.demos.android.LauncherUtil.OrderedProperties; + +public class MovieCubeActivityLauncher0b extends LauncherUtil.BaseActivityLauncher { + + static String demo = "com.jogamp.opengl.test.android.MovieCubeActivity0b"; + static String[] sys_pkgs = new String[] { "com.jogamp.common", "com.jogamp.opengl" }; + static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" }; + + @Override + public void init() { + final OrderedProperties props = getProperties(); + props.setProperty("jnlp.media0_url0", "http://archive.org/download/BigBuckBunny_328/BigBuckBunny_512kb.mp4"); + props.setProperty("jnlp.media1_url1", "http://archive.org/download/ElephantsDream/ed_1024_512kb.mp4"); + props.setProperty("jnlp.media0_url2", "file:///mnt/sdcard/Movies/BigBuckBunny_320x180.mp4"); + // props.setProperty("jogamp.debug.JNILibLoader", "true"); + // props.setProperty("jogamp.debug.NativeLibrary", "true"); + // props.setProperty("jogamp.debug.NativeLibrary.Lookup", "true"); + // props.setProperty("jogamp.debug.IOUtil", "true"); + // props.setProperty("jogamp.debug.Lock", "true"); + // props.setProperty("jogamp.debug.Lock.TraceLock", "true"); + // props.setProperty("nativewindow.debug", "all"); + // props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); + // props.setProperty("jogl.debug", "all"); + // props.setProperty("jogl.debug.GLProfile", "true"); + // props.setProperty("jogl.debug.GLDrawable", "true"); + // props.setProperty("jogl.debug.GLContext", "true"); + // props.setProperty("jogl.debug.GLMediaPlayer", "true"); + props.setProperty("jogl.debug.GLSLCode", "true"); + // props.setProperty("jogl.debug.CapabilitiesChooser", "true"); + // props.setProperty("jogl.debug.GLSLState", "true"); + // props.setProperty("jogl.debug.DebugGL", "true"); + // props.setProperty("jogl.debug.TraceGL", "true"); + // props.setProperty("newt.debug", "all"); + // props.setProperty("newt.debug.Window", "true"); + // props.setProperty("newt.debug.Window.MouseEvent", "true"); + // props.setProperty("newt.debug.Window.KeyEvent", "true"); + props.setProperty("jogamp.debug.IOUtil", "true"); + } + + @Override + public String getActivityName() { + return demo; + } + + @Override + public List getSysPackages() { + return Arrays.asList(sys_pkgs); + } + + @Override + public List getUsrPackages() { + return Arrays.asList(usr_pkgs); + } +} diff --git a/src/demos/com/jogamp/opengl/demos/android/MovieCubeActivityLauncher1a.java b/src/demos/com/jogamp/opengl/demos/android/MovieCubeActivityLauncher1a.java new file mode 100644 index 000000000..d4133df18 --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/android/MovieCubeActivityLauncher1a.java @@ -0,0 +1,87 @@ +/** + * 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.demos.android; + +import java.util.Arrays; +import java.util.List; + +import com.jogamp.opengl.demos.android.LauncherUtil.BaseActivityLauncher; +import com.jogamp.opengl.demos.android.LauncherUtil.OrderedProperties; + +public class MovieCubeActivityLauncher1a extends LauncherUtil.BaseActivityLauncher { + + static String demo = "com.jogamp.opengl.test.android.MovieCubeActivity0a"; + static String[] sys_pkgs = new String[] { "com.jogamp.common", "com.jogamp.opengl" }; + static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" }; + + @Override + public void init() { + final OrderedProperties props = getProperties(); + props.setProperty("jnlp.media0_url0", "camera:/0"); + props.setProperty("jnlp.media0_url1", ""); + props.setProperty("jnlp.media1_url2", ""); + // props.setProperty("jogamp.debug.JNILibLoader", "true"); + // props.setProperty("jogamp.debug.NativeLibrary", "true"); + // props.setProperty("jogamp.debug.NativeLibrary.Lookup", "true"); + // props.setProperty("jogamp.debug.IOUtil", "true"); + // props.setProperty("jogamp.debug.Lock", "true"); + // props.setProperty("jogamp.debug.Lock.TraceLock", "true"); + // props.setProperty("nativewindow.debug", "all"); + // props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); + // props.setProperty("jogl.debug", "all"); + // props.setProperty("jogl.debug.GLProfile", "true"); + // props.setProperty("jogl.debug.GLDrawable", "true"); + // props.setProperty("jogl.debug.GLContext", "true"); + props.setProperty("jogl.debug.GLMediaPlayer", "true"); + props.setProperty("jogl.debug.GLSLCode", "true"); + // props.setProperty("jogl.debug.CapabilitiesChooser", "true"); + // props.setProperty("jogl.debug.GLSLState", "true"); + // props.setProperty("jogl.debug.DebugGL", "true"); + // props.setProperty("jogl.debug.TraceGL", "true"); + // props.setProperty("newt.debug", "all"); + // props.setProperty("newt.debug.Window", "true"); + // props.setProperty("newt.debug.Window.MouseEvent", "true"); + // props.setProperty("newt.debug.Window.KeyEvent", "true"); + // props.setProperty("jogamp.debug.IOUtil", "true"); + } + + @Override + public String getActivityName() { + return demo; + } + + @Override + public List getSysPackages() { + return Arrays.asList(sys_pkgs); + } + + @Override + public List getUsrPackages() { + return Arrays.asList(usr_pkgs); + } +} diff --git a/src/demos/com/jogamp/opengl/demos/android/MovieCubeActivityLauncher1b.java b/src/demos/com/jogamp/opengl/demos/android/MovieCubeActivityLauncher1b.java new file mode 100644 index 000000000..21749ef74 --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/android/MovieCubeActivityLauncher1b.java @@ -0,0 +1,87 @@ +/** + * 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.demos.android; + +import java.util.Arrays; +import java.util.List; + +import com.jogamp.opengl.demos.android.LauncherUtil.BaseActivityLauncher; +import com.jogamp.opengl.demos.android.LauncherUtil.OrderedProperties; + +public class MovieCubeActivityLauncher1b extends LauncherUtil.BaseActivityLauncher { + + static String demo = "com.jogamp.opengl.test.android.MovieCubeActivity0b"; + static String[] sys_pkgs = new String[] { "com.jogamp.common", "com.jogamp.opengl" }; + static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" }; + + @Override + public void init() { + final OrderedProperties props = getProperties(); + props.setProperty("jnlp.media0_url0", "camera:/1"); + props.setProperty("jnlp.media0_url1", ""); + props.setProperty("jnlp.media1_url2", ""); + // props.setProperty("jogamp.debug.JNILibLoader", "true"); + // props.setProperty("jogamp.debug.NativeLibrary", "true"); + // props.setProperty("jogamp.debug.NativeLibrary.Lookup", "true"); + // props.setProperty("jogamp.debug.IOUtil", "true"); + // props.setProperty("jogamp.debug.Lock", "true"); + // props.setProperty("jogamp.debug.Lock.TraceLock", "true"); + // props.setProperty("nativewindow.debug", "all"); + // props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); + // props.setProperty("jogl.debug", "all"); + // props.setProperty("jogl.debug.GLProfile", "true"); + // props.setProperty("jogl.debug.GLDrawable", "true"); + // props.setProperty("jogl.debug.GLContext", "true"); + // props.setProperty("jogl.debug.GLMediaPlayer", "true"); + props.setProperty("jogl.debug.GLSLCode", "true"); + // props.setProperty("jogl.debug.CapabilitiesChooser", "true"); + // props.setProperty("jogl.debug.GLSLState", "true"); + // props.setProperty("jogl.debug.DebugGL", "true"); + // props.setProperty("jogl.debug.TraceGL", "true"); + // props.setProperty("newt.debug", "all"); + // props.setProperty("newt.debug.Window", "true"); + // props.setProperty("newt.debug.Window.MouseEvent", "true"); + // props.setProperty("newt.debug.Window.KeyEvent", "true"); + // props.setProperty("jogamp.debug.IOUtil", "true"); + } + + @Override + public String getActivityName() { + return demo; + } + + @Override + public List getSysPackages() { + return Arrays.asList(sys_pkgs); + } + + @Override + public List getUsrPackages() { + return Arrays.asList(usr_pkgs); + } +} diff --git a/src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivity0.java b/src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivity0.java new file mode 100644 index 000000000..07d0b9914 --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivity0.java @@ -0,0 +1,159 @@ +/** + * Copyright 2011 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.demos.android; + +import java.net.HttpURLConnection; +import java.net.URISyntaxException; +import java.net.URLConnection; +import java.util.Arrays; + +import com.jogamp.opengl.GLCapabilities; +import com.jogamp.opengl.GLProfile; +import com.jogamp.opengl.demos.av.MovieSimple; + +import jogamp.newt.driver.android.NewtBaseActivity; + +import com.jogamp.common.net.Uri; +import com.jogamp.common.util.IOUtil; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Window; +import com.jogamp.newt.event.MouseAdapter; +import com.jogamp.newt.event.MouseEvent; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.av.GLMediaPlayer; +import com.jogamp.opengl.util.av.GLMediaPlayer.GLMediaEventListener; +import com.jogamp.opengl.util.av.GLMediaPlayer.StreamException; +import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame; + +import android.os.Bundle; +import android.util.Log; + +public class MovieSimpleActivity0 extends NewtBaseActivity { + static String TAG = "MovieSimpleActivity0"; + + MouseAdapter toFrontMouseListener = new MouseAdapter() { + public void mouseClicked(final MouseEvent e) { + final Object src = e.getSource(); + if(src instanceof Window) { + ((Window)src).requestFocus(false); + } + } }; + + @Override + public void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + final String[] streamLocs = new String[] { + System.getProperty("jnlp.media0_url0"), + System.getProperty("jnlp.media0_url1"), + System.getProperty("jnlp.media0_url2") }; + final Uri streamLoc = getUri(streamLocs, 0, false); + if(null == streamLoc) { throw new RuntimeException("no media reachable: "+Arrays.asList(streamLocs)); } + + // also initializes JOGL + final GLCapabilities capsMain = new GLCapabilities(GLProfile.getGL2ES2()); + capsMain.setNumSamples(4); + capsMain.setSampleBuffers(true); + capsMain.setBackgroundOpaque(false); + + // screen for layout params .. + final com.jogamp.newt.Display dpy = NewtFactory.createDisplay(null); + final com.jogamp.newt.Screen scrn = NewtFactory.createScreen(dpy, 0); + scrn.addReference(); + + final Animator anim = new Animator(); + + // Main + final GLWindow glWindowMain = GLWindow.create(scrn, capsMain); + glWindowMain.setFullscreen(true); + setContentView(getWindow(), glWindowMain); + anim.add(glWindowMain); + glWindowMain.setVisible(true); + + final MovieSimple demoMain = new MovieSimple(null); + demoMain.setScaleOrig(true); + final GLMediaPlayer mPlayer = demoMain.getGLMediaPlayer(); + mPlayer.addEventListener( new GLMediaPlayer.GLMediaEventListener() { + @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("MovieSimpleActivity0 AttributesChanges: events_mask 0x"+Integer.toHexString(event_mask)+", when "+when); + System.err.println("MovieSimpleActivity0 State: "+mp); + if( 0 != ( GLMediaEventListener.EVENT_CHANGE_INIT & event_mask ) ) { + glWindowMain.addGLEventListener(demoMain); + anim.setUpdateFPSFrames(60*5, System.err); + anim.resetFPSCounter(); + } + if( 0 != ( ( GLMediaEventListener.EVENT_CHANGE_ERR | GLMediaEventListener.EVENT_CHANGE_EOS ) & event_mask ) ) { + final StreamException se = mPlayer.getStreamException(); + if( null != se ) { + se.printStackTrace(); + } + getActivity().finish(); + } + } + }); + demoMain.initStream(streamLoc, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, 0); + + scrn.removeReference(); + + Log.d(TAG, "onCreate - X"); + } + + static Uri getUri(final String path[], final int off, final boolean checkAvail) { + Uri uri = null; + for(int i=off; null==uri && i0) { + if( checkAvail ) { + final URLConnection uc = IOUtil.getResource(path[i], null); + if( null != uc ) { + try { + uri = Uri.valueOf(uc.getURL()); + } catch (final URISyntaxException e) { + uri = null; + } + if( uc instanceof HttpURLConnection ) { + ((HttpURLConnection)uc).disconnect(); + } + } + } else { + try { + uri = Uri.cast(path[i]); + } catch (final URISyntaxException e) { + uri = null; + } + } + Log.d(TAG, "Stream: <"+path[i]+">: "+(null!=uri)); + } + } + return uri; + } +} diff --git a/src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivity1.java b/src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivity1.java new file mode 100644 index 000000000..d7a2aeae1 --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivity1.java @@ -0,0 +1,262 @@ +/** + * Copyright 2011 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.demos.android; + +import java.net.HttpURLConnection; +import java.net.URISyntaxException; +import java.net.URLConnection; +import java.util.Arrays; + +import com.jogamp.nativewindow.util.Rectangle; +import com.jogamp.opengl.GLAutoDrawable; +import com.jogamp.opengl.GLCapabilities; +import com.jogamp.opengl.GLProfile; +import com.jogamp.opengl.GLRunnable; +import com.jogamp.opengl.demos.av.MovieSimple; + +import jogamp.newt.driver.android.NewtBaseActivity; + +import com.jogamp.common.net.Uri; +import com.jogamp.common.util.IOUtil; +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Window; +import com.jogamp.newt.event.MouseAdapter; +import com.jogamp.newt.event.MouseEvent; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.av.GLMediaPlayer; +import com.jogamp.opengl.util.av.GLMediaPlayer.GLMediaEventListener; +import com.jogamp.opengl.util.av.GLMediaPlayer.StreamException; +import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame; + +import android.os.Bundle; +import android.util.Log; +import android.view.Gravity; + +public class MovieSimpleActivity1 extends NewtBaseActivity { + static String TAG = "MovieSimpleActivity1"; + + MouseAdapter toFrontMouseListener = new MouseAdapter() { + public void mouseClicked(final MouseEvent e) { + final Object src = e.getSource(); + if(src instanceof Window) { + ((Window)src).requestFocus(false); + } + } }; + + @Override + public void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + final boolean mPlayerNoZoom = Boolean.valueOf(System.getProperty("jnlp.mplayer.nozoom")); + final boolean mPlayerHUD = Boolean.valueOf(System.getProperty("jnlp.mplayer.hud")); + final boolean mPlayerSharedHUD = mPlayerHUD && Boolean.valueOf(System.getProperty("jnlp.mplayer.hud.shared")); + Log.d(TAG, "onCreate - 0 - mPlayerNoScale "+mPlayerNoZoom+", mPlayerHUD "+mPlayerHUD+", mPlayerSharedHUD "+mPlayerSharedHUD); + + final String[] streamLocs = new String[] { + System.getProperty("jnlp.media0_url0"), + System.getProperty("jnlp.media0_url1"), + System.getProperty("jnlp.media0_url2") }; + final Uri streamLoc0 = getUri(streamLocs, 2, false); + if(null == streamLoc0) { throw new RuntimeException("no media reachable: "+Arrays.asList(streamLocs)); } + + final Uri streamLoc1; + { + Uri _streamLoc1 = null; + if(mPlayerHUD && !mPlayerSharedHUD) { + final String[] urls1 = new String[] { System.getProperty("jnlp.media1_url0") }; + _streamLoc1 = getUri(urls1, 1, false); + } + if(null == _streamLoc1) { _streamLoc1 = streamLoc0; } + streamLoc1 = _streamLoc1; + } + + setTransparencyTheme(); + setFullscreenFeature(getWindow(), true); + + final android.view.ViewGroup viewGroup = new android.widget.FrameLayout(getActivity().getApplicationContext()); + getWindow().setContentView(viewGroup); + + // also initializes JOGL + final GLCapabilities capsMain = new GLCapabilities(GLProfile.getGL2ES2()); + capsMain.setNumSamples(4); + capsMain.setSampleBuffers(true); + capsMain.setBackgroundOpaque(!mPlayerHUD); + + // screen for layout params .. + final com.jogamp.newt.Display dpy = NewtFactory.createDisplay(null); + final com.jogamp.newt.Screen scrn = NewtFactory.createScreen(dpy, 0); + scrn.addReference(); + + final Animator anim = new Animator(); + + // Main + final GLWindow glWindowMain = GLWindow.create(scrn, capsMain); + { + final int padding = mPlayerHUD ? 32 : 0; + final android.view.View androidView = ((jogamp.newt.driver.android.WindowDriver)glWindowMain.getDelegatedWindow()).getAndroidView(); + glWindowMain.setSurfaceSize(scrn.getWidth()-padding, scrn.getHeight()-padding); + glWindowMain.setUndecorated(true); + // setContentView(getWindow(), glWindowMain); + viewGroup.addView(androidView, new android.widget.FrameLayout.LayoutParams(glWindowMain.getSurfaceWidth(), glWindowMain.getSurfaceHeight(), Gravity.BOTTOM|Gravity.RIGHT)); + registerNEWTWindow(glWindowMain); + } + anim.add(glWindowMain); + glWindowMain.setVisible(true); + + final MovieSimple demoMain = new MovieSimple(null); + final GLMediaPlayer mPlayerMain = demoMain.getGLMediaPlayer(); + if(mPlayerHUD) { + demoMain.setEffects(MovieSimple.EFFECT_GRADIENT_BOTTOM2TOP); + demoMain.setTransparency(0.9f); + } + demoMain.setScaleOrig(mPlayerNoZoom); + mPlayerMain.addEventListener( new GLMediaPlayer.GLMediaEventListener() { + @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("MovieSimpleActivity1 AttributesChanges: events_mask 0x"+Integer.toHexString(event_mask)+", when "+when); + System.err.println("MovieSimpleActivity1 State: "+mp); + if( 0 != ( GLMediaEventListener.EVENT_CHANGE_INIT & event_mask ) ) { + glWindowMain.addGLEventListener(demoMain); + anim.setUpdateFPSFrames(60*5, System.err); + anim.resetFPSCounter(); + } + if( 0 != ( ( GLMediaEventListener.EVENT_CHANGE_ERR | GLMediaEventListener.EVENT_CHANGE_EOS ) & event_mask ) ) { + final StreamException se = mPlayerMain.getStreamException(); + if( null != se ) { + se.printStackTrace(); + } + getActivity().finish(); + } + } + }); + demoMain.initStream(streamLoc0, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, 0); + + if(mPlayerHUD) { + final GLMediaPlayer mPlayerShared = mPlayerSharedHUD ? mPlayerMain : null; + final GLCapabilities capsHUD = new GLCapabilities(GLProfile.getGL2ES2()); + capsHUD.setNumSamples(4); + capsHUD.setSampleBuffers(true); + capsHUD.setBackgroundOpaque(false); + final GLWindow glWindowHUD = GLWindow.create(scrn, capsHUD); + glWindowMain.invoke(false, new GLRunnable() { + @Override + public boolean run(final GLAutoDrawable drawable) { + final GLMediaPlayer mPlayerSub; + final MovieSimple demoHUD; + final Rectangle windowBounds = (Rectangle) scrn.getViewportInWindowUnits().cloneMutable(); + if(null != mPlayerShared) { + if(0 < mPlayerShared.getWidth() && mPlayerShared.getWidth()0) { + if( checkAvail ) { + final URLConnection uc = IOUtil.getResource(path[i], null); + if( null != uc ) { + try { + uri = Uri.valueOf(uc.getURL()); + } catch (final URISyntaxException e) { + uri = null; + } + if( uc instanceof HttpURLConnection ) { + ((HttpURLConnection)uc).disconnect(); + } + } + } else { + try { + uri = Uri.cast(path[i]); + } catch (final URISyntaxException e) { + uri = null; + } + } + Log.d(TAG, "Stream: <"+path[i]+">: "+(null!=uri)); + } + } + return uri; + } +} diff --git a/src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivityLauncher00b.java b/src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivityLauncher00b.java new file mode 100644 index 000000000..bfcf3dd06 --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivityLauncher00b.java @@ -0,0 +1,84 @@ +/** + * 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.demos.android; + +import java.util.Arrays; +import java.util.List; + +import com.jogamp.opengl.demos.android.LauncherUtil.BaseActivityLauncher; +import com.jogamp.opengl.demos.android.LauncherUtil.OrderedProperties; + +public class MovieSimpleActivityLauncher00b extends LauncherUtil.BaseActivityLauncher { + + static String demo = "com.jogamp.opengl.test.android.MovieSimpleActivity0"; + static String[] sys_pkgs = new String[] { "com.jogamp.common", "com.jogamp.opengl" }; + static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" }; + + @Override + public void init() { + final OrderedProperties props = getProperties(); + props.setProperty("jnlp.media0_url0", "http://archive.org/download/BigBuckBunny_328/BigBuckBunny_512kb.mp4"); + props.setProperty("jnlp.media0_url1", "http://video.webmfiles.org/big-buck-bunny_trailer.webm"); + props.setProperty("jnlp.media0_url2", "file:///mnt/sdcard/Movies/BigBuckBunny_320x180.mp4"); + // props.setProperty("jogamp.debug.JNILibLoader", "true"); + // props.setProperty("jogamp.debug.NativeLibrary", "true"); + // props.setProperty("jogamp.debug.NativeLibrary.Lookup", "true"); + // props.setProperty("jogamp.debug.IOUtil", "true"); + // props.setProperty("nativewindow.debug", "all"); + // props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); + // props.setProperty("jogl.debug", "all"); + // props.setProperty("jogl.debug.GLProfile", "true"); + // props.setProperty("jogl.debug.GLDrawable", "true"); + props.setProperty("jogl.debug.GLContext", "true"); + props.setProperty("jogl.debug.GLMediaPlayer", "true"); + props.setProperty("jogl.debug.GLSLCode", "true"); + // props.setProperty("jogl.debug.CapabilitiesChooser", "true"); + // props.setProperty("jogl.debug.GLSLState", "true"); + // props.setProperty("jogl.debug.DebugGL", "true"); + // props.setProperty("jogl.debug.TraceGL", "true"); + // props.setProperty("newt.debug", "all"); + // props.setProperty("newt.debug.Window", "true"); + // props.setProperty("newt.debug.Window.MouseEvent", "true"); + // props.setProperty("newt.debug.Window.KeyEvent", "true"); + props.setProperty("jogamp.debug.IOUtil", "true"); + } + + @Override + public String getActivityName() { + return demo; + } + @Override + public List getSysPackages() { + return Arrays.asList(sys_pkgs); + } + + @Override + public List getUsrPackages() { + return Arrays.asList(usr_pkgs); + } +} diff --git a/src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivityLauncher00c.java b/src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivityLauncher00c.java new file mode 100644 index 000000000..947e848c5 --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivityLauncher00c.java @@ -0,0 +1,84 @@ +/** + * 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.demos.android; + +import java.util.Arrays; +import java.util.List; + +import com.jogamp.opengl.demos.android.LauncherUtil.BaseActivityLauncher; +import com.jogamp.opengl.demos.android.LauncherUtil.OrderedProperties; + +public class MovieSimpleActivityLauncher00c extends LauncherUtil.BaseActivityLauncher { + + static String demo = "com.jogamp.opengl.test.android.MovieSimpleActivity0"; + static String[] sys_pkgs = new String[] { "com.jogamp.common", "com.jogamp.opengl" }; + static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" }; + + @Override + public void init() { + final OrderedProperties props = getProperties(); + props.setProperty("jnlp.media0_url0", "camera:/0"); + props.setProperty("jnlp.media0_url1", ""); + props.setProperty("jnlp.media0_url2", ""); + // props.setProperty("jogamp.debug.JNILibLoader", "true"); + // props.setProperty("jogamp.debug.NativeLibrary", "true"); + // props.setProperty("jogamp.debug.NativeLibrary.Lookup", "true"); + // props.setProperty("jogamp.debug.IOUtil", "true"); + // props.setProperty("nativewindow.debug", "all"); + // props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); + // props.setProperty("jogl.debug", "all"); + // props.setProperty("jogl.debug.GLProfile", "true"); + // props.setProperty("jogl.debug.GLDrawable", "true"); + props.setProperty("jogl.debug.GLContext", "true"); + props.setProperty("jogl.debug.GLMediaPlayer", "true"); + props.setProperty("jogl.debug.GLSLCode", "true"); + // props.setProperty("jogl.debug.CapabilitiesChooser", "true"); + // props.setProperty("jogl.debug.GLSLState", "true"); + // props.setProperty("jogl.debug.DebugGL", "true"); + // props.setProperty("jogl.debug.TraceGL", "true"); + // props.setProperty("newt.debug", "all"); + // props.setProperty("newt.debug.Window", "true"); + // props.setProperty("newt.debug.Window.MouseEvent", "true"); + // props.setProperty("newt.debug.Window.KeyEvent", "true"); + // props.setProperty("jogamp.debug.IOUtil", "true"); + } + + @Override + public String getActivityName() { + return demo; + } + @Override + public List getSysPackages() { + return Arrays.asList(sys_pkgs); + } + + @Override + public List getUsrPackages() { + return Arrays.asList(usr_pkgs); + } +} diff --git a/src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivityLauncher01a.java b/src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivityLauncher01a.java new file mode 100644 index 000000000..bf9114f4f --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivityLauncher01a.java @@ -0,0 +1,87 @@ +/** + * 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.demos.android; + +import java.util.Arrays; +import java.util.List; + +import com.jogamp.opengl.demos.android.LauncherUtil.BaseActivityLauncher; +import com.jogamp.opengl.demos.android.LauncherUtil.OrderedProperties; + +public class MovieSimpleActivityLauncher01a extends LauncherUtil.BaseActivityLauncher { + + static String demo = "com.jogamp.opengl.test.android.MovieSimpleActivity1"; + static String[] sys_pkgs = new String[] { "com.jogamp.common", "com.jogamp.opengl" }; + static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" }; + + @Override + public void init() { + final OrderedProperties props = getProperties(); + props.setProperty("jnlp.mplayer.nozoom", "true"); + props.setProperty("jnlp.mplayer.hud", "true"); + props.setProperty("jnlp.mplayer.hud.shared", "true"); + props.setProperty("jnlp.media0_url0", "http://archive.org/download/BigBuckBunny_328/BigBuckBunny_512kb.mp4"); + props.setProperty("jnlp.media1_url1", "http://archive.org/download/ElephantsDream/ed_1024_512kb.mp4"); + props.setProperty("jnlp.media0_url2", "file:///mnt/sdcard/Movies/BigBuckBunny_320x180.mp4"); + // props.setProperty("jogamp.debug.JNILibLoader", "true"); + // props.setProperty("jogamp.debug.NativeLibrary", "true"); + // props.setProperty("jogamp.debug.NativeLibrary.Lookup", "true"); + // props.setProperty("jogamp.debug.IOUtil", "true"); + // props.setProperty("nativewindow.debug", "all"); + // props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); + // props.setProperty("jogl.debug", "all"); + // props.setProperty("jogl.debug.GLProfile", "true"); + // props.setProperty("jogl.debug.GLDrawable", "true"); + // props.setProperty("jogl.debug.GLContext", "true"); + // props.setProperty("jogl.debug.GLMediaPlayer", "true"); + props.setProperty("jogl.debug.GLSLCode", "true"); + // props.setProperty("jogl.debug.CapabilitiesChooser", "true"); + // props.setProperty("jogl.debug.GLSLState", "true"); + // props.setProperty("jogl.debug.DebugGL", "true"); + // props.setProperty("jogl.debug.TraceGL", "true"); + // props.setProperty("newt.debug", "all"); + // props.setProperty("newt.debug.Window", "true"); + // props.setProperty("newt.debug.Window.MouseEvent", "true"); + // props.setProperty("newt.debug.Window.KeyEvent", "true"); + props.setProperty("jogamp.debug.IOUtil", "true"); + } + + @Override + public String getActivityName() { + return demo; + } + @Override + public List getSysPackages() { + return Arrays.asList(sys_pkgs); + } + + @Override + public List getUsrPackages() { + return Arrays.asList(usr_pkgs); + } +} diff --git a/src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivityLauncher01b.java b/src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivityLauncher01b.java new file mode 100644 index 000000000..35330b86b --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivityLauncher01b.java @@ -0,0 +1,87 @@ +/** + * 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.demos.android; + +import java.util.Arrays; +import java.util.List; + +import com.jogamp.opengl.demos.android.LauncherUtil.BaseActivityLauncher; +import com.jogamp.opengl.demos.android.LauncherUtil.OrderedProperties; + +public class MovieSimpleActivityLauncher01b extends LauncherUtil.BaseActivityLauncher { + + static String demo = "com.jogamp.opengl.test.android.MovieSimpleActivity1"; + static String[] sys_pkgs = new String[] { "com.jogamp.common", "com.jogamp.opengl" }; + static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" }; + + @Override + public void init() { + final OrderedProperties props = getProperties(); + props.setProperty("jnlp.mplayer.nozoom", "false"); + props.setProperty("jnlp.mplayer.hud", "true"); + props.setProperty("jnlp.mplayer.hud.shared", "true"); + props.setProperty("jnlp.media0_url0", "http://archive.org/download/BigBuckBunny_328/BigBuckBunny_512kb.mp4"); + props.setProperty("jnlp.media1_url1", "http://archive.org/download/ElephantsDream/ed_1024_512kb.mp4"); + props.setProperty("jnlp.media0_url2", "file:///mnt/sdcard/Movies/BigBuckBunny_320x180.mp4"); + // props.setProperty("jogamp.debug.JNILibLoader", "true"); + // props.setProperty("jogamp.debug.NativeLibrary", "true"); + // props.setProperty("jogamp.debug.NativeLibrary.Lookup", "true"); + // props.setProperty("jogamp.debug.IOUtil", "true"); + // props.setProperty("nativewindow.debug", "all"); + // props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); + // props.setProperty("jogl.debug", "all"); + // props.setProperty("jogl.debug.GLProfile", "true"); + // props.setProperty("jogl.debug.GLDrawable", "true"); + // props.setProperty("jogl.debug.GLContext", "true"); + // props.setProperty("jogl.debug.GLMediaPlayer", "true"); + props.setProperty("jogl.debug.GLSLCode", "true"); + // props.setProperty("jogl.debug.CapabilitiesChooser", "true"); + // props.setProperty("jogl.debug.GLSLState", "true"); + // props.setProperty("jogl.debug.DebugGL", "true"); + // props.setProperty("jogl.debug.TraceGL", "true"); + // props.setProperty("newt.debug", "all"); + // props.setProperty("newt.debug.Window", "true"); + // props.setProperty("newt.debug.Window.MouseEvent", "true"); + // props.setProperty("newt.debug.Window.KeyEvent", "true"); + props.setProperty("jogamp.debug.IOUtil", "true"); + } + + @Override + public String getActivityName() { + return demo; + } + @Override + public List getSysPackages() { + return Arrays.asList(sys_pkgs); + } + + @Override + public List getUsrPackages() { + return Arrays.asList(usr_pkgs); + } +} diff --git a/src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivityLauncher02.java b/src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivityLauncher02.java new file mode 100644 index 000000000..d7c064a28 --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/android/MovieSimpleActivityLauncher02.java @@ -0,0 +1,87 @@ +/** + * 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.demos.android; + +import java.util.Arrays; +import java.util.List; + +import com.jogamp.opengl.demos.android.LauncherUtil.BaseActivityLauncher; +import com.jogamp.opengl.demos.android.LauncherUtil.OrderedProperties; + +public class MovieSimpleActivityLauncher02 extends LauncherUtil.BaseActivityLauncher { + + static String demo = "com.jogamp.opengl.test.android.MovieSimpleActivity1"; + static String[] sys_pkgs = new String[] { "com.jogamp.common", "com.jogamp.opengl" }; + static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" }; + + @Override + public void init() { + final OrderedProperties props = getProperties(); + props.setProperty("jnlp.mplayer.nozoom", "false"); + props.setProperty("jnlp.mplayer.hud", "true"); + props.setProperty("jnlp.mplayer.hud.shared", "false"); + props.setProperty("jnlp.media0_url0", "http://archive.org/download/BigBuckBunny_328/BigBuckBunny_512kb.mp4"); + props.setProperty("jnlp.media1_url1", "http://archive.org/download/ElephantsDream/ed_1024_512kb.mp4"); + props.setProperty("jnlp.media0_url2", "file:///mnt/sdcard/Movies/BigBuckBunny_320x180.mp4"); + // props.setProperty("jogamp.debug.JNILibLoader", "true"); + // props.setProperty("jogamp.debug.NativeLibrary", "true"); + // props.setProperty("jogamp.debug.NativeLibrary.Lookup", "true"); + // props.setProperty("jogamp.debug.IOUtil", "true"); + // props.setProperty("nativewindow.debug", "all"); + // props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); + // props.setProperty("jogl.debug", "all"); + // props.setProperty("jogl.debug.GLProfile", "true"); + // props.setProperty("jogl.debug.GLDrawable", "true"); + // props.setProperty("jogl.debug.GLContext", "true"); + // props.setProperty("jogl.debug.GLMediaPlayer", "true"); + props.setProperty("jogl.debug.GLSLCode", "true"); + // props.setProperty("jogl.debug.CapabilitiesChooser", "true"); + // props.setProperty("jogl.debug.GLSLState", "true"); + // props.setProperty("jogl.debug.DebugGL", "true"); + // props.setProperty("jogl.debug.TraceGL", "true"); + // props.setProperty("newt.debug", "all"); + // props.setProperty("newt.debug.Window", "true"); + // props.setProperty("newt.debug.Window.MouseEvent", "true"); + // props.setProperty("newt.debug.Window.KeyEvent", "true"); + props.setProperty("jogamp.debug.IOUtil", "true"); + } + + @Override + public String getActivityName() { + return demo; + } + @Override + public List getSysPackages() { + return Arrays.asList(sys_pkgs); + } + + @Override + public List getUsrPackages() { + return Arrays.asList(usr_pkgs); + } +} diff --git a/src/demos/com/jogamp/opengl/demos/android/NEWTGearsES2Activity.java b/src/demos/com/jogamp/opengl/demos/android/NEWTGearsES2Activity.java new file mode 100644 index 000000000..8ab927487 --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/android/NEWTGearsES2Activity.java @@ -0,0 +1,134 @@ +/** + * Copyright 2011 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.demos.android; + +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.util.ArrayList; + +import com.jogamp.opengl.GLCapabilities; +import com.jogamp.opengl.GLProfile; +import com.jogamp.opengl.demos.es2.GearsES2; + +import jogamp.newt.driver.android.NewtBaseActivity; + +import com.jogamp.common.util.InterruptSource; +import com.jogamp.newt.event.MonitorEvent; +import com.jogamp.newt.event.MouseAdapter; +import com.jogamp.newt.event.MouseEvent; +import com.jogamp.newt.event.MonitorModeListener; +import com.jogamp.newt.opengl.GLWindow; + +import com.jogamp.opengl.util.Animator; + +import android.os.Bundle; +import android.util.Log; + +public class NEWTGearsES2Activity extends NewtBaseActivity { + static String TAG = "NEWTGearsES2Activity"; + + static final String forceRGBA5650 = "demo.force.rgba5650"; + static final String forceECT = "demo.force.ect"; + static final String forceKillProcessTest = "demo.force.killProcessTest"; + + @Override + public void onCreate(final Bundle savedInstanceState) { + Log.d(TAG, "onCreate - 0"); + super.onCreate(savedInstanceState); + + // create GLWindow (-> incl. underlying NEWT Display, Screen & Window) + final GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL2ES2)); + if( null != System.getProperty(forceRGBA5650) ) { + Log.d(TAG, "forceRGBA5650"); + caps.setRedBits(5); caps.setGreenBits(6); caps.setBlueBits(5); + } + + Log.d(TAG, "req caps: "+caps); + final GLWindow glWindow = GLWindow.create(caps); + glWindow.setFullscreen(true); + setContentView(getWindow(), glWindow); + + final GearsES2 demo = new GearsES2(-1); + // demo.enableAndroidTrace(true); + glWindow.addGLEventListener(demo); + glWindow.getScreen().addMonitorModeListener(new MonitorModeListener() { + @Override + public void monitorModeChangeNotify(final MonitorEvent me) { } + @Override + public void monitorModeChanged(final MonitorEvent me, final boolean success) { + System.err.println("MonitorMode Changed (success "+success+"): "+me); + } + }); + if( null != System.getProperty(forceKillProcessTest) ) { + Log.d(TAG, "forceKillProcessTest"); + glWindow.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(final MouseEvent e) { + if( e.getPointerCount() == 3 ) { + Log.d(TAG, "MemoryHog"); + new InterruptSource.Thread(null, new Runnable() { + @Override + public void run() { + final ArrayList buffers = new ArrayList(); + while(true) { + final int halfMB = 512 * 1024; + final float osizeMB = buffers.size() * 0.5f; + final float nsizeMB = osizeMB + 0.5f; + System.err.println("MemoryHog: ****** +4k: "+osizeMB+" MB +"+nsizeMB+" MB - Try"); + buffers.add(ByteBuffer.allocateDirect(halfMB)); // 0.5 MB each + System.err.println("MemoryHog: ****** +4k: "+osizeMB+" MB +"+nsizeMB+" MB - Done"); + try { + Thread.sleep(500); + } catch (final Exception e) { e.printStackTrace(); }; + } + } }, "MemoryHog").start(); + } else if( e.getPointerCount() == 4 ) { + Log.d(TAG, "ForceKill"); + android.os.Process.killProcess( android.os.Process.myPid() ); + } + } + }); + } + final Animator animator = new Animator(glWindow); + // animator.setRunAsFastAsPossible(true); + // glWindow.setSkipContextReleaseThread(animator.getThread()); + + if( null != System.getProperty(forceECT) ) { + Log.d(TAG, "forceECT"); + animator.setExclusiveContext(true); + } + + glWindow.setVisible(true); + + animator.setUpdateFPSFrames(60, System.err); + animator.resetFPSCounter(); + glWindow.resetFPSCounter(); + + Log.d(TAG, "onCreate - X"); + } +} diff --git a/src/demos/com/jogamp/opengl/demos/android/NEWTGearsES2ActivityLauncher.java b/src/demos/com/jogamp/opengl/demos/android/NEWTGearsES2ActivityLauncher.java new file mode 100644 index 000000000..a945baeab --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/android/NEWTGearsES2ActivityLauncher.java @@ -0,0 +1,84 @@ +/** + * 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.demos.android; + +import java.util.Arrays; +import java.util.List; + +import com.jogamp.opengl.demos.android.LauncherUtil.OrderedProperties; + +public class NEWTGearsES2ActivityLauncher extends LauncherUtil.BaseActivityLauncher { + + static String demo = "com.jogamp.opengl.test.android.NEWTGearsES2Activity"; + static String[] sys_pkgs = new String[] { "com.jogamp.common", "com.jogamp.opengl" }; + static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" }; + + @Override + public void init() { + final OrderedProperties props = getProperties(); + // props.setProperty("jogamp.debug.JNILibLoader", "true"); + // props.setProperty("jogamp.debug.NativeLibrary", "true"); + // props.setProperty("jogamp.debug.IOUtil", "true"); + // properties.setProperty("jogamp.debug.NativeLibrary.Lookup", "true"); + // props.setProperty("nativewindow.debug", "all"); + props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); + // props.setProperty("jogl.debug", "all"); + // properties.setProperty("jogl.debug.GLProfile", "true"); + props.setProperty("jogl.debug.EGLDisplayUtil", "true"); + // props.setProperty("jogl.debug.GLDrawable", "true"); + props.setProperty("jogl.debug.GLContext", "true"); + props.setProperty("jogl.debug.GLSLCode", "true"); + // props.setProperty("jogl.debug.CapabilitiesChooser", "true"); + // props.setProperty("jogl.debug.GLSLState", "true"); + // props.setProperty("jogl.debug.DebugGL", "true"); + // props.setProperty("jogl.debug.TraceGL", "true"); + // props.setProperty("newt.debug", "all"); + props.setProperty("newt.debug.Screen", "true"); + props.setProperty("newt.debug.Window", "true"); + props.setProperty("newt.debug.Window.MouseEvent", "true"); + props.setProperty("newt.debug.Window.KeyEvent", "true"); + // props.setProperty("newt.debug.Android.MouseEvent", "true"); + + // props.setProperty("demo.force.killProcessTest", "true"); + } + + @Override + public String getActivityName() { + return demo; + } + + @Override + public List getSysPackages() { + return Arrays.asList(sys_pkgs); + } + + @Override + public List getUsrPackages() { + return Arrays.asList(usr_pkgs); + } +} diff --git a/src/demos/com/jogamp/opengl/demos/android/NEWTGearsES2ECTActivityLauncher.java b/src/demos/com/jogamp/opengl/demos/android/NEWTGearsES2ECTActivityLauncher.java new file mode 100644 index 000000000..b627c6638 --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/android/NEWTGearsES2ECTActivityLauncher.java @@ -0,0 +1,80 @@ +/** + * 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.demos.android; + +import java.util.Arrays; +import java.util.List; + +import com.jogamp.opengl.demos.android.LauncherUtil.OrderedProperties; + +public class NEWTGearsES2ECTActivityLauncher extends LauncherUtil.BaseActivityLauncher { + + static String demo = "com.jogamp.opengl.test.android.NEWTGearsES2Activity"; + static String[] sys_pkgs = new String[] { "com.jogamp.common", "com.jogamp.opengl" }; + static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" }; + + @Override + public void init() { + final OrderedProperties props = getProperties(); + // props.setProperty("jogamp.debug.JNILibLoader", "true"); + // props.setProperty("jogamp.debug.NativeLibrary", "true"); + // props.setProperty("jogamp.debug.IOUtil", "true"); + // properties.setProperty("jogamp.debug.NativeLibrary.Lookup", "true"); + // props.setProperty("nativewindow.debug", "all"); + props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); + // props.setProperty("jogl.debug", "all"); + // properties.setProperty("jogl.debug.GLProfile", "true"); + // props.setProperty("jogl.debug.GLDrawable", "true"); + props.setProperty("jogl.debug.GLContext", "true"); + props.setProperty("jogl.debug.GLSLCode", "true"); + // props.setProperty("jogl.debug.CapabilitiesChooser", "true"); + // props.setProperty("jogl.debug.GLSLState", "true"); + // props.setProperty("jogl.debug.DebugGL", "true"); + // props.setProperty("jogl.debug.TraceGL", "true"); + // props.setProperty("newt.debug", "all"); + props.setProperty("newt.debug.Window", "true"); + props.setProperty("newt.debug.Window.MouseEvent", "true"); + props.setProperty("newt.debug.Window.KeyEvent", "true"); + + props.setProperty("demo.force.ect", "true"); + } + + @Override + public String getActivityName() { + return demo; + } + @Override + public List getSysPackages() { + return Arrays.asList(sys_pkgs); + } + + @Override + public List getUsrPackages() { + return Arrays.asList(usr_pkgs); + } +} diff --git a/src/demos/com/jogamp/opengl/demos/android/NEWTGearsES2RGB565ActivityLauncher.java b/src/demos/com/jogamp/opengl/demos/android/NEWTGearsES2RGB565ActivityLauncher.java new file mode 100644 index 000000000..5ab877b35 --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/android/NEWTGearsES2RGB565ActivityLauncher.java @@ -0,0 +1,80 @@ +/** + * 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.demos.android; + +import java.util.Arrays; +import java.util.List; + +import com.jogamp.opengl.demos.android.LauncherUtil.OrderedProperties; + +public class NEWTGearsES2RGB565ActivityLauncher extends LauncherUtil.BaseActivityLauncher { + + static String demo = "com.jogamp.opengl.test.android.NEWTGearsES2Activity"; + static String[] sys_pkgs = new String[] { "com.jogamp.common", "com.jogamp.opengl" }; + static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" }; + + @Override + public void init() { + final OrderedProperties props = getProperties(); + // props.setProperty("jogamp.debug.JNILibLoader", "true"); + // props.setProperty("jogamp.debug.NativeLibrary", "true"); + // props.setProperty("jogamp.debug.IOUtil", "true"); + // properties.setProperty("jogamp.debug.NativeLibrary.Lookup", "true"); + // props.setProperty("nativewindow.debug", "all"); + props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); + // props.setProperty("jogl.debug", "all"); + // properties.setProperty("jogl.debug.GLProfile", "true"); + // props.setProperty("jogl.debug.GLDrawable", "true"); + props.setProperty("jogl.debug.GLContext", "true"); + props.setProperty("jogl.debug.GLSLCode", "true"); + // props.setProperty("jogl.debug.CapabilitiesChooser", "true"); + // props.setProperty("jogl.debug.GLSLState", "true"); + // props.setProperty("jogl.debug.DebugGL", "true"); + // props.setProperty("jogl.debug.TraceGL", "true"); + // props.setProperty("newt.debug", "all"); + props.setProperty("newt.debug.Window", "true"); + props.setProperty("newt.debug.Window.MouseEvent", "true"); + props.setProperty("newt.debug.Window.KeyEvent", "true"); + + props.setProperty("demo.force.rgba5650", "true"); + } + + @Override + public String getActivityName() { + return demo; + } + @Override + public List getSysPackages() { + return Arrays.asList(sys_pkgs); + } + + @Override + public List getUsrPackages() { + return Arrays.asList(usr_pkgs); + } +} diff --git a/src/demos/com/jogamp/opengl/demos/android/NEWTGearsES2TransActivity.java b/src/demos/com/jogamp/opengl/demos/android/NEWTGearsES2TransActivity.java new file mode 100644 index 000000000..8d945aad0 --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/android/NEWTGearsES2TransActivity.java @@ -0,0 +1,88 @@ +/** + * Copyright 2011 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.demos.android; + +import com.jogamp.opengl.GLCapabilities; +import com.jogamp.opengl.GLProfile; +import com.jogamp.opengl.demos.es2.GearsES2; + +import jogamp.newt.driver.android.NewtBaseActivity; + +import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.Screen; +import com.jogamp.newt.event.MonitorEvent; +import com.jogamp.newt.event.MonitorModeListener; +import com.jogamp.newt.opengl.GLWindow; + +import com.jogamp.opengl.util.Animator; + +import android.os.Bundle; +import android.util.Log; + +public class NEWTGearsES2TransActivity extends NewtBaseActivity { + static String TAG = "NEWTGearsES2TransActivity"; + + @Override + public void onCreate(final Bundle savedInstanceState) { + Log.d(TAG, "onCreate - 0"); + super.onCreate(savedInstanceState); + + // create GLWindow (-> incl. underlying NEWT Display, Screen & Window) + final GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL2ES2)); + caps.setBackgroundOpaque(false); + + Log.d(TAG, "req caps: "+caps); + final Screen screen = NewtFactory.createScreen(NewtFactory.createDisplay(null), 0); + screen.addReference(); + final GLWindow glWindow = GLWindow.create(screen, caps); + glWindow.setSurfaceSize(2*screen.getWidth()/3, 2*screen.getHeight()/3); + glWindow.setUndecorated(true); + setContentView(getWindow(), glWindow); + + glWindow.addGLEventListener(new GearsES2(-1)); + glWindow.getScreen().addMonitorModeListener(new MonitorModeListener() { + @Override + public void monitorModeChangeNotify(final MonitorEvent me) { } + @Override + public void monitorModeChanged(final MonitorEvent me, final boolean success) { + System.err.println("MonitorMode Changed (success "+success+"): "+me); + } + }); + final Animator animator = new Animator(glWindow); + // glWindow.setSkipContextReleaseThread(animator.getThread()); + + glWindow.setVisible(true); + + animator.setUpdateFPSFrames(60, System.err); + animator.resetFPSCounter(); + glWindow.resetFPSCounter(); + + screen.removeReference(); + Log.d(TAG, "onCreate - X"); + } +} diff --git a/src/demos/com/jogamp/opengl/demos/android/NEWTGearsES2TransActivityLauncher.java b/src/demos/com/jogamp/opengl/demos/android/NEWTGearsES2TransActivityLauncher.java new file mode 100644 index 000000000..7a44a495b --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/android/NEWTGearsES2TransActivityLauncher.java @@ -0,0 +1,58 @@ +package com.jogamp.opengl.demos.android; + +import java.util.Arrays; +import java.util.List; + +import com.jogamp.opengl.demos.android.LauncherUtil.OrderedProperties; + +public class NEWTGearsES2TransActivityLauncher extends LauncherUtil.BaseActivityLauncher { + static String demo = "com.jogamp.opengl.test.android.NEWTGearsES2TransActivity"; + static String[] sys_pkgs = new String[] { "com.jogamp.common", "com.jogamp.opengl" }; + static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" }; + + @Override + public void init() { + final OrderedProperties props = getProperties(); + // props.setProperty("jnlp.android.translucent", "true"); + // props.setProperty("jogamp.debug.JNILibLoader", "true"); + // props.setProperty("jogamp.debug.NativeLibrary", "true"); + // properties.setProperty("jogamp.debug.NativeLibrary.Lookup", "true"); + // properties.setProperty("jogamp.debug.IOUtil", "true"); + // properties.setProperty("nativewindow.debug", "all"); + props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); + // properties.setProperty("jogl.debug", "all"); + // properties.setProperty("jogl.debug.GLProfile", "true"); + props.setProperty("jogl.debug.GLDrawable", "true"); + props.setProperty("jogl.debug.GLContext", "true"); + props.setProperty("jogl.debug.GLSLCode", "true"); + props.setProperty("jogl.debug.CapabilitiesChooser", "true"); + // properties.setProperty("jogl.debug.GLSLState", "true"); + // properties.setProperty("jogl.debug.DebugGL", "true"); + // properties.setProperty("jogl.debug.TraceGL", "true"); + // properties.setProperty("newt.debug", "all"); + props.setProperty("newt.debug.Window", "true"); + // properties.setProperty("newt.debug.Window.MouseEvent", "true"); + // properties.setProperty("newt.debug.Window.KeyEvent", "true"); + props.setProperty("jogamp.debug.IOUtil", "true"); + } + + @Override + public String getActivityName() { + return demo; + } + + @Override + public List getSysPackages() { + return Arrays.asList(sys_pkgs); + } + + @Override + public List getUsrPackages() { + return Arrays.asList(usr_pkgs); + } + + @Override + public String getAction() { + return LauncherUtil.LAUNCH_ACTIVITY_TRANSPARENT; + } +} diff --git a/src/demos/com/jogamp/opengl/demos/android/NEWTGraphUI1pActivity.java b/src/demos/com/jogamp/opengl/demos/android/NEWTGraphUI1pActivity.java new file mode 100644 index 000000000..ea512375f --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/android/NEWTGraphUI1pActivity.java @@ -0,0 +1,80 @@ +/** + * Copyright 2011 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.demos.android; + +import com.jogamp.opengl.GLCapabilities; +import com.jogamp.opengl.GLProfile; +import com.jogamp.opengl.demos.graph.ui.GPUUISceneGLListener0A; + +import jogamp.newt.driver.android.NewtBaseActivity; + +import com.jogamp.newt.event.MonitorEvent; +import com.jogamp.newt.event.MonitorModeListener; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.util.Animator; + +import android.os.Bundle; +import android.util.Log; + +public class NEWTGraphUI1pActivity extends NewtBaseActivity { + static String TAG = "NEWTGraphUIActivity"; + + @Override + public void onCreate(final Bundle savedInstanceState) { + Log.d(TAG, "onCreate - 0"); + super.onCreate(savedInstanceState); + + // create GLWindow (-> incl. underlying NEWT Display, Screen & Window) + final GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL2ES2)); + caps.setAlphaBits(4); + caps.setNumSamples(4); + caps.setSampleBuffers(true); + Log.d(TAG, "req caps: "+caps); + final GLWindow glWindow = GLWindow.create(caps); + glWindow.setFullscreen(true); + setContentView(getWindow(), glWindow); + + glWindow.addGLEventListener(new GPUUISceneGLListener0A(0)); + glWindow.getScreen().addMonitorModeListener(new MonitorModeListener() { + @Override + public void monitorModeChangeNotify(final MonitorEvent me) { } + @Override + public void monitorModeChanged(final MonitorEvent me, final boolean success) { + System.err.println("MonitorMode Changed (success "+success+"): "+me); + } + }); + glWindow.setVisible(true); + final Animator animator = new Animator(glWindow); + + animator.setUpdateFPSFrames(60, System.err); + animator.resetFPSCounter(); + glWindow.resetFPSCounter(); + + Log.d(TAG, "onCreate - X"); + } +} diff --git a/src/demos/com/jogamp/opengl/demos/android/NEWTGraphUI1pActivityLauncher.java b/src/demos/com/jogamp/opengl/demos/android/NEWTGraphUI1pActivityLauncher.java new file mode 100644 index 000000000..796cff268 --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/android/NEWTGraphUI1pActivityLauncher.java @@ -0,0 +1,52 @@ +package com.jogamp.opengl.demos.android; + +import java.util.Arrays; +import java.util.List; + +import com.jogamp.opengl.demos.android.LauncherUtil.BaseActivityLauncher; +import com.jogamp.opengl.demos.android.LauncherUtil.OrderedProperties; + +public class NEWTGraphUI1pActivityLauncher extends LauncherUtil.BaseActivityLauncher { + static String demo = "com.jogamp.opengl.test.android.NEWTGraphUI1pActivity"; + static String[] sys_pkgs = new String[] { "com.jogamp.common", "com.jogamp.opengl" }; + static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" }; + + @Override + public void init() { + final OrderedProperties props = getProperties(); + // props.setProperty("jogamp.debug.JNILibLoader", "true"); + // props.setProperty("jogamp.debug.NativeLibrary", "true"); + // props.setProperty("jogamp.debug.NativeLibrary.Lookup", "true"); + // props.setProperty("jogamp.debug.IOUtil", "true"); + // props.setProperty("nativewindow.debug", "all"); + props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); + // props.setProperty("jogl.debug", "all"); + // props.setProperty("jogl.debug.GLProfile", "true"); + props.setProperty("jogl.debug.GLDrawable", "true"); + props.setProperty("jogl.debug.GLContext", "true"); + props.setProperty("jogl.debug.GLSLCode", "true"); + props.setProperty("jogl.debug.CapabilitiesChooser", "true"); + // props.setProperty("jogl.debug.GLSLState", "true"); + // props.setProperty("jogl.debug.DebugGL", "true"); + // props.setProperty("jogl.debug.TraceGL", "true"); + // props.setProperty("newt.debug", "all"); + props.setProperty("newt.debug.Window", "true"); + // props.setProperty("newt.debug.Window.MouseEvent", "true"); + // props.setProperty("newt.debug.Window.KeyEvent", "true"); + } + + @Override + public String getActivityName() { + return demo; + } + + @Override + public List getSysPackages() { + return Arrays.asList(sys_pkgs); + } + + @Override + public List getUsrPackages() { + return Arrays.asList(usr_pkgs); + } +} diff --git a/src/demos/com/jogamp/opengl/demos/android/NEWTGraphUI2pActivity.java b/src/demos/com/jogamp/opengl/demos/android/NEWTGraphUI2pActivity.java new file mode 100644 index 000000000..ede8a5d31 --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/android/NEWTGraphUI2pActivity.java @@ -0,0 +1,79 @@ +/** + * Copyright 2011 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.demos.android; + +import com.jogamp.opengl.GLCapabilities; +import com.jogamp.opengl.GLProfile; +import com.jogamp.opengl.demos.graph.ui.GPUUISceneGLListener0A; + +import jogamp.newt.driver.android.NewtBaseActivity; + +import com.jogamp.graph.curve.Region; +import com.jogamp.newt.event.MonitorEvent; +import com.jogamp.newt.event.MonitorModeListener; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.util.Animator; + +import android.os.Bundle; +import android.util.Log; + +public class NEWTGraphUI2pActivity extends NewtBaseActivity { + static String TAG = "NEWTGraphUIActivity"; + + @Override + public void onCreate(final Bundle savedInstanceState) { + Log.d(TAG, "onCreate - 0"); + super.onCreate(savedInstanceState); + + // create GLWindow (-> incl. underlying NEWT Display, Screen & Window) + final GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL2ES2)); + caps.setAlphaBits(4); + Log.d(TAG, "req caps: "+caps); + final GLWindow glWindow = GLWindow.create(caps); + glWindow.setFullscreen(true); + setContentView(getWindow(), glWindow); + + glWindow.addGLEventListener(new GPUUISceneGLListener0A(Region.VBAA_RENDERING_BIT)); + glWindow.getScreen().addMonitorModeListener(new MonitorModeListener() { + @Override + public void monitorModeChangeNotify(final MonitorEvent me) { } + @Override + public void monitorModeChanged(final MonitorEvent me, final boolean success) { + System.err.println("MonitorMode Changed (success "+success+"): "+me); + } + }); + glWindow.setVisible(true); + final Animator animator = new Animator(glWindow); + + animator.setUpdateFPSFrames(60, System.err); + animator.resetFPSCounter(); + glWindow.resetFPSCounter(); + + Log.d(TAG, "onCreate - X"); + } +} diff --git a/src/demos/com/jogamp/opengl/demos/android/NEWTGraphUI2pActivityLauncher.java b/src/demos/com/jogamp/opengl/demos/android/NEWTGraphUI2pActivityLauncher.java new file mode 100644 index 000000000..3d6b7991d --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/android/NEWTGraphUI2pActivityLauncher.java @@ -0,0 +1,52 @@ +package com.jogamp.opengl.demos.android; + +import java.util.Arrays; +import java.util.List; + +import com.jogamp.opengl.demos.android.LauncherUtil.BaseActivityLauncher; +import com.jogamp.opengl.demos.android.LauncherUtil.OrderedProperties; + +public class NEWTGraphUI2pActivityLauncher extends LauncherUtil.BaseActivityLauncher { + static String demo = "com.jogamp.opengl.test.android.NEWTGraphUI2pActivity"; + static String[] sys_pkgs = new String[] { "com.jogamp.common", "com.jogamp.opengl" }; + static String[] usr_pkgs = new String[] { "com.jogamp.opengl.test" }; + + @Override + public void init() { + final OrderedProperties props = getProperties(); + // props.setProperty("jogamp.debug.JNILibLoader", "true"); + // props.setProperty("jogamp.debug.NativeLibrary", "true"); + // properties.setProperty("jogamp.debug.NativeLibrary.Lookup", "true"); + // properties.setProperty("jogamp.debug.IOUtil", "true"); + // properties.setProperty("nativewindow.debug", "all"); + props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); + // properties.setProperty("jogl.debug", "all"); + // properties.setProperty("jogl.debug.GLProfile", "true"); + props.setProperty("jogl.debug.GLDrawable", "true"); + props.setProperty("jogl.debug.GLContext", "true"); + props.setProperty("jogl.debug.GLSLCode", "true"); + props.setProperty("jogl.debug.CapabilitiesChooser", "true"); + // properties.setProperty("jogl.debug.GLSLState", "true"); + // properties.setProperty("jogl.debug.DebugGL", "true"); + // properties.setProperty("jogl.debug.TraceGL", "true"); + // properties.setProperty("newt.debug", "all"); + props.setProperty("newt.debug.Window", "true"); + // properties.setProperty("newt.debug.Window.MouseEvent", "true"); + // properties.setProperty("newt.debug.Window.KeyEvent", "true"); + } + + @Override + public String getActivityName() { + return demo; + } + + @Override + public List getSysPackages() { + return Arrays.asList(sys_pkgs); + } + + @Override + public List getUsrPackages() { + return Arrays.asList(usr_pkgs); + } +} diff --git a/src/demos/com/jogamp/opengl/demos/android/NEWTRedSquareES2Activity.java b/src/demos/com/jogamp/opengl/demos/android/NEWTRedSquareES2Activity.java new file mode 100644 index 000000000..1485fd3dd --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/android/NEWTRedSquareES2Activity.java @@ -0,0 +1,99 @@ +/** + * Copyright 2011 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.demos.android; + +import com.jogamp.opengl.GLCapabilities; +import com.jogamp.opengl.GLProfile; +import com.jogamp.opengl.demos.es2.RedSquareES2; + +import jogamp.newt.driver.android.NewtBaseActivity; + +import com.jogamp.newt.event.MonitorEvent; +import com.jogamp.newt.event.MonitorModeListener; +import com.jogamp.newt.opengl.GLWindow; + +import com.jogamp.opengl.util.Animator; + +import android.os.Bundle; +import android.util.Log; + +public class NEWTRedSquareES2Activity extends NewtBaseActivity { + static String TAG = "NEWTGearsES2Activity"; + + @Override + public void onCreate(final Bundle savedInstanceState) { + Log.d(TAG, "onCreate - 0"); + super.onCreate(savedInstanceState); + + // create GLWindow (-> incl. underlying NEWT Display, Screen & Window) + final GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL2ES2)); + Log.d(TAG, "req caps: "+caps); + final GLWindow glWindow = GLWindow.create(caps); + // glWindow.setSize(200, 200); + // glWindow.setUndecorated(true); + glWindow.setFullscreen(true); + setContentView(getWindow(), glWindow); + + final RedSquareES2 demo = new RedSquareES2(-1); + // demo.enableAndroidTrace(true); + glWindow.addGLEventListener(demo); + glWindow.getScreen().addMonitorModeListener(new MonitorModeListener() { + @Override + public void monitorModeChangeNotify(final MonitorEvent me) { } + @Override + public void monitorModeChanged(final MonitorEvent me, final boolean success) { + System.err.println("MonitorMode Changed (success "+success+"): "+me); + } + }); + final Animator animator = new Animator(glWindow); + // animator.setRunAsFastAsPossible(true); + // glWindow.setSkipContextReleaseThread(animator.getThread()); + glWindow.setVisible(true); + + animator.setUpdateFPSFrames(60, System.err); + animator.resetFPSCounter(); + glWindow.resetFPSCounter(); + + Log.d(TAG, "onCreate - X"); + } + + @Override + public void onResume() { + // android.os.Debug.startMethodTracing("GearsES2.trace"); + // android.os.Debug.startAllocCounting(); + super.onResume(); + } + + @Override + public void onPause() { + // android.os.Debug.stopAllocCounting(); + // android.os.Debug.stopMethodTracing(); + super.onPause(); + } + +} diff --git a/src/demos/com/jogamp/opengl/demos/android/NEWTRedSquareES2ActivityLauncher.java b/src/demos/com/jogamp/opengl/demos/android/NEWTRedSquareES2ActivityLauncher.java new file mode 100644 index 000000000..061953d5e --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/android/NEWTRedSquareES2ActivityLauncher.java @@ -0,0 +1,21 @@ +package com.jogamp.opengl.demos.android; + +import android.app.Activity; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.util.Log; + +public class NEWTRedSquareES2ActivityLauncher extends Activity { + @Override + public void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + final Uri uri = Uri.parse("launch://jogamp.org/com.jogamp.opengl.test.android.NEWTRedSquareES2Activity?sys=com.jogamp.common&sys=com.jogamp.opengl&pkg=com.jogamp.opengl.test"); + final Intent intent = new Intent("org.jogamp.launcher.action.LAUNCH_ACTIVITY_NORMAL", uri); + Log.d(getClass().getSimpleName(), "Launching Activity: "+intent); + startActivity (intent); + + finish(); // done + } +} diff --git a/src/demos/com/jogamp/opengl/demos/av/CrossFadePlayer.java b/src/demos/com/jogamp/opengl/demos/av/CrossFadePlayer.java new file mode 100644 index 000000000..a4d5e73de --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/av/CrossFadePlayer.java @@ -0,0 +1,212 @@ +/** + * 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.demos.av; + +import com.jogamp.common.net.Uri; +import com.jogamp.common.util.InterruptSource; +import com.jogamp.opengl.util.av.AudioSink; +import com.jogamp.opengl.util.av.GLMediaPlayer; +import com.jogamp.opengl.util.av.GLMediaPlayer.GLMediaEventListener; +import com.jogamp.opengl.util.av.GLMediaPlayer.StreamException; +import com.jogamp.opengl.util.av.GLMediaPlayerFactory; +import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame; + +import java.io.File; + +/** + * Parallel media player that demonstrate CrossFade of audio volume during playback. + * This also demonstrate audio only playback of the GLMediaPlayer. + */ +public class CrossFadePlayer +{ + static GLMediaPlayer[] player; + static volatile boolean stop = false; + + public static void main(final String[] args) + { + + if(args.length==0) { + System.out.println("No files! \n" + + "pass as many media files you want\n" + + "to the CrossFadePlayer arguments \n" + + "and i will try CrossFade-play them all in parallel!"); + } + + final GLMediaEventListener mediaEventListener = new GLMediaEventListener() + { + @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.out.println("\n***\nEvent mask changed: " + event_mask); + System.out.println("Timestamp: "+ when); + System.out.println("State of player: " + mp.getState().toString() +"\n"); + + if ((event_mask & GLMediaEventListener.EVENT_CHANGE_INIT) !=0) { + System.out.println("Duration: " + mp.getDuration() + "ms"); + System.out.println("Volume: " + mp.getAudioVolume()); + System.out.println("player.initGL()..."); + new InterruptSource.Thread() { + public void run() { + try { + mp.initGL(null); + if ( GLMediaPlayer.State.Paused == mp.getState() ) { // init OK + mp.play(); + } + } catch (final Exception e) { + e.printStackTrace(); + } + } + }.start(); + } else if ((event_mask & GLMediaEventListener.EVENT_CHANGE_PAUSE) !=0) { + System.out.println("player.paused()..."); + } else if ((event_mask & GLMediaEventListener.EVENT_CHANGE_PLAY) !=0) { + System.out.println("playing..."); + System.out.println(mp.toString()); + System.out.println(mp.getAudioSink().toString()); + } else if( 0 != ( GLMediaEventListener.EVENT_CHANGE_EOS & event_mask ) ) { + final StreamException se = mp.getStreamException(); + if( null != se ) { + System.err.println("Player State: EOS + Exception"); + stop = true; + } else { + System.err.println("Player State: EOS"); + new InterruptSource.Thread() { + public void run() { + System.out.println("mp.setPlaySpeed(1f) returned: " + mp.setPlaySpeed(1f)); + mp.seek(0); + mp.play(); + } + }.start(); + } + } + if( 0 != ( ( GLMediaEventListener.EVENT_CHANGE_ERR | GLMediaEventListener.EVENT_CHANGE_EOS ) & event_mask ) ) { + final StreamException se = mp.getStreamException(); + if( null != se ) { + se.printStackTrace(); + } + new InterruptSource.Thread() { + public void run() { + System.out.println("terminating..."); + stop = true; + } + }.start(); + } + + } + }; + + // Initialize media players + player = new GLMediaPlayer[args.length]; + int i=0; + for( final String arg: args ) { + player[i] = GLMediaPlayerFactory.createDefault(); + if(player[i]!=null){ + System.out.println("Created CrossFade player: "+ i + " " + player[i].getClass().getName()); + player[i].addEventListener(mediaEventListener); + try { + final String filename = arg; + if(filename.equals("")){ + System.out.println("No file selected: arg " + i +" = "+ filename); + player[i]=null; + } else { + final File file = new File(filename); + if(!file.exists()){ + System.out.println("File do not exist"); + } else { + final Uri uri = Uri.valueOf(file); + System.out.println("State of player "+ i +": " + player[i].getState().toString()); + System.out.println("...initializing stream "+ i +"..."); + player[i].initStream(uri, GLMediaPlayer.STREAM_ID_NONE, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.TEXTURE_COUNT_DEFAULT); + + } + } + } catch (final Exception e1) { + e1.printStackTrace(); + } + } else { + System.out.println("Failed to create player "+ i +"!"); + } + i++; + } + + + // Main thread CrossFade until playback is done + final long startTime = com.jogamp.common.os.Platform.currentTimeMillis(); + final double piPlayers = Math.PI*2.0f/args.length; + StreamException se = null; + while( null == se && stop == false ) { + try { + Thread.sleep(100); + } catch (final InterruptedException e) { } + + // Find out the longest duration... + float maxDuration = 1000.0f ; + for(final GLMediaPlayer p: player) { + if(p!=null){ + if( p.getDuration() > maxDuration) { + maxDuration = p.getDuration(); + } + } + } + + // tune the volume on players to crossfade! + final float progress = (com.jogamp.common.os.Platform.currentTimeMillis()-startTime)/maxDuration; + + i = 0; + for(final GLMediaPlayer p: player){ + if(p!=null){ + final AudioSink sink = p.getAudioSink(); + if(sink != null){ + final float volume = (float) (0.5f+(0.5f*(Math.cos(40.0f*progress+(piPlayers*i))))); + final float playbacktime = com.jogamp.common.os.Platform.currentTimeMillis()-startTime; + // System.out.println("player: "+ i +" volume = " + volume +" progress = "+ progress +" time = "+ playbacktime + " / duration = " + maxDuration); + sink.setVolume(volume); + } + + se = p.getStreamException(); + if( null != se) { + se.printStackTrace(); + throw new RuntimeException(se); + } + } + + i++; + } + } + + for(final GLMediaPlayer p: player) { + if(p!=null) + p.destroy(null); + } + System.out.println("...main exit..."); + } +} diff --git a/src/demos/com/jogamp/opengl/demos/av/MovieCube.java b/src/demos/com/jogamp/opengl/demos/av/MovieCube.java new file mode 100644 index 000000000..caf2f9381 --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/av/MovieCube.java @@ -0,0 +1,655 @@ +/** + * 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.demos.av; + +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; + +import com.jogamp.opengl.GL; +import com.jogamp.opengl.GL2ES2; +import com.jogamp.opengl.GLAnimatorControl; +import com.jogamp.opengl.GLAutoDrawable; +import com.jogamp.opengl.GLCapabilities; +import com.jogamp.opengl.GLEventListener; +import com.jogamp.opengl.GLException; +import com.jogamp.opengl.GLProfile; +import com.jogamp.opengl.GLRunnable; +import com.jogamp.common.net.Uri; +import com.jogamp.common.util.InterruptSource; +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.graph.font.FontScale; +import com.jogamp.junit.util.JunitTracer; +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.WindowAdapter; +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.demos.es2.TextureSequenceCubeES2; +import com.jogamp.opengl.demos.graph.TextRendererGLELBase; +import com.jogamp.opengl.demos.util.MiscUtils; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.av.GLMediaPlayer; +import com.jogamp.opengl.util.av.GLMediaPlayer.GLMediaEventListener; +import com.jogamp.opengl.util.av.GLMediaPlayer.StreamException; +import com.jogamp.opengl.util.av.GLMediaPlayerFactory; +import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame; + +/** + * Simple cube movie player w/ aspect ration true projection on a cube. + */ +public class MovieCube implements GLEventListener { + public static final float zoom_def = -2.77f; + private static boolean waitForKey = false; + private final float zoom0, rotx, roty; + private TextureSequenceCubeES2 cube=null; + private GLMediaPlayer mPlayer=null; + private int swapInterval = 1; + private boolean swapIntervalSet = true; + private long lastPerfPos = 0; + private volatile boolean resetGLState = false; + private volatile GLAutoDrawable autoDrawable = null; + + /** 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 = Uri.cast("http://archive.org/download/BigBuckBunny_328/BigBuckBunny_512kb.mp4"); + } catch (final URISyntaxException e) { + e.printStackTrace(); + } + defURI = _defURI; + } + + /** + * Default constructor which also issues {@link #initStream(URI, int, int, int)} w/ default values + * and polls until the {@link GLMediaPlayer} is {@link GLMediaPlayer.State#Initialized}. + * If {@link GLMediaEventListener#EVENT_CHANGE_EOS} is reached, the stream is started over again. + *

+ * This default constructor is merely useful for some drop-in test, e.g. using an applet. + *

+ */ + public MovieCube() throws IOException, URISyntaxException { + this(zoom_def, 0f, 0f, true); + + mPlayer.addEventListener(new GLMediaEventListener() { + @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("MovieCube AttributesChanges: events_mask 0x"+Integer.toHexString(event_mask)+", when "+when); + System.err.println("MovieCube State: "+mp); + if( 0 != ( GLMediaEventListener.EVENT_CHANGE_SIZE & event_mask ) ) { + resetGLState(); + } + if( 0 != ( GLMediaEventListener.EVENT_CHANGE_EOS & event_mask ) ) { + new InterruptSource.Thread() { + @Override + public void run() { + // loop for-ever .. + mPlayer.seek(0); + mPlayer.play(); + } }.start(); + } + } + }); + initStream(defURI, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.TEXTURE_COUNT_DEFAULT); + StreamException se = null; + while( null == se && GLMediaPlayer.State.Initialized != mPlayer.getState() ) { + try { + Thread.sleep(16); + } catch (final InterruptedException e) { } + se = mPlayer.getStreamException(); + } + if( null != se ) { + se.printStackTrace(); + throw new RuntimeException(se); + } + } + + /** + * Custom constructor, user needs to issue {@link #initStream(URI, int, int, int)} afterwards. + */ + public MovieCube(final float zoom0, final float rotx, final float roty, final boolean showText) throws IOException { + this.zoom0 = zoom0; + this.rotx = rotx; + this.roty = roty; + this.showText = showText; + screenshot = new GLReadBufferUtil(false, false); + mPlayer = GLMediaPlayerFactory.createDefault(); + } + + 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 void setSwapInterval(final int v) { this.swapInterval = v; } + + public GLMediaPlayer getGLMediaPlayer() { return mPlayer; } + + public void resetGLState() { + resetGLState = true; + } + + final int[] textSampleCount = { 4 }; + + private final class InfoTextRendererGLELBase extends TextRendererGLELBase { + private static final float z_diff = 0.001f; + private final Font font = getFont(0, 0, 0); + private final float fontSize1 = 12; + private final float fontSize2 = 10; + private final GLRegion regionFPS; + private float pixelSize1, pixelSize2, underlineSize; + + InfoTextRendererGLELBase(final GLProfile glp, final int rmode, final boolean lowPerfDevice) { + // FIXME: Graph TextRenderer does not AA well w/o MSAA and FBO + super(rmode, MovieCube.this.textSampleCount); + this.setRendererCallbacks(RegionRenderer.defaultBlendEnable, RegionRenderer.defaultBlendDisable); + if( lowPerfDevice ) { + regionFPS = null; + } else { + regionFPS = GLRegion.create(glp, renderModes, null); + System.err.println("RegionFPS "+Region.getRenderModeString(renderModes)+", sampleCount "+textSampleCount[0]+", class "+regionFPS.getClass().getName()); + } + staticRGBAColor[0] = 0.1f; + staticRGBAColor[1] = 0.1f; + staticRGBAColor[2] = 0.1f; + staticRGBAColor[3] = 1.0f; + } + + @Override + public void init(final GLAutoDrawable drawable) { + // non-exclusive mode! + this.setSharedPMVMatrix(cube.pmvMatrix); + super.init(drawable); + + autoDrawable = drawable; + + pixelSize1 = FontScale.toPixels(fontSize1, dpiH); + pixelSize2 = FontScale.toPixels(fontSize2, dpiH); + pixelScale = 1.0f / ( pixelSize1 * 20f ); + // underlineSize: 'underline' amount of pixel below 0/0 (Note: lineGap is negative) + final Font.Metrics metrics = font.getMetrics(); + final float lineGap = pixelSize1 * metrics.getLineGap(); + final float descent = pixelSize1 * metrics.getDescent(); + underlineSize = lineGap - descent; + System.err.println("XXX: dpiH "+dpiH+", fontSize "+fontSize1+", pixelSize "+pixelSize1+", pixelScale "+pixelScale+", fLG "+lineGap+", fDesc "+descent+", underlineSize "+underlineSize); + } + + @Override + public void dispose(final GLAutoDrawable drawable) { + autoDrawable = null; + screenshot.dispose(drawable.getGL()); + 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 [ -1 .. 1 ] + + // dy: position right above video rectangle (bottom text line) + final float aspect = (float)mPlayer.getWidth() / (float)mPlayer.getHeight(); + final float aspect_h = 1f/aspect; + final float dy = 1f-aspect_h; + + // yoff1: position right above video rectangle (bottom text line) + // less than underlineSize, so 'underline' pixels are above video. + final float yoff1 = dy-(pixelScale*underlineSize); + + // yoff2: position right below video rectangle (bottom text line) + final float yoff2 = 2f-dy; + + /** + System.err.println("XXX: a "+aspect+", aspect_h "+aspect_h+", dy "+dy+ + "; underlineSize "+underlineSize+" "+(pixelScale*underlineSize)+ + "; yoff "+yoff1+", yoff2 "+yoff2); */ + + final GL gl = drawable.getGL(); + 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, v-sync %d", + pts, mPlayer.getDuration() / 1000f, + mPlayer.getState().toString().toLowerCase(), mPlayer.getPlaySpeed(), mPlayer.getAudioVolume(), + aspect, mPlayer.getFramerate(), lfps, tfps, swapInterval); + 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().path.decode(); + if( displayOSD && null != renderer ) { + gl.glClearColor(1.0f, 1.0f, 1.0f, 0.0f); + if( null != regionFPS ) { + renderString(drawable, font, pixelSize1, text1, 1 /* col */, -1 /* row */, -1+z_diff, yoff1, 1f+z_diff, regionFPS.clear(gl.getGL2ES2())); // no-cache + } else { + renderString(drawable, font, pixelSize1, text1, 1 /* col */, -1 /* row */, -1+z_diff, yoff1, 1f+z_diff, true); + } + renderString(drawable, font, pixelSize2, text2, 1 /* col */, 0 /* row */, -1+z_diff, yoff2, 1f+z_diff, true); + renderString(drawable, font, pixelSize2, text3, 1 /* col */, 1 /* row */, -1+z_diff, yoff2, 1f+z_diff, true); + renderString(drawable, font, pixelSize2, text4, 1 /* col */, 2 /* row */, -1+z_diff, yoff2, 1f+z_diff, true); + } + } }; + private InfoTextRendererGLELBase textRendererGLEL = null; + final boolean showText; + private boolean displayOSD = true; + + public void printScreen(final GLAutoDrawable drawable) throws GLException, IOException { + final String filename = String.format("MovieCube-snap%02d-%03dx%03d.png", screenshot_num++, drawable.getSurfaceWidth(), drawable.getSurfaceHeight()); + if(screenshot.readPixels(drawable.getGL(), false)) { + screenshot.write(new File(filename.toString())); + } + } + private final GLReadBufferUtil screenshot; + private int screenshot_num = 0; + + public void printScreenOnGLThread(final GLAutoDrawable drawable) { + drawable.invoke(false, new GLRunnable() { + @Override + public boolean run(final GLAutoDrawable drawable) { + try { + printScreen(drawable); + } catch (final GLException e) { + e.printStackTrace(); + } catch (final IOException e) { + e.printStackTrace(); + } + return true; + } + }); + } + + private final KeyListener keyAction = new KeyAdapter() { + @Override + 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_V: { + switch(swapInterval) { + case 0: swapInterval = -1; break; + case -1: swapInterval = 1; break; + case 1: swapInterval = 0; break; + default: swapInterval = 1; break; + } + swapIntervalSet = true; + break; + } + 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; + case KeyEvent.VK_S: + if(null != autoDrawable) { + printScreenOnGLThread(autoDrawable); + } + break; + } + + if( 0 != pts1 ) { + mPlayer.seek(pts1); + } + } + }; + + @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); + } + if( GLMediaPlayer.STREAM_ID_NONE == mPlayer.getVID() ) { + // throw new IllegalStateException("mPlayer has no VID/stream selected: "+mPlayer); + } + resetGLState = false; + + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + System.err.println(JoglVersion.getGLInfo(gl, null)); + + cube = new TextureSequenceCubeES2(mPlayer, false, zoom0, rotx, roty); + + if(waitForKey) { + JunitTracer.waitForKey("Init>"); + } + + if( GLMediaPlayer.State.Initialized == mPlayer.getState() ) { + try { + mPlayer.initGL(gl); + } catch (final Exception e) { + e.printStackTrace(); + if(null != mPlayer) { + mPlayer.destroy(gl); + mPlayer = null; + } + throw new GLException(e); + } + } + cube.init(drawable); + mPlayer.play(); + System.out.println("play.0 "+mPlayer); + + boolean added; + final Object upstreamWidget = drawable.getUpstreamWidget(); + if (upstreamWidget instanceof Window) { + final Window window = (Window) upstreamWidget; + window.addKeyListener(keyAction); + added = true; + } else { added = false; } + System.err.println("MC.init: kl-added "+added+", "+drawable.getClass().getName()); + + if( showText ) { + final int rmode = drawable.getChosenGLCapabilities().getSampleBuffers() ? 0 : Region.VBAA_RENDERING_BIT; + final boolean lowPerfDevice = gl.isGLES(); + textRendererGLEL = new InfoTextRendererGLELBase(gl.getGLProfile(), rmode, lowPerfDevice); + drawable.addGLEventListener(textRendererGLEL); + } + } + + @Override + public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { + if(null == mPlayer) { return; } + cube.reshape(drawable, x, y, width, height); + } + + @Override + public void dispose(final GLAutoDrawable drawable) { + System.err.println(Thread.currentThread()+" MovieCube.dispose ... "); + if( null != textRendererGLEL ) { + drawable.disposeGLEventListener(textRendererGLEL, true); + 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.removeKeyListener(keyAction); + } + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + if( disposePlayer ) { + mPlayer.destroy(gl); + mPlayer=null; + } + cube.dispose(drawable); + cube=null; + } + + + @Override + public void display(final GLAutoDrawable drawable) { + if( swapIntervalSet ) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + final int _swapInterval = swapInterval; + gl.setSwapInterval(_swapInterval); // in case switching the drawable (impl. may bound attribute there) + drawable.getAnimator().resetFPSCounter(); + swapInterval = gl.getSwapInterval(); + System.err.println("Swap Interval: "+_swapInterval+" -> "+swapInterval); + swapIntervalSet = false; + } + 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; + } + cube.display(drawable); + } + + public static void main(final String[] args) throws IOException, InterruptedException, URISyntaxException { + int swapInterval = 1; + int width = 800; + int height = 600; + int textureCount = GLMediaPlayer.TEXTURE_COUNT_DEFAULT; // default - threaded + + boolean forceES2 = false; + boolean forceES3 = false; + boolean forceGL3 = false; + boolean forceGLDef = false; + int vid = GLMediaPlayer.STREAM_ID_AUTO; + int aid = GLMediaPlayer.STREAM_ID_AUTO; + final boolean origSize; + + String url_s=null, file_s=null; + { + boolean _origSize = false; + for(int i=0; i + * 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. + *

+ */ +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 = Uri.cast("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 GLProfile glp, 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(glp, 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().path.decode(); + if( displayOSD && null != renderer ) { + // We share ClearColor w/ MovieSimple's init ! + final float pixelSize = FontScale.toPixels(fontSize, dpiH); + if( null != regionFPS ) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + renderString(drawable, font, pixelSize, text1, 1 /* col */, 1 /* row */, 0, 0, -1, regionFPS.clear(gl)); // 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 final boolean enableTextRendererGLEL = false; + private InfoTextRendererGLELBase textRendererGLEL = null; + private boolean displayOSD = false; + + private final MouseListener mouseAction = new MouseAdapter() { + @Override + 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(); + } + } + } + @Override + public void mouseReleased(final MouseEvent e) { + if(e.getY()<=surfHeight/2) { + rotate = -1; + zoom = zoom0; + System.err.println("zoom: "+zoom); + } + } + @Override + public void mouseMoved(final MouseEvent e) { + prevMouseX = e.getX(); + // prevMouseY = e.getY(); + } + @Override + 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; + } + @Override + 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() { + @Override + 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()); + 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) { + JunitTracer.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(); + if( enableTextRendererGLEL ) { + textRendererGLEL = new InfoTextRendererGLELBase(gl.getGLProfile(), rmode, lowPerfDevice); + textRendererGLEL.init(drawable); + } else { + textRendererGLEL = null; + } + } + + 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); + if( null != textRendererGLEL ) { + textRendererGLEL.reshape(drawable, 0, 0, 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; + + private static final float[] vec3ScalePos = new float[] { 4f, 4f, 4f }; + + @Override + public void reshapeForEye(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height, + final EyeParameter eyeParam, final ViewerPose viewerPose) { + 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, viewerPose.position, 0); + VectorUtil.scaleVec3(shiftedEyePos, shiftedEyePos, vec3ScalePos); // amplify viewerPose position + VectorUtil.addVec3(shiftedEyePos, shiftedEyePos, eyeParam.positionOffset); + + rollPitchYaw.mult(viewerPose.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); + if( null != textRendererGLEL ) { + textRendererGLEL.reshape(drawable, 0, 0, width, height); + } + } + + @Override + public void dispose(final GLAutoDrawable drawable) { + if( null != textRendererGLEL ) { + 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(); + + if( null != textRendererGLEL ) { + textRendererGLEL.display(drawable); + } + } + + static class StereoGLMediaEventListener implements GLMediaEventListener { + void destroyWindow(final Window window) { + new InterruptSource.Thread() { + @Override + 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 InterruptSource.Thread() { + @Override + 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/demos/com/jogamp/opengl/demos/av/MovieSimple.java b/src/demos/com/jogamp/opengl/demos/av/MovieSimple.java new file mode 100644 index 000000000..42c7b94a5 --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/av/MovieSimple.java @@ -0,0 +1,1123 @@ +/** + * 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.demos.av; + +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.FloatBuffer; + +import com.jogamp.common.net.Uri; +import com.jogamp.common.os.Platform; +import com.jogamp.common.util.InterruptSource; +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.graph.font.FontScale; +import com.jogamp.junit.util.JunitTracer; +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.event.WindowAdapter; +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.GL; +import com.jogamp.opengl.GL2ES2; +import com.jogamp.opengl.GLAnimatorControl; +import com.jogamp.opengl.GLAutoDrawable; +import com.jogamp.opengl.GLCapabilities; +import com.jogamp.opengl.GLES2; +import com.jogamp.opengl.GLEventListener; +import com.jogamp.opengl.GLException; +import com.jogamp.opengl.GLExtensions; +import com.jogamp.opengl.GLProfile; +import com.jogamp.opengl.GLRunnable; +import com.jogamp.opengl.GLUniformData; +import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.demos.graph.TextRendererGLELBase; +import com.jogamp.opengl.demos.util.MiscUtils; +import com.jogamp.opengl.fixedfunc.GLMatrixFunc; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.GLArrayDataServer; +import com.jogamp.opengl.util.GLReadBufferUtil; +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.GLMediaPlayer.StreamException; +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.texture.Texture; +import com.jogamp.opengl.util.texture.TextureCoords; +import com.jogamp.opengl.util.texture.TextureSequence; +import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame; + +/** + * Simple planar movie player w/ orthogonal 1:1 projection. + */ +public class MovieSimple implements GLEventListener { + public static final int EFFECT_NORMAL = 0; + public static final int EFFECT_GRADIENT_BOTTOM2TOP = 1<<1; + public static final int EFFECT_TRANSPARENT = 1<<3; + + public static final String WINDOW_KEY = "window"; + public static final String PLAYER = "player"; + + private static boolean waitForKey = false; + private int surfWidth, surfHeight; + private int prevMouseX; // , prevMouseY; + private int rotate = 0; + private boolean orthoProjection = true; + private float nearPlaneNormalized; + private float zoom0; + private float zoom1; + private float zoom; + private long startTime; + private int effects = EFFECT_NORMAL; + private float alpha = 1.0f; + private int swapInterval = 1; + private boolean swapIntervalSet = true; + + private GLMediaPlayer mPlayer; + private final boolean mPlayerShared; + private boolean mPlayerScaleOrig; + private float[] verts = null; + private GLArrayDataServer interleavedVBO; + private volatile boolean resetGLState = false; + + private volatile GLAutoDrawable autoDrawable = null; + + 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 = Uri.cast("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 = 10f; + private final GLRegion regionFPS; + + InfoTextRendererGLELBase(final GLProfile glp, 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(glp, 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 = 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, v-sync %b", + pts, mPlayer.getDuration() / 1000f, + mPlayer.getState().toString().toLowerCase(), mPlayer.getPlaySpeed(), mPlayer.getAudioVolume(), + aspect, mPlayer.getFramerate(), lfps, tfps, swapIntervalSet); + 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().path.decode(); + if( displayOSD && null != renderer ) { + // We share ClearColor w/ MovieSimple's init ! + final float pixelSize = FontScale.toPixels(fontSize, dpiH); + if( null != regionFPS ) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + renderString(drawable, font, pixelSize, text1, 1 /* col */, 1 /* row */, 0, 0, -1, regionFPS.clear(gl)); // 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, -1, true); + renderString(drawable, font, pixelSize, text4, 1 /* col */, -2 /* row */, 0, height, -1, true); + } + } }; + private InfoTextRendererGLELBase textRendererGLEL = null; + private boolean displayOSD = true; + + public void printScreen(final GLAutoDrawable drawable) throws GLException, IOException { + final String filename = String.format("MovieSimple-snap%02d-%03dx%03d.png", screenshot_num++, drawable.getSurfaceWidth(), drawable.getSurfaceHeight()); + if(screenshot.readPixels(drawable.getGL(), false)) { + screenshot.write(new File(filename.toString())); + } + } + private final GLReadBufferUtil screenshot; + private int screenshot_num = 0; + + public void printScreenOnGLThread(final GLAutoDrawable drawable) { + drawable.invoke(false, new GLRunnable() { + @Override + public boolean run(final GLAutoDrawable drawable) { + try { + printScreen(drawable); + } catch (final GLException e) { + e.printStackTrace(); + } catch (final IOException e) { + e.printStackTrace(); + } + return true; + } + }); + } + + private final MouseListener mouseAction = new MouseAdapter() { + @Override + 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(); + } + } + } + @Override + public void mouseReleased(final MouseEvent e) { + if(e.getY()<=surfHeight/2) { + rotate = -1; + zoom = zoom0; + System.err.println("zoom: "+zoom); + } + } + @Override + public void mouseMoved(final MouseEvent e) { + prevMouseX = e.getX(); + // prevMouseY = e.getY(); + } + @Override + 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; + } + @Override + 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() { + @Override + 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_V: { + switch(swapInterval) { + case 0: swapInterval = -1; break; + case -1: swapInterval = 1; break; + case 1: swapInterval = 0; break; + default: swapInterval = 1; break; + } + swapIntervalSet = true; + break; + } + 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; + case KeyEvent.VK_S: + if(null != autoDrawable) { + printScreenOnGLThread(autoDrawable); + } + break; + } + + if( 0 != pts1 ) { + mPlayer.seek(pts1); + } + } }; + + /** + * Default constructor which also issues {@link #initStream(URI, int, int, int)} w/ default values + * and polls until the {@link GLMediaPlayer} is {@link GLMediaPlayer.State#Initialized}. + * If {@link GLMediaEventListener#EVENT_CHANGE_EOS} is reached, the stream is started over again. + *

+ * This default constructor is merely useful for some drop-in test, e.g. using an applet. + *

+ */ + public MovieSimple() { + this(null); + + mPlayer.addEventListener(new GLMediaEventListener() { + @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("MovieCube AttributesChanges: events_mask 0x"+Integer.toHexString(event_mask)+", when "+when); + System.err.println("MovieCube State: "+mp); + if( 0 != ( GLMediaEventListener.EVENT_CHANGE_SIZE & event_mask ) ) { + resetGLState(); + } + if( 0 != ( GLMediaEventListener.EVENT_CHANGE_EOS & event_mask ) ) { + new InterruptSource.Thread() { + @Override + public void run() { + // loop for-ever .. + mPlayer.seek(0); + mPlayer.play(); + } }.start(); + } + } + }); + initStream(defURI, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, 3 /* textureCount */); + StreamException se = null; + while( null == se && GLMediaPlayer.State.Initialized != mPlayer.getState() ) { + try { + Thread.sleep(16); + } catch (final InterruptedException e) { } + se = mPlayer.getStreamException(); + } + if( null != se ) { + se.printStackTrace(); + throw new RuntimeException(se); + } + } + + /** Custom constructor, user needs to issue {@link #initStream(URI, int, int, int)} afterwards. */ + public MovieSimple(final GLMediaPlayer sharedMediaPlayer) throws IllegalStateException { + screenshot = new GLReadBufferUtil(false, false); + mPlayer = sharedMediaPlayer; + mPlayerScaleOrig = false; + mPlayerShared = null != mPlayer; + if( !mPlayerShared ) { + mPlayer = GLMediaPlayerFactory.createDefault(); + mPlayer.attachObject(PLAYER, this); + } + System.out.println("pC.1a shared "+mPlayerShared+", "+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 void setSwapInterval(final int v) { this.swapInterval = v; } + + public GLMediaPlayer getGLMediaPlayer() { return mPlayer; } + + public void setScaleOrig(final boolean v) { + mPlayerScaleOrig = v; + } + + /** defaults to true */ + public void setOrthoProjection(final boolean v) { orthoProjection=v; } + public boolean getOrthoProjection() { return orthoProjection; } + + public boolean hasEffect(final int e) { return 0 != ( effects & e ) ; } + public void setEffects(final int e) { effects = e; }; + public void setTransparency(final float alpha) { + this.effects |= EFFECT_TRANSPARENT; + this.alpha = alpha; + } + + 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, MovieSimple.class, + "../shader", "../shader/bin", shaderBasename, true); + final ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, MovieSimple.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()); + 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 = orthoProjection ? 0f : -2.5f; + zoom1 = orthoProjection ? 0f : -5f; + zoom = zoom0; + + autoDrawable = drawable; + + 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) { + JunitTracer.waitForKey("Init>"); + } + final Texture tex; + try { + System.out.println("p0 "+mPlayer+", shared "+mPlayerShared); + if(!mPlayerShared && GLMediaPlayer.State.Initialized == mPlayer.getState() ) { + mPlayer.initGL(gl); + } + System.out.println("p1 "+mPlayer+", shared "+mPlayerShared); + 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); + } + } + if(!mPlayerShared) { + mPlayer.setTextureMinMagFilter( new int[] { GL.GL_NEAREST, GL.GL_LINEAR } ); + } + } catch (final Exception glex) { + glex.printStackTrace(); + if(!mPlayerShared && 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(orthoProjection) { + if(mPlayerScaleOrig && mWidth < dWidth && mHeight < dHeight) { + xs = mWidth/2f; ys = xs / mAspect; + } else { + xs = dWidth/2f; ys = xs / mAspect; // w>h + } + } else { + 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]); + } + + interleavedVBO = GLArrayDataServer.createGLSLInterleaved(3+4+2, GL.GL_FLOAT, false, 3*4, GL.GL_STATIC_DRAW); + { + interleavedVBO.addGLSLSubArray("mgl_Vertex", 3, GL.GL_ARRAY_BUFFER); + interleavedVBO.addGLSLSubArray("mgl_Color", 4, GL.GL_ARRAY_BUFFER); + interleavedVBO.addGLSLSubArray("mgl_MultiTexCoord", 2, GL.GL_ARRAY_BUFFER); + } + updateInterleavedVBO(gl, tex); + + st.ownAttribute(interleavedVBO, 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("iVBO: "+interleavedVBO); + System.out.println(st); + } + + if(!mPlayerShared) { + 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(gl.getGLProfile(), rmode, lowPerfDevice); + drawable.addGLEventListener(textRendererGLEL); + } + + protected void updateInterleavedVBO(final GL gl, final Texture tex) { + final float ss = 1f, ts = 1f; // scale tex-coord + final boolean wasEnabled = interleavedVBO.enabled(); + interleavedVBO.seal(gl, false); + interleavedVBO.rewind(); + { + final FloatBuffer ib = (FloatBuffer)interleavedVBO.getBuffer(); + final TextureCoords tc = tex.getImageTexCoords(); + System.err.println("XXX0: "+tc); + 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]); + if( hasEffect(EFFECT_GRADIENT_BOTTOM2TOP) ) { + ib.put( 0); ib.put( 0); ib.put( 0); ib.put(alpha); + } else { + ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha); + } + ib.put( tc.left() *ss); ib.put( tc.bottom() *ts); + + // right-bottom + ib.put(verts[3]); ib.put(verts[1]); ib.put(verts[2]); + if( hasEffect(EFFECT_GRADIENT_BOTTOM2TOP) ) { + ib.put( 0); ib.put( 0); ib.put( 0); ib.put(alpha); + } else { + ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha); + } + ib.put( tc.right() *ss); ib.put( tc.bottom() *ts); + + // 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); + ib.put( tc.left() *ss); ib.put( tc.top() *ts); + + // 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); + ib.put( tc.right() *ss); ib.put( tc.top() *ts); + } + interleavedVBO.seal(gl, true); + if( !wasEnabled ) { + interleavedVBO.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(); + if(null == mPlayer) { return; } + surfWidth = width; + surfHeight = height; + + if(null != st) { + reshapePMV(width, height); + st.useProgram(gl, true); + st.uniform(gl, pmvMatrixUniform); + st.useProgram(gl, false); + } + + 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(); + if(orthoProjection) { + final float fw = width / 2f; + final float fh = height/ 2f; + pmvMatrix.glOrthof(-fw, fw, -fh, fh, -1.0f, 1.0f); + nearPlaneNormalized = 0f; + } else { + pmvMatrix.gluPerspective(45.0f, (float)width / (float)height, zNear, zFar); + nearPlaneNormalized = 1f/(10f-1f); + } + System.err.println("XXX0: Perspective nearPlaneNormalized: "+nearPlaneNormalized); + + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glTranslatef(0, 0, zoom0); + } + + @Override + public void dispose(final GLAutoDrawable drawable) { + autoDrawable = null; + drawable.disposeGLEventListener(textRendererGLEL, true); + textRendererGLEL = null; + screenshot.dispose(drawable.getGL()); + 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 ) { + if(!mPlayerShared) { + 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) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + if( swapIntervalSet ) { + final int _swapInterval = swapInterval; + gl.setSwapInterval(_swapInterval); // in case switching the drawable (impl. may bound attribute there) + drawable.getAnimator().resetFPSCounter(); + swapInterval = gl.getSwapInterval(); + System.err.println("Swap Interval: "+_swapInterval+" -> "+swapInterval); + swapIntervalSet = false; + } + 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; + } + + 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.glLoadIdentity(); + 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); + interleavedVBO.enableBuffer(gl, true); + Texture tex = null; + if(null!=mPlayer) { + final TextureSequence.TextureFrame texFrame; + if( mPlayerShared ) { + 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); + } + interleavedVBO.enableBuffer(gl, false); + st.useProgram(gl, false); + } + + static class MyGLMediaEventListener implements GLMediaEventListener { + void destroyWindow(final Window window) { + new InterruptSource.Thread() { + @Override + 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 MovieSimple ms = (MovieSimple)mp.getAttachedObject(PLAYER); + if( 0 != ( GLMediaEventListener.EVENT_CHANGE_SIZE & event_mask ) ) { + System.err.println("MovieSimple State: CHANGE_SIZE"); + if( origSize ) { + window.setSurfaceSize(mp.getWidth(), mp.getHeight()); + } + // 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] + window.addGLEventListener(ms); + final GLAnimatorControl anim = window.getAnimator(); + anim.setUpdateFPSFrames(60, null); + anim.resetFPSCounter(); + /** + * Kick off player w/o GLEventListener, i.e. for audio only. + * + new InterruptSource.Thread() { + public void run() { + try { + mp.initGL(null); + if ( GLMediaPlayer.State.Paused == mp.getState() ) { // init OK + mp.play(); + } + System.out.println("play.1 "+mp); + } catch (Exception e) { + e.printStackTrace(); + destroyWindow(); + return; + } + } + }.start(); + */ + } + 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"); + if( loopEOS ) { + new InterruptSource.Thread() { + @Override + public void run() { + mp.setPlaySpeed(1f); + mp.seek(0); + mp.play(); + } + }.start(); + } else { + destroy = true; + } + } + } + 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 MyGLMediaEventListener myGLMediaEventListener = new MyGLMediaEventListener(); + + static boolean loopEOS = false; + static boolean origSize; + + public static void main(final String[] args) throws IOException, URISyntaxException { + int swapInterval = 1; + int width = 800; + int height = 600; + int textureCount = 3; // default - threaded + boolean ortho = true; + boolean zoom = false; + + boolean forceES2 = false; + boolean forceES3 = false; + boolean forceGL3 = false; + boolean forceGLDef = false; + int vid = GLMediaPlayer.STREAM_ID_AUTO; + int aid = GLMediaPlayer.STREAM_ID_AUTO; + + final int windowCount; + { + int _windowCount = 1; + for(int i=0; i + * java StereoDemo01 -time 10000000 + * + * All distortions, 8x multisampling, bilinear filtering, manual-swap and using two FBOs (best - slowest) + *
+ * java StereoDemo01 -time 10000000 -samples 8
+ * 
+ * All distortions, 8x multisampling, bilinear filtering, manual-swap and using one a big single FBO (w/ all commandline params) + *
+ * java StereoDemo01 -time 10000000 -vignette true -chromatic true -timewarp false -samples 8 -biLinear true -autoSwap false -singleFBO true -mainScreen false
+ * 
+ * No distortions, no multisampling, no filtering, auto-swap and using a big single FBO (worst and fastest) + *
+ * java StereoDemo01 -time 10000000 -vignette false -chromatic false -timewarp false -samples 0 -biLinear false -autoSwap true -singleFBO true
+ * 
+ * Test on main screen: + *
+ * java StereoDemo01 -time 10000000 -mainScreen true
+ * 
+ * Test a 3D SBS Movie: + *
+ * java StereoDemo01 -time 10000000 -filmFile Some_SBS_3D_Movie.mkv
+ * java StereoDemo01 -time 10000000 -filmURI http://whoknows.not/Some_SBS_3D_Movie.mkv
+ * 
+ *

+ * In case user likes to utilize the {@link StereoDeviceFactory.DeviceType#Generic Generic} software implementation, + * which is selected {@link StereoDeviceFactory.DeviceType#Default Default} if no other device is available + * or explicit via -device Generic, the user can chose between different generic stereo modes: + *

+ *   mono            : -device Generic -deviceIndex 0
+ *   stereo-sbs      : -device Generic -deviceIndex 1
+ *   stereo-sbs-lense: -device Generic -deviceIndex 2
+ * 
+ *

+ *

+ * Key 'R' enables/disables the VR's sensors, i.e. head rotation .. + *

+ * + */ +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 StereoDeviceFactory.DeviceType deviceType = StereoDeviceFactory.DeviceType.Default; + static int deviceIndex = 0; + + public static void main(final String args[]) throws InterruptedException, URISyntaxException { + boolean useRecommendedDistortionBits = true; + int posx = -1; + int posy = -1; + + for(int i=0; i 1 ) { + System.err.println("Default Fov[1]: "+defaultEyeFov[1]); + System.err.println("Default Fov[1]: "+defaultEyeFov[1].toStringInDegrees()); + } + + final boolean usesLenses = 0 != ( StereoDeviceRenderer.DISTORTION_BARREL & stereoDevice.getMinimumDistortionBits() ); + final float[] eyePositionOffset = null != movieSimple && usesLenses ? new float[] { 0f, 0.3f, 0f } // better fixed movie position w/ lenses + : stereoDevice.getDefaultEyePositionOffset(); // default + System.err.println("Eye Position Offset: "+Arrays.toString(eyePositionOffset)); + + final int textureUnit = 0; + final int reqDistortionBits; + if( useRecommendedDistortionBits ) { + reqDistortionBits = stereoDevice.getRecommendedDistortionBits(); + } else { + reqDistortionBits = ( useVignette ? StereoDeviceRenderer.DISTORTION_VIGNETTE : 0 ) | + ( useChromatic ? StereoDeviceRenderer.DISTORTION_CHROMATIC : 0 ) | + ( useTimewarp ? StereoDeviceRenderer.DISTORTION_TIMEWARP : 0 ); + } + System.err.println("Requesting Distortion Bits: "+StereoUtil.distortionBitsToString(reqDistortionBits)); + + final float pixelsPerDisplayPixel = 1f; + final StereoDeviceRenderer stereoDeviceRenderer = + stereoDevice.createRenderer(reqDistortionBits, 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() { + @Override + public void keyReleased(final KeyEvent e) { + if( e.isAutoRepeat() ) { + return; + } + switch(e.getKeySymbol()) { + case KeyEvent.VK_O: { + window.invoke(false, new GLRunnable() { + @Override + public boolean run(final GLAutoDrawable drawable) { + stereoDevice.resetLocationSensorOrigin(); + return true; + } }); + break; + } + case KeyEvent.VK_P: { + window.invoke(false, new GLRunnable() { + @Override + public boolean run(final GLAutoDrawable drawable) { + System.err.println(stereoDeviceRenderer.getLastViewerPose()); + return true; + } }); + break; + } + case KeyEvent.VK_R: { + if( stereoDevice.getSensorsStarted() ) { + stereoDevice.stopSensors(); + } else { + stereoDevice.startSensors(stereoDevice.getSupportedSensorBits(), 0); + } + break; + } + } + } } ); + + if( useAnimator ) { + animator.add(window); + animator.start(); + } + window.setVisible(true); + + // Correct window size to actual pixel size, + // which ration is unknown before window creation when using multiple displays! + System.err.println("Window.0.windowSize : "+window.getWidth()+" x "+window.getHeight()); + System.err.println("Window.0.surfaceSize: "+window.getSurfaceWidth()+" x "+window.getSurfaceHeight()); + window.setSurfaceSize(deviceRes.getWidth(), deviceRes.getHeight()); + if( useStereoScreen ) { + window.setPosition(devicePos.getX(), devicePos.getY()); + } + System.err.println("Window.1.windowSize : "+window.getWidth()+" x "+window.getHeight()); + System.err.println("Window.1.surfaceSize: "+window.getSurfaceWidth()+" x "+window.getSurfaceHeight()); + + if( useAnimator ) { + animator.setUpdateFPSFrames(60, System.err); + } + + final long t0 = System.currentTimeMillis(); + long t1 = t0; + while(!quitAdapter.shouldQuit() && t1-t0 * @author Brian Paul (converted to Java by Ron Cemer and Sven Gothel)

diff --git a/src/demos/com/jogamp/opengl/demos/es2/GearsObjectES2.java b/src/demos/com/jogamp/opengl/demos/es2/GearsObjectES2.java index 5c48a5df1..3aa6696df 100644 --- a/src/demos/com/jogamp/opengl/demos/es2/GearsObjectES2.java +++ b/src/demos/com/jogamp/opengl/demos/es2/GearsObjectES2.java @@ -27,13 +27,11 @@ import com.jogamp.opengl.GL2ES2; import com.jogamp.opengl.GLBufferStorage; import com.jogamp.opengl.GLException; import com.jogamp.opengl.GLUniformData; - +import com.jogamp.opengl.demos.GearsObject; import com.jogamp.opengl.util.GLArrayDataServer; import com.jogamp.opengl.util.PMVMatrix; import com.jogamp.opengl.util.glsl.ShaderState; -import com.jogamp.opengl.demos.GearsObject; - /** * GearsObjectES2.java
* @author Brian Paul (converted to Java by Ron Cemer and Sven Gothel)

diff --git a/src/demos/com/jogamp/opengl/demos/es2/TextureSequenceCubeES2.java b/src/demos/com/jogamp/opengl/demos/es2/TextureSequenceCubeES2.java new file mode 100644 index 000000000..6a7115143 --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/es2/TextureSequenceCubeES2.java @@ -0,0 +1,491 @@ +/** + * 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.demos.es2; + +import java.nio.FloatBuffer; + +import com.jogamp.opengl.GL; +import com.jogamp.opengl.GL2ES2; +import com.jogamp.opengl.GLAutoDrawable; +import com.jogamp.opengl.GLES2; +import com.jogamp.opengl.GLEventListener; +import com.jogamp.opengl.GLException; +import com.jogamp.opengl.GLProfile; +import com.jogamp.opengl.GLUniformData; +import com.jogamp.opengl.fixedfunc.GLMatrixFunc; + +import com.jogamp.common.os.Platform; +import com.jogamp.newt.Window; +import com.jogamp.newt.event.MouseAdapter; +import com.jogamp.newt.event.MouseEvent; +import com.jogamp.newt.event.MouseListener; +import com.jogamp.opengl.GLExtensions; +import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.util.GLArrayDataServer; +import com.jogamp.opengl.util.PMVMatrix; +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.texture.Texture; +import com.jogamp.opengl.util.texture.TextureCoords; +import com.jogamp.opengl.util.texture.TextureSequence; +import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame; + +public class TextureSequenceCubeES2 implements GLEventListener { + public TextureSequenceCubeES2 (final TextureSequence texSource, final boolean innerCube, final float zoom0, final float rotx, final float roty) { + this.texSeq = texSource; + this.innerCube = innerCube; + this.zoom = zoom0; + this.view_rotx = rotx; + this.view_roty = roty; + } + + private TextureSequence texSeq; + public ShaderState st; + public PMVMatrix pmvMatrix; + private GLUniformData pmvMatrixUniform; + // private TextureCoords[] textureCoords = null; + private float nearPlaneNormalized; + // private float zoom0=-5.0f, zoom=zoom0; + // private float view_rotx = 20.0f, view_roty = 30.0f, view_rotz = 0.0f; + public float zoom=-2.3f; + private float view_rotx = 0.0f, view_roty = 0.0f; + private final float view_rotz = 0.0f; + int[] vboNames = new int[4]; + boolean innerCube; + + private final MouseListener mouseAction = new MouseAdapter() { + int lx = 0; + int ly = 0; + boolean first = false; + + public void mousePressed(final MouseEvent e) { + first = true; + } + public void mouseMoved(final MouseEvent e) { + first = false; + } + public void mouseDragged(final MouseEvent e) { + int width, height; + final Object source = e.getSource(); + Window window = null; + if(source instanceof 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); + } + if(e.getPointerCount()==2) { + // 2 pointers zoom .. + if(first) { + lx = Math.abs(e.getY(0)-e.getY(1)); + first=false; + return; + } + final int nv = Math.abs(e.getY(0)-e.getY(1)); + final int dy = nv - lx; + + { + final float o = zoom; + final float d = 40f*Math.signum(dy)/height; + zoom += d; + System.err.println("zoom.d: "+o+" + "+d+" -> "+zoom); + } + + lx = nv; + } else { + // 1 pointer rotate + if(first) { + lx = e.getX(); + ly = e.getY(); + first=false; + return; + } + final int nx = e.getX(); + final int ny = e.getY(); + view_roty += 360f * ( (float)( nx - lx ) / (float)width ); + view_rotx += 360f * ( (float)( ny - ly ) / (float)height ); + lx = nx; + ly = ny; + } + } + public void mouseWheelMoved(final MouseEvent e) { + // System.err.println("XXX "+e); + if( !e.isShiftDown() ) { + final float o = zoom; + final float d = e.getRotation()[1]/10f; // vertical: wheel + zoom += d; + System.err.println("zoom.w: "+o+" + "+d+" -> "+zoom); + } + } + }; + + static final String shaderBasename = "texsequence_xxx"; + static final String myTextureLookupName = "myTexture2D"; + + private void initShader(final GL2ES2 gl) { + // Create & Compile the shader objects + final ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(), + "shader", "shader/bin", shaderBasename, true); + final ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(), + "shader", "shader/bin", shaderBasename, true); + + boolean preludeGLSLVersion = true; + if( GLES2.GL_TEXTURE_EXTERNAL_OES == texSeq.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, texSeq.getRequiredExtensionsShaderStub()); + rsFp.addDefaultShaderPrecision(gl, rsFpPos); + + final String texLookupFuncName = texSeq.getTextureLookupFunctionName(myTextureLookupName); + rsFp.replaceInShaderSource(myTextureLookupName, texLookupFuncName); + + // Inject TextureSequence shader details + final StringBuilder sFpIns = new StringBuilder(); + sFpIns.append("uniform ").append(texSeq.getTextureSampler2DType()).append(" mgl_ActiveTexture;\n"); + sFpIns.append(texSeq.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); + } + + GLArrayDataServer interleavedVBO, cubeIndicesVBO; + + public void init(final GLAutoDrawable drawable) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + System.err.println(JoglVersion.getGLInfo(gl, null)); + final TextureFrame frame = texSeq.getLastTexture(); + if( null == frame ) { + return; + } + final Texture tex= frame.getTexture(); + + initShader(gl); + + // Push the 1st uniform down the path + st.useProgram(gl, true); + + pmvMatrix = new PMVMatrix(); + reshapePMV(drawable.getSurfaceWidth(), drawable.getSurfaceHeight()); + pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); // P, Mv + if(!st.uniform(gl, pmvMatrixUniform)) { + throw new GLException("Error setting PMVMatrix in shader: "+st); + } + if(!st.uniform(gl, new GLUniformData("mgl_ActiveTexture", texSeq.getTextureUnit()))) { + throw new GLException("Error setting mgl_ActiveTexture in shader: "+st); + } + + + // calculate centered tex coords w/ aspect ratio + final float[] fixedCubeTexCoords = new float[s_cubeTexCoords.length]; + { + final float aspect = tex.getAspectRatio(); + final TextureCoords tc = tex.getImageTexCoords(); + System.err.println("XXX0: aspect: "+aspect); + System.err.println("XXX0: y-flip: "+tex.getMustFlipVertically()); + System.err.println("XXX0: "+tc); + final float tc_x1 = Math.max(tc.left(), tc.right()); + final float tc_y1 = Math.max(tc.bottom(), tc.top()); + final float ss=1f, ts=aspect; // scale tex-coord + final float dy = ( 1f - aspect ) / 2f ; + for(int i=0; i outlineShapes = new ArrayList(); + + public GPURegionGLListener10 (final RenderState rs, final int renderModes, final int sampleCount, final boolean debug, final boolean trace) { + super(RegionRenderer.create(rs, RegionRenderer.defaultBlendEnable, RegionRenderer.defaultBlendDisable), renderModes, debug, trace); + rs.setHintMask(RenderState.BITHINT_GLOBAL_DEPTH_TEST_ENABLED); + setMatrix(-20, 00, -50, 0f, sampleCount); + } + + private void createTestOutline(final GLProfile glp){ + OutlineShape shape = new OutlineShape(getRenderer().getRenderState().getVertexFactory()); + outlineShapes.add(shape); + shape.addVertex(0.0f,-10.0f,true); + shape.addVertex(15.0f,-10.0f, true); + shape.addVertex(10.0f,5.0f, false); + shape.addVertex(15.0f,10.0f, true); + shape.addVertex(6.0f,15.0f, false); + shape.addVertex(5.0f,8.0f, false); + shape.addVertex(0.0f,10.0f,true); + shape.closeLastOutline(true); + shape.addEmptyOutline(); + shape.addVertex(5.0f,-5.0f,true); + shape.addVertex(10.0f,-5.0f, false); + shape.addVertex(10.0f,0.0f, true); + shape.addVertex(5.0f,0.0f, false); + shape.closeLastOutline(true); + + /** Same shape as above but without any off-curve vertices */ + shape = new OutlineShape(getRenderer().getRenderState().getVertexFactory()); + outlineShapes.add(shape); + final float offset = 30; + shape.addVertex(offset+0.0f,-10.0f, true); + shape.addVertex(offset+17.0f,-10.0f, true); + shape.addVertex(offset+11.0f,5.0f, true); + shape.addVertex(offset+16.0f,10.0f, true); + shape.addVertex(offset+7.0f,15.0f, true); + shape.addVertex(offset+6.0f,8.0f, true); + shape.addVertex(offset+0.0f,10.0f, true); + shape.closeLastOutline(true); + shape.addEmptyOutline(); + shape.addVertex(offset+5.0f,0.0f, true); + shape.addVertex(offset+5.0f,-5.0f, true); + shape.addVertex(offset+10.0f,-5.0f, true); + shape.addVertex(offset+10.0f,0.0f, true); + shape.closeLastOutline(true); + + region = GLRegion.create(glp, getRenderModes(), null); + region.addOutlineShapes(outlineShapes, null, null); + } + + @Override + public void init(final GLAutoDrawable drawable) { + super.init(drawable); + + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + + final RenderState rs = getRenderer().getRenderState(); + + gl.setSwapInterval(1); + gl.glEnable(GL.GL_DEPTH_TEST); + gl.glEnable(GL.GL_BLEND); + rs.setColorStatic(0.0f, 0.0f, 0.0f, 1.0f); + + createTestOutline(gl.getGLProfile()); + } + + @Override + public void display(final GLAutoDrawable drawable) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + + gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + + final RegionRenderer regionRenderer = getRenderer(); + + final PMVMatrix pmv = regionRenderer.getMatrix(); + pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmv.glLoadIdentity(); + pmv.glTranslatef(getXTran(), getYTran(), getZTran()); + pmv.glRotatef(getAngle(), 0, 1, 0); + if( weight != regionRenderer.getRenderState().getWeight() ) { + regionRenderer.getRenderState().setWeight(weight); + } + regionRenderer.enable(gl, true); + region.draw(gl, regionRenderer, getSampleCount()); + regionRenderer.enable(gl, false); + + } +} diff --git a/src/demos/com/jogamp/opengl/demos/graph/GPURegionNewtDemo.java b/src/demos/com/jogamp/opengl/demos/graph/GPURegionNewtDemo.java new file mode 100644 index 000000000..59292c7be --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/graph/GPURegionNewtDemo.java @@ -0,0 +1,162 @@ +/** + * Copyright 2010 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.demos.graph; + +import com.jogamp.opengl.GLCapabilities; +import com.jogamp.opengl.GLProfile; +import com.jogamp.opengl.demos.util.MiscUtils; +import com.jogamp.graph.curve.Region; +import com.jogamp.graph.curve.opengl.RenderState; +import com.jogamp.graph.geom.SVertex; +import com.jogamp.newt.event.KeyAdapter; +import com.jogamp.newt.event.KeyEvent; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.util.Animator; + +/** Demonstrate the rendering of multiple outlines into one region/OutlineShape + * These Outlines are not necessary connected or contained. + * The output of this demo shows two identical shapes but the left one + * has some vertices with off-curve flag set to true, and the right allt he vertices + * are on the curve. Demos the Res. Independent Nurbs based Curve rendering + * + */ +public class GPURegionNewtDemo { + static final boolean DEBUG = false; + static final boolean TRACE = false; + + static int shape_ctor_mode = 1; + static int SceneMSAASamples = 0; + static int GraphVBAASamples = 4; + static int GraphMSAASamples = 0; + static boolean GraphUseWeight = true; + + public static void main(final String[] args) { + int width = 800, height = 400; + int x = 10, y = 10; + if( 0 != args.length ) { + SceneMSAASamples = 0; + GraphMSAASamples = 0; + GraphVBAASamples = 0; + GraphUseWeight = false; + + for(int i=0; i 0 ) { + caps.setSampleBuffers(true); + caps.setNumSamples(SceneMSAASamples); + } + System.out.println("Requested: " + caps); + + int rmode = GraphUseWeight ? Region.VARWEIGHT_RENDERING_BIT : 0; + int sampleCount = 0; + if( GraphVBAASamples > 0 ) { + rmode |= Region.VBAA_RENDERING_BIT; + sampleCount += GraphVBAASamples; + } else if( GraphMSAASamples > 0 ) { + rmode |= Region.MSAA_RENDERING_BIT; + sampleCount += GraphMSAASamples; + } + + final GLWindow window = GLWindow.create(caps); + window.setPosition(x, y); + window.setSize(width, height); + window.setTitle("GPU Curve Region Newt Demo - graph[vbaa"+GraphVBAASamples+" msaa"+GraphMSAASamples+"], msaa "+SceneMSAASamples); + + final RenderState rs = RenderState.createRenderState(SVertex.factory()); + final GPURegionGLListener01 regionGLListener = new GPURegionGLListener01 (shape_ctor_mode, rs, rmode, sampleCount, DEBUG, TRACE); + regionGLListener.attachInputListenerTo(window); + window.addGLEventListener(regionGLListener); + window.setVisible(true); + + //FPSAnimator animator = new FPSAnimator(60); + final Animator animator = new Animator(); + animator.setUpdateFPSFrames(60, System.err); + animator.add(window); + + window.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(final KeyEvent arg0) { + if(arg0.getKeyCode() == KeyEvent.VK_F4) { + window.destroy(); + } + } + }); + window.addWindowListener(new WindowAdapter() { + @Override + public void windowDestroyed(final WindowEvent e) { + animator.stop(); + } + }); + + animator.start(); + } +} diff --git a/src/demos/com/jogamp/opengl/demos/graph/GPURendererListenerBase01.java b/src/demos/com/jogamp/opengl/demos/graph/GPURendererListenerBase01.java new file mode 100644 index 000000000..185699d55 --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/graph/GPURendererListenerBase01.java @@ -0,0 +1,361 @@ +/** + * Copyright 2010 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.demos.graph; + +import java.io.File; +import java.io.IOException; + +import com.jogamp.opengl.FPSCounter; +import com.jogamp.opengl.GL; +import com.jogamp.opengl.GL2ES2; +import com.jogamp.opengl.GLAnimatorControl; +import com.jogamp.opengl.GLAutoDrawable; +import com.jogamp.opengl.GLEventListener; +import com.jogamp.opengl.GLException; +import com.jogamp.opengl.GLPipelineFactory; +import com.jogamp.opengl.GLRunnable; +import com.jogamp.opengl.fixedfunc.GLMatrixFunc; + +import com.jogamp.graph.curve.Region; +import com.jogamp.graph.curve.opengl.GLRegion; +import com.jogamp.graph.curve.opengl.RegionRenderer; +import com.jogamp.graph.curve.opengl.RenderState; +import com.jogamp.graph.font.FontScale; +import com.jogamp.newt.Window; +import com.jogamp.newt.event.KeyEvent; +import com.jogamp.newt.event.KeyListener; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.math.geom.AABBox; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.PMVMatrix; + +/** + * + * Action Keys: + * - 1/2: zoom in/out + * - 6/7: 2nd pass texture size + * - 0/9: rotate + * - Q/W: change weight + * - v: toggle v-sync + * - s: screenshot + */ +public abstract class GPURendererListenerBase01 implements GLEventListener { + private final RegionRenderer renderer; + private final int renderModes; + private final boolean debug; + private final boolean trace; + + protected GLRegion region; + + private final GLReadBufferUtil screenshot; + + private KeyAction keyAction; + + private volatile GLAutoDrawable autoDrawable = null; + + private final float[] position = new float[] {0,0,0}; + + protected final float zNear = 0.1f, zFar = 7000f; + /** Describing the bounding box in model-coordinates of the near-plane parallel at distance one. */ + protected final AABBox nearPlane1Box; + + private float xTran = -10; + private float yTran = 10; + private float ang = 0f; + private float zTran = -70f; + private final int[] sampleCount = new int[] { 4 }; + + protected volatile float weight = 1.0f; + boolean ignoreInput = false; + + public GPURendererListenerBase01(final RegionRenderer renderer, final int renderModes, final boolean debug, final boolean trace) { + this.renderer = renderer; + this.renderModes = renderModes; + this.debug = debug; + this.trace = trace; + this.screenshot = new GLReadBufferUtil(false, false); + nearPlane1Box = new AABBox(); + } + + public final RegionRenderer getRenderer() { return renderer; } + public final int getRenderModes() { return renderModes; } + public final float getZTran() { return zTran; } + public final float getXTran() { return xTran; } + public final float getYTran() { return yTran; } + public final float getAngle() { return ang; } + public final int[] getSampleCount() { return sampleCount; } + public final float[] getPosition() { return position; } + + public void setMatrix(final float xtrans, final float ytrans, final float zTran, final float angle, final int sampleCount) { + this.xTran = xtrans; + this.yTran = ytrans; + this.zTran = zTran; + this.ang = angle; + this.sampleCount[0] = sampleCount; + } + + @Override + public void init(final GLAutoDrawable drawable) { + final Object upObj = drawable.getUpstreamWidget(); + if( upObj instanceof Window ) { + final Window window = (Window) upObj; + final float[] sPpMM = window.getPixelsPerMM(new float[2]); + final float[] sDPI = FontScale.perMMToPerInch( new float[] { sPpMM[0], sPpMM[1] } ); + System.err.println("DPI "+sDPI[0]+" x "+sDPI[1]+", "+sPpMM[0]+" x "+sPpMM[1]+" pixel/mm"); + + final float[] hasSurfacePixelScale1 = window.getCurrentSurfaceScale(new float[2]); + System.err.println("HiDPI PixelScale: "+hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)"); + } + autoDrawable = drawable; + GL2ES2 gl = drawable.getGL().getGL2ES2(); + if(debug) { + gl = gl.getContext().setGL( GLPipelineFactory.create("com.jogamp.opengl.Debug", null, gl, null) ).getGL2ES2(); + } + if(trace) { + gl = gl.getContext().setGL( GLPipelineFactory.create("com.jogamp.opengl.Trace", null, gl, new Object[] { System.err } ) ).getGL2ES2(); + } + System.err.println("*** "+gl.getContext().getGLVersion()); + System.err.println("*** GLDebugMessage "+gl.getContext().isGLDebugMessageEnabled()); + MSAATool.dump(drawable); + gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + getRenderer().init(gl); + } + + public static void mapWin2ObjectCoords(final PMVMatrix pmv, final int[] view, + final float zNear, final float zFar, + final float orthoX, final float orthoY, final float orthoDist, + final float[] winZ, final float[] objPos) { + winZ[0] = (1f/zNear-1f/orthoDist)/(1f/zNear-1f/zFar); + pmv.gluUnProject(orthoX, orthoY, winZ[0], view, 0, objPos, 0); + } + + @Override + public void reshape(final GLAutoDrawable drawable, final int xstart, final int ystart, final int width, final int height) { + final PMVMatrix pmv = renderer.getMatrix(); + renderer.reshapePerspective(45.0f, width, height, zNear, zFar); + pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmv.glLoadIdentity(); + System.err.printf("Reshape: zNear %f, zFar %f%n", zNear, zFar); + System.err.printf("Reshape: Frustum: %s%n", pmv.glGetFrustum()); + { + final float orthoDist = 1f; + final float[] obj00Coord = new float[3]; + final float[] obj11Coord = new float[3]; + final float[] winZ = new float[1]; + final int[] view = new int[] { 0, 0, width, height }; + + mapWin2ObjectCoords(pmv, view, zNear, zFar, 0f, 0f, orthoDist, winZ, obj00Coord); + System.err.printf("Reshape: mapped.00: [%f, %f, %f], winZ %f -> [%f, %f, %f]%n", 0f, 0f, orthoDist, winZ[0], obj00Coord[0], obj00Coord[1], obj00Coord[2]); + + mapWin2ObjectCoords(pmv, view, zNear, zFar, width, height, orthoDist, winZ, obj11Coord); + System.err.printf("Reshape: mapped.11: [%f, %f, %f], winZ %f -> [%f, %f, %f]%n", (float)width, (float)height, orthoDist, winZ[0], obj11Coord[0], obj11Coord[1], obj11Coord[2]); + + nearPlane1Box.setSize( obj00Coord[0], // lx + obj00Coord[1], // ly + obj00Coord[2], // lz + obj11Coord[0], // hx + obj11Coord[1], // hy + obj11Coord[2] );// hz + System.err.printf("Reshape: dist1Box: %s%n", nearPlane1Box); + } + + dumpMatrix(); + // System.err.println("Reshape: "+renderer.getRenderState()); + } + + @Override + public void dispose(final GLAutoDrawable drawable) { + autoDrawable = null; + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + if(null != region) { + region.destroy(gl); + } + screenshot.dispose(gl); + renderer.destroy(gl); + } + + public void zoom(final int v){ + zTran += v; + dumpMatrix(); + } + + public void move(final float x, final float y){ + xTran += x; + yTran += y; + dumpMatrix(); + } + public void rotate(final float delta){ + ang += delta; + ang %= 360.0f; + dumpMatrix(); + } + public void editGlobalWeight(final float delta) { + if( !RenderState.isWeightValid(weight+delta) ) { + return; + } + weight += delta; + System.err.println("Global Weight: "+ weight); + } + + void dumpMatrix() { + System.err.println("Matrix: " + xTran + " / " + yTran + " / "+zTran + " @ "+ang); + } + + /** Attach the input listener to the window */ + public void attachInputListenerTo(final GLWindow window) { + if ( null == keyAction ) { + keyAction = new KeyAction(); + window.addKeyListener(keyAction); + } + } + + public void detachInputListenerFrom(final GLWindow window) { + if ( null == keyAction ) { + return; + } + window.removeKeyListener(keyAction); + } + + public void printScreen(final GLAutoDrawable drawable, final String dir, final String tech, final String objName, final boolean exportAlpha) throws GLException, IOException { + final String sw = String.format("_s%02d-%s-Z%04d-snap%02d-%03dx%03d", sampleCount[0], objName, (int)Math.abs(zTran), screenshot_num++, drawable.getSurfaceWidth(), drawable.getSurfaceHeight()); + final String filename = dir + tech + sw +".png"; + if(screenshot.readPixels(drawable.getGL(), false)) { + screenshot.write(new File(filename)); + } + } + private int screenshot_num = 0; + + public void printScreenOnGLThread(final GLAutoDrawable drawable, final String dir, final String tech, final String objName, final boolean exportAlpha) { + drawable.invoke(false, new GLRunnable() { + @Override + public boolean run(final GLAutoDrawable drawable) { + try { + printScreen(drawable, dir, tech, objName, exportAlpha); + } catch (final GLException e) { + e.printStackTrace(); + } catch (final IOException e) { + e.printStackTrace(); + } + return true; + } + }); + } + + public void setIgnoreInput(final boolean v) { + ignoreInput = v; + } + public boolean getIgnoreInput() { + return ignoreInput; + } + + public class KeyAction implements KeyListener { + @Override + public void keyPressed(final KeyEvent arg0) { + if(ignoreInput) { + return; + } + + if(arg0.getKeyCode() == KeyEvent.VK_1){ + zoom(10); + } + else if(arg0.getKeyCode() == KeyEvent.VK_2){ + zoom(-10); + } + else if(arg0.getKeyCode() == KeyEvent.VK_UP){ + move(0, -1); + } + else if(arg0.getKeyCode() == KeyEvent.VK_DOWN){ + move(0, 1); + } + else if(arg0.getKeyCode() == KeyEvent.VK_LEFT){ + move(-1, 0); + } + else if(arg0.getKeyCode() == KeyEvent.VK_RIGHT){ + move(1, 0); + } + else if(arg0.getKeyCode() == KeyEvent.VK_6){ + sampleCount[0] -= 1; + System.err.println("Sample Count: " + sampleCount[0]); + } + else if(arg0.getKeyCode() == KeyEvent.VK_7){ + sampleCount[0] += 1; + System.err.println("Sample Count: " + sampleCount[0]); + } + else if(arg0.getKeyCode() == KeyEvent.VK_0){ + rotate(1); + } + else if(arg0.getKeyCode() == KeyEvent.VK_9){ + rotate(-1); + } + else if(arg0.getKeyCode() == KeyEvent.VK_Q){ + editGlobalWeight(-0.1f); + } + else if(arg0.getKeyCode() == KeyEvent.VK_W){ + editGlobalWeight(0.1f); + } + else if(arg0.getKeyCode() == KeyEvent.VK_V) { + if(null != autoDrawable) { + autoDrawable.invoke(false, new GLRunnable() { + @Override + public boolean run(final GLAutoDrawable drawable) { + final GL gl = drawable.getGL(); + final int _i = gl.getSwapInterval(); + final int i; + switch(_i) { + case 0: i = -1; break; + case -1: i = 1; break; + case 1: i = 0; break; + default: i = 1; break; + } + gl.setSwapInterval(i); + + final GLAnimatorControl a = drawable.getAnimator(); + if( null != a ) { + a.resetFPSCounter(); + } + if(drawable instanceof FPSCounter) { + ((FPSCounter)drawable).resetFPSCounter(); + } + System.err.println("Swap Interval: "+_i+" -> "+i+" -> "+gl.getSwapInterval()); + return true; + } + }); + } + } + else if(arg0.getKeyCode() == KeyEvent.VK_S){ + if(null != autoDrawable) { + final String modeS = Region.getRenderModeString(renderModes); + final String type = modeS + ( Region.hasVariableWeight(renderModes) ? "-vc" : "-uc" ) ; + printScreenOnGLThread(autoDrawable, "./", "demo-"+type, "", false); + } + } + } + @Override + public void keyReleased(final KeyEvent arg0) {} + } +} diff --git a/src/demos/com/jogamp/opengl/demos/graph/GPUTextGLListener0A.java b/src/demos/com/jogamp/opengl/demos/graph/GPUTextGLListener0A.java new file mode 100644 index 000000000..8a8a49869 --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/graph/GPUTextGLListener0A.java @@ -0,0 +1,72 @@ +/** + * Copyright 2010 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.demos.graph; + + +import com.jogamp.opengl.GL; +import com.jogamp.opengl.GL2ES2; +import com.jogamp.opengl.GLAutoDrawable; +import com.jogamp.opengl.GLProfile; +import com.jogamp.graph.curve.Region; +import com.jogamp.graph.curve.opengl.RenderState; +import com.jogamp.graph.geom.SVertex; +import com.jogamp.newt.opengl.GLWindow; + +public class GPUTextGLListener0A extends GPUTextRendererListenerBase01 { + + public GPUTextGLListener0A(final GLProfile glp, final RenderState rs, final int renderModes, final int sampleCount, final boolean blending, final boolean debug, final boolean trace) { + super(glp, rs, renderModes, sampleCount, blending, debug, trace); + } + + @Override + public void init(final GLAutoDrawable drawable) { + if(drawable instanceof GLWindow) { + final GLWindow glw = (GLWindow) drawable; + attachInputListenerTo(glw); + } + super.init(drawable); + + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + + final RenderState rs = getRenderer().getRenderState(); + + gl.setSwapInterval(1); + gl.glEnable(GL.GL_DEPTH_TEST); + gl.glEnable(GL.GL_BLEND); + rs.setColorStatic(0.1f, 0.1f, 0.1f, 1.0f); + } + + @Override + public void dispose(final GLAutoDrawable drawable) { + if(drawable instanceof GLWindow) { + final GLWindow glw = (GLWindow) drawable; + detachInputListenerFrom(glw); + } + super.dispose(drawable); + } +} diff --git a/src/demos/com/jogamp/opengl/demos/graph/GPUTextNewtDemo.java b/src/demos/com/jogamp/opengl/demos/graph/GPUTextNewtDemo.java new file mode 100644 index 000000000..b4e91e01f --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/graph/GPUTextNewtDemo.java @@ -0,0 +1,193 @@ +/** + * Copyright 2010 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.demos.graph; + +import com.jogamp.opengl.GLCapabilities; +import com.jogamp.opengl.GLProfile; +import com.jogamp.opengl.demos.util.MiscUtils; +import com.jogamp.opengl.math.geom.AABBox; + +import java.io.File; +import java.io.IOException; + +import com.jogamp.common.util.InterruptSource; +import com.jogamp.graph.curve.Region; +import com.jogamp.graph.curve.opengl.RenderState; +import com.jogamp.graph.font.Font; +import com.jogamp.graph.font.FontFactory; +import com.jogamp.graph.font.FontScale; +import com.jogamp.graph.geom.SVertex; +import com.jogamp.newt.MonitorDevice; +import com.jogamp.newt.event.KeyAdapter; +import com.jogamp.newt.event.KeyEvent; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.util.Animator; + +public class GPUTextNewtDemo { + /** + * FIXME: + * + * If DEBUG is enabled: + * + * Caused by: com.jogamp.opengl.GLException: Thread[main-Display-X11_:0.0-1-EDT-1,5,main] glGetError() returned the following error codes after a call to glFramebufferRenderbuffer( 0x8D40, 0x1902, 0x8D41, 0x1): GL_INVALID_ENUM ( 1280 0x500), + * at com.jogamp.opengl.DebugGL4bc.checkGLGetError(DebugGL4bc.java:33961) + * at com.jogamp.opengl.DebugGL4bc.glFramebufferRenderbuffer(DebugGL4bc.java:33077) + * at jogamp.graph.curve.opengl.VBORegion2PGL3.initFBOTexture(VBORegion2PGL3.java:295) + */ + static final boolean DEBUG = false; + static final boolean TRACE = false; + + static int SceneMSAASamples = 0; + static int GraphVBAASamples = 4; + static int GraphMSAASamples = 0; + + public static void main(final String[] args) throws IOException { + Font opt_font = null; + int opt_fontSizeHead = -1; + int width = 800, height = 400; + int x = 10, y = 10; + if( 0 != args.length ) { + SceneMSAASamples = 0; + GraphMSAASamples = 0; + GraphVBAASamples = 0; + + for(int i=0; i 0 ) { + caps.setSampleBuffers(true); + caps.setNumSamples(SceneMSAASamples); + } + System.out.println("Requested: " + caps); + + int rmode = 0; // Region.VARIABLE_CURVE_WEIGHT_BIT; + int sampleCount = 0; + if( GraphVBAASamples > 0 ) { + rmode |= Region.VBAA_RENDERING_BIT; + sampleCount += GraphVBAASamples; + } else if( GraphMSAASamples > 0 ) { + rmode |= Region.MSAA_RENDERING_BIT; + sampleCount += GraphMSAASamples; + } + + final GLWindow window = GLWindow.create(caps); + window.setPosition(x, y); + window.setSize(width, height); + window.setTitle("GPU Text Newt Demo - graph[vbaa"+GraphVBAASamples+" msaa"+GraphMSAASamples+"], msaa "+SceneMSAASamples); + + final RenderState rs = RenderState.createRenderState(SVertex.factory()); + final GPUTextGLListener0A textGLListener = new GPUTextGLListener0A(glp, rs, rmode, sampleCount, true, DEBUG, TRACE); + textGLListener.setFont(opt_font); + textGLListener.setFontHeadSize(opt_fontSizeHead); + // ((TextRenderer)textGLListener.getRenderer()).setCacheLimit(32); + window.addGLEventListener(textGLListener); + window.setVisible(true); + + { + final Font font2 = textGLListener.getFont(); + final float[] sDPI = FontScale.perMMToPerInch( window.getPixelsPerMM(new float[2]) ); + final float font_ptpi = 12f; + final float font_ppi = FontScale.toPixels(font_ptpi, sDPI[1]); + final AABBox fontNameBox = font2.getMetricBounds(GPUTextRendererListenerBase01.textX1); + System.err.println("GPU Text Newt Demo: "+font2.fullString()); + System.err.println("GPU Text Newt Demo: screen-dpi: "+sDPI[0]+"x"+sDPI[1]+", font "+font_ptpi+" pt, "+font_ppi+" pixel"); + System.err.println("GPU Text Newt Demo: textX2: "+fontNameBox+" em, "+fontNameBox.scale(font_ppi, new float[3])+" px"); + final MonitorDevice monitor = window.getMainMonitor(); + System.err.println("GPU Text Newt Demo: "+monitor); + // window.setSurfaceSize((int)(fontNameBox.getWidth()*1.1f), (int)(fontNameBox.getHeight()*2f)); + } + + // FPSAnimator animator = new FPSAnimator(60); + final Animator animator = new Animator(); + animator.setUpdateFPSFrames(60, null); + animator.add(window); + + window.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(final KeyEvent arg0) { + if(arg0.getKeyCode() == KeyEvent.VK_F4) { + new InterruptSource.Thread() { + @Override + public void run() { + window.destroy(); + } }.start(); + } + } + }); + window.addWindowListener(new WindowAdapter() { + @Override + public void windowDestroyed(final WindowEvent e) { + animator.stop(); + } + }); + + animator.start(); + } +} diff --git a/src/demos/com/jogamp/opengl/demos/graph/GPUTextRendererListenerBase01.java b/src/demos/com/jogamp/opengl/demos/graph/GPUTextRendererListenerBase01.java new file mode 100644 index 000000000..f23548b8a --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/graph/GPUTextRendererListenerBase01.java @@ -0,0 +1,588 @@ +/** + * Copyright 2010 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.demos.graph; + +import java.io.IOException; + +import com.jogamp.opengl.GL; +import com.jogamp.opengl.GL2ES2; +import com.jogamp.opengl.GLAnimatorControl; +import com.jogamp.opengl.GLAutoDrawable; +import com.jogamp.opengl.GLException; +import com.jogamp.opengl.GLProfile; +import com.jogamp.opengl.fixedfunc.GLMatrixFunc; +import com.jogamp.common.util.InterruptSource; +import com.jogamp.graph.curve.Region; +import com.jogamp.graph.curve.opengl.GLRegion; +import com.jogamp.graph.curve.opengl.RegionRenderer; +import com.jogamp.graph.curve.opengl.RenderState; +import com.jogamp.graph.curve.opengl.TextRegionUtil; +import com.jogamp.graph.font.Font; +import com.jogamp.graph.font.FontFactory; +import com.jogamp.graph.font.FontScale; +import com.jogamp.graph.font.FontSet; +import com.jogamp.graph.geom.plane.AffineTransform; +import com.jogamp.newt.Window; +import com.jogamp.newt.event.KeyEvent; +import com.jogamp.newt.event.KeyListener; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.math.geom.AABBox; +import com.jogamp.opengl.util.PMVMatrix; + +/** + * + * GPURendererListenerBase01 Keys: + * - 1/2: zoom in/out + * - 6/7: 2nd pass texture size + * - 0/9: rotate + * - v: toggle v-sync + * - s: screenshot + * + * Additional Keys: + * - 3/4: font +/- + * - h: toogle draw 'font set' + * - f: toggle draw fps + * - space: toggle font (ubuntu/java) + * - i: live input text input (CR ends it, backspace supported) + */ +public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerBase01 { + public final TextRegionUtil textRegionUtil; + private final GLRegion regionFPS, regionHead, regionBottom; + int fontSet = FontFactory.UBUNTU; + Font font; + + int headType = 1; + boolean drawFPS = true; + final float fontSizeFName = 10f; + final float fontSizeFPS = 10f; + final int[] sampleCountFPS = new int[] { 8 }; + float fontSizeHead = 12f; + float fontSizeCenter = 16f; + float dpiV = 96; + float ppmmV = 1; + final int fontSizeModulo = 100; + String fontName; + AABBox fontNameBox; + String headtext; + AABBox headbox; + + protected final AffineTransform tempT1 = new AffineTransform(); + protected final AffineTransform tempT2 = new AffineTransform(); + + static final String text2 = "The quick brown fox jumps over the lazy dog"; + public static final String text_help = + "JOGL: Java™ Binding for OpenGL®, providing hardware-accelerated 3D graphics.\n\n"+ + "JOGAMP graph demo using Resolution Independent NURBS\n"+ + "JOGAMP JOGL - OpenGL ES2 profile\n"+ + "Press 1/2 to zoom in/out the below text\n"+ + "Press 3/4 to incr/decs font size (alt: head, w/o bottom)\n"+ + "Press 6/7 to edit texture size if using VBAA\n"+ + "Press 0/9 to rotate the below string\n"+ + "Press s to screenshot\n"+ + "Press v to toggle vsync\n"+ + "Press i for live input text input (CR ends it, backspace supported)\n"+ + "Press f to toggle fps. H for different text, space for font type\n"; + + public static final String textX1 = + "JOGL: Java™ Binding for OpenGL®, providing hardware-accelerated 3D graphics.\n\n"+ + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec nec sapien tellus. \n"+ + "Ut purus odio, rhoncus sit amet commodo eget, ullamcorper vel urna. Mauris ultricies \n"+ + "quam iaculis urna cursus ornare. Nullam ut felis a ante ultrices ultricies nec a elit. \n"+ + "In hac habitasse platea dictumst. Vivamus et mi a quam lacinia pharetra at venenatis est. \n"+ + "Morbi quis bibendum nibh. Donec lectus orci, sagittis in consequat nec, volutpat nec nisi. \n"+ + "Donec ut dolor et nulla tristique varius. In nulla magna, fermentum id tempus quis, semper \n"+ + "in lorem. Maecenas in ipsum ac justo scelerisque sollicitudin. Quisque sit amet neque lorem, \n" + + "-------Press H to change text---------"; + + public static final String textX2 = + "I “Ask Jeff” or ‘Ask Jeff’. Take the chef d’œuvre! Two of [of] (of) ‘of’ “of” of? of! of*.\n"+ + "Les Woëvres, the Fôret de Wœvres, the Voire and Vauvise. Yves is in heaven; D’Amboise is in jail.\n"+ + "Lyford’s in Texas & L’Anse-aux-Griffons in Québec; the Łyna in Poland. Yriarte, Yciar and Ysaÿe are at Yale.\n"+ + "Kyoto and Ryotsu are both in Japan, Kwikpak on the Yukon delta, Kvæven in Norway, Kyulu in Kenya, not in Rwanda.…\n"+ + "Von-Vincke-Straße in Münster, Vdovino in Russia, Ytterbium in the periodic table. Are Toussaint L’Ouverture, Wölfflin, Wolfe,\n"+ + "Miłosz and Wū Wŭ all in the library? 1510–1620, 11:00 pm, and the 1980s are over. X\n"+ + "-------Press H to change text---------"; + + public static final String textX20 = + "I “Ask Jeff” or ‘Ask Jeff’. Take the chef d’œuvre! Two of [of] (of) ‘of’ “of” of? of! of*.\n"+ + "Two of [of] (of) ‘of’ “of” of? of! of*. Ydes, Yffignac and Ygrande are in France: so are Ypres,\n"+ + "Les Woëvres, the Fôret de Wœvres, the Voire and Vauvise. Yves is in heaven; D’Amboise is in jail.\n"+ + "Lyford’s in Texas & L’Anse-aux-Griffons in Québec; the Łyna in Poland. Yriarte, Yciar and Ysaÿe are at Yale.\n"+ + "Kyoto and Ryotsu are both in Japan, Kwikpak on the Yukon delta, Kvæven in Norway, Kyulu in Kenya, not in Rwanda.…\n"+ + "Walton’s in West Virginia, but «Wren» is in Oregon. Tlálpan is near Xochimilco in México.\n"+ + "The Zygos & Xylophagou are in Cyprus, Zwettl in Austria, Fænø in Denmark, the Vøringsfossen and Værøy in Norway.\n"+ + "Tchula is in Mississippi, the Tittabawassee in Michigan. Twodot is here in Montana, Ywamun in Burma.\n"+ + "Yggdrasil and Ymir, Yngvi and Vóden, Vídrið and Skeggjöld and Týr are all in the Eddas.\n"+ + "Tørberget and Våg, of course, are in Norway, Ktipas and Tmolos in Greece, but Vázquez is in Argentina, Vreden in Germany,\n"+ + "Von-Vincke-Straße in Münster, Vdovino in Russia, Ytterbium in the periodic table. Are Toussaint L’Ouverture, Wölfflin, Wolfe,\n"+ + "Miłosz and Wū Wŭ all in the library? 1510–1620, 11:00 pm, and the 1980s are over.\n"+ + "Ut purus odio, rhoncus sit amet commodo eget, ullamcorper vel urna. Mauris ultricies \n"+ + "-------Press H to change text---------"; + + static final String textXLast = "abcdefghijklmnopqrstuvwxyz\nABCDEFGHIJKLMNOPQRSTUVWXYZ\n0123456789.:,;(*!?/\\\")$%^&-+@~#<>{}[]"; + + Window upstream_window = null; + StringBuilder userString = new StringBuilder(textX1); + boolean userInput = false; + public GPUTextRendererListenerBase01(final GLProfile glp, final RenderState rs, final int renderModes, final int sampleCount, final boolean blending, final boolean debug, final boolean trace) { + // NOTE_ALPHA_BLENDING: We use alpha-blending + super(RegionRenderer.create(rs, blending ? RegionRenderer.defaultBlendEnable : null, + blending ? RegionRenderer.defaultBlendDisable : null), + renderModes, debug, trace); + rs.setHintMask(RenderState.BITHINT_GLOBAL_DEPTH_TEST_ENABLED); + this.textRegionUtil = new TextRegionUtil(renderModes); + this.regionFPS = GLRegion.create(glp, renderModes, null); + this.regionHead = GLRegion.create(glp, renderModes, null); + this.regionBottom = GLRegion.create(glp, renderModes, null); + setFontSet(fontSet, FontSet.FAMILY_LIGHT, FontSet.STYLE_NONE); + setMatrix(0, 0, 0, 0f, sampleCount); + } + + void switchHeadBox() { + setHeadBox( ( headType + 1 ) % 5, true ); + } + public int getHeadBoxType() { return headType; } + public AABBox getHeadBox() { return headbox; } + public void setHeadBox(final int choice, final boolean resize) { + headType = choice % 5 ; + switch(headType) { + case 0: + headtext = null; + break; + + case 1: + headtext= textX1; + break; + case 2: + headtext= textX2; + break; + case 3: + headtext= text_help; + break; + + default: + headtext = textXLast; + } + if(resize && null != headtext) { + headbox = font.getMetricBounds(headtext); + if( headtext != text_help ) { + final float pxSz = FontScale.toPixels(fontSizeHead, dpiV); + upsizeWindowSurface(upstream_window, true, (int)(headbox.getWidth()*pxSz*1.1f), (int)(headbox.getHeight()*pxSz*2f)); + } + } + } + + public void setHeadBox(final String text, final boolean resize) { + headtext = text; + if(resize && null != headtext) { + headbox = font.getMetricBounds(headtext); + if( headtext != text_help ) { + final float pxSz = FontScale.toPixels(fontSizeHead, dpiV); + upsizeWindowSurface(upstream_window, true, (int)(headbox.getWidth()*pxSz*1.1f), (int)(headbox.getHeight()*pxSz*2f)); + } + } + } + + public static void upsizeWindowSurface(final Window window, final boolean off_thread, final int w, final int h) { + if( null == window ) { + return; + } + final int w2 = Math.max(window.getSurfaceWidth(), w); + final int h2 = Math.max(window.getSurfaceHeight(), h); + System.err.println("upsizeWindowSurface: "+window.getSurfaceWidth()+"x"+window.getSurfaceHeight()+" -> "+w+"x"+h+" -> "+w2+"x"+h2); + if( off_thread ) { + new InterruptSource.Thread() { + @Override + public void run() { + window.setSurfaceSize(w2, h2); + } }.start(); + } else { + window.setSurfaceSize(w2, h2); + } + } + + @Override + public void init(final GLAutoDrawable drawable) { + super.init(drawable); + final Object upObj = drawable.getUpstreamWidget(); + if( upObj instanceof Window ) { + upstream_window = (Window) upObj; + final float[] sPpMM = upstream_window.getPixelsPerMM(new float[2]); + final float[] sDPI = FontScale.perMMToPerInch( new float[] { sPpMM[0], sPpMM[1] } ); + dpiV = sDPI[1]; + ppmmV = sPpMM[1]; + System.err.println("Using vertical screen DPI of "+dpiV+", "+ppmmV+" pixel/mm"); + } else { + System.err.println("Using vertical default DPI of "+dpiV+", "+ppmmV+" pixel/mm"); + } + fontNameBox = font.getGlyphBounds(fontName, tempT1, tempT2); + setHeadBox(headType, true); + { + final float pixelSizeFName = FontScale.toPixels(fontSizeFName, dpiV); + System.err.println("XXX: fontName size "+fontSizeFName+"pt, dpiV "+dpiV+" -> "+pixelSizeFName+"px"); + System.err.println("XXX: fontName boxM fu "+font.getMetricBoundsFU(fontName)); + System.err.println("XXX: fontName boxG fu "+font.getGlyphBoundsFU(fontName, tempT1, tempT2)); + System.err.println("XXX: fontName boxM em "+font.getMetricBounds(fontName)); + System.err.println("XXX: fontName boxG em "+font.getGlyphBounds(fontName, tempT1, tempT2)); + System.err.println("XXX: fontName box height px "+(fontNameBox.getHeight() * pixelSizeFName)); + } + } + + @Override + public void reshape(final GLAutoDrawable drawable, final int xstart, final int ystart, final int width, final int height) { + super.reshape(drawable, xstart, ystart, width, height); + final Object upObj = drawable.getUpstreamWidget(); + if( upObj instanceof Window ) { + upstream_window = (Window) upObj; + } + final float dist = 100f; + nearPlaneX0 = nearPlane1Box.getMinX() * dist; + nearPlaneY0 = nearPlane1Box.getMinY() * dist; + nearPlaneZ0 = nearPlane1Box.getMinZ() * dist; + final float xd = nearPlane1Box.getWidth() * dist; + final float yd = nearPlane1Box.getHeight() * dist; + nearPlaneSx = xd / width; + nearPlaneSy = yd / height; + nearPlaneS = nearPlaneSy; + System.err.printf("Scale: [%f x %f] / [%d x %d] = [%f, %f] -> %f%n", xd, yd, width, height, nearPlaneSx, nearPlaneSy, nearPlaneS); + } + float nearPlaneX0, nearPlaneY0, nearPlaneZ0, nearPlaneSx, nearPlaneSy, nearPlaneS; + + @Override + public void dispose(final GLAutoDrawable drawable) { + upstream_window = null; + regionFPS.destroy(drawable.getGL().getGL2ES2()); + regionHead.destroy(drawable.getGL().getGL2ES2()); + regionBottom.destroy(drawable.getGL().getGL2ES2()); + super.dispose(drawable); + } + + @Override + public void display(final GLAutoDrawable drawable) { + final Object upObj = drawable.getUpstreamWidget(); + if( upObj instanceof Window ) { + upstream_window = (Window) upObj; + } + final int width = drawable.getSurfaceWidth(); + final int height = drawable.getSurfaceHeight(); + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + + gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + + // final float zDistance0 = 500f; + // final float zDistance1 = 400f; + // final float[] objPos = new float[3]; + // final float[] winZ = new float[1]; + // final int[] view = new int[] { 0, 0, drawable.getWidth(), drawable.getHeight() }; + + final RegionRenderer renderer = getRenderer(); + final RenderState rs = renderer.getRenderState(); + final PMVMatrix pmv = renderer.getMatrix(); + pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmv.glLoadIdentity(); + rs.setColorStatic(0.1f, 0.1f, 0.1f, 1.0f); + final float pixelSizeFName = FontScale.toPixels(fontSizeFName, dpiV); + final float pixelSizeHead = FontScale.toPixels(fontSizeHead, dpiV); + final float mmSizeHead = pixelSizeHead / ppmmV; + final float pixelSizeCenter = FontScale.toPixels(fontSizeCenter, dpiV); + final float mmSizeCenter = pixelSizeCenter / ppmmV; + + renderer.enable(gl, true); + + if( drawFPS ) { + pmv.glPushMatrix(); + final float pixelSizeFPS = FontScale.toPixels(fontSizeFPS, dpiV); + final float lfps, tfps, td; + final GLAnimatorControl animator = drawable.getAnimator(); + if( null != animator ) { + lfps = animator.getLastFPS(); + tfps = animator.getTotalFPS(); + td = animator.getTotalFPSDuration()/1000f; + } else { + lfps = 0f; + tfps = 0f; + td = 0f; + } + final String modeS = Region.getRenderModeString(regionFPS.getRenderModes()); + final String text = String.format("%03.1f/%03.1f fps, v-sync %d, dpiV %.2f %.2f px/mm, font[head %.1fpt %.2fpx %.2fmm, center %.1fpt %.2fpx %.2fmm], %s-samples[%d, this %d], blend %b, alpha %d", + lfps, tfps, gl.getSwapInterval(), dpiV, ppmmV, + fontSizeHead, pixelSizeHead, mmSizeHead, + fontSizeCenter, pixelSizeCenter, mmSizeCenter, + modeS, getSampleCount()[0], sampleCountFPS[0], + renderer.getRenderState().isHintMaskSet(RenderState.BITHINT_BLENDING_ENABLED), + drawable.getChosenGLCapabilities().getAlphaBits()); + + // bottom, half line up + pmv.glTranslatef(nearPlaneX0, nearPlaneY0+(nearPlaneS * pixelSizeFPS / 2f), nearPlaneZ0); + { + final float sxy = nearPlaneS * pixelSizeFPS; + pmv.glScalef(sxy, sxy, 1.0f); + } + // No cache, keep region alive! + TextRegionUtil.drawString3D(gl, regionFPS.clear(gl), renderer, font, text, null, sampleCountFPS, tempT1, tempT2); + pmv.glPopMatrix(); + } + + // float dx = width - ( fontNameBox.getWidth() + font.getAdvanceWidth( Glyph.ID_SPACE ) ) * pixelSizeFName; + float dx = width - ( fontNameBox.getWidth() + 2 * font.getAdvanceWidth( font.getGlyphID('X') ) ) * pixelSizeFName; + float dy = height - fontNameBox.getHeight() * pixelSizeFName; + { + pmv.glPushMatrix(); + pmv.glTranslatef(nearPlaneX0+(dx*nearPlaneSx), nearPlaneY0+(dy*nearPlaneSy), nearPlaneZ0); + { + final float sxy = nearPlaneS * pixelSizeFName; + pmv.glScalef(sxy, sxy, 1.0f); + } + // System.err.printf("FontN: [%f %f] -> [%f %f]%n", dx, dy, nearPlaneX0+(dx*nearPlaneSx), nearPlaneY0+(dy*nearPlaneSy)); + textRegionUtil.drawString3D(gl, renderer, font, fontName, null, getSampleCount()); + pmv.glPopMatrix(); + } + + dx = 10f; + dy += -fontNameBox.getHeight() * pixelSizeFName - 10f; + + if(null != headtext) { + pmv.glPushMatrix(); + // System.err.printf("Head: [%f %f] -> [%f %f]%n", dx, dy, nearPlaneX0+(dx*nearPlaneSx), nearPlaneY0+(dy*nearPlaneSy)); + pmv.glTranslatef(nearPlaneX0+(dx*nearPlaneSx), nearPlaneY0+(dy*nearPlaneSy), nearPlaneZ0); + { + final float sxy = nearPlaneS * pixelSizeHead; + pmv.glScalef(sxy, sxy, 1.0f); + } + // pmv.glTranslatef(x0, y1, z0); + textRegionUtil.drawString3D(gl, renderer, font, headtext, null, getSampleCount()); + pmv.glPopMatrix(); + } + + dy += ( -headbox.getHeight() - font.getLineHeight() ) * pixelSizeCenter; + + { + pmv.glPushMatrix(); + pmv.glTranslatef(nearPlaneX0+(dx*nearPlaneSx), nearPlaneY0+(dy*nearPlaneSy), nearPlaneZ0); + // System.err.printf("Bottom: [%f %f] -> [%f %f]%n", dx, dy, nearPlaneX0+(dx*nearPlaneSx), nearPlaneY0+(dy*nearPlaneSy)); + pmv.glTranslatef(getXTran(), getYTran(), getZTran()); + pmv.glRotatef(getAngle(), 0, 1, 0); + { + final float sxy = nearPlaneS * pixelSizeCenter; + pmv.glScalef(sxy, sxy, 1.0f); + } + rs.setColorStatic(0.9f, 0.0f, 0.0f, 1.0f); + + if( bottomTextUseFrustum ) { + regionBottom.setFrustum(pmv.glGetFrustum()); + } + if(!userInput) { + if( bottomTextUseFrustum ) { + TextRegionUtil.drawString3D(gl, regionBottom.clear(gl), renderer, font, text2, null, getSampleCount(), tempT1, tempT2); + } else { + textRegionUtil.drawString3D(gl, renderer, font, text2, null, getSampleCount()); + } + } else { + if( bottomTextUseFrustum ) { + TextRegionUtil.drawString3D(gl, regionBottom.clear(gl), renderer, font, userString.toString(), null, getSampleCount(), tempT1, tempT2); + } else { + textRegionUtil.drawString3D(gl, renderer, font, userString.toString(), null, getSampleCount()); + } + } + pmv.glPopMatrix(); + } + renderer.enable(gl, false); + } + final boolean bottomTextUseFrustum = true; + + public Font getFont() { return font; } + public float getFontSizeHead() { return fontSizeHead; } + + public void fontBottomIncr(final int v) { + fontSizeCenter = Math.abs((fontSizeCenter + v) % fontSizeModulo) ; + dumpMatrix(true); + } + + public void fontHeadIncr(final int v) { + fontSizeHead = Math.abs((fontSizeHead + v) % fontSizeModulo) ; + updateFontNameBox(); + if(null != headtext) { + headbox = font.getMetricBounds(headtext); + } + } + + public void setFontHeadSize(final int v) { + if( 0 < v ) { + fontSizeHead = v % fontSizeModulo; + updateFontNameBox(); + if(null != headtext) { + headbox = font.getMetricBounds(headtext); + } + } + } + + public boolean nextFontSet() { + try { + final int set = ( fontSet == FontFactory.UBUNTU ) ? FontFactory.JAVA : FontFactory.UBUNTU ; + final Font _font = FontFactory.get(set).getDefault(); + if(null != _font) { + fontSet = set; + font = _font; + updateFontNameBox(); + return true; + } + } catch (final IOException ex) { + System.err.println("Caught: "+ex.getMessage()); + } + return false; + } + + public boolean setFontSet(final int set, final int family, final int stylebits) { + try { + final Font _font = FontFactory.get(set).get(family, stylebits); + if(null != _font) { + fontSet = set; + font = _font; + updateFontNameBox(); + return true; + } + } catch (final IOException ex) { + System.err.println("Caught: "+ex.getMessage()); + } + return false; + } + + public boolean setFont(final Font _font) { + if(null != _font) { + // fontSet = ??? + font = _font; + updateFontNameBox(); + return true; + } + return false; + } + + private void updateFontNameBox() { + fontName = font.getFullFamilyName()+" (head "+fontSizeHead+"pt)"; + fontNameBox = font.getMetricBounds(fontName); + } + + public boolean isUserInputMode() { return userInput; } + + void dumpMatrix(final boolean bbox) { + System.err.println("Matrix: " + getXTran() + "/" + getYTran() + " x"+getZTran() + " @"+getAngle() +" fontSize "+fontSizeCenter); + if(bbox) { + System.err.println("bbox em: "+font.getMetricBounds(text2)); + System.err.println("bbox px: "+font.getMetricBounds(text2).scale(nearPlaneS * FontScale.toPixels(fontSizeCenter, dpiV), new float[3])); + } + } + + KeyAction keyAction = null; + + @Override + public void attachInputListenerTo(final GLWindow window) { + if ( null == keyAction ) { + keyAction = new KeyAction(); + window.addKeyListener(keyAction); + super.attachInputListenerTo(window); + } + } + + @Override + public void detachInputListenerFrom(final GLWindow window) { + super.detachInputListenerFrom(window); + if ( null == keyAction ) { + return; + } + window.removeKeyListener(keyAction); + } + + @Override + public void printScreen(final GLAutoDrawable drawable, final String dir, final String tech, final String objName, final boolean exportAlpha) throws GLException, IOException { + final String fn = font.getFullFamilyName().replace(' ', '_').replace('-', '_'); + final String modes = Region.getRenderModeString(getRenderModes()); + final String fsaa = "fsaa"+drawable.getChosenGLCapabilities().getNumSamples(); + super.printScreen(drawable, dir, tech+"-"+modes, fsaa+"-"+fn+"-text"+getHeadBoxType()+"-"+objName, exportAlpha); + } + + float fontHeadScale = 1f; + + public class KeyAction implements KeyListener { + @Override + public void keyPressed(final KeyEvent e) { + if(userInput) { + return; + } + final short s = e.getKeySymbol(); + if(s == KeyEvent.VK_3) { + if( e.isAltDown() ) { + fontHeadIncr(1); + } else { + fontBottomIncr(1); + } + } + else if(s == KeyEvent.VK_4) { + if( e.isAltDown() ) { + fontHeadIncr(-1); + } else { + fontBottomIncr(-1); + } + } + else if(s == KeyEvent.VK_H) { + switchHeadBox(); + } + else if(s == KeyEvent.VK_F) { + drawFPS = !drawFPS; + } + else if(s == KeyEvent.VK_SPACE) { + nextFontSet(); + } + else if(s == KeyEvent.VK_I) { + userInput = true; + setIgnoreInput(true); + } + } + + @Override + public void keyReleased(final KeyEvent e) { + if( !e.isPrintableKey() || e.isAutoRepeat() ) { + return; + } + if(userInput) { + final short k = e.getKeySymbol(); + if( KeyEvent.VK_ENTER == k ) { + userInput = false; + setIgnoreInput(false); + } else if( KeyEvent.VK_BACK_SPACE == k && userString.length()>0) { + userString.deleteCharAt(userString.length()-1); + } else { + final char c = e.getKeyChar(); + if( font.isPrintableChar( c ) ) { + userString.append(c); + } + } + } + } + } +} diff --git a/src/demos/com/jogamp/opengl/demos/graph/MSAATool.java b/src/demos/com/jogamp/opengl/demos/graph/MSAATool.java new file mode 100644 index 000000000..e0815b70a --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/graph/MSAATool.java @@ -0,0 +1,96 @@ +/** + * Copyright 2010 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.demos.graph; + +import com.jogamp.opengl.GL; +import com.jogamp.opengl.GL2ES2; +import com.jogamp.opengl.GL2GL3; +import com.jogamp.opengl.GLAutoDrawable; +import com.jogamp.opengl.GLCapabilitiesImmutable; + +public class MSAATool { + public static boolean glIsEnabled(final GL gl, final int name) { + boolean isEnabled = false; + try { + isEnabled = gl.glIsEnabled(name); + final int glerr = gl.glGetError(); + if(GL.GL_NO_ERROR != glerr) { + System.err.println("glIsEnabled(0x"+Integer.toHexString(name)+") -> error 0x"+Integer.toHexString(glerr)); + } + } catch (final Exception e) { + System.err.println("Caught exception: "+e.getMessage()); + // e.printStackTrace(); + } + return isEnabled; + } + public static void dump(final GLAutoDrawable drawable) { + final float[] vf = new float[] { 0f }; + final byte[] vb = new byte[] { 0 }; + final int[] vi = new int[] { 0, 0 }; + + System.out.println("GL MSAA SETUP:"); + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + final GLCapabilitiesImmutable caps = drawable.getChosenGLCapabilities(); + System.out.println(" Caps realised "+caps); + System.out.println(" Caps sample buffers "+caps.getSampleBuffers()+", samples "+caps.getNumSamples()); + + System.out.println(" GL MULTISAMPLE "+glIsEnabled(gl, GL.GL_MULTISAMPLE)); + // sample buffers min 0, same as GLX_SAMPLE_BUFFERS_ARB or WGL_SAMPLE_BUFFERS_ARB + gl.glGetIntegerv(GL.GL_SAMPLE_BUFFERS, vi, 0); + // samples min 0 + gl.glGetIntegerv(GL.GL_SAMPLES, vi, 1); + System.out.println(" GL SAMPLE_BUFFERS "+vi[0]+", SAMPLES "+vi[1]); + + System.out.println("GL CSAA SETUP:"); + // default FALSE + System.out.println(" GL SAMPLE COVERAGE "+glIsEnabled(gl, GL.GL_SAMPLE_COVERAGE)); + // default FALSE + System.out.println(" GL SAMPLE_ALPHA_TO_COVERAGE "+glIsEnabled(gl, GL.GL_SAMPLE_ALPHA_TO_COVERAGE)); + // default FALSE + System.out.println(" GL SAMPLE_ALPHA_TO_ONE "+glIsEnabled(gl, GL.GL_SAMPLE_ALPHA_TO_ONE)); + // default FALSE, value 1, invert false + gl.glGetFloatv(GL.GL_SAMPLE_COVERAGE_VALUE, vf, 0); + gl.glGetBooleanv(GL.GL_SAMPLE_COVERAGE_INVERT, vb, 0); + System.out.println(" GL SAMPLE_COVERAGE "+glIsEnabled(gl, GL.GL_SAMPLE_COVERAGE) + + ": SAMPLE_COVERAGE_VALUE "+vf[0]+ + ", SAMPLE_COVERAGE_INVERT "+vb[0]); + dumpBlend(gl); + } + public static void dumpBlend(final GL gl) { + final int[] vi = new int[] { 0, 0, 0, 0 }; + gl.glGetIntegerv(GL.GL_BLEND, vi, 0); + gl.glGetIntegerv(GL.GL_BLEND_SRC_ALPHA, vi, 1); + gl.glGetIntegerv(GL.GL_BLEND_SRC_RGB, vi, 2); + gl.glGetIntegerv(GL.GL_BLEND_DST_RGB, vi, 3); + final boolean blendEnabled = vi[0] == GL.GL_TRUE; + System.out.println("GL_BLEND "+blendEnabled+"/"+glIsEnabled(gl, GL.GL_BLEND) + + " GL_SRC_ALPHA 0x"+Integer.toHexString(vi[1])+ + " GL_SRC_RGB 0x"+Integer.toHexString(vi[2])+ + " GL_DST_RGB 0x"+Integer.toHexString(vi[3])); + } +} diff --git a/src/demos/com/jogamp/opengl/demos/graph/TextRendererGLELBase.java b/src/demos/com/jogamp/opengl/demos/graph/TextRendererGLELBase.java new file mode 100644 index 000000000..61240e4a2 --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/graph/TextRendererGLELBase.java @@ -0,0 +1,291 @@ +/** + * 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.demos.graph; + +import java.io.IOException; + +import com.jogamp.opengl.GL2ES2; +import com.jogamp.opengl.GLAutoDrawable; +import com.jogamp.opengl.GLEventListener; +import com.jogamp.opengl.fixedfunc.GLMatrixFunc; + +import com.jogamp.graph.curve.opengl.GLRegion; +import com.jogamp.graph.curve.opengl.RenderState; +import com.jogamp.graph.curve.opengl.RegionRenderer; +import com.jogamp.graph.curve.opengl.TextRegionUtil; +import com.jogamp.graph.font.Font; +import com.jogamp.graph.font.FontFactory; +import com.jogamp.graph.font.FontScale; +import com.jogamp.graph.font.FontSet; +import com.jogamp.graph.geom.SVertex; +import com.jogamp.graph.geom.plane.AffineTransform; +import com.jogamp.newt.Window; +import com.jogamp.opengl.util.PMVMatrix; + +public abstract class TextRendererGLELBase implements GLEventListener { + public final int renderModes; + + protected final int[] vbaaSampleCount; + protected final float[] staticRGBAColor = new float[] { 1f, 1f, 1f, 1f }; + + private boolean exclusivePMVMatrix = true; + private PMVMatrix sharedPMVMatrix = null; + private RenderState rs = null; + private RegionRenderer.GLCallback enableCallback=null, disableCallback=null; + protected RegionRenderer renderer = null; + protected TextRegionUtil textRenderUtil = null; + + protected final AffineTransform tempT1 = new AffineTransform(); + protected final AffineTransform tempT2 = new AffineTransform(); + + /** scale pixel, default is 1f */ + protected float pixelScale = 1.0f; + + /** dpi display resolution, queried at {@link #init(GLAutoDrawable)} if NEWT, otherwise 96. */ + protected float dpiH = 96; + + boolean flipVerticalInGLOrientation = false; + + /** + * @param fontSet e.g. default is {@link FontFactory#UBUNTU} + * @param fontFamily e.g. default is {@link FontSet#FAMILY_REGULAR} + * @param fontStylebits e.g. default is {@link FontSet#STYLE_NONE} + * @return the resulting font. + */ + public static Font getFont(final int fontSet, final int fontFamily, final int fontStylebits) { + try { + return FontFactory.get(fontSet).get(fontFamily, fontStylebits); + } catch (final IOException e) { + e.printStackTrace(); + } + return null; + } + + /** + * @param renderModes + * @param sampleCount desired multisampling sample count for msaa-rendering. + * @see #setRendererCallbacks(com.jogamp.graph.curve.opengl.RegionRenderer.GLCallback, com.jogamp.graph.curve.opengl.RegionRenderer.GLCallback) + */ + public TextRendererGLELBase(final int renderModes, final int[] sampleCount) { + this.renderModes = renderModes; + this.vbaaSampleCount = sampleCount; + } + + /** + *

+ * Must be called before {@link #init(GLAutoDrawable)}. + *

+ * @param rs + */ + public void setRenderState(final RenderState rs) { this.rs = rs; } + + /** + * In exclusive mode, impl. uses a pixelScale of 1f and orthogonal PMV on window dimensions + * and renderString uses 'height' for '1'. + *

+ * In non-exclusive mode, i.e. shared w/ custom PMV (within another 3d scene), + * it uses the custom pixelScale and renderString uses normalized 'height', i.e. '1'. + *

+ *

+ * Must be called before {@link #init(GLAutoDrawable)}. + *

+ */ + public void setSharedPMVMatrix(final PMVMatrix pmv) { + this.sharedPMVMatrix = pmv; + } + + /** + * See {@link RegionRenderer#create(RenderState, com.jogamp.graph.curve.opengl.RegionRenderer.GLCallback, com.jogamp.graph.curve.opengl.RegionRenderer.GLCallback)}. + *

+ * Must be called before {@link #init(GLAutoDrawable)}. + *

+ */ + public void setRendererCallbacks(final RegionRenderer.GLCallback enable, final RegionRenderer.GLCallback disable) { + this.enableCallback = enable; + this.disableCallback = disable; + } + + public void setFlipVerticalInGLOrientation(final boolean v) { flipVerticalInGLOrientation=v; } + public final RegionRenderer getRenderer() { return renderer; } + public final TextRegionUtil getTextRenderUtil() { return textRenderUtil; } + + @Override + public void init(final GLAutoDrawable drawable) { + if( null == this.rs ) { + exclusivePMVMatrix = null == sharedPMVMatrix; + this.rs = RenderState.createRenderState(SVertex.factory(), sharedPMVMatrix); + } + this.renderer = RegionRenderer.create(rs, enableCallback, disableCallback); + rs.setHintMask(RenderState.BITHINT_GLOBAL_DEPTH_TEST_ENABLED); + this.textRenderUtil = new TextRegionUtil(renderModes); + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + renderer.init(gl); + rs.setColorStatic(staticRGBAColor[0], staticRGBAColor[1], staticRGBAColor[2], staticRGBAColor[3]); + renderer.enable(gl, false); + + final Object upObj = drawable.getUpstreamWidget(); + if( upObj instanceof Window ) { + final float[] dpi = FontScale.perMMToPerInch( ((Window)upObj).getPixelsPerMM(new float[2]) ); + dpiH = dpi[1]; + } + } + + @Override + public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { + if( null != renderer ) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + renderer.enable(gl, true); + if( exclusivePMVMatrix ) { + // renderer.reshapePerspective(gl, 45.0f, width, height, 0.1f, 1000.0f); + renderer.reshapeOrtho(width, height, 0.1f, 1000.0f); + pixelScale = 1.0f; + } else { + renderer.reshapeNotify(width, height); + } + renderer.enable(gl, false); + } + } + + @Override + public abstract void display(GLAutoDrawable drawable); + + @Override + public void dispose(final GLAutoDrawable drawable) { + if( null != renderer ) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + renderer.destroy(gl); + } + } + + int lastRow = -1; + + /** + * + * @param drawable + * @param font + * @param pixelSize Use {@link Font#toPixels(float, float)} for resolution correct pixel-size. + * @param text + * @param column + * @param tx + * @param ty + * @param tz + * @param cacheRegion + */ + public void renderString(final GLAutoDrawable drawable, + final Font font, final float pixelSize, final String text, + final int column, final float tx, final float ty, final float tz, final boolean cacheRegion) { + final int row = lastRow + 1; + renderStringImpl(drawable, font, pixelSize, text, column, row, tx, ty, tz, cacheRegion, null); + } + + public void renderString(final GLAutoDrawable drawable, + final Font font, final float pixelSize, final String text, + final int column, final float tx, final float ty, final float tz, final GLRegion region) { + final int row = lastRow + 1; + renderStringImpl(drawable, font, pixelSize, text, column, row, tx, ty, tz, false, region); + } + + /** + * + * @param drawable + * @param font + * @param pixelSize Use {@link Font#toPixels(float, float)} for resolution correct pixel-size. + * @param text + * @param column + * @param row + * @param tx + * @param ty + * @param tz + * @param cacheRegion + */ + public void renderString(final GLAutoDrawable drawable, + final Font font, final float pixelSize, final String text, + final int column, final int row, + final float tx, final float ty, final float tz, final boolean cacheRegion) { + renderStringImpl(drawable, font, pixelSize, text, column, row, tx, ty, tz, cacheRegion, null); + } + + public void renderString(final GLAutoDrawable drawable, + final Font font, final float pixelSize, final String text, + final int column, final int row, + final float tx, final float ty, final float tz, final GLRegion region) { + renderStringImpl(drawable, font, pixelSize, text, column, row, tx, ty, tz, false, region); + } + + private void renderStringImpl(final GLAutoDrawable drawable, + final Font font, final float pixelSize, final String text, + final int column, final int row, + final float tx, final float ty, final float tz, final boolean cacheRegion, final GLRegion region) { + if( null != renderer ) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + + float dx = tx; + float dy; + + if( !exclusivePMVMatrix ) { + dy = 1f-ty; + } else { + final int height = drawable.getSurfaceHeight(); + dy = height-ty; + } + final float sxy = pixelScale * pixelSize; + final int newLineCount = TextRegionUtil.getCharCount(text, '\n'); + final float lineHeight = font.getLineHeight(); + dx += sxy * font.getAdvanceWidth('X') * column; + dy -= sxy * lineHeight * ( row + 1 ); + + final PMVMatrix pmvMatrix = rs.getMatrix(); + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + if( !exclusivePMVMatrix ) { + pmvMatrix.glPushMatrix(); + } else { + pmvMatrix.glLoadIdentity(); + } + pmvMatrix.glTranslatef(dx, dy, tz); + if( flipVerticalInGLOrientation && drawable.isGLOriented() ) { + pmvMatrix.glScalef(sxy, -1f*sxy, 1.0f); + } else { + pmvMatrix.glScalef(sxy, sxy, 1.0f); + } + renderer.enable(gl, true); + if( cacheRegion ) { + textRenderUtil.drawString3D(gl, renderer, font, text, null, vbaaSampleCount); + } else if( null != region ) { + TextRegionUtil.drawString3D(gl, region, renderer, font, text, null, vbaaSampleCount, tempT1, tempT1); + } else { + TextRegionUtil.drawString3D(gl, renderModes, renderer, font, text, null, vbaaSampleCount, tempT1, tempT1); + } + renderer.enable(gl, false); + + if( !exclusivePMVMatrix ) { + pmvMatrix.glPopMatrix(); + } + lastRow = row + newLineCount; + } + } +} diff --git a/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeMono.ttf b/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeMono.ttf new file mode 100644 index 000000000..c4200565a Binary files /dev/null and b/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeMono.ttf differ diff --git a/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeMonoBold.ttf b/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeMonoBold.ttf new file mode 100644 index 000000000..0bee057ec Binary files /dev/null and b/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeMonoBold.ttf differ diff --git a/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeMonoBoldOblique.ttf b/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeMonoBoldOblique.ttf new file mode 100644 index 000000000..91bbc0e8a Binary files /dev/null and b/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeMonoBoldOblique.ttf differ diff --git a/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeMonoOblique.ttf b/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeMonoOblique.ttf new file mode 100644 index 000000000..3252bdda6 Binary files /dev/null and b/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeMonoOblique.ttf differ diff --git a/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeSans.ttf b/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeSans.ttf new file mode 100644 index 000000000..e56dc6e90 Binary files /dev/null and b/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeSans.ttf differ diff --git a/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeSansBold.ttf b/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeSansBold.ttf new file mode 100644 index 000000000..66e19ecb0 Binary files /dev/null and b/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeSansBold.ttf differ diff --git a/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeSansBoldOblique.ttf b/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeSansBoldOblique.ttf new file mode 100644 index 000000000..de8a9e153 Binary files /dev/null and b/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeSansBoldOblique.ttf differ diff --git a/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeSansOblique.ttf b/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeSansOblique.ttf new file mode 100644 index 000000000..b0357eabb Binary files /dev/null and b/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeSansOblique.ttf differ diff --git a/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeSerif.ttf b/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeSerif.ttf new file mode 100644 index 000000000..dffa1aedb Binary files /dev/null and b/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeSerif.ttf differ diff --git a/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeSerifBold.ttf b/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeSerifBold.ttf new file mode 100644 index 000000000..e2393ad22 Binary files /dev/null and b/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeSerifBold.ttf differ diff --git a/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeSerifBoldItalic.ttf b/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeSerifBoldItalic.ttf new file mode 100644 index 000000000..46bc4695f Binary files /dev/null and b/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeSerifBoldItalic.ttf differ diff --git a/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeSerifItalic.ttf b/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeSerifItalic.ttf new file mode 100644 index 000000000..d173e3566 Binary files /dev/null and b/src/demos/com/jogamp/opengl/demos/graph/fonts/freefont/FreeSerifItalic.ttf differ diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/GPUUISceneGLListener0A.java b/src/demos/com/jogamp/opengl/demos/graph/ui/GPUUISceneGLListener0A.java new file mode 100644 index 000000000..990143de8 --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/graph/ui/GPUUISceneGLListener0A.java @@ -0,0 +1,973 @@ +/** + * Copyright 2010-2023 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.demos.graph.ui; + +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; + +import com.jogamp.opengl.GL; +import com.jogamp.opengl.GL2ES2; +import com.jogamp.opengl.GLAnimatorControl; +import com.jogamp.opengl.GLAutoDrawable; +import com.jogamp.opengl.GLEventListener; +import com.jogamp.opengl.GLPipelineFactory; +import com.jogamp.opengl.GLRunnable; +import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.demos.es2.GearsES2; +import com.jogamp.opengl.demos.graph.FontSetDemos; +import com.jogamp.opengl.demos.graph.MSAATool; +import com.jogamp.common.net.Uri; +import com.jogamp.common.util.IOUtil; +import com.jogamp.common.util.InterruptSource; +import com.jogamp.graph.curve.Region; +import com.jogamp.graph.curve.opengl.RegionRenderer; +import com.jogamp.graph.curve.opengl.RenderState; +import com.jogamp.graph.font.Font; +import com.jogamp.graph.font.FontFactory; +import com.jogamp.graph.font.FontScale; +import com.jogamp.graph.geom.SVertex; +import com.jogamp.graph.ui.gl.Scene; +import com.jogamp.graph.ui.gl.Shape; +import com.jogamp.graph.ui.gl.shapes.Button; +import com.jogamp.graph.ui.gl.shapes.GLButton; +import com.jogamp.graph.ui.gl.shapes.ImageButton; +import com.jogamp.graph.ui.gl.shapes.Label; +import com.jogamp.graph.ui.gl.shapes.MediaButton; +import com.jogamp.graph.ui.gl.shapes.RoundButton; +import com.jogamp.newt.MonitorDevice; +import com.jogamp.newt.Window; +import com.jogamp.newt.event.InputEvent; +import com.jogamp.newt.event.MouseEvent; +import com.jogamp.newt.event.PinchToZoomGesture; +import com.jogamp.newt.event.GestureHandler.GestureEvent; +import com.jogamp.newt.event.MouseEvent.PointerClass; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.math.FloatUtil; +import com.jogamp.opengl.math.VectorUtil; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.av.GLMediaPlayer; +import com.jogamp.opengl.util.av.GLMediaPlayerFactory; +import com.jogamp.opengl.util.texture.ImageSequence; +import com.jogamp.opengl.util.texture.TextureIO; + +public class GPUUISceneGLListener0A implements GLEventListener { + static private final String defaultMediaURL = "http://archive.org/download/BigBuckBunny_328/BigBuckBunny_512kb.mp4"; + + private boolean debug = false; + private boolean trace = false; + + private final float noAADPIThreshold; + private final Scene sceneUICntrl; + + /** -1 == AUTO, TBD @ init(..) */ + private int renderModes; + + private final Font font; + private final Font fontFPS; + private final Uri filmURL; + + private final float sceneDist = 3000f; + private final float zNear = 0.1f, zFar = 7000f; + + private final float relTop = 80f/100f; + private final float relMiddle = 22f/100f; + private final float relLeft = 11f/100f; + + /** Proportional Button Size to Window Height, per-vertical-pixels [PVP] */ + private final float buttonYSizePVP = 0.084f; + private final float buttonXSizePVP = 0.084f; // 0.105f; + private final float fontSizePt = 10f; + /** Proportional Font Size to Window Height for Main Text, per-vertical-pixels [PVP] */ + private final float fontSizeFixedPVP = 0.04f; + /** Proportional Font Size to Window Height for FPS Status Line, per-vertical-pixels [PVP] */ + private final float fontSizeFpsPVP = 0.03f; + private float dpiV = 96; + + /** + * Default DPI threshold value to disable {@link Region#VBAA_RENDERING_BIT VBAA}: {@value} dpi + * @see #GPUUISceneGLListener0A(float) + * @see #GPUUISceneGLListener0A(float, boolean, boolean) + */ + public static final float DefaultNoAADPIThreshold = 200f; + + private int currentText = 0; + + private String actionText = null; + private Label[] labels = null; + private String[] strings = null; + private final List buttons = new ArrayList(); + private int buttonsLeftCount = 0; + private Label truePtSizeLabel = null; + private Label jogampLabel = null; + private Label fpsLabel = null; + + private GLAutoDrawable cDrawable; + + private final GLReadBufferUtil screenshot; + + private final String jogamp = "JogAmp - Jogl Graph Module Demo"; + private final String truePtSize = fontSizePt+" pt font size label - true scale!"; + + private final String longText = "JOGL: Java™ Binding for the OpenGL® API.\n\n"+ + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec \n"+ + "Ut purus odio, rhoncus sit amet commodo eget, ullamcorper vel\n"+ + "quam iaculis urna cursus ornare. Nullam ut felis a ante ultrices\n"+ + "In hac habitasse platea dictumst. Vivamus et mi a quam lacinia\n"+ + "Morbi quis bibendum nibh. Donec lectus orci, sagittis in consequat\n"+ + "Donec ut dolor et nulla tristique varius. In nulla magna, fermentum\n"+ + "in lorem. Maecenas in ipsum ac justo scelerisque sollicitudin.\n"+ + "\n"+ + "Lyford’s in Texas & L’Anse-aux-Griffons in Québec;\n"+ + "Kwikpak on the Yukon delta, Kvæven in Norway, Kyulu in Kenya, not Rwanda.…\n"+ + "Ytterbium in the periodic table. Are Toussaint L’Ouverture, Wölfflin, Wolfe,\n"+ + "\n"+ + "The quick brown fox jumps over the lazy dog\n"; + + /** + * @param renderModes + */ + public GPUUISceneGLListener0A(final int renderModes) { + this(null, null, renderModes, false, false); + } + + /** + * @param filmURL TODO + * @param renderModes + * @param debug + * @param trace + */ + public GPUUISceneGLListener0A(final String fontfilename, final String filmURL, final int renderModes, final boolean debug, final boolean trace) { + this(fontfilename, filmURL, 0f, renderModes, debug, trace); + } + + /** + * @param filmURL TODO + * @param noAADPIThreshold see {@link #DefaultNoAADPIThreshold} + * @param debug + * @param trace + */ + public GPUUISceneGLListener0A(final String fontfilename, final String filmURL, final float noAADPIThreshold, final boolean debug, final boolean trace) { + this(fontfilename, filmURL, noAADPIThreshold, 0, debug, trace); + } + + private GPUUISceneGLListener0A(final String fontfilename, final String filmURL, final float noAADPIThreshold, final int renderModes, final boolean debug, final boolean trace) { + this.noAADPIThreshold = noAADPIThreshold; + this.debug = debug; + this.trace = trace; + + this.renderModes = renderModes; + + try { + if( null == fontfilename ) { + font = FontFactory.get(IOUtil.getResource("fonts/freefont/FreeSerif.ttf", + FontSetDemos.class.getClassLoader(), FontSetDemos.class).getInputStream(), true); + } else { + font = FontFactory.get( new File( fontfilename ) ); + } + System.err.println("Font "+font.getFullFamilyName()); + + fontFPS = FontFactory.get(IOUtil.getResource("fonts/freefont/FreeMonoBold.ttf", + FontSetDemos.class.getClassLoader(), FontSetDemos.class).getInputStream(), true); + System.err.println("Font FPS "+fontFPS.getFullFamilyName()); + + } catch (final IOException ioe) { + throw new RuntimeException(ioe); + } + try { + this.filmURL = Uri.cast( null != filmURL ? filmURL : defaultMediaURL ); + } catch (final URISyntaxException e1) { + throw new RuntimeException(e1); + } + { + final RenderState rs = RenderState.createRenderState(SVertex.factory()); + final RegionRenderer renderer = RegionRenderer.create(rs, RegionRenderer.defaultBlendEnable, RegionRenderer.defaultBlendDisable); + rs.setHintMask(RenderState.BITHINT_GLOBAL_DEPTH_TEST_ENABLED); + // renderer = RegionRenderer.create(rs, null, null); + + sceneUICntrl = new Scene(renderer, sceneDist, zNear, zFar); + // sceneUIController.setSampleCount(3); // easy on embedded devices w/ just 3 samples (default is 4)? + } + screenshot = new GLReadBufferUtil(false, false); + } + + private void rotateButtons(float[] angdeg) { + angdeg = VectorUtil.scaleVec3(angdeg, angdeg, FloatUtil.PI / 180.0f); + for(int i=0; i "+buttonXSize+" x "+buttonYSize); + final float xStartLeft = 0f; // aligned to left edge w/ space via reshape + final float yStartTop = 0f; // aligned to top edge w/ space via reshape + final float diffX = 1.2f * buttonXSize; + final float diffY = 1.5f * buttonYSize; + + Button button = new Button(SVertex.factory(), renderModes, font, "Next Text", buttonXSize, buttonYSize); + button.setName(BUTTON_NEXTTEXT); + button.move(xStartLeft,yStartTop-diffY*buttons.size(), 0f); + button.addMouseListener(new Shape.MouseGestureAdapter() { + @Override + public void mouseClicked(final MouseEvent e) { + if( null != labels[currentText] ) { + labels[currentText].setEnabled(false); + } + currentText = (currentText+1)%labels.length; + if( null != labels[currentText] ) { + labels[currentText].setEnabled(true); + } + } } ); + button.addMouseListener(dragZoomRotateListener); + buttons.add(button); + + button = new Button(SVertex.factory(), renderModes, font, "Show FPS", buttonXSize, buttonYSize); + button.setName(BUTTON_FPS); + button.move(xStartLeft,yStartTop - diffY*buttons.size(), 0f); + button.setToggleable(true); + button.setToggle(fpsLabel.isEnabled()); + button.addMouseListener(new Shape.MouseGestureAdapter() { + @Override + public void mouseClicked(final MouseEvent e) { + final GLAnimatorControl a = cDrawable.getAnimator(); + if( null != a ) { + a.resetFPSCounter(); + } + fpsLabel.setEnabled(!fpsLabel.isEnabled()); + } } ); + button.addMouseListener(dragZoomRotateListener); + buttons.add(button); + + button = new Button(SVertex.factory(), renderModes, font, "V-Sync", buttonXSize, buttonYSize); + button.setName(BUTTON_VSYNC); + button.move(xStartLeft,yStartTop - diffY*buttons.size(), 0f); + button.setToggleable(true); + button.setToggle(gl.getSwapInterval()>0); + button.addMouseListener(new Shape.MouseGestureAdapter() { + @Override + public void mouseClicked(final MouseEvent e) { + cDrawable.invoke(false, new GLRunnable() { + @Override + public boolean run(final GLAutoDrawable drawable) { + final GL gl = drawable.getGL(); + gl.setSwapInterval(gl.getSwapInterval()<=0?1:0); + final GLAnimatorControl a = drawable.getAnimator(); + if( null != a ) { + a.resetFPSCounter(); + } + return true; + } + }); + } } ); + button.addMouseListener(dragZoomRotateListener); + buttons.add(button); + + button = new Button(SVertex.factory(), renderModes, font, "< Tilt >", buttonXSize, buttonYSize); + button.move(xStartLeft,yStartTop - diffY*buttons.size(), 0f); + button.addMouseListener(new Shape.MouseGestureAdapter() { + @Override + public void mouseClicked(final MouseEvent e) { + final Shape.EventInfo shapeEvent = (Shape.EventInfo) e.getAttachment(); + if( shapeEvent.objPos[0] < shapeEvent.shape.getBounds().getCenter()[0] ) { + rotateButtons(new float[] { 0f, -5f, 0f}); // left-half pressed + } else { + rotateButtons(new float[] { 0f, 5f, 0f}); // right-half pressed + } + } + @Override + public void mouseWheelMoved(final MouseEvent e) { + rotateButtons(new float[] { 0f, e.getRotation()[1], 0f}); + } } ); + buttons.add(button); + + if( pass2Mode ) { // second column to the left + button = new Button(SVertex.factory(), renderModes, font, "< Samples >", buttonXSize, buttonYSize); + button.move(xStartLeft,yStartTop - diffY*buttons.size(), 0f); + button.addMouseListener(new Shape.MouseGestureAdapter() { + @Override + public void mouseClicked(final MouseEvent e) { + final Shape.EventInfo shapeEvent = (Shape.EventInfo) e.getAttachment(); + int sampleCount = sceneUICntrl.getSampleCount(); + if( shapeEvent.objPos[0] < shapeEvent.shape.getBounds().getCenter()[0] ) { + // left-half pressed + sampleCount--; + } else { + // right-half pressed + sampleCount++; + } + sampleCount = sceneUICntrl.setSampleCount(sampleCount); // validated / clipped + } } ); + button.addMouseListener(dragZoomRotateListener); + buttons.add(button); + + button = new Button(SVertex.factory(), renderModes, font, "< Quality >", buttonXSize, buttonYSize); + button.move(xStartLeft,yStartTop - diffY*buttons.size(), 0f); + button.addMouseListener(new Shape.MouseGestureAdapter() { + @Override + public void mouseClicked(final MouseEvent e) { + final Shape.EventInfo shapeEvent = (Shape.EventInfo) e.getAttachment(); + int quality = shapeEvent.shape.getQuality(); + + if( shapeEvent.objPos[0] < shapeEvent.shape.getBounds().getCenter()[0] ) { + // left-half pressed + if( quality > 0 ) { + quality--; + } + } else { + // right-half pressed + if( quality < Region.MAX_QUALITY ) { + quality++; + } + } + sceneUICntrl.setAllShapesQuality(quality); + } } ); + button.addMouseListener(dragZoomRotateListener); + buttons.add(button); + } + + button = new Button(SVertex.factory(), renderModes, font, "Quit", buttonXSize, buttonYSize); + button.setName(BUTTON_QUIT); + button.move(xStartLeft,yStartTop - diffY*buttons.size(), 0f); + button.setColor(0.7f, 0.0f, 0.0f, 1.0f); + button.setLabelColor(1.2f, 1.2f, 1.2f); + button.setPressedColorMod(1.1f, 0.0f, 0.0f, 1.0f); + button.addMouseListener(new Shape.MouseGestureAdapter() { + @Override + public void mouseClicked(final MouseEvent e) { + new InterruptSource.Thread() { + @Override + public void run() { + if( null != cDrawable ) { + final GLAnimatorControl actrl = cDrawable.getAnimator(); + if( null != actrl ) { + actrl.stop(); + } + cDrawable.destroy(); + } + } }.start(); + } } ); + button.addMouseListener(dragZoomRotateListener); + buttons.add(button); + + // second column to the left + { + final int j = 1; // column + int k = 0; // row + button = new Button(SVertex.factory(), renderModes, font, "Y Flip", buttonXSize, buttonYSize); + button.move(xStartLeft - diffX*j,yStartTop - diffY*k, 0f); + button.addMouseListener(new Shape.MouseGestureAdapter() { + @Override + public void mouseClicked(final MouseEvent e) { + rotateButtons(new float[] { 0f, 180f, 0f}); + } } ); + button.addMouseListener(dragZoomRotateListener); + buttons.add(button); + + k++; + button = new Button(SVertex.factory(), renderModes, font, "X Flip", buttonXSize, buttonYSize); + button.move(xStartLeft - diffX*j,yStartTop - diffY*k, 0f); + button.addMouseListener(new Shape.MouseGestureAdapter() { + @Override + public void mouseClicked(final MouseEvent e) { + rotateButtons(new float[] { 180f, 0f, 0f}); + } } ); + button.addMouseListener(dragZoomRotateListener); + buttons.add(button); + k++; + + button = new Button(SVertex.factory(), renderModes, font, "+", buttonXSize, buttonYSize); + button.move(xStartLeft - diffX*j,yStartTop - diffY*k, 0f); + button.addMouseListener(new Shape.MouseGestureAdapter() { + @Override + public void mouseClicked(final MouseEvent e) { + final Shape.EventInfo shapeEvent = (Shape.EventInfo) e.getAttachment(); + // rel position to center + final float dx = shapeEvent.objPos[0] - shapeEvent.shape.getBounds().getCenter()[0] ; + final float dy = shapeEvent.objPos[1] - shapeEvent.shape.getBounds().getCenter()[1] ; + // per-cent position to center (remove dependency on dimension) + final float awdx = Math.abs(dx)/shapeEvent.shape.getBounds().getWidth(); + final float awdy = Math.abs(dy)/shapeEvent.shape.getBounds().getHeight(); + float tx = 0, ty = 0; + if ( awdx > awdy ) { + tx = dx < 0 ? -5 : 5; + } else { + ty = dy < 0 ? -5 : 5; + } + translateButtons(tx, ty, 0f); + } } ); + button.addMouseListener(dragZoomRotateListener); + buttons.add(button); + k++; + + button = new Button(SVertex.factory(), renderModes, font, "< Space >", buttonXSize, buttonYSize); + button.move(xStartLeft - diffX*j,yStartTop - diffY*k, 0f); + button.addMouseListener(new Shape.MouseGestureAdapter() { + @Override + public void mouseClicked(final MouseEvent e) { + final Shape.EventInfo shapeEvent = (Shape.EventInfo) e.getAttachment(); + final float dx, dy; + if( shapeEvent.objPos[0] < shapeEvent.shape.getBounds().getCenter()[0] ) { + dx=-0.01f; dy=-0.005f; + } else { + dx=0.01f; dy=0.005f; + } + setButtonsSpacing(dx, dy); + } + @Override + public void mouseWheelMoved(final MouseEvent e) { + setButtonsSpacing(e.getRotation()[0]/100f, e.getRotation()[1]/200f); + } } ); + buttons.add(button); + k++; + + button = new Button(SVertex.factory(), renderModes, font, "< Corner >", buttonXSize, buttonYSize); + button.move(xStartLeft - diffX*j,yStartTop - diffY*k, 0f); + button.addMouseListener(new Shape.MouseGestureAdapter() { + @Override + public void mouseClicked(final MouseEvent e) { + final Shape.EventInfo shapeEvent = (Shape.EventInfo) e.getAttachment(); + final float dc; + if( shapeEvent.objPos[0] < shapeEvent.shape.getBounds().getCenter()[0] ) { + dc=-0.1f; + } else { + dc=0.1f; + } + setButtonsCorner(dc); + } + @Override + public void mouseWheelMoved(final MouseEvent e) { + setButtonsCorner(e.getRotation()[1]/20f); + } } ); + buttons.add(button); + k++; + + button = new Button(SVertex.factory(), renderModes, font, "Reset", buttonXSize, buttonYSize); + button.move(xStartLeft - diffX*j,yStartTop - diffY*k, 0f); + button.addMouseListener(new Shape.MouseGestureAdapter() { + @Override + public void mouseClicked(final MouseEvent e) { + resetButtons(); + } } ); + button.addMouseListener(dragZoomRotateListener); + buttons.add(button); + k++; + + button = new Button(SVertex.factory(), renderModes, font, "Snapshot", buttonXSize, buttonYSize); + button.move(xStartLeft - diffX*j,yStartTop - diffY*k, 0f); + button.addMouseListener(new Shape.MouseGestureAdapter() { + @Override + public void mouseClicked(final MouseEvent e) { + cDrawable.invoke(false, new GLRunnable() { + @Override + public boolean run(final GLAutoDrawable drawable) { + printScreen(drawable.getGL()); + return true; + } + }); + } } ); + button.addMouseListener(dragZoomRotateListener); + buttons.add(button); + k++; + } + + buttonsLeftCount = buttons.size(); + + final float button2XSize = 2f*buttonXSize; + final float button2YSize = 2f*buttonYSize; + final float xStartRight = -button2XSize - 8f; // aligned to right edge via reshape + final int texUnitMediaPlayer, texUnitImageButton, texUnitGLELButton; + { + // works - but not required .. + texUnitMediaPlayer=1; + texUnitImageButton=2; + texUnitGLELButton=3; + } + + if( true ) { + final GLMediaPlayer mPlayer = GLMediaPlayerFactory.createDefault(); + mPlayer.setTextureUnit(texUnitMediaPlayer); + final MediaButton mPlayerButton = new MediaButton(sceneUICntrl.getVertexFactory(), renderModes, + button2XSize, button2YSize, mPlayer); + mPlayerButton.setName(BUTTON_MOVIE); + mPlayerButton.setVerbose(true); + mPlayerButton.addDefaultEventListener(); + mPlayerButton.move(xStartRight, yStartTop - diffY*1, 0f); + mPlayerButton.setToggleable(true); + mPlayerButton.setToggle(false); // toggle == false -> mute audio + mPlayerButton.setToggleOffColorMod(0f, 1f, 0f, 1.0f); + mPlayerButton.addMouseListener(dragZoomRotateListener); + mPlayerButton.addMouseListener(new Shape.MouseGestureAdapter() { + @Override + public void mouseClicked(final MouseEvent e) { + mPlayer.setAudioVolume( mPlayerButton.isToggleOn() ? 1f : 0f ); + } } ); + buttons.add(mPlayerButton); + mPlayer.initStream(filmURL, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.TEXTURE_COUNT_DEFAULT); + } + if( true ) { + final ImageSequence imgSeq = new ImageSequence(texUnitImageButton, true); + final ImageButton imgButton = new ImageButton(sceneUICntrl.getVertexFactory(), renderModes, + button2XSize, button2YSize, imgSeq); + try { + imgSeq.addFrame(gl, GPUUISceneGLListener0A.class, "button-released-145x53.png", TextureIO.PNG); + imgSeq.addFrame(gl, GPUUISceneGLListener0A.class, "button-pressed-145x53.png", TextureIO.PNG); + } catch (final IOException e2) { + e2.printStackTrace(); + } + imgSeq.setManualStepping(true); + imgButton.move(xStartRight, yStartTop - diffY*2.5f, 0f); + imgButton.addMouseListener(dragZoomRotateListener); + imgButton.addMouseListener(new Shape.MouseGestureAdapter() { + @Override + public void mousePressed(final MouseEvent e) { + imgButton.setCurrentIdx(1); + System.err.println("XXX: "+imgButton); + } + @Override + public void mouseReleased(final MouseEvent e) { + imgButton.setCurrentIdx(0); + } } ); + buttons.add(imgButton); + } + if( true ) { + // Issues w/ OSX and NewtCanvasAWT when rendering / animating + // Probably related to CALayer - FBO - FBO* (of this button) + final GLEventListener glel; + { + final GearsES2 gears = new GearsES2(0); + gears.setVerbose(false); + gears.setClearColor(new float[] { 0.9f, 0.9f, 0.9f, 1f } ); + glel = gears; + } + final GLButton glelButton = new GLButton(sceneUICntrl.getVertexFactory(), renderModes, + button2XSize, button2YSize, + texUnitGLELButton, glel, false /* useAlpha */, + (int)(button2XSize), (int)(button2YSize)); + glelButton.setName(BUTTON_GLEL); + glelButton.setToggleable(true); + glelButton.setToggle(false); // toggle == true -> animation + glelButton.setAnimate(false); + glelButton.move(xStartRight, yStartTop - diffY*4f, 0f); + glelButton.addMouseListener(dragZoomRotateListener); + glelButton.addMouseListener(new Shape.MouseGestureAdapter() { + @Override + public void mouseClicked(final MouseEvent e) { + glelButton.setAnimate( glelButton.isToggleOn() ); + } } ); + buttons.add(glelButton); + } + } + + private void initTexts() { + strings = new String[4]; + int i = 0; + + strings[i++] = "- Mouse Scroll Over Object\n"+ + " - General\n"+ + " - Z Translation\n"+ + " - Ctrl: Y-Rotation (Shift: X-Rotation)\n"+ + " - Tilt, Space and Corner\n"+ + " - Their respective action via wheel\n"+ + " (shift = other value)\n"+ + "\n"+ + "- Mouse Drag On Object\n"+ + " - Click on Object and drag mouse\n"+ + " - Current postion in status line at bottom\n"+ + "\n"+ + "- Tilt Button Rotate Whole Button Group"; + + strings[i++] = "abcdefghijklmn\nopqrstuvwxyz\n"+ + "ABCDEFGHIJKL\n"+ + "MNOPQRSTUVWXYZ\n"+ + "0123456789.:,;(*!?/\\\")$%^&-+@~#<>{}[]"; + + strings[i++] = "The quick brown fox jumps over the lazy dog"; + + strings[i++] = longText; + + labels = new Label[i]; + + currentText = strings.length - 1; + } + + + private static final boolean enableOthers = true; + private static final boolean reshape_ui = false; // incomplete: button positioning + + + private void setupUI(final GLAutoDrawable drawable) { + final float pixelSizeFixed = fontSizeFixedPVP * drawable.getSurfaceHeight(); + jogampLabel = new Label(sceneUICntrl.getVertexFactory(), renderModes, font, pixelSizeFixed, jogamp); + jogampLabel.addMouseListener(dragZoomRotateListener); + sceneUICntrl.addShape(jogampLabel); + jogampLabel.setEnabled(enableOthers); + + final float pixelSize10Pt = FontScale.toPixels(fontSizePt, dpiV); + System.err.println("10Pt PixelSize: Display "+dpiV+" dpi, fontSize "+fontSizePt+" ppi -> "+pixelSize10Pt+" pixel-size"); + truePtSizeLabel = new Label(sceneUICntrl.getVertexFactory(), renderModes, font, pixelSize10Pt, truePtSize); + sceneUICntrl.addShape(truePtSizeLabel); + truePtSizeLabel.setEnabled(enableOthers); + truePtSizeLabel.move(0, - 1.5f * jogampLabel.getLineHeight(), 0f); + truePtSizeLabel.setColor(0.1f, 0.1f, 0.1f, 1.0f); + + /** + * + * [Label] Display 112.88889 dpi, fontSize 12.0 ppi -> pixelSize 18.814816 + * [FPS] Display 112.88889 dpi, fontSize 12.0 ppi -> pixelSize 15.679012 + */ + final float pixelSizeFPS = fontSizeFpsPVP * drawable.getSurfaceHeight(); + fpsLabel = new Label(sceneUICntrl.getVertexFactory(), renderModes, fontFPS, pixelSizeFPS, "Nothing there yet"); + fpsLabel.addMouseListener(dragZoomRotateListener); + sceneUICntrl.addShape(fpsLabel); + fpsLabel.setEnabled(enableOthers); + fpsLabel.setColor(0.1f, 0.1f, 0.1f, 1.0f); + fpsLabel.move(0f, pixelSizeFPS * (fontFPS.getMetrics().getLineGap() - fontFPS.getMetrics().getDescent()), 0f); + + initButtons(drawable.getGL().getGL2ES2(), drawable.getSurfaceWidth(), drawable.getSurfaceHeight()); + for(int i=0; i "+pixelSize10Pt+" pixel-size"); + truePtSizeLabel.setPixelSize(pixelSize10Pt); + + /** + * + * [Label] Display 112.88889 dpi, fontSize 12.0 ppi -> pixelSize 18.814816 + * [FPS] Display 112.88889 dpi, fontSize 12.0 ppi -> pixelSize 15.679012 + */ + final float pixelSizeFPS = fontSizeFpsPVP * drawable.getSurfaceHeight(); + fpsLabel.setPixelSize(pixelSizeFPS); + + final float buttonXSize = buttonXSizePVP * drawable.getSurfaceWidth(); + // final float buttonYSize = buttonYSizePVP * height; + final float buttonYSize = buttonXSize / 2.5f; + final float button2XSize = 2f*buttonXSize; + final float button2YSize = 2f*buttonYSize; + + for(int i=0; i= noAADPIThreshold; + final String noAAs = noAA ? " >= " : " < "; + System.err.println("AUTO RenderMode: dpi "+dpiV+noAAs+noAADPIThreshold+" -> noAA "+noAA); + renderModes = noAA ? 0 : Region.VBAA_RENDERING_BIT; + } + if(drawable instanceof GLWindow) { + System.err.println("GPUUISceneGLListener0A: init (1)"); + final GLWindow glw = (GLWindow) drawable; + sceneUICntrl.attachInputListenerTo(glw); + } else { + System.err.println("GPUUISceneGLListener0A: init (0)"); + } + cDrawable = drawable; + GL2ES2 gl = drawable.getGL().getGL2ES2(); + if(debug) { + gl = gl.getContext().setGL( GLPipelineFactory.create("com.jogamp.opengl.Debug", null, gl, null) ).getGL2ES2(); + } + if(trace) { + gl = gl.getContext().setGL( GLPipelineFactory.create("com.jogamp.opengl.Trace", null, gl, new Object[] { System.err } ) ).getGL2ES2(); + } + System.err.println(JoglVersion.getGLInfo(gl, null, false /* withCapsAndExts */).toString()); + System.err.println("VSync Swap Interval: "+gl.getSwapInterval()); + System.err.println("Chosen: "+drawable.getChosenGLCapabilities()); + MSAATool.dump(drawable); + + gl.setSwapInterval(1); + gl.glEnable(GL.GL_DEPTH_TEST); + gl.glEnable(GL.GL_BLEND); + + initTexts(); + + sceneUICntrl.init(drawable); + + final GLAnimatorControl a = drawable.getAnimator(); + if( null != a ) { + a.resetFPSCounter(); + } + + setupUI(drawable); + } + + @Override + public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { + System.err.println("GPUUISceneGLListener0A: reshape"); + + // + // Layout all shapes: Relational move regarding window coordinates + // + final float dw = width - lastWidth; + final float dh = height - lastHeight; + + final float dz = 0f; + final float dyTop = dh * relTop; + final float dxLeft = dw * relLeft; + final float dxRight = dw; + + if( reshape_ui ) { + reshapeUI(drawable); + } + for(int i=0; i 0 ) { + caps.setSampleBuffers(true); + caps.setNumSamples(SceneMSAASamples); + } + System.out.println("Requested: " + caps); + + final int rmode; + if( GraphVBAAMode ) { + rmode = Region.VBAA_RENDERING_BIT; + } else if( GraphMSAAMode ) { + rmode = Region.MSAA_RENDERING_BIT; + } else { + rmode = 0; + } + + final GLWindow window = GLWindow.create(screen, caps); + if( 0 == SceneMSAASamples ) { + window.setCapabilitiesChooser(new NonFSAAGLCapsChooser(true)); + } + window.setSize(width, height); + window.setTitle("GraphUI Newt Demo: graph["+Region.getRenderModeString(rmode)+"], msaa "+SceneMSAASamples); + window.setSurfaceScale(reqSurfacePixelScale); + // final float[] valReqSurfacePixelScale = window.getRequestedSurfaceScale(new float[2]); + + final GPUUISceneGLListener0A scene = 0 < GraphAutoMode ? new GPUUISceneGLListener0A(fontfilename, filmURL, GraphAutoMode, DEBUG, TRACE) : + new GPUUISceneGLListener0A(fontfilename, filmURL, rmode, DEBUG, TRACE); + + window.addGLEventListener(scene); + scene.attachInputListenerTo(window); + + final Animator animator = new Animator(); + animator.setUpdateFPSFrames(5*60, null); + animator.add(window); + + window.addWindowListener(new WindowAdapter() { + @Override + public void windowDestroyed(final WindowEvent e) { + animator.stop(); + } + }); + + window.setVisible(true); + animator.start(); + + // sleep(3000); + // final UIShape movie = scene.getWidget(GPUUISceneGLListener0A.BUTTON_MOVIE); + } + +} diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/GPUUISceneTextAnim01.java b/src/demos/com/jogamp/opengl/demos/graph/ui/GPUUISceneTextAnim01.java new file mode 100644 index 000000000..45bfd53f1 --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/graph/ui/GPUUISceneTextAnim01.java @@ -0,0 +1,351 @@ +/** + * Copyright 2010-2023 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.demos.graph.ui; + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.Locale; + +import com.jogamp.common.util.IOUtil; +import com.jogamp.graph.curve.Region; +import com.jogamp.graph.curve.opengl.RegionRenderer; +import com.jogamp.graph.curve.opengl.RenderState; +import com.jogamp.graph.font.Font; +import com.jogamp.graph.font.FontFactory; +import com.jogamp.graph.font.FontScale; +import com.jogamp.graph.geom.SVertex; +import com.jogamp.graph.ui.gl.Scene; +import com.jogamp.graph.ui.gl.Shape; +import com.jogamp.graph.ui.gl.shapes.Label; +import com.jogamp.newt.MonitorDevice; +import com.jogamp.newt.Window; +import com.jogamp.newt.event.GestureHandler.GestureEvent; +import com.jogamp.newt.event.InputEvent; +import com.jogamp.newt.event.MouseEvent; +import com.jogamp.newt.event.MouseEvent.PointerClass; +import com.jogamp.newt.event.PinchToZoomGesture; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.GL; +import com.jogamp.opengl.GL2ES2; +import com.jogamp.opengl.GLAnimatorControl; +import com.jogamp.opengl.GLAutoDrawable; +import com.jogamp.opengl.GLEventListener; +import com.jogamp.opengl.GLPipelineFactory; +import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.demos.graph.FontSetDemos; +import com.jogamp.opengl.demos.graph.MSAATool; +import com.jogamp.opengl.math.FloatUtil; +import com.jogamp.opengl.math.VectorUtil; +import com.jogamp.opengl.util.GLReadBufferUtil; + +public class GPUUISceneTextAnim01 implements GLEventListener { + + private boolean debug = false; + private boolean trace = false; + + private final float noAADPIThreshold; + private final Scene sceneUICntrl; + + /** -1 == AUTO, TBD @ init(..) */ + private int renderModes; + + private final Font font; + private final Font fontFPS; + + private final float sceneDist = 3000f; + private final float zNear = 0.1f, zFar = 7000f; + + // private final float relTop = 80f/100f; + private final float relMiddle = 22f/100f; + // private final float relLeft = 11f/100f; + + private final float fontSizePt = 10f; + /** Proportional Font Size to Window Height for Main Text, per-vertical-pixels [PVP] */ + private final float fontSizeFixedPVP = 0.04f; + /** Proportional Font Size to Window Height for FPS Status Line, per-vertical-pixels [PVP] */ + private final float fontSizeFpsPVP = 0.03f; + private float dpiV = 96; + + /** + * Default DPI threshold value to disable {@link Region#VBAA_RENDERING_BIT VBAA}: {@value} dpi + * @see #GPUUISceneGLListener0A(float) + * @see #GPUUISceneGLListener0A(float, boolean, boolean) + */ + public static final float DefaultNoAADPIThreshold = 200f; + + private String actionText = null; + private Label jogampLabel = null; + private Label fpsLabel = null; + + // private GLAutoDrawable cDrawable; + + private final GLReadBufferUtil screenshot; + + private final String jogamp = "JogAmp - Jogl Graph Module Demo"; + + // private final String longText = "JOGL: Java™ Binding for the OpenGL® API."; + + public GPUUISceneTextAnim01(final String fontfilename, final float noAADPIThreshold, final int renderModes, final boolean debug, final boolean trace) { + this.noAADPIThreshold = noAADPIThreshold; + this.debug = debug; + this.trace = trace; + + this.renderModes = renderModes; + + try { + if( null == fontfilename ) { + font = FontFactory.get(IOUtil.getResource("fonts/freefont/FreeSerif.ttf", + FontSetDemos.class.getClassLoader(), FontSetDemos.class).getInputStream(), true); + } else { + font = FontFactory.get( new File( fontfilename ) ); + } + System.err.println("Font "+font.getFullFamilyName()); + + fontFPS = FontFactory.get(IOUtil.getResource("fonts/freefont/FreeMonoBold.ttf", + FontSetDemos.class.getClassLoader(), FontSetDemos.class).getInputStream(), true); + System.err.println("Font FPS "+fontFPS.getFullFamilyName()); + + } catch (final IOException ioe) { + throw new RuntimeException(ioe); + } + + { + final RenderState rs = RenderState.createRenderState(SVertex.factory()); + final RegionRenderer renderer = RegionRenderer.create(rs, RegionRenderer.defaultBlendEnable, RegionRenderer.defaultBlendDisable); + rs.setHintMask(RenderState.BITHINT_GLOBAL_DEPTH_TEST_ENABLED); + // renderer = RegionRenderer.create(rs, null, null); + + sceneUICntrl = new Scene(renderer, sceneDist, zNear, zFar); + // sceneUIController.setSampleCount(3); // easy on embedded devices w/ just 3 samples (default is 4)? + } + screenshot = new GLReadBufferUtil(false, false); + } + + private void setupUI(final GLAutoDrawable drawable) { + final float pixelSizeFixed = fontSizeFixedPVP * drawable.getSurfaceHeight(); + jogampLabel = new Label(sceneUICntrl.getVertexFactory(), renderModes, font, pixelSizeFixed, jogamp); + jogampLabel.addMouseListener(dragZoomRotateListener); + sceneUICntrl.addShape(jogampLabel); + jogampLabel.setEnabled(true); + + final float pixelSize10Pt = FontScale.toPixels(fontSizePt, dpiV); + System.err.println("10Pt PixelSize: Display "+dpiV+" dpi, fontSize "+fontSizePt+" ppi -> "+pixelSize10Pt+" pixel-size"); + + /** + * + * [Label] Display 112.88889 dpi, fontSize 12.0 ppi -> pixelSize 18.814816 + * [FPS] Display 112.88889 dpi, fontSize 12.0 ppi -> pixelSize 15.679012 + */ + final float pixelSizeFPS = fontSizeFpsPVP * drawable.getSurfaceHeight(); + fpsLabel = new Label(sceneUICntrl.getVertexFactory(), renderModes, fontFPS, pixelSizeFPS, "Nothing there yet"); + fpsLabel.addMouseListener(dragZoomRotateListener); + sceneUICntrl.addShape(fpsLabel); + fpsLabel.setEnabled(true); + fpsLabel.setColor(0.1f, 0.1f, 0.1f, 1.0f); + fpsLabel.move(0f, pixelSizeFPS * (fontFPS.getMetrics().getLineGap() - fontFPS.getMetrics().getDescent()), 0f); + } + + @Override + public void init(final GLAutoDrawable drawable) { + final Object upObj = drawable.getUpstreamWidget(); + if( upObj instanceof Window ) { + final Window upWin = (Window)upObj; + final MonitorDevice monitor = upWin.getMainMonitor(); + final float[] monitorDPI = MonitorDevice.perMMToPerInch( monitor.getPixelsPerMM(new float[2]) ); + final float[] sDPI = MonitorDevice.perMMToPerInch( upWin.getPixelsPerMM(new float[2]) ); + dpiV = sDPI[1]; + System.err.println("Monitor detected: "+monitor); + System.err.println("Monitor dpi: "+monitorDPI[0]+" x "+monitorDPI[1]); + System.err.println("Surface scale: native "+Arrays.toString(upWin.getMaximumSurfaceScale(new float[2]))+", current "+Arrays.toString(upWin.getCurrentSurfaceScale(new float[2]))); + System.err.println("Surface dpi "+sDPI[0]+" x "+sDPI[1]); + } else { + System.err.println("Using default DPI of "+dpiV); + } + if( 0 == renderModes && !FloatUtil.isZero(noAADPIThreshold, FloatUtil.EPSILON)) { + final boolean noAA = dpiV >= noAADPIThreshold; + final String noAAs = noAA ? " >= " : " < "; + System.err.println("AUTO RenderMode: dpi "+dpiV+noAAs+noAADPIThreshold+" -> noAA "+noAA); + renderModes = noAA ? 0 : Region.VBAA_RENDERING_BIT; + } + if(drawable instanceof GLWindow) { + System.err.println("GPUUISceneGLListener0A: init (1)"); + final GLWindow glw = (GLWindow) drawable; + sceneUICntrl.attachInputListenerTo(glw); + } else { + System.err.println("GPUUISceneGLListener0A: init (0)"); + } + // cDrawable = drawable; + GL2ES2 gl = drawable.getGL().getGL2ES2(); + if(debug) { + gl = gl.getContext().setGL( GLPipelineFactory.create("com.jogamp.opengl.Debug", null, gl, null) ).getGL2ES2(); + } + if(trace) { + gl = gl.getContext().setGL( GLPipelineFactory.create("com.jogamp.opengl.Trace", null, gl, new Object[] { System.err } ) ).getGL2ES2(); + } + System.err.println(JoglVersion.getGLInfo(gl, null, false /* withCapsAndExts */).toString()); + System.err.println("VSync Swap Interval: "+gl.getSwapInterval()); + System.err.println("Chosen: "+drawable.getChosenGLCapabilities()); + MSAATool.dump(drawable); + + gl.setSwapInterval(1); + gl.glEnable(GL.GL_DEPTH_TEST); + gl.glEnable(GL.GL_BLEND); + + sceneUICntrl.init(drawable); + + final GLAnimatorControl a = drawable.getAnimator(); + if( null != a ) { + a.resetFPSCounter(); + } + + setupUI(drawable); + } + + @Override + public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { + System.err.println("GPUUISceneGLListener0A: reshape"); + + // + // Layout all shapes: Relational move regarding window coordinates + // + final float dz = 0f; + + final float dxMiddleAbs = width * relMiddle; + final float dyTopLabelAbs = drawable.getSurfaceHeight() - 2f*jogampLabel.getLineHeight(); + jogampLabel.setPosition(dxMiddleAbs, dyTopLabelAbs, dz); + fpsLabel.move(0f, 0f, 0f); + + sceneUICntrl.reshape(drawable, x, y, width, height); + + lastWidth = width; + lastHeight = height; + } + float lastWidth = 0f, lastHeight = 0f; + + @Override + public void dispose(final GLAutoDrawable drawable) { + System.err.println("GPUUISceneGLListener0A: dispose"); + + sceneUICntrl.dispose(drawable); // disposes all registered UIShapes + + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + screenshot.dispose(gl); + } + + private int shotCount = 0; + + public void printScreen(final GL gl) { + final RegionRenderer renderer = sceneUICntrl.getRenderer(); + final String modeS = Region.getRenderModeString(jogampLabel.getRenderModes()); + final String filename = String.format((Locale)null, "GraphUIDemo-shot%03d-%03dx%03d-S_%s_%02d.png", + shotCount++, renderer.getWidth(), renderer.getHeight(), + modeS, sceneUICntrl.getSampleCount()); + gl.glFinish(); // just make sure rendering finished .. + if(screenshot.readPixels(gl, false)) { + screenshot.write(new File(filename)); + System.err.println("Wrote: "+filename); + } + } + + @Override + public void display(final GLAutoDrawable drawable) { + if( fpsLabel.isEnabled() ) { + final String text; + if( null == actionText ) { + text = sceneUICntrl.getStatusText(drawable, renderModes, fpsLabel.getQuality(), dpiV); + } else if( null != drawable.getAnimator() ) { + text = Scene.getStatusText(drawable.getAnimator())+", "+actionText; + } else { + text = actionText; + } + if( fpsLabel.setText(text) ) { // marks dirty only if text differs. + System.err.println(text); + } + } + sceneUICntrl.display(drawable); + } + + public void attachInputListenerTo(final GLWindow window) { + sceneUICntrl.attachInputListenerTo(window); + } + + public void detachInputListenerFrom(final GLWindow window) { + sceneUICntrl.detachInputListenerFrom(window); + } + + /** + * We can share this instance w/ all UI elements, + * since only mouse action / gesture is complete for a single one (press, drag, released and click). + */ + private final Shape.MouseGestureAdapter dragZoomRotateListener = new Shape.MouseGestureAdapter() { + @Override + public void mouseReleased(final MouseEvent e) { + actionText = null; + } + + @Override + public void mouseDragged(final MouseEvent e) { + final Shape.EventInfo shapeEvent = (Shape.EventInfo) e.getAttachment(); + if( e.getPointerCount() == 1 ) { + final float[] tx = shapeEvent.shape.getPosition(); + actionText = String.format((Locale)null, "Pos %6.2f / %6.2f / %6.2f", tx[0], tx[1], tx[2]); + } + } + + @Override + public void mouseWheelMoved(final MouseEvent e) { + final Shape.EventInfo shapeEvent = (Shape.EventInfo) e.getAttachment(); + final boolean isOnscreen = PointerClass.Onscreen == e.getPointerType(0).getPointerClass(); + if( 0 == ( ~InputEvent.BUTTONALL_MASK & e.getModifiers() ) && !isOnscreen ) { + // offscreen vertical mouse wheel zoom + final float tz = 100f*e.getRotation()[1]; // vertical: wheel + System.err.println("Rotate.Zoom.W: "+tz); + shapeEvent.shape.move(0f, 0f, tz); + } else if( isOnscreen || e.isControlDown() ) { + final float[] rot = VectorUtil.scaleVec3(e.getRotation(), e.getRotation(), FloatUtil.PI / 180.0f); + if( isOnscreen ) { + System.err.println("XXX: "+e); + // swap axis for onscreen rotation matching natural feel + final float tmp = rot[0]; rot[0] = rot[1]; rot[1] = tmp; + VectorUtil.scaleVec3(rot, rot, 2f); + } + shapeEvent.shape.getRotation().rotateByEuler( rot ); + } + } + @Override + public void gestureDetected(final GestureEvent e) { + final Shape.EventInfo shapeEvent = (Shape.EventInfo) e.getAttachment(); + if( e instanceof PinchToZoomGesture.ZoomEvent ) { + final PinchToZoomGesture.ZoomEvent ze = (PinchToZoomGesture.ZoomEvent) e; + final float tz = ze.getDelta() * ze.getScale(); + System.err.println("Rotate.Zoom.G: "+tz); + shapeEvent.shape.move(0f, 0f, tz); + } + } }; +} diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/UIShapeDemo01.java b/src/demos/com/jogamp/opengl/demos/graph/ui/UIShapeDemo01.java new file mode 100644 index 000000000..b89b3e2b9 --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/graph/ui/UIShapeDemo01.java @@ -0,0 +1,569 @@ +/** + * Copyright 2010-2023 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.demos.graph.ui; + +import java.io.File; +import java.io.IOException; + +import com.jogamp.opengl.FPSCounter; +import com.jogamp.opengl.GL; +import com.jogamp.opengl.GL2ES2; +import com.jogamp.opengl.GLAnimatorControl; +import com.jogamp.opengl.GLAutoDrawable; +import com.jogamp.opengl.GLCapabilities; +import com.jogamp.opengl.GLEventListener; +import com.jogamp.opengl.GLException; +import com.jogamp.opengl.GLPipelineFactory; +import com.jogamp.opengl.GLProfile; +import com.jogamp.opengl.GLRunnable; +import com.jogamp.opengl.demos.graph.MSAATool; +import com.jogamp.opengl.fixedfunc.GLMatrixFunc; +import com.jogamp.opengl.math.FloatUtil; +import com.jogamp.opengl.math.geom.AABBox; +import com.jogamp.common.util.InterruptSource; +import com.jogamp.graph.curve.Region; +import com.jogamp.graph.curve.opengl.RegionRenderer; +import com.jogamp.graph.curve.opengl.RenderState; +import com.jogamp.graph.curve.opengl.TextRegionUtil; +import com.jogamp.graph.font.Font; +import com.jogamp.graph.font.FontFactory; +import com.jogamp.graph.font.FontSet; +import com.jogamp.graph.geom.SVertex; +import com.jogamp.graph.geom.plane.AffineTransform; +import com.jogamp.graph.ui.gl.Shape; +import com.jogamp.graph.ui.gl.shapes.Button; +import com.jogamp.graph.ui.gl.shapes.CrossHair; +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.MouseEvent; +import com.jogamp.newt.event.MouseListener; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.PMVMatrix; + +/** + * Basic UIShape and Type Rendering demo. + * + * Action Keys: + * - 1/2: zoom in/out + * - 4/5: increase/decrease shape/text spacing + * - 6/7: increase/decrease corner size + * - 0/9: rotate + * - v: toggle v-sync + * - s: screenshot + */ +public class UIShapeDemo01 implements GLEventListener { + static final boolean DEBUG = false; + static final boolean TRACE = false; + + public static void main(final String[] args) throws IOException { + Font font = null; + if( 0 != args.length ) { + for(int i=0; i obj [%f, %f, %f]%n", glWinX, glWinY, winZ, objCoord0[0], objCoord0[1], objCoord0[2]); + } + } + glWinX = drawable.getSurfaceWidth(); + glWinY = drawable.getSurfaceHeight(); + if( pmv.gluUnProject(glWinX, glWinY, winZ, renderer.getViewport(), 0, objCoord1, 0) ) { + if( once ) { + System.err.printf("winToObjCoord: win [%f, %f, %f] -> obj [%f, %f, %f]%n", glWinX, glWinY, winZ, objCoord1[0], objCoord1[1], objCoord1[2]); + } + } + full_width_o = objCoord1[0] - objCoord0[0]; + } + final AABBox txt_box_em = font.getGlyphBounds(text, tempT1, tempT2); + final float full_width_s = full_width_o / txt_box_em.getWidth(); + final float txt_scale = full_width_s/2f; + pmv.glPushMatrix(); + pmv.glScalef(txt_scale, txt_scale, 1f); + pmv.glTranslatef(-txt_box_em.getWidth(), 0f, 0f); + final AABBox txt_box_r = TextRegionUtil.drawString3D(gl, renderModes, renderer, font, text, new float[] { 0, 0, 0, 1 }, sampleCount, tempT1, tempT2); + if( once ) { + final AABBox txt_box_em2 = font.getGlyphShapeBounds(null, text); + System.err.println("XXX: full_width: "+full_width_o+" / "+txt_box_em.getWidth()+" -> "+full_width_s); + System.err.println("XXX: txt_box_em "+txt_box_em); + System.err.println("XXX: txt_box_e2 "+txt_box_em2); + System.err.println("XXX: txt_box_rg "+txt_box_r); + once = false; + } + pmv.glPopMatrix(); + } + renderer.enable(gl, false); + } + static boolean once = true; + + @Override + public void dispose(final GLAutoDrawable drawable) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + button.destroy(gl, getRegionRenderer()); + crossHair.destroy(gl, getRegionRenderer()); + + autoDrawable = null; + screenshot.dispose(gl); + rRenderer.destroy(gl); + } + + /** Attach the input listener to the window */ + public void attachInputListenerTo(final GLWindow window) { + if ( null == keyAction ) { + keyAction = new KeyAction(); + window.addKeyListener(keyAction); + } + if ( null == mouseAction ) { + mouseAction = new MouseAction(); + window.addMouseListener(mouseAction); + } + } + + public void detachFrom(final GLWindow window) { + if ( null == keyAction ) { + return; + } + if ( null == mouseAction ) { + return; + } + window.removeGLEventListener(this); + window.removeKeyListener(keyAction); + window.removeMouseListener(mouseAction); + } + + public void printScreen(final GLAutoDrawable drawable, final String dir, final String tech, final String objName, final boolean exportAlpha) throws GLException, IOException { + final String sw = String.format("-%03dx%03d-Z%04d-T%04d-%s", drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), (int)Math.abs(zTran), 0, objName); + + final String filename = dir + tech + sw +".png"; + if(screenshot.readPixels(drawable.getGL(), false)) { + screenshot.write(new File(filename)); + } + } + + int screenshot_num = 0; + + public void setIgnoreInput(final boolean v) { + ignoreInput = v; + } + public boolean getIgnoreInput() { + return ignoreInput; + } + + public class MouseAction implements MouseListener{ + + @Override + public void mouseClicked(final MouseEvent e) { + + } + + @Override + public void mouseEntered(final MouseEvent e) { + } + + @Override + public void mouseExited(final MouseEvent e) { + } + + @Override + public void mousePressed(final MouseEvent e) { + autoDrawable.invoke(false, new GLRunnable() { // avoid data-race + @Override + public boolean run(final GLAutoDrawable drawable) { + System.err.println("\n\nMouse: "+e); + + final RegionRenderer renderer = getRegionRenderer(); + final PMVMatrix pmv = renderer.getMatrix(); + pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmv.glLoadIdentity(); + pmv.glTranslatef(xTran, yTran, zTran); + + // flip to GL window coordinates, origin bottom-left + final int[] viewport = renderer.getViewport(new int[4]); + final int glWinX = e.getX(); + final int glWinY = viewport[3] - e.getY() - 1; + + { + pmv.glPushMatrix(); + button.setTransform(pmv); + + final float[] objPos = new float[3]; + System.err.println("\n\nButton: "+button); + button.winToObjCoord(renderer, glWinX, glWinY, objPos); + System.err.println("Button: Click: Win "+glWinX+"/"+glWinY+" -> Obj "+objPos[0]+"/"+objPos[1]+"/"+objPos[1]); + + final int[] surfaceSize = new int[2]; + button.getSurfaceSize(renderer, surfaceSize); + System.err.println("Button: Size: Pixel "+surfaceSize[0]+" x "+surfaceSize[1]); + + pmv.glPopMatrix(); + } + { + pmv.glPushMatrix(); + crossHair.setTransform(pmv); + + final float[] objPosC = crossHair.getBounds().getCenter(); + final int[] objWinPos = new int[2]; + System.err.println("\n\nCrossHair: "+crossHair); + if( crossHair.objToWinCoord(renderer, objPosC, objWinPos) ) { + System.err.println("CrossHair: Obj: Obj "+objPosC[0]+"/"+objPosC[1]+"/"+objPosC[1]+" -> Win "+objWinPos[0]+"/"+objWinPos[1]); + } + + final float[] objPos2 = new float[3]; + crossHair.winToObjCoord(renderer, objWinPos[0], objWinPos[1], objPos2); + System.err.println("CrossHair: Obj: Win "+objWinPos[0]+"/"+objWinPos[1]+" -> Obj "+objPos2[0]+"/"+objPos2[1]+"/"+objPos2[1]); + + final float[] winObjPos = new float[3]; + if( crossHair.winToObjCoord(renderer, glWinX, glWinY, winObjPos) ) { + // final float[] translate = crossHair.getTranslate(); + // final float[] objPosT = new float[] { objPosC[0]+translate[0], objPosC[1]+translate[1], objPosC[2]+translate[2] }; + final float dx = winObjPos[0] - objPosC[0]; + final float dy = winObjPos[1] - objPosC[1]; + // final float dz = winObjPos[2] - objPosT[2]; + if( !FloatUtil.isZero(dx, FloatUtil.EPSILON) || !FloatUtil.isZero(dy, FloatUtil.EPSILON) ) { + System.err.println("CrossHair: Move.1: Win "+glWinX+"/"+glWinY+" -> Obj "+winObjPos[0]+"/"+winObjPos[1]+"/"+winObjPos[1]+" -> diff "+dx+" / "+dy); + crossHair.move(dx, dy, 0f); + } else { + System.err.println("CrossHair: Move.0: Win "+glWinX+"/"+glWinY+" -> Obj "+winObjPos[0]+"/"+winObjPos[1]+"/"+winObjPos[1]+" -> diff "+dx+" / "+dy); + } + } + + final int[] surfaceSize = new int[2]; + crossHair.getSurfaceSize(renderer, surfaceSize); + System.err.println("CrossHair: Size: Pixel "+surfaceSize[0]+" x "+surfaceSize[1]); + + pmv.glPopMatrix(); + } + return true; + } } ); + + } + + @Override + public void mouseReleased(final MouseEvent e) { + } + + @Override + public void mouseMoved(final MouseEvent e) { + // TODO Auto-generated method stub + + } + + @Override + public void mouseDragged(final MouseEvent e) { + // TODO Auto-generated method stub + + } + + @Override + public void mouseWheelMoved(final MouseEvent e) { + // TODO Auto-generated method stub + + } + + } + + public class KeyAction implements KeyListener { + @Override + public void keyPressed(final KeyEvent arg0) { + if(ignoreInput) { + return; + } + + if(arg0.getKeyCode() == KeyEvent.VK_1){ + button.move(0f, 0f, -zTran/10f); + } + else if(arg0.getKeyCode() == KeyEvent.VK_2){ + button.move(0f, 0f, zTran/10f); + } + else if(arg0.getKeyCode() == KeyEvent.VK_UP){ + button.move(0f, button.getHeight()/10f, 0f); + } + else if(arg0.getKeyCode() == KeyEvent.VK_DOWN){ + button.move(0f, -button.getHeight()/10f, 0f); + } + else if(arg0.getKeyCode() == KeyEvent.VK_LEFT){ + button.move(-button.getWidth()/10f, 0f, 0f); + } + else if(arg0.getKeyCode() == KeyEvent.VK_RIGHT){ + button.move(button.getWidth()/10f, 0f, 0f); + } + else if(arg0.getKeyCode() == KeyEvent.VK_4){ + button.setSpacing(button.getSpacingX()-0.01f, button.getSpacingY()-0.005f); + System.err.println("Button Spacing: " + button.getSpacingX()); + } + else if(arg0.getKeyCode() == KeyEvent.VK_5){ + button.setSpacing(button.getSpacingX()+0.01f, button.getSpacingY()+0.005f); + System.err.println("Button Spacing: " + button.getSpacingX()); + } + else if(arg0.getKeyCode() == KeyEvent.VK_6){ + button.setCorner(button.getCorner()-0.01f); + System.err.println("Button Corner: " + button.getCorner()); + } + else if(arg0.getKeyCode() == KeyEvent.VK_7){ + button.setCorner(button.getCorner()+0.01f); + System.err.println("Button Corner: " + button.getCorner()); + } + else if(arg0.getKeyCode() == KeyEvent.VK_0){ + // rotate(1); + } + else if(arg0.getKeyCode() == KeyEvent.VK_9){ + // rotate(-1); + } + else if(arg0.getKeyCode() == KeyEvent.VK_V) { + if(null != autoDrawable) { + autoDrawable.invoke(false, new GLRunnable() { + @Override + public boolean run(final GLAutoDrawable drawable) { + final GL gl = drawable.getGL(); + final int _i = gl.getSwapInterval(); + final int i; + switch(_i) { + case 0: i = 1; break; + case 1: i = -1; break; + case -1: i = 0; break; + default: i = 1; break; + } + gl.setSwapInterval(i); + + final GLAnimatorControl a = drawable.getAnimator(); + if( null != a ) { + a.resetFPSCounter(); + } + if(drawable instanceof FPSCounter) { + ((FPSCounter)drawable).resetFPSCounter(); + } + System.err.println("Swap Interval: "+_i+" -> "+i+" -> "+gl.getSwapInterval()); + return true; + } + }); + } + } + else if(arg0.getKeyCode() == KeyEvent.VK_S){ + if(null != autoDrawable) { + autoDrawable.invoke(false, new GLRunnable() { + @Override + public boolean run(final GLAutoDrawable drawable) { + try { + final String type = Region.getRenderModeString(renderModes); + printScreen(drawable, "./", "demo-"+type, "snap"+screenshot_num, false); + screenshot_num++; + } catch (final GLException e) { + e.printStackTrace(); + } catch (final IOException e) { + e.printStackTrace(); + } + return true; + } + }); + } + } + } + @Override + public void keyReleased(final KeyEvent arg0) {} + } +} diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/UITypeDemo01.java b/src/demos/com/jogamp/opengl/demos/graph/ui/UITypeDemo01.java new file mode 100644 index 000000000..56962e110 --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/graph/ui/UITypeDemo01.java @@ -0,0 +1,617 @@ +/** + * Copyright 2010-2023 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.demos.graph.ui; + +import java.io.File; +import java.io.IOException; + +import com.jogamp.opengl.FPSCounter; +import com.jogamp.opengl.GL; +import com.jogamp.opengl.GL2ES2; +import com.jogamp.opengl.GLAnimatorControl; +import com.jogamp.opengl.GLAutoDrawable; +import com.jogamp.opengl.GLCapabilities; +import com.jogamp.opengl.GLEventListener; +import com.jogamp.opengl.GLException; +import com.jogamp.opengl.GLPipelineFactory; +import com.jogamp.opengl.GLProfile; +import com.jogamp.opengl.GLRunnable; +import com.jogamp.opengl.demos.graph.MSAATool; +import com.jogamp.opengl.demos.graph.ui.testshapes.Glyph03FreeMonoRegular_M; +import com.jogamp.opengl.demos.graph.ui.testshapes.Glyph04FreeSans_0; +import com.jogamp.opengl.demos.graph.ui.testshapes.Glyph05FreeSerifBoldItalic_ae; +import com.jogamp.opengl.demos.util.MiscUtils; +import com.jogamp.opengl.fixedfunc.GLMatrixFunc; +import com.jogamp.opengl.math.FloatUtil; +import com.jogamp.opengl.math.geom.AABBox; +import com.jogamp.common.util.InterruptSource; +import com.jogamp.graph.curve.Region; +import com.jogamp.graph.curve.opengl.GLRegion; +import com.jogamp.graph.curve.opengl.RegionRenderer; +import com.jogamp.graph.curve.opengl.RenderState; +import com.jogamp.graph.curve.opengl.TextRegionUtil; +import com.jogamp.graph.font.Font; +import com.jogamp.graph.font.FontFactory; +import com.jogamp.graph.font.FontSet; +import com.jogamp.graph.font.Font.Glyph; +import com.jogamp.graph.geom.SVertex; +import com.jogamp.graph.geom.plane.AffineTransform; +import com.jogamp.graph.ui.gl.Shape; +import com.jogamp.graph.ui.gl.shapes.CrossHair; +import com.jogamp.graph.ui.gl.shapes.Rectangle; +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.MouseEvent; +import com.jogamp.newt.event.MouseListener; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.PMVMatrix; + +/** + * Basic UIShape and Type Rendering demo. + * + * Action Keys: + * - 1/2: zoom in/out + * - 4/5: increase/decrease shape/text spacing + * - 6/7: increase/decrease corner size + * - 0/9: rotate + * - v: toggle v-sync + * - s: screenshot + */ +public class UITypeDemo01 implements GLEventListener { + static final boolean DEBUG = false; + static final boolean TRACE = false; + + public static void main(final String[] args) throws IOException { + Font font = null; + String text = "Hello Origin."; + int glyph_id = Glyph.ID_UNKNOWN; + if( 0 != args.length ) { + for(int i=0; i obj [%f, %f, %f]%n", glWinX, glWinY, winZ, objCoord0[0], objCoord0[1], objCoord0[2]); + } + } + glWinX = drawable.getSurfaceWidth(); + glWinY = drawable.getSurfaceHeight(); + if( pmv.gluUnProject(glWinX, glWinY, winZ, renderer.getViewport(), 0, objCoord1, 0) ) { + if( once ) { + System.err.printf("winToObjCoord: win [%f, %f, %f] -> obj [%f, %f, %f]%n", glWinX, glWinY, winZ, objCoord1[0], objCoord1[1], objCoord1[2]); + } + } + full_width_o = objCoord1[0] - objCoord0[0]; + full_height_o = objCoord1[1] - objCoord0[1]; + } + pmv.glPushMatrix(); + + final Font.Glyph glyph; + if( Glyph.ID_UNKNOWN < glyph_id ) { + glyph = font.getGlyph(glyph_id); + if( once ) { + System.err.println("glyph_id "+glyph_id+": "+glyph); + } + } else { + glyph = null; + } + if( null != glyph && glyph.getID() != Glyph.ID_UNKNOWN ) { + final AABBox txt_box_em = glyph.getBBox(); + final float full_width_s = full_width_o / txt_box_em.getWidth(); + final float full_height_s = full_height_o / txt_box_em.getHeight(); + final float txt_scale = full_width_s < full_height_s ? full_width_s/2f : full_height_s/2f; + pmv.glScalef(txt_scale, txt_scale, 1f); + pmv.glTranslatef(-txt_box_em.getWidth(), 0f, 0f); + if( null != glyph.getShape() ) { + final GLRegion region = GLRegion.create(gl.getGLProfile(), renderModes, null); + region.addOutlineShape(glyph.getShape(), null, region.hasColorChannel() ? fg_color : null); + region.draw(gl, renderer, sampleCount); + region.destroy(gl); + } + if( once ) { + final AABBox txt_box_em2 = font.getGlyphShapeBounds(null, text); + System.err.println("XXX: full_width: "+full_width_o+" / "+txt_box_em.getWidth()+" -> "+full_width_s); + System.err.println("XXX: full_height: "+full_height_o+" / "+txt_box_em.getHeight()+" -> "+full_height_s); + System.err.println("XXX: txt_scale: "+txt_scale); + System.err.println("XXX: txt_box_em "+txt_box_em); + System.err.println("XXX: txt_box_e2 "+txt_box_em2); + } + } else if( Glyph.ID_UNKNOWN == glyph_id ) { + final AABBox txt_box_em = font.getGlyphBounds(text, tempT1, tempT2); + final float full_width_s = full_width_o / txt_box_em.getWidth(); + final float full_height_s = full_height_o / txt_box_em.getHeight(); + final float txt_scale = full_width_s < full_height_s ? full_width_s/2f : full_height_s/2f; + pmv.glScalef(txt_scale, txt_scale, 1f); + pmv.glTranslatef(-txt_box_em.getWidth(), 0f, 0f); + final AABBox txt_box_r = TextRegionUtil.drawString3D(gl, renderModes, renderer, font, text, fg_color, sampleCount, tempT1, tempT2); + if( once ) { + final AABBox txt_box_em2 = font.getGlyphShapeBounds(null, text); + System.err.println("XXX: full_width: "+full_width_o+" / "+txt_box_em.getWidth()+" -> "+full_width_s); + System.err.println("XXX: full_height: "+full_height_o+" / "+txt_box_em.getHeight()+" -> "+full_height_s); + System.err.println("XXX: txt_scale: "+txt_scale); + System.err.println("XXX: txt_box_em "+txt_box_em); + System.err.println("XXX: txt_box_e2 "+txt_box_em2); + System.err.println("XXX: txt_box_rg "+txt_box_r); + } + } + pmv.glPopMatrix(); + if( once ) { + try { + printScreen(drawable); + } catch (GLException | IOException e) { + e.printStackTrace(); + } + } + once = false; + } + renderer.enable(gl, false); + } + private boolean once = true; + + @Override + public void dispose(final GLAutoDrawable drawable) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + crossHair.destroy(gl, getRegionRenderer()); + testObj.destroy(gl, getRegionRenderer()); + + autoDrawable = null; + screenshot.dispose(gl); + rRenderer.destroy(gl); + } + + /** Attach the input listener to the window */ + public void attachInputListenerTo(final GLWindow window) { + if ( null == keyAction ) { + keyAction = new KeyAction(); + window.addKeyListener(keyAction); + } + if ( null == mouseAction ) { + mouseAction = new MouseAction(); + window.addMouseListener(mouseAction); + } + } + + public void detachFrom(final GLWindow window) { + if ( null == keyAction ) { + return; + } + if ( null == mouseAction ) { + return; + } + window.removeGLEventListener(this); + window.removeKeyListener(keyAction); + window.removeMouseListener(mouseAction); + } + + public void printScreen(final GLAutoDrawable drawable) throws GLException, IOException { + final String dir = "./"; + final String tech="demo-"+Region.getRenderModeString(renderModes); + final String objName = "snap"+screenshot_num; + { + final String sw = String.format("-%03dx%03d-Z%04d-T%04d-%s", drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), (int)Math.abs(zTran), 0, objName); + + final String filename = dir + tech + sw +".png"; + if(screenshot.readPixels(drawable.getGL(), false)) { + screenshot.write(new File(filename)); + } + } + screenshot_num++; + } + int screenshot_num = 0; + + public void setIgnoreInput(final boolean v) { + ignoreInput = v; + } + public boolean getIgnoreInput() { + return ignoreInput; + } + + public class MouseAction implements MouseListener{ + + @Override + public void mouseClicked(final MouseEvent e) { + + } + + @Override + public void mouseEntered(final MouseEvent e) { + } + + @Override + public void mouseExited(final MouseEvent e) { + } + + @Override + public void mousePressed(final MouseEvent e) { + autoDrawable.invoke(false, new GLRunnable() { // avoid data-race + @Override + public boolean run(final GLAutoDrawable drawable) { + System.err.println("\n\nMouse: "+e); + + final RegionRenderer renderer = getRegionRenderer(); + final PMVMatrix pmv = renderer.getMatrix(); + pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmv.glLoadIdentity(); + pmv.glTranslatef(xTran, yTran, zTran); + + // flip to GL window coordinates, origin bottom-left + final int[] viewport = renderer.getViewport(new int[4]); + final int glWinX = e.getX(); + final int glWinY = viewport[3] - e.getY() - 1; + + { + pmv.glPushMatrix(); + crossHair.setTransform(pmv); + + final float[] objPosC = crossHair.getBounds().getCenter(); + final int[] objWinPos = new int[2]; + System.err.println("\n\nCrossHair: "+crossHair); + if( crossHair.objToWinCoord(renderer, objPosC, objWinPos) ) { + System.err.println("CrossHair: Obj: Obj "+objPosC[0]+"/"+objPosC[1]+"/"+objPosC[1]+" -> Win "+objWinPos[0]+"/"+objWinPos[1]); + } + + final float[] objPos2 = new float[3]; + crossHair.winToObjCoord(renderer, objWinPos[0], objWinPos[1], objPos2); + System.err.println("CrossHair: Obj: Win "+objWinPos[0]+"/"+objWinPos[1]+" -> Obj "+objPos2[0]+"/"+objPos2[1]+"/"+objPos2[1]); + + final float[] winObjPos = new float[3]; + if( crossHair.winToObjCoord(renderer, glWinX, glWinY, winObjPos) ) { + // final float[] translate = crossHair.getTranslate(); + // final float[] objPosT = new float[] { objPosC[0]+translate[0], objPosC[1]+translate[1], objPosC[2]+translate[2] }; + final float dx = winObjPos[0] - objPosC[0]; + final float dy = winObjPos[1] - objPosC[1]; + // final float dz = winObjPos[2] - objPosT[2]; + if( !FloatUtil.isZero(dx, FloatUtil.EPSILON) || !FloatUtil.isZero(dy, FloatUtil.EPSILON) ) { + System.err.println("CrossHair: Move.1: Win "+glWinX+"/"+glWinY+" -> Obj "+winObjPos[0]+"/"+winObjPos[1]+"/"+winObjPos[1]+" -> diff "+dx+" / "+dy); + crossHair.move(dx, dy, 0f); + } else { + System.err.println("CrossHair: Move.0: Win "+glWinX+"/"+glWinY+" -> Obj "+winObjPos[0]+"/"+winObjPos[1]+"/"+winObjPos[1]+" -> diff "+dx+" / "+dy); + } + } + + final int[] surfaceSize = new int[2]; + crossHair.getSurfaceSize(renderer, surfaceSize); + System.err.println("CrossHair: Size: Pixel "+surfaceSize[0]+" x "+surfaceSize[1]); + + pmv.glPopMatrix(); + } + return true; + } } ); + + } + + @Override + public void mouseReleased(final MouseEvent e) { + } + + @Override + public void mouseMoved(final MouseEvent e) { + // TODO Auto-generated method stub + + } + + @Override + public void mouseDragged(final MouseEvent e) { + // TODO Auto-generated method stub + + } + + @Override + public void mouseWheelMoved(final MouseEvent e) { + // TODO Auto-generated method stub + + } + + } + + public class KeyAction implements KeyListener { + @Override + public void keyPressed(final KeyEvent arg0) { + if(ignoreInput) { + return; + } + + if(arg0.getKeyCode() == KeyEvent.VK_1){ + crossHair.move(0f, 0f, -zTran/10f); + } + else if(arg0.getKeyCode() == KeyEvent.VK_2){ + crossHair.move(0f, 0f, zTran/10f); + } + else if(arg0.getKeyCode() == KeyEvent.VK_UP){ + crossHair.move(0f, crossHair.getHeight()/10f, 0f); + } + else if(arg0.getKeyCode() == KeyEvent.VK_DOWN){ + crossHair.move(0f, -crossHair.getHeight()/10f, 0f); + } + else if(arg0.getKeyCode() == KeyEvent.VK_LEFT){ + crossHair.move(-crossHair.getWidth()/10f, 0f, 0f); + } + else if(arg0.getKeyCode() == KeyEvent.VK_RIGHT){ + crossHair.move(crossHair.getWidth()/10f, 0f, 0f); + } + else if(arg0.getKeyCode() == KeyEvent.VK_0){ + // rotate(1); + } + else if(arg0.getKeyCode() == KeyEvent.VK_9){ + // rotate(-1); + } + else if(arg0.getKeyCode() == KeyEvent.VK_V) { + if(null != autoDrawable) { + autoDrawable.invoke(false, new GLRunnable() { + @Override + public boolean run(final GLAutoDrawable drawable) { + final GL gl = drawable.getGL(); + final int _i = gl.getSwapInterval(); + final int i; + switch(_i) { + case 0: i = 1; break; + case 1: i = -1; break; + case -1: i = 0; break; + default: i = 1; break; + } + gl.setSwapInterval(i); + + final GLAnimatorControl a = drawable.getAnimator(); + if( null != a ) { + a.resetFPSCounter(); + } + if(drawable instanceof FPSCounter) { + ((FPSCounter)drawable).resetFPSCounter(); + } + System.err.println("Swap Interval: "+_i+" -> "+i+" -> "+gl.getSwapInterval()); + return true; + } + }); + } + } + else if(arg0.getKeyCode() == KeyEvent.VK_S){ + if(null != autoDrawable) { + autoDrawable.invoke(false, new GLRunnable() { + @Override + public boolean run(final GLAutoDrawable drawable) { + try { + printScreen(drawable); + } catch (final GLException e) { + e.printStackTrace(); + } catch (final IOException e) { + e.printStackTrace(); + } + return true; + } + }); + } + } + } + @Override + public void keyReleased(final KeyEvent arg0) {} + } +} diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/button-pressed-145x53.png b/src/demos/com/jogamp/opengl/demos/graph/ui/button-pressed-145x53.png new file mode 100644 index 000000000..1eba3a09e Binary files /dev/null and b/src/demos/com/jogamp/opengl/demos/graph/ui/button-pressed-145x53.png differ diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/button-released-145x53.png b/src/demos/com/jogamp/opengl/demos/graph/ui/button-released-145x53.png new file mode 100644 index 000000000..fe223c6d3 Binary files /dev/null and b/src/demos/com/jogamp/opengl/demos/graph/ui/button-released-145x53.png differ diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph01UbuntuLight_o.java b/src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph01UbuntuLight_o.java new file mode 100644 index 000000000..4171eeda8 --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph01UbuntuLight_o.java @@ -0,0 +1,316 @@ +/** + * Copyright 2023 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.demos.graph.ui.testshapes; + +import com.jogamp.opengl.GL2ES2; +import com.jogamp.graph.curve.OutlineShape; +import com.jogamp.graph.curve.opengl.RegionRenderer; +import com.jogamp.graph.geom.Vertex; +import com.jogamp.graph.geom.Vertex.Factory; +import com.jogamp.graph.geom.plane.Winding; +import com.jogamp.graph.ui.gl.Shape; + +/** + * GPU based resolution independent test object + * - Ubuntu-Light, lower case 'o' + * - TTF Shape for Glyph 82 + */ +public class Glyph01UbuntuLight_o extends Shape { + + public Glyph01UbuntuLight_o(final Factory factory, final int renderModes) { + super(factory, renderModes); + } + + @Override + protected void clearImpl(final GL2ES2 gl, final RegionRenderer renderer) { + } + + @Override + protected void destroyImpl(final GL2ES2 gl, final RegionRenderer renderer) { + } + + @SuppressWarnings("unused") + @Override + protected void addShapeToRegion(final GL2ES2 gl, final RegionRenderer renderer) { + final OutlineShape shape = new OutlineShape(renderer.getRenderState().getVertexFactory()); + + // Ubuntu-Light, lower case 'o' + // Start TTF Shape for Glyph 82 + if( false ) { + // Original Outer shape: Winding.CW + // Moved into OutlineShape reverse -> Winding.CCW -> OK + // + // Shape.MoveTo: + shape.closeLastOutline(false); + shape.addEmptyOutline(); + shape.addVertex(0, 0.527000f, 0.258000f, true); + // 000: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.527000f, 0.197000f, false); + shape.addVertex(0, 0.510000f, 0.147000f, true); + // 002: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0, 0.492000f, 0.097000f, false); + shape.addVertex(0, 0.461000f, 0.062000f, true); + // 003: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0, 0.429000f, 0.027000f, false); + shape.addVertex(0, 0.386000f, 0.008000f, true); + // 004: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.343000f, -0.012000f, false); + shape.addVertex(0, 0.291000f, -0.012000f, true); + // 005: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.239000f, -0.012000f, false); + shape.addVertex(0, 0.196000f, 0.007000f, true); + // 007: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0, 0.153000f, 0.027000f, false); + shape.addVertex(0, 0.122000f, 0.062000f, true); + // 008: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0, 0.090000f, 0.097000f, false); + shape.addVertex(0, 0.073000f, 0.147000f, true); + // 009: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.055000f, 0.197000f, false); + shape.addVertex(0, 0.055000f, 0.258000f, true); + // 010: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.055000f, 0.319000f, false); + shape.addVertex(0, 0.072000f, 0.369000f, true); + // 012: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0, 0.090000f, 0.419000f, false); + shape.addVertex(0, 0.121000f, 0.454000f, true); + // 013: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0, 0.153000f, 0.490000f, false); + shape.addVertex(0, 0.196000f, 0.509000f, true); + // 014: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.239000f, 0.529000f, false); + shape.addVertex(0, 0.291000f, 0.529000f, true); + // 015: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.343000f, 0.529000f, false); + shape.addVertex(0, 0.386000f, 0.510000f, true); + // 017: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0, 0.429000f, 0.490000f, false); + shape.addVertex(0, 0.460000f, 0.455000f, true); + // 018: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0, 0.492000f, 0.419000f, false); + shape.addVertex(0, 0.509000f, 0.369000f, true); + // 019: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.527000f, 0.319000f, false); + shape.addVertex(0, 0.527000f, 0.258000f, true); + System.err.println("Glyph01UbuntuLight_o.shape01a.winding_area: "+shape.getWindingOfLastOutline()); + shape.closeLastOutline(false); + } else { + // Outer shape: Winding.CW + // Moved into OutlineShape same-order -> Winding.CW -> ERROR (so we fix it in the end, see below) + // + // Shape.MoveTo: + shape.closeLastOutline(false); + shape.addEmptyOutline(); + shape.addVertex(0.527000f, 0.258000f, true); + // 000: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0.527000f, 0.197000f, false); + shape.addVertex(0.510000f, 0.147000f, true); + // 002: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0.492000f, 0.097000f, false); + shape.addVertex(0.461000f, 0.062000f, true); + // 003: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0.429000f, 0.027000f, false); + shape.addVertex(0.386000f, 0.008000f, true); + // 004: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0.343000f, -0.012000f, false); + shape.addVertex(0.291000f, -0.012000f, true); + // 005: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0.239000f, -0.012000f, false); + shape.addVertex(0.196000f, 0.007000f, true); + // 007: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0.153000f, 0.027000f, false); + shape.addVertex(0.122000f, 0.062000f, true); + // 008: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0.090000f, 0.097000f, false); + shape.addVertex(0.073000f, 0.147000f, true); + // 009: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0.055000f, 0.197000f, false); + shape.addVertex(0.055000f, 0.258000f, true); + // 010: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0.055000f, 0.319000f, false); + shape.addVertex(0.072000f, 0.369000f, true); + // 012: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0.090000f, 0.419000f, false); + shape.addVertex(0.121000f, 0.454000f, true); + // 013: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0.153000f, 0.490000f, false); + shape.addVertex(0.196000f, 0.509000f, true); + // 014: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0.239000f, 0.529000f, false); + shape.addVertex(0.291000f, 0.529000f, true); + // 015: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0.343000f, 0.529000f, false); + shape.addVertex(0.386000f, 0.510000f, true); + // 017: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0.429000f, 0.490000f, false); + shape.addVertex(0.460000f, 0.455000f, true); + // 018: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0.492000f, 0.419000f, false); + shape.addVertex(0.509000f, 0.369000f, true); + // 019: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0.527000f, 0.319000f, false); + shape.addVertex(0.527000f, 0.258000f, true); + System.err.println("Glyph01UbuntuLight_o.shape01b.1.winding_area: "+shape.getWindingOfLastOutline()); + shape.setWindingOfLastOutline(Winding.CCW); + System.err.println("Glyph01UbuntuLight_o.shape01b.2.winding_area: "+shape.getWindingOfLastOutline()); + shape.closeLastOutline(false); + } + + if( true ) { + // Original Inner shape: Winding.CCW + // Moved into OutlineShape reverse -> Winding.CW -> OK + // + // Shape.MoveTo: + shape.closeLastOutline(false); + shape.addEmptyOutline(); + shape.addVertex(0, 0.458000f, 0.258000f, true); + // 020: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.458000f, 0.355000f, false); + shape.addVertex(0, 0.413000f, 0.412000f, true); + // 022: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.368000f, 0.470000f, false); + shape.addVertex(0, 0.291000f, 0.470000f, true); + // 023: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.214000f, 0.470000f, false); + shape.addVertex(0, 0.169000f, 0.413000f, true); + // 025: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.124000f, 0.355000f, false); + shape.addVertex(0, 0.124000f, 0.258000f, true); + // 026: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.124000f, 0.161000f, false); + shape.addVertex(0, 0.169000f, 0.104000f, true); + // 028: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.214000f, 0.047000f, false); + shape.addVertex(0, 0.291000f, 0.047000f, true); + // 029: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.368000f, 0.047000f, false); + shape.addVertex(0, 0.413000f, 0.104000f, true); + // 031: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.458000f, 0.161000f, false); + shape.addVertex(0, 0.458000f, 0.258000f, true); + System.err.println("Glyph01UbuntuLight_o.shape02a.winding_area: "+shape.getWindingOfLastOutline()); + shape.closeLastOutline(false); + } else { + // Inner shape: Winding.CCW + // Moved into OutlineShape same-order -> Winding.CCW -> OK + // + // Shape.MoveTo: + shape.closeLastOutline(false); + shape.addEmptyOutline(); + + shape.addVertex(0.458000f, 0.258000f, true); + // 020: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0.458000f, 0.355000f, false); + shape.addVertex(0.413000f, 0.412000f, true); + // 022: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0.368000f, 0.470000f, false); + shape.addVertex(0.291000f, 0.470000f, true); + // 023: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0.214000f, 0.470000f, false); + shape.addVertex(0.169000f, 0.413000f, true); + // 025: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0.124000f, 0.355000f, false); + shape.addVertex(0.124000f, 0.258000f, true); + // 026: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0.124000f, 0.161000f, false); + shape.addVertex(0.169000f, 0.104000f, true); + // 028: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0.214000f, 0.047000f, false); + shape.addVertex(0.291000f, 0.047000f, true); + // 029: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0.368000f, 0.047000f, false); + shape.addVertex(0.413000f, 0.104000f, true); + // 031: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0.458000f, 0.161000f, false); + shape.addVertex(0.458000f, 0.258000f, true); + + System.err.println("Glyph01UbuntuLight_o.shape02b.winding_area: "+shape.getWindingOfLastOutline()); + shape.closeLastOutline(false); + } + // End Shape for Glyph 82 + + shape.setIsQuadraticNurbs(); + shape.setSharpness(shapesSharpness); + region.addOutlineShape(shape, null, rgbaColor); + + box.resize(shape.getBounds()); + } + + @Override + public String getSubString() { + return super.getSubString(); + } +} diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph02UbuntuLight_ae.java b/src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph02UbuntuLight_ae.java new file mode 100644 index 000000000..28d6f6390 --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph02UbuntuLight_ae.java @@ -0,0 +1,652 @@ +/** + * Copyright 2023 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.demos.graph.ui.testshapes; + +import com.jogamp.opengl.GL2ES2; +import com.jogamp.graph.curve.OutlineShape; +import com.jogamp.graph.curve.opengl.RegionRenderer; +import com.jogamp.graph.geom.Vertex; +import com.jogamp.graph.geom.Vertex.Factory; +import com.jogamp.graph.ui.gl.Shape; + +/** + * GPU based resolution independent test object + * - Ubuntu-Light, lower case 'æ' + * - TTF Shape for Glyph 193 + */ +public class Glyph02UbuntuLight_ae extends Shape { + + public Glyph02UbuntuLight_ae(final Factory factory, final int renderModes) { + super(factory, renderModes); + } + + @Override + protected void clearImpl(final GL2ES2 gl, final RegionRenderer renderer) { + } + + @Override + protected void destroyImpl(final GL2ES2 gl, final RegionRenderer renderer) { + } + + @SuppressWarnings("unused") + @Override + protected void addShapeToRegion(final GL2ES2 gl, final RegionRenderer renderer) { + final OutlineShape shape = new OutlineShape(renderer.getRenderState().getVertexFactory()); + + // Ubuntu-Light, lower case 'æ' + + // Start TTF Shape for Glyph 193 + if( true ) { + // Original Inner e-shape: Winding.CCW + // Moved into OutlineShape reverse -> Winding.CW -> OK + // + // Shape.MoveTo: + shape.closeLastOutline(false); + shape.addEmptyOutline(); + shape.addVertex(0, 0.728000f, 0.300000f, true); + // 000: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.726000f, 0.381000f, false); + shape.addVertex(0, 0.690000f, 0.426000f, true); + // 002: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.654000f, 0.471000f, false); + shape.addVertex(0, 0.588000f, 0.471000f, true); + // 003: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.553000f, 0.471000f, false); + shape.addVertex(0, 0.526000f, 0.457000f, true); + // 005: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0, 0.498000f, 0.443000f, false); + shape.addVertex(0, 0.478000f, 0.420000f, true); + // 006: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0, 0.457000f, 0.396000f, false); + shape.addVertex(0, 0.446000f, 0.365000f, true); + // 007: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.434000f, 0.334000f, false); + shape.addVertex(0, 0.432000f, 0.300000f, true); + // 008: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.728000f, 0.300000f, true); + System.err.println("Glyph02UbuntuLight_ae.shape01a.winding_area: "+shape.getWindingOfLastOutline()); + shape.closeLastOutline(false); + } else { + // Inner e-shape: Winding.CCW + // Moved into OutlineShape same-order -> Winding.CCW -> ?? + // + // Shape.MoveTo: + shape.closeLastOutline(false); + shape.addEmptyOutline(); + shape.addVertex(0.728000f, 0.300000f, true); + // 000: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0.726000f, 0.381000f, false); + shape.addVertex(0.690000f, 0.426000f, true); + // 002: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0.654000f, 0.471000f, false); + shape.addVertex(0.588000f, 0.471000f, true); + // 003: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0.553000f, 0.471000f, false); + shape.addVertex(0.526000f, 0.457000f, true); + // 005: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0.498000f, 0.443000f, false); + shape.addVertex(0.478000f, 0.420000f, true); + // 006: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0.457000f, 0.396000f, false); + shape.addVertex(0.446000f, 0.365000f, true); + // 007: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0.434000f, 0.334000f, false); + shape.addVertex(0.432000f, 0.300000f, true); + // 008: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0.728000f, 0.300000f, true); + System.err.println("Glyph02UbuntuLight_ae.shape01b.winding_area: "+shape.getWindingOfLastOutline()); + shape.closeLastOutline(false); + } + + if( true ) { + // Original Outer shape: Winding.CW + // Moved into OutlineShape reverse -> Winding.CCW -> OK + // + // Shape.MoveTo: + shape.closeLastOutline(false); + shape.addEmptyOutline(); + shape.addVertex(0, 0.252000f, -0.011000f, true); + // 009: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.208000f, -0.011000f, false); + shape.addVertex(0, 0.171000f, -0.002000f, true); + // 011: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0, 0.133000f, 0.007000f, false); + shape.addVertex(0, 0.106000f, 0.026000f, true); + // 012: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0, 0.079000f, 0.046000f, false); + shape.addVertex(0, 0.064000f, 0.076000f, true); + // 013: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.048000f, 0.107000f, false); + shape.addVertex(0, 0.048000f, 0.151000f, true); + // 014: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.048000f, 0.193000f, false); + shape.addVertex(0, 0.064000f, 0.223000f, true); + // 016: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0, 0.080000f, 0.253000f, false); + shape.addVertex(0, 0.109000f, 0.272000f, true); + // 017: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0, 0.138000f, 0.292000f, false); + shape.addVertex(0, 0.178000f, 0.301000f, true); + // 018: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.218000f, 0.310000f, false); + shape.addVertex(0, 0.265000f, 0.310000f, true); + // 019: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.279000f, 0.310000f, false); + shape.addVertex(0, 0.294000f, 0.309000f, true); + // 021: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0, 0.310000f, 0.307000f, false); + shape.addVertex(0, 0.324000f, 0.305000f, true); + // 022: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0, 0.339000f, 0.302000f, false); + shape.addVertex(0, 0.349000f, 0.300000f, true); + // 023: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.360000f, 0.297000f, false); + shape.addVertex(0, 0.364000f, 0.295000f, true); + // 024: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.364000f, 0.327000f, true); + // 025: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.364000f, 0.354000f, false); + shape.addVertex(0, 0.360000f, 0.379000f, true); + // 027: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0, 0.356000f, 0.405000f, false); + shape.addVertex(0, 0.343000f, 0.425000f, true); + // 028: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0, 0.329000f, 0.446000f, false); + shape.addVertex(0, 0.305000f, 0.458000f, true); + // 029: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.280000f, 0.471000f, false); + shape.addVertex(0, 0.240000f, 0.471000f, true); + // 030: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.186000f, 0.471000f, false); + shape.addVertex(0, 0.156000f, 0.464000f, true); + // 032: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.126000f, 0.456000f, false); + shape.addVertex(0, 0.113000f, 0.451000f, true); + // 033: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.105000f, 0.507000f, true); + // 034: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.122000f, 0.515000f, false); + shape.addVertex(0, 0.158000f, 0.522000f, true); + // 036: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.194000f, 0.529000f, false); + shape.addVertex(0, 0.243000f, 0.529000f, true); + // 037: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.314000f, 0.529000f, false); + shape.addVertex(0, 0.354000f, 0.503000f, true); + // 039: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.395000f, 0.476000f, false); + shape.addVertex(0, 0.412000f, 0.431000f, true); + // 040: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.445000f, 0.480000f, false); + shape.addVertex(0, 0.491000f, 0.504000f, true); + // 042: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.537000f, 0.529000f, false); + shape.addVertex(0, 0.587000f, 0.529000f, true); + // 043: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.682000f, 0.529000f, false); + shape.addVertex(0, 0.738000f, 0.467000f, true); + // 045: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.795000f, 0.405000f, false); + shape.addVertex(0, 0.795000f, 0.276000f, true); + // 046: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.795000f, 0.268000f, false); + shape.addVertex(0, 0.795000f, 0.260000f, true); + // 048: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.794000f, 0.252000f, false); + shape.addVertex(0, 0.793000f, 0.245000f, true); + // 049: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.430000f, 0.245000f, true); + // 050: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.433000f, 0.150000f, false); + shape.addVertex(0, 0.477000f, 0.099000f, true); + // 052: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.521000f, 0.048000f, false); + shape.addVertex(0, 0.617000f, 0.048000f, true); + // 053: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.670000f, 0.048000f, false); + shape.addVertex(0, 0.701000f, 0.058000f, true); + // 055: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.732000f, 0.068000f, false); + shape.addVertex(0, 0.746000f, 0.075000f, true); + // 056: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.758000f, 0.019000f, true); + // 057: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.744000f, 0.011000f, false); + shape.addVertex(0, 0.706000f, 0.000000f, true); + // 059: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.667000f, -0.011000f, false); + shape.addVertex(0, 0.615000f, -0.011000f, true); + // 060: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.558000f, -0.011000f, false); + shape.addVertex(0, 0.514000f, 0.003000f, true); + // 062: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.470000f, 0.017000f, false); + shape.addVertex(0, 0.437000f, 0.049000f, true); + // 063: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.426000f, 0.040000f, false); + shape.addVertex(0, 0.410000f, 0.030000f, true); + // 065: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0, 0.393000f, 0.019000f, false); + shape.addVertex(0, 0.370000f, 0.010000f, true); + // 066: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0, 0.347000f, 0.001000f, false); + shape.addVertex(0, 0.318000f, -0.005000f, true); + // 067: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.289000f, -0.011000f, false); + shape.addVertex(0, 0.252000f, -0.011000f, true); + System.err.println("Glyph02UbuntuLight_ae.shape02a.winding_area: "+shape.getWindingOfLastOutline()); + shape.closeLastOutline(false); + } else { + // Outer shape: Winding.CW + // Moved into OutlineShape same-order -> Winding.CW -> OK now + // + // Shape.MoveTo: + shape.closeLastOutline(false); + shape.addEmptyOutline(); + shape.addVertex(0.252000f, -0.011000f, true); + // 009: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0.208000f, -0.011000f, false); + shape.addVertex(0.171000f, -0.002000f, true); + // 011: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0.133000f, 0.007000f, false); + shape.addVertex(0.106000f, 0.026000f, true); + // 012: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0.079000f, 0.046000f, false); + shape.addVertex(0.064000f, 0.076000f, true); + // 013: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0.048000f, 0.107000f, false); + shape.addVertex(0.048000f, 0.151000f, true); + // 014: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0.048000f, 0.193000f, false); + shape.addVertex(0.064000f, 0.223000f, true); + // 016: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0.080000f, 0.253000f, false); + shape.addVertex(0.109000f, 0.272000f, true); + // 017: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0.138000f, 0.292000f, false); + shape.addVertex(0.178000f, 0.301000f, true); + // 018: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0.218000f, 0.310000f, false); + shape.addVertex(0.265000f, 0.310000f, true); + // 019: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0.279000f, 0.310000f, false); + shape.addVertex(0.294000f, 0.309000f, true); + // 021: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0.310000f, 0.307000f, false); + shape.addVertex(0.324000f, 0.305000f, true); + // 022: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0.339000f, 0.302000f, false); + shape.addVertex(0.349000f, 0.300000f, true); + // 023: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0.360000f, 0.297000f, false); + shape.addVertex(0.364000f, 0.295000f, true); + // 024: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0.364000f, 0.327000f, true); + // 025: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0.364000f, 0.354000f, false); + shape.addVertex(0.360000f, 0.379000f, true); + // 027: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0.356000f, 0.405000f, false); + shape.addVertex(0.343000f, 0.425000f, true); + // 028: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0.329000f, 0.446000f, false); + shape.addVertex(0.305000f, 0.458000f, true); + // 029: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0.280000f, 0.471000f, false); + shape.addVertex(0.240000f, 0.471000f, true); + // 030: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0.186000f, 0.471000f, false); + shape.addVertex(0.156000f, 0.464000f, true); + // 032: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0.126000f, 0.456000f, false); + shape.addVertex(0.113000f, 0.451000f, true); + // 033: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0.105000f, 0.507000f, true); + // 034: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0.122000f, 0.515000f, false); + shape.addVertex(0.158000f, 0.522000f, true); + // 036: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0.194000f, 0.529000f, false); + shape.addVertex(0.243000f, 0.529000f, true); + // 037: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0.314000f, 0.529000f, false); + shape.addVertex(0.354000f, 0.503000f, true); + // 039: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0.395000f, 0.476000f, false); + shape.addVertex(0.412000f, 0.431000f, true); + // 040: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0.445000f, 0.480000f, false); + shape.addVertex(0.491000f, 0.504000f, true); + // 042: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0.537000f, 0.529000f, false); + shape.addVertex(0.587000f, 0.529000f, true); + // 043: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0.682000f, 0.529000f, false); + shape.addVertex(0.738000f, 0.467000f, true); + // 045: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0.795000f, 0.405000f, false); + shape.addVertex(0.795000f, 0.276000f, true); + // 046: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0.795000f, 0.268000f, false); + shape.addVertex(0.795000f, 0.260000f, true); + // 048: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0.794000f, 0.252000f, false); + shape.addVertex(0.793000f, 0.245000f, true); + // 049: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0.430000f, 0.245000f, true); + // 050: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0.433000f, 0.150000f, false); + shape.addVertex(0.477000f, 0.099000f, true); + // 052: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0.521000f, 0.048000f, false); + shape.addVertex(0.617000f, 0.048000f, true); + // 053: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0.670000f, 0.048000f, false); + shape.addVertex(0.701000f, 0.058000f, true); + // 055: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0.732000f, 0.068000f, false); + shape.addVertex(0.746000f, 0.075000f, true); + // 056: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0.758000f, 0.019000f, true); + // 057: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0.744000f, 0.011000f, false); + shape.addVertex(0.706000f, 0.000000f, true); + // 059: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0.667000f, -0.011000f, false); + shape.addVertex(0.615000f, -0.011000f, true); + // 060: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0.558000f, -0.011000f, false); + shape.addVertex(0.514000f, 0.003000f, true); + // 062: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0.470000f, 0.017000f, false); + shape.addVertex(0.437000f, 0.049000f, true); + // 063: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0.426000f, 0.040000f, false); + shape.addVertex(0.410000f, 0.030000f, true); + // 065: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0.393000f, 0.019000f, false); + shape.addVertex(0.370000f, 0.010000f, true); + // 066: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0.347000f, 0.001000f, false); + shape.addVertex(0.318000f, -0.005000f, true); + // 067: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0.289000f, -0.011000f, false); + shape.addVertex(0.252000f, -0.011000f, true); + System.err.println("Glyph02UbuntuLight_ae.shape02b.winding_area: "+shape.getWindingOfLastOutline()); + shape.closeLastOutline(false); + } + + if( true ) { + // Original Inner a-shape: Winding.CCW + // Moved into OutlineShape reverse -> Winding.CW -> OK now + // + // Shape.MoveTo: + shape.closeLastOutline(false); + shape.addEmptyOutline(); + shape.addVertex(0, 0.365000f, 0.238000f, true); + // 068: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.354000f, 0.243000f, false); + shape.addVertex(0, 0.330000f, 0.248000f, true); + // 070: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.305000f, 0.254000f, false); + shape.addVertex(0, 0.263000f, 0.254000f, true); + // 071: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.239000f, 0.254000f, false); + shape.addVertex(0, 0.213000f, 0.251000f, true); + // 073: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0, 0.187000f, 0.247000f, false); + shape.addVertex(0, 0.165000f, 0.236000f, true); + // 074: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0, 0.143000f, 0.224000f, false); + shape.addVertex(0, 0.129000f, 0.204000f, true); + // 075: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.115000f, 0.184000f, false); + shape.addVertex(0, 0.115000f, 0.151000f, true); + // 076: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.115000f, 0.122000f, false); + shape.addVertex(0, 0.125000f, 0.102000f, true); + // 078: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0, 0.135000f, 0.082000f, false); + shape.addVertex(0, 0.153000f, 0.070000f, true); + // 079: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0, 0.172000f, 0.058000f, false); + shape.addVertex(0, 0.197000f, 0.053000f, true); + // 080: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.222000f, 0.047000f, false); + shape.addVertex(0, 0.252000f, 0.047000f, true); + // 081: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.314000f, 0.047000f, false); + shape.addVertex(0, 0.350000f, 0.063000f, true); + // 083: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.386000f, 0.080000f, false); + shape.addVertex(0, 0.400000f, 0.093000f, true); + // 084: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.384000f, 0.119000f, false); + shape.addVertex(0, 0.375000f, 0.154000f, true); + // 086: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.366000f, 0.190000f, false); + shape.addVertex(0, 0.365000f, 0.238000f, true); + System.err.println("Glyph02UbuntuLight_ae.shape03a.winding_area: "+shape.getWindingOfLastOutline()); + shape.closeLastOutline(false); + } else { + // Inner a-shape: Winding.CCW + // Moved into OutlineShape same-order -> Winding.CCW -> OK + // + // Shape.MoveTo: + shape.closeLastOutline(false); + shape.addEmptyOutline(); + shape.addVertex(0.365000f, 0.238000f, true); + // 068: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0.354000f, 0.243000f, false); + shape.addVertex(0.330000f, 0.248000f, true); + // 070: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0.305000f, 0.254000f, false); + shape.addVertex(0.263000f, 0.254000f, true); + // 071: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0.239000f, 0.254000f, false); + shape.addVertex(0.213000f, 0.251000f, true); + // 073: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0.187000f, 0.247000f, false); + shape.addVertex(0.165000f, 0.236000f, true); + // 074: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0.143000f, 0.224000f, false); + shape.addVertex(0.129000f, 0.204000f, true); + // 075: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0.115000f, 0.184000f, false); + shape.addVertex(0.115000f, 0.151000f, true); + // 076: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0.115000f, 0.122000f, false); + shape.addVertex(0.125000f, 0.102000f, true); + // 078: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0.135000f, 0.082000f, false); + shape.addVertex(0.153000f, 0.070000f, true); + // 079: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0.172000f, 0.058000f, false); + shape.addVertex(0.197000f, 0.053000f, true); + // 080: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0.222000f, 0.047000f, false); + shape.addVertex(0.252000f, 0.047000f, true); + // 081: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0.314000f, 0.047000f, false); + shape.addVertex(0.350000f, 0.063000f, true); + // 083: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0.386000f, 0.080000f, false); + shape.addVertex(0.400000f, 0.093000f, true); + // 084: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0.384000f, 0.119000f, false); + shape.addVertex(0.375000f, 0.154000f, true); + // 086: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0.366000f, 0.190000f, false); + shape.addVertex(0.365000f, 0.238000f, true); + System.err.println("Glyph02UbuntuLight_ae.shape03b.winding_area: "+shape.getWindingOfLastOutline()); + shape.closeLastOutline(false); + } + // End Shape for Glyph 193 + + shape.setIsQuadraticNurbs(); + shape.setSharpness(shapesSharpness); + region.addOutlineShape(shape, null, rgbaColor); + + box.resize(shape.getBounds()); + } + + @Override + public String getSubString() { + return super.getSubString(); + } +} diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph03FreeMonoRegular_M.java b/src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph03FreeMonoRegular_M.java new file mode 100644 index 000000000..45868762c --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph03FreeMonoRegular_M.java @@ -0,0 +1,804 @@ +/** + * Copyright 2023 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.demos.graph.ui.testshapes; + +import com.jogamp.opengl.GL2ES2; +import com.jogamp.graph.curve.OutlineShape; +import com.jogamp.graph.curve.opengl.RegionRenderer; +import com.jogamp.graph.geom.Vertex; +import com.jogamp.graph.geom.Vertex.Factory; +import com.jogamp.graph.ui.gl.Shape; + +/** + * GPU based resolution independent test object + * - FreeMono-Regular, capital case 'M' + * - TTF Shape for Glyph 48 + */ +public class Glyph03FreeMonoRegular_M extends Shape { + + public Glyph03FreeMonoRegular_M(final Factory factory, final int renderModes) { + super(factory, renderModes); + } + + @Override + protected void clearImpl(final GL2ES2 gl, final RegionRenderer renderer) { + } + + @Override + protected void destroyImpl(final GL2ES2 gl, final RegionRenderer renderer) { + } + + @SuppressWarnings("unused") + @Override + protected void addShapeToRegion(final GL2ES2 gl, final RegionRenderer renderer) { + final OutlineShape shape = new OutlineShape(renderer.getRenderState().getVertexFactory()); + + if( false ) { + // Start TTF Shape for Glyph 48 + // GlyphShape<48>: offset 0 of 45/45 points + // pM[044] P[483/522, on true, end true] + // p0[000] P[326/169, on true, end false] + // p1[001] P[280/169, on true, end false] + // p2[002] P[121/522, on true, end false] + // 000: B0a: move-to p0 + // Shape.MoveTo: + shape.closeLastOutline(false); + shape.addEmptyOutline(); + shape.addVertex(0, 0.326000f, 0.169000f, true); + // 000: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.280000f, 0.169000f, true); + // GlyphShape<48>: offset 1 of 45/45 points + // pM[000] P[326/169, on true, end false] + // p0[001] P[280/169, on true, end false] + // p1[002] P[121/522, on true, end false] + // p2[003] P[113/522, on true, end false] + // 001: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.121000f, 0.522000f, true); + // GlyphShape<48>: offset 2 of 45/45 points + // pM[001] P[280/169, on true, end false] + // p0[002] P[121/522, on true, end false] + // p1[003] P[113/522, on true, end false] + // p2[004] P[113/41, on true, end false] + // 002: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.113000f, 0.522000f, true); + // GlyphShape<48>: offset 3 of 45/45 points + // pM[002] P[121/522, on true, end false] + // p0[003] P[113/522, on true, end false] + // p1[004] P[113/41, on true, end false] + // p2[005] P[187/41, on true, end false] + // 003: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.113000f, 0.041000f, true); + // GlyphShape<48>: offset 4 of 45/45 points + // pM[003] P[113/522, on true, end false] + // p0[004] P[113/41, on true, end false] + // p1[005] P[187/41, on true, end false] + // p2[006] P[215/41, on false, end false] + // 004: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.187000f, 0.041000f, true); + // GlyphShape<48>: offset 5 of 45/45 points + // pM[004] P[113/41, on true, end false] + // p0[005] P[187/41, on true, end false] + // p1[006] P[215/41, on false, end false] + // p2[007] P[215/21, on true, end false] + // 005: B2: quad-to p0-p1-p2 + // Shape.QuadTo: + shape.addVertex(0, 0.215000f, 0.041000f, false); + shape.addVertex(0, 0.215000f, 0.021000f, true); + // GlyphShape<48>: offset 7 of 45/45 points + // pM[006] P[215/41, on false, end false] + // p0[007] P[215/21, on true, end false] + // p1[008] P[215/0, on false, end false] + // p2[009] P[187/0, on true, end false] + // 007: B2: quad-to p0-p1-p2 + // Shape.QuadTo: + shape.addVertex(0, 0.215000f, 0.000000f, false); + shape.addVertex(0, 0.187000f, 0.000000f, true); + // GlyphShape<48>: offset 9 of 45/45 points + // pM[008] P[215/0, on false, end false] + // p0[009] P[187/0, on true, end false] + // p1[010] P[38/0, on true, end false] + // p2[011] P[11/0, on false, end false] + // 009: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.038000f, 0.000000f, true); + // GlyphShape<48>: offset 10 of 45/45 points + // pM[009] P[187/0, on true, end false] + // p0[010] P[38/0, on true, end false] + // p1[011] P[11/0, on false, end false] + // p2[012] P[11/21, on true, end false] + // 010: B2: quad-to p0-p1-p2 + // Shape.QuadTo: + shape.addVertex(0, 0.011000f, 0.000000f, false); + shape.addVertex(0, 0.011000f, 0.021000f, true); + // GlyphShape<48>: offset 12 of 45/45 points + // pM[011] P[11/0, on false, end false] + // p0[012] P[11/21, on true, end false] + // p1[013] P[11/41, on false, end false] + // p2[014] P[38/41, on true, end false] + // 012: B2: quad-to p0-p1-p2 + // Shape.QuadTo: + shape.addVertex(0, 0.011000f, 0.041000f, false); + shape.addVertex(0, 0.038000f, 0.041000f, true); + // GlyphShape<48>: offset 14 of 45/45 points + // pM[013] P[11/41, on false, end false] + // p0[014] P[38/41, on true, end false] + // p1[015] P[72/41, on true, end false] + // p2[016] P[72/522, on true, end false] + // 014: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.072000f, 0.041000f, true); + // GlyphShape<48>: offset 15 of 45/45 points + // pM[014] P[38/41, on true, end false] + // p0[015] P[72/41, on true, end false] + // p1[016] P[72/522, on true, end false] + // p2[017] P[47/522, on true, end false] + // 015: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.072000f, 0.522000f, true); + // GlyphShape<48>: offset 16 of 45/45 points + // pM[015] P[72/41, on true, end false] + // p0[016] P[72/522, on true, end false] + // p1[017] P[47/522, on true, end false] + // p2[018] P[20/522, on false, end false] + // 016: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.047000f, 0.522000f, true); + // GlyphShape<48>: offset 17 of 45/45 points + // pM[016] P[72/522, on true, end false] + // p0[017] P[47/522, on true, end false] + // p1[018] P[20/522, on false, end false] + // p2[019] P[20/543, on true, end false] + // 017: B2: quad-to p0-p1-p2 + // Shape.QuadTo: + shape.addVertex(0, 0.020000f, 0.522000f, false); + shape.addVertex(0, 0.020000f, 0.543000f, true); + // GlyphShape<48>: offset 19 of 45/45 points + // pM[018] P[20/522, on false, end false] + // p0[019] P[20/543, on true, end false] + // p1[020] P[20/563, on false, end false] + // p2[021] P[47/563, on true, end false] + // 019: B2: quad-to p0-p1-p2 + // Shape.QuadTo: + shape.addVertex(0, 0.020000f, 0.563000f, false); + shape.addVertex(0, 0.047000f, 0.563000f, true); + // GlyphShape<48>: offset 21 of 45/45 points + // pM[020] P[20/563, on false, end false] + // p0[021] P[47/563, on true, end false] + // p1[022] P[146/563, on true, end false] + // p2[023] P[303/215, on true, end false] + // 021: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.146000f, 0.563000f, true); + // GlyphShape<48>: offset 22 of 45/45 points + // pM[021] P[47/563, on true, end false] + // p0[022] P[146/563, on true, end false] + // p1[023] P[303/215, on true, end false] + // p2[024] P[457/563, on true, end false] + // 022: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.303000f, 0.215000f, true); + // GlyphShape<48>: offset 23 of 45/45 points + // pM[022] P[146/563, on true, end false] + // p0[023] P[303/215, on true, end false] + // p1[024] P[457/563, on true, end false] + // p2[025] P[557/563, on true, end false] + // 023: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.457000f, 0.563000f, true); + // GlyphShape<48>: offset 24 of 45/45 points + // pM[023] P[303/215, on true, end false] + // p0[024] P[457/563, on true, end false] + // p1[025] P[557/563, on true, end false] + // p2[026] P[584/563, on false, end false] + // 024: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.557000f, 0.563000f, true); + // GlyphShape<48>: offset 25 of 45/45 points + // pM[024] P[457/563, on true, end false] + // p0[025] P[557/563, on true, end false] + // p1[026] P[584/563, on false, end false] + // p2[027] P[584/543, on true, end false] + // 025: B2: quad-to p0-p1-p2 + // Shape.QuadTo: + shape.addVertex(0, 0.584000f, 0.563000f, false); + shape.addVertex(0, 0.584000f, 0.543000f, true); + // GlyphShape<48>: offset 27 of 45/45 points + // pM[026] P[584/563, on false, end false] + // p0[027] P[584/543, on true, end false] + // p1[028] P[584/522, on false, end false] + // p2[029] P[557/522, on true, end false] + // 027: B2: quad-to p0-p1-p2 + // Shape.QuadTo: + shape.addVertex(0, 0.584000f, 0.522000f, false); + shape.addVertex(0, 0.557000f, 0.522000f, true); + // GlyphShape<48>: offset 29 of 45/45 points + // pM[028] P[584/522, on false, end false] + // p0[029] P[557/522, on true, end false] + // p1[030] P[532/522, on true, end false] + // p2[031] P[532/41, on true, end false] + // 029: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.532000f, 0.522000f, true); + // GlyphShape<48>: offset 30 of 45/45 points + // pM[029] P[557/522, on true, end false] + // p0[030] P[532/522, on true, end false] + // p1[031] P[532/41, on true, end false] + // p2[032] P[566/41, on true, end false] + // 030: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.532000f, 0.041000f, true); + // GlyphShape<48>: offset 31 of 45/45 points + // pM[030] P[532/522, on true, end false] + // p0[031] P[532/41, on true, end false] + // p1[032] P[566/41, on true, end false] + // p2[033] P[593/41, on false, end false] + // 031: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.566000f, 0.041000f, true); + // GlyphShape<48>: offset 32 of 45/45 points + // pM[031] P[532/41, on true, end false] + // p0[032] P[566/41, on true, end false] + // p1[033] P[593/41, on false, end false] + // p2[034] P[593/21, on true, end false] + // 032: B2: quad-to p0-p1-p2 + // Shape.QuadTo: + shape.addVertex(0, 0.593000f, 0.041000f, false); + shape.addVertex(0, 0.593000f, 0.021000f, true); + // GlyphShape<48>: offset 34 of 45/45 points + // pM[033] P[593/41, on false, end false] + // p0[034] P[593/21, on true, end false] + // p1[035] P[593/0, on false, end false] + // p2[036] P[566/0, on true, end false] + // 034: B2: quad-to p0-p1-p2 + // Shape.QuadTo: + shape.addVertex(0, 0.593000f, 0.000000f, false); + shape.addVertex(0, 0.566000f, 0.000000f, true); + // GlyphShape<48>: offset 36 of 45/45 points + // pM[035] P[593/0, on false, end false] + // p0[036] P[566/0, on true, end false] + // p1[037] P[417/0, on true, end false] + // p2[038] P[390/0, on false, end false] + // 036: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.417000f, 0.000000f, true); + // GlyphShape<48>: offset 37 of 45/45 points + // pM[036] P[566/0, on true, end false] + // p0[037] P[417/0, on true, end false] + // p1[038] P[390/0, on false, end false] + // p2[039] P[390/21, on true, end false] + // 037: B2: quad-to p0-p1-p2 + // Shape.QuadTo: + shape.addVertex(0, 0.390000f, 0.000000f, false); + shape.addVertex(0, 0.390000f, 0.021000f, true); + // GlyphShape<48>: offset 39 of 45/45 points + // pM[038] P[390/0, on false, end false] + // p0[039] P[390/21, on true, end false] + // p1[040] P[390/41, on false, end false] + // p2[041] P[417/41, on true, end false] + // 039: B2: quad-to p0-p1-p2 + // Shape.QuadTo: + shape.addVertex(0, 0.390000f, 0.041000f, false); + shape.addVertex(0, 0.417000f, 0.041000f, true); + // GlyphShape<48>: offset 41 of 45/45 points + // pM[040] P[390/41, on false, end false] + // p0[041] P[417/41, on true, end false] + // p1[042] P[491/41, on true, end false] + // p2[043] P[491/522, on true, end false] + // 041: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.491000f, 0.041000f, true); + // GlyphShape<48>: offset 42 of 45/45 points + // pM[041] P[417/41, on true, end false] + // p0[042] P[491/41, on true, end false] + // p1[043] P[491/522, on true, end false] + // p2[044] P[483/522, on true, end true] + // 042: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.491000f, 0.522000f, true); + // GlyphShape<48>: offset 43 of 45/45 points + // pM[042] P[491/41, on true, end false] + // p0[043] P[491/522, on true, end false] + // p1[044] P[483/522, on true, end true] + // p2[000] P[326/169, on true, end false] + // 043: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.483000f, 0.522000f, true); + // GlyphShape<48>: offset 44 of 45/45 points + // pM[043] P[491/522, on true, end false] + // p0[044] P[483/522, on true, end true] + // p1[000] P[326/169, on true, end false] + // p2[001] P[280/169, on true, end false] + // 044: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.326000f, 0.169000f, true); + System.err.println("Glyph03FreeMonoRegular_M.shape01a.winding_area: "+shape.getWindingOfLastOutline()); + shape.closeLastOutline(false); + + // End Shape for Glyph 48 + } else if( false ) { + // Start TTF Shape for Glyph 48 + // GlyphShape<48>: offset 0 of 45/45 points + // pM[044] P[483/522, on true, end true] + // p0[000] P[326/169, on true, end false] + // p1[001] P[280/169, on true, end false] + // p2[002] P[121/522, on true, end false] + // 000: B0a: move-to p0 + // Shape.MoveTo: + shape.closeLastOutline(false); + shape.addEmptyOutline(); + shape.addVertex(0, 0.326000f, 0.169000f, true); + // 000: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.280000f, 0.169000f, true); + // GlyphShape<48>: offset 1 of 45/45 points + // pM[000] P[326/169, on true, end false] + // p0[001] P[280/169, on true, end false] + // p1[002] P[121/522, on true, end false] + // p2[003] P[113/522, on true, end false] + // 001: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.121000f, 0.522000f, true); + // GlyphShape<48>: offset 2 of 45/45 points + // pM[001] P[280/169, on true, end false] + // p0[002] P[121/522, on true, end false] + // p1[003] P[113/522, on true, end false] + // p2[004] P[113/41, on true, end false] + // 002: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.113000f, 0.522000f, true); + // GlyphShape<48>: offset 3 of 45/45 points + // pM[002] P[121/522, on true, end false] + // p0[003] P[113/522, on true, end false] + // p1[004] P[113/41, on true, end false] + // p2[005] P[187/41, on true, end false] + // 003: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.113000f, 0.041000f, true); + // GlyphShape<48>: offset 4 of 45/45 points + // pM[003] P[113/522, on true, end false] + // p0[004] P[113/41, on true, end false] + // p1[005] P[187/41, on true, end false] + // p2[006] P[215/41, on false, end false] + // 004: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.187000f, 0.041000f, true); + // GlyphShape<48>: offset 5 of 45/45 points + // pM[004] P[113/41, on true, end false] + // p0[005] P[187/41, on true, end false] + // p1[006] P[215/41, on false, end false] + // p2[007] P[215/21, on true, end false] + // 005: B2: quad-to p0-p1-p2 + // Shape.QuadTo: + shape.addVertex(0, 0.215000f, 0.041000f, true); // curve -> line + shape.addVertex(0, 0.215000f, 0.021000f, true); + // GlyphShape<48>: offset 7 of 45/45 points + // pM[006] P[215/41, on false, end false] + // p0[007] P[215/21, on true, end false] + // p1[008] P[215/0, on false, end false] + // p2[009] P[187/0, on true, end false] + // 007: B2: quad-to p0-p1-p2 + // Shape.QuadTo: + shape.addVertex(0, 0.215000f, 0.000000f, true); // curve -> line + shape.addVertex(0, 0.187000f, 0.000000f, true); + // GlyphShape<48>: offset 9 of 45/45 points + // pM[008] P[215/0, on false, end false] + // p0[009] P[187/0, on true, end false] + // p1[010] P[38/0, on true, end false] + // p2[011] P[11/0, on false, end false] + // 009: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.038000f, 0.000000f, true); + // GlyphShape<48>: offset 10 of 45/45 points + // pM[009] P[187/0, on true, end false] + // p0[010] P[38/0, on true, end false] + // p1[011] P[11/0, on false, end false] + // p2[012] P[11/21, on true, end false] + // 010: B2: quad-to p0-p1-p2 + // Shape.QuadTo: + shape.addVertex(0, 0.011000f, 0.000000f, true); // curve -> line + shape.addVertex(0, 0.011000f, 0.021000f, true); + // GlyphShape<48>: offset 12 of 45/45 points + // pM[011] P[11/0, on false, end false] + // p0[012] P[11/21, on true, end false] + // p1[013] P[11/41, on false, end false] + // p2[014] P[38/41, on true, end false] + // 012: B2: quad-to p0-p1-p2 + // Shape.QuadTo: + shape.addVertex(0, 0.011000f, 0.041000f, true); // curve -> line + shape.addVertex(0, 0.038000f, 0.041000f, true); + // GlyphShape<48>: offset 14 of 45/45 points + // pM[013] P[11/41, on false, end false] + // p0[014] P[38/41, on true, end false] + // p1[015] P[72/41, on true, end false] + // p2[016] P[72/522, on true, end false] + // 014: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.072000f, 0.041000f, true); + // GlyphShape<48>: offset 15 of 45/45 points + // pM[014] P[38/41, on true, end false] + // p0[015] P[72/41, on true, end false] + // p1[016] P[72/522, on true, end false] + // p2[017] P[47/522, on true, end false] + // 015: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.072000f, 0.522000f, true); + // GlyphShape<48>: offset 16 of 45/45 points + // pM[015] P[72/41, on true, end false] + // p0[016] P[72/522, on true, end false] + // p1[017] P[47/522, on true, end false] + // p2[018] P[20/522, on false, end false] + // 016: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.047000f, 0.522000f, true); + // GlyphShape<48>: offset 17 of 45/45 points + // pM[016] P[72/522, on true, end false] + // p0[017] P[47/522, on true, end false] + // p1[018] P[20/522, on false, end false] + // p2[019] P[20/543, on true, end false] + // 017: B2: quad-to p0-p1-p2 + // Shape.QuadTo: + shape.addVertex(0, 0.020000f, 0.522000f, true); // curve -> line + shape.addVertex(0, 0.020000f, 0.543000f, true); + // GlyphShape<48>: offset 19 of 45/45 points + // pM[018] P[20/522, on false, end false] + // p0[019] P[20/543, on true, end false] + // p1[020] P[20/563, on false, end false] + // p2[021] P[47/563, on true, end false] + // 019: B2: quad-to p0-p1-p2 + // Shape.QuadTo: + shape.addVertex(0, 0.020000f, 0.563000f, true); // curve -> line + shape.addVertex(0, 0.047000f, 0.563000f, true); + // GlyphShape<48>: offset 21 of 45/45 points + // pM[020] P[20/563, on false, end false] + // p0[021] P[47/563, on true, end false] + // p1[022] P[146/563, on true, end false] + // p2[023] P[303/215, on true, end false] + // 021: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.146000f, 0.563000f, true); + // GlyphShape<48>: offset 22 of 45/45 points + // pM[021] P[47/563, on true, end false] + // p0[022] P[146/563, on true, end false] + // p1[023] P[303/215, on true, end false] + // p2[024] P[457/563, on true, end false] + // 022: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.303000f, 0.215000f, true); + // GlyphShape<48>: offset 23 of 45/45 points + // pM[022] P[146/563, on true, end false] + // p0[023] P[303/215, on true, end false] + // p1[024] P[457/563, on true, end false] + // p2[025] P[557/563, on true, end false] + // 023: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.457000f, 0.563000f, true); + // GlyphShape<48>: offset 24 of 45/45 points + // pM[023] P[303/215, on true, end false] + // p0[024] P[457/563, on true, end false] + // p1[025] P[557/563, on true, end false] + // p2[026] P[584/563, on false, end false] + // 024: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.557000f, 0.563000f, true); + // GlyphShape<48>: offset 25 of 45/45 points + // pM[024] P[457/563, on true, end false] + // p0[025] P[557/563, on true, end false] + // p1[026] P[584/563, on false, end false] + // p2[027] P[584/543, on true, end false] + // 025: B2: quad-to p0-p1-p2 + // Shape.QuadTo: + shape.addVertex(0, 0.584000f, 0.563000f, true); // curve -> line + shape.addVertex(0, 0.584000f, 0.543000f, true); + // GlyphShape<48>: offset 27 of 45/45 points + // pM[026] P[584/563, on false, end false] + // p0[027] P[584/543, on true, end false] + // p1[028] P[584/522, on false, end false] + // p2[029] P[557/522, on true, end false] + // 027: B2: quad-to p0-p1-p2 + // Shape.QuadTo: + shape.addVertex(0, 0.584000f, 0.522000f, true); // curve -> line + shape.addVertex(0, 0.557000f, 0.522000f, true); + // GlyphShape<48>: offset 29 of 45/45 points + // pM[028] P[584/522, on false, end false] + // p0[029] P[557/522, on true, end false] + // p1[030] P[532/522, on true, end false] + // p2[031] P[532/41, on true, end false] + // 029: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.532000f, 0.522000f, true); + // GlyphShape<48>: offset 30 of 45/45 points + // pM[029] P[557/522, on true, end false] + // p0[030] P[532/522, on true, end false] + // p1[031] P[532/41, on true, end false] + // p2[032] P[566/41, on true, end false] + // 030: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.532000f, 0.041000f, true); + // GlyphShape<48>: offset 31 of 45/45 points + // pM[030] P[532/522, on true, end false] + // p0[031] P[532/41, on true, end false] + // p1[032] P[566/41, on true, end false] + // p2[033] P[593/41, on false, end false] + // 031: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.566000f, 0.041000f, true); + // GlyphShape<48>: offset 32 of 45/45 points + // pM[031] P[532/41, on true, end false] + // p0[032] P[566/41, on true, end false] + // p1[033] P[593/41, on false, end false] + // p2[034] P[593/21, on true, end false] + // 032: B2: quad-to p0-p1-p2 + // Shape.QuadTo: + shape.addVertex(0, 0.593000f, 0.041000f, true); // curve -> line + shape.addVertex(0, 0.593000f, 0.021000f, true); + // GlyphShape<48>: offset 34 of 45/45 points + // pM[033] P[593/41, on false, end false] + // p0[034] P[593/21, on true, end false] + // p1[035] P[593/0, on false, end false] + // p2[036] P[566/0, on true, end false] + // 034: B2: quad-to p0-p1-p2 + // Shape.QuadTo: + shape.addVertex(0, 0.593000f, 0.000000f, true); // curve -> line + shape.addVertex(0, 0.566000f, 0.000000f, true); + // GlyphShape<48>: offset 36 of 45/45 points + // pM[035] P[593/0, on false, end false] + // p0[036] P[566/0, on true, end false] + // p1[037] P[417/0, on true, end false] + // p2[038] P[390/0, on false, end false] + // 036: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.417000f, 0.000000f, true); + // GlyphShape<48>: offset 37 of 45/45 points + // pM[036] P[566/0, on true, end false] + // p0[037] P[417/0, on true, end false] + // p1[038] P[390/0, on false, end false] + // p2[039] P[390/21, on true, end false] + // 037: B2: quad-to p0-p1-p2 + // Shape.QuadTo: + shape.addVertex(0, 0.390000f, 0.000000f, true); // curve -> line + shape.addVertex(0, 0.390000f, 0.021000f, true); + // GlyphShape<48>: offset 39 of 45/45 points + // pM[038] P[390/0, on false, end false] + // p0[039] P[390/21, on true, end false] + // p1[040] P[390/41, on false, end false] + // p2[041] P[417/41, on true, end false] + // 039: B2: quad-to p0-p1-p2 + // Shape.QuadTo: + shape.addVertex(0, 0.390000f, 0.041000f, true); // curve -> line + shape.addVertex(0, 0.417000f, 0.041000f, true); + // GlyphShape<48>: offset 41 of 45/45 points + // pM[040] P[390/41, on false, end false] + // p0[041] P[417/41, on true, end false] + // p1[042] P[491/41, on true, end false] + // p2[043] P[491/522, on true, end false] + // 041: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.491000f, 0.041000f, true); + // GlyphShape<48>: offset 42 of 45/45 points + // pM[041] P[417/41, on true, end false] + // p0[042] P[491/41, on true, end false] + // p1[043] P[491/522, on true, end false] + // p2[044] P[483/522, on true, end true] + // 042: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.491000f, 0.522000f, true); + // GlyphShape<48>: offset 43 of 45/45 points + // pM[042] P[491/41, on true, end false] + // p0[043] P[491/522, on true, end false] + // p1[044] P[483/522, on true, end true] + // p2[000] P[326/169, on true, end false] + // 043: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.483000f, 0.522000f, true); + // GlyphShape<48>: offset 44 of 45/45 points + // pM[043] P[491/522, on true, end false] + // p0[044] P[483/522, on true, end true] + // p1[000] P[326/169, on true, end false] + // p2[001] P[280/169, on true, end false] + // 044: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.326000f, 0.169000f, true); + System.err.println("Glyph03FreeMonoRegular_M.shape01a.winding_area: "+shape.getWindingOfLastOutline()); + shape.closeLastOutline(false); + } else { + final boolean with_left_leg = true; // ERROR + final boolean with_right_leg = false; // OK + + // Start TTF Shape for Glyph 48 + // GlyphShape<48>: offset 0 of 45/45 points + // pM[044] P[483/522, on true, end true] + // p0[000] P[326/169, on true, end false] + // p1[001] P[280/169, on true, end false] + // p2[002] P[121/522, on true, end false] + // 000: B0a: move-to p0 + // Shape.MoveTo: + shape.closeLastOutline(false); + shape.addEmptyOutline(); + shape.addVertex(0, 0.326000f, 0.169000f, true); + // 000: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.280000f, 0.169000f, true); + // GlyphShape<48>: offset 1 of 45/45 points + // pM[000] P[326/169, on true, end false] + // p0[001] P[280/169, on true, end false] + // p1[002] P[121/522, on true, end false] + // p2[003] P[113/522, on true, end false] + // 001: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.121000f, 0.522000f, true); // ID 11 + + // GlyphShape<48>: offset 2 of 45/45 points + // pM[001] P[280/169, on true, end false] + // p0[002] P[121/522, on true, end false] + // p1[003] P[113/522, on true, end false] + // p2[004] P[113/41, on true, end false] + // 002: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.113000f, 0.522000f, true); + + if( with_left_leg ) { + // GlyphShape<48>: offset 3 of 45/45 points + // pM[002] P[121/522, on true, end false] + // p0[003] P[113/522, on true, end false] + // p1[004] P[113/41, on true, end false] + // p2[005] P[187/41, on true, end false] + // 003: B1: line-to p0-p1 + // Shape.LineTo: + // shape.addVertex(0, 0.113000f, 0.041000f, true); + + shape.addVertex(0, 0.113000f, 0.000000f, true); + shape.addVertex(0, 0.072000f, 0.000000f, true); + + // GlyphShape<48>: offset 14 of 45/45 points + // pM[013] P[11/41, on false, end false] + // p0[014] P[38/41, on true, end false] + // p1[015] P[72/41, on true, end false] + // p2[016] P[72/522, on true, end false] + // 014: B1: line-to p0-p1 + // Shape.LineTo: + // shape.addVertex(0, 0.072000f, 0.041000f, true); + + // GlyphShape<48>: offset 15 of 45/45 points + // pM[014] P[38/41, on true, end false] + // p0[015] P[72/41, on true, end false] + // p1[016] P[72/522, on true, end false] + // p2[017] P[47/522, on true, end false] + // 015: B1: line-to p0-p1 + // Shape.LineTo: + // shape.addVertex(0, 0.072000f, 0.522000f, true); + + shape.addVertex(0, 0.072000f, 0.563000f, true); // ID 7 + } else { + shape.addVertex(0, 0.113000f, 0.563000f, true); + } + + // GlyphShape<48>: offset 21 of 45/45 points + // pM[020] P[20/563, on false, end false] + // p0[021] P[47/563, on true, end false] + // p1[022] P[146/563, on true, end false] + // p2[023] P[303/215, on true, end false] + // 021: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.146000f, 0.563000f, true); + // GlyphShape<48>: offset 22 of 45/45 points + // pM[021] P[47/563, on true, end false] + // p0[022] P[146/563, on true, end false] + // p1[023] P[303/215, on true, end false] + // p2[024] P[457/563, on true, end false] + // 022: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.303000f, 0.215000f, true); + // GlyphShape<48>: offset 23 of 45/45 points + // pM[022] P[146/563, on true, end false] + // p0[023] P[303/215, on true, end false] + // p1[024] P[457/563, on true, end false] + // p2[025] P[557/563, on true, end false] + // 023: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.457000f, 0.563000f, true); // ID 4 + + if( with_right_leg ) { + shape.addVertex(0, 0.532000f, 0.563000f, true); + + // GlyphShape<48>: offset 29 of 45/45 points + // pM[028] P[584/522, on false, end false] + // p0[029] P[557/522, on true, end false] + // p1[030] P[532/522, on true, end false] + // p2[031] P[532/41, on true, end false] + // 029: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.532000f, 0.522000f, true); + // GlyphShape<48>: offset 30 of 45/45 points + // pM[029] P[557/522, on true, end false] + // p0[030] P[532/522, on true, end false] + // p1[031] P[532/41, on true, end false] + // p2[032] P[566/41, on true, end false] + // 030: B1: line-to p0-p1 + // Shape.LineTo: + // shape.addVertex(0, 0.532000f, 0.041000f, true); + + shape.addVertex(0, 0.532000f, 0.000000f, true); + shape.addVertex(0, 0.491000f, 0.000000f, true); + } else { + shape.addVertex(0, 0.491000f, 0.563000f, true); // ID 3 + } + + // GlyphShape<48>: offset 41 of 45/45 points + // pM[040] P[390/41, on false, end false] + // p0[041] P[417/41, on true, end false] + // p1[042] P[491/41, on true, end false] + // p2[043] P[491/522, on true, end false] + // 041: B1: line-to p0-p1 + // Shape.LineTo: + // shape.addVertex(0, 0.491000f, 0.041000f, true); + + // GlyphShape<48>: offset 42 of 45/45 points + // pM[041] P[417/41, on true, end false] + // p0[042] P[491/41, on true, end false] + // p1[043] P[491/522, on true, end false] + // p2[044] P[483/522, on true, end true] + // 042: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.491000f, 0.522000f, true); // ID 2 + // GlyphShape<48>: offset 43 of 45/45 points + // pM[042] P[491/41, on true, end false] + // p0[043] P[491/522, on true, end false] + // p1[044] P[483/522, on true, end true] + // p2[000] P[326/169, on true, end false] + // 043: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.483000f, 0.522000f, true); // ID 1 + // GlyphShape<48>: offset 44 of 45/45 points + // pM[043] P[491/522, on true, end false] + // p0[044] P[483/522, on true, end true] + // p1[000] P[326/169, on true, end false] + // p2[001] P[280/169, on true, end false] + // 044: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.326000f, 0.169000f, true); + System.err.println("Glyph03FreeMonoRegular_M.shape01a.winding_area: "+shape.getWindingOfLastOutline()); + shape.closeLastOutline(false); + } + + shape.setIsQuadraticNurbs(); + shape.setSharpness(shapesSharpness); + region.addOutlineShape(shape, null, rgbaColor); + + box.resize(shape.getBounds()); + } + + @Override + public String getSubString() { + return super.getSubString(); + } +} diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph04FreeSans_0.java b/src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph04FreeSans_0.java new file mode 100644 index 000000000..63bc0b5b5 --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph04FreeSans_0.java @@ -0,0 +1,150 @@ +/** + * Copyright 2023 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.demos.graph.ui.testshapes; + +import com.jogamp.opengl.GL2ES2; +import com.jogamp.graph.curve.OutlineShape; +import com.jogamp.graph.curve.opengl.RegionRenderer; +import com.jogamp.graph.geom.Vertex; +import com.jogamp.graph.geom.Vertex.Factory; +import com.jogamp.graph.ui.gl.Shape; + +/** + * GPU based resolution independent test object + * - FreeSans, '0' + * - TTF Shape for Glyph 19 + */ +public class Glyph04FreeSans_0 extends Shape { + + public Glyph04FreeSans_0(final Factory factory, final int renderModes) { + super(factory, renderModes); + } + + @Override + protected void clearImpl(final GL2ES2 gl, final RegionRenderer renderer) { + } + + @Override + protected void destroyImpl(final GL2ES2 gl, final RegionRenderer renderer) { + } + + @Override + protected void addShapeToRegion(final GL2ES2 gl, final RegionRenderer renderer) { + final OutlineShape shape = new OutlineShape(renderer.getRenderState().getVertexFactory()); + + // Start TTF Shape for Glyph 19 + // 000: B0a: move-to p0 + // Shape.MoveTo: + shape.closeLastOutline(false); + shape.addEmptyOutline(); + shape.addVertex(0, 0.043000f, 0.343000f, true); + // 000: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.043000f, 0.432000f, false); + shape.addVertex(0, 0.058000f, 0.500000f, true); + // 002: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0, 0.073000f, 0.568000f, false); + shape.addVertex(0, 0.096000f, 0.606000f, true); + // 003: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0, 0.119000f, 0.645000f, false); + shape.addVertex(0, 0.151000f, 0.669000f, true); + // 004: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0, 0.183000f, 0.693000f, false); + shape.addVertex(0, 0.212000f, 0.701000f, true); + // 005: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.242000f, 0.709000f, false); + shape.addVertex(0, 0.275000f, 0.709000f, true); + // 006: B2: quad-to p0-p1-p2 + // Shape.QuadTo: + shape.addVertex(0, 0.507000f, 0.709000f, false); + shape.addVertex(0, 0.507000f, 0.337000f, true); + // 008: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.507000f, 0.162000f, false); + shape.addVertex(0, 0.448000f, 0.070000f, true); + // 010: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.388000f, -0.023000f, false); + shape.addVertex(0, 0.275000f, -0.023000f, true); + // 011: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.161000f, -0.023000f, false); + shape.addVertex(0, 0.102000f, 0.070000f, true); + // 013: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.043000f, 0.164000f, false); + shape.addVertex(0, 0.043000f, 0.343000f, true); + System.err.println("Glyph04FreeSans_0.shape01a.winding_area: "+shape.getWindingOfLastOutline()); + shape.closeLastOutline(false); + + // 021: B0b: move-to pM + // Shape.MoveTo: + shape.closeLastOutline(false); + shape.addEmptyOutline(); + shape.addVertex(0, 0.417000f, 0.345000f, true); + // 021: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.417000f, 0.631000f, false); + shape.addVertex(0, 0.275000f, 0.631000f, true); + // 015: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.133000f, 0.631000f, false); + shape.addVertex(0, 0.133000f, 0.342000f, true); + // 016: B2: quad-to p0-p1-p2 + // Shape.QuadTo: + shape.addVertex(0, 0.133000f, 0.050000f, false); + shape.addVertex(0, 0.273000f, 0.050000f, true); + // 018: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.347000f, 0.050000f, false); + shape.addVertex(0, 0.382000f, 0.122000f, true); + // 020: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.417000f, 0.194000f, false); + shape.addVertex(0, 0.417000f, 0.345000f, true); + System.err.println("Glyph04FreeSans_0.shape02a.winding_area: "+shape.getWindingOfLastOutline()); + shape.closeLastOutline(false); + + // End Shape for Glyph 19 + + shape.setIsQuadraticNurbs(); + shape.setSharpness(shapesSharpness); + region.addOutlineShape(shape, null, rgbaColor); + + box.resize(shape.getBounds()); + } + + @Override + public String getSubString() { + return super.getSubString(); + } +} diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph05FreeSerifBoldItalic_ae.java b/src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph05FreeSerifBoldItalic_ae.java new file mode 100644 index 000000000..dd92228ff --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/graph/ui/testshapes/Glyph05FreeSerifBoldItalic_ae.java @@ -0,0 +1,287 @@ +/** + * Copyright 2023 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.demos.graph.ui.testshapes; + +import com.jogamp.opengl.GL2ES2; +import com.jogamp.graph.curve.OutlineShape; +import com.jogamp.graph.curve.opengl.RegionRenderer; +import com.jogamp.graph.geom.Vertex; +import com.jogamp.graph.geom.Vertex.Factory; +import com.jogamp.graph.ui.gl.Shape; + +/** + * GPU based resolution independent test object + * - FreeSans, '0' + * - TTF Shape for Glyph 19 + */ +public class Glyph05FreeSerifBoldItalic_ae extends Shape { + + public Glyph05FreeSerifBoldItalic_ae(final Factory factory, final int renderModes) { + super(factory, renderModes); + } + + @Override + protected void clearImpl(final GL2ES2 gl, final RegionRenderer renderer) { + } + + @Override + protected void destroyImpl(final GL2ES2 gl, final RegionRenderer renderer) { + } + + @Override + protected void addShapeToRegion(final GL2ES2 gl, final RegionRenderer renderer) { + final OutlineShape shape = new OutlineShape(renderer.getRenderState().getVertexFactory()); + + // Start TTF Shape for Glyph 168 + // 000: B0a: move-to p0 + // Shape.MoveTo: + shape.closeLastOutline(false); + shape.addEmptyOutline(); + shape.addVertex(0, 0.450000f, -0.013000f, true); + // 000: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.386000f, -0.013000f, false); + shape.addVertex(0, 0.353000f, 0.018000f, true); + // 002: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.319000f, 0.049000f, false); + shape.addVertex(0, 0.307000f, 0.118000f, true); + // 003: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.265000f, 0.049000f, false); + shape.addVertex(0, 0.225000f, 0.019000f, true); + // 005: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.184000f, -0.012000f, false); + shape.addVertex(0, 0.134000f, -0.012000f, true); + // 006: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.085000f, -0.012000f, false); + shape.addVertex(0, 0.053000f, 0.021000f, true); + // 008: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.020000f, 0.055000f, false); + shape.addVertex(0, 0.020000f, 0.106000f, true); + // 009: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.020000f, 0.185000f, false); + shape.addVertex(0, 0.062000f, 0.269000f, true); + // 011: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0, 0.105000f, 0.353000f, false); + shape.addVertex(0, 0.170000f, 0.407000f, true); + // 012: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.235000f, 0.462000f, false); + shape.addVertex(0, 0.296000f, 0.462000f, true); + // 013: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.328000f, 0.462000f, false); + shape.addVertex(0, 0.346000f, 0.448000f, true); + // 015: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.364000f, 0.433000f, false); + shape.addVertex(0, 0.377000f, 0.396000f, true); + // 016: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.395000f, 0.454000f, true); + // 017: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.498000f, 0.459000f, true); + // 018: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.478000f, 0.394000f, true); + // 019: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.510000f, 0.431000f, false); + shape.addVertex(0, 0.535000f, 0.445000f, true); + // 021: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.561000f, 0.459000f, false); + shape.addVertex(0, 0.598000f, 0.459000f, true); + // 022: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.645000f, 0.459000f, false); + shape.addVertex(0, 0.671000f, 0.436000f, true); + // 024: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.698000f, 0.413000f, false); + shape.addVertex(0, 0.698000f, 0.372000f, true); + // 025: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.698000f, 0.310000f, false); + shape.addVertex(0, 0.639000f, 0.263000f, true); + // 027: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.579000f, 0.215000f, false); + shape.addVertex(0, 0.470000f, 0.190000f, true); + // 028: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.431000f, 0.181000f, true); + // 029: B2: quad-to p0-p1-p2 + // Shape.QuadTo: + shape.addVertex(0, 0.426000f, 0.156000f, false); + shape.addVertex(0, 0.426000f, 0.134000f, true); + // 031: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.426000f, 0.096000f, false); + shape.addVertex(0, 0.444000f, 0.073000f, true); + // 033: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.462000f, 0.050000f, false); + shape.addVertex(0, 0.493000f, 0.050000f, true); + // 034: B2: quad-to p0-p1-p2 + // Shape.QuadTo: + shape.addVertex(0, 0.565000f, 0.050000f, false); + shape.addVertex(0, 0.616000f, 0.139000f, true); + // 036: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.644000f, 0.122000f, true); + // 037: B2: quad-to p0-p1-p2 + // Shape.QuadTo: + shape.addVertex(0, 0.578000f, -0.013000f, false); + shape.addVertex(0, 0.450000f, -0.013000f, true); + System.err.println("Glyph05FreeSerifBoldItalic_ae.shape01a.winding_area: "+shape.getWindingOfLastOutline()); + shape.closeLastOutline(false); + + // 039: B0a: move-to p0 + // Shape.MoveTo: + shape.closeLastOutline(false); + shape.addEmptyOutline(); + shape.addVertex(0, 0.194000f, 0.058000f, true); + // 039: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.238000f, 0.058000f, false); + shape.addVertex(0, 0.278000f, 0.122000f, true); + // 041: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0, 0.319000f, 0.187000f, false); + shape.addVertex(0, 0.338000f, 0.256000f, true); + // 042: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.358000f, 0.326000f, false); + shape.addVertex(0, 0.358000f, 0.363000f, true); + // 043: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.358000f, 0.387000f, false); + shape.addVertex(0, 0.345000f, 0.403000f, true); + // 045: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.331000f, 0.419000f, false); + shape.addVertex(0, 0.310000f, 0.419000f, true); + // 046: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.267000f, 0.419000f, false); + shape.addVertex(0, 0.227000f, 0.356000f, true); + // 048: B5: quad-to pMh-p0-p1h ***** MID + // Shape.QuadTo: + shape.addVertex(0, 0.187000f, 0.293000f, false); + shape.addVertex(0, 0.167000f, 0.225000f, true); + // 049: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.146000f, 0.156000f, false); + shape.addVertex(0, 0.146000f, 0.119000f, true); + // 050: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.146000f, 0.092000f, false); + shape.addVertex(0, 0.159000f, 0.075000f, true); + // 052: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.172000f, 0.058000f, false); + shape.addVertex(0, 0.194000f, 0.058000f, true); + System.err.println("Glyph05FreeSerifBoldItalic_ae.shape02a.winding_area: "+shape.getWindingOfLastOutline()); + shape.closeLastOutline(false); + + if( true ) { + // GlyphShape<168>: offset 0 of 8/61 points + // pM[060] P[443/231, on true, end true] + // p0[053] P[438/214, on true, end false] + // p1[054] P[498/223, on false, end false] + // p2[055] P[608/320, on false, end false] + // 053: B0a: move-to p0 + // Shape.MoveTo: + shape.closeLastOutline(false); + shape.addEmptyOutline(); + shape.addVertex(0, 0.438000f, 0.214000f, true); + // 053: B4: quad-to p0-p1-p2h **** MID + // Shape.QuadTo: + shape.addVertex(0, 0.498000f, 0.223000f, false); + shape.addVertex(0, 0.553000f, 0.271000f, true); + // GlyphShape<168>: offset 2 of 8/61 points + // pM[054] P[498/223, on false, end false] + // p0[055] P[608/320, on false, end false] + // p1[056] P[608/388, on true, end false] + // p2[057] P[608/429, on false, end false] + // 055: B6: quad-to pMh-p0-p1 + // Shape.QuadTo: + shape.addVertex(0, 0.608000f, 0.320000f, false); + shape.addVertex(0, 0.608000f, 0.388000f, true); + // GlyphShape<168>: offset 3 of 8/61 points + // pM[055] P[608/320, on false, end false] + // p0[056] P[608/388, on true, end false] + // p1[057] P[608/429, on false, end false] + // p2[058] P[575/429, on true, end false] + // 056: B2: quad-to p0-p1-p2 + // Shape.QuadTo: + shape.addVertex(0, 0.608000f, 0.429000f, false); + shape.addVertex(0, 0.575000f, 0.429000f, true); + // GlyphShape<168>: offset 5 of 8/61 points + // pM[057] P[608/429, on false, end false] + // p0[058] P[575/429, on true, end false] + // p1[059] P[502/429, on false, end false] + // p2[060] P[443/231, on true, end true] + // 058: B2: quad-to p0-p1-p2 + // Shape.QuadTo: + shape.addVertex(0, 0.502000f, 0.429000f, false); + shape.addVertex(0, 0.443000f, 0.231000f, true); + // GlyphShape<168>: offset 7 of 8/61 points + // pM[059] P[502/429, on false, end false] + // p0[060] P[443/231, on true, end true] + // p1[053] P[438/214, on true, end false] + // p2[054] P[498/223, on false, end false] + // 060: B1: line-to p0-p1 + // Shape.LineTo: + shape.addVertex(0, 0.438000f, 0.214000f, true); + System.err.println("Glyph05FreeSerifBoldItalic_ae.shape03a.winding_area: "+shape.getWindingOfLastOutline()); + shape.closeLastOutline(false); + } + + // End Shape for Glyph 168 + + shape.setIsQuadraticNurbs(); + shape.setSharpness(shapesSharpness); + region.addOutlineShape(shape, null, rgbaColor); + + box.resize(shape.getBounds()); + } + + @Override + public String getSubString() { + return super.getSubString(); + } +} diff --git a/src/demos/com/jogamp/opengl/demos/util/MiscUtils.java b/src/demos/com/jogamp/opengl/demos/util/MiscUtils.java new file mode 100644 index 000000000..f1c367e95 --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/util/MiscUtils.java @@ -0,0 +1,259 @@ +/** + * Copyright 2010 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.demos.util; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.lang.reflect.*; +import java.nio.FloatBuffer; +import java.util.Iterator; +import java.util.List; + +import com.jogamp.opengl.GLContext; + +import com.jogamp.common.os.Platform; +import com.jogamp.common.util.InterruptSource; + +public class MiscUtils { + public static boolean atob(final String str, final boolean def) { + try { + return Boolean.parseBoolean(str); + } catch (final Exception ex) { + ex.printStackTrace(); + } + return def; + } + + public static int atoi(final String str, final int def) { + try { + return Integer.parseInt(str); + } catch (final Exception ex) { + ex.printStackTrace(); + } + return def; + } + + public static long atol(final String str, final long def) { + try { + return Long.parseLong(str); + } catch (final Exception ex) { + ex.printStackTrace(); + } + return def; + } + + public static float atof(final String str, final float def) { + try { + return Float.parseFloat(str); + } catch (final Exception ex) { + ex.printStackTrace(); + } + return def; + } + + public static String toHexString(final byte hex) { + return "0x" + Integer.toHexString( hex & 0x000000FF ); + } + + public static String toHexString(final short hex) { + return "0x" + Integer.toHexString( hex & 0x0000FFFF ); + } + + public static String toHexString(final int hex) { + return "0x" + Integer.toHexString( hex ); + } + + public static String toHexString(final long hex) { + return "0x" + Long.toHexString( hex ); + } + + public static void assertFloatBufferEquals(final String errmsg, final FloatBuffer expected, final FloatBuffer actual, final float delta) { + if(null == expected && null == actual) { + return; + } + final String msg = null != errmsg ? errmsg + " " : ""; + if(null == expected) { + throw new AssertionError(msg+"; Expected is null, but actual not: "+actual); + } + if(null == actual) { + throw new AssertionError(msg+"; Actual is null, but expected not: "+expected); + } + if(expected.remaining() != actual.remaining()) { + throw new AssertionError(msg+"; Expected has "+expected.remaining()+" remaining, but actual has "+actual.remaining()); + } + final int a0 = expected.position(); + final int b0 = actual.position(); + for(int i=0; i delta ) { + throw new AssertionError(msg+"; Expected @ ["+a0+"+"+i+"] has "+ai+", but actual @ ["+b0+"+"+i+"] has "+bi+", it's delta "+daibi+" > "+delta); + } + } + } + + public static void assertFloatBufferNotEqual(final String errmsg, final FloatBuffer expected, final FloatBuffer actual, final float delta) { + if(null == expected || null == actual) { + return; + } + if(expected.remaining() != actual.remaining()) { + return; + } + final String msg = null != errmsg ? errmsg + " " : ""; + final int a0 = expected.position(); + final int b0 = actual.position(); + for(int i=0; i delta ) { + return; + } + } + throw new AssertionError(msg+"; Expected and actual are equal."); + } + + public static boolean setFieldIfExists(final Object instance, final String fieldName, final Object value) { + try { + final Field f = instance.getClass().getField(fieldName); + if(value instanceof Boolean || f.getType().isInstance(value)) { + f.set(instance, value); + return true; + } else { + System.out.println(instance.getClass()+" '"+fieldName+"' field not assignable with "+value.getClass()+", it's a: "+f.getType()); + } + } catch (final IllegalAccessException ex) { + throw new RuntimeException(ex); + } catch (final NoSuchFieldException nsfe) { + // OK - throw new RuntimeException(instance.getClass()+" has no '"+fieldName+"' field", nsfe); + } + return false; + } + + public static void waitForKey(final String preMessage) { + final BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); + System.err.println(preMessage+"> Press enter to continue"); + try { + System.err.println(stdin.readLine()); + } catch (final IOException e) { e.printStackTrace(); } + } + + + public static class StreamDump extends InterruptSource.Thread { + final InputStream is; + final StringBuilder outString; + final OutputStream outStream; + final String prefix; + final Object sync; + volatile boolean eos = false; + + public StreamDump(final OutputStream out, final String prefix, final InputStream is, final Object sync) { + this.is = is; + this.outString = null; + this.outStream = out; + this.prefix = prefix; + this.sync = sync; + } + public StreamDump(final StringBuilder sb, final String prefix, final InputStream is, final Object sync) { + this.is = is; + this.outString = sb; + this.outStream = null; + this.prefix = prefix; + this.sync = sync; + } + public StreamDump(final StringBuilder sb, final InputStream is, final Object sync) { + this.is = is; + this.outString = sb; + this.outStream = null; + this.prefix = null; + this.sync = sync; + } + + public final boolean eos() { return eos; } + + @Override + public void run() { + synchronized ( sync ) { + try { + final BufferedReader in = new BufferedReader( new InputStreamReader(is) ); + String line = null; + while ((line = in.readLine()) != null) { + if( null != outString ) { + outString.append(line).append(Platform.getNewline()); + } else if( null != outStream ) { + if( null != prefix ) { + outStream.write(prefix.getBytes()); + } + outStream.write(line.getBytes()); + outStream.write(Platform.getNewline().getBytes()); + outStream.flush(); + } + } + } catch (final IOException ioe) { + System.err.println("Caught "+ioe.getClass().getName()+": "+ioe.getMessage()); + ioe.printStackTrace(); + } finally { + eos = true; + sync.notifyAll(); + } + } + } + } + + public static void dumpSharedGLContext(final String prefix, final GLContext self) { + int i = 0, j = 0; + final GLContext master = self.getSharedMaster(); + final int masterHash = null != master ? master.hashCode() : 0; + System.err.println(prefix+": hash 0x"+Integer.toHexString(self.hashCode())+", \t(isShared "+self.isShared()+", created "+self.isCreated()+", master 0x"+Integer.toHexString(masterHash)+")"); + { + final List set = self.getCreatedShares(); + for (final Iterator iter = set.iterator(); iter.hasNext(); ) { + final GLContext c = iter.next(); + System.err.println(" Created Ctx #"+(i++)+": hash 0x"+Integer.toHexString(c.hashCode())+", \t(created "+c.isCreated()+")"); + } + } + { + final List set = self.getDestroyedShares(); + for (final Iterator iter = set.iterator(); iter.hasNext(); ) { + final GLContext c = iter.next(); + System.err.println(" Destroyed Ctx #"+(j++)+": hash 0x"+Integer.toHexString(c.hashCode())+", \t(created "+c.isCreated()+")"); + } + } + System.err.println("\t Total created "+i+" + destroyed "+j+" = "+(i+j)); + System.err.println(); + } +} + + + diff --git a/src/demos/com/jogamp/opengl/demos/util/QuitAdapter.java b/src/demos/com/jogamp/opengl/demos/util/QuitAdapter.java new file mode 100644 index 000000000..b7c3a6c22 --- /dev/null +++ b/src/demos/com/jogamp/opengl/demos/util/QuitAdapter.java @@ -0,0 +1,64 @@ +/** + * Copyright 2010 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.demos.util; + +import com.jogamp.newt.event.*; + +public class QuitAdapter extends WindowAdapter implements WindowListener, KeyListener { + boolean shouldQuit = false; + boolean enabled = true; + + public void enable(final boolean v) { enabled = v; } + + public void clear() { shouldQuit = false; } + + public boolean shouldQuit() { return shouldQuit; } + public void doQuit() { shouldQuit=true; } + + public void windowDestroyNotify(final WindowEvent e) { + if( enabled ) { + System.err.println("QUIT Window "+Thread.currentThread()); + shouldQuit = true; + } + } + + public void keyReleased(final KeyEvent e) { + if( !e.isPrintableKey() || e.isAutoRepeat() ) { + return; + } + if( enabled ) { + if(e.getKeyChar()=='q') { + System.err.println("QUIT Key "+Thread.currentThread()); + shouldQuit = true; + } + } + } + public void keyPressed(final KeyEvent e) {} +} + -- cgit v1.2.3