JME3 development and missing features

Hi everyone!



I started to develop a JME3 application for some days. First I’d like to say that working with the new engine is quite easier. All the states (cullstate, materialstate, texturestate, renderstate,…) of JME2 where a pain. I really like the new way to handle materials. I also like the JBullet integration. :slight_smile:



But there are some features I miss.

Set the alpha of textures or use translucent objects. I’m going to need the ability to fade out objects and/or textures.

A “local” bloom filter. Apply the bloom effect only for some objects or texture ids. (I think in JME2 it was possible with texture ids)

Planar mapping. I want to map a texture planar on a box.

Filters to work with offscreen rendering. I implemented a render-to-texture feature by adapting the SimpleWaterProcessor. First it seemed to work fine, but there are problems: When adding a SSAO filter to the offscreen scene, the rendered texture gets corrupted (see picture). The same with other filters.







Material alpha buggy? When a transparent materials is in front of the rendered texture, the alpha blend mode seems not to be applied. The transparent parts are rendered black (see picture). In front of regular objects it works.







GameStates? I didn’t find game states in JME3. Will they be implemented later or is there a new concept for switching whole scenes?



I’m going to require these features for my master thesis. If it isn’t possible to implement them in near future, I got to switch back to JME2, where I already made a game. I’m an experienced java programmer but I have no clue about shaders or OpenGL programming. Even so I’d like to offer my help for JME3.

1 Like
Set the alpha of textures or use translucent objects

This sort of depends on what material you're using. Some materials have different ways of setting transparency.
If a material doesn't support it by default, you'll have to force it with:
[java]
material.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
[/java]

For the Lighting.j3md material, you need to set the parameter m_UseAlpha to true and do the above.

Material alpha buggy? When a transparent materials is in front of the rendered texture, the alpha blend mode seems not to be applied.

All transparent objects should be in the transparent queue (setQueueBucket(Bucket.Transparent))

GameStates? I didn’t find game states in JME3.

They are now called AppStates. See jme3test.app.state.TestAppStates
1 Like
3H said:
A "local" bloom filter. Apply the bloom effect only for some objects or texture ids. (I think in JME2 it was possible with texture ids)

I'm working on the bloom filter, there is already classic bloom with light extraction, but i'm developing a glow based on a glowmap applied on the object, so that only some parts of an object are glowing. I already have a working version in my local repo, but it's not ready to be committed.
It will support glowmap, and glow color (if you want an entire object to glow).

3H said:
Filters to work with offscreen rendering. I implemented a render-to-texture feature by adapting the SimpleWaterProcessor. First it seemed to work fine, but there are problems: When adding a SSAO filter to the offscreen scene, the rendered texture gets corrupted (see picture). The same with other filters.

Could you produce a test case so i could look into it. Filters are not design to be applied on offscreens renders so you can have unexpected results.

Thanks for your reply!


Momoko_Fan said:
This sort of depends on what material you're using. Some materials have different ways of setting transparency.
If a material doesn't support it by default, you'll have to force it with:
[java]
material.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
[/java]

For the Lighting.j3md material, you need to set the parameter m_UseAlpha to true and do the above.


Maybe you missunderstood me. I want to be able to set the alpha by calling something like
[java]mat.setFloat("m_Alpha", 0.4f)[/java]
so I can implement a fade in/out animation.

nehon said:
All transparent objects should be in the transparent queue (setQueueBucket(Bucket.Transparent))

That works fine, thank you.

nehon said:
They are now called AppStates. See jme3test.app.state.TestAppStates

Very impressive! :)

nehon said:
I'm working on the bloom filter, there is already classic bloom with light extraction, but i'm developing a glow based on a glowmap applied on the object, so that only some parts of an object are glowing. I already have a working version in my local repo, but it's not ready to be committed.
It will support glowmap, and glow color (if you want an entire object to glow).

Sounds nice, can't wait to see it.

nehon said:
Could you produce a test case so i could look into it. Filters are not design to be applied on offscreens renders so you can have unexpected results.

Heres my processor:
[java]
package com.jme3.texture;

import com.jme3.asset.AssetManager;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.post.FilterPostProcessor;
import com.jme3.post.SceneProcessor;
import com.jme3.post.ssao.SSAOConfig;
import com.jme3.post.ssao.SSAOFilter;
import com.jme3.renderer.Camera;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.renderer.queue.RenderQueue;
import com.jme3.scene.Node;
import com.jme3.texture.Image.Format;

