Unable to update renderstates on 3ds model after loading

ok, I've literally spent about 3 hours messing with this and trying to find a solution on the forum.  I have no idea what I am doing wrong, or perhaps not doing at all.



I have a simple 3DS model exported with no texture but with texture coordinates in place (Applied UVW mapping modifier, set it up the way I want, and checked "preserve texture coordinates" on export) that I have converted to a .jme file.



I can load the model just fine, but when i try to apply a texture to it nothing happens.  I'd like to load multiple instances of this object but then have different textures for each loaded instance (red, green, blue textures for example).  Here is what I believe to be the relevant code but if more info is needed or the model itself is needed just let me know.



// Red Texture
URL redLoc = KeyboardHero.class.getClassLoader().getResource("data/textures/red.png");
TextureState redTex = DisplaySystem.getDisplaySystem().getRenderer().createTextureState();
Texture redMap = TextureManager.loadTexture(redLoc,
    Texture.MM_LINEAR_LINEAR, Texture.FM_LINEAR, Image.GUESS_FORMAT_NO_S3TC, 2f, true);
redTex.setTexture(redMap);
redTex.setEnabled(true);

// Material State
MaterialState ms = DisplaySystem.getDisplaySystem().getRenderer().createMaterialState() ;
ms.setDiffuse(new ColorRGBA(0.5f, 0.5f, 0.5f, 1.0f));
ms.setAmbient(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
ms.setEnabled(true);

URL modelURL=Test3DS.class.getClassLoader().getResource("data/models/note.jme");
try {
    Node model = (Node)BinaryImporter.getInstance().load(modelURL);
    model.setName("Red Model");
    rootNode.attachChild(model);
    model.setLocalScale(0.1f);
    model.setLocalTranslation(new Vector3f(-5.1f, -45, 0));

    //model.getRenderState(RenderState.RS_TEXTURE).setEnabled(false);  // Doing this makes the model invisible

    // Clear all states on the parent node and child node - probably don't need to do both
    model.clearRenderState(RenderState.RS_TEXTURE);
    model.clearRenderState(RenderState.RS_MATERIAL);
    model.getChild(0).clearRenderState(RenderState.RS_TEXTURE);
    model.getChild(0).clearRenderState(RenderState.RS_MATERIAL);
    model.getChild(0).updateRenderState();
    model.updateRenderState();

    // Apply new texture and material state to child node
    model.getChild(0).setRenderState(redTex);
    model.getChild(0).setRenderState(ms);
    model.getChild(0).updateRenderState();
} catch ( Exception e ) {
    e.printStackTrace();
}



This all happens inside the simpleInitGame() method of a SimplePassGame (using a bloom pass if that helps).  The model only has one "part" hence only one child node which I believe to be the right one to set the new renderstates on.

Any help with this would be great.  I'm totally stumped at this point.

Are you attaching 'model' to the rootNode? Is there a LightState set on the scene? (required for MaterialState)

Momoko_Fan said:

Are you attaching 'model' to the rootNode? Is there a LightState set on the scene? (required for MaterialState)


Yes, I attach it to the rootNode right after loading it:


Node model = (Node)BinaryImporter.getInstance().load(modelURL);
model.setName("Red Model");
rootNode.attachChild(model); // ********



Edit:  In my real implementation of this I do NOT plan to attach these models to the rootNode - is that going to be an issue?  Just wondering since you specifically asked if I attached it to the rootNode rather than just asking if it was 'added to the scene'.

And yes, there is a lightstate:


PointLight light = new PointLight();
light.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
light.setAmbient(new ColorRGBA(0.6f, 0.6f, 0.6f, 1.0f));
light.setLocation(new Vector3f(0, 30, 0));
light.setEnabled(true);
lightState.attach(light);



If I change the colors on the material state I do see that reflected in the scene, so I assume that means it's working but I want the coloring to come from the texture (it's a mix of red and white).

Do you have UV texture coordinates for you model? Unless you do UV-mapping, your model does not have any texture coordinates, and applying a texture state to the model will not work.

