Texture Coordinates became crazy when lockMesh() was used

I loaded a simple model and try to add a texture to a node of my model.

I would use lockMesh() to my node to improve my program but when i call lockMesh the texture coordinates became crazy and so my texture was'nt displayed. When i comments the "boat.lockMesh()" the texture displays fine.


Node boat = (Node) BinaryImporter.getInstance().load(openStream);
Node find = findNode("mainSail-node", boat);
if (find != null) {
     Texture text = TextureManager.loadTexture(texture);
     TextureState texState = DisplaySystem.getDisplaySystem().getRenderer().createTextureState();
       find.setRenderState(texState);
       texState.setTexture(text);
       find.updateRenderState();
}
       boat.setLocalScale(.1f);
       boat.setModelBound(new BoundingSphere());
       boat.updateModelBound();
       rootNode.attachChild(boat);
       boat.lockMeshes();



Do someone know what exatly do lockMesh()? (I trace the code without found an answer)
And why the lockMesh break my texture coordinate?

Thanks you in advance  :D

Hello everybody,

In SharedMesh (JME 2.0 version), the method lockMeshes() locks the target of the SharedMesh but the unlock() method (inherited from Geometry.java) doesn't affect the target mesh and do nothing because the display list ID is equal to -1 :|



public void lockMeshes(Renderer r) {
        target.lockMeshes(r);
}



But in Geometry.java:


public void unlockMeshes(Renderer r) {
        lockedMode &= ~LOCKED_MESH_DATA;
        if (getDisplayListID() != -1) {
            r.releaseDisplayList(getDisplayListID());
            setDisplayListID(-1);
        }
}



Could someone explain me the lockMeshes() mechanism for SharedMesh ?? Is there an error somewhere?

Thanks for your answers!  :)

Ideally you would call lock and unlock on the target once and never do it through the Shared copy, but for consistency I think it would be correct to also override and point unlock at the target.

Hi everyBody!

Thank you renanse for your answer. I agree with you the lock and unlock should be done once on target.

But my problem is that my texture doesn't appears when lock is used.



I will present to you this problem using my custom HelloModelLoading example:

I load a DAE file that contains a simple box using the colladaImporter (so i've got a shareNode!). I apply the monkey texture because i love it! I lock my box to optimize the display and i add my box to the rootNode.

But no texture appears!



When i add the textureState to the targetmesh after got it (with an awful code i know), the texture appears!!!



// Point to a URL of my model : a simple box
URL model = HelloModelLoading.class.getResource("box.DAE");

// The Monkey texture
URL texture = HelloModelLoading.class.getResource("Monkey.jpg");
InputStream openStream = null;
try {
  openStream = model.openStream();
} catch (IOException e1) {
  e1.printStackTrace();
}
// Load the box using the ColladaImporter
ColladaImporter.load(openStream, "box");
m_box = ColladaImporter.getModel();
ColladaImporter.cleanUp();

// Create a texture with texture URL
Texture text = TextureManager.loadTexture(texture);
// Create a texture state
TextureState texState = DisplaySystem.getDisplaySystem().getRenderer().createTextureState();
texState.setTexture(text);
// Apply the texture state to the box and update
m_box.setRenderState(texState);
m_box.updateRenderState();
      
////////////////////////////////////////////////
////////////////MY HACK SOLUTION///////////////
//Gets the shareMesh with an awful code...
Spatial shareMesh = m_box;
while (!TriMesh.class.isInstance(shareMesh)) {
  if (Node.class.isInstance(shareMesh)) {
    shareMesh = ((Node) shareMesh).getChild(0);
  } else if (!TriMesh.class.isInstance(shareMesh)) {
  System.err.println("error");
  }
}
//Gets the target trimesh
TriMesh target = ((SharedMesh) shareMesh).getTarget();
//Sets a textureState
target.setRenderState(texState);
////////////////////////////////////////////////
      
// Lock the box to optimize display
m_box.lockMeshes();
      
// Put her on the scene graph
rootNode.attachChild(m_box);





As far as I'm concerned, i think the texture isn't activate if the target havent got a textureState.
When i lock my box, i know that the target is locked so the display list is build from the target but if the target havent got a texture state the texture arent activate and so doesn't appear.

I would know if this process is normal??? and Does another (cleaner and more simple) solution exist?

thanks you in advance
:D

I need to display many times the same mesh and to change the textures of the meshes on the fly. So, I would like to create some SharedMesh, lock the target mesh, and then change their texture states. But I have a few problems :

The behavior of lockMeshes() is to lock vertex, texcoord, normal and color data. But when lockMeshes() is called, a display list is generated and if the target of the SharedMesh doesn't have a TextureState, the texture coordinates are not added to the display list and will never be added :


protected boolean predrawGeometry(Geometry g) {
....
        TextureState ts = (TextureState) context.currentStates[RenderState.RS_TEXTURE];
        int offset = 0;
        if (ts != null) {
            .... // Add the texture coordinates to the list
        }
...
}




The only way to have the textures coordinates activated and the SharedMesh locked seems to be by adding a dummy TextureState on the target mesh just before the lockMeshes() call.

Is there a better way to do that?? :|


To me it seems like a totally point-less optimization, if you are not planning to texture the mesh you won't set texture cordinates. That reminds me, I had some issues with displaylists before and texturing was one of them.