JOGL v2.6.0-rc-20250721
JOGL, High-Performance Graphics Binding for Java™ (public API).
Scene.java
Go to the documentation of this file.
1/**
2 * Copyright 2010-2024 JogAmp Community. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification, are
5 * permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * The views and conclusions contained in the software and documentation are those of the
25 * authors and should not be interpreted as representing official policies, either expressed
26 * or implied, of JogAmp Community.
27 */
28package com.jogamp.graph.ui;
29
30import java.io.File;
31import java.nio.ByteBuffer;
32import java.util.ArrayList;
33import java.util.Arrays;
34import java.util.Collection;
35import java.util.Comparator;
36import java.util.List;
37import java.util.Locale;
38import java.util.concurrent.CopyOnWriteArrayList;
39import java.util.concurrent.atomic.AtomicReference;
40
41import com.jogamp.opengl.FPSCounter;
42import com.jogamp.opengl.GL;
43import com.jogamp.opengl.GL2ES2;
44import com.jogamp.opengl.GLAutoDrawable;
45import com.jogamp.opengl.GLCapabilitiesImmutable;
46import com.jogamp.opengl.GLEventListener;
47import com.jogamp.opengl.GLException;
48import com.jogamp.opengl.GLProfile;
49import com.jogamp.opengl.GLRunnable;
50import com.jogamp.opengl.fixedfunc.GLMatrixFunc;
51import com.jogamp.common.nio.Buffers;
52import com.jogamp.common.os.Platform;
53import com.jogamp.graph.curve.Region;
54import com.jogamp.graph.curve.opengl.GLRegion;
55import com.jogamp.graph.curve.opengl.RegionRenderer;
56import com.jogamp.graph.curve.opengl.RenderState;
57import com.jogamp.math.FloatUtil;
58import com.jogamp.math.Matrix4f;
59import com.jogamp.math.Ray;
60import com.jogamp.math.Recti;
61import com.jogamp.math.Vec2f;
62import com.jogamp.math.Vec3f;
63import com.jogamp.math.geom.AABBox;
64import com.jogamp.math.util.PMVMatrix4f;
65import com.jogamp.newt.event.GestureHandler;
66import com.jogamp.newt.event.InputEvent;
67import com.jogamp.newt.event.KeyEvent;
68import com.jogamp.newt.event.KeyListener;
69import com.jogamp.newt.event.MouseEvent;
70import com.jogamp.newt.event.MouseListener;
71import com.jogamp.newt.event.PinchToZoomGesture;
72import com.jogamp.newt.event.GestureHandler.GestureEvent;
73import com.jogamp.newt.opengl.GLWindow;
74import com.jogamp.opengl.util.GLPixelStorageModes;
75import com.jogamp.opengl.util.GLReadBufferUtil;
76import com.jogamp.opengl.util.texture.TextureSequence;
77
78import jogamp.graph.ui.TreeTool;
79
80/**
81 * GraphUI Scene
82 * <p>
83 * GraphUI is GPU based and resolution independent.
84 * </p>
85 * <p>
86 * GraphUI is intended to become an immediate- and retained-mode API.
87 * </p>
88 * <p>
89 * To utilize a Scene instance directly as a {@link GLEventListener},
90 * user needs to {@link #setClearParams(float[], int)}.
91 *
92 * Otherwise user may just call provided {@link GLEventListener} from within their own workflow
93 * - {@link GLEventListener#init(GLAutoDrawable)}
94 * - {@link GLEventListener#reshape(GLAutoDrawable, int, int, int, int)}
95 * - {@link GLEventListener#display(GLAutoDrawable)}
96 * - {@link GLEventListener#dispose(GLAutoDrawable)}
97 * </p>
98 * <p>
99 * {@link #setPMVMatrixSetup(PMVMatrixSetup)} maybe used to provide a custom {@link PMVMatrix4f} setup.
100 * </p>
101 * @see Shape
102 */
103public final class Scene implements Container, GLEventListener {
104 /** Default scene distance on z-axis to projection is -1/5f. */
105 public static final float DEFAULT_SCENE_DIST = -1/5f;
106 /** Default projection angle in radians is PI/4, i.e. 45.0 degrees. */
107 public static final float DEFAULT_ANGLE = FloatUtil.QUARTER_PI;
108 /** Default projection z-near value is {@value}. */
109 public static final float DEFAULT_ZNEAR = 0.1f;
110 /** Default projection z-far value is {@value}. */
111 public static final float DEFAULT_ZFAR = 7000.0f;
112 /** Default Z precision on 16-bit depth buffer using {@link #DEFAULT_SCENE_DIST} z-position and {@link #DEFAULT_ZNEAR}. Value is {@code 6.1033297E-6}. */
114 /** Default Z precision scale, i.e. multiple of {@link #DEFAULT_Z16_EPSILON} for {@link #setActiveShapeZOffsetScale(float)}. Value is {@value}. */
115 public static final float DEFAULT_ACTIVE_ZOFFSET_SCALE = 10f;
116 /** Default Z precision scale, i.e. multiple of {@link #DEFAULT_Z16_EPSILON} for {@link #setActiveTopLevelZOffsetScale(float)}. Value is {@value}. */
117 public static final float DEFAULT_ACTIVE_TOPLEVEL_ZOFFSET_SCALE = 100f;
118 /** Default Z precision on 16-bit depth buffer using {@code -1} z-position and {@link #DEFAULT_ZNEAR}. Value is {@code 1.5256461E-4}. */
119 // public static final float DIST1_Z16_EPSILON = FloatUtil.getZBufferEpsilon(16 /* zBits */, -1, DEFAULT_ZNEAR);
120
121 /**
122 * Return Z precision on using {@link PMVMatrixSetup#getSceneDist()} z-position and {@link PMVMatrixSetup#getZNear()}.
123 * @param zBits depth buffer bit-depth, minimum 16-bit
124 * @param setup {@link PMVMatrixSetup} for scene-distance as z-position and zNear
125 * @return the Z precision
126 */
127 public static float getZEpsilon(final int zBits, final PMVMatrixSetup setup) {
128 return FloatUtil.getZBufferEpsilon(zBits, setup.getSceneDist(), setup.getZNear());
129 }
130
131 private static final boolean DEBUG = false;
132 private static final boolean DEBUG_PICKING = DEBUG;
133
134 private final List<Shape> shapes = new CopyOnWriteArrayList<Shape>();
135 private Shape[] displayShapeArray = new Shape[0]; // reduce memory re-alloc @ display
136 private final List<Shape> renderedShapesB0 = new ArrayList<Shape>();
137 private final List<Shape> renderedShapesB1 = new ArrayList<Shape>();
138 private final List<Shape> renderedShapesB2 = new ArrayList<Shape>();
139 private volatile List<Shape> renderedShapes = renderedShapesB1;
140 private int renderedShapesIdx = 1;
141 private final AtomicReference<Tooltip> toolTipActive = new AtomicReference<Tooltip>();
142 private final AtomicReference<Shape> toolTipHUD = new AtomicReference<Shape>();
143 private final List<Group> topLevel = new ArrayList<Group>();
144
145 private boolean doFrustumCulling = false;
146
147 private float[] clearColor = null;
148 private int clearMask;
149
150 private final RegionRenderer renderer;
151
152 /** Describing the bounding box in shape's object model-coordinates of the near-plane parallel at its scene-distance, post {@link #translate(PMVMatrix4f)} */
153 private final AABBox planeBox = new AABBox(0f, 0f, 0f, 0f, 0f, 0f);
154
155 private volatile Shape activeShape = null;
156 private volatile Group activeTopLevel = null;
157
158 private SBCMouseListener sbcMouseListener = null;
159 private SBCGestureListener sbcGestureListener = null;
160 private PinchToZoomGesture pinchToZoomGesture = null;
161 private SBCKeyListener sbcKeyListener = null;
162
163 private final GLReadBufferUtil screenshot;
164
165 private GLAutoDrawable cDrawable = null;
166
167 private static RegionRenderer createRenderer() {
169 }
170
171 /**
172 * Create a new scene with an internally created {@link RegionRenderer}, a graph AA sample-count 4 and using {@link DefaultPMVMatrixSetup#DefaultPMVMatrixSetup()}.
173 * @see #Scene(RegionRenderer)
174 * @see #setSampleCount(int)
175 * @see #setAAQuality(int)
176 */
177 public Scene() {
178 this( createRenderer() );
179 }
180
181 /**
182 * Create a new scene with an internally created {@link RegionRenderer}, using {@link DefaultPMVMatrixSetup#DefaultPMVMatrixSetup()}.
183 * @param sampleCount sample count for Graph Region AA {@link Region#getRenderModes() render-modes}: {@link Region#VBAA_RENDERING_BIT} or {@link Region#MSAA_RENDERING_BIT},
184 * clipped to [{@link Region#MIN_AA_SAMPLE_COUNT}..{@link Region#MAX_AA_SAMPLE_COUNT}]
185 * @see #Scene(RegionRenderer)
186 * @see #setSampleCount(int)
187 * @see #setAAQuality(int)
188 */
189 public Scene(final int sampleCount) {
190 this( createRenderer() );
191 this.getRenderer().setSampleCount(sampleCount);
192 }
193
194 /**
195 * Create a new scene taking ownership of the given RegionRenderer, using {@link DefaultPMVMatrixSetup#DefaultPMVMatrixSetup()}.
196 * @param renderer {@link RegionRenderer} to be owned
197 * @see #setSampleCount(int)
198 * @see #setAAQuality(int)
199 */
200 public Scene(final RegionRenderer renderer) {
201 if( null == renderer ) {
202 throw new IllegalArgumentException("Null RegionRenderer");
203 }
204 this.renderer = renderer;
205 if( Platform.OSType.ANDROID != Platform.getOSType() ) {
206 this.screenshot = new GLReadBufferUtil(false, false);
207 } else {
208 this.screenshot = null;
209 }
210 }
211
212 /** Returns the associated RegionRenderer */
213 public RegionRenderer getRenderer() { return renderer; }
214
215 /**
216 * Sets the clear parameter for {@link GL#glClearColor(float, float, float, float) glClearColor(..)} and {@link GL#glClear(int) glClear(..)}
217 * to be issued at {@link #display(GLAutoDrawable)}.
218 *
219 * Without setting these parameter, user has to issue
220 * {@link GL#glClearColor(float, float, float, float) glClearColor(..)} and {@link GL#glClear(int) glClear(..)}
221 * before calling {@link #display(GLAutoDrawable)}.
222 *
223 * @param clearColor {@link GL#glClearColor(float, float, float, float) glClearColor(..)} arguments
224 * @param clearMask {@link GL#glClear(int) glClear(..)} mask, default is {@link GL#GL_COLOR_BUFFER_BIT} | {@link GL#GL_DEPTH_BUFFER_BIT}
225 */
226 public final void setClearParams(final float[] clearColor, final int clearMask) { this.clearColor = clearColor; this.clearMask = clearMask; }
227
228 /** Returns the {@link GL#glClearColor(float, float, float, float) glClearColor(..)} arguments, see {@link #setClearParams(float[], int)}. */
229 public final float[] getClearColor() { return clearColor; }
230
231 /** Returns the {@link GL#glClear(int) glClear(..)} mask, see {@link #setClearParams(float[], int)}. */
232 public final int getClearMask() { return clearMask; }
233
234 @Override
235 public final void setPMvCullingEnabled(final boolean v) { doFrustumCulling = v; }
236
237 @Override
238 public final boolean isPMvCullingEnabled() { return doFrustumCulling; }
239
240 @Override
241 public final boolean isCullingEnabled() { return doFrustumCulling; }
242
243 public synchronized void attachGLAutoDrawable(final GLAutoDrawable drawable) {
244 cDrawable = drawable;
245 }
246 public synchronized void detachGLAutoDrawable(final GLAutoDrawable drawable) {
247 if( cDrawable == drawable ) {
248 cDrawable = null;
249 }
250 }
251 public synchronized void attachInputListenerTo(final GLWindow window) {
252 cDrawable = window;
253 if(null == sbcMouseListener) {
254 sbcMouseListener = new SBCMouseListener();
255 window.addMouseListener(sbcMouseListener);
256 sbcGestureListener = new SBCGestureListener();
257 window.addGestureListener(sbcGestureListener);
258 pinchToZoomGesture = new PinchToZoomGesture(window.getNativeSurface(), false);
259 window.addGestureHandler(pinchToZoomGesture);
260 }
261 if(null == sbcKeyListener) {
262 sbcKeyListener = new SBCKeyListener();
263 window.addKeyListener(sbcKeyListener);
264 }
265 }
266
267 public synchronized void detachInputListenerFrom(final GLWindow window) {
268 if(null != sbcMouseListener) {
269 window.removeMouseListener(sbcMouseListener);
270 sbcMouseListener = null;
271 window.removeGestureListener(sbcGestureListener);
272 sbcGestureListener = null;
273 window.removeGestureHandler(pinchToZoomGesture);
274 pinchToZoomGesture = null;
275 }
276 if(null == sbcKeyListener) {
277 window.removeKeyListener(sbcKeyListener);
278 sbcKeyListener = null;
279 }
280 }
281
282 @Override
283 public int getShapeCount() { return shapes.size(); }
284
285 @Override
286 public List<Shape> getShapes() { return shapes; }
287
288 @Override
289 public List<Shape> getRenderedShapes() { return renderedShapes; }
290
291 @Override
292 public void addShape(final Shape s) {
293 shapes.add(s);
294 }
295
296 @Override
297 public Shape removeShape(final Shape s) {
298 if( shapes.remove(s) ) {
299 return s;
300 } else {
301 return null;
302 }
303 }
304
305 @Override
306 public void removeShapes(final Collection<? extends Shape> shapes) {
307 for(final Shape s : shapes) {
308 removeShape(s);
309 }
310 }
311
312 @Override
313 public boolean removeShape(final GL2ES2 gl, final RegionRenderer renderer, final Shape s) {
314 if( shapes.remove(s) ) {
315 s.destroy(gl, renderer);
316 return true;
317 } else {
318 return false;
319 }
320 }
321
322 /** Removes given shape and destroy it, if contained - convenient call for {@link #removeShape(GL2ES2, RegionRenderer, Shape)}. */
323 public boolean removeShape(final GL2ES2 gl, final Shape s) {
324 return removeShape(gl, renderer, s);
325 }
326 @Override
327 public void addShapes(final Collection<? extends Shape> shapes) {
328 for(final Shape s : shapes) {
329 addShape(s);
330 }
331 }
332 @Override
333 public void removeShapes(final GL2ES2 gl, final RegionRenderer renderer, final Collection<? extends Shape> shapes) {
334 for(final Shape s : shapes) {
335 removeShape(gl, renderer, s);
336 }
337 }
338 /** Removes all given shapes and destroys them, convenient call for {@link #removeShape(GL2ES2, RegionRenderer, Shape)} */
339 public void removeShapes(final GL2ES2 gl, final Collection<? extends Shape> shapes) {
340 removeShapes(gl, renderer, shapes);
341 }
342 @Override
343 public void removeAllShapes(final GL2ES2 gl, final RegionRenderer renderer) {
344 final int count = shapes.size();
345 for(int i=count-1; i>=0; --i) {
346 removeShape(gl, renderer, shapes.get(i));
347 }
348 }
349 /** Removes all given shapes and destroys them, convenient call for {@link #removeAllShapes(GL2ES2, RegionRenderer)}. */
350 public void removeAllShapes(final GL2ES2 gl) {
351 removeAllShapes(gl, renderer);
352 }
353
354 @Override
355 public boolean contains(final Shape s) {
356 return TreeTool.contains(this, s);
357 }
358 @Override
359 public Shape getShapeByIdx(final int id) {
360 if( 0 > id ) {
361 return null;
362 }
363 return shapes.get(id);
364 }
365 @Override
366 public Shape getShapeByID(final int id) {
367 return TreeTool.getShapeByID(this, id);
368 }
369 @Override
370 public Shape getShapeByName(final String name) {
371 return TreeTool.getShapeByName(this, name);
372 }
373
374 /** Returns {@link RegionRenderer#getSampleCount()}. */
375 public int getSampleCount() { return renderer.getSampleCount(); }
376 /**
377 * Sets {@link RegionRenderer#setSampleCount(int)}
378 * @return clipped and set value
379 */
380 public int setSampleCount(final int v) { return renderer.setSampleCount(v); /* markStatesDirty() -> autodetected within GLRegion.draw(..) */ }
381
382 /** Returns {@link RegionRenderer#getAAQuality()}. */
383 public int getAAQuality() { return renderer.getAAQuality(); }
384 /**
385 * Sets {@link RegionRenderer#setAAQuality(int)}.
386 * @return clipped and set value
387 */
388 public int setAAQuality(final int v) { return renderer.setAAQuality(v); /* markStatesDirty() -> autodetected within GLRegion.draw(..) */ }
389
390 public void setSharpness(final float sharpness) {
391 TreeTool.forAll(this, (final Shape s) -> {
392 if( s instanceof GraphShape ) {
393 ((GraphShape)s).setSharpness(sharpness);
394 }
395 return false;
396 });
397 }
398 public void markShapesDirty() {
399 TreeTool.forAll(this, (final Shape s) -> {
400 s.markShapeDirty();
401 return false;
402 });
403 }
404 public void markStatesDirty() {
405 TreeTool.forAll(this, (final Shape s) -> {
406 s.markStateDirty();
407 return false;
408 });
409 }
410
411 @Override
412 public void init(final GLAutoDrawable drawable) {
413 if( null == cDrawable ) {
414 cDrawable = drawable;
415 }
416 renderer.init(drawable.getGL().getGL2ES2());
417 }
418
419 /**
420 * Enqueues a one-shot {@link GLRunnable},
421 * which will be executed within the next {@link GLAutoDrawable#display()} call
422 * if this {@link Scene} has been added as a {@link GLEventListener} and {@link #init(GLAutoDrawable)} has been called.
423 * <p>
424 * See {@link GLAutoDrawable#invoke(boolean, GLRunnable)}.
425 * </p>
426 *
427 * @param wait if <code>true</code> block until execution of <code>glRunnable</code> is finished, otherwise return immediately w/o waiting
428 * @param glRunnable the {@link GLRunnable} to execute within {@link #display()}
429 * @return <code>true</code> if the {@link GLRunnable} has been processed or queued, otherwise <code>false</code>.
430 * @throws IllegalStateException in case of a detected deadlock situation ahead, see above.
431 * @see GLAutoDrawable#invoke(boolean, GLRunnable)
432 */
433 public boolean invoke(final boolean wait, final GLRunnable glRunnable) throws IllegalStateException {
434 if( null != cDrawable ) {
435 return cDrawable.invoke(wait, glRunnable);
436 }
437 return false;
438 }
439
440 public void addGLEventListener(final GLEventListener listener) {
441 if( null != cDrawable ) {
442 cDrawable.addGLEventListener(listener);
443 }
444 }
445 public void removeGLEventListener(final GLEventListener listener) {
446 if( null != cDrawable ) {
447 cDrawable.removeGLEventListener(listener);
448 }
449 }
450
451 /**
452 * Reshape scene using {@link #setupMatrix(PMVMatrix4f, int, int, int, int)} using {@link PMVMatrixSetup}.
453 * <p>
454 * {@inheritDoc}
455 * </p>
456 * @see PMVMatrixSetup
457 * @see #setPMVMatrixSetup(PMVMatrixSetup)
458 * @see #setupMatrix(PMVMatrix4f, int, int, int, int)
459 * @see #getBounds()
460 * @see #getBoundsCenter()
461 */
462 @Override
463 public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
464 renderer.reshapeNotify(x, y, width, height);
465
466 setupMatrix(renderer.getMatrix(), renderer.getViewport());
467 pmvMatrixSetup.setPlaneBox(planeBox, renderer.getMatrix(), renderer.getViewport());
468 }
469
470 @Override
471 public final boolean isOutside(final PMVMatrix4f pmv, final Shape shape) {
472 if( doFrustumCulling ){
473 pmv.pushMv();
474 shape.applyMatToMv(pmv);
475 final boolean res = pmv.getFrustum().isOutside( shape.getBounds() );
476 pmv.popMv();
477 return res;
478 } else {
479 return false;
480 }
481 }
482 @Override
483 public boolean isOutside2(final Matrix4f mvCont, final Shape shape, final PMVMatrix4f pmvShape) {
484 if( doFrustumCulling ){
485 return pmvShape.getFrustum().isOutside( shape.getBounds() );
486 } else {
487 return false;
488 }
489 }
490
491 @Override
492 public void display(final GLAutoDrawable drawable) {
493 final int shapeCount = shapes.size();
494 Arrays.fill(displayShapeArray, null); // flush old refs
495 final Shape[] shapeArray = shapes.toArray(displayShapeArray); // local-backup
496 displayShapeArray = shapeArray; // keep backup
497 Arrays.sort(shapeArray, 0, shapeCount, Shape.ZAscendingComparator);
498 // TreeTool.cullShapes(shapeArray, shapeCount);
499
500 final GL2ES2 gl = drawable.getGL().getGL2ES2();
501 final PMVMatrix4f pmv = renderer.getMatrix();
502
503 final List<Shape> iShapes;
504 final int iShapeIdx;
505 switch(renderedShapesIdx) {
506 case 0: iShapeIdx = 1; iShapes = renderedShapesB1; break;
507 case 1: iShapeIdx = 2; iShapes = renderedShapesB2; break;
508 default: iShapeIdx = 0; iShapes = renderedShapesB0; break;
509 }
510 if( null != clearColor ) {
511 gl.glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
512 gl.glClear(clearMask);
513 }
514 renderer.enable(gl, true);
515
516 synchronized( iShapes ) { // tripple-buffering is just almost enough
517 iShapes.clear();
518
519 for(int i=0; i<shapeCount; i++) {
520 final Shape shape = shapeArray[i];
521 if( shape.isVisible() ) { // && !shape.isDiscarded() ) {
522 pmv.pushMv();
523 shape.applyMatToMv(pmv);
524
525 if( !doFrustumCulling || !pmv.getFrustum().isOutside( shape.getBounds() ) ) {
526 shape.draw(gl, renderer);
527 iShapes.add(shape);
528 shape.setDiscarded(false);
529 } else {
530 shape.setDiscarded(true);
531 }
532 pmv.popMv();
533 }
534 }
535 }
536
537 renderer.enable(gl, false);
538 renderedShapes = iShapes;
539 renderedShapesIdx = iShapeIdx;
540
541 synchronized ( syncDisplayedOnce ) {
542 displayedOnce = true;
543 syncDisplayedOnce.notifyAll();
544 }
545 final Tooltip tt = toolTipActive.get();
546 if( null != tt ) {
547 activateTooltipImpl(drawable, pmv, tt);
548 }
549 }
550
551 private void displayGLSelect(final GLAutoDrawable drawable, final Object[] shapes) {
552 final GL2ES2 gl = drawable.getGL().getGL2ES2();
553
554 gl.glClearColor(0f, 0f, 0f, 1f);
556
557 final PMVMatrix4f pmv = renderer.getMatrix();
558
560
561 final int shapeCount = shapes.length;
562 for(int i=0; i<shapeCount; i++) {
563 final Shape shape = (Shape)shapes[i];
564 if( shape.isVisible() ) {
565 pmv.pushMv();
566 shape.applyMatToMv(pmv);
567
568 if( !doFrustumCulling || !pmv.getFrustum().isOutside( shape.getBounds() ) ) {
569 final float color = ( i + 1f ) / ( shapeCount + 2f );
570 // FIXME
571 // System.err.printf("drawGL: color %f, index %d of [0..%d[%n", color, i, shapeCount);
572 renderer.setColorStatic(color, color, color, 1f);
573 shape.drawToSelect(gl, renderer);
574 }
575 pmv.popMv();
576 }
577 }
578 renderer.enable(gl, false, RegionRenderer.defaultBlendDisable, RegionRenderer.defaultBlendDisable);
579 synchronized ( syncDisplayedOnce ) {
580 displayedOnce = true;
581 syncDisplayedOnce.notifyAll();
582 }
583 }
584
585 private volatile boolean displayedOnce = false;
586 private final Object syncDisplayedOnce = new Object();
587
588 /** Blocks until first {@link #display(GLAutoDrawable)} has completed after construction or {@link #dispose(GLAutoDrawable). */
589 public void waitUntilDisplayed() {
590 synchronized( syncDisplayedOnce ) {
591 while( !displayedOnce ) {
592 try {
593 syncDisplayedOnce.wait();
594 } catch (final InterruptedException e) { }
595 }
596 }
597 }
598
599 /**
600 * Disposes all {@link #addShape(Shape) added} {@link Shape}s.
601 * <p>
602 * Implementation also issues {@link RegionRenderer#destroy(GL2ES2)} if set
603 * and {@link #detachInputListenerFrom(GLWindow)} in case the drawable is of type {@link GLWindow}.
604 * </p>
605 * <p>
606 * {@inheritDoc}
607 * </p>
608 */
609 @Override
610 public void dispose(final GLAutoDrawable drawable) {
611 synchronized ( syncDisplayedOnce ) {
612 displayedOnce = false;
613 syncDisplayedOnce.notifyAll();
614 }
615 if( drawable instanceof GLWindow ) {
616 final GLWindow glw = (GLWindow) drawable;
618 }
619 final GL2ES2 gl = drawable.getGL().getGL2ES2();
620 for(int i=0; i<shapes.size(); i++) {
621 shapes.get(i).destroy(gl, renderer);
622 }
623 for(int i=0; i<disposeActions.size(); i++) {
624 try {
625 disposeActions.get(i).run(drawable);
626 } catch(final Throwable t) {
627 System.err.println("Scene.dispose: Caught Exception @ User Disposable["+i+"]: "+t.getMessage());
628 t.printStackTrace();
629 }
630 }
631 shapes.clear();
632 topLevel.clear();
633 displayShapeArray = new Shape[0];
634 renderedShapesB0.clear();
635 renderedShapesB1.clear();
636 renderedShapesB2.clear();
637 renderedShapes = renderedShapesB1;
638 renderedShapesIdx = 1;
639 disposeActions.clear();
640 if( drawable == cDrawable ) {
641 cDrawable = null;
642 }
643 renderer.destroy(gl);
644 if( null != screenshot ) {
645 screenshot.dispose(gl);
646 }
647 }
648 private final List<GLRunnable> disposeActions = new ArrayList<GLRunnable>();
649 /**
650 * Add a user one-time {@link GLRunnable} disposal action to an internal list, all invoked at {@Link #dispose(GLAutoDrawable)}
651 * where the list is cleared afterwards similar to all shapes.
652 * <p>
653 * This allows proper take-down of custom user resources at exit.
654 * </p>
655 * @param action the custom {@link GLRunnable} disposal action
656 */
657 public void addDisposeAction(final GLRunnable action) { disposeActions.add(action); }
658
659 /**
660 * Calling {@link Shape#winToObjCoord(Scene, int, int, float[])}, retrieving its Shape object position.
661 * @param shape
662 * @param glWinX in GL window coordinates, origin bottom-left
663 * @param glWinY in GL window coordinates, origin bottom-left
664 * @param pmv a new {@link PMVMatrix4f} which will {@link Scene.PMVMatrixSetup#set(PMVMatrix4f, Recti) be setup},
665 * {@link Shape#applyMatToMv(PMVMatrix4f) shape-transformed} and can be reused by the caller and runnable.
666 * @param objPos resulting object position
667 * @param runnable action
668 */
669 public void winToShapeCoord(final Shape shape, final int glWinX, final int glWinY, final PMVMatrix4f pmv, final Vec3f objPos, final Runnable runnable) {
670 if( null == shape ) {
671 return;
672 }
673 final Recti viewport = getViewport();
674 setupMatrix(pmv);
675 TreeTool.forOne(this, pmv, shape, () -> {
676 if( null != shape.winToShapeCoord(pmv, viewport, glWinX, glWinY, objPos) ) {
677 runnable.run();
678 }
679 });
680 }
681
682 @Override
683 public AABBox getBounds(final PMVMatrix4f pmv, final Shape shape) {
684 final AABBox res = new AABBox();
685 if( null == shape ) {
686 return res;
687 }
688 setupMatrix(pmv);
689 TreeTool.forOne(this, pmv, shape, () -> {
690 shape.getBounds().transform(pmv.getMv(), res);
691 });
692 return res;
693 }
694
695 /**
696 * Interface providing {@link #set(PMVMatrix4f, Recti) a method} to
697 * setup {@link PMVMatrix4f}'s {@link GLMatrixFunc#GL_PROJECTION} and {@link GLMatrixFunc#GL_MODELVIEW}.
698 * <p>
699 * At the end of operations, the {@link GLMatrixFunc#GL_MODELVIEW} matrix has to be selected.
700 * </p>
701 * <p>
702 * Implementation is being called by {@link Scene#setupMatrix(PMVMatrix4f, int, int, int, int)}
703 * and hence {@link Scene#reshape(GLAutoDrawable, int, int, int, int)}.
704 * </p>
705 * <p>
706 * Custom implementations can be set via {@link Scene#setPMVMatrixSetup(PMVMatrixSetup)}.
707 * </p>
708 * <p>
709 * The default implementation is {@link Scene.DefaultPMVMatrixSetup}.
710 * @see DefaultPMVMatrixSetup
711 * @see Scene#setPMVMatrixSetup(PMVMatrixSetup)
712 */
713 public static interface PMVMatrixSetup {
714 /** Returns scene distance on z-axis to projection. */
716 /** Returns fov projection angle in radians, shall be {@code 0} for orthogonal projection. */
717 float getAngle();
718 /** Returns projection z-near value. */
719 float getZNear();
720 /** Returns projection z-far value. */
721 float getZFar();
722
723 /**
724 * Setup {@link PMVMatrix4f}'s {@link GLMatrixFunc#GL_PROJECTION} and {@link GLMatrixFunc#GL_MODELVIEW}.
725 * <p>
726 * See {@link PMVMatrixSetup} for details.
727 * </p>
728 * <p>
729 * At the end of operations, the {@link GLMatrixFunc#GL_MODELVIEW} matrix is selected.
730 * </p>
731 * @param pmv the {@link PMVMatrix4f} to setup
732 * @param viewport Rect4i viewport
733 */
734 void set(PMVMatrix4f pmv, Recti viewport);
735
736 /**
737 * Optional method to set the {@link Scene#getBounds()} {@link AABBox}, maybe a {@code nop} if not desired.
738 * <p>
739 * Will be called by {@link Scene#reshape(GLAutoDrawable, int, int, int, int)} after {@link #set(PMVMatrix4f, Recti)}.
740 * </p>
741 * @param planeBox the {@link AABBox} to define
742 * @param pmv the {@link PMVMatrix4f}, already setup via {@link #set(PMVMatrix4f, Recti)}.
743 * @param viewport Rect4i viewport
744 */
745 void setPlaneBox(final AABBox planeBox, final PMVMatrix4f pmv, Recti viewport);
746 }
747
748 /** Return the default or {@link #setPMVMatrixSetup(PMVMatrixSetup)} {@link PMVMatrixSetup}. */
749 public final PMVMatrixSetup getPMVMatrixSetup() { return pmvMatrixSetup; }
750
751 /** Set a custom {@link PMVMatrixSetup}. */
752 public final void setPMVMatrixSetup(final PMVMatrixSetup setup) { pmvMatrixSetup = setup; }
753
754 /**
755 * Setup {@link PMVMatrix4f} {@link GLMatrixFunc#GL_PROJECTION} and {@link GLMatrixFunc#GL_MODELVIEW}
756 * by calling {@link #getPMVMatrixSetup()}'s {@link PMVMatrixSetup#set(PMVMatrix4f, Recti)}.
757 * @param pmv the {@link PMVMatrix4f} to setup
758 * @param Recti viewport
759 */
760 public void setupMatrix(final PMVMatrix4f pmv, final Recti viewport) {
761 pmvMatrixSetup.set(pmv, viewport);
762 }
763
764 /**
765 * Setup {@link PMVMatrix4f} {@link GLMatrixFunc#GL_PROJECTION} and {@link GLMatrixFunc#GL_MODELVIEW}
766 * using implicit {@link #getViewport()} surface dimension by calling {@link #getPMVMatrixSetup()}'s {@link PMVMatrixSetup#set(PMVMatrix4f, Recti)}.
767 * @param pmv the {@link PMVMatrix4f} to setup
768 */
769 public void setupMatrix(final PMVMatrix4f pmv) {
770 final Recti viewport = renderer.getViewport();
771 setupMatrix(pmv, viewport);
772 }
773
774 /** 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)}. */
775 public final Recti getViewport(final Recti target) { return renderer.getViewport(target); }
776
777 /** Borrows the current int[4] viewport w/o copying. It is set after initial {@link #reshape(GLAutoDrawable, int, int, int, int)}. */
778 public Recti getViewport() { return renderer.getViewport(); }
779
780 /** Returns the {@link #getViewport()}'s width, set after initial {@link #reshape(GLAutoDrawable, int, int, int, int)}. */
781 public int getWidth() { return renderer.getWidth(); }
782 /** Returns the {@link #getViewport()}'s height, set after initial {@link #reshape(GLAutoDrawable, int, int, int, int)}. */
783 public int getHeight() { return renderer.getHeight(); }
784
785 /** Borrow the current {@link PMVMatrix4f}. */
786 public PMVMatrix4f getMatrix() { return renderer.getMatrix(); }
787
788 /**
789 * Describing the scene's object model-dimensions of the plane at scene-distance covering the visible viewport rectangle.
790 * <p>
791 * The value is evaluated at {@link #reshape(GLAutoDrawable, int, int, int, int)} via {@link }
792 * </p>
793 * <p>
794 * {@link AABBox#getWidth()} and {@link AABBox#getHeight()} define scene's dimension covered by surface size.
795 * </p>
796 * <p>
797 * {@link AABBox} is setup via {@link #getPMVMatrixSetup()}'s {@link PMVMatrixSetup#setPlaneBox(AABBox, PMVMatrix4f, Recti)}.
798 * </p>
799 * <p>
800 * The default {@link PMVMatrixSetup} implementation scales to normalized plane dimensions, 1 for the greater of width and height.
801 * </p>
802 */
803 public AABBox getBounds() { return planeBox; }
804
805 /**
806 * Return Z precision on using current {@link #getPMVMatrixSetup()}'s {@link PMVMatrixSetup#getSceneDist()} z-position and {@link PMVMatrixSetup#getZNear()}.
807 * @param zBits depth buffer bit-depth, minimum 16-bit
808 * @return the Z precision
809 */
810 public float getZEpsilon(final int zBits) {
811 return FloatUtil.getZBufferEpsilon(zBits, pmvMatrixSetup.getSceneDist(), pmvMatrixSetup.getZNear());
812 }
813
814 /**
815 *
816 * @param pmv
817 * @param viewport
818 * @param zNear
819 * @param zFar
820 * @param winX
821 * @param winY
822 * @param objOrthoZ
823 * @param objPos float[3] storage for object coord result
824 * @param winZ
825 */
826 public static void winToPlaneCoord(final PMVMatrix4f pmv, final Recti viewport,
827 final float zNear, final float zFar,
828 final float winX, final float winY, final float objOrthoZ,
829 final Vec3f objPos) {
830 final float winZ = FloatUtil.getOrthoWinZ(objOrthoZ, zNear, zFar);
831 pmv.mapWinToObj(winX, winY, winZ, viewport, objPos);
832 }
833
834 /**
835 * Map given window surface-size to object coordinates relative to this scene using
836 * the give projection parameters.
837 * @param viewport viewport rectangle
838 * @param zNear custom {@link #DEFAULT_ZNEAR}
839 * @param zFar custom {@link #DEFAULT_ZFAR}
840 * @param objOrthoDist custom {@link #DEFAULT_SCENE_DIST}
841 * @param objSceneSize Vec2f storage for object surface size result
842 */
843 public void surfaceToPlaneSize(final Recti viewport, final float zNear, final float zFar, final float objOrthoDist, final Vec2f objSceneSize) {
844 final PMVMatrix4f pmv = new PMVMatrix4f();
845 setupMatrix(pmv, viewport);
846 {
847 final Vec3f obj00Coord = new Vec3f();
848 final Vec3f obj11Coord = new Vec3f();
849
850 winToPlaneCoord(pmv, viewport, DEFAULT_ZNEAR, DEFAULT_ZFAR, viewport.x(), viewport.y(), objOrthoDist, obj00Coord);
851 winToPlaneCoord(pmv, viewport, DEFAULT_ZNEAR, DEFAULT_ZFAR, viewport.width(), viewport.height(), objOrthoDist, obj11Coord);
852 objSceneSize.set( obj11Coord.x() - obj00Coord.x(),
853 obj11Coord.y() - obj00Coord.y() );
854 }
855 }
856
857 /**
858 * Map given window surface-size to object coordinates relative to this scene using
859 * the default {@link PMVMatrixSetup}, i.e. {@link #DEFAULT_ZNEAR}, {@link #DEFAULT_ZFAR} and {@link #DEFAULT_SCENE_DIST}
860 * @param viewport viewport rectangle
861 * @param objSceneSize Vec2f storage for object surface size result
862 */
863 public void surfaceToPlaneSize(final Recti viewport, final Vec2f objSceneSize) {
865 }
866
867 public final Shape getActiveShape() {
868 return activeShape;
869 }
870
871 public void releaseActiveShape() {
872 final Shape lastShape = activeShape;
873 if( null != lastShape ) {
874 final Group lastTL = activeTopLevel;
875 lastShape.setActive(false, 0);
876 activeShape = null;
877
878 activeTopLevel = null;
879 if( null != lastTL ) {
880 lastTL.setActiveTopLevel(false, 0);
881 }
882 if( DEBUG_PICKING ) {
883 System.err.println("ACTIVE-RELEASE: s 0x"+Integer.toHexString(System.identityHashCode(lastShape))+", "+lastShape);
884 System.err.println("ACTIVE-RELEASE: g 0x"+Integer.toHexString(System.identityHashCode(lastTL))+", "+lastTL);
885 dumpTopLevelParent();
886 }
887 }
888 }
889 private void setActiveShape(final Shape shape) {
890 final Shape lastShape = activeShape;
891 if( lastShape != shape && null != shape ) {
892 final float zEpsilon = getZEpsilon(16);
893 final boolean isTopLevel = topLevel.contains(shape);
894 final float newZOffset = ( isTopLevel ? activeZOffsetScale : activeTopLevelZOffsetScale ) * zEpsilon;
895 if( shape.setActive(true, newZOffset) ) {
896 final Group lastTL = activeTopLevel;
897 final Group thisTL = isTopLevel ? (Group)shape : getTopLevelParent(shape);
898 int mode = 0;
899 if( null != lastShape && thisTL != lastShape ) {
900 lastShape.setActive(false, 0);
901 mode += 10;
902 }
903 if( lastTL != thisTL ) {
904 mode += 100;
905 if( null!=lastTL) {
906 lastTL.setActiveTopLevel(false, 0);
907 mode += 1000;
908 }
909 if( null!=thisTL && !isTopLevel ) {
910 thisTL.setActiveTopLevel(true, activeTopLevelZOffsetScale * zEpsilon);
911 mode += 10000;
912 }
913 activeTopLevel = thisTL;
914 }
915
916 if( DEBUG_PICKING ) {
917 System.err.println("ACTIVE-SHAPE: NEW mode "+mode+", isTopLevel "+isTopLevel+", s 0x"+Integer.toHexString(System.identityHashCode(shape))+", "+shape);
918 System.err.println("ACTIVE-SHAPE: NEW g 0x"+Integer.toHexString(System.identityHashCode(thisTL))+", "+thisTL);
919 System.err.println("ACTIVE-SHAPE: PRE s 0x"+Integer.toHexString(System.identityHashCode(lastShape))+", "+lastShape);
920 System.err.println("ACTIVE-SHAPE: PRE g 0x"+Integer.toHexString(System.identityHashCode(lastTL))+", "+lastTL);
921 // dumpTopLevelParent();
922 }
923 mode = mode + 0; // (void)mode ;-)
924 activeShape = shape;
925 }
926 }
927 }
928 private float activeZOffsetScale = DEFAULT_ACTIVE_ZOFFSET_SCALE;
929 private float activeTopLevelZOffsetScale = DEFAULT_ACTIVE_TOPLEVEL_ZOFFSET_SCALE;
930
931 /** Returns the active {@link Shape} Z-Offset scale, defaults to {@link #DEFAULT_ACTIVE_ZOFFSET_SCALE}. */
932 public float getActiveShapeZOffsetScale() { return activeZOffsetScale; }
933 /** Sets the active {@link Shape} Z-Offset scale, defaults to {@link #DEFAULT_ACTIVE_ZOFFSET_SCALE}. */
934 public void setActiveShapeZOffsetScale(final float v) { activeZOffsetScale = v; }
935
936 /** Returns the general {@link Group#enableTopLevelWidget(Scene) top-level widget} Z-Offset scale, defaults to {@link #DEFAULT_ACTIVE_ZOFFSET_SCALE}. */
937 public float getActiveTopLevelZOffsetScale() { return activeTopLevelZOffsetScale; }
938 /** Sets the general {@link Group#enableTopLevelWidget(Scene) top-level widget} Z-Offset scale, defaults to {@link #DEFAULT_ACTIVE_TOPLEVEL_ZOFFSET_SCALE}. */
939 public void setActiveTopLevelZOffsetScale(final float v) { activeTopLevelZOffsetScale = v; }
940
941 /* pp */ void addTopLevel(final Group g) { topLevel.add(g); }
942 /* pp */ void removeTopLevel(final Group g) { topLevel.add(g); }
943 private Group getTopLevelParent(final Shape s) {
944 for(final Group g : topLevel) {
945 if(g.contains(s)) {
946 return g;
947 }
948 }
949 return null;
950 }
951 private void dumpTopLevelParent() {
952 int idx = 0;
953 for(final Group g : topLevel) {
954 final boolean a0 = g.isActive();
955 System.err.printf("- %02d: 0x%08x %s %s/%s, %s%n", idx++, System.identityHashCode(g), (a0?"****":"____"), g.getClass().getSimpleName(), g.getName(), g);
956 if( g.isActive() ) {
957 final int idx1 = idx-1;
958 final int[] idx2 = { 0 };
959 TreeTool.forAll(g, (final Shape s) -> {
960 final boolean a1 = s.isActive();
961 System.err.printf("- %02d:%02d: 0x%08x %s %s/%s, %s%n", idx1, idx2[0]++, System.identityHashCode(s), (a1?"****":"____"), s.getClass().getSimpleName(), s.getName(), s);
962 return false;
963 });
964 }
965 }
966 }
967
968 private final class SBCGestureListener implements GestureHandler.GestureListener {
969 @Override
970 public void gestureDetected(final GestureEvent gh) {
971 clearToolTip();
972 if( null != activeShape ) {
973 // gesture .. delegate to active shape!
974 final InputEvent orig = gh.getTrigger();
975 if( orig instanceof MouseEvent ) {
976 final Shape shape = activeShape;
977 if( shape.isInteractive() ) {
978 final MouseEvent e = (MouseEvent) orig;
979 // flip to GL window coordinates
980 final int glWinX = e.getX();
981 final int glWinY = getHeight() - e.getY() - 1;
982 final PMVMatrix4f pmv = new PMVMatrix4f();
983 final Vec3f objPos = new Vec3f();
984 winToShapeCoord(shape, glWinX, glWinY, pmv, objPos, () -> {
985 shape.dispatchGestureEvent(gh, glWinX, glWinY, pmv, renderer.getViewport(), objPos);
986 });
987 }
988 }
989 }
990 }
991 }
992
993 /**
994 * Attempt to pick a {@link Shape} using the OpenGL false color rendering.
995 * <p>
996 * If {@link Shape} was found the given action is performed on the rendering thread.
997 * </p>
998 * <p>
999 * Method is non blocking and performs on rendering-thread, it returns immediately.
1000 * </p>
1001 * @param glWinX window X coordinate, bottom-left origin
1002 * @param glWinY window Y coordinate, bottom-left origin
1003 * @param objPos storage for found object position in model-space of found {@link Shape}
1004 * @param shape storage for found {@link Shape} or null
1005 * @param runnable the action to perform if {@link Shape} was found
1006 */
1007 public void pickShapeGL(final int glWinX, final int glWinY, final Vec3f objPos, final Shape[] shape, final Runnable runnable) {
1008 if( null == cDrawable ) {
1009 return;
1010 }
1011 cDrawable.invoke(false, new GLRunnable() {
1012 @Override
1013 public boolean run(final GLAutoDrawable drawable) {
1014 final Shape s = pickShapeGLImpl(drawable, glWinX, glWinY);
1015 shape[0] = s;
1016 if( null != s ) {
1017 final PMVMatrix4f pmv = renderer.getMatrix();
1018 pmv.pushMv();
1019 s.applyMatToMv(pmv);
1020 final boolean ok = null != shape[0].winToShapeCoord(getMatrix(), getViewport(), glWinX, glWinY, objPos);
1021 pmv.popMv();
1022 if( ok ) {
1023 runnable.run();
1024 }
1025 }
1026 return false; // needs to re-render to wash away our false-color glSelect
1027 } } );
1028 }
1029 @SuppressWarnings({ "unchecked", "rawtypes" })
1030 private Shape pickShapeGLImpl(final GLAutoDrawable drawable, final int glWinX, final int glWinY) {
1031 final Object[] shapesS = shapes.toArray();
1032 Arrays.sort(shapesS, (Comparator)Shape.ZAscendingComparator);
1033
1034 final GLPixelStorageModes psm = new GLPixelStorageModes();
1035 final ByteBuffer pixel = Buffers.newDirectByteBuffer(4);
1036
1037 final GL2ES2 gl = drawable.getGL().getGL2ES2();
1038
1039 displayGLSelect(drawable, shapesS);
1040
1041 psm.setPackAlignment(gl, 4);
1042 // psm.setUnpackAlignment(gl, 4);
1043 try {
1044 // gl.glReadPixels(glWinX, getHeight() - glWinY, 1, 1, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, pixel);
1045 gl.glReadPixels(glWinX, glWinY, 1, 1, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, pixel);
1046 } catch(final GLException gle) {
1047 gle.printStackTrace();
1048 return null;
1049 }
1050 psm.restore(gl);
1051
1052 // final float color = ( i + 1f ) / ( shapeCount + 2f );
1053 final int shapeCount = shapes.size();
1054 final int qp = pixel.get(0) & 0xFF;
1055 final float color = qp / 255.0f;
1056 final int index = Math.round( ( color * ( shapeCount + 2f) ) - 1f );
1057
1058 // FIXME drawGL: color 0.333333, index 0 of [0..1[
1059 System.err.printf("pickGL: glWin %d / %d, byte %d, color %f, index %d of [0..%d[%n",
1060 glWinX, glWinY, qp, color, index, shapeCount);
1061
1062 if( 0 <= index && index < shapeCount ) {
1063 return (Shape)shapesS[index];
1064 } else {
1065 return null;
1066 }
1067 }
1068
1069 /**
1070 * General {@link Shape} visitor
1071 */
1072 private static interface PickVisitor {
1073 /**
1074 * Visitor method
1075 * @param s the {@link Shape} to process
1076 * @param pmv the {@link PMVMatrix4f} setup from the {@link Scene} down to the {@link Shape}
1077 * @return the picked shape signaling end of traversal, otherwise null to continue
1078 */
1079 Shape visit(Shape s, final PMVMatrix4f pmv);
1080 }
1081 private static Shape pickForAllRenderedDesc(final Container cont, final PMVMatrix4f pmv, final PickVisitor v) {
1082 Shape picked = null;
1083 final List<Shape> shapes = cont.getRenderedShapes();
1084 synchronized( shapes ) { // tripple-buffering is just almost enough
1085 for(int i=shapes.size()-1; null == picked && i>=0; --i) {
1086 final Shape s = shapes.get(i);
1087 pmv.pushMv();
1088 s.applyMatToMv(pmv);
1089 picked = v.visit(s, pmv);
1090 if( s instanceof Container ) {
1091 final Shape childPick = pickForAllRenderedDesc((Container)s, pmv, v);
1092 if( null != childPick ) {
1093 picked = childPick; // child picked overrides group parent!
1094 }
1095 }
1096 pmv.popMv();
1097 }
1098 }
1099 return picked;
1100 }
1101 /**
1102 * Attempt to pick a {@link Shape} using the window coordinates and contained {@ling Shape}'s {@link AABBox} {@link Shape#getBounds() bounds}
1103 * using a ray-intersection algorithm in Z-axis descending order.
1104 * <p>
1105 * If {@link Shape} was found the given action is performed.
1106 * </p>
1107 * <p>
1108 * Method performs on current thread and returns after either a shaper is determined to be picked/active or
1109 * probing every {@link Shape} w/o result.
1110 * </p>
1111 * @param pmv a new {@link PMVMatrix4f} which will {@link Scene.PMVMatrixSetup#set(PMVMatrix4f, Recti) be setup},
1112 * {@link Shape#applyMatToMv(PMVMatrix4f) shape-transformed} and can be reused by the caller and runnable.
1113 * @param ray temporary {@link Ray} storage, passed for reusage
1114 * @param glWinX window X coordinate, bottom-left origin
1115 * @param glWinY window Y coordinate, bottom-left origin
1116 * @param objPos storage for found object position in model-space of found {@link Shape}
1117 * @param runnable the action to perform if {@link Shape} was found
1118 * @return last picked (inner) Shape if any or null
1119 */
1120 public Shape pickShape(final PMVMatrix4f pmv, final Ray ray, final int glWinX, final int glWinY, final Vec3f objPos, final Shape.Visitor1 visitor) {
1121 setupMatrix(pmv);
1122
1123 final float winZ0 = 0f;
1124 final float winZ1 = 0.3f;
1125 /**
1126 final FloatBuffer winZRB = Buffers.newDirectFloatBuffer(1);
1127 gl.glReadPixels( x, y, 1, 1, GL2ES2.GL_DEPTH_COMPONENT, GL.GL_FLOAT, winZRB);
1128 winZ1 = winZRB.get(0); // dir
1129 */
1130 final Recti viewport = getViewport();
1131 final int[] shapeIdx = { -1 };
1132 return pickForAllRenderedDesc(this, pmv, (final Shape s, final PMVMatrix4f pmv2) -> {
1133 shapeIdx[0]++;
1134 if( pmv.mapWinToRay(glWinX, glWinY, winZ0, winZ1, viewport, ray) ) {
1135 final AABBox sbox = s.getBounds();
1136 if( sbox.intersectsRay(ray) ) {
1137 if( null == sbox.getRayIntersection(objPos, ray, FloatUtil.EPSILON, true) ) {
1138 throw new InternalError("Ray "+ray+", box "+sbox);
1139 }
1140 if( visitor.visit(s) ) {
1141 return s;
1142 }
1143 }
1144 }
1145 return null;
1146 });
1147 }
1148 /**
1149 * Pick the shape using the event coordinates
1150 * @param e original Newt {@link MouseEvent}
1151 * @param glWinX in GL window coordinates, origin bottom-left
1152 * @param glWinY in GL window coordinates, origin bottom-left
1153 */
1154 private final Shape dispatchMouseEventPickShape(final MouseEvent e, final int glWinX, final int glWinY) {
1155 final Shape shape = pickShape(dispMEPSPMv, dispMEPSRay, glWinX, glWinY, dispMEPSObjPos, (final Shape s) -> {
1156 // return s.isInteractive() && ( s.dispatchMouseEvent(e, glWinX, glWinY, dispMEPSObjPos) || true );
1157 if( !s.isInteractive() ) {
1158 if( DEBUG_PICKING ) {
1159 System.err.printf("Pick.X.0: shape %s/%s, [%d, %d]%n", s.getClass().getSimpleName(), s.getName(), glWinX, glWinY);
1160 }
1161 return false;
1162 }
1163 if( !s.dispatchMouseEvent(e, glWinX, glWinY, dispMEPSObjPos) ) {
1164 if( DEBUG_PICKING ) {
1165 System.err.printf("Pick.X.1: shape %s/%s, [%d, %d], %s%n", s.getClass().getSimpleName(), s.getName(), glWinX, glWinY, e);
1166 }
1167 return false;
1168 }
1169 if( DEBUG_PICKING ) {
1170 System.err.printf("Pick.X.S: shape %s/%s, [%d, %d], %s%n", s.getClass().getSimpleName(), s.getName(), glWinX, glWinY, e);
1171 }
1172 return true;
1173 });
1174 if( null != shape ) {
1175 if( DEBUG_PICKING ) {
1176 System.err.printf("Pick.X: shape %s/%s%n%n", shape.getClass().getSimpleName(), shape.getName());
1177 }
1178 setActiveShape(shape);
1179 return shape;
1180 } else {
1181 if( DEBUG_PICKING ) {
1182 System.err.printf("Pick.X: shape null%n%n");
1183 }
1184 releaseActiveShape();
1185 return null;
1186 }
1187 }
1188 private final PMVMatrix4f dispMEPSPMv = new PMVMatrix4f();
1189 private final Ray dispMEPSRay = new Ray();
1190 private final Vec3f dispMEPSObjPos = new Vec3f();
1191
1192 /**
1193 * Dispatch event to shape
1194 * @param shape target active shape of event
1195 * @param e original Newt {@link MouseEvent}
1196 * @param glWinX in GL window coordinates, origin bottom-left
1197 * @param glWinY in GL window coordinates, origin bottom-left
1198 */
1199 private final void dispatchMouseEventForShape(final Shape shape, final MouseEvent e, final int glWinX, final int glWinY) {
1200 final PMVMatrix4f pmv = new PMVMatrix4f();
1201 final Vec3f objPos = new Vec3f();
1202 winToShapeCoord(shape, glWinX, glWinY, pmv, objPos, () -> { shape.dispatchMouseEvent(e, glWinX, glWinY, objPos); });
1203 if( DEBUG_PICKING ) {
1204 System.err.printf("ForShape: shape %s/%s%n%n", shape.getClass().getSimpleName(), shape.getName());
1205 }
1206 }
1207
1208 private final class SBCMouseListener implements MouseListener {
1209 private int lx, ly, lId;
1210 private boolean mouseOver;
1211
1212 private SBCMouseListener() {
1213 clear();
1214 }
1215 private final void clear() {
1216 lx = -1; ly = -1; lId = -1; mouseOver = false;
1217 }
1218 private final Shape dispatchPickShape(final MouseEvent e, final int glWinX, final int glWinY) {
1219 final Shape s = dispatchMouseEventPickShape(e, glWinX, glWinY);
1220 if( null == s ) {
1221 clear();
1222 }
1223 return s;
1224 }
1225 @Override
1226 public void mousePressed(final MouseEvent e) {
1227 if( -1 == lId || e.getPointerId(0) == lId ) {
1228 lx = e.getX();
1229 ly = e.getY();
1230 lId = e.getPointerId(0);
1231 }
1232 // flip to GL window coordinates, origin bottom-left
1233 final int glWinX = e.getX();
1234 final int glWinY = getHeight() - e.getY() - 1;
1235 // Can't use selected activeShape via mouseOver,
1236 // since mouseMove and mousePressed/Drag or mouseClicked may-shall select a different shape
1237 // based on draggable. mouseMove simply activates any shape.
1238 dispatchPickShape(e, glWinX, glWinY);
1239 }
1240
1241 @Override
1242 public void mouseReleased(final MouseEvent e) {
1243 // flip to GL window coordinates, origin bottom-left
1244 final int glWinX = e.getX();
1245 final int glWinY = getHeight() - e.getY() - 1;
1246 if( mouseOver && null != activeShape && activeShape.isInteractive() && !pinchToZoomGesture.isWithinGesture() && e.getPointerId(0) == lId ) {
1247 dispatchMouseEventForShape(activeShape, e, glWinX, glWinY);
1248 } else {
1249 dispatchPickShape(e, glWinX, glWinY);
1250 }
1251 if( !mouseOver && 1 == e.getPointerCount() ) {
1252 // Release active shape: last pointer has been lifted!
1253 releaseActiveShape();
1254 clear();
1255 }
1256 }
1257
1258 @Override
1259 public void mouseClicked(final MouseEvent e) {
1260 // flip to GL window coordinates
1261 final int glWinX = e.getX();
1262 final int glWinY = getHeight() - e.getY() - 1;
1263 // Can't use selected activeShape via mouseOver,
1264 // since mouseMove and mousePressed/Drag or mouseClicked may-shall select a different shape
1265 // based on draggable. mouseMove simply activates any shape.
1266 dispatchPickShape(e, glWinX, glWinY);
1267 }
1268
1269 @Override
1270 public void mouseDragged(final MouseEvent e) {
1271 clearToolTip();
1272 // drag activeShape, if no gesture-activity, only on 1st pointer
1273 if( null != activeShape && activeShape.isInteractive() && !pinchToZoomGesture.isWithinGesture() && e.getPointerId(0) == lId ) {
1274 lx = e.getX();
1275 ly = e.getY();
1276
1277 // dragged .. delegate to active shape!
1278 // flip to GL window coordinates, origin bottom-left
1279 final int glWinX = e.getX();
1280 final int glWinY = getHeight() - e.getY() - 1;
1281 dispatchMouseEventForShape(activeShape, e, glWinX, glWinY);
1282 }
1283 }
1284
1285 @Override
1286 public void mouseWheelMoved(final MouseEvent e) {
1287 clearToolTip();
1288 // flip to GL window coordinates
1289 final int glWinX = lx;
1290 final int glWinY = getHeight() - ly - 1;
1291 if( mouseOver && null != activeShape && activeShape.isInteractive() && !pinchToZoomGesture.isWithinGesture() && e.getPointerId(0) == lId ) {
1292 dispatchMouseEventForShape(activeShape, e, glWinX, glWinY);
1293 } else {
1294 dispatchPickShape(e, glWinX, glWinY);
1295 }
1296 }
1297
1298 @Override
1299 public void mouseMoved(final MouseEvent e) {
1300 if( -1 == lId || e.getPointerId(0) == lId ) {
1301 lx = e.getX();
1302 ly = e.getY();
1303 lId = e.getPointerId(0);
1304 }
1305 clearToolTip();
1306 final int glWinX = lx;
1307 final int glWinY = getHeight() - ly - 1;
1308 final Shape s = dispatchPickShape(e, glWinX, glWinY);
1309 if( null != s ) {
1310 mouseOver = true;
1311 synchronized( toolTipActive ) {
1312 toolTipActive.set( s.startToolTip(true /* lookupParents */) );
1313 }
1314 }
1315 }
1316 @Override
1317 public void mouseEntered(final MouseEvent e) { }
1318 @Override
1319 public void mouseExited(final MouseEvent e) {
1320 clearToolTip();
1321 releaseActiveShape();
1322 clear();
1323 }
1324 }
1325 private final class SBCKeyListener implements KeyListener {
1326 @Override
1327 public void keyPressed(final KeyEvent e) {
1328 if( null != activeShape && activeShape.isInteractive() ) {
1329 activeShape.dispatchKeyEvent(e);
1330 }
1331 }
1332
1333 @Override
1334 public void keyReleased(final KeyEvent e) {
1335 if( null != activeShape && activeShape.isInteractive() ) {
1336 activeShape.dispatchKeyEvent(e);
1337 }
1338 }
1339 }
1340
1341 private void setToolTip(final Shape hud) {
1342 addShape( hud );
1343 toolTipHUD.set( hud );
1344 }
1345
1346 private void clearToolTip() {
1347 final Tooltip tt;
1348 synchronized( toolTipActive ) {
1349 tt = toolTipActive.get();
1350 if( null != tt && tt.stop(false) ) {
1351 toolTipActive.set(null);
1352 }
1353 }
1354 final Shape s = toolTipHUD.getAndSet(null);
1355 if( null != s ) {
1356 invoke(false, (final GLAutoDrawable drawable) -> {
1357 if( null != tt ) {
1358 if( s == removeShape(s) ) {
1359 tt.destroyTip(drawable.getGL().getGL2ES2(), renderer, s);
1360 }
1361 } else {
1362 removeShape(drawable.getGL().getGL2ES2(), renderer, s);
1363 }
1364 return true;
1365 });
1366 }
1367 }
1368 private void activateTooltipImpl(final GLAutoDrawable drawable, final PMVMatrix4f pmv, final Tooltip tt) {
1369 if( null == toolTipHUD.get() ) {
1370 final Shape[] hud = { null };
1371 if( tt.tick() && TreeTool.forOne(this, pmv, tt.getTool(), () -> {
1372 final AABBox toolMvBounds = tt.getToolMvBounds(pmv);
1373 hud[0] = tt.createTip(Scene.this, toolMvBounds);
1374 }) )
1375 {
1376 setToolTip( hud[0] );
1377 }
1378 }
1379 }
1380
1381 /**
1382 * Return a formatted status string containing avg fps and avg frame duration.
1383 * @param glad GLAutoDrawable instance for FPSCounter, its chosen GLCapabilities and its GL's swap-interval
1384 * @param renderModes render modes for {@link Region#getRenderModeString(int, int, int, int)}
1385 * @param dpi the monitor's DPI (vertical preferred)
1386 * @return formatted status string
1387 */
1388 public String getStatusText(final GLAutoDrawable glad, final int renderModes, final float dpi) {
1389 final FPSCounter fpsCounter = glad.getAnimator();
1390 final float lfps, tfps, td;
1391 if( null != fpsCounter ) {
1392 lfps = fpsCounter.getLastFPS();
1393 tfps = fpsCounter.getTotalFPS();
1394 td = (float)fpsCounter.getLastFPSPeriod() / (float)fpsCounter.getUpdateFPSFrames();
1395 } else {
1396 lfps = 0f;
1397 tfps = 0f;
1398 td = 0f;
1399 }
1401 final String modeS = Region.getRenderModeString(renderModes, getAAQuality(), getSampleCount(), caps.getNumSamples());
1402 final String blendStr;
1403 if( getRenderer().hintBitsSet(RenderState.BITHINT_BLENDING_ENABLED) ) {
1404 blendStr = ", blend";
1405 } else {
1406 blendStr = "";
1407 }
1408 return String.format("%03.1f/%03.1f fps, %.1f ms/f, vsync %d, dpi %.1f, %s%s, a %d",
1409 lfps, tfps, td, glad.getGL().getSwapInterval(), dpi, modeS, blendStr, caps.getAlphaBits());
1410 }
1411
1412 /**
1413 * Return a formatted status string containing avg fps and avg frame duration.
1414 * @param fpsCounter the counter, must not be null
1415 * @return formatted status string
1416 */
1417 public static String getStatusText(final FPSCounter fpsCounter) {
1418 final float lfps = fpsCounter.getLastFPS();
1419 final float tfps = fpsCounter.getTotalFPS();
1420 final float td = (float)fpsCounter.getLastFPSPeriod() / (float)fpsCounter.getUpdateFPSFrames();
1421 return String.format("%03.1f/%03.1f fps, %.1f ms/f", lfps, tfps, td);
1422 }
1423
1424 /**
1425 * Return the unique next technical screenshot PNG {@link File} instance as follows:
1426 * <pre>
1427 * filename = [{dir}][{prefix}-]{@link Region#getRenderModeString(int, int, int, int)}[-{contentDetails}]-snap{screenShotCount}-{resolution}.png
1428 * </pre>
1429 * Implementation increments {@link #getScreenshotCount()}.
1430 *
1431 * @param dir the target directory, may be `null` or an empty string
1432 * @param prefix the prefix, may be `null` or an empty string
1433 * @param renderModes the used Graph renderModes, see {@link GLRegion#create(GLProfile, int, TextureSequence) create(..)}
1434 * @param caps the used {@link GLCapabilitiesImmutable} used to retrieved the full-screen AA (fsaa) {@link GLCapabilitiesImmutable#getNumSamples()}
1435 * @param contentDetail user content details to be added at the end but before {@link #getScreenshotCount()}, may be `null` or an empty string
1436 * @return a unique descriptive screenshot filename
1437 * @see #screenshot(GL, File)
1438 * @see #screenshot(boolean, File)
1439 * @see #getScreenshotCount()
1440 */
1441 public File nextScreenshotFile(final String dir, final String prefix, final int renderModes, final GLCapabilitiesImmutable caps, final String contentDetail) {
1442 final String dir2 = ( null != dir && dir.length() > 0 ) ? dir : "";
1443 final String prefix2 = ( null != prefix && prefix.length() > 0 ) ? prefix+"-" : "";
1444 final RegionRenderer renderer = getRenderer();
1445 final String modeS = Region.getRenderModeString(renderModes, getAAQuality(), getSampleCount(), caps.getNumSamples());
1446 final String contentDetail2 = ( null != contentDetail && contentDetail.length() > 0 ) ? contentDetail+"-" : "";
1447 return new File( String.format((Locale)null, "%s%s%s-%ssnap%02d-%04dx%04d.png",
1448 dir2, prefix2, modeS, contentDetail2,
1449 screenShotCount++, renderer.getWidth(), renderer.getHeight() ) );
1450 }
1451 private int screenShotCount = 0;
1452
1453 /** Return the number of {@link #nextScreenshotFile(String, String, int, GLCapabilitiesImmutable, String)} calls. */
1454 public int getScreenshotCount() { return screenShotCount; }
1455
1456 public boolean isScreenshotSupported() { return null != screenshot; }
1457
1458 /**
1459 * Write current read drawable (screen) to a file.
1460 * <p>
1461 * Best to be {@link GLAutoDrawable#invoke(boolean, GLRunnable) invoked on the display call},
1462 * see {@link #screenshot(boolean, String)}.
1463 * </p>
1464 * @param gl current GL object
1465 * @param file the target file to be used, consider using {@link #nextScreenshotFile(String, String, int, GLCapabilitiesImmutable, String)}
1466 * @see #nextScreenshotFile(String, String, int, GLCapabilitiesImmutable, String)
1467 * @see #getScreenshotCount()
1468 * @see #screenshot(boolean, File)
1469 */
1470 public void screenshot(final GL gl, final File file) {
1471 if(null != screenshot && screenshot.readPixels(gl, false)) {
1472 screenshot.write(file);
1473 System.err.println("Wrote: "+file);
1474 }
1475 }
1476
1477 /**
1478 * Write current read drawable (screen) to a file on {@link GLAutoDrawable#invoke(boolean, GLRunnable) on the display call}.
1479 *
1480 * @param wait if true block until execution of screenshot {@link GLRunnable} is finished, otherwise return immediately w/o waiting
1481 * @param file the target file to be used, consider using {@link #nextScreenshotFile(String, String, int, GLCapabilitiesImmutable, String)}
1482 * @see #nextScreenshotFile(String, String, int, GLCapabilitiesImmutable, String)
1483 * @see #getScreenshotCount()
1484 * @see #screenshot(GL, File)
1485 */
1486 public void screenshot(final boolean wait, final File file) {
1487 if( null != cDrawable ) {
1488 cDrawable.invoke(wait, (drawable) -> {
1489 screenshot(drawable.getGL(), file);
1490 return true;
1491 });
1492 }
1493 }
1494
1495 /**
1496 * Default implementation of {@link Scene.PMVMatrixSetup},
1497 * implementing {@link Scene.PMVMatrixSetup#set(PMVMatrix4f, Recti)} as follows:
1498 * <ul>
1499 * <li>{@link GLMatrixFunc#GL_PROJECTION} Matrix
1500 * <ul>
1501 * <li>Identity</li>
1502 * <li>Perspective {@link #getAngle()} with {@link #getZNear()} and {@link #getZFar()}</li>
1503 * <li>Translated to given {@link #getSceneDist()}</li>
1504 * </ul></li>
1505 * <li>{@link GLMatrixFunc#GL_MODELVIEW} Matrix
1506 * <ul>
1507 * <li>identity</li>
1508 * </ul></li>
1509 * </ul>
1510 * </p>
1511 * @see DefaultPMVMatrixSetup#DefaultPMVMatrixSetup()
1512 * @see Scene#setPMVMatrixSetup(PMVMatrixSetup)
1513 * @see Scene.PMVMatrixSetup
1514 */
1515 public static class DefaultPMVMatrixSetup implements PMVMatrixSetup {
1516 /** Scene distance on z-axis to projection. */
1517 private final float scene_dist;
1518 /** Projection angle in radians. */
1519 private final float angle;
1520 /** Projection z-near value. */
1521 private final float zNear;
1522 /** Projection z-far value. */
1523 private final float zFar;
1524
1525 /**
1526 * Custom {@link DefaultPMVMatrixSetup} instance
1527 * @param scene_dist scene distance on z-axix
1528 * @param zNear projection z-near value
1529 * @param zFar projection z-far value
1530 * @param angle projection angle in radians
1531 * @see DefaultPMVMatrixSetup
1532 * @see Scene#setPMVMatrixSetup(PMVMatrixSetup)
1533 * @see Scene.PMVMatrixSetup
1534 */
1535 public DefaultPMVMatrixSetup(final float scene_dist, final float zNear, final float zFar, final float angle) {
1536 if( !( zNear > 0 && zFar > zNear ) ) {
1537 throw new IllegalArgumentException("zNear is "+zNear+", but must be > 0 and < zFar, zFar "+zFar);
1538 }
1539 this.scene_dist = scene_dist;
1540 this.zNear = zNear;
1541 this.zFar = zFar;
1542 this.angle = angle;
1543 }
1544 /**
1545 * Custom {@link DefaultPMVMatrixSetup} instance using given {@code scene_dist}, {@code zNear}, {@code zFar} and {@link Scene#DEFAULT_ANGLE}.
1546 * @param scene_dist scene distance on z-axix
1547 * @param zNear projection z-near value
1548 * @param zFar projection z-far value
1549 * @see DefaultPMVMatrixSetup
1550 * @see Scene#setPMVMatrixSetup(PMVMatrixSetup)
1551 * @see Scene.PMVMatrixSetup
1552 */
1553 public DefaultPMVMatrixSetup(final float scene_dist, final float zNear, final float zFar) {
1554 this(scene_dist, zNear, zFar, Scene.DEFAULT_ANGLE);
1555 }
1556 /**
1557 * Custom {@link DefaultPMVMatrixSetup} instance using given {@code scene_dist} and {@link Scene#DEFAULT_ZNEAR}, {@link Scene#DEFAULT_ZFAR}, {@link Scene#DEFAULT_ANGLE}.
1558 * @param scene_dist scene distance on z-axix
1559 * @see DefaultPMVMatrixSetup
1560 * @see Scene#setPMVMatrixSetup(PMVMatrixSetup)
1561 * @see Scene.PMVMatrixSetup
1562 */
1563 public DefaultPMVMatrixSetup(final float scene_dist) {
1565 }
1566 /**
1567 * Default {@link DefaultPMVMatrixSetup} instance using {@link Scene#DEFAULT_SCENE_DIST}, {@link Scene#DEFAULT_ZNEAR}, {@link Scene#DEFAULT_ZFAR}, {@link Scene#DEFAULT_ANGLE}.
1568 * @see DefaultPMVMatrixSetup
1569 * @see Scene#setPMVMatrixSetup(PMVMatrixSetup)
1570 * @see Scene.PMVMatrixSetup
1571 */
1574 }
1575
1576 @Override
1577 public void set(final PMVMatrix4f pmv, final Recti viewport) {
1578 final float ratio = (float) viewport.width() / (float) viewport.height();
1579 pmv.loadPIdentity();
1580 pmv.perspectiveP(angle, ratio, zNear, zFar);
1581 pmv.translateP(0f, 0f, scene_dist);
1582
1583 pmv.loadMvIdentity();
1584 }
1585
1586 @Override
1587 public void setPlaneBox(final AABBox planeBox, final PMVMatrix4f pmv, final Recti viewport) {
1588 final float orthoDist = -scene_dist;
1589 final Vec3f obj00Coord = new Vec3f();
1590 final Vec3f obj11Coord = new Vec3f();
1591
1592 winToPlaneCoord(pmv, viewport, zNear, zFar, viewport.x(), viewport.y(), orthoDist, obj00Coord);
1593 winToPlaneCoord(pmv, viewport, zNear, zFar, viewport.width(), viewport.height(), orthoDist, obj11Coord);
1594
1595 planeBox.setSize( obj00Coord, obj11Coord );
1596 }
1597
1598 @Override
1599 public float getSceneDist() { return scene_dist; }
1600 @Override
1601 public float getAngle() { return angle; }
1602 @Override
1603 public float getZNear() { return zNear; }
1604 @Override
1605 public float getZFar() { return zFar; }
1606 };
1607 private PMVMatrixSetup pmvMatrixSetup = new DefaultPMVMatrixSetup();
1608}
Abstract Outline shape representation define the method an OutlineShape(s) is bound and rendered.
Definition: Region.java:62
static String getRenderModeString(final int renderModes)
Returns a unique technical description string for renderModes as follows:
Definition: Region.java:251
final void enable(final GL2ES2 gl, final boolean enable)
Enabling or disabling the RenderState's current shader program.
final int getAAQuality()
Returns pass2 AA-quality rendering value for Graph Region AA render-modes: Region#VBAA_RENDERING_BIT.
final int getHeight()
Return height of current viewport.
final void setColorStatic(final Vec4f rgbaColor)
final PMVMatrix4f getMatrix()
Borrow the current PMVMatrix4f.
final void reshapeNotify(final int x, final int y, final int width, final int height)
No PMVMatrix4f operation is performed here.
final int getWidth()
Return width of current viewport.
final int setSampleCount(final int v)
Sets pass2 AA sample count clipped to the range [Region#MIN_AA_SAMPLE_COUNT..Region#MAX_AA_SAMPLE_COU...
static final GLCallback defaultBlendDisable
Default GL#GL_BLEND disable GLCallback, simply turning-off the GL#GL_BLEND state and turning-on depth...
final int setAAQuality(final int v)
Sets pass2 AA-quality rendering value clipped to the range [Region#MIN_AA_QUALITY....
static final GLCallback defaultBlendEnable
Default GL#GL_BLEND enable GLCallback, turning-off depth writing via GL#glDepthMask(boolean) if Rende...
final void init(final GL2ES2 gl)
Initialize shader and bindings for GPU based rendering bound to the given GL object's GLContext if no...
final int getSampleCount()
Returns pass2 AA sample count for Graph Region AA render-modes: VBAA_RENDERING_BIT or Region#MSAA_REN...
static RegionRenderer create()
Create a hardware accelerated RegionRenderer including its RenderState composition.
final Recti getViewport(final Recti target)
Copies the current Rect4i viewport in given target and returns it for chaining.
final void destroy(final GL2ES2 gl)
Deletes all ShaderPrograms and nullifies its references including RenderState#destroy(GL2ES2).
The RenderState is owned by RegionRenderer.
static final int BITHINT_BLENDING_ENABLED
Bitfield hint, if set stating enabled GL#GL_BLEND, otherwise disabled.
Graph based GLRegion Shape.
Definition: GraphShape.java:55
Group of Shapes, optionally utilizing a Group.Layout.
Definition: Group.java:61
Default implementation of Scene.PMVMatrixSetup, implementing Scene.PMVMatrixSetup#set(PMVMatrix4f,...
Definition: Scene.java:1515
float getAngle()
Returns fov projection angle in radians, shall be 0 for orthogonal projection.
Definition: Scene.java:1601
float getZFar()
Returns projection z-far value.
Definition: Scene.java:1605
void setPlaneBox(final AABBox planeBox, final PMVMatrix4f pmv, final Recti viewport)
Optional method to set the Scene#getBounds() AABBox, maybe a nop if not desired.
Definition: Scene.java:1587
DefaultPMVMatrixSetup(final float scene_dist, final float zNear, final float zFar, final float angle)
Custom DefaultPMVMatrixSetup instance.
Definition: Scene.java:1535
float getSceneDist()
Returns scene distance on z-axis to projection.
Definition: Scene.java:1599
DefaultPMVMatrixSetup()
Default DefaultPMVMatrixSetup instance using Scene#DEFAULT_SCENE_DIST, Scene#DEFAULT_ZNEAR,...
Definition: Scene.java:1572
DefaultPMVMatrixSetup(final float scene_dist, final float zNear, final float zFar)
Custom DefaultPMVMatrixSetup instance using given scene_dist, zNear, zFar and Scene#DEFAULT_ANGLE.
Definition: Scene.java:1553
DefaultPMVMatrixSetup(final float scene_dist)
Custom DefaultPMVMatrixSetup instance using given scene_dist and Scene#DEFAULT_ZNEAR,...
Definition: Scene.java:1563
float getZNear()
Returns projection z-near value.
Definition: Scene.java:1603
GraphUI Scene.
Definition: Scene.java:103
float getZEpsilon(final int zBits)
Return Z precision on using current getPMVMatrixSetup()'s PMVMatrixSetup#getSceneDist() z-position an...
Definition: Scene.java:810
void addShape(final Shape s)
Adds a Shape.
Definition: Scene.java:292
static final float DEFAULT_ACTIVE_ZOFFSET_SCALE
Default Z precision scale, i.e.
Definition: Scene.java:115
void addDisposeAction(final GLRunnable action)
Add a user one-time GLRunnable disposal action to an internal list, all invoked at {@Link dispose(GLA...
Definition: Scene.java:657
static final float DEFAULT_ACTIVE_TOPLEVEL_ZOFFSET_SCALE
Default Z precision scale, i.e.
Definition: Scene.java:117
synchronized void attachGLAutoDrawable(final GLAutoDrawable drawable)
Definition: Scene.java:243
final void setClearParams(final float[] clearColor, final int clearMask)
Sets the clear parameter for glClearColor(..) and glClear(..) to be issued at display(GLAutoDrawable)...
Definition: Scene.java:226
static final float DEFAULT_ZFAR
Default projection z-far value is {@value}.
Definition: Scene.java:111
float getActiveShapeZOffsetScale()
Returns the active Shape Z-Offset scale, defaults to DEFAULT_ACTIVE_ZOFFSET_SCALE.
Definition: Scene.java:932
int setSampleCount(final int v)
Sets RegionRenderer#setSampleCount(int).
Definition: Scene.java:380
boolean isScreenshotSupported()
Definition: Scene.java:1456
synchronized void detachInputListenerFrom(final GLWindow window)
Definition: Scene.java:267
void init(final GLAutoDrawable drawable)
Called by the drawable immediately after the OpenGL context is initialized.
Definition: Scene.java:412
float getActiveTopLevelZOffsetScale()
Returns the general top-level widget Z-Offset scale, defaults to DEFAULT_ACTIVE_ZOFFSET_SCALE.
Definition: Scene.java:937
Scene()
Create a new scene with an internally created RegionRenderer, a graph AA sample-count 4 and using Def...
Definition: Scene.java:177
int getSampleCount()
Returns RegionRenderer#getSampleCount().
Definition: Scene.java:375
RegionRenderer getRenderer()
Returns the associated RegionRenderer.
Definition: Scene.java:213
void screenshot(final GL gl, final File file)
Write current read drawable (screen) to a file.
Definition: Scene.java:1470
static final float DEFAULT_SCENE_DIST
Default scene distance on z-axis to projection is -1/5f.
Definition: Scene.java:105
Shape getShapeByID(final int id)
Definition: Scene.java:366
Shape removeShape(final Shape s)
Removes given shape, w/o Shape#destroy(GL2ES2, RegionRenderer).
Definition: Scene.java:297
List< Shape > getShapes()
Returns added Shapes.
Definition: Scene.java:286
final void setPMvCullingEnabled(final boolean v)
Enable or disable Project-Modelview (PMv) frustum culling per Shape for this container.
Definition: Scene.java:235
int setAAQuality(final int v)
Sets RegionRenderer#setAAQuality(int).
Definition: Scene.java:388
final PMVMatrixSetup getPMVMatrixSetup()
Return the default or setPMVMatrixSetup(PMVMatrixSetup) PMVMatrixSetup.
Definition: Scene.java:749
static void winToPlaneCoord(final PMVMatrix4f pmv, final Recti viewport, final float zNear, final float zFar, final float winX, final float winY, final float objOrthoZ, final Vec3f objPos)
Definition: Scene.java:826
Scene(final int sampleCount)
Create a new scene with an internally created RegionRenderer, using DefaultPMVMatrixSetup#DefaultPMVM...
Definition: Scene.java:189
void dispose(final GLAutoDrawable drawable)
Disposes all added Shapes.
Definition: Scene.java:610
void removeShapes(final GL2ES2 gl, final RegionRenderer renderer, final Collection<? extends Shape > shapes)
Removes all given shapes with Shape#destroy(GL2ES2, RegionRenderer).
Definition: Scene.java:333
Scene(final RegionRenderer renderer)
Create a new scene taking ownership of the given RegionRenderer, using DefaultPMVMatrixSetup#DefaultP...
Definition: Scene.java:200
boolean contains(final Shape s)
Definition: Scene.java:355
void waitUntilDisplayed()
Blocks until first display(GLAutoDrawable) has completed after construction or dispose(GLAutoDrawable...
Definition: Scene.java:589
final boolean isOutside(final PMVMatrix4f pmv, final Shape shape)
Returns whether the given Shape is completely outside of this container.
Definition: Scene.java:471
void setupMatrix(final PMVMatrix4f pmv)
Setup PMVMatrix4f GLMatrixFunc#GL_PROJECTION and GLMatrixFunc#GL_MODELVIEW using implicit getViewport...
Definition: Scene.java:769
void setupMatrix(final PMVMatrix4f pmv, final Recti viewport)
Setup PMVMatrix4f GLMatrixFunc#GL_PROJECTION and GLMatrixFunc#GL_MODELVIEW by calling getPMVMatrixSet...
Definition: Scene.java:760
final void setPMVMatrixSetup(final PMVMatrixSetup setup)
Set a custom PMVMatrixSetup.
Definition: Scene.java:752
final Recti getViewport(final Recti target)
Copies the current int[4] viewport in given target and returns it for chaining.
Definition: Scene.java:775
void removeAllShapes(final GL2ES2 gl, final RegionRenderer renderer)
Removes all contained shapes with Shape#destroy(GL2ES2, RegionRenderer).
Definition: Scene.java:343
AABBox getBounds()
Describing the scene's object model-dimensions of the plane at scene-distance covering the visible vi...
Definition: Scene.java:803
void removeAllShapes(final GL2ES2 gl)
Removes all given shapes and destroys them, convenient call for removeAllShapes(GL2ES2,...
Definition: Scene.java:350
int getWidth()
Returns the getViewport()'s width, set after initial reshape(GLAutoDrawable, int, int,...
Definition: Scene.java:781
void setActiveTopLevelZOffsetScale(final float v)
Sets the general top-level widget Z-Offset scale, defaults to DEFAULT_ACTIVE_TOPLEVEL_ZOFFSET_SCALE.
Definition: Scene.java:939
void removeShapes(final Collection<? extends Shape > shapes)
Removes all given shapes, w/o Shape#destroy(GL2ES2, RegionRenderer).
Definition: Scene.java:306
final float[] getClearColor()
Returns the glClearColor(..) arguments, see setClearParams(float[], int).
Definition: Scene.java:229
void addGLEventListener(final GLEventListener listener)
Definition: Scene.java:440
PMVMatrix4f getMatrix()
Borrow the current PMVMatrix4f.
Definition: Scene.java:786
List< Shape > getRenderedShapes()
Returns added shapes which are rendered and sorted by z-axis in ascending order toward z-near.
Definition: Scene.java:289
static final float DEFAULT_Z16_EPSILON
Default Z precision on 16-bit depth buffer using DEFAULT_SCENE_DIST z-position and DEFAULT_ZNEAR.
Definition: Scene.java:113
void pickShapeGL(final int glWinX, final int glWinY, final Vec3f objPos, final Shape[] shape, final Runnable runnable)
Attempt to pick a Shape using the OpenGL false color rendering.
Definition: Scene.java:1007
static float getZEpsilon(final int zBits, final PMVMatrixSetup setup)
Default Z precision on 16-bit depth buffer using -1 z-position and DEFAULT_ZNEAR.
Definition: Scene.java:127
static final float DEFAULT_ANGLE
Default projection angle in radians is PI/4, i.e.
Definition: Scene.java:107
Shape getShapeByName(final String name)
Definition: Scene.java:370
void surfaceToPlaneSize(final Recti viewport, final float zNear, final float zFar, final float objOrthoDist, final Vec2f objSceneSize)
Map given window surface-size to object coordinates relative to this scene using the give projection ...
Definition: Scene.java:843
AABBox getBounds(final PMVMatrix4f pmv, final Shape shape)
Returns AABBox dimension of given Shape from this container's perspective, i.e.
Definition: Scene.java:683
final Shape getActiveShape()
Definition: Scene.java:867
int getHeight()
Returns the getViewport()'s height, set after initial reshape(GLAutoDrawable, int,...
Definition: Scene.java:783
synchronized void attachInputListenerTo(final GLWindow window)
Definition: Scene.java:251
Recti getViewport()
Borrows the current int[4] viewport w/o copying.
Definition: Scene.java:778
final boolean isCullingEnabled()
Return whether Project-Modelview (PMv) frustum culling or Group's Modelview (Mv) frustum clipping is ...
Definition: Scene.java:241
boolean removeShape(final GL2ES2 gl, final RegionRenderer renderer, final Shape s)
Removes given shape with Shape#destroy(GL2ES2, RegionRenderer), if contained.
Definition: Scene.java:313
synchronized void detachGLAutoDrawable(final GLAutoDrawable drawable)
Definition: Scene.java:246
boolean removeShape(final GL2ES2 gl, final Shape s)
Removes given shape and destroy it, if contained - convenient call for removeShape(GL2ES2,...
Definition: Scene.java:323
void removeShapes(final GL2ES2 gl, final Collection<? extends Shape > shapes)
Removes all given shapes and destroys them, convenient call for removeShape(GL2ES2,...
Definition: Scene.java:339
boolean invoke(final boolean wait, final GLRunnable glRunnable)
Enqueues a one-shot GLRunnable, which will be executed within the next GLAutoDrawable#display() call ...
Definition: Scene.java:433
boolean isOutside2(final Matrix4f mvCont, final Shape shape, final PMVMatrix4f pmvShape)
Returns whether the given Shape is completely outside of this container.
Definition: Scene.java:483
Shape getShapeByIdx(final int id)
Definition: Scene.java:359
static final float DEFAULT_ZNEAR
Default projection z-near value is {@value}.
Definition: Scene.java:109
int getScreenshotCount()
Return the number of nextScreenshotFile(String, String, int, GLCapabilitiesImmutable,...
Definition: Scene.java:1454
void winToShapeCoord(final Shape shape, final int glWinX, final int glWinY, final PMVMatrix4f pmv, final Vec3f objPos, final Runnable runnable)
Calling Shape#winToObjCoord(Scene, int, int, float[]), retrieving its Shape object position.
Definition: Scene.java:669
Shape pickShape(final PMVMatrix4f pmv, final Ray ray, final int glWinX, final int glWinY, final Vec3f objPos, final Shape.Visitor1 visitor)
Attempt to pick a Shape using the window coordinates and contained {@ling Shape}'s AABBox bounds usin...
Definition: Scene.java:1120
void display(final GLAutoDrawable drawable)
Called by the drawable to initiate OpenGL rendering by the client.
Definition: Scene.java:492
void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height)
Reshape scene using setupMatrix(PMVMatrix4f, int, int, int, int) using PMVMatrixSetup.
Definition: Scene.java:463
void setSharpness(final float sharpness)
Definition: Scene.java:390
final int getClearMask()
Returns the glClear(..) mask, see setClearParams(float[], int).
Definition: Scene.java:232
int getAAQuality()
Returns RegionRenderer#getAAQuality().
Definition: Scene.java:383
final boolean isPMvCullingEnabled()
Return whether Project-Modelview (PMv) frustum culling is enabled for this container.
Definition: Scene.java:238
void addShapes(final Collection<? extends Shape > shapes)
Definition: Scene.java:327
String getStatusText(final GLAutoDrawable glad, final int renderModes, final float dpi)
Return a formatted status string containing avg fps and avg frame duration.
Definition: Scene.java:1388
File nextScreenshotFile(final String dir, final String prefix, final int renderModes, final GLCapabilitiesImmutable caps, final String contentDetail)
Return the unique next technical screenshot PNG File instance as follows:
Definition: Scene.java:1441
void setActiveShapeZOffsetScale(final float v)
Sets the active Shape Z-Offset scale, defaults to DEFAULT_ACTIVE_ZOFFSET_SCALE.
Definition: Scene.java:934
void removeGLEventListener(final GLEventListener listener)
Definition: Scene.java:445
int getShapeCount()
Returns number of Shapes, see getShapes().
Definition: Scene.java:283
static String getStatusText(final FPSCounter fpsCounter)
Return a formatted status string containing avg fps and avg frame duration.
Definition: Scene.java:1417
void surfaceToPlaneSize(final Recti viewport, final Vec2f objSceneSize)
Map given window surface-size to object coordinates relative to this scene using the default PMVMatri...
Definition: Scene.java:863
void screenshot(final boolean wait, final File file)
Write current read drawable (screen) to a file on on the display call.
Definition: Scene.java:1486
Generic Shape, potentially using a Graph via GraphShape or other means of representing content.
Definition: Shape.java:87
void draw(final GL2ES2 gl, final RegionRenderer renderer)
Renders the shape.
Definition: Shape.java:798
final Shape setDiscarded(final boolean v)
Set whether this shape is discarded in last draw(GL2ES2, RegionRenderer), i.e.
Definition: Shape.java:1735
final Vec3f winToShapeCoord(final PMVMatrix4f pmv, final Recti viewport, final int glWinX, final int glWinY, final Vec3f objPos)
Map given gl-window-coordinates to object coordinates relative to this shape and its z-coordinate.
Definition: Shape.java:1305
final void clear(final GL2ES2 gl, final RegionRenderer renderer)
Clears all data and reset all states as if this instance was newly created.
Definition: Shape.java:425
final void markStateDirty()
Marks the rendering state dirty, causing next draw() to notify the Graph region to reselect shader an...
Definition: Shape.java:696
static Comparator< Shape > ZAscendingComparator
Definition: Shape.java:2287
final AABBox getBounds()
Returns the unscaled bounding AABBox for this shape, borrowing internal instance.
Definition: Shape.java:732
final boolean isVisible()
Returns true if this shape is set visible by the user, otherwise false.
Definition: Shape.java:353
void drawToSelect(final GL2ES2 gl, final RegionRenderer renderer)
Experimental selection draw command used by Scene.
Definition: Shape.java:783
final void markShapeDirty()
Marks the shape dirty, causing next draw() to recreate the Graph shape and reset the region.
Definition: Shape.java:688
final void destroy(final GL2ES2 gl, final RegionRenderer renderer)
Destroys all data.
Definition: Shape.java:457
final void applyMatToMv(final PMVMatrix4f pmv)
Applies the internal Matrix4f to the given modelview matrix, i.e.
Definition: Shape.java:908
final boolean isInteractive()
Returns if this shape allows user interaction in general, see setInteractive(boolean).
Definition: Shape.java:1717
final boolean setActive(final boolean v, final float zOffset)
Definition: Shape.java:1612
A HUD tooltip for Shape, see Shape#setToolTip(Tooltip).
Definition: Tooltip.java:44
Basic Float math utility functions.
Definition: FloatUtil.java:83
static float getOrthoWinZ(final float orthoZ, final float zNear, final float zFar)
Returns orthogonal distance (1f/zNear-1f/orthoZ) / (1f/zNear-1f/zFar);.
static float getZBufferEpsilon(final int zBits, final float z, final float zNear)
Returns resolution of Z buffer of given parameter, see Love Your Z-Buffer.
static final float QUARTER_PI
The value PI/4, i.e.
Basic 4x4 float matrix implementation using fields for intensive use-cases (host operations).
Definition: Matrix4f.java:89
Simple compound denoting a ray.
Definition: Ray.java:49
Rectangle with x, y, width and height integer components.
Definition: Recti.java:34
2D Vector based upon two float components.
Definition: Vec2f.java:37
void set(final Vec2f o)
this = o, returns this.
Definition: Vec2f.java:73
3D Vector based upon three float components.
Definition: Vec3f.java:37
Axis Aligned Bounding Box.
Definition: AABBox.java:54
final AABBox setSize(final float[] low, final float[] high)
Set size of the AABBox specifying the coordinates of the low and high.
Definition: AABBox.java:173
final boolean isOutside(final AABBox box)
Returns whether the given AABBox is completely outside of this frustum.
Definition: Frustum.java:424
PMVMatrix4f implements the basic computer graphics Matrix4f pack using projection (P),...
final boolean mapWinToRay(final float winx, final float winy, final float winz0, final float winz1, final Recti viewport, final Ray ray)
Map two window coordinates w/ shared X/Y and distinctive Z to a Ray.
final Matrix4f getMv()
Returns the modelview matrix (Mv).
final Frustum getFrustum()
Returns the frustum, derived from projection x modelview.
final PMVMatrix4f popMv()
Pop the modelview matrix from its stack.
final boolean mapWinToObj(final float winx, final float winy, final float winz, final Recti viewport, final Vec3f objPos)
Map window coordinates to object coordinates.
final PMVMatrix4f pushMv()
Push the modelview matrix to its stack, while preserving its values.
boolean isWithinGesture()
Returns true if within a gesture as detected by a previous process(InputEvent) command,...
An implementation of GLAutoDrawable and Window interface, using a delegated Window instance,...
Definition: GLWindow.java:121
final void removeGestureListener(final GestureHandler.GestureListener gl)
Removes the given GestureHandler.GestureListener from the list.
Definition: GLWindow.java:980
final void addGestureHandler(final GestureHandler gh)
Appends the given GestureHandler to the end of the list.
Definition: GLWindow.java:960
final void addMouseListener(final MouseListener l)
Appends the given MouseListener to the end of the list.
Definition: GLWindow.java:927
final void addGestureListener(final GestureHandler.GestureListener gl)
Appends the given GestureHandler.GestureListener to the end of the list.
Definition: GLWindow.java:972
final void addKeyListener(final KeyListener l)
Appends the given com.jogamp.newt.event.KeyListener to the end of the list.
Definition: GLWindow.java:902
final void removeKeyListener(final KeyListener l)
Definition: GLWindow.java:912
final void removeMouseListener(final MouseListener l)
Removes the given MouseListener from the list.
Definition: GLWindow.java:937
final void removeGestureHandler(final GestureHandler gh)
Removes the given GestureHandler from the list.
Definition: GLWindow.java:968
Utility to read out the current FB to TextureData, optionally writing the data back to a texture obje...
void write(final File dest)
Write the TextureData filled by readPixels(GLAutoDrawable, boolean) to file.
boolean readPixels(final GL gl, final boolean mustFlipVertically)
Read the drawable's pixels to TextureData and Texture, if requested at construction.
Container interface of UI Shapes.
Definition: Container.java:44
Interface providing a method to setup PMVMatrix4f's GLMatrixFunc#GL_PROJECTION and GLMatrixFunc#GL_MO...
Definition: Scene.java:713
float getSceneDist()
Returns scene distance on z-axis to projection.
float getZFar()
Returns projection z-far value.
void set(PMVMatrix4f pmv, Recti viewport)
Setup PMVMatrix4f's GLMatrixFunc#GL_PROJECTION and GLMatrixFunc#GL_MODELVIEW.
void setPlaneBox(final AABBox planeBox, final PMVMatrix4f pmv, Recti viewport)
Optional method to set the Scene#getBounds() AABBox, maybe a nop if not desired.
float getZNear()
Returns projection z-near value.
float getAngle()
Returns fov projection angle in radians, shall be 0 for orthogonal projection.
General Shape visitor.
Definition: Shape.java:91
int getAlphaBits()
Returns the number of bits for the color buffer's alpha component.
FPSCounter feature.
Definition: FPSCounter.java:37
A higher-level abstraction than GLDrawable which supplies an event based mechanism (GLEventListener) ...
boolean invoke(boolean wait, GLRunnable glRunnable)
Enqueues a one-shot GLRunnable, which will be executed within the next display() call after all regis...
GLAnimatorControl getAnimator()
GL getGL()
Returns the GL pipeline object this GLAutoDrawable uses.
void addGLEventListener(GLEventListener listener)
Adds the given listener to the end of this drawable queue.
GLEventListener removeGLEventListener(GLEventListener listener)
Removes the given listener from this drawable queue.
GL getGL()
Casts this object to the GL interface.
GL2ES2 getGL2ES2()
Casts this object to the GL2ES2 interface.
int getSwapInterval()
Return the current swap interval.
Specifies an immutable set of OpenGL capabilities.
int getNumSamples()
Returns the number of sample buffers to be allocated if sample buffers are enabled,...
GLCapabilitiesImmutable getChosenGLCapabilities()
Fetches the GLCapabilitiesImmutable corresponding to the chosen OpenGL capabilities (pixel format / v...
NativeSurface getNativeSurface()
Returns the associated NativeSurface of this NativeSurfaceHolder.
Declares events which client code can use to manage OpenGL rendering into a GLAutoDrawable.
static final int GL_COLOR_BUFFER_BIT
GL_ES_VERSION_2_0, GL_VERSION_1_1, GL_VERSION_1_0, GL_VERSION_ES_1_0 Define "GL_COLOR_BUFFER_BIT" wit...
Definition: GL.java:390
void glClearColor(float red, float green, float blue, float alpha)
Entry point to C language function: void {@native glClearColor}(GLfloat red, GLfloat green,...
void glClear(int mask)
Entry point to C language function: void {@native glClear}(GLbitfield mask) Part of GL_ES_VERSION_...
static final int GL_DEPTH_BUFFER_BIT
GL_ES_VERSION_2_0, GL_VERSION_1_1, GL_VERSION_1_0, GL_VERSION_ES_1_0 Define "GL_DEPTH_BUFFER_BIT" wit...
Definition: GL.java:738