Buffer overflow when using geometrybatchinstance in my own scene

Hey guys,



I'm stumped by this buffer overflow when I try to use the TestGeometryInstancing code in my own code.



This is the stack:

[ERROR] (GameTask.java:152)   Exception
Jan 4, 2009 6:37:38 PM class com.jme.util.GameTask invoke()
SEVERE: Exception
java.nio.BufferOverflowException
   at java.nio.DirectFloatBufferU.put(DirectFloatBufferU.java:303)
   at com.jme.scene.geometryinstancing.GeometryBatchInstance.commit(GeometryBatchInstance.java:82)
   at com.jme.scene.geometryinstancing.instance.GeometryBatchCreator.commit(GeometryBatchCreator.java:91)
   at nl.tygron.constructit.client.jme.MaquetteBlockModelBuilder.update(MaquetteBlockModelBuilder.java:307)
   at nl.tygron.sge.client.jme.map.SimMap$2.call(SimMap.java:707)
   at com.jme.util.GameTask.invoke(GameTask.java:140)
   at com.jme.util.GameTaskQueue.execute(GameTaskQueue.java:111)
   at com.jmex.awt.lwjgl.LWJGLCanvas.paintGL(LWJGLCanvas.java:136)
   at org.lwjgl.opengl.AWTGLCanvas.paint(AWTGLCanvas.java:290)
   at org.lwjgl.opengl.AWTGLCanvas.update(AWTGLCanvas.java:321)
   at sun.awt.RepaintArea.updateComponent(RepaintArea.java:267)
   at sun.awt.RepaintArea.paint(RepaintArea.java:233)
   at apple.awt.ComponentModel.handleEvent(ComponentModel.java:268)
   at java.awt.Component.dispatchEventImpl(Component.java:4144)
   at java.awt.Component.dispatchEvent(Component.java:3903)
   at java.awt.EventQueue.dispatchEvent(EventQueue.java:463)
   at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:269)
   at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:190)
   at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:184)
   at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:176)
   at java.awt.EventDispatchThread.run(EventDispatchThread.java:110)



this is the offending piece of code: (line where error occurs commented)

   public void update() {

      // Rewind the buffers in the mesh
      rewindBatchBuffers(mesh);

      // Set the buffers that should be updated
      updateBuffers.setVertexBuffer(mesh.getVertexBuffer());
      updateBuffers.setColorBuffer(mesh.getColorBuffer());
      updateBuffers.setNormalBuffer(mesh.getNormalBuffer());
      updateBuffers.setTextureCoords(mesh.getTextureCoords(0), 0);

      // Commit the instances to the mesh batch
      geometryBatchCreator.commit(updateBuffers); // Bufer overflow here
      mesh.updateModelBound();
   }


Note: This routine is only called when instances have changed.

The batch is inited like so:

   public void prepareRootNode(Node rootNode) {

      // Create a TriMesh
      mesh = new TriMesh();
      mesh.setModelBound(new BoundingBox());

      // Create the batch's buffers
      mesh.setIndexBuffer(BufferUtils.createIntBuffer(geometryBatchCreator.getNumIndices()));
      mesh.setVertexBuffer(BufferUtils.createVector3Buffer(geometryBatchCreator.getNumVertices()));
      mesh.setNormalBuffer(BufferUtils.createVector3Buffer(geometryBatchCreator.getNumVertices()));
      mesh.setTextureCoords(new TexCoords(BufferUtils.createVector2Buffer(geometryBatchCreator.getNumVertices())), 0);
      mesh.setColorBuffer(BufferUtils.createFloatBuffer(geometryBatchCreator.getNumVertices() * 4));

      // mesh.setRenderState(ls);
      // mesh.setRenderState(ms);
      // mesh.setLightCombineMode(LightCombineMode.CombineClosestEnabled);

      // Commit the instances to the mesh batch
      geometryBatchCreator.commit(mesh);

      // Add it to the given rootNode
      rootNode.attachChild(mesh);
      rootNode.updateRenderState();
   }


Note: Though it's called "rootNode", I can only access a node that's a couple of nodes up in the tree at that point. So I'm adding the mesh to that. Is that a problem?

Also, rewind methods:

   /**
    * Rewind a Buffer if it exists
    */
   private void rewindBuffer(Buffer buf) {
      if (buf != null) {
         buf.rewind();
      }
   }

   /**
    * Rewind a Buffer if it exists
    */
   private void rewindBuffer(TexCoords tc) {
      if (tc != null && tc.coords != null) {
         tc.coords.rewind();
      }
   }

   /**
    * Rewind all buffers in a batch
    */
   public void rewindBatchBuffers(TriMesh batch) {
      rewindBuffer(batch.getIndexBuffer());
      rewindBuffer(batch.getVertexBuffer());
      rewindBuffer(batch.getColorBuffer());
      rewindBuffer(batch.getNormalBuffer());
      ArrayList<TexCoords> textureBuffers = batch.getTextureCoords();
      for (TexCoords textureBuffer : textureBuffers) {
         rewindBuffer(textureBuffer);
      }
   }



Relevant fields in my class:

   /** The mesh containing the created batch */
   private TriMesh mesh;

   /** The batch creator */
   private GeometryBatchCreator geometryBatchCreator = new GeometryBatchCreator();

   /** A batch refering to the buffers that should be updated */
   private TriMesh updateBuffers = new TriMesh();

   /** A box that will be instantiated */
   private Box maquetteBlockTemplate = new Box("MaquetteBlock", Vector3f.ZERO.clone(), new Vector3f(
           (AbstractCIMap.BLOCK_LENGTH_IN_REAL_WORLD_METERS - 2.5f) / 2, 1f, (AbstractCIMap.BLOCK_LENGTH_IN_REAL_WORLD_METERS - 2.5f) / 2));



And finally instance creation:

   private GeometryBatchInstance createBlock(Vector3f translation, float height, ColorRGBA color) {
      // Box instance attributes
      GeometryBatchInstanceAttributes attributes = new GeometryBatchInstanceAttributes( //
              translation, // Translation
              new Vector3f(0, height / 2, 0), // Scale
              new Quaternion().fromAngles(0.0f, 0.0f, 0.0f), // Rotation
              color); // Color

      // Box instance (batch and attributes)
      GeometryBatchInstance instance = new GeometryBatchInstance(maquetteBlockTemplate, attributes);

      // Add the instance
      geometryBatchCreator.addInstance(instance);
      return instance;

   }



I figure it's pretty hard to debug without the same scene build-up on your side, I'll try to reproduce it in a small test.. But until then, any ideas how to get on track debugging this one?

Thanks in advance,
Alex

Hm, looks like running the code in prepareRootNode() with an empty batch creator and then filling it later is the problem… still getting it to work though.

new Vector3f(0, height / 2, 0), // Scale


lol, setting the scale to 1 might help :)