Create another camera view on another node

So, Recently I have been reading about multiple views/camera in jmonkey, however whenever I try to to add the camera to a another node that isn’t connected to the rootnode the app will crash and the error will say:

“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: n”
n = Name of my Node.

How can I get rid of this error and add another camera on another node?
Thanks

if you made another root node, you have to make sure it’s properly updated.
call

node.updateLogicalState();
node.updateGeometricState();

in the update method

Presuming it’s in its own viewport.

Really, I think we need to know more about OPs code.

blind shot :smiley:

2 Likes

now the same thing happens when I try to create a particle node in the other node.
I am now using updateGeometricState() and updateLogicalState();
SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,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: null
at com.jme3.scene.Spatial.checkCulling(Spatial.java:260)
at com.jme3.renderer.RenderManager.renderSubScene(RenderManager.java:647)
at com.jme3.renderer.RenderManager.renderScene(RenderManager.java:640)
at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:974)
at com.jme3.renderer.RenderManager.render(RenderManager.java:1029)
at com.jme3.app.SimpleApplication.update(SimpleApplication.java:252)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:151)
at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:185)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:228)
at java.lang.Thread.run(Thread.java:744)

Apparently fixes itself when it is attached to the rootNode, however is there a way that i can do this whithout attaching to the rootNode.

Also I have another problem now if I try to add a particle effect to this root node it will say the same error scene graph doesn’t update properly error spatial: null. Is there a way I can attach a particle affect without having it crash?

We don’t really know what you are trying to do so it’s hard to say. Like, we still don’t really know for sure why you have a node that you want rendered but not attached to the scene graph nor do we know exactly what you’ve done to make that work.

Essentially, we aren’t going to be able to help without knowing a) what you are trying to do, and b) what code you’ve got so far.

I wanted to make a viewModel, like the hands they have in fps games

So you have a model in its own Viewport? Note: there are about half a dozen different ways to implement ‘hands’ in a view so it’s tough to guess for sure which approach you are using. In general, more information is better.

Note: I don’t think anyone has ever been yelled at for giving too much information but 95% of the responses on this forum are posts asking for more information.

1 Like

still though, how do I add pariticle nodes to the separate node…
Still confused about it. It just tells me I’m updating the scene graph wrongly.

…because you are updating the scene wrong.

There are only so many ways to say “we can’t help without more information”.

1 Like

Well, you update n and then you change a child of n… so n is not updated.

Class:

package mygame;

import com.jme3.animation.AnimChannel;
import com.jme3.animation.AnimControl;
import com.jme3.animation.AnimEventListener;
import com.jme3.app.SimpleApplication;
import com.jme3.audio.AudioNode;
import com.jme3.effect.ParticleEmitter;
import com.jme3.effect.ParticleMesh;
import com.jme3.input.MouseInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.MouseButtonTrigger;
import com.jme3.light.AmbientLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Box;