public class OffscreenProcessor implements SceneProcessor {
private int renderWidth = 512;
private int renderHeight = 512;
private FrameBuffer offscreenBuffer;
private Camera offscreenCam;
private Node offscreenScene;
private ViewPort offscreenView;
private RenderManager rm;
private FilterPostProcessor fpp;

// the texture to render to
private Texture2D texture;

// the material that will be created
protected Material material;

private boolean useSSAO = false;

public OffscreenProcessor(AssetManager assetManager, Node scene) {
this.offscreenScene = scene;

fpp = new FilterPostProcessor(assetManager);

// update the state of the scene that should be added
scene.updateGeometricState();

material = new Material(assetManager,
"Common/MatDefs/Misc/SimpleTextured.j3md");
}

@Override
public void initialize(RenderManager rm, ViewPort vp) {
this.rm = rm;

texture = new Texture2D(renderWidth, renderHeight, Format.RGBA8);

offscreenCam = new Camera(renderWidth, renderHeight);
offscreenCam.setLocation(new Vector3f(9, 3, 9));
offscreenCam.lookAt(new Vector3f(-9, 1, -9), Vector3f.UNIT_Y);
Camera cam = vp.getCamera();
offscreenCam.setFrustum(cam.getFrustumNear(), 30, cam.getFrustumLeft(),
cam.getFrustumRight(), cam.getFrustumTop(), cam.getFrustumBottom());

// create a pre-view. a view that is rendered before the main view
offscreenView = rm.createPreView("Offscreen View", offscreenCam);
offscreenView.setClearEnabled(true);
offscreenView.setBackgroundColor(ColorRGBA.White);
// create offscreen framebuffer
offscreenBuffer = new FrameBuffer(renderWidth, renderHeight, 0);
// setup framebuffer to use texture
offscreenBuffer.setDepthBuffer(Format.Depth);
offscreenBuffer.setColorTexture(texture);

// set viewport to render to offscreen framebuffer
offscreenView.setOutputFrameBuffer(offscreenBuffer);

// attach the scene to the viewport to be rendered
offscreenView.attachScene(offscreenScene);

// apply the texture
material.setTexture("m_ColorMap", texture);

// add the filter, if desired
if (useSSAO) {
SSAOFilter ssaoFilter = new SSAOFilter(offscreenView, new SSAOConfig(
2.5f, 1.5f, 3f, -0.1f, false, true));
fpp.addFilter(ssaoFilter);
offscreenView.addProcessor(fpp);
}
}

public void setUseSSAO(boolean useSSAO) {
this.useSSAO = useSSAO;
}

@Override
public void reshape(ViewPort vp, int w, int h) {
}

@Override
public boolean isInitialized() {
return rm != null;
}

@Override
public void preFrame(float tpf) {
}

@Override
public void postQueue(RenderQueue rq) {
}

@Override
public void postFrame(FrameBuffer out) {
}

@Override
public void cleanup() {
}

public Material getMaterial() {
return material;
}
}
[/java]

And here's my test code:

[java]
package jme3test.texture;

import com.jme3.app.SimpleApplication;
import com.jme3.light.PointLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Box;
import com.jme3.texture.OffscreenProcessor;

public class TestOffscreenRendering extends SimpleApplication {
private Spatial teapot;
private Geometry box;

private OffscreenProcessor processor;

public static void main(String[] args) {
TestOffscreenRendering app = new TestOffscreenRendering();
app.start();
}

@Override
public void simpleInitApp() {
cam.setLocation(new Vector3f(0, 0, 3));

// init the teapot and the teapot material
Material whiteMat = new Material(assetManager,
"Common/MatDefs/Light/Lighting.j3md");
whiteMat.setFloat("m_Shininess", 0.1f);
whiteMat.setBoolean("m_UseMaterialColors", true);
whiteMat.setColor("m_Ambient", ColorRGBA.Black);
whiteMat.setColor("m_Diffuse", ColorRGBA.Red);
whiteMat.setColor("m_Specular", ColorRGBA.Gray);
whiteMat.setReceivesShadows(true);

teapot = assetManager.loadModel("Models/Teapot/Teapot.obj");
teapot.setLocalTranslation(7.6f, 2.5f, 7.8f);
teapot.setMaterial(whiteMat);
teapot.setShadowMode(ShadowMode.CastAndReceive);

// init offscreen scene
Node offScreenScene = new Node();
offScreenScene.attachChild(teapot);
PointLight l = new PointLight();
l.setPosition(new Vector3f(5, 5, 5));
offScreenScene.addLight(l);

// init the processor
processor = new OffscreenProcessor(assetManager, offScreenScene);
// FOR TESTING
processor.setUseSSAO(true); // <
deactivate the filter here
viewPort.addProcessor(processor);

// init the box to render to
box = new Geometry("box", new Box(new Vector3f(0, 0, 0), .5f, .5f, .5f));
box.setMaterial(processor.getMaterial());
box.setShadowMode(ShadowMode.CastAndReceive);
rootNode.attachChild(box);
}

@Override
public void simpleUpdate(float tpf) {
box.rotate(0, tpf, 0);
}
}
[/java]
3H said:
Maybe you missunderstood me. I want to be able to set the alpha by calling something like
[java]mat.setFloat("m_Alpha", 0.4f)[/java]
so I can implement a fade in/out animation.

