From c1531c3d99b19032040018b9414263b0d3000147 Mon Sep 17 00:00:00 2001 From: Sven Göthel Date: Sat, 20 Jan 2024 05:01:38 +0100 Subject: Graph Clipping: Use Frustum Clipping using AABBox -> Mv transformed Cube -> Frustum mapping + GraphUI Support AABBox clipping naturally couldn't be transformed into 3D Model-View (Mv) Space, as it is axis aligned and only provided 2 points (min/max). Therefor we map the Group's AABBox to a 8-point Cube, perform the Mv-transformation and then produce the 6-plane Frustum. As before, we cull fully outside shapes within the Group's draw method and perform fragment clipping with same Frustum planes in the shader. With clipping enabled, the 3D z-axis getBounds() depth will be slightly increased for functional Frustum operation. This is also done for setFixedSize(Vec2f). The Frustum planes are copied to the Graph shader via float[4*6] -> uniform vec4 gcu_ClipFrustum[6]; // L, R, B, T, N, F each {n.x, n.y, n.z, d} +++ Concludes related work of below commits - 1040bed4ecc6f4598ea459f1073a9240583fc3c3 - 5cca51e32999a882e2a5f00cb45ecafc824ffd86 --- src/graphui/classes/com/jogamp/graph/ui/Group.java | 111 +++++++++++++++------ src/graphui/classes/com/jogamp/graph/ui/Scene.java | 4 +- .../com/jogamp/graph/ui/widgets/RangedGroup.java | 20 ++-- 3 files changed, 97 insertions(+), 38 deletions(-) (limited to 'src/graphui/classes/com') diff --git a/src/graphui/classes/com/jogamp/graph/ui/Group.java b/src/graphui/classes/com/jogamp/graph/ui/Group.java index 1202752b1..d1156120a 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/Group.java +++ b/src/graphui/classes/com/jogamp/graph/ui/Group.java @@ -42,6 +42,8 @@ import com.jogamp.math.Vec2f; import com.jogamp.math.Vec3f; import com.jogamp.math.Vec4f; import com.jogamp.math.geom.AABBox; +import com.jogamp.math.geom.Cube; +import com.jogamp.math.geom.Frustum; import com.jogamp.math.util.PMVMatrix4f; import com.jogamp.opengl.GL2ES2; import com.jogamp.opengl.GLProfile; @@ -77,14 +79,15 @@ public class Group extends Shape implements Container { } private final List shapes = new CopyOnWriteArrayList(); - private final Vec2f fixedSize = new Vec2f(); + /** Enforced fixed size. In case z-axis is NaN, its 3D z-axis will be adjusted. */ + private final Vec3f fixedSize = new Vec3f(); private Layout layouter; private Rectangle border = null; private boolean relayoutOnDirtyShapes = true; private boolean widgetMode = false; private boolean clipOnBounds = false; - private AABBox clipBBox = null; + private Frustum clipFrustum = null; /** * Create a group of {@link Shape}s w/o {@link Group.Layout}. @@ -118,43 +121,65 @@ public class Group extends Shape implements Container { /** Set {@link Group.Layout}. */ public Group setLayout(final Layout l) { layouter = l; return this; } - /** Enforce size of this group to given dimension. */ - public Group setFixedSize(final Vec2f v) { fixedSize.set(v); return this; } - public Vec2f getFixedSize() { return fixedSize; } + /** Enforce size of this group for all given 3 dimensions {@link #getBounds()} without adjusting 3D z-axis like {@link #setFixedSize(Vec2f)}. */ + public Group setFixedSize(final Vec3f v) { fixedSize.set(v); return this; } + /** + * Enforce size of this group to given 2 dimensions, + * adjusting the 3D z-axis {@link #getBounds()} giving room for potential clipping via {@link #setClipOnBounds(boolean)} or {@link #setClipFrustum(Frustum)}. + * @see #setFixedSize(Vec3f) + */ + public Group setFixedSize(final Vec2f v) { fixedSize.set(v.x(), v.y(), Float.NaN); return this; } + /** Returns borrowed fixed size instance, see {@link #setFixedSize(Vec3f)} and {@link #setFixedSize(Vec2f)}. */ + public Vec3f getFixedSize() { return fixedSize; } + /** Returns given {@link Vec2f} instance set with 2 dimensions, see {@link #setFixedSize(Vec2f)}. */ + public Vec2f getFixedSize(final Vec2f out) { out.set(fixedSize.x(), fixedSize.y()); return out; } /** - * Enable {@link AABBox} clipping on {@link #getBounds()} for this group and its shapes as follows + * Enable {@link Frustum} clipping on {@link #getBounds()} for this group and its shapes as follows *
    *
  • Discard {@link Shape} {@link #draw(GL2ES2, RegionRenderer) rendering} if not intersecting {@code clip-box}.
  • *
  • Otherwise perform pixel-accurate clipping inside the shader to {@code clip-box}.
  • *
*

- * {@link #setClipBBox(AABBox)} takes precedence over {@link #setClipOnBounds(boolean)}. + * {@link #setClipFrustum(Frustum)} takes precedence over {@link #setClipOnBounds(boolean)}. + *

+ *

+ * With clipping enabled, the 3D z-axis {@link #getBounds()} depth + * will be slightly increased for functional {@link Frustum} operation. *

* @param v boolean to toggle clipping * @return this instance for chaining - * @see #setClipBBox(AABBox) + * @see #setClipFrustum(Frustum) + * @see #setFixedSize(Vec2f) + * @see #setFixedSize(Vec3f) */ public Group setClipOnBounds(final boolean v) { clipOnBounds = v; return this; } /** Returns {@link #setClipOnBounds(boolean)} value */ public boolean getClipOnBounds() { return clipOnBounds; } /** - * Enable {@link AABBox} clipping on explicit given pre-multiplied Mv-matrix {@code clip-box} as follows + * Enable {@link Frustum} clipping on explicit given pre-multiplied w/ Mv-matrix {@code clip-box} + * for this group and its shapes as follows *
    *
  • Discard {@link Shape} {@link #draw(GL2ES2, RegionRenderer) rendering} if not intersecting {@code clip-box}.
  • *
  • Otherwise perform pixel-accurate clipping inside the shader to {@code clip-box}.
  • *
*

- * {@link #setClipBBox(AABBox)} takes precedence over {@link #setClipOnBounds(boolean)}. + * {@link #setClipFrustum(Frustum)} takes precedence over {@link #setClipOnBounds(boolean)}. + *

+ *

+ * With clipping enabled, the 3D z-axis {@link #getBounds()} depth + * will be slightly increased for functional {@link Frustum} operation. *

- * @param v {@link AABBox} pre-multiplied Mv-matrix + * @param v {@link Frustum} pre-multiplied w/ Mv-matrix * @return this instance for chaining * @see #setClipOnBounds(boolean) + * @see #setFixedSize(Vec2f) + * @see #setFixedSize(Vec3f) */ - public Group setClipBBox(final AABBox v) { clipBBox = v; return this; } - /** Returns {@link #setClipBBox(AABBox)} value */ - public AABBox getClipBBox() { return clipBBox; } + public Group setClipFrustum(final Frustum v) { clipFrustum = v; return this; } + /** Returns {@link #setClipFrustum(Frustum)} value */ + public Frustum getClipFrustum() { return clipFrustum; } @Override public int getShapeCount() { return shapes.size(); } @@ -281,12 +306,12 @@ public class Group extends Shape implements Container { final Object[] shapesS = shapes.toArray(); Arrays.sort(shapesS, (Comparator)Shape.ZAscendingComparator); - final boolean useClipBBox = null != clipBBox; - if( useClipBBox || clipOnBounds ) { - final AABBox origClipBox = renderer.getClipBBox(); + final boolean useClipFrustum = null != clipFrustum; + if( useClipFrustum || clipOnBounds ) { + final Frustum origClipFrustum = renderer.getClipFrustum(); - final AABBox clipBox = useClipBBox ? clipBBox : box.transform(pmv.getMv(), tempBB0); - renderer.setClipBBox( tempBB1.set(clipBox) ); // Mv pre-multiplied AABBox + final Frustum frustumMv = useClipFrustum ? clipFrustum : tempC00.set( box ).transform( pmv.getMv() ).updateFrustumPlanes(tempF00); + renderer.setClipFrustum( frustumMv ); final int shapeCount = shapesS.length; for(int i=0; i