java.lang.IllegalStateException in Spatial.class

8)

My program crashed once awhile because there is an uncaught IllegalStateException from Spatial.class. What we can do is catch this exception in renderScene(Spatial scene, ViewPort vp) method of RenderManager.class. For example, (after adding import java.util.logging.Level;)

use:

try {

// check culling first.

if (!scene.checkCulling(vp.getCamera())) {

// move on to shadow-only render

if (scene.getShadowMode() != RenderQueue.ShadowMode.Off

|| scene instanceof Node) {

renderShadow(scene, vp.getQueue());

}

return;

}

} catch (IllegalStateException ex) {

logger.log(Level.SEVERE, "Error from IllegalStateException ", ex);

}

or, use ex.printStackTrace(); in the catch.

Missing a rendering is not very good thing but user can hardly notice it, much better than program crash. After the change, my program does not crash.

What is the source of the exception? I never see it occur, so there is probably something wrong with your app or the data in it that should be tracked down.

I am new in this playground. I am sure there will be good way to modify my program to avoid the IllegalStateException. I am working on it. On other consideration, I feel good library classes do the best to catch all exceptions in case to crash the program.

I do not know the real tricks inside the JMonkey and I cannot find a better way to handle this exception in a general way. Hopefully, Someone with more experience can solve the issue. Here is the source:



package com.jme3.wen;



import java.util.TimerTask;



import com.jme3.app.SimpleApplication;

import com.jme3.light.DirectionalLight;

import com.jme3.material.Material;

import com.jme3.material.RenderState.BlendMode;

import com.jme3.math.ColorRGBA;

import com.jme3.scene.Geometry;

import com.jme3.scene.Node;

import com.jme3.scene.shape.Cylinder;

import com.jme3.scene.shape.Sphere;

import com.jme3.math.Vector3f;



