aboutsummaryrefslogtreecommitdiffstats
path: root/src/demos/com/jogamp
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2023-08-27 12:55:50 +0200
committerSven Gothel <[email protected]>2023-08-27 13:10:13 +0200
commit4448010d8d787c73d48f54b296c3a8c2499aeaa0 (patch)
tree81c55c148b0af0cb291e24814f9a90dac9a2eb75 /src/demos/com/jogamp
parent74e9bd8a46e20666700ce79e22d08a2a05f2c26f (diff)
GraphUI: Extract generalized AnimGroup functionality from UISceneDemo03*, providing sets of animated Shapes (GlyphShape or any other)
Hardcoding the whole animation process into user code is not feasible to allow a quick add-on. GraphUI's new AnimGroup is a Group and allows to add multiple AnimGroup.Set of AnimGroup.ShapeData. +++ AnimGroup.ShapeData holds the actual Shape and its start- and target position as well as its active animation state and an optional user object attachment. AnimGroup.Set holds a list of AnimGroup.ShapeData as well as the animation properties and states like acceleration and velocity for translation and angular operations. It also contains the AnimGroup.LerpFunc for linear interpolation of the next position as called via AnimGroup.tick() over all sets. AnimGroup.LerpFunc is intended to perform the linear interpolation for the next position, either user provided or one of the provided may be used, i.e. TargetLerp, ScrollLerp and SineLerp. To setup the start- and target position for each AnimGroup.ShapeData, a AnimGroup.ShapeSetup is used - user implementated or one of the build-in of AnimGroup.addGlyphSetHorizScroll01(..), AnimGroup.assGlyphSetRandom01(..). +++ UISceneDemo03 consolidated UISceneDemo03 + UISceneDemo03b (deleted) and shows the following AnimGroup capabilities: - Two repetitive scrolling text lines. One text shorter than the line-width and one longer. - One line of animated rectangles, rotating around their z-axis - A text animation assembling one line of text, each glyph coming from from a random 3D point moving to its destination all at once including rotation. - One line of text with sine wave animation
Diffstat (limited to 'src/demos/com/jogamp')
-rw-r--r--src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo03.java691
-rw-r--r--src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo03b.java563
-rw-r--r--src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo20.java16
-rw-r--r--src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemoU01a.java1
-rw-r--r--src/demos/com/jogamp/opengl/demos/util/CommandlineOptions.java15
-rw-r--r--src/demos/com/jogamp/opengl/demos/util/MiscUtils.java19
6 files changed, 524 insertions, 781 deletions
diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo03.java b/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo03.java
index e1febc560..e4bde4c3e 100644
--- a/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo03.java
+++ b/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo03.java
@@ -28,31 +28,42 @@
package com.jogamp.opengl.demos.graph.ui;
import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.Arrays;
import java.util.Random;
import com.jogamp.common.os.Clock;
import com.jogamp.common.util.IOUtil;
-import com.jogamp.common.util.InterruptSource;
import com.jogamp.graph.curve.Region;
import com.jogamp.graph.font.Font;
import com.jogamp.graph.font.FontFactory;
+import com.jogamp.graph.ui.GraphShape;
import com.jogamp.graph.ui.Group;
import com.jogamp.graph.ui.Scene;
+import com.jogamp.graph.ui.Shape;
+import com.jogamp.graph.ui.AnimGroup;
import com.jogamp.graph.ui.Scene.PMVMatrixSetup;
-import com.jogamp.graph.ui.shapes.GlyphShape;
+import com.jogamp.graph.ui.layout.Alignment;
+import com.jogamp.graph.ui.layout.Gap;
+import com.jogamp.graph.ui.layout.GridLayout;
+import com.jogamp.graph.ui.shapes.Button;
import com.jogamp.graph.ui.shapes.Label;
+import com.jogamp.graph.ui.shapes.Rectangle;
import com.jogamp.newt.MonitorDevice;
import com.jogamp.newt.event.KeyAdapter;
import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.newt.event.MouseAdapter;
+import com.jogamp.newt.event.MouseEvent;
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.GLEventListener;
import com.jogamp.opengl.GLProfile;
+import com.jogamp.opengl.JoglVersion;
import com.jogamp.opengl.demos.graph.FontSetDemos;
import com.jogamp.opengl.demos.util.CommandlineOptions;
import com.jogamp.opengl.demos.util.MiscUtils;
@@ -61,19 +72,28 @@ import com.jogamp.opengl.math.FloatUtil;
import com.jogamp.opengl.math.Quaternion;
import com.jogamp.opengl.math.Recti;
import com.jogamp.opengl.math.Vec3f;
+import com.jogamp.opengl.math.Vec4f;
import com.jogamp.opengl.math.geom.AABBox;
import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.util.PMVMatrix;
/**
- * Res independent Shape, Scene attached to GLWindow showing simple linear Shape movement.
+ * Res independent Shape, Scene attached to GLWindow showing multiple animated shape movements.
* <p>
- * This variation of {@link UISceneDemo00} shows a text animation assembling one line of text,
- * each glyph coming from from a random 3D point moving to its destination all at once.
+ * This variation of {@link UISceneDemo00} shows
+ * <ul>
+ * <li>Two repetitive scrolling text lines. One text shorter than the line-width and one longer.</li>
+ * <li>One line of animated rectangles, rotating around their z-axis</li>
+ * <li>A text animation assembling one line of text,
+ * each glyph coming from from a random 3D point moving to its destination all at once including rotation.</li>
+ * <li>One line of text with sine wave animation.</li>
+ * </ul>
* </p>
* <p>
* - Pass '-keep' to main-function to keep running.
* - Pass '-aspeed' to vary velocity
+ * - Pass '-rspeed <float>' angular velocity in radians/s
+ * - Pass '-no_anim_box' to not show a visible and shrunken box around the AnimGroup
* </p>
*/
public class UISceneDemo03 {
@@ -86,16 +106,24 @@ public class UISceneDemo03 {
};
static CommandlineOptions options = new CommandlineOptions(1280, 720, Region.VBAA_RENDERING_BIT);
+ static float frame_velocity = 5f / 1e3f; // [m]/[s]
static float velocity = 30 / 1e3f; // [m]/[s]
- static float rot_step = velocity * 1;
+ static float ang_velo = velocity * 60f; // [radians]/[s]
+ static int autoSpeed = -1;
+
+ static final int[] manualScreenShorCount = { 0 };
static void setVelocity(final float v) {
velocity = v; // Math.max(1/1e3f, v);
- rot_step = velocity * 1;
+ ang_velo = velocity * 60f;
+ autoSpeed = 0;
}
public static void main(final String[] args) throws IOException {
- int autoSpeed = 0;
+ setVelocity(80/1000f);
+ autoSpeed = -1;
+ options.keepRunning = true;
+ boolean showAnimBox = true;
if (0 != args.length) {
final int[] idx = { 0 };
@@ -106,12 +134,18 @@ public class UISceneDemo03 {
++idx[0];
setVelocity(MiscUtils.atoi(args[idx[0]], (int) velocity * 1000) / 1000f);
} else if(args[idx[0]].equals("-aspeed")) {
- autoSpeed = -1;
setVelocity(80/1000f);
+ autoSpeed = -1;
options.keepRunning = true;
+ } else if(args[idx[0]].equals("-rspeed")) {
+ ++idx[0];
+ ang_velo = MiscUtils.atof(args[idx[0]], ang_velo);
+ } else if(args[idx[0]].equals("-no_anim_box")) {
+ showAnimBox = false;
}
}
}
+ System.err.println(JoglVersion.getInstance().toString());
// renderModes |= Region.COLORCHANNEL_RENDERING_BIT;
System.err.println(options);
@@ -128,14 +162,14 @@ public class UISceneDemo03 {
final Scene scene = new Scene();
scene.setClearParams(new float[] { 1f, 1f, 1f, 1f }, GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
- scene.setPMVMatrixSetup(new MyPMVMatrixSetup());
+ scene.setPMVMatrixSetup( new MyPMVMatrixSetup(Scene.DEFAULT_SCENE_DIST) );
scene.setDebugBorderBox(options.debugBoxThickness);
- final Group glyphGroup = new Group();
- scene.addShape(glyphGroup);
+ final AnimGroup animGroup = new AnimGroup(null);
+ scene.addShape(animGroup);
- // scene.setFrustumCullingEnabled(true);
- glyphGroup.setFrustumCullingEnabled(true);
+ scene.setFrustumCullingEnabled(true);
+ animGroup.setFrustumCullingEnabled(true);
final Animator animator = new Animator(0 /* w/o AWT */);
animator.setUpdateFPSFrames(1 * 60, null); // System.err);
@@ -153,46 +187,18 @@ public class UISceneDemo03 {
window.setTitle(UISceneDemo03.class.getSimpleName() + ": " + window.getSurfaceWidth() + " x " + window.getSurfaceHeight());
window.setVisible(true);
window.addGLEventListener(scene);
- window.addWindowListener(new WindowAdapter() {
- @Override
- public void windowResized(final WindowEvent e) {
- window.setTitle(UISceneDemo03.class.getSimpleName() + ": " + window.getSurfaceWidth() + " x " + window.getSurfaceHeight());
- }
-
- @Override
- public void windowDestroyNotify(final WindowEvent e) {
- animator.stop();
- }
- });
- window.addKeyListener(new KeyAdapter() {
- @Override
- public void keyReleased(final KeyEvent e) {
- final short keySym = e.getKeySymbol();
- if (keySym == KeyEvent.VK_PLUS ||
- keySym == KeyEvent.VK_ADD)
- {
- if (e.isShiftDown()) {
- setVelocity(velocity + 10 / 1000f);
- } else {
- setVelocity(velocity + 1 / 1000f);
- }
- } else if (keySym == KeyEvent.VK_MINUS ||
- keySym == KeyEvent.VK_SUBTRACT)
- {
- if (e.isShiftDown()) {
- setVelocity(velocity - 10 / 1000f);
- } else {
- setVelocity(velocity - 1 / 1000f);
- }
- } else if( keySym == KeyEvent.VK_F4 || keySym == KeyEvent.VK_ESCAPE || keySym == KeyEvent.VK_Q ) {
- new InterruptSource.Thread( () -> { window.destroy(); } ).start();
- }
- }
- });
-
scene.attachInputListenerTo(window);
+ final float pixPerMM, dpiV;
+ {
+ final float[] tmp = window.getPixelsPerMM(new float[2]);
+ pixPerMM = tmp[0]; // [px]/[mm]
+ final float[] sDPI = MonitorDevice.perMMToPerInch( tmp );
+ dpiV = sDPI[1];
+ }
+
animator.add(window);
+ animator.setExclusiveContext(options.exclusiveContext);
animator.start();
//
@@ -202,18 +208,44 @@ public class UISceneDemo03 {
// - Compute the animation values with DPI
scene.waitUntilDisplayed();
- scene.setFrustumCullingEnabled(true);
window.invoke(true, (drawable) -> {
final GL gl = drawable.getGL();
gl.glEnable(GL.GL_DEPTH_TEST);
+ // gl.glDepthFunc(GL.GL_LEQUAL);
+ // gl.glEnable(GL.GL_BLEND);
return true;
});
final GLProfile hasGLP = window.getChosenGLCapabilities().getGLProfile();
final AABBox sceneBox = scene.getBounds();
+ final float sceneBoxFrameWidth;
+ {
+ sceneBoxFrameWidth = sceneBox.getWidth() * 0.0025f;
+ final GraphShape r = new Rectangle(options.renderModes, sceneBox, sceneBoxFrameWidth);
+ if( showAnimBox ) {
+ r.setColor(0.45f, 0.45f, 0.45f, 0.9f);
+ } else {
+ r.setColor(0f, 0f, 0f, 0f);
+ }
+ r.setInteractive(false);
+ animGroup.addShape( r );
+ }
+ animGroup.setRotationPivot(0, 0, 0);
+ if( showAnimBox ) {
+ animGroup.scale(0.85f, 0.85f, 1f);
+ animGroup.move(-sceneBox.getWidth()/2f*0.075f, 0f, 0f);
+ animGroup.getRotation().rotateByAngleY(0.1325f);
+ } else {
+ animGroup.scale(1.0f, 1.0f, 1f);
+ }
+ animGroup.validate(hasGLP);
+ animGroup.setInteractive(false);
+ animGroup.setToggleable(true);
+ animGroup.setResizable(false);
+ animGroup.setToggle( false );
System.err.println("SceneBox " + sceneBox);
System.err.println("Frustum " + scene.getMatrix().getFrustum());
- System.err.println("GlyphGroup.0: "+glyphGroup);
+ System.err.println("AnimGroup.0: "+animGroup);
final Label statusLabel;
{
@@ -227,6 +259,7 @@ public class UISceneDemo03 {
statusLabel.moveTo(sceneBox.getMinX(), sceneBox.getMinY() + statusLabelScale * (fontStatus.getMetrics().getLineGap() - fontStatus.getMetrics().getDescent()), 0f);
scene.addShape(statusLabel);
}
+ sub01SetupWindowListener(window, scene, animGroup, statusLabel, dpiV);
{
final StringBuilder sb = new StringBuilder();
@@ -248,194 +281,452 @@ public class UISceneDemo03 {
window.invoke(true, (drawable) -> {
final GL2ES2 gl = drawable.getGL().getGL2ES2();
- scene.screenshot(drawable.getGL(), scene.nextScreenshotFile(null, UISceneDemo03.class.getSimpleName(), options.renderModes, drawable.getChosenGLCapabilities(), null));
+ scene.screenshot(gl, scene.nextScreenshotFile(null, UISceneDemo03.class.getSimpleName(), options.renderModes, window.getChosenGLCapabilities(), null));
scene.removeShape(gl, l);
return true;
});
}
//
+ // HUD UI
+ //
+ sub02AddUItoScene(scene, animGroup, 2, window);
+
+ //
// Setup the moving glyphs
//
+ final boolean[] z_only = { true };
+ int txt_idx = 0;
- final List<GlyphShape> glyphShapes = new ArrayList<GlyphShape>();
+ final AABBox animBox = new AABBox( animGroup.getBounds() );
+ final float g_w = animBox.getWidth();
+ System.err.println("AnimBox " + animBox);
+ System.err.println("AnimGroup.1 " + animGroup);
- final float pixPerMM, dpiV;
- {
- final float[] tmp = window.getPixelsPerMM(new float[2]);
- pixPerMM = tmp[0]; // [px]/[mm]
- final float[] sDPI = MonitorDevice.perMMToPerInch( tmp );
- dpiV = sDPI[1];
- }
-
- boolean z_only = true;
- int txt_idx = 0;
+ final float[] y_pos = { 0 };
+ window.invoke(true, (drawable) -> {
+ final float fontScale2;
+ {
+ final String vs = "Welcome to Göthel Software *** Jausoft *** https://jausoft.com *** We do software ... Bremerhaven 19°C, Munich";
+ final AABBox fbox = font.getGlyphBounds(vs);
+ fontScale2 = g_w / fbox.getWidth();
+ System.err.println("FontScale2: " + fontScale2 + " = " + g_w + " / " + fbox.getWidth());
+ }
+ final AABBox clippedBox = new AABBox(animBox).resizeWidth(sceneBoxFrameWidth, -sceneBoxFrameWidth);
+ y_pos[0] = clippedBox.getMaxY();
+ // AnimGroup.Set 1:
+ // Circular short scrolling text (right to left) without rotation, no acceleration
+ {
+ final String vs = "Welcome to Göthel Software *** Jausoft *** https://jausoft.com *** We do software ... ";
+ y_pos[0] -= fontScale2 * 1.5f;
+ animGroup.addGlyphSetHorizScroll01(pixPerMM, hasGLP, scene.getMatrix(), scene.getViewport(), options.renderModes,
+ font, vs, fontScale2, new Vec4f(0.1f, 0.1f, 0.1f, 0.9f),
+ 50 / 1e3f /* velocity */, clippedBox, y_pos[0]);
+ }
+ // AnimGroup.Set 2:
+ // Circular long scrolling text (right to left) without rotation, no acceleration
+ {
+ final String vs = "Berlin 23°C, London 20°C, Paris 22°C, Madrid 26°C, Lisbon 28°C, Moscow 22°C, Prag 22°C, Bremerhaven 19°C, Munich 25°C, Fukushima 40°C, Bejing 30°C, Rome 29°C, Beirut 28°C, Damaskus 29°C *** ";
+ y_pos[0] -= fontScale2 * 1.2f;
+ animGroup.addGlyphSetHorizScroll01(pixPerMM, hasGLP, scene.getMatrix(), scene.getViewport(), options.renderModes,
+ font, vs, fontScale2, new Vec4f(0.1f, 0.1f, 0.1f, 0.9f),
+ 30 / 1e3f /* velocity */, clippedBox, y_pos[0]);
+ }
+ return true;
+ });
do {
+ //
+ // Setup new animation sequence
+ // - Flush all AnimGroup.Set entries
+ // - Add newly created AnimGroup.Set entries
+ //
+ final String curText = originalTexts[txt_idx];
final float fontScale;
+ final AnimGroup.Set[] dynAnimSet = { null, null, null };
{
- final AABBox fbox = font.getGlyphBounds(originalTexts[txt_idx]);
- fontScale = sceneBox.getWidth() / fbox.getWidth();
- System.err.println("FontScale: " + fontScale + " = " + sceneBox.getWidth() + " / " + fbox.getWidth());
+ final AABBox fbox = font.getGlyphBounds(curText);
+ fontScale = g_w / fbox.getWidth();
+ System.err.println("FontScale: " + fontScale + " = " + g_w + " / " + fbox.getWidth());
}
- z_only = !z_only;
+ z_only[0] = !z_only[0];
window.invoke(true, (drawable) -> {
- glyphGroup.removeAllShapes(drawable.getGL().getGL2ES2(), scene.getRenderer());
- return true;
- });
+ // AnimGroup.Set 3: This `mainAnimSet[0]` is controlling overall animation duration
+ // Rotating animated text moving to target (right to left) + slight acceleration on rotation
+ dynAnimSet[0] = animGroup.addGlyphSetRandom01(pixPerMM, hasGLP, scene.getMatrix(), scene.getViewport(),
+ options.renderModes, font, curText, fontScale, new Vec4f(0.1f, 0.1f, 0.1f, 1f),
+ 0f /* accel */, velocity, FloatUtil.PI/20f /* ang_accel */, ang_velo,
+ animBox, z_only[0], new Random(), new AnimGroup.TargetLerp(Vec3f.UNIT_Y));
+
+ // AnimGroup.Set 4:
+ // Sine animated text moving to target (right to left) with sine amplitude alternating on Z- and Y-axis + acceleration
+ {
+ final GL gl = drawable.getGL();
- final float[] movingGlyphPixPerShapeUnit;
- {
- final Random random = new Random();
-
- final GlyphShape testGlyph = new GlyphShape(options.renderModes, font, 'X', 0, 0);
- testGlyph.setScale(fontScale, fontScale, 1f);
- testGlyph.validate(hasGLP);
- final PMVMatrix pmv = new PMVMatrix();
- final int[] movingGlyphSizePx = testGlyph.getSurfaceSize(scene, pmv, new int[2]); // [px]
- movingGlyphPixPerShapeUnit = testGlyph.getPixelPerShapeUnit(movingGlyphSizePx, new float[2]); // [px]/[shapeUnit]
-
- final AABBox box = GlyphShape.processString(glyphShapes, options.renderModes, font, originalTexts[txt_idx]);
- System.err.println("Shapes: "+box);
- for(final GlyphShape gs : glyphShapes) {
- gs.setScale(fontScale, fontScale, 1f);
- gs.setColor(0.1f, 0.1f, 0.1f, 1);
- final Vec3f target = gs.getOrigPos(fontScale).add(sceneBox.getMinX(), 0f, 0f);
-
- final float start_pos_x = z_only ? target.x() :
- sceneBox.getMinX() + random.nextFloat() * sceneBox.getWidth();
- final float start_pos_y = z_only ? target.y() :
- sceneBox.getMinY() + random.nextFloat() * sceneBox.getHeight();
- final float start_pos_z = 0f + random.nextFloat() * sceneBox.getHeight() * 1f;
- gs.moveTo(start_pos_x, start_pos_y, start_pos_z);
+ final String vs = "JogAmp Version "+JoglVersion.getInstance().getImplementationVersion()+", "+gl.glGetString(GL.GL_VERSION)+", "+gl.glGetString(GL.GL_VENDOR);
+ final float fontScale2;
+ {
+ final AABBox fbox = font.getGlyphBounds(vs);
+ fontScale2 = g_w / fbox.getWidth() * 0.6f;
+ }
+ // Translation : We use velocity as acceleration (good match) and pass only velocity/10 as starting velocity
+ dynAnimSet[1] = animGroup.addGlyphSet(pixPerMM, hasGLP, scene.getMatrix(), scene.getViewport(),
+ options.renderModes, font, 'X', vs, fontScale2,
+ velocity /* accel */, velocity/10f, 0f /* ang_accel */, 2*FloatUtil.PI /* 1-rotation/s */,
+ new AnimGroup.SineLerp(z_only[0] ? Vec3f.UNIT_Z : Vec3f.UNIT_Y, 1.618f, 1.618f),
+ (final AnimGroup.Set as, final int idx, final AnimGroup.ShapeData sd) -> {
+ sd.shape.setColor(0.1f, 0.1f, 0.1f, 0.9f);
+
+ sd.targetPos.add(
+ animBox.getMinX() + as.refShape.getScaledWidth() * 1.0f,
+ animBox.getMinY() + as.refShape.getScaledHeight() * 2.0f, 0f);
+
+ sd.startPos.set( sd.targetPos.x() + animBox.getWidth(),
+ sd.targetPos.y(), sd.targetPos.z());
+ sd.shape.moveTo( sd.startPos );
+ } );
}
- // just add testGlyph to scene to be cleaned up, invisible
- testGlyph.setEnabled(false);
- glyphGroup.addShape(testGlyph);
- }
- glyphGroup.addShapes(glyphShapes);
+ // AnimGroup.Set 5:
+ // 3 animated Shapes moving to target (right to left) while rotating around z-axis + acceleration on translation
+ {
+ final float size2 = fontScale/2;
+ final float yscale = 1.1f;
+ final GraphShape refShape = new Rectangle(options.renderModes, size2, size2*yscale, sceneBox.getWidth() * 0.0025f );
+ dynAnimSet[2] = animGroup.addAnimSet(
+ pixPerMM, hasGLP, scene.getMatrix(), scene.getViewport(),
+ velocity /* accel */, velocity/10f, 0f /* ang_accel */, 2*FloatUtil.PI /* 1-rotation/s */,
+ new AnimGroup.TargetLerp(Vec3f.UNIT_Z), refShape);
+ final AnimGroup.ShapeSetup shapeSetup = (final AnimGroup.Set as, final int idx, final AnimGroup.ShapeData sd) -> {
+ sd.targetPos.add(animBox.getMinX() + as.refShape.getScaledWidth() * 1.0f,
+ y_pos[0] - as.refShape.getScaledHeight() * 1.5f, 0f);
+
+ sd.startPos.set( sd.targetPos.x() + animBox.getWidth(),
+ sd.targetPos.y(), sd.targetPos.z());
+ sd.shape.moveTo( sd.startPos );
+ };
+ refShape.setColor(1.0f, 0.0f, 0.0f, 0.9f);
+ refShape.getRotation().rotateByAngleZ(FloatUtil.QUARTER_PI);
+ dynAnimSet[2].addShape(animGroup, refShape, shapeSetup);
+ {
+ final Shape s = new Rectangle(options.renderModes, size2, size2*yscale, sceneBox.getWidth() * 0.0025f ).validate(hasGLP);
+ s.setColor(0.0f, 1.0f, 0.0f, 0.9f);
+ s.move(refShape.getScaledWidth() * 1.5f * 1, 0, 0);
+ dynAnimSet[2].addShape(animGroup, s, shapeSetup);
+ }
+ {
+ final Shape s = new Rectangle(options.renderModes, size2, size2*yscale, sceneBox.getWidth() * 0.0025f ).validate(hasGLP);
+ s.setColor(0.0f, 0.0f, 1.0f, 0.9f);
+ s.move(refShape.getScaledWidth() * 1.5f * 2, 0, 0);
+ s.getRotation().rotateByAngleZ(FloatUtil.QUARTER_PI);
+ dynAnimSet[2].addShape(animGroup, s, shapeSetup);
+ }
+ }
+ return true;
+ });
- final float pos_eps = FloatUtil.EPSILON * 5000; // ~= 0.0005960
- final float rot_eps = FloatUtil.adegToRad(0.5f); // 1 adeg ~= 0.01745 rad
+ // animGroup.setTickOnDraw(false);
final long t0_us = Clock.currentNanos() / 1000; // [us]
- final long[] t2_us = { t0_us };
- while ( !glyphShapes.isEmpty() && window.isNativeValid() ) {
- window.invoke(true, (drawable) -> {
- final long t3_us = Clock.currentNanos() / 1000;
- final float dt_s = (t3_us - t2_us[0]) / 1e6f;
- t2_us[0] = t3_us;
-
- final float velocity_px = velocity * 1e3f * pixPerMM; // [px]/[s]
- final float velocity_obj = velocity_px / movingGlyphPixPerShapeUnit[0]; // [shapeUnit]/[s]
- final float dxy = velocity_obj * dt_s; // [shapeUnit]
-
- for (int idx = glyphShapes.size() - 1; 0 <= idx; --idx) {
- final GlyphShape glyph = glyphShapes.get(idx);
- final Vec3f pos = new Vec3f(glyph.getPosition());
- final Vec3f target = glyph.getOrigPos(fontScale).add(sceneBox.getMinX(), 0f, 0f);
- final Vec3f p_t = target.minus(pos);
- final float p_t_diff = p_t.length();
- final Quaternion q = glyph.getRotation();
- final Vec3f euler = q.toEuler(new Vec3f());
- final float radY = euler.y();
- final float radYdiff = Math.min(Math.abs(radY), FloatUtil.TWO_PI - Math.abs(radY));
- final boolean pos_ok = p_t_diff <= pos_eps;
- final boolean pos_near = p_t_diff <= glyph.getBounds().getSize() * fontScale * 2f;
- final boolean rot_ok = pos_near && ( radYdiff <= rot_eps || radYdiff <= rot_step * 2f );
- if ( pos_ok && rot_ok ) {
- // arrived
- if( DEBUG ) {
- if( 0 == idx ) {
- System.err.println("F: rot: "+radY+" ("+FloatUtil.radToADeg(radY)+"), diff "+radYdiff+" ("+FloatUtil.radToADeg(radYdiff)+"), step "+rot_step+" ("+FloatUtil.radToADeg(rot_step)+")");
- }
- }
- glyph.moveTo(target.x(), target.y(), target.z());
- glyph.setInteractive(false);
- q.setIdentity();
- glyphShapes.remove(idx);
- continue;
- }
- if( !pos_ok ) {
- if( DEBUG ) {
- if( 0 == idx ) {
- System.err.println("p_t_diff: "+p_t_diff+", dxy "+dxy);
- }
- }
- if( p_t_diff <= dxy || p_t_diff <= pos_eps ) {
- glyph.moveTo(target.x(), target.y(), target.z());
- } else {
- p_t.normalize();
- pos.add( p_t.scale( dxy ) );
- glyph.moveTo(pos.x(), pos.y(), pos.z());
- }
- if( !rot_ok ) {
- if( pos_near ) {
- q.rotateByAngleY( rot_step * 2f );
- } else {
- q.rotateByAngleY( rot_step );
- }
- }
- } else {
- if( DEBUG ) {
- if( 0 == idx ) {
- System.err.println("P: rot: "+radY+" ("+FloatUtil.radToADeg(radY)+"), diff "+radYdiff+" ("+FloatUtil.radToADeg(radYdiff)+"), step "+rot_step+" ("+FloatUtil.radToADeg(rot_step)+")");
- }
- }
- if( radYdiff <= rot_step * 3f || radYdiff <= rot_eps ) {
- q.setIdentity();
- } else {
- q.rotateByAngleY( rot_step * 3f );
- }
- }
+ while ( ( null == dynAnimSet[0] || dynAnimSet[0].isAnimationActive() ) && window.isNativeValid() ) {
+ try { Thread.sleep(100); } catch (final InterruptedException e1) { }
+ }
+ if( window.isNativeValid() ) {
+ final float has_dur_s = ((Clock.currentNanos() / 1000) - t0_us) / 1e6f; // [us]
+ System.err.printf("Text travel-duration %.3f s, %d chars%n", has_dur_s, curText.length());
+ if( scene.getScreenshotCount() - manualScreenShorCount[0] < 1 + originalTexts.length ) {
+ scene.screenshot(true, scene.nextScreenshotFile(null, UISceneDemo03.class.getSimpleName(), options.renderModes, window.getChosenGLCapabilities(), null));
+ }
+ try { Thread.sleep(1500); } catch (final InterruptedException e1) { }
+ if( autoSpeed > 0 ) {
+ if( velocity < 60/1000f ) {
+ setVelocity(velocity + 9/1000f);
+ } else {
+ setVelocity(velocity - 9/1000f);
+ autoSpeed = -1;
+ }
+ } else if( autoSpeed < 0 ) {
+ if( velocity > 11/1000f ) {
+ setVelocity(velocity - 9/1000f);
+ } else {
+ setVelocity(velocity + 9/1000f);
+ autoSpeed = 1;
}
- final String text = String.format("%s, v %.1f mm/s, r %.3f",
- scene.getStatusText(drawable, options.renderModes, 0, dpiV), velocity * 1e3f, rot_step);
- statusLabel.setText(text);
+ }
+ txt_idx = ( txt_idx + 1 ) % originalTexts.length;
+ window.invoke(true, (drawable) -> {
+ animGroup.removeAnimSets(drawable.getGL().getGL2ES2(), scene.getRenderer(), Arrays.asList(dynAnimSet));
return true;
- });
+ } );
}
- final float has_dur_s = ((Clock.currentNanos() / 1000) - t0_us) / 1e6f; // [us]
- System.err.printf("Text travel-duration %.3f s, %d chars%n", has_dur_s, originalTexts[txt_idx].length());
- if( scene.getScreenshotCount() < 1 + originalTexts.length ) {
- scene.screenshot(true, scene.nextScreenshotFile(null, UISceneDemo03.class.getSimpleName(), options.renderModes, window.getChosenGLCapabilities(), null));
+ } while (options.keepRunning && window.isNativeValid());
+ if (!options.stayOpen) {
+ MiscUtils.destroyWindow(window);
+ }
+ }
+
+ /**
+ * Setup Window listener for I/O
+ * @param window
+ * @param animGroup
+ */
+ static void sub01SetupWindowListener(final GLWindow window, final Scene scene, final AnimGroup animGroup, final Label statusLabel, final float dpiV) {
+ window.addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowResized(final WindowEvent e) {
+ window.setTitle(UISceneDemo03.class.getSimpleName() + ": " + window.getSurfaceWidth() + " x " + window.getSurfaceHeight());
}
- try { Thread.sleep(2000); } catch (final InterruptedException e1) { }
- if( autoSpeed > 0 ) {
- if( velocity < 60/1000f ) {
- setVelocity(velocity + 9/1000f);
- } else {
- setVelocity(velocity - 9/1000f);
- autoSpeed = -1;
+
+ @Override
+ public void windowDestroyNotify(final WindowEvent e) {
+ final GLAnimatorControl animator = window.getAnimator();
+ if( null != animator ) {
+ animator.stop();
+ }
+ }
+ });
+ window.addKeyListener(new KeyAdapter() {
+ @Override
+ public void keyReleased(final KeyEvent e) {
+ final short keySym = e.getKeySymbol();
+ if (keySym == KeyEvent.VK_PLUS ||
+ keySym == KeyEvent.VK_ADD)
+ {
+ if (e.isShiftDown()) {
+ setVelocity(velocity + 10 / 1000f);
+ } else {
+ setVelocity(velocity + 1 / 1000f);
+ }
+ } else if (keySym == KeyEvent.VK_MINUS ||
+ keySym == KeyEvent.VK_SUBTRACT)
+ {
+ if (e.isShiftDown()) {
+ setVelocity(velocity - 10 / 1000f);
+ } else {
+ setVelocity(velocity - 1 / 1000f);
+ }
+ } else if( keySym == KeyEvent.VK_F4 || keySym == KeyEvent.VK_ESCAPE || keySym == KeyEvent.VK_Q ) {
+ MiscUtils.destroyWindow(window);
+ } else if( keySym == KeyEvent.VK_SPACE ) {
+ animGroup.setTickPaused ( !animGroup.getTickPaused() );
+ } else if( keySym == KeyEvent.VK_ENTER ) {
+ animGroup.stopAnimation();
}
- } else if( autoSpeed < 0 ) {
- if( velocity > 11/1000f ) {
- setVelocity(velocity - 9/1000f);
- } else {
- setVelocity(velocity + 9/1000f);
- autoSpeed = 1;
+ }
+ });
+ window.addMouseListener( new MouseAdapter() {
+ @Override
+ public void mouseWheelMoved(final MouseEvent e) {
+ int axis = 1;
+ if( e.isControlDown() ) {
+ axis = 0;
+ } else if( e.isAltDown() ) {
+ axis = 2;
}
+ final float angle = e.getRotation()[1] < 0f ? FloatUtil.adegToRad(-1f) : FloatUtil.adegToRad(1f);
+ rotateShape(animGroup, angle, axis);
}
- txt_idx = ( txt_idx + 1 ) % originalTexts.length;
- } while (options.keepRunning && window.isNativeValid());
- if (!options.stayOpen) {
- window.destroy();
+ });
+ window.addGLEventListener(new GLEventListener() {
+ float dir = 1f;
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ System.err.println(JoglVersion.getGLInfo(drawable.getGL(), null));
+ }
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {}
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ if( animGroup.isToggleOn() ) {
+ final Quaternion rot = animGroup.getRotation();
+ final Vec3f euler = rot.toEuler(new Vec3f());
+ if( FloatUtil.HALF_PI <= euler.y() ) {
+ dir = -1f;
+ } else if( euler.y() <= -FloatUtil.HALF_PI ) {
+ dir = 1f;
+ }
+ animGroup.getRotation().rotateByAngleY( frame_velocity * dir );
+ }
+ final String text = String.format("%s, v %.1f mm/s, r %.3f rad/s",
+ scene.getStatusText(drawable, options.renderModes, 0, dpiV), velocity * 1e3f, ang_velo);
+ statusLabel.setText(text);
+ }
+ @Override
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {}
+ });
+ }
+
+ /**
+ * Add a HUD UI to the scene
+ * @param scene
+ * @param animGroup
+ * @param window
+ * @throws IOException
+ */
+ static void sub02AddUItoScene(final Scene scene, final AnimGroup animGroup, final int mainAnimSetIdx, final GLWindow window) throws IOException {
+ final AABBox sceneBox = scene.getBounds();
+ final Group buttonsRight = new Group();
+
+ final Font fontButtons = FontFactory.get(FontFactory.UBUNTU).getDefault();
+ final float buttonWidth = sceneBox.getWidth() * 0.09f;
+ final float buttonHeight = buttonWidth / 3.0f;
+
+ buttonsRight.setLayout(new GridLayout(buttonWidth, buttonHeight, Alignment.Fill, new Gap(buttonHeight*0.50f, buttonWidth*0.10f), 7));
+ {
+ final Button button = new Button(options.renderModes, fontButtons, " Pause ", buttonWidth, buttonHeight);
+ button.setToggleable(true);
+ button.addMouseListener(new Shape.MouseGestureAdapter() {
+ @Override
+ public void mouseClicked(final MouseEvent e) {
+ animGroup.setTickPaused ( !animGroup.getTickPaused() );
+ } } );
+ buttonsRight.addShape(button);
+ }
+ {
+ final Button button = new Button(options.renderModes, fontButtons, " Next ", buttonWidth, buttonHeight);
+ button.addMouseListener(new Shape.MouseGestureAdapter() {
+ @Override
+ public void mouseClicked(final MouseEvent e) {
+ final AnimGroup.Set as = animGroup.getAnimSet(mainAnimSetIdx);
+ if( null != as ) {
+ as.setAnimationActive(false);
+ }
+ } } );
+ buttonsRight.addShape(button);
+ }
+ {
+ final Button button = new Button(options.renderModes, fontButtons, " Rotate ", buttonWidth, buttonHeight);
+ button.setToggleable(true);
+ button.addMouseListener(new Shape.MouseGestureAdapter() {
+ @Override
+ public void mouseClicked(final MouseEvent e) {
+ animGroup.toggle();
+ } } );
+ buttonsRight.addShape(button);
+ }
+ {
+ final Button button = new Button(options.renderModes, fontButtons, " < Rot > ", buttonWidth, buttonHeight);
+ button.addMouseListener(new Shape.MouseGestureAdapter() {
+ @Override
+ public void mouseClicked(final MouseEvent e) {
+ final Shape.EventInfo shapeEvent = (Shape.EventInfo) e.getAttachment();
+ int axis = 1;
+ if( e.isControlDown() ) {
+ axis = 0;
+ } else if( e.isAltDown() ) {
+ axis = 2;
+ }
+ if( shapeEvent.objPos.x() < shapeEvent.shape.getBounds().getCenter().x() ) {
+ rotateShape(animGroup, FloatUtil.adegToRad(1f), axis);
+ } else {
+ rotateShape(animGroup, FloatUtil.adegToRad(-1f), axis);
+ }
+ } } );
+ buttonsRight.addShape(button);
+ }
+ {
+ final Button button = new Button(options.renderModes, fontButtons, " < Velo > ", buttonWidth, buttonHeight);
+ button.addMouseListener(new Shape.MouseGestureAdapter() {
+ @Override
+ public void mouseClicked(final MouseEvent e) {
+ final Shape.EventInfo shapeEvent = (Shape.EventInfo) e.getAttachment();
+ final float scale = e.isShiftDown() ? 1f : 10f;
+ if( shapeEvent.objPos.x() < shapeEvent.shape.getBounds().getCenter().x() ) {
+ setVelocity(velocity - scale / 1000f);
+ } else {
+ setVelocity(velocity + scale / 1000f);
+ }
+ final AnimGroup.Set as = animGroup.getAnimSet(mainAnimSetIdx);
+ if( null != as ) {
+ as.setAnimationActive(false);
+ }
+ } } );
+ buttonsRight.addShape(button);
+ }
+ {
+ final Button button = new Button(options.renderModes, fontButtons, " Snap ", buttonWidth, buttonHeight);
+ button.addMouseListener(new Shape.MouseGestureAdapter() {
+ @Override
+ public void mouseClicked(final MouseEvent e) {
+ scene.screenshot(false, scene.nextScreenshotFile(null, UISceneDemo03.class.getSimpleName(), options.renderModes, window.getChosenGLCapabilities(), null));
+ manualScreenShorCount[0]++;
+ } } );
+ buttonsRight.addShape(button);
+ }
+ {
+ final Button button = new Button(options.renderModes, fontButtons, " Quit ", buttonWidth, buttonHeight);
+ button.setColor(0.7f, 0.3f, 0.3f, 1.0f);
+ button.addMouseListener(new Shape.MouseGestureAdapter() {
+ @Override
+ public void mouseClicked(final MouseEvent e) {
+ MiscUtils.destroyWindow(window);
+ } } );
+ buttonsRight.addShape(button);
+ }
+ buttonsRight.forAll((final Shape s) -> { s.setDragAndResizeable(false); return false; });
+ buttonsRight.validate(window.getChosenGLCapabilities().getGLProfile());
+ buttonsRight.moveTo(sceneBox.getWidth()/2f - buttonsRight.getScaledWidth()*1.02f,
+ sceneBox.getHeight()/2f - buttonsRight.getScaledHeight()*1.02f, 0f);
+ scene.addShape(buttonsRight);
+ if( DEBUG ) {
+ System.err.println("Buttons-Right: Button-1 "+buttonsRight.getShapes().get(0));
+ System.err.println("Buttons-Right: SceneBox "+sceneBox);
+ System.err.println("Buttons-Right: scaled "+buttonsRight.getScaledWidth()+" x "+buttonsRight.getScaledHeight());
+ System.err.println("Buttons-Right: Box "+buttonsRight.getBounds());
+ System.err.println("Buttons-Right: "+buttonsRight);
}
}
/**
+ * Rotate the shape while avoiding 90 degree position
+ * @param shape the shape to rotate
+ * @param angle the angle in radians
+ * @param axis 0 for X-, 1 for Y- and 2 for Z-axis
+ */
+ public static void rotateShape(final Shape shape, float angle, final int axis) {
+ final Quaternion rot = shape.getRotation();
+ final Vec3f euler = rot.toEuler(new Vec3f());
+ final Vec3f eulerOld = euler.copy();
+
+ final float eps = FloatUtil.adegToRad(5f);
+ final float sign = angle >= 0f ? 1f : -1f;
+ final float v;
+ switch( axis ) {
+ case 0: v = euler.x(); break;
+ case 1: v = euler.y(); break;
+ case 2: v = euler.z(); break;
+ default: return;
+ }
+ final float av = Math.abs(v);
+ if( 1f*FloatUtil.HALF_PI - eps <= av && av <= 1f*FloatUtil.HALF_PI + eps ||
+ 3f*FloatUtil.HALF_PI - eps <= av && av <= 3f*FloatUtil.HALF_PI + eps) {
+ angle = 2f * eps * sign;
+ }
+ switch( axis ) {
+ case 0: euler.add(angle, 0, 0); break;
+ case 1: euler.add(0, angle, 0); break;
+ case 2: euler.add(0, 0, angle); break;
+ }
+ System.err.println("Rot: angleDelta "+angle+" (eps "+eps+"): "+eulerOld+" -> "+euler);
+ rot.setFromEuler(euler);
+ }
+
+ /**
* Our PMVMatrixSetup:
* - gluPerspective like Scene's default
* - no normal scale to 1, keep distance to near plane for rotation effects.
*/
public static class MyPMVMatrixSetup implements PMVMatrixSetup {
+ private final float scene_dist;
+ public MyPMVMatrixSetup(final float scene_dist) {
+ this.scene_dist = scene_dist;
+ }
@Override
public void set(final PMVMatrix pmv, final Recti viewport) {
final float ratio = (float) viewport.width() / (float) viewport.height();
pmv.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
pmv.glLoadIdentity();
pmv.gluPerspective(Scene.DEFAULT_ANGLE, ratio, Scene.DEFAULT_ZNEAR, Scene.DEFAULT_ZFAR);
- pmv.glTranslatef(0f, 0f, Scene.DEFAULT_SCENE_DIST);
+ pmv.glTranslatef(0f, 0f, scene_dist);
pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
pmv.glLoadIdentity();
diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo03b.java b/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo03b.java
deleted file mode 100644
index 4d3e603ab..000000000
--- a/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo03b.java
+++ /dev/null
@@ -1,563 +0,0 @@
-/**
- * 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;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
-
-import com.jogamp.common.os.Clock;
-import com.jogamp.common.util.IOUtil;
-import com.jogamp.graph.curve.Region;
-import com.jogamp.graph.font.Font;
-import com.jogamp.graph.font.FontFactory;
-import com.jogamp.graph.ui.GraphShape;
-import com.jogamp.graph.ui.Group;
-import com.jogamp.graph.ui.Scene;
-import com.jogamp.graph.ui.Shape;
-import com.jogamp.graph.ui.Scene.PMVMatrixSetup;
-import com.jogamp.graph.ui.shapes.GlyphShape;
-import com.jogamp.graph.ui.shapes.Label;
-import com.jogamp.graph.ui.shapes.Rectangle;
-import com.jogamp.newt.MonitorDevice;
-import com.jogamp.newt.event.KeyAdapter;
-import com.jogamp.newt.event.KeyEvent;
-import com.jogamp.newt.event.MouseEvent;
-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.GLAutoDrawable;
-import com.jogamp.opengl.GLCapabilities;
-import com.jogamp.opengl.GLEventListener;
-import com.jogamp.opengl.GLProfile;
-import com.jogamp.opengl.demos.graph.FontSetDemos;
-import com.jogamp.opengl.demos.util.CommandlineOptions;
-import com.jogamp.opengl.demos.util.MiscUtils;
-import com.jogamp.opengl.fixedfunc.GLMatrixFunc;
-import com.jogamp.opengl.math.FloatUtil;
-import com.jogamp.opengl.math.Quaternion;
-import com.jogamp.opengl.math.Recti;
-import com.jogamp.opengl.math.Vec3f;
-import com.jogamp.opengl.math.geom.AABBox;
-import com.jogamp.opengl.util.Animator;
-import com.jogamp.opengl.util.PMVMatrix;
-
-/**
- * Res independent Shape, Scene attached to GLWindow showing simple linear Shape movement.
- * <p>
- * This variation of {@link UISceneDemo00} shows a text animation assembling one line of text,
- * each glyph coming from from a random 3D point moving to its destination all at once.
- * </p>
- * <p>
- * - Pass '-keep' to main-function to keep running.
- * - Pass '-aspeed' to vary velocity
- * </p>
- */
-public class UISceneDemo03b {
- static final boolean DEBUG = false;
-
- static final String[] originalTexts = {
- " JOGL, Java™ Binding for the OpenGL® API ",
- " GraphUI, Resolution Independent Curves ",
- " JogAmp, Java™ libraries for 3D & Media "
- };
-
- static CommandlineOptions options = new CommandlineOptions(1280, 720, Region.VBAA_RENDERING_BIT);
- static float frame_velocity = 5f / 1e3f; // [m]/[s]
- static float velocity = 30 / 1e3f; // [m]/[s]
- static float rot_step = velocity * 1;
-
- static void setVelocity(final float v) {
- velocity = v; // Math.max(1/1e3f, v);
- rot_step = velocity * 1;
- }
-
- public static void main(final String[] args) throws IOException {
- int autoSpeed = -1;
- setVelocity(80/1000f);
- options.keepRunning = true;
- boolean groupRotate = true;
- boolean groupFrame = true;
-
- if (0 != args.length) {
- final int[] idx = { 0 };
- for (idx[0] = 0; idx[0] < args.length; ++idx[0]) {
- if( options.parse(args, idx) ) {
- continue;
- } else if (args[idx[0]].equals("-v")) {
- ++idx[0];
- setVelocity(MiscUtils.atoi(args[idx[0]], (int) velocity * 1000) / 1000f);
- autoSpeed = 0;
- } else if(args[idx[0]].equals("-aspeed")) {
- autoSpeed = -1;
- setVelocity(80/1000f);
- options.keepRunning = true;
- } else if(args[idx[0]].equals("-no_group_rotate")) {
- groupRotate = false;
- } else if(args[idx[0]].equals("-no_group_frame")) {
- groupFrame = false;
- }
- }
- }
- // renderModes |= Region.COLORCHANNEL_RENDERING_BIT;
- System.err.println(options);
-
- final GLProfile reqGLP = GLProfile.get(options.glProfileName);
- System.err.println("GLProfile: "+reqGLP);
-
- //
- // Resolution independent, no screen size
- //
- final Font font = FontFactory.get(IOUtil.getResource("fonts/freefont/FreeSerif.ttf",FontSetDemos.class.getClassLoader(), FontSetDemos.class).getInputStream(), true);
- // final Font font = FontFactory.get(IOUtil.getResource("jogamp/graph/font/fonts/ubuntu/Ubuntu-R.ttf",FontSetDemos.class.getClassLoader(), FontSetDemos.class).getInputStream(), true);
- System.err.println("Font: " + font.getFullFamilyName());
- final Font fontStatus = FontFactory.get(IOUtil.getResource("fonts/freefont/FreeMono.ttf", FontSetDemos.class.getClassLoader(), FontSetDemos.class).getInputStream(), true);
-
- final Scene scene = new Scene();
- scene.setClearParams(new float[] { 1f, 1f, 1f, 1f }, GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
- scene.setPMVMatrixSetup(new MyPMVMatrixSetup(groupRotate ? Scene.DEFAULT_SCENE_DIST : -0.16f));
- scene.setDebugBorderBox(options.debugBoxThickness);
-
- final Group glyphGroup = new Group();
- scene.addShape(glyphGroup);
-
- scene.setFrustumCullingEnabled(true);
- glyphGroup.setFrustumCullingEnabled(true);
-
- final Animator animator = new Animator(0 /* w/o AWT */);
- animator.setUpdateFPSFrames(1 * 60, null); // System.err);
-
- final GLCapabilities caps = new GLCapabilities(reqGLP);
- caps.setAlphaBits(4);
- if( options.sceneMSAASamples > 0 ) {
- caps.setSampleBuffers(true);
- caps.setNumSamples(options.sceneMSAASamples);
- }
- System.out.println("Requested: " + caps);
-
- final GLWindow window = GLWindow.create(caps);
- window.setSize(options.surface_width, options.surface_height);
- window.setTitle(UISceneDemo03b.class.getSimpleName() + ": " + window.getSurfaceWidth() + " x " + window.getSurfaceHeight());
- window.setVisible(true);
- window.addGLEventListener(scene);
- window.addWindowListener(new WindowAdapter() {
- @Override
- public void windowResized(final WindowEvent e) {
- window.setTitle(UISceneDemo03b.class.getSimpleName() + ": " + window.getSurfaceWidth() + " x " + window.getSurfaceHeight());
- }
-
- @Override
- public void windowDestroyNotify(final WindowEvent e) {
- animator.stop();
- }
- });
- window.addKeyListener(new KeyAdapter() {
- @Override
- public void keyReleased(final KeyEvent e) {
- if (e.getKeySymbol() == KeyEvent.VK_PLUS ||
- e.getKeySymbol() == KeyEvent.VK_ADD)
- {
- if (e.isShiftDown()) {
- setVelocity(velocity + 10 / 1000f);
- } else {
- setVelocity(velocity + 1 / 1000f);
- }
- } else if (e.getKeySymbol() == KeyEvent.VK_MINUS ||
- e.getKeySymbol() == KeyEvent.VK_SUBTRACT)
- {
- if (e.isShiftDown()) {
- setVelocity(velocity - 10 / 1000f);
- } else {
- setVelocity(velocity - 1 / 1000f);
- }
- }
- }
- });
-
- scene.attachInputListenerTo(window);
-
- animator.add(window);
- animator.start();
-
- //
- // After initial display we can use screen resolution post initial
- // Scene.reshape(..)
- // However, in this example we merely use the resolution to
- // - Compute the animation values with DPI
- scene.waitUntilDisplayed();
-
- window.invoke(true, (drawable) -> {
- final GL gl = drawable.getGL();
- gl.glEnable(GL.GL_DEPTH_TEST);
- return true;
- });
-
- final GLProfile hasGLP = window.getChosenGLCapabilities().getGLProfile();
- final AABBox sceneBox = scene.getBounds();
- {
- final GraphShape r = new Rectangle(options.renderModes, sceneBox, sceneBox.getWidth()*0.01f);
- // final GraphShape r = new Rectangle(options.renderModes, sceneBox.getMinX(), sceneBox.getMinY(), sceneBox.getWidth(), sceneBox.getHeight(), sceneBox.getWidth()*0.01f);
- // final GraphShape r = new Rectangle(options.renderModes, sceneBox.getMinX()*0.5f, sceneBox.getMinY()*0.5f, sceneBox.getWidth()*0.5f, sceneBox.getHeight()*0.5f, sceneBox.getWidth()*0.5f*0.01f, sceneBox.getMinZ());
- if( !groupFrame ) {
- r.setColor(0f, 0f, 0f, 0f);
- }
- glyphGroup.addShape( r );
- }
- glyphGroup.scale(0.8f, 0.8f, 1f);
- // glyphGroup.scale(0.5f, 0.5f, 1f);
- glyphGroup.setRotationPivot(0, 0, 0);
- glyphGroup.validate(hasGLP);
- System.err.println("SceneBox " + sceneBox);
- System.err.println("Frustum " + scene.getMatrix().getFrustum());
- System.err.println("GlyphGroup.0: "+glyphGroup);
-
- final Label statusLabel;
- {
- final AABBox fbox = fontStatus.getGlyphBounds("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
- final float statusLabelScale = sceneBox.getWidth() / fbox.getWidth();
- System.err.println("StatusLabelScale: " + statusLabelScale + " = " + sceneBox.getWidth() + " / " + fbox.getWidth() + ", " + fbox);
-
- statusLabel = new Label(options.renderModes, fontStatus, "Nothing there yet");
- statusLabel.setScale(statusLabelScale, statusLabelScale, 1f);
- statusLabel.setColor(0.1f, 0.1f, 0.1f, 1.0f);
- statusLabel.moveTo(sceneBox.getMinX(), sceneBox.getMinY() + statusLabelScale * (fontStatus.getMetrics().getLineGap() - fontStatus.getMetrics().getDescent()), 0f);
- scene.addShape(statusLabel);
- }
-
- {
- final StringBuilder sb = new StringBuilder();
- for(final String s : originalTexts) {
- sb.append(s).append("\n");
- }
- final Label l = new Label(options.renderModes, font, sb.toString()); // originalTexts[0]);
- l.validate(hasGLP);
- final float scale = sceneBox.getWidth() / l.getBounds().getWidth();
- l.setScale(scale, scale, 1f);
- l.setColor(0.1f, 0.1f, 0.1f, 1.0f);
- l.moveTo(sceneBox.getMinX(), 0f, 0f);
- scene.addShape(l);
-
- if( options.wait_to_start ) {
- statusLabel.setText("Press enter to continue");
- MiscUtils.waitForKey("Start");
- }
-
- window.invoke(true, (drawable) -> {
- final GL2ES2 gl = drawable.getGL().getGL2ES2();
- scene.screenshot(gl, scene.nextScreenshotFile(null, UISceneDemo03b.class.getSimpleName(), options.renderModes, drawable.getChosenGLCapabilities(), null));
- scene.removeShape(gl, l);
- return true;
- });
- }
-
- //
- // Setup the moving glyphs
- //
-
- final List<GlyphShape> glyphShapesAnim = new ArrayList<GlyphShape>();
- final List<GlyphShape> glyphShapesAll = new ArrayList<GlyphShape>();
-
- final float pixPerMM, dpiV;
- {
- final float[] tmp = window.getPixelsPerMM(new float[2]);
- pixPerMM = tmp[0]; // [px]/[mm]
- final float[] sDPI = MonitorDevice.perMMToPerInch( tmp );
- dpiV = sDPI[1];
- }
- boolean z_only = true;
- int txt_idx = 0;
-
- final AABBox glyphBox = glyphGroup.getBounds();
- final float g_w = glyphBox.getWidth();
- final float g_h = glyphBox.getHeight();
-
- // glyphGroup.scale(0.8f, 0.8f, 1f);
- // glyphGroup.validate(hasGLP);
- System.err.println("GlyphBox " + glyphBox);
- System.err.println("GlyphGroup " + glyphGroup);
-
- glyphGroup.addMouseListener( new Shape.MouseGestureAdapter() {
- @Override
- public void mouseWheelMoved(final MouseEvent e) {
- final Shape.EventInfo shapeEvent = (Shape.EventInfo) e.getAttachment();
- final Shape shape = shapeEvent.shape;
- final Quaternion rot = shape.getRotation();
- final Vec3f euler = rot.toEuler(new Vec3f());
- final Vec3f eulerOld = euler.copy();
- if( !e.isShiftDown() ) {
- final float eps = FloatUtil.adegToRad(5f);
- float diff = e.getRotation()[1] < 0f ? FloatUtil.adegToRad(-1f) : FloatUtil.adegToRad(1f);
- final float sign = diff >= 0f ? 1f : -1f;
- final float v;
- if( e.isAltDown() ) {
- shape.scale(1f+sign/10f, 1f+sign/10f, 1f);
- System.err.println("Scaled: "+shape);
- return;
- } else if( e.isControlDown() ) {
- v = euler.x();
- } else {
- v = euler.y();
- }
- final float av = Math.abs(v);
- if( 1f*FloatUtil.HALF_PI - eps <= av && av <= 1f*FloatUtil.HALF_PI + eps ||
- 3f*FloatUtil.HALF_PI - eps <= av && av <= 3f*FloatUtil.HALF_PI + eps) {
- diff = 2f * eps * sign;
- }
- if( e.isAltDown() ) {
- euler.add(0, 0, diff);
- } else if( e.isControlDown() ) {
- euler.add(diff, 0, 0);
- } else {
- euler.add(0, diff, 0);
- }
- System.err.println("Rot: diff "+diff+" (eps "+eps+"): "+eulerOld+" -> "+euler);
- rot.setFromEuler(euler);
- }
- }
- });
- glyphGroup.onToggle((final Shape shape) -> {
- System.err.println("Toggle: "+shape);
- });
- glyphGroup.setInteractive(true);
- glyphGroup.setDraggable(false);
- glyphGroup.setResizable(false);
- glyphGroup.setToggleable(true);
- glyphGroup.setToggle( groupRotate );
- System.err.println("GlyphGroup.1: "+glyphGroup);
-
- window.addGLEventListener(new GLEventListener() {
- float dir = 1f;
- @Override
- public void init(final GLAutoDrawable drawable) {}
- @Override
- public void dispose(final GLAutoDrawable drawable) {}
- @Override
- public void display(final GLAutoDrawable drawable) {
- if( glyphGroup.isToggleOn() ) {
- final Quaternion rot = glyphGroup.getRotation();
- final Vec3f euler = rot.toEuler(new Vec3f());
- if( FloatUtil.HALF_PI <= euler.y() ) {
- dir = -1f;
- } else if( euler.y() <= -FloatUtil.HALF_PI ) {
- dir = 1f;
- }
- glyphGroup.getRotation().rotateByAngleY( frame_velocity * dir );
- }
- }
- @Override
- public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {}
- });
-
- do {
- final float fontScale;
- {
- final AABBox fbox = font.getGlyphBounds(originalTexts[txt_idx]);
- // fontScale = s_w / fbox.getWidth();
- // System.err.println("FontScale: " + fontScale + " = " + s_w + " / " + fbox.getWidth());
- fontScale = g_w / fbox.getWidth();
- System.err.println("FontScale: " + fontScale + " = " + g_w + " / " + fbox.getWidth());
- }
- z_only = !z_only;
- window.invoke(true, (drawable) -> {
- glyphGroup.removeShapes(drawable.getGL().getGL2ES2(), scene.getRenderer(), glyphShapesAll);
- return true;
- });
- glyphShapesAll.clear();
- glyphShapesAnim.clear();
-
- final float[] movingGlyphPixPerShapeUnit;
- {
- final Random random = new Random();
-
- final GlyphShape testGlyph = new GlyphShape(options.renderModes, font, 'X', 0, 0);
- testGlyph.setScale(fontScale, fontScale, 1f);
- testGlyph.validate(hasGLP);
- final PMVMatrix pmv = new PMVMatrix();
- final int[] movingGlyphSizePx = testGlyph.getSurfaceSize(scene, pmv, new int[2]); // [px]
- movingGlyphPixPerShapeUnit = testGlyph.getPixelPerShapeUnit(movingGlyphSizePx, new float[2]); // [px]/[shapeUnit]
-
- final AABBox box = GlyphShape.processString(glyphShapesAll, options.renderModes, font, originalTexts[txt_idx]);
- System.err.println("Shapes: "+box);
- for(final GlyphShape gs : glyphShapesAll) {
- gs.setScale(fontScale, fontScale, 1f);
- gs.setColor(0.1f, 0.1f, 0.1f, 1);
- final Vec3f target = gs.getOrigPos(fontScale).add(glyphBox.getMinX(), 0f, 0f);
-
- final float start_pos_x = z_only ? target.x() :
- glyphBox.getMinX() + random.nextFloat() * glyphBox.getWidth();
- final float start_pos_y = z_only ? target.y() :
- glyphBox.getMinY() + random.nextFloat() * glyphBox.getHeight();
- final float start_pos_z = 0f + random.nextFloat() * glyphBox.getHeight() * 1f;
- gs.moveTo(start_pos_x, start_pos_y, start_pos_z);
- }
- // just add destText to scene to be cleaned up, invisible
- testGlyph.setEnabled(false);
- glyphGroup.addShape(testGlyph);
- }
- glyphGroup.addShapes(glyphShapesAll);
- glyphShapesAnim.addAll(glyphShapesAll);
-
- final float pos_eps = FloatUtil.EPSILON * 5000; // ~= 0.0005960
- final float rot_eps = FloatUtil.adegToRad(0.5f); // 1 adeg ~= 0.01745 rad
-
- final long t0_us = Clock.currentNanos() / 1000; // [us]
- final long[] t2_us = { t0_us };
- while (!glyphShapesAnim.isEmpty()) {
- window.invoke(true, (drawable) -> {
- final long t3_us = Clock.currentNanos() / 1000;
- final float dt_s = (t3_us - t2_us[0]) / 1e6f;
- t2_us[0] = t3_us;
-
- final float velocity_px = velocity * 1e3f * pixPerMM; // [px]/[s]
- final float velocity_obj = velocity_px / movingGlyphPixPerShapeUnit[0]; // [shapeUnit]/[s]
- final float dxy = velocity_obj * dt_s; // [shapeUnit]
-
- for (int idx = glyphShapesAnim.size() - 1; 0 <= idx; --idx) {
- final GlyphShape glyph = glyphShapesAnim.get(idx);
- final Vec3f pos = new Vec3f(glyph.getPosition());
- final Vec3f target = glyph.getOrigPos(fontScale).add(glyphBox.getMinX(), 0f, 0f);
- final Vec3f p_t = target.minus(pos);
- final float p_t_diff = p_t.length();
- final Quaternion q = glyph.getRotation();
- final Vec3f euler = q.toEuler(new Vec3f());
- final float radY = euler.y();
- final float radYdiff = Math.min(Math.abs(radY), FloatUtil.TWO_PI - Math.abs(radY));
- final boolean pos_ok = p_t_diff <= pos_eps;
- final boolean pos_near = p_t_diff <= glyph.getBounds().getSize() * fontScale * 2f;
- final boolean rot_ok = pos_near && ( radYdiff <= rot_eps || radYdiff <= rot_step * 2f );
- if ( pos_ok && rot_ok ) {
- // arrived
- if( DEBUG ) {
- if( 0 == idx ) {
- System.err.println("F: rot: "+radY+" ("+FloatUtil.radToADeg(radY)+"), diff "+radYdiff+" ("+FloatUtil.radToADeg(radYdiff)+"), step "+rot_step+" ("+FloatUtil.radToADeg(rot_step)+")");
- }
- }
- glyph.moveTo(target.x(), target.y(), target.z());
- q.setIdentity();
- glyphShapesAnim.remove(idx);
- continue;
- }
- if( !pos_ok ) {
- if( DEBUG ) {
- if( 0 == idx ) {
- System.err.println("p_t_diff: "+p_t_diff+", dxy "+dxy);
- }
- }
- if( p_t_diff <= dxy || p_t_diff <= pos_eps ) {
- glyph.moveTo(target.x(), target.y(), target.z());
- } else {
- p_t.normalize();
- pos.add( p_t.scale( dxy ) );
- glyph.moveTo(pos.x(), pos.y(), pos.z());
- }
- if( !rot_ok ) {
- if( pos_near ) {
- q.rotateByAngleY( rot_step * 2f );
- } else {
- q.rotateByAngleY( rot_step );
- }
- }
- } else {
- if( DEBUG ) {
- if( 0 == idx ) {
- System.err.println("P: rot: "+radY+" ("+FloatUtil.radToADeg(radY)+"), diff "+radYdiff+" ("+FloatUtil.radToADeg(radYdiff)+"), step "+rot_step+" ("+FloatUtil.radToADeg(rot_step)+")");
- }
- }
- if( radYdiff <= rot_step * 3f || radYdiff <= rot_eps ) {
- q.setIdentity();
- } else {
- q.rotateByAngleY( rot_step * 3f );
- }
- }
- }
-
- final String text = String.format("%s, v %.1f mm/s, r %.3f",
- scene.getStatusText(drawable, options.renderModes, 0, dpiV), velocity * 1e3f, rot_step);
- statusLabel.setText(text);
- return true;
- });
- }
- final float has_dur_s = ((Clock.currentNanos() / 1000) - t0_us) / 1e6f; // [us]
- System.err.printf("Text travel-duration %.3f s, %d chars%n", has_dur_s, originalTexts[txt_idx].length());
- if( scene.getScreenshotCount() < 1 + originalTexts.length ) {
- scene.screenshot(true, scene.nextScreenshotFile(null, UISceneDemo03b.class.getSimpleName(), options.renderModes, window.getChosenGLCapabilities(), null));
- }
- try { Thread.sleep(2000); } catch (final InterruptedException e1) { }
- if( autoSpeed > 0 ) {
- if( velocity < 60/1000f ) {
- setVelocity(velocity + 9/1000f);
- } else {
- setVelocity(velocity - 9/1000f);
- autoSpeed = -1;
- }
- } else if( autoSpeed < 0 ) {
- if( velocity > 11/1000f ) {
- setVelocity(velocity - 9/1000f);
- } else {
- setVelocity(velocity + 9/1000f);
- autoSpeed = 1;
- }
- }
- txt_idx = ( txt_idx + 1 ) % originalTexts.length;
- } while (options.keepRunning && window.isNativeValid());
- if (!options.stayOpen) {
- window.destroy();
- }
- }
-
- /**
- * Our PMVMatrixSetup:
- * - gluPerspective like Scene's default
- * - no normal scale to 1, keep distance to near plane for rotation effects.
- */
- public static class MyPMVMatrixSetup implements PMVMatrixSetup {
- private final float scene_dist;
- public MyPMVMatrixSetup(final float scene_dist) {
- this.scene_dist = scene_dist;
- }
- @Override
- public void set(final PMVMatrix pmv, final Recti viewport) {
- final float ratio = (float) viewport.width() / (float) viewport.height();
- pmv.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
- pmv.glLoadIdentity();
- pmv.gluPerspective(Scene.DEFAULT_ANGLE, ratio, Scene.DEFAULT_ZNEAR, Scene.DEFAULT_ZFAR);
- pmv.glTranslatef(0f, 0f, scene_dist);
-
- pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
- pmv.glLoadIdentity();
- }
-
- @Override
- public void setPlaneBox(final AABBox planeBox, final PMVMatrix pmv, final Recti viewport) {
- Scene.getDefaultPMVMatrixSetup().setPlaneBox(planeBox, pmv, viewport);
- }
- };
-}
diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo20.java b/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo20.java
index 64904bdb4..799933ba0 100644
--- a/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo20.java
+++ b/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo20.java
@@ -38,7 +38,6 @@ import java.util.Locale;
import com.jogamp.common.av.AudioSink;
import com.jogamp.common.net.Uri;
import com.jogamp.common.util.IOUtil;
-import com.jogamp.common.util.InterruptSource;
import com.jogamp.common.util.VersionUtil;
import com.jogamp.graph.curve.Region;
import com.jogamp.graph.curve.opengl.RenderState;
@@ -65,7 +64,6 @@ import com.jogamp.newt.MonitorDevice;
import com.jogamp.newt.NewtFactory;
import com.jogamp.newt.Screen;
import com.jogamp.newt.Window;
-import com.jogamp.newt.event.KeyEvent;
import com.jogamp.newt.event.MouseEvent;
import com.jogamp.newt.event.WindowAdapter;
import com.jogamp.newt.event.WindowEvent;
@@ -179,6 +177,7 @@ public class UISceneDemo20 implements GLEventListener {
final Animator animator = new Animator(0 /* w/o AWT */);
animator.setUpdateFPSFrames(5*60, null);
animator.add(window);
+ animator.setExclusiveContext(options.exclusiveContext);
window.addWindowListener(new WindowAdapter() {
@Override
@@ -600,20 +599,13 @@ public class UISceneDemo20 implements GLEventListener {
button = new Button(renderModes, fontButtons, "Quit", buttonLWidth, buttonLHeight);
button.setName(BUTTON_QUIT);
- button.setColor(0.7f, 0.0f, 0.0f, 1.0f);
+ button.setColor(0.7f, 0.3f, 0.3f, 1.0f);
((Button)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( () -> {
- if( null != cDrawable ) {
- final GLAnimatorControl actrl = cDrawable.getAnimator();
- if( null != actrl ) {
- actrl.stop();
- }
- cDrawable.destroy();
- } } ).start();
+ MiscUtils.destroyWindow(cDrawable);
} } );
button.addMouseListener(dragZoomRotateListener);
buttonsLeft.addShape(button);
@@ -689,7 +681,7 @@ public class UISceneDemo20 implements GLEventListener {
button.addMouseListener(new Shape.MouseGestureAdapter() {
@Override
public void mouseClicked(final MouseEvent e) {
- scene.screenshot(true, scene.nextScreenshotFile(null, UISceneDemo20.class.getSimpleName(), options.renderModes, gl.getContext().getGLDrawable().getChosenGLCapabilities(), null));
+ scene.screenshot(false, scene.nextScreenshotFile(null, UISceneDemo20.class.getSimpleName(), options.renderModes, gl.getContext().getGLDrawable().getChosenGLCapabilities(), null));
} } );
button.addMouseListener(dragZoomRotateListener);
buttonsLeft.addShape(button);
diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemoU01a.java b/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemoU01a.java
index 2269a79aa..c5ba2e918 100644
--- a/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemoU01a.java
+++ b/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemoU01a.java
@@ -209,6 +209,7 @@ public class UISceneDemoU01a {
@Override
public void init(final GLAutoDrawable drawable) {
final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ System.err.println(JoglVersion.getGLInfo(gl, null));
if( !textOnly ) {
shape = new CrossHair(options.renderModes, normWidgetSize, normWidgetSize, normWidgetSize/100f); // normalized: 1 is 100% surface size (width and/or height)
diff --git a/src/demos/com/jogamp/opengl/demos/util/CommandlineOptions.java b/src/demos/com/jogamp/opengl/demos/util/CommandlineOptions.java
index 81fbbac65..d3b4ae1af 100644
--- a/src/demos/com/jogamp/opengl/demos/util/CommandlineOptions.java
+++ b/src/demos/com/jogamp/opengl/demos/util/CommandlineOptions.java
@@ -36,9 +36,10 @@ public class CommandlineOptions {
public boolean wait_to_start = false;
public boolean keepRunning = false;
public boolean stayOpen = false;
- public int renderModes;
+ public int renderModes = Region.NORM_RENDERING_BIT;
public int sceneMSAASamples = 0;
public float debugBoxThickness = 0f;
+ public boolean exclusiveContext = false;
static {
GLProfile.initSingleton(); // ensure JOGL is completely initialized
@@ -76,12 +77,20 @@ public class CommandlineOptions {
glProfileName = GLProfile.GLES2;
} else if(args[idx[0]].equals("-es3")) {
glProfileName = GLProfile.GLES3;
+ } else if(args[idx[0]].equals("-gl2")) {
+ glProfileName = GLProfile.GL2;
+ } else if(args[idx[0]].equals("-gl3bc")) {
+ glProfileName = GLProfile.GL3bc;
} else if(args[idx[0]].equals("-gl3")) {
glProfileName = GLProfile.GL3;
} else if(args[idx[0]].equals("-gl4")) {
glProfileName = GLProfile.GL4;
+ } else if(args[idx[0]].equals("-gl4bc")) {
+ glProfileName = GLProfile.GL4bc;
} else if(args[idx[0]].equals("-gldef")) {
glProfileName = null;
+ } else if(args[idx[0]].equals("-exclusiveContext")) {
+ exclusiveContext = true;
} else if(args[idx[0]].equals("-wait")) {
wait_to_start = true;
} else if (args[idx[0]].equals("-keep")) {
@@ -91,7 +100,7 @@ public class CommandlineOptions {
stayOpen = true;
} else if(args[idx[0]].equals("-gnone")) {
sceneMSAASamples = 0;
- renderModes = 0;
+ renderModes = Region.NORM_RENDERING_BIT;
} else if(args[idx[0]].equals("-color")) {
renderModes |= Region.COLORCHANNEL_RENDERING_BIT;
} else if(args[idx[0]].equals("-no-color")) {
@@ -119,7 +128,7 @@ public class CommandlineOptions {
@Override
public String toString() {
return "Options{surface[width "+surface_width+" x "+surface_height+"], glp "+glProfileName+
- ", wait "+wait_to_start+", keep "+keepRunning+", stay "+stayOpen+
+ ", exclusiveContext "+exclusiveContext+", wait "+wait_to_start+", keep "+keepRunning+", stay "+stayOpen+
", renderModes "+Region.getRenderModeString(renderModes)+
", smsaa "+sceneMSAASamples+", dbgbox "+debugBoxThickness+"}";
}
diff --git a/src/demos/com/jogamp/opengl/demos/util/MiscUtils.java b/src/demos/com/jogamp/opengl/demos/util/MiscUtils.java
index f1c367e95..9284dfc84 100644
--- a/src/demos/com/jogamp/opengl/demos/util/MiscUtils.java
+++ b/src/demos/com/jogamp/opengl/demos/util/MiscUtils.java
@@ -1,5 +1,5 @@
/**
- * Copyright 2010 JogAmp Community. All rights reserved.
+ * 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:
@@ -25,8 +25,6 @@
* 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;
@@ -39,6 +37,8 @@ import java.nio.FloatBuffer;
import java.util.Iterator;
import java.util.List;
+import com.jogamp.opengl.GLAnimatorControl;
+import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLContext;
import com.jogamp.common.os.Platform;
@@ -253,6 +253,19 @@ public class MiscUtils {
System.err.println("\t Total created "+i+" + destroyed "+j+" = "+(i+j));
System.err.println();
}
+
+ public static void destroyWindow(final GLAutoDrawable glad) {
+ if( glad.isRealized() ) {
+ glad.setExclusiveContextThread(null);
+ final GLAnimatorControl actrl = glad.getAnimator();
+ if( null != actrl ) {
+ actrl.stop();
+ }
+ System.err.println("Destroying window from thread "+Thread.currentThread());
+ // Thread.dumpStack();
+ new InterruptSource.Thread( () -> { glad.destroy(); } ).start();
+ }
+ }
}