chirstius said:

Edit:  In my real implementation of this I do NOT plan to attach these models to the rootNode - is that going to be an issue?  Just wondering since you specifically asked if I attached it to the rootNode rather than just asking if it was 'added to the scene'.

Since you're using SimplePassGame your 'scene' is the rootNode.

Texture redMap = TextureManager.loadTexture(redLoc,
    Texture.MM_LINEAR_LINEAR, Texture.FM_LINEAR, Image.GUESS_FORMAT_NO_S3TC, 2f, true);


It seems that you're using an invalid anisotropic value there, anisotropy value must be between 0 and 1 (was changed in a recent jME update)
lex said:

Do you have UV texture coordinates for you model? Unless you do UV-mapping, your model does not have any texture coordinates, and applying a texture state to the model will not work.


Is there some way to verify this?  If I export the model with a texture it maps correctly.  I did nothing but delete the texture from the model in 3DS MAX.  I have tried the exact same code WITH the texture still on it and nothing happened - meaning the original texture simply stayed in place and was not cleared or replaced.  Because I thought I might be losing the tex coords by deleting the texture map itself, I specifically added a UVW Mapping modifier to my model within 3DS MAX and set it up to map the texture how I want it.  Then, when exporting I made sure to check 'Preserve Max's texture coordinates' or whatever it says.

I am using 3DS MAX 5.1 which I bought ages ago and which I cannot afford to upgrade.  I don't know if that has anything to do with it.

If you know of how I can verify that tex coords are being set let me know and I'll give it a shot.
Momoko_Fan said:

Since you're using SimplePassGame your 'scene' is the rootNode.


Yes, but eventually it won't be, these models will be in a separate node off the scene root - will that matter?

Momoko_Fan said:

It seems that you're using an invalid anisotropic value there, anisotropy value must be between 0 and 1 (was changed in a recent jME update)


Thanks for the info.  I'll update that.  Surprised jME never complained about it.

Just bumping this, I've moved on to other pieces for the time being but I still can't seem to make this work.  Is there any other data/code/whatever I can post that might make it easier to see what's going wrong here?

You could make a testcase with your problem. As an added benefit, narrowing down the problem to a simple test case usually results in finding the solution.



Another thing you can test is substituting simple jme objects like a sphere or a box instead of 3d max models in your code. This way if the texturing works on simple object, you know the problem is with models. And if it doesn't work with simple objects, the problem is somewhere in the code.

I'll see if I can get a simple case put together and offer up the model and textures so other people can try it.



On a side note, did you see my previous message?  Is there any easy way you know of to confirm that tex coords are indeed in place on my exported model?  Is there a tool or a simple test I can do in jME to verify this?  Trying to get the tex coords array or something off the node?

Is there any easy way you know of to confirm that tex coords are indeed in place on my exported model?

I don't know any tools to do that. At some point I had to write a scene-graph parser that prints the info and can add, remove or modify render states and other properties. But it's very raw code and I wouldn't release it just yet.
Other than that, you could save your model as ".jme" and load it into MonkeyWorld3D. There you can find out if you have the texture coordinate array, and figure out how to reach it via getters. Then you could even print it.

The easies way to test your UV-coordinates is to export a model with a texture, load it and see if the texture is applied correctly. Then you can swap that texture for some other texture, if you know how to reach your texture states via getters.
chirstius said:

Is there a tool or a simple test I can do in jME to verify this?  Trying to get the tex coords array or something off the node?

Have you tried TriMesh.getTextureBuffer() ?

Ok, this is solved.  Feel like an idiot.  Thanks to heevee and lex.



Created a greatly simplified test case and through trial and error found a "hidden" (to me) node which is where I needed to be clearing and setting the texture and material states.



I must say, some kind of scenegraph dumper/browser would have been very helpful here.  Once I found the node I was able to verify texture coords were indeed set correctly and the rest was butter.  Sorry for the idiocy.