I want to load the assets on a separate thread, so that the main thread can run a simple animation. Sometimes it works, but sometimes I get this:
ago 04, 2020 3:41:01 PM com.jme3.app.LegacyApplication handleError
GRAVE: Uncaught exception thrown in Thread[jME3 Main,5,main]
java.lang.IllegalStateException: Scene graph is not properly updated for rendering.
State was changed after rootNode.updateGeometricState() call.
Make sure you do not modify the scene from another thread!
Problem spatial name: Gui Node
at com.jme3.scene.Spatial.checkCulling(Spatial.java:361)
at com.jme3.renderer.RenderManager.renderSubScene(RenderManager.java:717)
at com.jme3.renderer.RenderManager.renderScene(RenderManager.java:710)
at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:1096)
at com.jme3.renderer.RenderManager.render(RenderManager.java:1166)
at com.jme3.app.SimpleApplication.update(SimpleApplication.java:272)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:153)
at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:193)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:234)
at java.lang.Thread.run(Thread.java:745)
My code is:
public class Loading3AppState extends BaseAppState {
Node stateGuiNode = new Node();
Geometry bg;
Material bgM;
Geometry eve;
Application app;
@Override
protected void initialize(Application app) {
//some spatials for the loading screen
bg = new Geometry("monkeybg", new Quad(MS_WIDTH, MS_HEIGHT));
bgM = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
bgM.setColor("Color", new ColorRGBA(0.21875f, 0.21875f, 0.21875f, 1f));
bg.setMaterial(bgM);
eve = new Geometry("monkey", new Quad(540, 640));
Material logoM = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
logoM.setTexture("ColorMap", app.getAssetManager().loadTexture("Comics/eve.png"));
logoM.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha); // !
logoM.getAdditionalRenderState().setFaceCullMode(RenderState.FaceCullMode.Off);
eve.setMaterial(logoM);
eve.setLocalTranslation(500, 0, 0);
this.app = app;
stateGuiNode.attachChild(bg);
stateGuiNode.attachChild(eve);
setEnabled(false);
}
SharedDrawable drawable;
float totTPF = 0;
@Override
public void update(float tpf) {
//some animation...
bgM.setColor("Color", new ColorRGBA(1f, interp(0, step_dur,0.3f,0.5f,totTPF), interp(0, step_dur,1f,0.9f,totTPF), 1f));
//other animations...
}
private float interp(float Tstart, float Tend, float Cstart, float Cend, float Tval){
return ((Tval-Tstart)*(Cend-Cstart)/(Tend-Tstart))+Cstart;
}
private void cacheTexture(String texture) {
System.out.println(new Date() + " cache load " + texture);
Geometry cache = new Geometry("????", new Quad(1, 1));
Material mat = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
mat.setTexture("ColorMap", app.getAssetManager().loadTexture(texture));
cache.setMaterial(mat);
mat.preload(app.getRenderManager(), cache);
}
@Override
protected void cleanup(Application app) {
}
@Override
protected void onEnable() {
System.out.println(new Date() + " onEnable");
((Main) getApplication()).scaledGuiNode.attachChild(stateGuiNode);
try {
drawable = new SharedDrawable(Display.getDrawable());
} catch (LWJGLException e) {
e.printStackTrace();
}
System.out.println(new Date() + " created drawable");
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(new Date() + " BG thread");
try {
drawable.makeCurrent();
} catch (LWJGLException e) {
e.printStackTrace();
}
cacheTexture("Textures/deepsky01p.png");
cacheTexture("Textures/moon-blue.png");
for (int i = 0; i < nebulas.length; i++) {
if (i < 9) {
cacheTexture("Textures/aurora0" + (i + 1) + ".png");
} else {
cacheTexture("Textures/aurora" + (i + 1) + ".png");
}
}
cacheTexture("Textures/deepsky01p.png");
cacheTexture("Textures/aurora01.png");
cacheTexture("Textures/aurora02.png");
cacheTexture("Textures/aurora03.png");
cacheTexture("Textures/aurora04.png");
cacheTexture("Textures/aurora05.png");
cacheTexture("Textures/aurora06.png");
cacheTexture("Textures/aurora07.png");
cacheTexture("Textures/aurora08.png");
cacheTexture("Textures/aurora09.png");
cacheTexture("Textures/aurora10.png");
cacheTexture("Textures/moon-blue.png");
cacheTexture("Textures/black-hole4.png");
cacheTexture("Textures/MonkeySheet/boss-armor-break.dds");
cacheTexture("Textures/MonkeySheet/pppp.dds");
cacheTexture("Textures/MonkeySheet/shell.dds");
cacheTexture("Textures/MonkeySheet/simonetta2.dds");
cacheTexture("Textures/MonkeySheet/size64.dds");
cacheTexture("Textures/MonkeySheet/size128.dds");
cacheTexture("Textures/MonkeySheet/size256.dds");
cacheTexture("Textures/MonkeySheet/slugdeath.dds");
cacheTexture("Textures/MonkeySheet/slug-pinata-death.dds");
cacheTexture("Textures/MonkeySheet/slugs128.dds");
cacheTexture("Textures/MonkeySheet/slugs512.dds");
cacheTexture("Textures/MonkeySheet/slugs1024.dds");
cacheTexture("Textures/MonkeySheet/ssss.dds");
cacheTexture("Textures/boot.png");
drawable.destroy();
//loading is finished, so start the game
getState(UberState.class).setState(INGAME);
}
}).start();
}
@Override
protected void onDisable() {
stateGuiNode.removeFromParent();
}
}