Yeah it is possible. But once again it depends on the material being used. Some materials might not support it (like SimpleTextured).
For the Lighting.j3md material, you will need to alter the alpha value of the m_Diffuse color and set m_UseMaterialColors and m_UseAlpha to true.
1 Like

OK check the last SVN you should be able now to use filters on off-screen viewports.



Your processor is a pretty good work can we keep it for JME3?

Momoko_Fan said:
Yeah it is possible. But once again it depends on the material being used. Some materials might not support it (like SimpleTextured).
For the Lighting.j3md material, you will need to alter the alpha value of the m_Diffuse color and set m_UseMaterialColors and m_UseAlpha to true.


Ok, thanks. I will try it tomorrow.

nehon said:
OK check the last SVN you should be able now to use filters on off-screen viewports.

Your processor is a pretty good work can we keep it for JME3?


I'll try.
Of course, you can use it. I always want to contribute to JME. But let me add some abilities to change the camera location for offscreen rendering and set a material template (e.g. Lighting.j3md) for the rendered material. I'll post new code tomorrow.

Ok, it works. Now I got the expected results, thanks a lot!



For the OffscreenProcessor, I added methods to access the camera from outside the processor, set the background color and texture size and initialize the processor with a material to render to.



[java]package com.jme3.texture;



import com.jme3.asset.AssetManager;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.post.FilterPostProcessor;

import com.jme3.post.SceneProcessor;

import com.jme3.post.ssao.SSAOConfig;

import com.jme3.post.ssao.SSAOFilter;

import com.jme3.renderer.Camera;

import com.jme3.renderer.RenderManager;

import com.jme3.renderer.ViewPort;

import com.jme3.renderer.queue.RenderQueue;

import com.jme3.scene.Node;

import com.jme3.texture.Image.Format;



public class OffscreenProcessor implements SceneProcessor {

private int renderWidth = 512;

private int renderHeight = 512;

private FrameBuffer offscreenBuffer;

private Camera offscreenCam;

private Node offscreenScene;

private ViewPort offscreenView;

private AssetManager assetManager;

private RenderManager rm;

private FilterPostProcessor fpp;



private ColorRGBA backgroundColor = ColorRGBA.White;



// the texture to render to

private Texture2D texture;



// the material that will be created

protected Material material;



private SSAOConfig ssaoConfig;



// the key to apply the texture to the material

private String textureKey;



/**

  • Creates a new offscreen texture processor with a SimpleTextured material

    *
  • @param assetManager
  •      The AssetManager<br />
    
  • @param scene
  •      The scene that will be rendered<br />
    

*/

public OffscreenProcessor(AssetManager assetManager, Node scene) {

this.assetManager = assetManager;

this.offscreenScene = scene;

this.material = new Material(assetManager,

“Common/MatDefs/Misc/SimpleTextured.j3md”);

this.textureKey = “m_ColorMap”;



init();

}



/**

  • Creates a new offscreen texture processor with a SimpleTextured material

    *
  • @param assetManager
  •      The AssetManager<br />
    
  • @param scene
  •      The scene that will be rendered<br />
    
  • @param material
  •      The material to apply the texture to<br />
    
  • @param textureKey
  •      The texture key used to apply the texture<br />
    

*/

public OffscreenProcessor(AssetManager assetManager, Node scene,

Material material, String textureKey) {

this.assetManager = assetManager;

this.offscreenScene = scene;

this.material = material;

this.textureKey = textureKey;



init();

}



/**

  • Pre-initializes the processor

    */

