Saving shared geometry issues

Hello!



I think there is a problem with the export of jme.scene.batch.SharedBatch.



I want use this class to share geometry without sharing render states and local transformation. So, I wrote a function which share all the triangle batches of a triangle mesh :


private static TriMesh buildTriMeshWithSharedBatches(String name, TriMesh mother) {
   TriMesh mesh = new TriMesh(name);
   mesh.clearBatches();
   for(int i=0; i<mother.getBatchCount(); ++i) {
      TriangleBatch batch = mother.getBatch(i);
      mesh.addBatch(new SharedBatch(batch));
   }
   return mesh;
}



The problem has come when I tried to export and re-import the results of this function :
Here is my code :


import java.io.File;
import java.io.IOException;

import com.jme.app.SimpleGame;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.Node;
import com.jme.scene.TriMesh;
import com.jme.scene.batch.SharedBatch;
import com.jme.scene.batch.TriangleBatch;
import com.jme.scene.shape.Box;
import com.jme.scene.state.MaterialState;
import com.jme.util.export.binary.BinaryExporter;
import com.jme.util.export.binary.BinaryImporter;


public class SharedBatchSystem extends SimpleGame {
   
   public static void main(String[] args) {
      SharedBatchSystem app = new SharedBatchSystem();
      app.start();
   }

   protected void simpleInitGame() {
      Box mother = new Box("mother", new Vector3f(-5, -5, -5), new Vector3f(5, 5, 5));
      
      Node savedNode = new Node("myNode");
      
      TriMesh mesh0 = buildTriMeshWithSharedBatches("mesh0", mother);
      mesh0.setLocalTranslation(new Vector3f(-10, 0, 0));
      MaterialState ms0 = display.getRenderer().createMaterialState();
      ms0.setDiffuse(ColorRGBA.blue);
      mesh0.setRenderState(ms0);
      savedNode.attachChild(mesh0);
      
      TriMesh mesh1 = buildTriMeshWithSharedBatches("mesh1", mother);
      mesh1.setLocalTranslation(new Vector3f(10, 0, 0));
      MaterialState ms1 = display.getRenderer().createMaterialState();
      ms1.setDiffuse(ColorRGBA.red);
      mesh1.setRenderState(ms1);
      savedNode.attachChild(mesh1);
      
//      rootNode.attachChild(savedNode);
      
      try {
         BinaryExporter.getInstance().save(savedNode, new File("C:/file.jme"));
      } catch (IOException e) {
         e.printStackTrace();
      }
      
      Node loadedNode = null;
      try {
         loadedNode = (Node)BinaryImporter.getInstance().load(new File("C:/file.jme"));
      } catch (IOException e) {
         e.printStackTrace();
      }
      
      rootNode.attachChild(loadedNode);
   }

   private static TriMesh buildTriMeshWithSharedBatches(String name, TriMesh mother) {
      TriMesh mesh = new TriMesh(name);
      mesh.clearBatches();
      for(int i=0; i<mother.getBatchCount(); ++i) {
         TriangleBatch batch = mother.getBatch(i);
         mesh.addBatch(new SharedBatch(batch));
      }
      return mesh;
   }
}



Here is the exception :


java.lang.NullPointerException
   at com.jme.scene.batch.SharedBatch.draw(SharedBatch.java:431)
   at com.jme.scene.TriMesh.draw(TriMesh.java:268)
   at com.jme.scene.Spatial.onDraw(Spatial.java:212)
   at com.jme.scene.Node.draw(Node.java:511)
   at com.jme.scene.Spatial.onDraw(Spatial.java:212)
   at com.jme.scene.Node.draw(Node.java:511)
   at com.jme.scene.Spatial.onDraw(Spatial.java:212)
   at com.jme.renderer.lwjgl.LWJGLRenderer.draw(LWJGLRenderer.java:1178)
   at com.jme.app.SimpleGame.render(SimpleGame.java:92)
   at com.jme.app.BaseGame.start(BaseGame.java:69)
   at SharedBatchSystem.main(SharedBatchSystem.java:21)



I think that jME do not save the "mother" TriangleMesh, and that is why there is an exception.

Does anyone could help me to solve my problem ?
I don't know if it is really a bug...

Thanks

Year !!! I find a possible fix for this "bug" :



I add some code to the com.jme.scene.batch.SharedBatch.read function :


    public void read(JMEImporter e) throws IOException {
        InputCapsule capsule = e.getCapsule(this);
        target = (TriangleBatch)capsule.readSavable("target", null);
   if(target.parentGeom==null) {
      TriMesh mesh = new TriMesh("");
      mesh.clearBatches();
      mesh.addBatch(target);
   }
        updatesCollisionTree = capsule.readBoolean("updatesCollisionTree", false);
        super.read(e);
    }



Is it a good fix ? If it is, could you send my fix on the repository please :) .


Thanks.

I found a little better implementation :



In com.jme.scene.batch.SharedBatch :


    private static TriMesh motherMesh = null;

    public void read(JMEImporter e) throws IOException {
        InputCapsule capsule = e.getCapsule(this);
        target = (TriangleBatch)capsule.readSavable("target", null);
      if(target.parentGeom==null) {
         if(motherMesh==null) {
            motherMesh = new TriMesh("mother");
            motherMesh.clearBatches();
         }
         motherMesh.addBatch(target);
      }
        updatesCollisionTree = capsule.readBoolean("updatesCollisionTree", false);
        super.read(e);
    }



So, I will post this patch to the tracker soon...

Thanks Targ, that looks like a good solution. I did verify the problem, but having integrated your solution locally for confirmation. Monday, I plan on doing another bulk CVS checkin at work (everybody cringe), so I'll get this in place then.

Thanks mojo monkey master !



I think it is a good idea to create a public CVS ! I want to add some minor feature to jME and I want to to know how to send my code on your new CVS repository.