ClodCreator gives java.lang.IndexOutOfBoundsException after update

I just updated, and my CLODed meshes that worked fine before now cause this exception:



java.lang.IndexOutOfBoundsException: 128
   at java.nio.DirectFloatBufferU.get(DirectFloatBufferU.java:209)
   at com.jme.scene.lod.ClodCreator.reorder(ClodCreator.java:522)
   at com.jme.scene.lod.ClodCreator.<init>(ClodCreator.java:208)
   at com.jme.scene.lod.ClodMesh.create(ClodMesh.java:146)
   at com.jme.scene.lod.ClodMesh.<init>(ClodMesh.java:127)
   at com.jme.scene.lod.ClodMesh.<init>(ClodMesh.java:101)
   at com.jme.scene.lod.AreaClodMesh.<init>(AreaClodMesh.java:98)
   at net.java.dev.aircarrier.planes.SimplePlaneModel.clodinate(SimplePlaneModel.java:228)
   at net.java.dev.aircarrier.planes.SimplePlaneModel.clodinate(SimplePlaneModel.java:226)
   at net.java.dev.aircarrier.planes.SimplePlaneModel.<init>(SimplePlaneModel.java:64)
   at net.java.dev.aircarrier.planes.HammerheadModel.<init>(HammerheadModel.java:39)
   at net.java.dev.aircarrier.CarrierSimpleLevelManagers.simpleInitGame(CarrierSimpleLevelManagers.java:565)
   at net.java.dev.aircarrier.CarrierGame.initGame(CarrierGame.java:560)
   at com.jme.app.BaseGame.start(BaseGame.java:56)
   at net.java.dev.aircarrier.CarrierSimpleLevelManagers.main(CarrierSimpleLevelManagers.java:179)



The "clodinate" code looks like this, and is called on the root of a loaded mesh tree:


   public void clodinate(Node model) {
      List<Spatial> children = model.getChildren();
      if (children != null) {
         for (Spatial c : children) {
            if (c instanceof Node) {
               clodinate((Node)c);
            } else if (c instanceof TriMesh) {
               AreaClodMesh clodMesh = new AreaClodMesh(c.getName(), (TriMesh)c, null);
               clodMesh.setTrisPerPixel(0.05f);
               model.detachChild(c);
               model.attachChild(clodMesh);
            }
         }
      }
   }



I haven't had a chance to look at this in detail, because I have to go to work :| I thought I would post it anyway since I ran exactly the same code just before and after the update so it seems likely to be a bug. I think it must be something pretty recent as well, since I was nearly up to date before I updated.

shingoki,



I saw that and posted about it in the Graphics forum; no response yet.



However, what I ended up doing was the below check



if ((((TriMesh)child).getColorBuffer(0) != null) &&
   ((TriMesh)child).getColorBuffer(0).hasRemaining() &&
   (((TriMesh)child).getTextureBuffers(0) != null) &&
   (((TriMesh)child).getTextureBuffers(0)[0] != null) &&
   ((TriMesh)child).getTextureBuffers(0)[0].hasRemaining())



As the clod creator would crash on TriMeshes that has neither a color or texture buffer.  I look at the ClodCreator itself and didn't see anything that had changed radically between latest and previous revisions, so potentially its something that is farther down in the engine?

Ah right… yup that is definitely where the problem is. In fact… if I don't use clod at all, it still gets an exception.



So, it turns out the problem is with JmeBinaryReader, which creates zero length buffers as "default" when loading. Some of these are then left over, and ClodCreator doesn't like this, since it only checks for null buffers, not zero length buffers. Even if you don't use ClodCreator, you get an exception at com.jme.renderer.lwjgl.LWJGLRenderer.predrawGeometry(LWJGLRenderer.java:1313) when the code tries to use the color buffer, assuming it is big enough, and of course it isn't :wink:



So… as a quick fix, I altered JmeBinaryReader to recursively strip away any zero length color and texture buffers after loading a node (replacing them with null), and this fixes everything  :smiley:



I'm just going to have a look through to see if there is a neater way of fixing JBR, I think there must be :slight_smile:


Yup I think I found the right way to fix it, but I could be wrong. This fixes the problem for me, without any obvious side effects anyway :slight_smile:



The following is (hopefully) a patch to fix JmeBinaryReader. Basically just set null color and texture buffers instead of zero-length buffers, at two places in method readBegining().



Index: src/com/jmex/model/XMLparser/JmeBinaryReader.java
===================================================================
RCS file: /cvs/jme/src/com/jmex/model/XMLparser/JmeBinaryReader.java,v
retrieving revision 1.19
diff -u -r1.19 JmeBinaryReader.java
--- src/com/jmex/model/XMLparser/JmeBinaryReader.java   14 Mar 2007 01:03:11 -0000   1.19
+++ src/com/jmex/model/XMLparser/JmeBinaryReader.java   16 Mar 2007 22:56:41 -0000
@@ -244,8 +244,12 @@
             t.getBatch(0).setIndexBuffer(BufferUtils.createIntBuffer(0));
             t.getBatch(0).setNormalBuffer(BufferUtils.createFloatBuffer(0));
             t.getBatch(0).setVertexBuffer(BufferUtils.createFloatBuffer(0));
-            t.getBatch(0).setColorBuffer(BufferUtils.createFloatBuffer(0));
-            t.getBatch(0).setTextureBuffer(BufferUtils.createFloatBuffer(0), 0);
+           
+            //shingoki change start
+            t.getBatch(0).setColorBuffer(null);
+            t.getBatch(0).setTextureBuffer(null, 0);
+            //shingoki change end
+           
             objStack.push(processSpatial(t, attributes));
         }else if (tagName.startsWith("batch")) {
             if(!"batch0".equals(tagName)) {
@@ -263,8 +267,12 @@
                 }
                 batch.setNormalBuffer(BufferUtils.createFloatBuffer(0));
                 batch.setVertexBuffer(BufferUtils.createFloatBuffer(0));
-                batch.setColorBuffer(BufferUtils.createFloatBuffer(0));
-                batch.setTextureBuffer(BufferUtils.createFloatBuffer(0), 0);
+               
+                //shingoki change start
+                batch.setColorBuffer(null);
+                batch.setTextureBuffer(null, 0);
+                //shingoki change end
+
                 geo.addBatch(batch);
                 objStack.push(geo);
                 objStack.push(batch);

I'll apply this and have a look though it.

Well its also broken with the BinaryImporter too.

More than likely the clod stuff is related to changes made in using limit(), remaining() and capacity(), etc.  If I get a chance this weekend, I'll take a look at that.