    private void init() {

    fpp = new FilterPostProcessor(assetManager);



    // update the state of the offscreen scene

    offscreenScene.updateGeometricState();



    texture = new Texture2D(renderWidth, renderHeight, Format.RGBA8);



    offscreenCam = new Camera(renderWidth, renderHeight);

    }



    /**
  • Sets the size of the offscreen texture

    *
  • @param width
  • @param height

    /

    public void setTextureSize(int width, int height) {

    this.renderWidth = width;

    this.renderHeight = height;



    init();

    }



    /

  • (non-Javadoc)

    *
  • @see
  • com.jme3.post.SceneProcessor#initialize(com.jme3.renderer.RenderManager,
  • com.jme3.renderer.ViewPort)

    /

    @Override

    public void initialize(RenderManager rm, ViewPort vp) {

    this.rm = rm;



    // create a pre-view. a view that is rendered before the main view

    offscreenView = rm.createPreView(“Offscreen View”, offscreenCam);

    offscreenCam.setFrustum(vp.getCamera().getFrustumNear(), vp.getCamera()

    .getFrustumFar(), vp.getCamera().getFrustumLeft(), vp.getCamera()

    .getFrustumRight(), vp.getCamera().getFrustumTop(), vp.getCamera()

    .getFrustumBottom());

    offscreenView.setClearEnabled(true);

    offscreenView.setBackgroundColor(backgroundColor);

    // create offscreen framebuffer

    offscreenBuffer = new FrameBuffer(renderWidth, renderHeight, 0);

    // setup framebuffer to use texture

    offscreenBuffer.setDepthBuffer(Format.Depth);

    offscreenBuffer.setColorTexture(texture);



    // set viewport to render to offscreen framebuffer

    offscreenView.setOutputFrameBuffer(offscreenBuffer);



    // attach the scene to the viewport to be rendered

    offscreenView.attachScene(offscreenScene);



    // apply the texture

    material.setTexture(textureKey, texture);



    // add the filter, if desired

    if (ssaoConfig != null) {

    SSAOFilter ssaoFilter = new SSAOFilter(offscreenView, ssaoConfig);

    fpp.addFilter(ssaoFilter);

    offscreenView.addProcessor(fpp);

    }

    }



    /

  • (non-Javadoc)

    *
  • @see com.jme3.post.SceneProcessor#reshape(com.jme3.renderer.ViewPort, int,
  • int)

    /

    @Override

    public void reshape(ViewPort vp, int w, int h) {

    }



    /

  • (non-Javadoc)

    *
  • @see com.jme3.post.SceneProcessor#isInitialized()

    /

    @Override

    public boolean isInitialized() {

    return rm != null;

    }



    /

  • (non-Javadoc)

    *
  • @see com.jme3.post.SceneProcessor#preFrame(float)

    /

    @Override

    public void preFrame(float tpf) {

    }



    /

  • (non-Javadoc)

    *
  • @see
  • com.jme3.post.SceneProcessor#postQueue(com.jme3.renderer.queue.RenderQueue)

    /

    @Override

    public void postQueue(RenderQueue rq) {

    }



    /

  • (non-Javadoc)

    *
  • @see com.jme3.post.SceneProcessor#postFrame(com.jme3.texture.FrameBuffer)

    /

    @Override

    public void postFrame(FrameBuffer out) {

    }



    /

  • (non-Javadoc)

    *
  • @see com.jme3.post.SceneProcessor#cleanup()

    */

    @Override

    public void cleanup() {

    }



    /**
  • Getter for the camera

    *
  • @return The camera of the offscreen scene

    */

    public Camera getCamera() {

    return offscreenCam;

    }



    /**
  • Set true to use SSAO in the offscreen scene

    *
  • @param useSSAO

    */

    public void enableSSAO(SSAOConfig ssaoConfig) {

    this.ssaoConfig = ssaoConfig;

    }



    /**
  • Getter for the material to render to

    *
  • @return

    */

    public Material getMaterial() {

    return material;

    }



    /**
  • Getter for the offscreen scene

    *
  • @return

    */

    public Node getScene() {

    return offscreenScene;

    }



    /**
  • Getter for the background color of the scene

    *
  • @return

    */

    public ColorRGBA getBackgroundColor() {

    return backgroundColor;

    }



