Array index exception caused by TextureUnitState??

I’m following the getting started guide (my code isn’t exactly what is shown in the guide though) and I have a little program that uses all the functions taught up until multitexturing, but when I added multitexturing with the TextureUnitState[] array (it’s the only array I explicitly use in the program), the program fails to run, giving an ArrayIndexOutOfBoundsException. I’ve tried increasing the TextureUnitState[] array size by one during initalization and then adding a dummy TextureUnitState, but that doesn’t work either. Even though there are 2 or 3 objects in the array, index 1 is considered out of bounds. This to me is very odd, and I don’t know what I have done wrong. Could someone please tell me what this is caused by? Thanks.

Here is the Xith3DTest constructor, where the problem should lie. At the very end is the exception I get from the program.

  public Xith3DTest() {
      VirtualUniverse universe = new VirtualUniverse();

      View view = new View();
      universe.addView(view);

      Locale locale = new Locale();
      universe.addLocale(locale);

      BranchGroup scene = new BranchGroup();
      locale.addBranchGraph(scene);

      translate = new Transform3D();
      objTranslate = new TransformGroup(translate);
      scene.addChild(objTranslate);

      rotate = new Transform3D();
      objRotate = new TransformGroup(rotate);
      objTranslate.addChild(objRotate);

      Texture2D textureCube1, textureCube2 = null;
      TextureLoader tl = new TextureLoader();
      tl.registerPath(".");
      TextureUnitState[] textures = new TextureUnitState[2];
      textures[0] = new TextureUnitState((Texture2D)tl.getMinMapTexture("wormhole1.gif"), null, null);
      textures[1] = new TextureUnitState((Texture2D)tl.getMinMapTexture("wormhole2.gif"), null, null);
      
      Geometry g = Cube.createCubeViaTriangles(0, 0, 0, 1, false);
      Appearance a = new Appearance();
      a.setTextureUnitState(textures);
      Shape3D sh0 = new Shape3D(g, a);
      objRotate.addChild(sh0);

      Shape3D sh1 = new Shape3D(createTriangle());
      scene.addChild(sh1);

      Shape3D sh2 = new Shape3D(createCross());
      scene.addChild(sh2);

      Shape3D sh3 = new Shape3D(createXPoints());
      scene.addChild(sh3);

      Shape3D sh4 = new Shape3D(createQuad());
      objRotate.addChild(sh4);

      scene.compile();

      RenderPeer rp = new RenderPeerImpl();
      CanvasPeer cp = rp.makeCanvas(null, 800, 600, 32, false);
      Canvas3D canvas = new Canvas3D();
      canvas.set3DPeer(cp);
      cp.getComponent().addKeyListener(new KeyAdapter() {
          public void keyPressed(KeyEvent e) {
              switch(e.getKeyCode()) {
                    case KeyEvent.VK_UP            :      rotXtemp += 0.05;
                                                              isRotationScheduled = true;
                                                              break;
                    case KeyEvent.VK_DOWN      :      rotXtemp -= 0.05;
                                                                    isRotationScheduled = true;
                                                                    break;
                    case KeyEvent.VK_LEFT      :      rotYtemp += 0.05;
                                                                    isRotationScheduled = true;
                                                                    break;
                    case KeyEvent.VK_RIGHT      :      rotYtemp -= 0.05;
                                                                    isRotationScheduled = true;
                                                                    break;
              }
          }
          
          public void keyReleased(KeyEvent e) {
                int key = e.getKeyCode();
                if(            key == KeyEvent.VK_UP
                          ||       key == KeyEvent.VK_RIGHT
                          ||      key == KeyEvent.VK_DOWN
                          ||      key == KeyEvent.VK_LEFT) {
                      rotX = rotXtemp;
                      rotY = rotYtemp;
                }
          }

          public void keyTyped(KeyEvent e) {
              switch(e.getKeyCode()) {
                    case KeyEvent.VK_ESCAPE      :      System.exit(0); break;
              }
          }
      });
      Toolkit.getDefaultToolkit().addAWTEventListener(new EventListener(),      AWTEvent.KEY_EVENT_MASK
                                                                                                                  | AWTEvent.MOUSE_EVENT_MASK
                                                                                                                    | AWTEvent.MOUSE_MOTION_EVENT_MASK);

      view.addCanvas3D(canvas);
      view.getTransform().lookAt(
              new Vector3f(0,0,2f),
              new Vector3f(0,0,0),
              new Vector3f(0,1,0));
      view.startView();

      while(true) {
            if(isRotationScheduled) {
                  performRotation();
            }
            
          view.renderOnce();
      }
  }

java.lang.ArrayIndexOutOfBoundsException: 1
at com.xith3d.scenegraph.GeometryArray.getTexCoordData(GeometryArray.java:107)
at com.xith3d.render.jogl.ShapeAtomPeer.setupTextureCoords(ShapeAtomPeer.java:114)
at com.xith3d.render.jogl.ShapeAtomPeer.setupTextureUnit(ShapeAtomPeer.java:592)
at com.xith3d.render.jogl.ShapeAtomPeer.renderAtom(ShapeAtomPeer.java:698)
at com.xith3d.render.CanvasPeerBase.render(CanvasPeerBase.java:102)
at com.xith3d.render.jogl.CanvasPeerImpl.drawBin(CanvasPeerImpl.java:760)
at com.xith3d.render.jogl.CanvasPeerImpl.display(CanvasPeerImpl.java:1008)
at net.java.games.jogl.impl.GLDrawableHelper.display(GLDrawableHelper.java:74)
at net.java.games.jogl.GLCanvas$DisplayAction.run(GLCanvas.java:198)
at net.java.games.jogl.impl.GLContext.invokeGL(GLContext.java:239)
at net.java.games.jogl.GLCanvas.displayImpl(GLCanvas.java:186)
at net.java.games.jogl.GLCanvas.display(GLCanvas.java:74)
at com.xith3d.render.jogl.CanvasPeerImpl.render(CanvasPeerImpl.java:1109)
at com.xith3d.scenegraph.View.renderOnce(View.java:756)
at com.xith3d.scenegraph.View.renderOnce(View.java:689)
at Xith3DTest.(Xith3DTest.java:153)
at Xith3DTest.main(Xith3DTest.java:48)

I encountered the same problem, when layering two textures.

It’s because the Geometry you are trying to texture only has one set of texture coords. You require 1 set of texture coords per TextureUnitState.

The code that creates the Geometry would need a extra call to setTextureCoordinates, something like…


float[] texCoords = 
{
 // Your coords here
};
quad_data.setTextureCoordinates(0, offset, texCoords); // texture one
quad_data.setTextureCoordinates(1, offset, texCoords); // texture two

Where quad_data is a QuadArray or similar sub-class of Geometry
They do seem to have omitted mentioning this in the tutorial, which I’m sure has caught out many other people

Yay thanks. What I did was I just copied the createCubeViaTriangles() used in one of the official test classes and pasted it into my source and used that local one instead of the createCubeViaTriangles() in the Cube class. It then worked for whatever reason. But your way of doing it is the proper way :D. It should be added to the guide, which I find often leaves out a lot…