public class Balls2 extends SimpleApplication{

private Geometry[][][] balls = new Geometry[4][4][4];

private ColorRGBA myGreen = new ColorRGBA(0.2f, 1f, 0.2f, 1);

private ColorRGBA myAmbient = new ColorRGBA(0.1f, 0.1f, 0.1f, 1);

private Node myNode = new Node();

private static RotatingJob rotatingJob;



class RotatingJob extends TimerTask {

public void run() {

myNode.rotate(0f, 0.1f, 0f);

}

}

public static void main(String[] args) {

Balls2 app = new Balls2();

app.setShowSettings(false);

app.start();

app.startRotation();

}

public void startRotation() {

java.util.Timer rotatingtimer = new java.util.Timer();

rotatingJob = new RotatingJob();

rotatingtimer.scheduleAtFixedRate(rotatingJob, 300, 300);

}



@Override

public void simpleInitApp() {

flyCam.setEnabled(false);

viewPort.setBackgroundColor(ColorRGBA.LightGray);



Geometry c1geom = createCylinderGeometry();

c1geom.setLocalTranslation(-3f, -3f, 0);

Geometry c2geom = c1geom.clone();

c2geom.setLocalTranslation(-1f, -3f, 0);

Geometry c3geom = c1geom.clone();

c3geom.setLocalTranslation(1f, -3f, 0);

Geometry c4geom = c1geom.clone();

c4geom.setLocalTranslation(3f, -3f, 0);



// layer1 is at the bottom (in xz plane), each cylinder extends in z

// direction

Node layer1 = new Node();

layer1.attachChild(c1geom);

layer1.attachChild(c2geom);

layer1.attachChild(c3geom);

layer1.attachChild(c4geom);



// layer2 to layer4 are on top of layer1, cylinders are in same

// direction as layer1

Node layer2 = (Node) layer1.clone();

layer2.setLocalTranslation(0f, 2f, 0);

Node layer3 = (Node) layer1.clone();

layer3.setLocalTranslation(0f, 4f, 0);

Node layer4 = (Node) layer1.clone();

layer4.setLocalTranslation(0f, 6f, 0);



// layer5 is layer by vertical cylinder. The layer is in xy plane

Node layer5 = (Node) layer1.clone();

layer5.rotate((float) (Math.PI / 2.0), 0f, 0f);

layer5.setLocalTranslation(0f, 0f, 0f);

// layer6 to layer 8 are parallel to layer5

Node layer6 = (Node) layer1.clone();

layer6.rotate((float) (Math.PI / 2.0), 0f, 0f);

layer6.setLocalTranslation(0f, 0f, 2f);



Node layer7 = (Node) layer1.clone();

layer7.rotate((float) (Math.PI / 2.0), 0f, 0f);

layer7.setLocalTranslation(0f, 0f, 4f);



Node layer8 = (Node) layer1.clone();

layer8.rotate((float) (Math.PI / 2.0), 0f, 0f);

layer8.setLocalTranslation(0f, 0f, 6f);



// layer9 layer is in xz plane. Each cylinder extends in x direction

Node layer9 = (Node) layer1.clone();

layer9.rotate(0f, (float) (Math.PI / 2.0), 0f);

layer9.setLocalTranslation(0f, 0f, 0f);



// layer10 to layer12 are on top of layer9, parallel

Node layer10 = (Node) layer1.clone();

layer10.rotate(0f, (float) (Math.PI / 2.0), 0f);

layer10.setLocalTranslation(0f, 2f, 0f);



Node layer11 = (Node) layer1.clone();

layer11.rotate(0f, (float) (Math.PI / 2.0), 0f);

layer11.setLocalTranslation(0f, 4f, 0f);



Node layer12 = (Node) layer1.clone();

layer12.rotate(0f, (float) (Math.PI / 2.0), 0f);

layer12.setLocalTranslation(0f, 6f, 0f);



myNode.attachChild(layer1);

myNode.attachChild(layer2);

myNode.attachChild(layer3);

myNode.attachChild(layer4);

myNode.attachChild(layer5);

myNode.attachChild(layer6);

myNode.attachChild(layer7);

myNode.attachChild(layer8);

myNode.attachChild(layer9);

myNode.attachChild(layer10);

myNode.attachChild(layer11);

myNode.attachChild(layer12);



// Create balls and attach balls to myNode.

createBalls(ColorRGBA.LightGray, balls);

rootNode.attachChild(myNode);

myNode.setLocalScale(0.75f);



DirectionalLight sun = new DirectionalLight();

sun.setDirection(new Vector3f(3, -4, -1).normalizeLocal());

rootNode.addLight(sun);



}



private Geometry createCylinderGeometry() {

Cylinder c1 = new Cylinder(16, 16, 0.05f, 6f, false);

Geometry c1geom = new Geometry(“Cylinder”, c1);

Material cylinderMat = new Material(assetManager,

“Common/MatDefs/Light/Lighting.j3md”);

cylinderMat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);

cylinderMat.setColor(“Diffuse”, myGreen);

cylinderMat.setColor(“Ambient”, myAmbient);

cylinderMat.setColor(“Specular”, myGreen);

cylinderMat.setFloat(“Shininess”, 100);

cylinderMat.setBoolean(“UseMaterialColors”, true);

c1geom.setMaterial(cylinderMat);

return c1geom;

}



private Geometry createBallGeometry(ColorRGBA color) {

Sphere ball = new Sphere(16, 16, 0.35f);

Geometry ballgeom = new Geometry(“Cylinder”, ball);

Material ballMat = new Material(assetManager,

“Common/MatDefs/Light/Lighting.j3md”);

ballMat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);

ballMat.setColor(“Diffuse”, color);

ballMat.setColor(“Ambient”, myAmbient);

ballMat.setColor(“Specular”, color);

ballMat.setFloat(“Shininess”, 100);

ballMat.setBoolean(“UseMaterialColors”, true);

ballgeom.setMaterial(ballMat);

return ballgeom;

}



private void createBalls(ColorRGBA color, Geometry[][][] balls) {

Geometry ball0 = createBallGeometry(color);

for (int i = 0; i < 4; i++) {

for (int j = 0; j < 4; j++) {

for (int k = 0; k < 4; k++) {

balls[j][k] = ball0.clone();

balls[j][k].setLocalTranslation(2 * i - 3, 2 * j - 3,

2 * k - 3);

myNode.attachChild(balls[j][k]);

}

}

}

}

}

The exception occurs randomly. Change the ball, cylinder to better resolution:

Sphere(32, 32, 0.35f);

Cylinder(32, 32, 0.05f, 6f, false);

will reduce the exception (may because of lower frames per second.)

Thanks.

The problem is your timer task. It isn’t running on the GL thread and it is updating the state of the geometry, which can cause this error.

Use the simpleUpdate method of SimpleApplication to update any rotations in your geometries.



It probably shouldn’t crash when this happens, but it is very severe. I will see what some of the devs think about making this just an error.

Nope, this is just evil threading, modifying outside the OpenGL thread is not allowed.