From 5f9fb7159fa33bc979e5050d384b6939658049bd Mon Sep 17 00:00:00 2001 From: Sven Göthel Date: Mon, 22 Jan 2024 06:35:25 +0100 Subject: Bug 1489 - GraphUI Group: Resolve Performance Regression in Scene.pickShape(): Drop invisible and clipped shapes After implementing Bug 1487 (Frustum Clipping/Culling) and using thousands of shapes within one Group mostly culled (outside of frustum), overall mouse Scene.pickShape() caused tremendous lagging. This is caused by Scene.pickShape() traversing through _all_ shapes, rendered ones, invisible ones and culled ones. +++ Solution is to have Scene and Group provide a pre-sorted list of actually rendered shapes, i.e. isVisible() and not culled. Scene.pickShape() can now use this reduced and pre-sorted list reducing the load considerably. +++ Further - cleanup TreeTool - rename Container methods: -- setFrustumCullingEnabled() -> setPMvCullingEnabled() -- isFrustumCullingEnabled() -> isPMvCullingEnabled() - supply Container with -- isCullingEnabled() -- List getRenderedShapes() -- isOutside() -- isOutside2() -- forAllRendered() --- src/graphui/classes/jogamp/graph/ui/TreeTool.java | 103 +++++++++++++++------- 1 file changed, 72 insertions(+), 31 deletions(-) (limited to 'src/graphui/classes/jogamp') diff --git a/src/graphui/classes/jogamp/graph/ui/TreeTool.java b/src/graphui/classes/jogamp/graph/ui/TreeTool.java index c37cd53d8..1a12ff461 100644 --- a/src/graphui/classes/jogamp/graph/ui/TreeTool.java +++ b/src/graphui/classes/jogamp/graph/ui/TreeTool.java @@ -36,24 +36,27 @@ import com.jogamp.graph.ui.Scene; import com.jogamp.graph.ui.Shape; import com.jogamp.graph.ui.Shape.Visitor1; import com.jogamp.graph.ui.Shape.Visitor2; +import com.jogamp.math.Matrix4f; import com.jogamp.math.util.PMVMatrix4f; /** Generic static {@link Shape} tree traversal tools, utilized by {@link Scene} and {@link Container} implementations. */ public class TreeTool { /** - * Traverses through the graph up until {@code shape} and apply {@code action} on it. + * Traverses through the graph up until {@code shape} of {@link Container#getShapes()} and apply {@code action} on it. * @param pmv * @param shape * @param action * @return true to signal operation complete, i.e. {@code shape} found, otherwise false */ - public static boolean forOne(final List shapes, final PMVMatrix4f pmv, final Shape shape, final Runnable action) { - for(int i=0; i shapes = cont.getShapes(); + final int shapeCount = shapes.size(); + for(int i=0; i shapes, final Visitor1 v) { + public static boolean forAll(final Container cont, final Visitor1 v) { + final List shapes = cont.getShapes(); + final int shapeCount = shapes.size(); boolean res = false; - for(int i=0; !res && i shapes, final PMVMatrix4f pmv, final Visitor2 v) { + public static boolean forAll(final Container cont, final PMVMatrix4f pmv, final Visitor2 v) { + final List shapes = cont.getShapes(); + final int shapeCount = shapes.size(); boolean res = false; - for(int i=0; !res && i * Each {@link Container} level is sorted using {@code sortComp} + *

+ * @param cont container of the shapes * @param sortComp * @param pmv * @param v * @return true to signal operation complete and to stop traversal, i.e. {@link Visitor2#visit(Shape, PMVMatrix4f)} returned true, otherwise false */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - public static boolean forSortedAll(final Comparator sortComp, final List shapes, final PMVMatrix4f pmv, final Visitor2 v) { - final Object[] shapesS = shapes.toArray(); - Arrays.sort(shapesS, (Comparator)sortComp); + public static boolean forSortedAll(final Container cont, final Comparator sortComp, final PMVMatrix4f pmv, final Visitor2 v) { + final List shapes = cont.getShapes(); + final int shapeCount = shapes.size(); + final Shape[] shapesS = shapes.toArray(new Shape[shapeCount]); + Arrays.sort(shapesS, sortComp); + boolean res = false; + + for(int i=0; !res && i + * Each {@link Container} level is sorted using {@code sortComp} + *

+ * @param cont container of the shapes + * @param pmv + * @param v + * @return true to signal operation complete and to stop traversal, i.e. {@link Visitor2#visit(Shape, PMVMatrix4f)} returned true, otherwise false + */ + public static boolean forAllRendered(final Container cont, final PMVMatrix4f pmv, final Visitor2 v) { + final List shapes = cont.getRenderedShapes(); boolean res = false; - for(int i=0; !res && i shapes, final Shape s) { + public static boolean contains(final Container cont, final Shape s) { + final List shapes = cont.getShapes(); if( shapes.contains(s) ) { return true; } for(final Shape shape : shapes) { if( shape instanceof Container ) { - if( ((Container)shape).contains(s) ) { + if( contains((Container)shape, s) ) { return true; } } @@ -156,9 +197,9 @@ public class TreeTool { return false; } - public static Shape getShapeByID(final List shapes, final int id) { + public static Shape getShapeByID(final Container cont, final int id) { final Shape[] res = { null }; - forAll(shapes, (final Shape s) -> { + forAll(cont, (final Shape s) -> { if( s.getID() == id ) { res[0] = s; return true; @@ -168,9 +209,9 @@ public class TreeTool { }); return res[0]; } - public static Shape getShapeByName(final List shapes, final String name) { + public static Shape getShapeByName(final Container cont, final String name) { final Shape[] res = { null }; - forAll(shapes, (final Shape s) -> { + forAll(cont, (final Shape s) -> { if( s.getName().equals(name) ) { res[0] = s; return true; -- cgit v1.2.3