Can anyone help me understand this texture loading code?

Started by CuppoJava, March 18, 2005, 19:14:26

Previous topic - Next topic

CuppoJava

 private int loadTexture(String path)
  {
    IntBuffer image = ByteBuffer.allocateDirect(4).order(ByteOrder.nativeOrder()).asIntBuffer();
    IL.ilGenImages(1, image);
    IL.ilBindImage(image.get(0));
    IL.ilLoadImage(path);
    IL.ilConvertImage(IL.IL_RGB, IL.IL_BYTE);
    ByteBuffer scratch = ByteBuffer.allocateDirect(IL.ilGetInteger(IL.IL_IMAGE_WIDTH) * IL.ilGetInteger(IL.IL_IMAGE_HEIGHT) * 3);
    IL.ilCopyPixels(0, 0, 0, IL.ilGetInteger(IL.IL_IMAGE_WIDTH), IL.ilGetInteger(IL.IL_IMAGE_HEIGHT), 1, IL.IL_RGB, IL.IL_BYTE, scratch);

    // Create A IntBuffer For Image Address In Memory
    IntBuffer buf = ByteBuffer.allocateDirect(4).order(ByteOrder.nativeOrder()).asIntBuffer();
    GL11.glGenTextures(buf); // Create Texture In OpenGL

    GL11.glBindTexture(GL11.GL_TEXTURE_2D, buf.get(0));
    // Typical Texture Generation Using Data From The Image

    // Linear Filtering
    GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
    // Linear Filtering
    GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
    // Generate The Texture
    GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGB, IL.ilGetInteger(IL.IL_IMAGE_WIDTH),
        IL.ilGetInteger(IL.IL_IMAGE_HEIGHT), 0, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, scratch);

    return buf.get(0); // Return Image Address In Memory
  }


This was from Nehe's sixth lesson. What's really bothering me is I can't tell which are OGL specific commands and which are DevIL commands. I pretty much all looks like mush to me. Can I create a texture from a java Image? Does anyone have a link they can point me to that explains how? What are the difficulties in loading a texture? Why does it require this much code to load in an image? And what does the ByteBuffer do?

Thx for any replies.[/code]

jam007

Quote
What's really bothering me is I can't tell which are OGL specific commands and which are DevIL commands. I pretty much all looks like mush to me. Can I create a texture from a java Image? Does anyone have a link they can point me to that explains how? What are the difficulties in loading a texture? Why does it require this much code to load in an image? And what does the ByteBuffer do?
I will try to answer some of your questions and the more experienced can fill in and correct me

The IL.ilXxxx are DevIL commands and the GL11.glXxxx are OpenGL
Java Image - I leave that to someone else but I think it is possible since IÃ,´v seen and used a font class that used Java image objects to create a font textured object
The difficulies lies in translating form images of different formts to OpenGL textures as the data are stored in different ways.
Most of the ByteBuffer things are just fancy ways to store an integer. They are needed "to speak LWJGL OpenGL laguage" see LWJGL homepage FAQ for a discussion. the large ByteBuffer scratch stores the image .

Anders

PS

I made this Textures class with the help of sample code and answers to my questions on this forum when I got stuck. Calling requestTexture loads a texture if not already loaded and returns the handle. The image must be 2^n x 2^m pixels:
import org.lwjgl.devil.IL;
import org.lwjgl.devil.ILU;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.nio.ByteOrder;
import java.io.FileNotFoundException;
import org.lwjgl.*;
import org.lwjgl.opengl.*;
import java.util.Map;
import java.util.HashMap;
import org.lwjgl.util.vector.Vector3f;
import org.lwjgl.util.vector.Vector2f;
/**
 * Handles textures
 * @author Anders
 */
public class Textures {
    
