A bug in ByteBuffers?

I uploaded a demo of mine that I tested and positive is working on my pc to xith.org intending to run it as a webstart application.
My demo reads a 3D model from the jar file using a FileInputStream that fills a bytearray that I finally wrap into a bytebuffer to ease the byte to float/integer conversion.
Having noticed (it didn’t take me that long ::slight_smile: ) that running as a webstart application my demo would display nothing on the screen (besides few sprites that are totally independant from the model that I just loaded) I started some trouble shooting trying to figure out what the f was happening.
So I created a Jframe that holds a JTextArea which was created using a StringBuffer containing all the data that I assumed was correctly loaded, and I scrolled down a bit to check the model info.
Well the readings seemed ok till I’ve reached down to 6 lines where all Tuple3fs were displayed as (0,0,0).
Question is what might have caused the bytebuffer to return 0s after doing a great job at loading the first few vertices? ???

It looks like java can’t read all the file at once through webstart… ::slight_smile:

Is that the thing to do with reading from stream from the middle of jars. InputStream.available() doesn’t return the total size of the file for streams retrieved ClassLoader.getResourceAsStream().

You got it to work now?

Kev

nope the size returned is correct…


  public static IndexedTriangleArray readJCDModel(ArrayList list,
                                                  String    name,
                                                  float     scale){

    InputStream     fileStream     = JCD3DSFactory.class.getClassLoader().
                                                         getResourceAsStream(name);
    ByteBuffer      modelInfo      = null;
    byte            fileContents[] = null;

    try{
      if(fileStream == null)
        fileStream = new FileInputStream(name);
      fileContents = new byte[fileStream.available()];
      
      fileStream.read(fileContents);
      modelInfo = ByteBuffer.wrap(fileContents);
    }
    catch(Exception e){}
    int[]        indices     = new int       [modelInfo.getInt()];
    Point3f[]    vertices    = new Point3f   [modelInfo.getInt()];
    Vector3f[]   normals     = new Vector3f  [vertices.length  ];
    TexCoord3f[] tangents    = new TexCoord3f[vertices.length  ],
                 binormals   = new TexCoord3f[vertices.length  ],
                 texcoords3f = new TexCoord3f[vertices.length  ];

   for(int i = 0; i< vertices.length; i++){
      vertices   [i]= new Point3f   (scale*modelInfo.getFloat(),
                                     scale*modelInfo.getFloat(),
                                     scale*modelInfo.getFloat());
      normals    [i]= new Vector3f  (modelInfo.getFloat(),
                                     modelInfo.getFloat(),
                                     modelInfo.getFloat());
      tangents   [i]= new TexCoord3f(modelInfo.getFloat(),
                                     modelInfo.getFloat(),
                                     modelInfo.getFloat());
      binormals  [i]= new TexCoord3f(modelInfo.getFloat(),
                                     modelInfo.getFloat(),
                                     modelInfo.getFloat());
      texcoords3f[i]= new TexCoord3f(modelInfo.getFloat(),
                                     modelInfo.getFloat(),
                                     modelInfo.getFloat());
    }

    for(int i = 0; i< indices.length; i++)
      indices[i] = modelInfo.getInt();

    IndexedTriangleArray geometry = new IndexedTriangleArray(
                                        vertices.length,
                                        GeometryArray.TEXTURE_COORDINATE_3 |
                                        GeometryArray.COORDINATES          |
                                        GeometryArray.COLOR_3              |
                                        GeometryArray.NORMALS,
                                        2,
                                        new int[]{0,1},
                                        indices.length);
    geometry.setIndex(indices);
    geometry.setNormals(0, normals);
    geometry.setCoordinates(0,vertices);
    geometry.setValidIndexCount(indices.length);
    geometry.setTextureCoordinates(0,0, texcoords3f);
    geometry.setTextureCoordinates(1,0, texcoords3f);

    list.add(vertices);
    list.add(normals);
    list.add(tangents);
    list.add(binormals);
    list.add(indices);
    return geometry;
  }

[quote]fileStream.read(fileContents);
[/quote]
Check out the javadoc on InputStream.read(byte[]). It is only required to block until one byte is read. It is not required to read the whole array. You have to use DataInputStream.readFully() if you need to read the whole array in one go.

Also, do not use available() to get the length of file. It might work now, but can fail at any moment. It do not give you the length of the file but the number of bytes that can be read without blocking.

Instead read the data into a temp buffer until inputstream returns -1.

Fixed using this approach


    InputStream     fileStream     = JCD3DSFactory.class.getClassLoader().
                                                         getResourceAsStream(name);
    ByteBuffer      modelInfo      = null;
    byte            fileContents[] = null;

    try{
      if(fileStream == null)
        fileStream = new FileInputStream(name);

      DataInputStream dataStream = new DataInputStream(fileStream);
      dataStream.readFully(fileContents = new byte[fileStream.available()]);
      modelInfo = ByteBuffer.wrap(fileContents);
    }
    catch(Exception e){}

This was a very timely thread, as I just ran into the same issue trying to get some webstarted demos working. So, I was able to solve one issue switching to readFully. However, I have a couple other model formats that are plain text. I’m using a BufferedReader to read them in. I’m experiencing the same issue. I use the readLine method as needed, works fine locally, doesn’t work in webstart. Any ideas?