Skip to content

Commit 7abc35b

Browse files
authored
solve issue #2007 (instanced objects are culled when using WaterFilter) (#2008)
* Fix issue with InstancedGeometry that uses the wrong camera for "instance culling" check. * Minor javadoc update.
1 parent 3f0fa2d commit 7abc35b

File tree

3 files changed

+97
-13
lines changed

3 files changed

+97
-13
lines changed

jme3-core/src/main/java/com/jme3/scene/instancing/InstancedGeometry.java

+2-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2009-2022 jMonkeyEngine
2+
* Copyright (c) 2009-2023 jMonkeyEngine
33
* All rights reserved.
44
*
55
* Redistribution and use in source and binary forms, with or without
@@ -75,7 +75,6 @@ public class InstancedGeometry extends Geometry {
7575

7676
private int firstUnusedIndex = 0;
7777
private int numVisibleInstances = 0;
78-
private Camera cam;
7978

8079
public InstancedGeometry() {
8180
super();
@@ -276,7 +275,7 @@ private void swap(int idx1, int idx2) {
276275
}
277276
}
278277

279-
public void updateInstances() {
278+
public void updateInstances(Camera cam) {
280279
FloatBuffer fb = (FloatBuffer) transformInstanceData.getData();
281280
fb.limit(fb.capacity());
282281
fb.position(0);
@@ -416,12 +415,6 @@ private void updateAllInstanceData() {
416415
allInstanceData = allData.toArray(new VertexBuffer[allData.size()]);
417416
}
418417

419-
@Override
420-
public boolean checkCulling(Camera cam) {
421-
this.cam = cam;
422-
return super.checkCulling(cam);
423-
}
424-
425418
@Override
426419
public int collideWith(Collidable other, CollisionResults results) {
427420
return 0; // Ignore collision

jme3-core/src/main/java/com/jme3/scene/instancing/InstancedNode.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2014-2021 jMonkeyEngine
2+
* Copyright (c) 2014-2023 jMonkeyEngine
33
* All rights reserved.
44
*
55
* Redistribution and use in source and binary forms, with or without
@@ -35,6 +35,7 @@
3535
import com.jme3.export.JmeImporter;
3636
import com.jme3.material.MatParam;
3737
import com.jme3.material.Material;
38+
import com.jme3.renderer.Camera;
3839
import com.jme3.renderer.RenderManager;
3940
import com.jme3.renderer.ViewPort;
4041
import com.jme3.renderer.queue.RenderQueue;
@@ -161,7 +162,7 @@ public void update(float tpf){
161162

162163
@Override
163164
public void render(RenderManager rm, ViewPort vp) {
164-
node.renderFromControl();
165+
node.renderFromControl(vp.getCamera());
165166
}
166167

167168
@Override
@@ -198,9 +199,9 @@ public InstancedNode(String name) {
198199
addControl(control);
199200
}
200201

201-
private void renderFromControl() {
202+
private void renderFromControl(Camera cam) {
202203
for (InstancedGeometry ig : instancesMap.values()) {
203-
ig.updateInstances();
204+
ig.updateInstances(cam);
204205
}
205206
}
206207

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* Copyright (c) 2009-2023 jMonkeyEngine
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are
7+
* met:
8+
*
9+
* * Redistributions of source code must retain the above copyright
10+
* notice, this list of conditions and the following disclaimer.
11+
*
12+
* * Redistributions in binary form must reproduce the above copyright
13+
* notice, this list of conditions and the following disclaimer in the
14+
* documentation and/or other materials provided with the distribution.
15+
*
16+
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17+
* may be used to endorse or promote products derived from this software
18+
* without specific prior written permission.
19+
*
20+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22+
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23+
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24+
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25+
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26+
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27+
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28+
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29+
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31+
*/
32+
33+
package jme3test.scene.instancing;
34+
35+
import com.jme3.app.SimpleApplication;
36+
import com.jme3.light.DirectionalLight;
37+
import com.jme3.material.Material;
38+
import com.jme3.math.Vector3f;
39+
import com.jme3.post.FilterPostProcessor;
40+
import com.jme3.scene.Geometry;
41+
import com.jme3.scene.instancing.InstancedNode;
42+
import com.jme3.scene.shape.Box;
43+
import com.jme3.water.WaterFilter;
44+
45+
/**
46+
* A test case for using instancing with shadow filter. This is a test case
47+
* for issue 2007 (Instanced objects are culled when using the WaterFilter).
48+
*
49+
* If test succeeds, all the boxes in the camera frustum will be rendered. If
50+
* test fails, some of the boxes that are in the camera frustum will be culled.
51+
*
52+
* @author Ali-RS
53+
*/
54+
public class TestInstancingWithWaterFilter extends SimpleApplication {
55+
public static void main(String[] args) {
56+
TestInstancingWithWaterFilter test = new TestInstancingWithWaterFilter();
57+
test.start();
58+
}
59+
60+
@Override
61+
public void simpleInitApp() {
62+
flyCam.setMoveSpeed(10);
63+
64+
DirectionalLight light = new DirectionalLight();
65+
light.setDirection(new Vector3f(-1, -1, -1));
66+
rootNode.addLight(light);
67+
68+
Material mat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
69+
mat.setBoolean("UseInstancing", true);
70+
71+
Box mesh = new Box(0.5f, 0.5f, 0.5f);
72+
73+
InstancedNode instanceNode = new InstancedNode("TestInstancedNode");
74+
//instanceNode.setCullHint(Spatial.CullHint.Never);
75+
rootNode.attachChild(instanceNode);
76+
77+
for (int i = 0; i < 200; i++) {
78+
Geometry obj = new Geometry("TestBox" + i, mesh);
79+
obj.setMaterial(mat);
80+
obj.setLocalTranslation(i, i, 0);
81+
instanceNode.attachChild(obj);
82+
}
83+
instanceNode.instance();
84+
85+
FilterPostProcessor fpp = new FilterPostProcessor(assetManager);
86+
WaterFilter waterFilter = new WaterFilter(rootNode, light.getDirection());
87+
fpp.addFilter(waterFilter);
88+
viewPort.addProcessor(fpp);
89+
}
90+
}

0 commit comments

Comments
 (0)