    /**
  • Setter for the background color of the scene

    *
  • @param backgroundColor

    */

    public void setBackgroundColor(ColorRGBA backgroundColor) {

    this.backgroundColor = backgroundColor;



    if (isInitialized()) {

    offscreenView.setBackgroundColor(backgroundColor);

    }

    }



    }

    [/java]



    I also extended the test:



    [java]package jme3test.texture;



    import com.jme3.app.SimpleApplication;

    import com.jme3.light.PointLight;

    import com.jme3.material.Material;

    import com.jme3.math.ColorRGBA;

    import com.jme3.math.Vector3f;

    import com.jme3.post.ssao.SSAOConfig;

    import com.jme3.renderer.queue.RenderQueue.ShadowMode;

    import com.jme3.scene.Geometry;

    import com.jme3.scene.Node;

    import com.jme3.scene.Spatial;

    import com.jme3.scene.shape.Box;

    import com.jme3.texture.OffscreenProcessor;



    public class TestOffscreenRendering extends SimpleApplication {

    private Spatial teapot;

    private Geometry box;



    private OffscreenProcessor processor;



    public static void main(String[] args) {

    TestOffscreenRendering app = new TestOffscreenRendering();

    app.start();

    }



    @Override

    public void simpleInitApp() {

    cam.setLocation(new Vector3f(0, 1, 3));

    cam.lookAt(Vector3f.ZERO, Vector3f.UNIT_Y);



    // init the teapot and the teapot material

    Material teapotMat = new Material(assetManager,

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

    teapotMat.setFloat(“m_Shininess”, 0.1f);

    teapotMat.setBoolean(“m_UseMaterialColors”, true);

    teapotMat.setColor(“m_Ambient”, ColorRGBA.Black);

    teapotMat.setColor(“m_Diffuse”, ColorRGBA.Red);

    teapotMat.setColor(“m_Specular”, ColorRGBA.Gray);

    teapotMat.setReceivesShadows(true);



    teapot = assetManager.loadModel(“Models/Teapot/Teapot.obj”);

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

    teapot.setMaterial(teapotMat);

    teapot.setShadowMode(ShadowMode.CastAndReceive);



    // init offscreen scene

    Node offScreenScene = new Node();

    offScreenScene.attachChild(teapot);

    PointLight l = new PointLight();

    l.setPosition(new Vector3f(5, 5, 5));

    offScreenScene.addLight(l);



    Material offscreenMat = new Material(assetManager,

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

    offscreenMat.setFloat(“m_Shininess”, 1.0f);

    offscreenMat.setBoolean(“m_UseMaterialColors”, true);

    offscreenMat.setColor(“m_Ambient”, ColorRGBA.Black);

    offscreenMat.setColor(“m_Diffuse”, ColorRGBA.White);

    offscreenMat.setColor(“m_Specular”, ColorRGBA.Gray);

    offscreenMat.setReceivesShadows(true);



    // init the processor with the material. it will render to m_DiffuseMap

    processor = new OffscreenProcessor(assetManager, offScreenScene,

    offscreenMat, “m_DiffuseMap”);



    // add a ssao effect

    processor.enableSSAO(new SSAOConfig(2.5f, 1.5f, 3f, -0.1f, false, true));



    processor.getCamera().setLocation(new Vector3f(0f, .2f, 2f));

    processor.getCamera().lookAt(new Vector3f(0f, .4f, 0f), Vector3f.UNIT_Y);

    viewPort.addProcessor(processor);



    // init the box to render to

    box = new Geometry(“box”, new Box(new Vector3f(0f, 0f, 0f), .5f, .5f, .5f));

    box.setMaterial(offscreenMat);

    box.setShadowMode(ShadowMode.CastAndReceive);

    rootNode.attachChild(box);



    l = new PointLight();

    l.setPosition(new Vector3f(5, 5, 15));

    rootNode.addLight(l);

    }



    @Override

    public void simpleUpdate(float tpf) {

    box.rotate(0, tpf, 0);



    teapot.rotate(0, tpf * -.5f, 0);

    processor.getScene().updateGeometricState();

    }

    }

    [/java]



    If the offscreen scene is changed from outside, I need to call updateGeometricState(). I think thats dirty. I tried to call it on the preFrame() method in the processor, but it didn’t prevent IllegalStateException.

Good thank you.

About enableSSAO, and the FilterPostProcessor, maybe it would be more flexible to allow the user to add any processor he may need : FilterProcessor with any Filters, or a shadow processor, HDR etc…

Thats a problem. The filter constructors require a viewport, which hasn’t been created until the processor is initialized.

good point.



i’m gonna look into that

Is the render manager for processors the same instance as the rendermanager for the main app?

If so, I can create the viewport in the constructor instead of the processor init method.

But the speed-thing isn’t really the solution for my problem.

I’ve created a SceneAppState which contains the basic scene stuff: a camera, a viewport, a root node references to the assetmanager, the inputmanager, the renderer and the timer. Thats all I need to build a basic scene. But I can not simply turn it off so it isn’t updated nor rendered. For this case I want the setActive() and isActive() methods because I think it’s a dirty hack to attach/detach it everytime I want to switch the scene.



I understand your opinion that the AppStates are nothing more than an abstract concept, but they could provide much more than that to the developer.



By the way: the guiNode and guiViewPort in SimpleApplication could be put into their own AppState to turn a hud or statsview on or off. :wink:

I have looked into the appstate example, but can not find much state stuff in there. It seems to me the AppStates are not more than a draft and now not ready to use. In JME2 you have a statemanager that can active/deactive states and switch between them.



I need a state with physics and an own viewport or camera. Tried to merge SimpleBulletApplication and AppState, with no success. :frowning:

No, AppStates are working, I use them in jMP already. You can add and remove them with the stateManager. There is no static method to do that because in jME3 we try to avoid those static methods to keep the engine “objective” and allow multiple instances of the subsystems. You can create a static accessor yourself if you want but you wont see it in the engine.



The “GameStates” of jME2 were nothing more than a bunch callbacks from the render thread despite the fact that the now old “new way of thinking” wiki article for jME2 somehow sold it as a multithreading system. AppStates are exactly that.

We will probably move the physics to an AppState soon, so in the future to have physics you will simply add the BulletAppState or something to your SimpleApplications stateManager to enable physics.



Cheers,

Normen

I just thought about it again. Additional appstates need no viewport, I just have to set the cam and the rootnode of the appstate to the main viewport.



I think AppStates are an encapsulation of scenes to switch between them, or am I wrong?



What I am missing is the ability to activate/deactivate the appstates.



That would be a small change.

In the AppState interface I need to methods:

[java]public void setActive(boolean active);

public boolean isActive();

[/java]



And then the AppStateManager has to check for it:

[java] public void update(float tpf){

synchronized (states){

int num = states.size();

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

AppState state = states.get(i);

if (state.isActive()){

if (!state.isInitialized())

state.initialize(this, app);



state.update(tpf);

}

}

}

}



/**

  • Calls render for all attached states, do not call directly.
  • @param rm The RenderManager

    */

    public void render(RenderManager rm){

    synchronized (states){

    int num = states.size();

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

    AppState state = states.get(i);

    if (state.isActive()){

    if (!state.isInitialized())

    state.initialize(this, app);



    state.render(tpf);

    }

    }

    }

    }[/java]



    Furthermore the following methods would be nice in AppStateManager:

    [java]public void activateState(AppState state){

    state.setActive(true);

    }

    public void deactivateState(AppState state){

    state.setActive(false);

    }

    [/java]

I dont know what version of AppState you are using, but all the functionality you ask for is there, although we will probably add some “preXXX” and “postXXX” methods. An AppState can do anything to the scene or cam. It can create a new one and render that, it can use the current scene to switch the models inside… The NiftyGUI example also uses an AppState for the gui.



I implemented Physics as an AppState now: http://code.google.com/p/jmonkeyengine/source/detail?r=5951

SimpleBulletApplication is still there but its deprecated now, it shows how to use the BulletAppState.



Cheers,

Normen

We can definitely add the setActive()/isActive() methods. You don’t need the callbacks however as you can just override setActive.

Wow that was fast, nice work. I just wonder, the physics update is called in the render method, not the update method? Won’t that slow down the rendering when many physics nodes are updated sequentially?



get/setActive methods would be nice :slight_smile:

Its got a setSpeed method.

It does not matter when the physics update is happening in the loop, it will always take time. Physics update and rendering can be seen as the same thing, they happen when the user finished modifying the scenegraph. In fact, its now even easier possible to do “parallel” physics. Meaning physics update is done during rendering on another thread.

Cheers,

Normen