Skip to content

Commit fca6939

Browse files
authored
Update TestBatchLod.java
1 parent 389d91a commit fca6939

File tree

1 file changed

+144
-22
lines changed

1 file changed

+144
-22
lines changed

jme3-examples/src/main/java/jme3test/stress/TestBatchLod.java

Lines changed: 144 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2009-2021 jMonkeyEngine
2+
* Copyright (c) 2009-2025 jMonkeyEngine
33
* All rights reserved.
44
*
55
* Redistribution and use in source and binary forms, with or without
@@ -32,25 +32,51 @@
3232
package jme3test.stress;
3333

3434
import com.jme3.app.SimpleApplication;
35+
import com.jme3.bounding.BoundingBox;
36+
import com.jme3.font.BitmapText;
37+
import com.jme3.input.KeyInput;
38+
import com.jme3.input.controls.ActionListener;
39+
import com.jme3.input.controls.KeyTrigger;
40+
import com.jme3.input.controls.Trigger;
3541
import com.jme3.light.DirectionalLight;
3642
import com.jme3.material.Material;
37-
import com.jme3.math.Quaternion;
43+
import com.jme3.material.RenderState;
44+
import com.jme3.math.ColorRGBA;
45+
import com.jme3.math.FastMath;
3846
import com.jme3.math.Vector3f;
3947
import com.jme3.scene.Geometry;
4048
import com.jme3.scene.Node;
49+
import com.jme3.scene.SceneGraphVisitorAdapter;
4150
import com.jme3.scene.control.LodControl;
51+
import com.jme3.scene.control.UpdateControl;
52+
import com.jme3.scene.debug.WireBox;
4253
import jme3tools.optimize.GeometryBatchFactory;
4354

