Sorry for all the questions but hopefully this will be the last one for a while as once I’ve solved this it should be full steam ahead!
For the game I’m working on we need to render different textures onto an object, with those textures being built dynamically but changing infrequently (they will be static most of the time once created). For example a card might have a picture of a hero with that hero’s name above it and stats down the side. That name would virtually never change and the stats would rarely change but they would be different for each hero (and hence need generating separately for each one).
The obvious way forwards would be to create the textures using Java2D but I’d like to keep platform compatibility and not have to write everything twice (once for android, once for everywhere else). One reason I picked jME is because of the high quality and convenient cross-platform deployment support.
I found http://hub.jmonkeyengine.org/groups/contribution-depot-jme3/snippets/14/ but that involves pixel-level operations. It would need enhancing a lot to allow images and text to be drawn into the texture in non-painful ways. The other similar things I found were JME2 and/or used Java2D.
I tried this and it did work well but there was a problem: Framerate with 3 cards spinning in space dropped from something like 2500 fps to 900fps, this is a massive overhead and so far only with 3 cards being rendered when potentially there could be hundreds on screen.
I then investigated the way the Nifty projection works and it looks like it is being rendered into the texture every frame for every card - which obviously for mostly static data seems like massive overkill. Ideally what I’d like to do is have one Nifty instance, use that to render the textures and then save those textures for use and only go back to nifty when a value changes and the texture needs re-rendering.
I tried to set that up by detaching the Nifty view from the renderManager but I just ended up with a plain black texture so I guess I did something wrong there.
Ok, I’ve spent some more time on this today and I think I’ve cracked it. What I have is working but considering my unfamiliarity with the system I thought I’d ask if any of the more experienced jME/Nifty people here would mind taking a look. If it looks generally useful I’m happy to release this as a code fragment with whatever license is usually used for that sort of thing.
[java]
public class NiftyTexture {
private Nifty nifty = null;
private Texture2D workingTexture = null;
private ViewPort niftyView = null;
private final int width;
private final int height;
private final SimpleApplication jme3;
public NiftyTexture(int width, int height, SimpleApplication jme3) {
this.width = width;
this.height = height;
this.jme3 = jme3;
// Will just use standard plain colour material until nifty is ready
jme3.enqueue(new Callable<Object>() {
@Override
public Object call() throws Exception {
niftyView = new ViewPort(“NiftyView”, new Camera(NiftyTexture.this.width, NiftyTexture.this.height));
niftyView.setClearFlags(true, true, true);
NiftyJmeDisplay niftyDisplay = new NiftyJmeDisplay(NiftyTexture.this.jme3.getAssetManager(),
One mistake I already realised was doing the thread safety stuff inside the NiftyTexture class when it may well be used from the jme thread so I’ve moved that outside and/or made it optional.
I’ve posted a patch for nifty that fixes the controller problem, I’ve no idea how long it will take for that to be applied and filter through into JME though. For now I’m using reflection to access the field directly but that won’t work if a security manager gets involved.
I also ran into a problem with textures being shared/copied - essentially I didn’t seem to be able to take a copy of the texture at the end of the method running and get anything but black. If I recreate the frame buffer at the start of the render call that makes things work but that seems wasteful and I was also worried that there might be hidden race conditions. I did try creating 100 at once and checked they all created correctly though which means race conditions are at least not common.
Does anyone know how I’m supposed to take a copy of a texture/image that won’t be shared with the original? I’ve tried clone on both texture and image and even creating a new image with get/set data and I get either one image with two references or blackness.