    private static Map<String,Integer> texhash=new HashMap<String,Integer>();
    /**
     * Handles a texture request. If the texture is already loaded the OpenGL handle will
     * be given directly else the texture will be loaded.
     * @param filename the filename (with path)
     * @return returns the integer handle
     * @throws TextureNotFoundException this ist thrown if the file could not be loaded
     */
    public static int requestTexture(String filename) throws TextureNotFoundException {
        int i;
        if (!Textures.texhash.containsKey(filename)) {
            i=makeTextureFromFile(filename);
            Textures.texhash.put(filename, i);
        } else i=(Integer)Textures.texhash.get(filename);
        return i;
    }
    /**
     * Creates a texture from a image file
     * @param filename the filename (with path)
     * @throws TextureNotFoundException thrown if the file could not be loaded
     * @return returns the integer handle
     */    
    public static int makeTextureFromFile(String filename) throws TextureNotFoundException {
       IntBuffer image = ByteBuffer.allocateDirect(4).order(ByteOrder.nativeOrder()).asIntBuffer();
       IL.ilGenImages(1, image);
       IL.ilBindImage(image.get(0));
       System.out.println("Loading "+filename);
       IL.ilLoadImage(filename);
       IL.ilConvertImage(IL.IL_RGBA, IL.IL_BYTE);
       ILU.iluFlipImage(); // turns it up side down to fit OpenGL coord sys.
       ByteBuffer scratch = IL.ilGetData();
       if (IL.ilGetError()!=IL.IL_NO_ERROR) {
             System.out.println("Error "+ILU.iluErrorString(IL.ilGetError())+", file "+filename); 
             throw new TextureNotFoundException(filename); 
       }
        // Create A IntBuffer? For Image Address In Memory
       IntBuffer buf = ByteBuffer.allocateDirect(4).order(ByteOrder.nativeOrder()).asIntBuffer();
       GL11.glGenTextures(buf); // Create Texture In OpenGL
       GL11.glBindTexture(GL11.GL_TEXTURE_2D, buf.get(0));
       // Typical Texture Generation Using Data From The Image
       // Linear Filtering
       GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
       // Linear Filtering
       GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
       // Generate The Texture
       GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, IL.ilGetInteger(IL.IL_IMAGE_WIDTH), IL.ilGetInteger(IL.IL_IMAGE_HEIGHT), 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, scratch);

       return buf.get(0); // Return Image Address In Memory
    }
    /**
     * Creates a vertex with associated normal and texture coordiantes
     * @param vertex the point coordinates
     * @param normal the normal associated with the vertex
     * @param texture the associated texture coordinates
     */
    public static void texVertex(Vector3f vertex, Vector3f normal, Vector2f texture) {
        GL11.glNormal3f(normal.x, normal.y, normal.z);
        GL11.glTexCoord2f(texture.x, texture.y);
        GL11.glVertex3f(vertex.x, vertex.y, vertex.z);
    }
}
/**
 * Texture not found
 */
class TextureNotFoundException extends Exception{

    TextureNotFoundException(String fn){
        super(fn);
    }

}

elias4444

Any command that starts with "IL" are from the DevIL library. And commands that starts with "GL" are from the OpenGL library.

And yes, you can load images using the standard Java IO libraries as well, it's just that OpenIL (Open Image Library) is a bit faster and probably has more functions to it (although I'm not sure on that, as I'm still using plain Java to do my stuff since cross-platform compatibility is so important to me).

After an image is loaded, it needs to be put into a buffer and "given to" OpenGL (via the glGenTextures() method) in order to be mapped onto 3D objects.

I'd highly recommend taking a look at the space invaders example on the LWJGL demos page to get a good example of using Java IO to read in textures, as there's more to it than just what I've said (OpenGL requires things to be in a specific format). It's a great starting place. I'm actually using a heavily modified version of his Texture and TextureLoader code in my own stuff.

Edit: Oh! You beat me to it!  :P
=-=-=-=-=-======-=-=-=-=-=-
http://www.tommytwisters.com

funsheep

hi,

in the JOGL forum, there is a thread, where some people have build an TextureLoader, it loads through javas ImageIO (therefore it can read several image types from scratch), buffers the image in an BufferedImage and binds the texture when needed.

also there are much comments, explaining whats going on.

regards,
funsheep

http://www.javagaming.org/cgi-bin/JGNetForums/YaBB.cgi?board=jogl;action=display;num=1058674409

BatKid

Here is the code to load texture with Java IO, I got this from either the space invader example or the nehe lesson:

   public static int loadTexture(String textureFile) {
        Image image = (new javax.swing.ImageIcon(textureFile)).getImage();
        
        // Exctract The Image
        BufferedImage tex = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_3BYTE_BGR);
        Graphics2D g = (Graphics2D) tex.getGraphics();
        g.drawImage(image, null, null);
        g.dispose();

        // Put Image In Memory
        ByteBuffer scratch = ByteBuffer.allocateDirect(4 * tex.getWidth() * tex.getHeight());
        
        byte data[] = (byte[]) tex.getRaster().getDataElements(0, 0, tex.getWidth(), tex.getHeight(), null);
        scratch.clear();
        scratch.put(data);
        scratch.rewind();
        
        // Create A IntBuffer For Image Address In Memory
        IntBuffer buf = ByteBuffer.allocateDirect(4).order(ByteOrder.nativeOrder()).asIntBuffer();
        GL11.glGenTextures(buf); // Create Texture In OpenGL    
        
        GL11.glBindTexture(GL11.GL_TEXTURE_2D, buf.get(0));
        
        // Linear Filtering
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
        // Linear Filtering
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
        // Generate The Texture
        GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGB, tex.getWidth(), tex.getHeight(), 0, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, scratch);
        
        return buf.get(0); // Return Image Address In Memory
        
    }
Projects: 
   Env3D (http://env3d.org): Learn Java in 3D
   WhaleChat (http://whalechat.com): A 3D social programming experiment