aboutsummaryrefslogtreecommitdiffstats
path: root/src/graphui/classes
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2023-03-19 08:04:48 +0100
committerSven Gothel <[email protected]>2023-03-19 08:04:48 +0100
commita81fff28e9380ebce877d974d402ef613b5ea850 (patch)
tree88a940532f11ebfb070b4201752161b7227fbb28 /src/graphui/classes
parentc04c8947c7cd0788ea8a4e615887d236eb2fbbb8 (diff)
Add Scene.PMVMatrixSetup for programmable PMVMatrix setup in Scene replacing fixed projection params; Simplify API requirements ..
Scene: - Add Scene.PMVMatrixSetup and use it throughout Scene/Shape for reshape(), setupMatrix() and Shape's win<->obj coordinate mappings. - Default Scene.PMVMatrixSetup is no more moving origin to bottom-left, kept at screen-center. - Add waitUntilDisplayer(), allowing to wait until 1st display is completed, ensuring certain states are well set (init, reshape and 1st display on Shapes, plane-box, ..) Shape: - Rename setPosition() -> moveTo() - Add getBounds(GLProfile) to retrieve AABBox before rendering, - Enhance validateImpl(..) to allow this mode @ initial validation (only)
Diffstat (limited to 'src/graphui/classes')
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/gl/Scene.java457
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/gl/Shape.java124
2 files changed, 301 insertions, 280 deletions
diff --git a/src/graphui/classes/com/jogamp/graph/ui/gl/Scene.java b/src/graphui/classes/com/jogamp/graph/ui/gl/Scene.java
index 9c9334182..7e98df635 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/gl/Scene.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/gl/Scene.java
@@ -27,6 +27,7 @@
*/
package com.jogamp.graph.ui.gl;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
@@ -37,8 +38,10 @@ import com.jogamp.opengl.GL2ES2;
import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLCapabilitiesImmutable;
import com.jogamp.opengl.GLEventListener;
+import com.jogamp.opengl.GLException;
import com.jogamp.opengl.GLRunnable;
import com.jogamp.opengl.fixedfunc.GLMatrixFunc;
+import com.jogamp.common.nio.Buffers;
import com.jogamp.graph.curve.Region;
import com.jogamp.graph.curve.opengl.RegionRenderer;
import com.jogamp.graph.curve.opengl.RenderState;
@@ -75,6 +78,9 @@ import com.jogamp.opengl.util.PMVMatrix;
* - {@link GLEventListener#display(GLAutoDrawable)}
* - {@link GLEventListener#dispose(GLAutoDrawable)}
* </p>
+ * <p>
+ * {@link #setPMVMatrixSetup(PMVMatrixSetup)} maybe used to provide a custom {@link PMVMatrix} setup.
+ * </p>
* @see Shape
*/
public final class Scene implements GLEventListener {
@@ -87,12 +93,11 @@ public final class Scene implements GLEventListener {
/** Default projection z-far value is 7000. */
public static final float DEFAULT_ZFAR = 7000.0f;
+ @SuppressWarnings("unused")
private static final boolean DEBUG = false;
private final ArrayList<Shape> shapes = new ArrayList<Shape>();
- private final float sceneDist, zNear, zFar;
- private final float projAngle = DEFAULT_ANGLE;
private float[] clearColor = null;
private int clearMask;
@@ -100,10 +105,8 @@ public final class Scene implements GLEventListener {
private final int[] sampleCount = new int[1];
- /** Describing the bounding box in shape's object model-coordinates of the near-plane parallel at its scene-distance, pre {@link #translate(PMVMatrix)} to origin. */
- private final AABBox planeBoxCtr = new AABBox(0f, 0f, 0f, 0f, 0f, 0f);
/** Describing the bounding box in shape's object model-coordinates of the near-plane parallel at its scene-distance, post {@link #translate(PMVMatrix)} */
- private final AABBox planBoxBL = new AABBox(0f, 0f, 0f, 0f, 0f, 0f);
+ private final AABBox planeBox = new AABBox(0f, 0f, 0f, 0f, 0f, 0f);
private volatile Shape activeShape = null;
@@ -119,60 +122,24 @@ public final class Scene implements GLEventListener {
/**
* Create a new scene with an internally created RegionRenderer
- * and using default values {@link #DEFAULT_SCENE_DIST}, {@link #DEFAULT_ZNEAR} and {@link #DEFAULT_ZFAR}.
+ * and using default values {@link #DEFAULT_SCENE_DIST}, {@link #DEFAULT_ANGLE}, {@link #DEFAULT_ZNEAR} and {@link #DEFAULT_ZFAR}.
*/
public Scene() {
- this(createRenderer(), DEFAULT_SCENE_DIST, DEFAULT_ZNEAR, DEFAULT_ZFAR);
- }
-
- /**
- * Create a new scene with given projection values and an internally created RegionRenderer.
- * @param sceneDist scene distance on z-axis to projection, consider using {@link #DEFAULT_SCENE_DIST}.
- * @param zNear projection z-near value, consider using {@link #DEFAULT_ZNEAR}
- * @param zFar projection z-far value, consider using {@link #DEFAULT_ZFAR}
- */
- public Scene(final float sceneDist, final float zNear, final float zFar) {
- this(createRenderer(), sceneDist, zNear, zFar);
+ this(createRenderer());
}
/**
* Create a new scene taking ownership of the given RegionRenderer
- * and using default values {@link #DEFAULT_SCENE_DIST}, {@link #DEFAULT_ZNEAR} and {@link #DEFAULT_ZFAR}.
+ * and using default values {@link #DEFAULT_SCENE_DIST}, {@link #DEFAULT_ANGLE}, {@link #DEFAULT_ZNEAR} and {@link #DEFAULT_ZFAR}.
*/
public Scene(final RegionRenderer renderer) {
- this(renderer, DEFAULT_SCENE_DIST, DEFAULT_ZNEAR, DEFAULT_ZFAR);
- }
-
- /**
- * Create a new scene with given projection values and taking ownership of the given RegionRenderer.
- * @param renderer RegionRenderer to use and own
- * @param sceneDist scene distance on z-axis to projection, consider using {@link #DEFAULT_SCENE_DIST}.
- * @param zNear projection z-near value, consider using {@link #DEFAULT_ZNEAR}
- * @param zFar projection z-far value, consider using {@link #DEFAULT_ZFAR}
- */
- public Scene(final RegionRenderer renderer, final float sceneDist, final float zNear, final float zFar) {
if( null == renderer ) {
throw new IllegalArgumentException("Null RegionRenderer");
}
this.renderer = renderer;
- this.sceneDist = sceneDist;
- this.zFar = zFar;
- this.zNear = zNear;
this.sampleCount[0] = 4;
}
- /** Return z-axis distance of scene to projection, see {@link #DEFAULT_SCENE_DIST}. */
- public float getProjSceneDist() { return sceneDist; }
-
- /** Return projection angle in degrees, see {@link #DEFAULT_ANGLE}. */
- public float getProjAngle() { return projAngle; }
-
- /** Return projection z-near value, see {@link #DEFAULT_ZNEAR}. */
- public float getProjZNear() { return zNear; }
-
- /** Return projection z-far value, see {@link #DEFAULT_ZFAR}. */
- public float getProjZFar() { return zFar; }
-
/** Returns the associated RegionRenderer */
public RegionRenderer getRenderer() { return renderer; }
@@ -352,8 +319,24 @@ public final class Scene implements GLEventListener {
} else {
renderer.enable(gl, false);
}
+ synchronized ( syncDisplayedOnce ) {
+ displayedOnce = true;
+ syncDisplayedOnce.notifyAll();
+ }
+ }
+
+ private volatile boolean displayedOnce = false;
+ private final Object syncDisplayedOnce = new Object();
- renderer.enable(gl, false);
+ /** Blocks until first {@link #display(GLAutoDrawable)} has completed after construction or {@link #dispose(GLAutoDrawable). */
+ public void waitUntilDisplayed() {
+ synchronized( syncDisplayedOnce ) {
+ while( !displayedOnce ) {
+ try {
+ syncDisplayedOnce.wait();
+ } catch (final InterruptedException e) { }
+ }
+ }
}
/**
@@ -367,18 +350,21 @@ public final class Scene implements GLEventListener {
* </p>
* @param glWinX window X coordinate, bottom-left origin
* @param glWinY window Y coordinate, bottom-left origin
+ * @param pmv a new {@link PMVMatrix} which will {@link Scene.PMVMatrixSetup#set(PMVMatrix, int, int, int, int) be setup},
+ * {@link Shape#setTransform(PMVMatrix) shape-transformed} and can be reused by the caller and runnable.
* @param objPos storage for found object position in model-space of found {@link Shape}
* @param shape storage for found {@link Shape} or null
* @param runnable the action to perform if {@link Shape} was found
*/
- public void pickShape(final int glWinX, final int glWinY, final float[] objPos, final Shape[] shape, final Runnable runnable) {
- shape[0] = pickShapeImpl(glWinX, glWinY, objPos);
+ public Shape pickShape(final int glWinX, final int glWinY, final PMVMatrix pmv, final float[] objPos, final Shape[] shape, final Runnable runnable) {
+ shape[0] = pickShapeImpl(glWinX, glWinY, pmv, objPos);
if( null != shape[0] ) {
runnable.run();
}
+ return shape[0];
}
@SuppressWarnings({ "unchecked", "rawtypes" })
- private Shape pickShapeImpl(final int glWinX, final int glWinY, final float[] objPos) {
+ private Shape pickShapeImpl(final int glWinX, final int glWinY, final PMVMatrix pmv, final float[] objPos) {
final float winZ0 = 0f;
final float winZ1 = 0.3f;
/**
@@ -386,7 +372,6 @@ public final class Scene implements GLEventListener {
gl.glReadPixels( x, y, 1, 1, GL2ES2.GL_DEPTH_COMPONENT, GL.GL_FLOAT, winZRB);
winZ1 = winZRB.get(0); // dir
*/
- final PMVMatrix pmv = new PMVMatrix();
setupMatrix(pmv);
final Ray ray = new Ray();
@@ -401,7 +386,6 @@ public final class Scene implements GLEventListener {
pmv.glPushMatrix();
uiShape.setTransform(pmv);
final boolean ok = pmv.gluUnProjectRay(glWinX, glWinY, winZ0, winZ1, getViewport(), 0, ray);
- pmv.glPopMatrix();
if( ok ) {
final AABBox sbox = uiShape.getBounds();
if( sbox.intersectsRay(ray) ) {
@@ -413,6 +397,7 @@ public final class Scene implements GLEventListener {
return uiShape;
}
}
+ pmv.glPopMatrix(); // we leave the stack open if picked above, allowing the modelview shape transform to be reused
}
}
return null;
@@ -501,11 +486,13 @@ public final class Scene implements GLEventListener {
* @param shape
* @param glWinX in GL window coordinates, origin bottom-left
* @param glWinY in GL window coordinates, origin bottom-left
+ * @param pmv a new {@link PMVMatrix} which will {@link Scene.PMVMatrixSetup#set(PMVMatrix, int, int, int, int) be setup},
+ * {@link Shape#setTransform(PMVMatrix) shape-transformed} and can be reused by the caller and runnable.
* @param objPos resulting object position
* @param runnable action
*/
- public void winToObjCoord(final Shape shape, final int glWinX, final int glWinY, final float[] objPos, final Runnable runnable) {
- if( null != shape && shape.winToObjCoord(this, glWinX, glWinY, objPos) ) {
+ public void winToObjCoord(final Shape shape, final int glWinX, final int glWinY, final PMVMatrix pmv, final float[] objPos, final Runnable runnable) {
+ if( null != shape && shape.winToObjCoord(pmvMatrixSetup, renderer.getViewport(), glWinX, glWinY, pmv, objPos) ) {
runnable.run();
}
}
@@ -523,6 +510,10 @@ public final class Scene implements GLEventListener {
@Override
public void dispose(final GLAutoDrawable drawable) {
System.err.println("SceneUIController: dispose");
+ synchronized ( syncDisplayedOnce ) {
+ displayedOnce = false;
+ syncDisplayedOnce.notifyAll();
+ }
if( drawable instanceof GLWindow ) {
final GLWindow glw = (GLWindow) drawable;
detachInputListenerFrom(glw);
@@ -537,119 +528,102 @@ public final class Scene implements GLEventListener {
}
/**
- *
- * @param pmv
- * @param view
- * @param zNear
- * @param zFar
- * @param orthoX
- * @param orthoY
- * @param orthoDist
- * @param winZ
- * @param objPos float[3] storage for object coord result
+ * Interface providing {@link #set(PMVMatrix, int, int, int, int) a method} to
+ * setup {@link PMVMatrix}'s {@link GLMatrixFunc#GL_PROJECTION} and {@link GLMatrixFunc#GL_MODELVIEW}.
+ * <p>
+ * At the end of operations, the {@link GLMatrixFunc#GL_MODELVIEW} matrix has to be selected.
+ * </p>
+ * <p>
+ * Implementation is being called by {@link Scene#setupMatrix(PMVMatrix, int, int, int, int)}
+ * and hence {@link Scene#reshape(GLAutoDrawable, int, int, int, int)}.
+ * </p>
+ * <p>
+ * Custom implementations can be set via {@link Scene#setPMVMatrixSetup(PMVMatrixSetup)}.
+ * </p>
+ * <p>
+ * The default implementation is described below
+ * </p>
+ * <p>
+ * {@link GLMatrixFunc#GL_PROJECTION} is setup using perspective {@link Scene#DEFAULT_ANGLE} with {@link Scene#DEFAULT_ZNEAR} and {@link Scene#DEFAULT_ZFAR}.
+ * </p>
+ * <p>
+ * Further {@link GLMatrixFunc#GL_MODELVIEW} is translated to given {@link Scene#DEFAULT_SCENE_DIST}.
+ * </p>
*/
- public static void winToObjCoord(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] = FloatUtil.getOrthoWinZ(orthoDist, zNear, zFar);
- pmv.gluUnProject(orthoX, orthoY, winZ[0], view, 0, objPos, 0);
+ public static interface PMVMatrixSetup {
+ /**
+ * Setup {@link PMVMatrix}'s {@link GLMatrixFunc#GL_PROJECTION} and {@link GLMatrixFunc#GL_MODELVIEW}.
+ * <p>
+ * See {@link PMVMatrixSetup} for details.
+ * </p>
+ * <p>
+ * At the end of operations, the {@link GLMatrixFunc#GL_MODELVIEW} matrix is selected.
+ * </p>
+ * @param pmv the {@link PMVMatrix} to setup
+ * @param x lower left corner of the viewport rectangle
+ * @param y lower left corner of the viewport rectangle
+ * @param width width of the viewport rectangle
+ * @param height height of the viewport rectangle
+ */
+ void set(PMVMatrix pmv, final int x, final int y, final int width, final int height);
+
+ /**
+ * Optional method to set the {@link Scene#getBounds()} {@link AABBox}, maybe a {@code nop} if not desired.
+ * <p>
+ * Will be called by {@link Scene#reshape(GLAutoDrawable, int, int, int, int)} after {@link #set(PMVMatrix, int, int, int, int)}.
+ * </p>
+ * @param x TODO
+ * @param y TODO
+ */
+ void setPlaneBox(final AABBox planeBox, final PMVMatrix pmv, int x, int y, final int width, final int height);
}
- /**
- * Map given window surface-size to object coordinates relative to this scene and {@link #getProjSceneDist() and projection settings.
- * @param width surface width in pixel
- * @param height surface height in pixel
- * @param objSceneSize float[2] storage for object surface size result
- */
- public void surfaceToObjSize(final int width, final int height, final float[/*2*/] objSceneSize) {
- final int[] viewport = { 0, 0, width, height };
+ /** Return the default or {@link #setPMVMatrixSetup(PMVMatrixSetup)} {@link PMVMatrixSetup}. */
+ public final PMVMatrixSetup getPMVMatrixSetup() { return pmvMatrixSetup; }
- final PMVMatrix pmv = new PMVMatrix();
- setupMatrix(pmv, width, height);
- {
- final float orthoDist = -sceneDist;
- final float[] obj00Coord = new float[3];
- final float[] obj11Coord = new float[3];
- final float[] winZ = new float[1];
-
- winToObjCoord(pmv, viewport, zNear, zFar, 0f, 0f, orthoDist, winZ, obj00Coord);
- winToObjCoord(pmv, viewport, zNear, zFar, width, height, orthoDist, winZ, obj11Coord);
- objSceneSize[0] = obj11Coord[0] - obj00Coord[0];
- objSceneSize[1] = obj11Coord[1] - obj00Coord[1];
- }
- }
+ /** Set a custom {@link PMVMatrixSetup}. */
+ public final void setPMVMatrixSetup(final PMVMatrixSetup setup) { pmvMatrixSetup = setup; }
/**
- * Reshape scene {@link #setupMatrix(PMVMatrix, int, int)}.
- * <p>
- * {@link GLMatrixFunc#GL_PROJECTION} is setup using perspective {@link #getProjAngle()} with {@link #getProjZNear()} and {@link #getProjZFar()}.
- * </p>
+ * Reshape scene using {@link #setupMatrix(PMVMatrix, int, int, int, int)} using {@link PMVMatrixSetup}.
* <p>
- * {@link GLMatrixFunc#GL_MODELVIEW} is translated to given {@link #getProjSceneDist()}
- * and and origin 0/0 becomes the bottom-left corner.
+ * {@inheritDoc}
* </p>
- * @see #setupMatrix(PMVMatrix, int, int)
+ * @see PMVMatrixSetup
+ * @see #setPMVMatrixSetup(PMVMatrixSetup)
+ * @see #setupMatrix(PMVMatrix, int, int, int, int)
* @see #getBounds()
* @see #getBoundsCenter()
*/
- @SuppressWarnings("unused")
@Override
public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
renderer.reshapeNotify(x, y, width, height);
- final PMVMatrix pmv = renderer.getMatrix();
- setupMatrix0(pmv, width, height);
- pmv.glTranslatef(0f, 0f, sceneDist);
- {
- final float orthoDist = -sceneDist;
- final float[] obj00Coord = new float[3];
- final float[] obj11Coord = new float[3];
- final float[] winZ = new float[1];
-
- winToObjCoord(pmv, getViewport(), zNear, zFar, 0f, 0f, orthoDist, winZ, obj00Coord);
- winToObjCoord(pmv, getViewport(), zNear, zFar, width, height, orthoDist, winZ, obj11Coord);
-
- pmv.glTranslatef(obj00Coord[0], obj00Coord[1], 0f); // bottom-left corder origin 0/0
-
- planeBoxCtr.setSize( obj00Coord[0], // lx
- obj00Coord[1], // ly
- obj00Coord[2], // lz
- obj11Coord[0], // hx
- obj11Coord[1], // hy
- obj11Coord[2] );// hz
-
- planBoxBL.setSize( 0, // lx
- 0, // ly
- 0, // lz
- planeBoxCtr.getWidth(), // hx
- planeBoxCtr.getHeight(),// hy
- planeBoxCtr.getDepth());// hz
-
- if( true || DEBUG ) {
- System.err.printf("Reshape: zNear %f, zFar %f, sceneDist %f%n", zNear, zFar, sceneDist);
- System.err.printf("Reshape: Frustum: %s%n", pmv.glGetFrustum());
- 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]);
- 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]);
- System.err.printf("Reshape: scenePlaneBox: %s%n", planeBoxCtr);
- }
- }
+ setupMatrix(renderer.getMatrix(), x, y, width, height);
+ pmvMatrixSetup.setPlaneBox(planeBox, renderer.getMatrix(), x, y, width, height);
+ }
- if( false ) {
- final float[] sceneScale = new float[3];
- final float[] scenePlaneOrigin = new float[3];
- scenePlaneOrigin[0] = planeBoxCtr.getMinX() * sceneDist;
- scenePlaneOrigin[1] = planeBoxCtr.getMinY() * sceneDist;
- scenePlaneOrigin[2] = planeBoxCtr.getMinZ() * sceneDist;
- sceneScale[0] = ( planeBoxCtr.getWidth() * sceneDist ) / width;
- sceneScale[1] = ( planeBoxCtr.getHeight() * sceneDist ) / height;
- sceneScale[2] = 1f;
- System.err.printf("Scene Origin [%f, %f, %f]%n", scenePlaneOrigin[0], scenePlaneOrigin[1], scenePlaneOrigin[2]);
- System.err.printf("Scene Scale %f * [%f x %f] / [%d x %d] = [%f, %f, %f]%n",
- sceneDist, planeBoxCtr.getWidth(), planeBoxCtr.getHeight(),
- width, height,
- sceneScale[0], sceneScale[1], sceneScale[2]);
- }
+ /**
+ * Setup {@link PMVMatrix} {@link GLMatrixFunc#GL_PROJECTION} and {@link GLMatrixFunc#GL_MODELVIEW}
+ * by calling {@link #getPMVMatrixSetup()}'s {@link PMVMatrixSetup#set(PMVMatrix, int, int, int, int)}.
+ * @param pmv the {@link PMVMatrix} to setup
+ * @param x lower left corner of the viewport rectangle
+ * @param y lower left corner of the viewport rectangle
+ * @param width width of the viewport rectangle
+ * @param height height of the viewport rectangle
+ */
+ public void setupMatrix(final PMVMatrix pmv, final int x, final int y, final int width, final int height) {
+ pmvMatrixSetup.set(pmv, x, y, width, height);
+ }
+
+ /**
+ * Setup {@link PMVMatrix} {@link GLMatrixFunc#GL_PROJECTION} and {@link GLMatrixFunc#GL_MODELVIEW}
+ * using implicit {@link #getViewport()} surface dimension by calling {@link #getPMVMatrixSetup()}'s {@link PMVMatrixSetup#set(PMVMatrix, int, int, int, int)}.
+ * @param pmv the {@link PMVMatrix} to setup
+ */
+ public void setupMatrix(final PMVMatrix pmv) {
+ final int[] viewport = renderer.getViewport();
+ setupMatrix(pmv, viewport[0], viewport[1], viewport[2], viewport[3]);
}
/** Copies the current int[4] viewport in given target and returns it for chaining. It is set after initial {@link #reshape(GLAutoDrawable, int, int, int, int)}. */
@@ -666,94 +640,79 @@ public final class Scene implements GLEventListener {
/** Borrow the current {@link PMVMatrix}. */
public PMVMatrix getMatrix() { return renderer.getMatrix(); }
- /** Translate current matrix to {@link #getBounds()}'s origin (minx/miny) and {@link #getProjSceneDist()}, a convenience method. */
- private void translate(final PMVMatrix pmv) {
- pmv.glTranslatef(planeBoxCtr.getMinX(), planeBoxCtr.getMinY(), sceneDist);
- }
-
/**
- * Setup {@link PMVMatrix} {@link GLMatrixFunc#GL_PROJECTION} and {@link GLMatrixFunc#GL_MODELVIEW}
- * using explicit surface width and height before {@link #reshape(GLAutoDrawable, int, int, int, int)} happened, a convenience method.
+ * Describing the scene's object model-dimensions of the plane at scene-distance covering the visible viewport rectangle.
* <p>
- * {@link GLMatrixFunc#GL_PROJECTION} is setup using perspective {@link #getProjAngle()} with {@link #getProjZNear()} and {@link #getProjZFar()}.
+ * The value is evaluated at {@link #reshape(GLAutoDrawable, int, int, int, int)} via {@link }
* </p>
* <p>
- * {@link GLMatrixFunc#GL_MODELVIEW} is translated to given {@link #getProjSceneDist()}
- * and and origin 0/0 becomes the bottom-left corner.
+ * {@link AABBox#getWidth()} and {@link AABBox#getHeight()} define scene's dimension covered by surface size.
* </p>
* <p>
- * At the end of operations, the {@link GLMatrixFunc#GL_MODELVIEW} matrix is selected.
+ * {@link AABBox} is setup via {@link #getPMVMatrixSetup()}'s {@link PMVMatrixSetup#setPlaneBox(AABBox, PMVMatrix, int, int, int, int)}.
* </p>
- * @param pmv the {@link PMVMatrix} to setup
- * @param surface_width explicit surface width
- * @param surface_height explicit surface height
*/
- public void setupMatrix(final PMVMatrix pmv, final int surface_width, final int surface_height) {
- setupMatrix0(pmv, surface_width, surface_height);
- translate(pmv);
- }
- private void setupMatrix0(final PMVMatrix pmv, final int surface_width, final int surface_height) {
- final float ratio = (float)surface_width/(float)surface_height;
- pmv.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
- pmv.glLoadIdentity();
- pmv.gluPerspective(projAngle, ratio, zNear, zFar);
-
- pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
- pmv.glLoadIdentity();
- }
+ public AABBox getBounds() { return planeBox; }
/**
- * Setup {@link PMVMatrix} {@link GLMatrixFunc#GL_PROJECTION} and {@link GLMatrixFunc#GL_MODELVIEW}
- * using implicit {@link #getViewport()} surface dimension after {@link #reshape(GLAutoDrawable, int, int, int, int)} happened, a convenience method.
- * <p>
- * {@link GLMatrixFunc#GL_PROJECTION} is setup using perspective {@link #getProjAngle()} with {@link #getProjZNear()} and {@link #getProjZFar()}.
- * </p>
- * <p>
- * {@link GLMatrixFunc#GL_MODELVIEW} is translated to given {@link #getProjSceneDist()}
- * and and origin 0/0 becomes the bottom-left corner.
- * </p>
- * <p>
- * At the end of operations, the {@link GLMatrixFunc#GL_MODELVIEW} matrix is selected.
- * </p>
- * @param pmv the {@link PMVMatrix} to setup
- * @param surface_width explicit surface width
- * @param surface_height explicit surface height
+ *
+ * @param pmv
+ * @param viewport
+ * @param zNear
+ * @param zFar
+ * @param winX
+ * @param winY
+ * @param objOrthoZ
+ * @param objPos float[3] storage for object coord result
+ * @param winZ
*/
- public void setupMatrix(final PMVMatrix pmv) {
- setupMatrix(pmv, getWidth(), getHeight());
+ public static void winToPlaneCoord(final PMVMatrix pmv, final int[] viewport,
+ final float zNear, final float zFar,
+ final float winX, final float winY, final float objOrthoZ,
+ final float[] objPos) {
+ final float winZ = FloatUtil.getOrthoWinZ(objOrthoZ, zNear, zFar);
+ pmv.gluUnProject(winX, winY, winZ, viewport, 0, objPos, 0);
}
/**
- * Describing the scene's object model-dimensions of the near-plane parallel at its scene-distance {@link #getProjSceneDist()}
- * having the origin 0/0 on the bottom-left corner.
- * <p>
- * The value is evaluated at {@link #reshape(GLAutoDrawable, int, int, int, int)}.
- * </p>
- * <p>
- * {@link AABBox#getWidth()} and {@link AABBox#getHeight()} define scene's dimension covered by surface size.
- * </p>
+ * Map given window surface-size to object coordinates relative to this scene using
+ * the give projection parameters.
+ * @param viewport
+ * @param zNear
+ * @param zFar
+ * @param objOrthoDist
+ * @param objSceneSize float[2] storage for object surface size result
*/
- public AABBox getBounds() { return planBoxBL; }
+ public void surfaceToPlaneSize(final int[] viewport, final float zNear, final float zFar, final float objOrthoDist, final float[/*2*/] objSceneSize) {
+ final PMVMatrix pmv = new PMVMatrix();
+ setupMatrix(pmv, viewport[0], viewport[1], viewport[2], viewport[3]);
+ {
+ final float[] obj00Coord = new float[3];
+ final float[] obj11Coord = new float[3];
+
+ winToPlaneCoord(pmv, viewport, DEFAULT_ZNEAR, DEFAULT_ZFAR, viewport[0], viewport[1], objOrthoDist, obj00Coord);
+ winToPlaneCoord(pmv, viewport, DEFAULT_ZNEAR, DEFAULT_ZFAR, viewport[2], viewport[3], objOrthoDist, obj11Coord);
+ objSceneSize[0] = obj11Coord[0] - obj00Coord[0];
+ objSceneSize[1] = obj11Coord[1] - obj00Coord[1];
+ }
+ }
/**
- * Describing the scene's object model-dimensions of the near-plane parallel at its scene-distance {@link #getProjSceneDist()}
- * having the origin 0/0 in the center of the screen.
- * <p>
- * The value is evaluated at {@link #reshape(GLAutoDrawable, int, int, int, int)} before translating to the bottom-left origin 0/0,
- * i.e. its minimum values are negative of half dimension.
- * </p>
- * <p>
- * {@link AABBox#getWidth()} and {@link AABBox#getHeight()} define scene's dimension covered by surface size.
- * </p>
+ * Map given window surface-size to object coordinates relative to this scene using
+ * the default {@link PMVMatrixSetup}.
+ * @param viewport
+ * @param objSceneSize float[2] storage for object surface size result
*/
- public AABBox getBoundsCenter() { return planeBoxCtr; }
+ public void surfaceToPlaneSize(final int[] viewport, final float[/*2*/] objSceneSize) {
+ surfaceToPlaneSize(viewport, DEFAULT_ZNEAR, DEFAULT_ZFAR, -DEFAULT_SCENE_DIST, objSceneSize);
+ }
public final Shape getActiveShape() {
return activeShape;
}
- public void release() {
- setActiveShape(null);
+ public void releaseActiveShape() {
+ activeShape = null;
}
private void setActiveShape(final Shape shape) {
activeShape = shape;
@@ -770,10 +729,11 @@ public final class Scene implements GLEventListener {
// flip to GL window coordinates
final int glWinX = e.getX();
final int glWinY = getHeight() - e.getY() - 1;
+ final PMVMatrix pmv = new PMVMatrix();
final float[] objPos = new float[3];
final Shape shape = activeShape;
- winToObjCoord(shape, glWinX, glWinY, objPos, () -> {
- shape.dispatchGestureEvent(Scene.this, gh, glWinX, glWinY, objPos);
+ winToObjCoord(shape, glWinX, glWinY, pmv, objPos, () -> {
+ shape.dispatchGestureEvent(gh, glWinX, glWinY, pmv, renderer.getViewport(), objPos);
});
}
}
@@ -788,7 +748,7 @@ public final class Scene implements GLEventListener {
*/
final void dispatchMouseEvent(final MouseEvent e, final int glWinX, final int glWinY) {
if( null == activeShape ) {
- dispatchMouseEventPickShape(e, glWinX, glWinY, true);
+ dispatchMouseEventPickShape(e, glWinX, glWinY);
} else {
dispatchMouseEventForShape(activeShape, e, glWinX, glWinY);
}
@@ -798,17 +758,18 @@ public final class Scene implements GLEventListener {
* @param e original Newt {@link MouseEvent}
* @param glWinX in GL window coordinates, origin bottom-left
* @param glWinY in GL window coordinates, origin bottom-left
- * @param setActive
*/
- final void dispatchMouseEventPickShape(final MouseEvent e, final int glWinX, final int glWinY, final boolean setActive) {
+ final void dispatchMouseEventPickShape(final MouseEvent e, final int glWinX, final int glWinY) {
+ final PMVMatrix pmv = new PMVMatrix();
final float[] objPos = new float[3];
final Shape[] shape = { null };
- pickShape(glWinX, glWinY, objPos, shape, () -> {
- if( setActive ) {
- setActiveShape(shape[0]);
- }
+ if( null == pickShape(glWinX, glWinY, pmv, objPos, shape, () -> {
+ setActiveShape(shape[0]);
shape[0].dispatchMouseEvent(e, glWinX, glWinY, objPos);
- } );
+ } ) )
+ {
+ releaseActiveShape();
+ }
}
/**
* Dispatch event to shape
@@ -818,8 +779,9 @@ public final class Scene implements GLEventListener {
* @param glWinY in GL window coordinates, origin bottom-left
*/
final void dispatchMouseEventForShape(final Shape shape, final MouseEvent e, final int glWinX, final int glWinY) {
+ final PMVMatrix pmv = new PMVMatrix();
final float[] objPos = new float[3];
- winToObjCoord(shape, glWinX, glWinY, objPos, () -> { shape.dispatchMouseEvent(e, glWinX, glWinY, objPos); });
+ winToObjCoord(shape, glWinX, glWinY, pmv, objPos, () -> { shape.dispatchMouseEvent(e, glWinX, glWinY, objPos); });
}
private class SBCMouseListener implements MouseListener {
@@ -850,7 +812,7 @@ public final class Scene implements GLEventListener {
dispatchMouseEvent(e, glWinX, glWinY);
if( 1 == e.getPointerCount() ) {
// Release active shape: last pointer has been lifted!
- release();
+ releaseActiveShape();
clear();
}
}
@@ -861,9 +823,9 @@ public final class Scene implements GLEventListener {
final int glWinX = e.getX();
final int glWinY = getHeight() - e.getY() - 1;
// activeId should have been released by mouseRelease() already!
- dispatchMouseEventPickShape(e, glWinX, glWinY, false);
+ dispatchMouseEventPickShape(e, glWinX, glWinY);
// Release active shape: last pointer has been lifted!
- release();
+ releaseActiveShape();
clear();
}
@@ -887,7 +849,7 @@ public final class Scene implements GLEventListener {
// flip to GL window coordinates
final int glWinX = lx;
final int glWinY = getHeight() - ly - 1;
- dispatchMouseEventPickShape(e, glWinX, glWinY, true);
+ dispatchMouseEvent(e, glWinX, glWinY);
}
@Override
@@ -897,12 +859,16 @@ public final class Scene implements GLEventListener {
ly = e.getY();
lId = e.getPointerId(0);
}
+ final int glWinX = lx;
+ final int glWinY = getHeight() - ly - 1;
+ // dispatchMouseEvent(e, glWinX, glWinY);
+ dispatchMouseEventPickShape(e, glWinX, glWinY);
}
@Override
public void mouseEntered(final MouseEvent e) { }
@Override
public void mouseExited(final MouseEvent e) {
- release();
+ releaseActiveShape();
clear();
}
}
@@ -948,4 +914,35 @@ public final class Scene implements GLEventListener {
return String.format("%03.1f/%03.1f fps, %.1f ms/f", lfps, tfps, td);
}
+ private final PMVMatrixSetup defaultPMVMatrixSetup = new PMVMatrixSetup() {
+ @Override
+ public void set(final PMVMatrix pmv, final int x, final int y, final int width, final int height) {
+ final float ratio = (float)width/(float)height;
+ pmv.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ pmv.glLoadIdentity();
+ pmv.gluPerspective(DEFAULT_ANGLE, ratio, DEFAULT_ZNEAR, DEFAULT_ZFAR);
+ pmv.glTranslatef(0f, 0f, DEFAULT_SCENE_DIST);
+
+ pmv.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmv.glLoadIdentity();
+ }
+
+ @Override
+ public void setPlaneBox(final AABBox planeBox, final PMVMatrix pmv, final int x, final int y, final int width, final int height) {
+ final float orthoDist = -DEFAULT_SCENE_DIST;
+ final float[] obj00Coord = new float[3];
+ final float[] obj11Coord = new float[3];
+
+ winToPlaneCoord(pmv, getViewport(), DEFAULT_ZNEAR, DEFAULT_ZFAR, x, y, orthoDist, obj00Coord);
+ winToPlaneCoord(pmv, getViewport(), DEFAULT_ZNEAR, DEFAULT_ZFAR, width, height, orthoDist, obj11Coord);
+
+ planeBox.setSize( obj00Coord[0], // lx
+ obj00Coord[1], // ly
+ obj00Coord[2], // lz
+ obj11Coord[0], // hx
+ obj11Coord[1], // hy
+ obj11Coord[2] );// hz }
+ }
+ };
+ private PMVMatrixSetup pmvMatrixSetup = defaultPMVMatrixSetup;
}
diff --git a/src/graphui/classes/com/jogamp/graph/ui/gl/Shape.java b/src/graphui/classes/com/jogamp/graph/ui/gl/Shape.java
index 140ac8cc8..56ba928d7 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/gl/Shape.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/gl/Shape.java
@@ -37,7 +37,6 @@ import com.jogamp.graph.curve.OutlineShape;
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.geom.Vertex;
import com.jogamp.graph.geom.Vertex.Factory;
import com.jogamp.graph.geom.plane.AffineTransform;
@@ -47,7 +46,6 @@ import com.jogamp.newt.event.MouseAdapter;
import com.jogamp.newt.event.NEWTEvent;
import com.jogamp.newt.event.PinchToZoomGesture;
import com.jogamp.newt.event.MouseEvent;
-import com.jogamp.newt.event.MouseEvent.PointerClass;
import com.jogamp.newt.event.MouseListener;
import com.jogamp.opengl.math.FloatUtil;
import com.jogamp.opengl.math.Quaternion;
@@ -77,7 +75,7 @@ public abstract class Shape {
protected static final int DIRTY_SHAPE = 1 << 0 ;
protected static final int DIRTY_STATE = 1 << 1 ;
- private final Factory<? extends Vertex> vertexFactory;
+ protected final Factory<? extends Vertex> vertexFactory;
private final int renderModes;
protected final AABBox box;
@@ -176,13 +174,13 @@ public abstract class Shape {
markShapeDirty();
}
- public void setPosition(final float tx, final float ty, final float tz) {
+ public final void moveTo(final float tx, final float ty, final float tz) {
position[0] = tx;
position[1] = ty;
position[2] = tz;
// System.err.println("UIShape.setTranslate: "+tx+"/"+ty+"/"+tz+": "+toString());
}
- public void move(final float tx, final float ty, final float tz) {
+ public final void move(final float tx, final float ty, final float tz) {
position[0] += tx;
position[1] += ty;
position[2] += tz;
@@ -249,10 +247,27 @@ public abstract class Shape {
*/
public final AABBox getBounds() { return box; }
+ /**
+ * Returns the unscaled bounding {@link AABBox} for this shape.
+ *
+ * This variant differs from {@link #getBounds()} as it
+ * returns a valid {@link AABBox} even before {@link #draw(GL2ES2, RegionRenderer, int[]) draw(..)}
+ * and having an OpenGL instance available.
+ *
+ * @see #getBounds()
+ */
+ public final AABBox getBounds(final GLProfile glp) {
+ if( null == region ) {
+ // initial creation of region, producing a valid box
+ validateImpl(glp, null);
+ }
+ return box;
+ }
+
public final int getRenderModes() { return renderModes; }
- public GLRegion getRegion(final GL2ES2 gl, final RegionRenderer renderer) {
- validate(gl, renderer);
+ public GLRegion getRegion(final GL2ES2 gl) {
+ validate(gl);
return region;
}
@@ -270,7 +285,7 @@ public abstract class Shape {
* @param renderer the used {@link RegionRenderer}, also source of {@link RegionRenderer#getMatrix()} and {@link RegionRenderer#getViewport()}.
* @param sampleCount sample count if used by Graph renderModes
*/
- public void drawShape(final GL2ES2 gl, final RegionRenderer renderer, final int[] sampleCount) {
+ public void draw(final GL2ES2 gl, final RegionRenderer renderer, final int[] sampleCount) {
final float r, g, b, a;
final boolean isPressed = isPressed(), isToggleOn = isToggleOn();
final boolean modBaseColor = !Region.hasColorChannel( renderModes ) && !Region.hasColorTexture( renderModes );
@@ -324,7 +339,7 @@ public abstract class Shape {
}
}
renderer.getRenderState().setColorStatic(r, g, b, a);
- getRegion(gl, renderer).draw(gl, renderer, sampleCount);
+ getRegion(gl).draw(gl, renderer, sampleCount);
}
protected GLRegion createGLRegion(final GLProfile glp) {
@@ -335,24 +350,21 @@ public abstract class Shape {
* Validates the shape's underlying {@link GLRegion}.
*
* @param gl
- * @param renderer
*/
- public final void validate(final GL2ES2 gl, final RegionRenderer renderer) {
+ public final void validate(final GL2ES2 gl) {
+ validateImpl(gl.getGLProfile(), gl);
+ }
+ private final void validateImpl(final GLProfile glp, final GL2ES2 gl) {
if( isShapeDirty() || null == region ) {
box.reset();
if( null == region ) {
- region = createGLRegion(gl.getGLProfile());
- } else {
- region.clear(gl);
- }
- addShapeToRegion(gl, renderer);
- if( DRAW_DEBUG_BOX ) {
+ region = createGLRegion(glp);
+ } else if( null != gl ) {
region.clear(gl);
- final OutlineShape shape = new OutlineShape(renderer.getRenderState().getVertexFactory());
- shape.setSharpness(shapesSharpness);
- shape.setIsQuadraticNurbs();
- region.addOutlineShape(shape, null, rgbaColor);
+ } else {
+ throw new IllegalArgumentException("GL is null on non-initial validation");
}
+ addShapeToRegion();
region.setQuality(regionQuality);
dirty &= ~(DIRTY_SHAPE|DIRTY_STATE);
} else if( isStateDirty() ) {
@@ -402,7 +414,7 @@ public abstract class Shape {
* @param viewport the int[4] viewport
* @param surfaceSize int[2] target surface size
* @return true for successful gluProject(..) operation, otherwise false
- * @see #getSurfaceSize(Scene, int[])
+ * @see #getSurfaceSize(com.jogamp.graph.ui.gl.Scene.PMVMatrixSetup, int[], PMVMatrix, int[])
*/
public boolean getSurfaceSize(final PMVMatrix pmv, final int[/*4*/] viewport, final int[/*2*/] surfaceSize) {
boolean res = false;
@@ -426,22 +438,26 @@ public abstract class Shape {
}
/**
- * Retrieve window surface size of this shape using a local {@link PMVMatrix}.
+ * Retrieve surface (view) size of this shape.
* <p>
- * The {@link Scene} has be {@link Scene#reshape(com.jogamp.opengl.GLAutoDrawable, int, int, int, int) reshape(..)}ed once.
+ * The given {@link PMVMatrix} will be {@link Scene.PMVMatrixSetup#set(PMVMatrix, int, int, int, int) setup} properly for this shape
+ * including this shape's {@link #setTransform(PMVMatrix)}.
* </p>
- * @param scene {@link Scene} source of viewport and local {@link PMVMatrix} {@link Scene#setupMatrix(PMVMatrix) setupMatrix(..)}.
+ * @param pmvMatrixSetup {@link Scene.PMVMatrixSetup} to {@link Scene.PMVMatrixSetup#set(PMVMatrix, int, int, int, int) setup} given {@link PMVMatrix} {@code pmv}.
+ * @param viewport used viewport for {@link PMVMatrix#gluProject(float, float, float, int[], int, float[], int)}
+ * @param pmv a new {@link PMVMatrix} which will {@link Scene.PMVMatrixSetup#set(PMVMatrix, int, int, int, int) be setup},
+ * {@link #setTransform(PMVMatrix) shape-transformed} and can be reused by the caller.
* @param surfaceSize int[2] target surface size
* @return true for successful gluProject(..) operation, otherwise false
* @see #getSurfaceSize(PMVMatrix, int[], int[])
*/
- public boolean getSurfaceSize(final Scene scene, final int[/*2*/] surfaceSize) {
- final PMVMatrix pmv = new PMVMatrix();
- scene.setupMatrix(pmv);
+ public boolean getSurfaceSize(final Scene.PMVMatrixSetup pmvMatrixSetup, final int[/*4*/] viewport, final PMVMatrix pmv, final int[/*2*/] surfaceSize) {
+ pmvMatrixSetup.set(pmv, viewport[0], viewport[1], viewport[2], viewport[3]);
setTransform(pmv);
- return getSurfaceSize(pmv, scene.getViewport(), surfaceSize);
+ return getSurfaceSize(pmv, viewport, surfaceSize);
}
+
/**
* Map given object coordinate relative to this shape to window coordinates.
* <p>
@@ -454,7 +470,7 @@ public abstract class Shape {
* @param objPos float[3] object position relative to this shape's center
* @param glWinPos int[2] target window position of objPos relative to this shape
* @return true for successful gluProject(..) operation, otherwise false
- * @see #objToWinCoord(Scene, float[], int[])
+ * @see #objToWinCoord(com.jogamp.graph.ui.gl.Scene.PMVMatrixSetup, int[], float[], PMVMatrix, int[])
*/
public boolean objToWinCoord(final PMVMatrix pmv, final int[/*4*/] viewport, final float[/*3*/] objPos, final int[/*2*/] glWinPos) {
boolean res = false;
@@ -474,19 +490,22 @@ public abstract class Shape {
/**
* Map given object coordinate relative to this shape to window coordinates.
* <p>
- * The {@link Scene} has be {@link Scene#reshape(com.jogamp.opengl.GLAutoDrawable, int, int, int, int) reshape(..)}ed once.
+ * The given {@link PMVMatrix} will be {@link Scene.PMVMatrixSetup#set(PMVMatrix, int, int, int, int) setup} properly for this shape
+ * including this shape's {@link #setTransform(PMVMatrix)}.
* </p>
- * @param scene {@link Scene} source of viewport and local {@link PMVMatrix} {@link Scene#setupMatrix(PMVMatrix) setupMatrix(..)}.
+ * @param pmvMatrixSetup {@link Scene.PMVMatrixSetup} to {@link Scene.PMVMatrixSetup#set(PMVMatrix, int, int, int, int) setup} given {@link PMVMatrix} {@code pmv}.
+ * @param viewport used viewport for {@link PMVMatrix#gluProject(float, float, float, int[], int, float[], int)}
* @param objPos float[3] object position relative to this shape's center
+ * @param pmv a new {@link PMVMatrix} which will {@link Scene.PMVMatrixSetup#set(PMVMatrix, int, int, int, int) be setup},
+ * {@link #setTransform(PMVMatrix) shape-transformed} and can be reused by the caller.
* @param glWinPos int[2] target window position of objPos relative to this shape
* @return true for successful gluProject(..) operation, otherwise false
* @see #objToWinCoord(PMVMatrix, int[], float[], int[])
*/
- public boolean objToWinCoord(final Scene scene, final float[/*3*/] objPos, final int[/*2*/] glWinPos) {
- final PMVMatrix pmv = new PMVMatrix();
- scene.setupMatrix(pmv);
+ public boolean objToWinCoord(final Scene.PMVMatrixSetup pmvMatrixSetup, final int[/*4*/] viewport, final float[/*3*/] objPos, final PMVMatrix pmv, final int[/*2*/] glWinPos) {
+ pmvMatrixSetup.set(pmv, viewport[0], viewport[1], viewport[2], viewport[3]);
setTransform(pmv);
- return this.objToWinCoord(pmv, scene.getViewport(), objPos, glWinPos);
+ return this.objToWinCoord(pmv, viewport, objPos, glWinPos);
}
/**
@@ -502,7 +521,7 @@ public abstract class Shape {
* @param glWinY in GL window coordinates, origin bottom-left
* @param objPos float[3] target object position of glWinX/glWinY relative to this shape
* @return true for successful gluProject(..) and gluUnProject(..) operations, otherwise false
- * @see #winToObjCoord(Scene, int, int, float[])
+ * @see #winToObjCoord(com.jogamp.graph.ui.gl.Scene.PMVMatrixSetup, int[], int, int, PMVMatrix, float[])
*/
public boolean winToObjCoord(final PMVMatrix pmv, final int[/*4*/] viewport, final int glWinX, final int glWinY, final float[/*3*/] objPos) {
boolean res = false;
@@ -520,23 +539,26 @@ public abstract class Shape {
}
/**
- * Map given gl-window-coordinates to object coordinates relative to this shape and its z-coordinate
- * using a local {@link PMVMatrix}.
+ * Map given gl-window-coordinates to object coordinates relative to this shape and its z-coordinate.
* <p>
- * The {@link Scene} has be {@link Scene#reshape(com.jogamp.opengl.GLAutoDrawable, int, int, int, int) reshape(..)}ed once.
+ * The given {@link PMVMatrix} will be {@link Scene.PMVMatrixSetup#set(PMVMatrix, int, int, int, int) setup} properly for this shape
+ * including this shape's {@link #setTransform(PMVMatrix)}.
* </p>
+ * @param pmvMatrixSetup {@link Scene.PMVMatrixSetup} to {@link Scene.PMVMatrixSetup#set(PMVMatrix, int, int, int, int) setup} given {@link PMVMatrix} {@code pmv}.
+ * @param viewport used viewport for {@link PMVMatrix#gluUnProject(float, float, float, int[], int, float[], int)}
* @param scene {@link Scene} source of viewport and local {@link PMVMatrix} {@link Scene#setupMatrix(PMVMatrix) setupMatrix(..)}.
* @param glWinX in GL window coordinates, origin bottom-left
* @param glWinY in GL window coordinates, origin bottom-left
+ * @param pmv a new {@link PMVMatrix} which will {@link Scene.PMVMatrixSetup#set(PMVMatrix, int, int, int, int) be setup},
+ * {@link #setTransform(PMVMatrix) shape-transformed} and can be reused by the caller.
* @param objPos float[3] target object position of glWinX/glWinY relative to this shape
- * @return @return true for successful gluProject(..) and gluUnProject(..) operations, otherwise false
+ * @return true for successful gluProject(..) and gluUnProject(..) operations, otherwise false
* @see #winToObjCoord(PMVMatrix, int[], int, int, float[])
*/
- public boolean winToObjCoord(final Scene scene, final int glWinX, final int glWinY, final float[/*3*/] objPos) {
- final PMVMatrix pmv = new PMVMatrix();
- scene.setupMatrix(pmv);
+ public boolean winToObjCoord(final Scene.PMVMatrixSetup pmvMatrixSetup, final int[/*4*/] viewport, final int glWinX, final int glWinY, final PMVMatrix pmv, final float[/*3*/] objPos) {
+ pmvMatrixSetup.set(pmv, viewport[0], viewport[1], viewport[2], viewport[3]);
setTransform(pmv);
- return this.winToObjCoord(pmv, scene.getViewport(), glWinX, glWinY, objPos);
+ return this.winToObjCoord(pmv, viewport, glWinX, glWinY, objPos);
}
public float[] getColor() {
@@ -912,18 +934,20 @@ public abstract class Shape {
}
/**
- * @param renderer TODO
* @param e original Newt {@link GestureEvent}
* @param glWinX x-position in OpenGL model space
* @param glWinY y-position in OpenGL model space
+ * @param pmv well formed PMVMatrix for this shape
+ * @param viewport the viewport
+ * @param objPos object position of mouse event relative to this shape
*/
- /* pp */ final void dispatchGestureEvent(final Scene scene, final GestureEvent e, final int glWinX, final int glWinY, final float[] objPos) {
+ /* pp */ final void dispatchGestureEvent(final GestureEvent e, final int glWinX, final int glWinY, final PMVMatrix pmv, final int[] viewport, final float[] objPos) {
if( resizable && e instanceof PinchToZoomGesture.ZoomEvent ) {
final PinchToZoomGesture.ZoomEvent ze = (PinchToZoomGesture.ZoomEvent) e;
final float pixels = ze.getDelta() * ze.getScale(); //
final float[] objPos2 = { 0f, 0f, 0f };
final int winX2 = glWinX + Math.round(pixels);
- final boolean ok = winToObjCoord(scene, winX2, glWinY, objPos2);
+ final boolean ok = winToObjCoord(pmv, viewport, winX2, glWinY, objPos2);
final float dx = objPos2[0];
final float dy = objPos2[1];
final float sx = scale[0] + ( dx/box.getWidth() ); // bottom-right
@@ -933,7 +957,7 @@ public abstract class Shape {
inResize, ok, glWinX, glWinY, objPos[0], objPos[1], objPos[2], position[0], position[1], position[2],
dx, dy, sx, sy);
}
- if( ok && resize_sxy_min <= sx && sx <= resize_sxy_max && resize_sxy_min <= sy && sy <= resize_sxy_max ) {
+ if( ok && resize_sxy_min <= sx && resize_sxy_min <= sy ) { // avoid scale flip
if( DEBUG ) {
System.err.printf("PinchZoom: pixels %f, obj %4d/%4d, %.3f/%.3f/%.3f %.3f/%.3f/%.3f + %.3f/%.3f -> %.3f/%.3f%n",
pixels, glWinX, glWinY, objPos[0], objPos[1], objPos[2], position[0], position[1], position[2],
@@ -958,7 +982,7 @@ public abstract class Shape {
protected abstract void clearImpl(GL2ES2 gl, RegionRenderer renderer);
protected abstract void destroyImpl(GL2ES2 gl, RegionRenderer renderer);
- protected abstract void addShapeToRegion(GL2ES2 gl, RegionRenderer renderer);
+ protected abstract void addShapeToRegion();
//
//