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