|
58 | 58 | import java.nio.FloatBuffer;
|
59 | 59 | import java.util.ArrayList;
|
60 | 60 | import java.util.Arrays;
|
| 61 | +import java.util.function.BiFunction; |
61 | 62 |
|
62 | 63 | public class InstancedGeometry extends Geometry {
|
63 | 64 |
|
64 | 65 | private static final int INSTANCE_SIZE = 16;
|
65 | 66 |
|
| 67 | + private static BiFunction<Camera, Geometry, Boolean> instanceCullingFunction = new DefaultInstanceCullingFunction(); |
| 68 | + |
66 | 69 | private VertexBuffer[] globalInstanceData;
|
67 | 70 | private VertexBuffer transformInstanceData;
|
68 | 71 | private Geometry[] geometries = new Geometry[1];
|
@@ -95,6 +98,22 @@ public InstancedGeometry(String name) {
|
95 | 98 | setMaxNumInstances(1);
|
96 | 99 | }
|
97 | 100 |
|
| 101 | + /** |
| 102 | + * Set the function used for culling instances from being rendered. |
| 103 | + * Default is {@link DefaultInstanceCullingFunction}. |
| 104 | + */ |
| 105 | + public static void setInstanceCullingFunction(BiFunction<Camera, Geometry, Boolean> instanceCullingFunction) { |
| 106 | + InstancedGeometry.instanceCullingFunction = instanceCullingFunction; |
| 107 | + } |
| 108 | + |
| 109 | + /** |
| 110 | + * @return The instance culling function or null if there isn't any. |
| 111 | + * Default is {@link DefaultInstanceCullingFunction}. |
| 112 | + */ |
| 113 | + public static BiFunction<Camera, Geometry, Boolean> getInstanceCullingFunction() { |
| 114 | + return instanceCullingFunction; |
| 115 | + } |
| 116 | + |
98 | 117 | /**
|
99 | 118 | * Global user specified per-instance data.
|
100 | 119 | *
|
@@ -284,14 +303,9 @@ public void updateInstances() {
|
284 | 303 | }
|
285 | 304 | }
|
286 | 305 |
|
287 |
| - if (cam != null) { |
288 |
| - BoundingVolume bv = geom.getWorldBound(); |
289 |
| - int save = cam.getPlaneState(); |
290 |
| - cam.setPlaneState(0); |
291 |
| - FrustumIntersect intersect = cam.contains(bv); |
292 |
| - cam.setPlaneState(save); |
293 |
| - |
294 |
| - if (intersect == FrustumIntersect.Outside) { |
| 306 | + if (cam != null && instanceCullingFunction != null) { |
| 307 | + boolean culled = instanceCullingFunction.apply(cam, geom); |
| 308 | + if (culled) { |
295 | 309 | numCulledGeometries++;
|
296 | 310 | continue;
|
297 | 311 | }
|
@@ -458,4 +472,22 @@ protected void cleanup() {
|
458 | 472 | allInstanceData = null;
|
459 | 473 | geometries = null;
|
460 | 474 | }
|
| 475 | + |
| 476 | + /** |
| 477 | + * By default, it checks if geometry is in camera frustum and culls it |
| 478 | + * if it is outside camera view. |
| 479 | + */ |
| 480 | + public static class DefaultInstanceCullingFunction implements BiFunction<Camera, Geometry, Boolean> { |
| 481 | + |
| 482 | + @Override |
| 483 | + public Boolean apply(Camera cam, Geometry geom) { |
| 484 | + BoundingVolume bv = geom.getWorldBound(); |
| 485 | + int save = cam.getPlaneState(); |
| 486 | + cam.setPlaneState(0); |
| 487 | + FrustumIntersect intersect = cam.contains(bv); |
| 488 | + cam.setPlaneState(save); |
| 489 | + |
| 490 | + return intersect == FrustumIntersect.Outside; |
| 491 | + } |
| 492 | + } |
461 | 493 | }
|
0 commit comments