Search code examples
javatexturesout-of-memoryjava-3d

Java3D: How to avoid OutOfMemoryError while using textures


I'm creating several visual objects in loop:

...
Package packet; // a visual packet
for(int i = 0; i < numberOfSteps; i++){
  packet = new Package(packetSize, packetSize, packetSize);

  // position, rotate, etc. and add to scene graph
}
...

The Package is basically just a simple cube with a texture. The constructer of package looks as follows:

public Package(float x, float y, float z) {
    Appearance appear = new Appearance();
    BufferedImage filename = null;

    try {
        filename = ImageIO.read(getClass().getResource("package.jpg"));
    } catch (IOException e) {
                    e.printStackTrace();
        System.exit(1);
    }

    TextureLoader loader = new TextureLoader(filename);
    ImageComponent2D image = loader.getImage();
    Texture2D texture = new Texture2D(Texture.BASE_LEVEL, Texture.RGBA,
            image.getWidth(), image.getHeight());
    texture.setImage(0, image);
    appear.setTexture(texture);
    textureCube = new Box(x, y, z, Box.GENERATE_TEXTURE_COORDS, appear);
}

So I'm loading the same texture over and over again in the loop which eventually causes an OutOfMemoryError. Is there anyway to avoid/optimise that?


Solution

  • The most obvious optimization is to cache your BufferedImage:

    class ImageProvider{
    
       private static Map<String, Image> images = new HashMap<String, Image>();
    
       public static Image getImage(String filename){
           if(!images.contains(filename))
               try {
                  images.put(filename, ImageIO.read(ImageProvider.class.getResource(filename));
               } catch (IOException ignore){
                  //will return null if image cannot be loaded
               }
    
           return images.get(filename);
       }
    }
    

    Depending on the manipulations you make later, you could also cache your ImageComponent2D objects and/or your Texture2D objects.