public class Main extends SimpleApplication implements ActionListener,AnimEventListener{

public static void main(String[] args) {
    Main app = new Main();
    app.start();
}
Geometry boxGeo;
Node n;
Spatial gun;
Spatial gunTest;
AudioNode a;
ParticleEmitter debrisEffect;
AnimChannel animation;
AnimControl control;

@Override
public void simpleInitApp() {
n = new Node();
/* A colored lit cube. Needs light source! */ 

    /** Uses Texture from jme3-test-data library! */
ParticleEmitter fireEffect = new ParticleEmitter("Emitter", ParticleMesh.Type.Triangle, 30);
Material fireMat = new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md");
//fireMat.setTexture("Texture", assetManager.loadTexture("Effects/Explosion/flame.png"));
fireEffect.setMaterial(fireMat);
fireEffect.setImagesX(2); fireEffect.setImagesY(2); // 2x2 texture animation
fireEffect.setEndColor( new ColorRGBA(1f, 0f, 0f, 1f) );   // red
fireEffect.setStartColor( new ColorRGBA(1f, 1f, 0f, 0.5f) ); // yellow
fireEffect.getParticleInfluencer().setInitialVelocity(new Vector3f(0, 2, 0));
fireEffect.setStartSize(0.6f);
fireEffect.setEndSize(0.1f);
fireEffect.setGravity(0f,0f,0f);
fireEffect.setLowLife(0.5f);
fireEffect.setHighLife(3f);
fireEffect.getParticleInfluencer().setVelocityVariation(0.3f);
n.attachChild(fireEffect);

AmbientLight ambient2 = new AmbientLight();
ambient2.setColor(ColorRGBA.White);
rootNode.addLight(ambient2); 

AmbientLight ambient = new AmbientLight();
ambient.setColor(ColorRGBA.White);
n.addLight(ambient); 
gun = assetManager.loadModel("Models/TKX Tomex/TKX Tomex.j3o");
gun.setLocalTranslation(0, 0, 1);
gun.scale(0.2f);
gun.rotate(0, 100.5f, 0);
n.attachChild(gun);

    a = new AudioNode(assetManager,"Sounds/soundscrate-machinegun.wav",false);
    a.setPositional(false);
    a.setLooping(true);
    a.setVolume(2);
    n.attachChild(a);
    

// Setup second, smaller PiP view
Camera cam2 = cam.clone();
cam2.setViewPort( 0, 1.0f , 0, 1f );
cam2.setLocation(new Vector3f(-0.10f, 1.57f, 4.81f));
cam2.setRotation(new Quaternion(0.00f, 0.99f, -0.04f, 0.02f));

ViewPort viewPort2 = renderManager.createMainView("PiP", cam2);
viewPort2.setClearFlags(false, false, false);
viewPort2.attachScene(n);

initKeys();
}
int t1 = 0;
public boolean shoot = false;
@Override
public void simpleUpdate(float tpf) {
    n.updateGeometricState();
    n.updateLogicalState(tpf);
if (shoot == true) {
    System.out.println("true");
    t1++;
    if (t1 > 3) {
    t1 = 0;
    }
   
    if (t1 == 3) {
    gun.setLocalTranslation(gun.getLocalTranslation().x, 0, gun.getLocalTranslation().z + 1f);
    a.playInstance();
    
    }
    
    else {
    gun.setLocalTranslation(0, 0, 1);
    }
    
 
}

if (shoot == false) {
t1 = 0; 
gun.setLocalTranslation(0, 0, 1);
System.out.println("false");
}

n.updateGeometricState();
n.updateLogicalState(tpf);
}

@Override
public void simpleRender(RenderManager rm) {
    
}

public void initKeys() {
inputManager.addMapping("Shoot", new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
inputManager.addListener(this, "Shoot");
}


public void onAction(String name, boolean isPressed, float tpf) {
if (name.equals("Shoot") && isPressed) {

}

else {

}

}

public void onAnimCycleDone(AnimControl control, AnimChannel channel, String animName) {
    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}

public void onAnimChange(AnimControl control, AnimChannel channel, String animName) {
    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}

Crash Message:

Errors:

SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,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: null
at com.jme3.scene.Spatial.checkCulling(Spatial.java:260)
at com.jme3.renderer.RenderManager.renderSubScene(RenderManager.java:647)
at com.jme3.renderer.RenderManager.renderScene(RenderManager.java:640)
at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:974)
at com.jme3.renderer.RenderManager.render(RenderManager.java:1029)
at com.jme3.app.SimpleApplication.update(SimpleApplication.java:252)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:151)
at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:185)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:228)
at java.lang.Thread.run(Thread.java:744)

Sorry About the messiness

Ok, I see you update twice for some reason. Strange.

Anyway, you can try moving updateGeometricState() to render where it’s safer. simpleUpdate() runs before everything… before app states, before controls, etc…

“render” is the simpleRender Method right?

Yes.

I can now add the particles into the other node now, however they won’t show.

New Code::
public void ViewModels() {

viewCam = Main.app.getCamera().clone();
viewCam.setViewPort(0f, 1f, 0f, 1f);
viewCam.setLocation(new Vector3f(0, 10, 0));


ViewPort view2 = Main.app.getRenderManager().createMainView("Bottom Left", viewCam);
view2.setClearFlags(false, false, false);
view2.attachScene(view);
//view is the other node
}

On another Class

 public void simpleRender(RenderManager rm) {
p.ViewModels();
p.view.updateGeometricState();
 
//p is the class where ViewModels() is located

    
}

So you recreate the viewport every frame? That doesn’t seem right. I’m surprised things don’t blow up badly very quickly.

Is renderManager a loop?