44-
public class TestBatchLod extends SimpleApplication {
55+
import java.util.Locale;
56+
57+
public class TestBatchLod extends SimpleApplication implements ActionListener {
4558

4659
public static void main(String[] args) {
4760
TestBatchLod app = new TestBatchLod();
61+
app.setPauseOnLostFocus(false);
4862
app.start();
4963
}
5064

65+
private BitmapText hud;
66+
private Material lightMaterial;
67+
private final Node debugNode = new Node("DebugNode");
68+
private LodControl lodControl;
69+
// Tuning parameters
70+
private float trisPerPixel = 1.0f;
71+
private float distTolerance = 1.0f;
72+
5173
@Override
5274
public void simpleInitApp() {
53-
// inputManager.registerKeyBinding("USELOD", KeyInput.KEY_L);
75+
76+
configureCamera();
77+
78+
hud = createLabelText(10, 20, "<placeholder>");
79+
updateHud();
5480

5581
DirectionalLight dl = new DirectionalLight();
5682
dl.setDirection(new Vector3f(-1, -1, -1).normalizeLocal());
@@ -59,30 +85,126 @@ public void simpleInitApp() {
5985
Node teapotNode = (Node) assetManager.loadModel("Models/Teapot/Teapot.mesh.xml");
6086
Geometry teapot = (Geometry) teapotNode.getChild(0);
6187

62-
Material mat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
63-
mat.setFloat("Shininess", 16f);
64-
mat.setBoolean("VertexLighting", true);
65-
teapot.setMaterial(mat);
88+
lightMaterial = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
89+
lightMaterial.setFloat("Shininess", 16f);
90+
lightMaterial.setBoolean("VertexLighting", true);
91+
lightMaterial.getAdditionalRenderState().setWireframe(true);
92+
teapot.setMaterial(lightMaterial);
6693

67-
// A special Material to visualize mesh normals:
68-
//Material mat = new Material(assetManager, "Common/MatDefs/Misc/ShowNormals.j3md");
69-
flyCam.setMoveSpeed(5);
94+
boolean cloneMaterial = false;
7095
for (int y = -5; y < 5; y++) {
7196
for (int x = -5; x < 5; x++) {
72-
Geometry clonePot = teapot.clone();
97+
Geometry geo = teapot.clone(cloneMaterial);
98+
geo.setLocalTranslation(x * .5f, 0, y * .5f);
99+
geo.setLocalScale(.15f);
100+
geo.setMaterial(lightMaterial);
101+
debugNode.attachChild(geo);
102+
}
103+
}
104+
105+
lodControl = new LodControl();
106+
boolean useLods = true;
107+
Node batchNode = GeometryBatchFactory.optimize(debugNode, useLods);
108+
batchNode.depthFirstTraversal(new SceneGraphVisitorAdapter() {
109+
@Override
110+
public void visit(Geometry geom) {
111+
if (geom.getMesh().getNumLodLevels() > 0) {
112+
113+
geom.addControl(lodControl);
114+
debugWorldBound((BoundingBox) geom.getWorldBound());
73115

74-
//clonePot.setMaterial(mat);
75-
clonePot.setLocalTranslation(x * .5f, 0, y * .5f);
76-
clonePot.setLocalScale(.15f);
77-
clonePot.setMaterial(mat);
78-
rootNode.attachChild(clonePot);
116+
geom.addControl(new UpdateControl() {
117+
int lastLevel = -1;
118+
final BitmapText label = createLabelText(10, 50, "Updating...");
119+
120+
@Override
121+
protected void controlUpdate(float tpf) {
122+
if (lastLevel != geom.getLodLevel()) {
123+
lastLevel = geom.getLodLevel();
124+
label.setText("LodLevel: " + lastLevel);
125+
}
126+
}
127+
});
128+
}
129+
}
130+
131+
private void debugWorldBound(BoundingBox bbox) {
132+
Geometry geo = WireBox.makeGeometry(bbox);
133+
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
134+
mat.setColor("Color", ColorRGBA.Blue);
135+
geo.setMaterial(mat);
136+
rootNode.attachChild(geo);
79137
}
138+
});
139+
140+
rootNode.attachChild(debugNode);
141+
registerInputMappings();
142+
}
143+
144+
private void updateHud() {
145+
hud.setText(String.format(Locale.ENGLISH, "TrisPerPixel: %.1f, DistTolerance: %.1f",
146+
trisPerPixel, distTolerance));
147+
}
148+
149+
@Override
150+
public void onAction(String name, boolean isPressed, float tpf) {
151+
if (!isPressed) return;
152+
153+
if (name.equals("toggleWireframe")) {
154+
RenderState renderState = lightMaterial.getAdditionalRenderState();
155+
boolean wireframe = renderState.isWireframe();
156+
renderState.setWireframe(!wireframe);
157+
}
158+
if (name.equals("TrisPerPixel+")) {
159+
trisPerPixel = FastMath.clamp(trisPerPixel + 0.1f, 0.1f, 5f);
160+
lodControl.setTrisPerPixel(trisPerPixel);
161+
updateHud();
162+
163+
} else if (name.equals("TrisPerPixel-")) {
164+
trisPerPixel = FastMath.clamp(trisPerPixel - 0.1f, 0.1f, 5f);
165+
lodControl.setTrisPerPixel(trisPerPixel);
166+
updateHud();
167+
168+
} else if (name.equals("DistTolerance+")) {
169+
distTolerance = FastMath.clamp(distTolerance + 0.1f, 0.1f, 5f);
170+
lodControl.setDistTolerance(distTolerance);
171+
updateHud();
172+
173+
} else if (name.equals("DistTolerance-")) {
174+
distTolerance = FastMath.clamp(distTolerance - 0.1f, 0.1f, 5f);
175+
lodControl.setDistTolerance(distTolerance);
176+
updateHud();
80177
}
81-
GeometryBatchFactory.optimize(rootNode, true);
82-
LodControl control = new LodControl();
83-
rootNode.getChild(0).addControl(control);
84-
cam.setLocation(new Vector3f(-1.0748308f, 1.35778f, -1.5380064f));
85-
cam.setRotation(new Quaternion(0.18343268f, 0.34531063f, -0.069015436f, 0.9177962f));
178+
}
86179

180+
private void registerInputMappings() {
181+
addMapping("toggleWireframe", new KeyTrigger(KeyInput.KEY_SPACE));
182+
addMapping("TrisPerPixel+", new KeyTrigger(KeyInput.KEY_I));
183+
addMapping("TrisPerPixel-", new KeyTrigger(KeyInput.KEY_K));
184+
addMapping("DistTolerance+", new KeyTrigger(KeyInput.KEY_L));
185+
addMapping("DistTolerance-", new KeyTrigger(KeyInput.KEY_J));
87186
}
187+
188+
private void addMapping(String mappingName, Trigger... triggers) {
189+
inputManager.addMapping(mappingName, triggers);
190+
inputManager.addListener(this, mappingName);
191+
}
192+
193+
private void configureCamera() {
194+
flyCam.setMoveSpeed(25f);
195+
flyCam.setDragToRotate(true);
196+
197+
cam.setLocation(Vector3f.UNIT_XYZ.mult(8f));
198+
cam.lookAt(Vector3f.ZERO, Vector3f.UNIT_Y);
199+
}
200+
201+
private BitmapText createLabelText(int x, int y, String text) {
202+
BitmapText bmp = new BitmapText(guiFont);
203+
bmp.setText(text);
204+
bmp.setLocalTranslation(x, settings.getHeight() - y, 0);
205+
bmp.setColor(ColorRGBA.Red);
206+
guiNode.attachChild(bmp);
207+
return bmp;
208+
}
209+
88210
}

0 commit comments

Comments
 (0)