One way of using DDS texture files

Started by Evil-Devil, September 05, 2005, 16:18:37

Previous topic - Next topic

Evil-Devil

Hi folks, as i refactor my DDS Textureloader classes, I thought about sharing this stuff. As I got the first steps from the old wiki DDS Tutorial which was a little bit crappy to handle. If wished, i will add this to the wiki. As soon the code is finished.

For the moment there is no mipmap loading, but that will included soon.
DXT1, DXT1 (with alpha), DXT3 and DXT5 are supported. I have not tested with the RGB format, but i think about implementing full support for   that too.
Feel free to utilize the classes to your need and please give some comments :)

Benny

DDSLoader.java
/* =============================================================================
 * DDSLoader.java Bubble_Engine 
 * com.evildevil.engines.bubble.texture
 * Copyright (c) 2004 - 2005 Benjamin "Evil-Devil" Behrendt
 * All rights reserved
 * -----------------------------------------------------------------------------
 * powered by LWJGL - Copyright (c) LWJGL Team (http://www.lwjgl.org)
 * powered by JAVA - Copyright (c) Sun Microsystems (http://www.sun.com)
 * -------------------------------------------------------------------------- */
package com.evildevil.engines.bubble.texture;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.nio.channels.FileChannel;

import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13;

import static org.lwjgl.opengl.EXTTextureCompressionS3TC.*;
import static org.lwjgl.opengl.GL11.GL_LINEAR;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_MAG_FILTER;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_MIN_FILTER;
import static org.lwjgl.opengl.GL11.glTexParameteri;

/**
 * <p>DDSLoader.java Bubble Engine</p>
 * <p><strong>Copyright (c) 2004 - 2005 Benjamin "Evil-Devil" Behrendt<br />
 * All rights reserved</strong><br />
 * Website: <a href="http://www.evil-devil.com" target="_blank">http://www.evil-devil.com</a></p><hr />
 * @author Benjamin "Evil-Devil" Behrendt
 * @version 1.0, 02.09.2005
 * <p>This class provides an example view about how to load a texture that uses<br>
 * the DDS (Direct Draw Surface) file format.<br />
 * This is not a common engine Bubble Engine class nor should it be used as it, there are
 * other classes for loading dds and other texture format files :D
 */
public final class DDSLoader implements DDSurface {
    
    private final String DDS_IDENTIFIER = "DDS ";
    private final int DDS_HEADER_SIZE = 128;        // size of the dds header
    private final int DDS_DESC2_RESERVED_1 = 44;    // bytesize of DWORD[11]
    private final int DDS_DESC2_RESERVED_2 = 4;     // bytesize of DWORD
    private final int DDS_CAPS2_RESERVED = 8;       // bytesize of DWORD[2]
    private final int DEFAULT_DXT_BLOCKSIZE = 16;
    private final int DXT1_BLOCKSIZE = 8;
    
    private DDSurfaceDesc2 ddsDesc2 = null;
    private ByteBuffer ddsHeader = null;
    private FileChannel ddsFileChannel = null;
    
    public DDSLoader() {
    }
    
    public int loadDDSFile(String fileName) {
        // our DDS file
        File ddsFile = new File(fileName);
        
        try {
            FileInputStream fis = new FileInputStream(ddsFile);
            // assign the filechannel for reading data from it
            ddsFileChannel = fis.getChannel();
            // check for null
            if (ddsFileChannel == null) 
                throw new NullPointerException("ddsFileChannel couldn't be null!");
        } catch (FileNotFoundException fnfe) {
            fnfe.printStackTrace();
        }
        
        // create a new DDSurfaceDesc2 object to hold all dds file information
        ddsDesc2 = new DDSurfaceDesc2();
        // allocate enough memory for storing the whole header
        ddsHeader = BufferUtils.createByteBuffer(DDS_HEADER_SIZE);
        readFileHeader();
        int glName = readFileData();
        return glName;
    }
    
    private void readFileHeader() {
        
        try {
            // read the header
            ddsFileChannel.read(ddsHeader);
            ddsHeader.rewind();
            
            // read and feed the DDSurfaceDesc2            
            ddsDesc2.setIdentifier(ddsHeader.getInt());
            ddsDesc2.setSize(ddsHeader.getInt());
            ddsDesc2.setFlags(ddsHeader.getInt());
            ddsDesc2.setHeight(ddsHeader.getInt());
            ddsDesc2.setWidth(ddsHeader.getInt());
            ddsDesc2.setPitchOrLinearSize(ddsHeader.getInt());
            ddsDesc2.setDepth(ddsHeader.getInt());
            ddsDesc2.setMipMapCount(ddsHeader.getInt());
            // skip, cause next is unused
            ddsHeader.position(ddsHeader.position()+DDS_DESC2_RESERVED_1);
            
            // DDPixelFormat of DDSurfaceDesc2            
            DDPixelFormat pixelFormat = ddsDesc2.getDDPixelformat();
            pixelFormat.setSize(ddsHeader.getInt());
            pixelFormat.setFlags(ddsHeader.getInt());
            pixelFormat.setFourCC(ddsHeader.getInt());
            pixelFormat.setRGBBitCount(ddsHeader.getInt());
            pixelFormat.setRBitMask(ddsHeader.getInt());
            pixelFormat.setGBitMask(ddsHeader.getInt());
            pixelFormat.setBBitMask(ddsHeader.getInt());
            pixelFormat.setRGBAlphaBitMask(ddsHeader.getInt());
            
            // DDSCaps2 of DDSurfaceDesc2
            DDSCaps2 caps2 = ddsDesc2.getDDSCaps2();
            caps2.setCaps1(ddsHeader.getInt());
            caps2.setCaps2(ddsHeader.getInt());
                    
            // skip, cause next is unused
            ddsHeader.position(ddsHeader.position()+DDS_CAPS2_RESERVED);
            
            // we don't wanna read the last 4 bytes, they are not used anyway,
            // but we skip them. Funny, ain't?
            ddsHeader.position(ddsHeader.position()+DDS_DESC2_RESERVED_2);            
            // the last two instuctions might be banned, but thats your decission
        
        } catch (BufferUnderflowException bue) {
            bue.printStackTrace();
        } catch (TextureFormatException tfe) {
            tfe.printStackTrace();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        } finally {
            ddsHeader = null;   // free the memory
        }
    }
    
    private int readFileData() {
        final DDPixelFormat ddpf = ddsDesc2.getDDPixelformat();
        int imageSize = 0;
        int dxtFormat = 0;
        
        /* calculate the image size depending on the used blocksize
           and set the used DXT format */
        if (ddpf.isCompressed && ddpf.getFourCCString().equalsIgnoreCase("DXT1")) {
            imageSize = calculateSize(DXT1_BLOCKSIZE);
            // at the moment we treat any DXT1 image as RGBA,
            // maybe this can be switched dynamically in future...
            dxtFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
        } else {
            imageSize = calculateSize(DEFAULT_DXT_BLOCKSIZE);
            if (ddpf.getFourCCString().equalsIgnoreCase("DXT3"))
                dxtFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
            else if(ddpf.getFourCCString().equals("DXT5"))
                dxtFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
        }
        
        // read the dds file data itself
        ByteBuffer imageData = BufferUtils.createByteBuffer(ddsDesc2.pitchOrLinearSize);
        
        try {
            ddsFileChannel.read(imageData);
            imageData.rewind();            
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
        
        // create the GL Name
        IntBuffer glName = BufferUtils.createIntBuffer(1);        
        
        // create the texture
        GL11.glGenTextures(glName);
        GL11.glBindTexture(GL11.GL_TEXTURE_2D,glName.get(0));
        
        /* Implement the filtering stuff anywhere you want, this is only here to
           have at least one filter applied on the texture */
        // Linear Filtering
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D,GL11.GL_TEXTURE_WRAP_S,GL11.GL_REPEAT);
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D,GL11.GL_TEXTURE_WRAP_T,GL11.GL_REPEAT);
        GL13.glCompressedTexImage2D(GL11.GL_TEXTURE_2D,0,dxtFormat,ddsDesc2.width,ddsDesc2.height,0,ddsDesc2.pitchOrLinearSize,imageData);
        
        return glName.get(0);
    }
    
    private int calculateSize(int blockSize) {
        double size = Math.ceil(ddsDesc2.width/4) * Math.ceil(ddsDesc2.height/4) * blockSize;
        return (int)size;
    }
    
    public void debugInfo() {        
        DDPixelFormat pixelFormat = ddsDesc2.getDDPixelformat();
        DDSCaps2 caps2 = ddsDesc2.getDDSCaps2();
        
        System.out.println("\nDDSURFACEDESC2:");
        System.out.println("----------------------------------------");
        System.out.println("SIZE: "+ddsDesc2.size);
        System.out.println("FLAGS: "+ddsDesc2.flags);
        System.out.println("HEIGHT: "+ddsDesc2.height);
        System.out.println("WIDTH: "+ddsDesc2.width);
        System.out.println("PITCH_OR_LINEAR_SIZE: "+ddsDesc2.pitchOrLinearSize);
        System.out.println("DEPTH: "+ddsDesc2.depth);
        System.out.println("MIP_MAP_COUNT: "+ddsDesc2.mipMapCount);
        
        System.out.println("\nDDPIXELFORMAT of DDSURFACEDESC2:");
        System.out.println("----------------------------------------");
        System.out.println("SIZE :"+pixelFormat.size);
        System.out.println("FLAGS: "+pixelFormat.flags);
        System.out.println("FOUR_CC: "+pixelFormat.getFourCCString());
        System.out.println("RGB_BIT_COUNT: "+pixelFormat.rgbBitCount);
        System.out.println("R_BIT_MASK: "+pixelFormat.rBitMask);
        System.out.println("G_BIT_MASK: "+pixelFormat.gBitMask);
        System.out.println("B_BIT_MASK: "+pixelFormat.bBitMask);
        System.out.println("RGB_ALPHA_BIT_MASK: "+pixelFormat.rgbAlphaBitMask);    
        
        System.out.println("\nDDSCAPS of DDSURFACEDESC2");
        System.out.println("----------------------------------------");
        System.out.println("CAPS1: "+caps2.caps1);
        System.out.println("CAPS2: "+caps2.caps2);     
    }
}

DDSurface.java
/* =============================================================================
 * DDSurface.java Bubble_Engine 
 * com.evildevil.engines.bubble.texture
 * Copyright (c) 2004 - 2005 Benjamin "Evil-Devil" Behrendt
 * All rights reserved
 * -----------------------------------------------------------------------------
 * powered by LWJGL - Copyright (c) LWJGL Team (http://www.lwjgl.org)
 * powered by JAVA - Copyright (c) Sun Microsystems (http://www.sun.com)
 * -------------------------------------------------------------------------- */
package com.evildevil.engines.bubble.texture;

/**
 * <p>DDSurface.java Bubble Engine</p>
 * <p><strong>Copyright (c) 2004 - 2005 Benjamin "Evil-Devil" Behrendt<br />
 * All rights reserved</strong><br />
 * Website: <a href="http://www.evil-devil.com" target="_blank">http://www.evil-devil.com</a></p><hr />
 * @author Benjamin "Evil-Devil" Behrendt
 * @version 1.0, 02.09.2005
 */
interface DDSurface {
    
    // dwFags - DDSurfaceDesc2
    int DDSD_CAPS           = 0x00000001;
    int DDSD_HEIGHT         = 0x00000002;
    int DDSD_WIDTH          = 0x00000004;
    int DDSD_PITCH          = 0x00000008;
    int DDSD_PIXELFORMAT    = 0x00001000;
    int DDSD_MIPMAPCOUNT    = 0x00020000;
    int DDSD_LINEARSIZE      = 0x00080000;
    int DDSD_DEPTH          = 0x00800000;
    
    // ddpfPixeFormat - DDSurfaceDesc2
    int DDPF_APHAPIXES  = 0x00000001;
    int DDPF_FOURCC     = 0x00000004;
    int DDPF_RGB        = 0x00000040;
    
    // dwCaps1  - DDSCaps2
    int DDSCAPS_COMPLEX    = 0x00000008;
    int DDSCAPS_TEXTURE    = 0x00001000;
    int DDSCAPS_MIPMAP     = 0x00400000;
    
    // dwCaps2 - DDSCaps2
    int DDSCAPS2_CUBEMAP            = 0x00000200;
    int DDSCAPS2_CUBEMAP_POSITVEX   = 0x00000400;
    int DDSCAPS2_CUBEMAP_NEGATIVEX  = 0x00000800;
    int DDSCAPS2_CUBEMAP_POSITIVEY  = 0x00001000;
    int DDSCAPS2_CUBEMAP_NEGATIVEY  = 0x00002000;
    int DDSCAPS2_CUBEMAP_POSITIVEZ  = 0x00004000;
    int DDSCAPS2_CUBEMAP_NEGATIVEZ  = 0x00008000;
    int DDSCAPS2_VOLUME              = 0x00200000;

}

DDSurfaceDesc2.java
/* =============================================================================
 * DDSurfaceDesc2.java Bubbe_Engine 
 * com.evildevil.engines.bubble.texture
 * Copyright (c) 2004 - 2005 Benjamin "Evil-Devil" Behrendt
 * All rights reserved
 * -----------------------------------------------------------------------------
 * powered by LWJGL - Copyright (c) LWJGL Team (http://www.lwjgl.org)
 * powered by JAVA - Copyright (c) Sun Microsystems (http://www.sun.com)
 * -------------------------------------------------------------------------- */
package com.evildevil.engines.bubble.texture;

/**
 * <p>DDSurfaceDesc2.java Bubble Engine</p>
 * <p><strong>Copyright (c) 2004 - 2005 Benjamin "Evil-Devil" Behrendt<br />
 * All rights reserved</strong><br />
 * Website: <a href="http://www.evil-devil.com" target="_bank">http://www.evil-devil.com</a></p><hr />
 * @author Benjamin "Evil-Devil" Behrendt
 * @version 1.0, 02.09.2005
 */
final class DDSurfaceDesc2 implements DDSurface {
    
    private final String DDS_IDENTIFIER = "DDS ";
    protected int identifier = 0;
    private String identifierString = "";
    protected int size = 0;                     // size of the structure, must be 124
    protected int flags = 0;
    protected int height = 0;
    protected int width = 0;
    protected int pitchOrLinearSize = 0;
    protected int depth = 0;
    protected int mipMapCount = 0;
    protected int reserved = 0;                 // unused by documentation
    private DDPixelFormat pixelFormat = null;   // the surfaces DDPixelFormat
    private DDSCaps2 caps2 = null;              // the surfaces DDSCaps2
    protected int reserved2 = 0;                // unused by documentation
        
    public DDSurfaceDesc2() {
        pixelFormat = new DDPixelFormat();
        caps2 = new DDSCaps2();
    }
    
    public void setIdentifier(int identifier) throws TextureFormatException {
        this.identifier = identifier;
        createIdentifierString();
    }
    
    private void createIdentifierString() throws TextureFormatException {
        byte[] identifierString = new byte[4];
        identifierString[0] = (byte)this.identifier;
        identifierString[1] = (byte)(this.identifier >> 8);
        identifierString[2] = (byte)(this.identifier >> 16);
        identifierString[3] = (byte)(this.identifier >> 24);
        
        this.identifierString = new String(identifierString);
        // validate
        if (!this.identifierString.equalsIgnoreCase(this.DDS_IDENTIFIER)) {
            throw new TextureFormatException("The DDS Identifier is wrong. Have to be \"DDS \"!");
        }
    }
    
    public void setSize(int size) throws TextureFormatException{
        if (size != 124)    // TODO: include your own Exception handling here!
            throw new TextureFormatException("Wrong DDSurfaceDesc2 size. DDSurfaceDesc2 size must be 124!");        
        this.size = size;
    }
    
    public void setFlags(int flags) throws TextureFormatException {
        this.flags = flags;
        // check for DDSD_CAPS, DDSD_PIXELFORMAT, DDSD_WIDTH, DDSD_HEIGHT
        if ((flags & DDSD_CAPS) != DDSD_CAPS || (flags & DDSD_PIXELFORMAT) != DDSD_PIXELFORMAT
                || (flags & DDSD_WIDTH) != DDSD_WIDTH || (flags & DDSD_HEIGHT) != DDSD_HEIGHT)
            throw new TextureFormatException("One or more required flag bits are set wrong\n"+
                    "flags have to include \"DDSD_CAPS, DDSD_PIXELFORMAT, DDSD_WIDTH, DDSD_HEIGHT\"");
    }
    
    public void setHeight(int height) {
        this.height = height;
    }
    
    public void setWidth(int width) {
        this.width = width;
    }
    
    public void setPitchOrLinearSize(int pitchOrLinearSize) {
        this.pitchOrLinearSize = pitchOrLinearSize;
    }
    
    public void setDepth(int depth) {
        this.depth = depth;
    }
    
    public void setMipMapCount(int mipMapCount) {
        this.mipMapCount = mipMapCount;
    }
    
    public void setDDPixelFormat(DDPixelFormat pixelFormat) throws NullPointerException {
        if (pixelFormat == null)
            throw new NullPointerException("DDPixelFormat can't be null. DDSurfaceDesc2 needs a valid DDPixelFormat.");
        this.pixelFormat = pixelFormat;
    }
    
    public DDPixelFormat getDDPixelformat() {
        return pixelFormat;
    }
    
    public void setDDSCaps2(DDSCaps2 caps2) throws NullPointerException {
        if (caps2 == null)
            throw new NullPointerException("DDSCaps can't be null. DDSurfaceDesc2 needs a valid DDSCaps2.");
        this.caps2 = caps2;
    }
    
    public DDSCaps2 getDDSCaps2() {
        return caps2;
    }
}

DDPixelFormat.java
/* =============================================================================
 * DDPixelFormat.java Bubble_Engine 
 * com.evildevil.engines.bubble.texture
 * Copyright (c) 2004 - 2005 Benjamin "Evil-Devil" Behrendt
 * All rights reserved
 * -----------------------------------------------------------------------------
 * powered by LWJGL - Copyright (c) LWJGL Team (http://www.lwjgl.org)
 * powered by JAVA - Copyright (c) Sun Microsystems (http://www.sun.com)
 * -------------------------------------------------------------------------- */
package com.evildevil.engines.bubble.texture;

/**
 * <p>DDPixelFormat.java Bubble Engine</p>
 * <p><strong>Copyright (c) 2004 - 2005 Benjamin "Evil-Devil" Behrendt<br />
 * All rights reserved</strong><br />
 * Website: <a href="http://www.evil-devil.com" target="_blank">http://www.evil-devil.com</a></p><hr />
 * @author Benjamin "Evil-Devil" Behrendt
 * @version 1.0, 02.09.2005
 */
final class DDPixelFormat implements DDSurface {
    
    protected int size = 0;             // this must be set to 32!
    protected int flags = 0;
    protected int fourCC = 0;
    private String fourCCString = "";
    protected int rgbBitCount = 0;
    protected int rBitMask = 0;
    protected int gBitMask = 0;
    protected int bBitMask = 0;
    protected int rgbAlphaBitMask = 0;
    
    protected boolean isCompressed = true;
    
    public DDPixelFormat() {        
    }
    
    public void setSize(int size) throws TextureFormatException {
        if (size != 32)
            throw new TextureFormatException("Wrong DDPixelFormat size. DDPixelFormat size must be 32!");        
        this.size = size;
    }
        
    public void setFlags(int flags) {
        this.flags = flags;
        // check for (un)compressed
        if ((flags & DDPF_RGB) == DDPF_RGB)
            this.isCompressed = false;
        else if ((flags & DDPF_FOURCC) == DDPF_FOURCC)
            this.isCompressed = true;
    }
    
    public void setFourCC(int fourCC) {
        this.fourCC = fourCC;        
        if (this.isCompressed)
            createFourCCString();       // create the fourCCString
    }
    
    private void createFourCCString() {        
        byte[] fourCCString = new byte[DDPF_FOURCC];
        fourCCString[0] = (byte)this.fourCC;
        fourCCString[1] = (byte)(this.fourCC >> 8);
        fourCCString[2] = (byte)(this.fourCC >> 16);
        fourCCString[3] = (byte)(this.fourCC >> 24);
        // fourCCString is done :)
        this.fourCCString = new String(fourCCString);        
    }
    
    public String getFourCCString() {
        return this.fourCCString;
    }
    
    public void setRGBBitCount(int rgbBitCount) {
        this.rgbAlphaBitMask = rgbBitCount;
    }
    
    public void setRBitMask(int rBitMask) {
        this.rBitMask = rBitMask;
    }
    
    public void setGBitMask(int gBitMask) {
        this.gBitMask = gBitMask;
    }
    
    public void setBBitMask(int bBitMask) {
        this.bBitMask = bBitMask;
    }
    
    public void setRGBAlphaBitMask(int rgbAlphaBitMask) {
        this.rgbAlphaBitMask = rgbAlphaBitMask;
    }
}

DDSCaps2
/* =============================================================================
 * DDSCaps2.java Bubble_Engine 
 * com.evildevil.engines.bubble.texture
 * Copyright (c) 2004 - 2005 Benjamin "Evil-Devil" Behrendt
 * All rights reserved
 * -----------------------------------------------------------------------------
 * powered by LWJGL - Copyright (c) LWJGL Team (http://www.lwjgl.org)
 * powered by JAVA - Copyright (c) Sun Microsystems (http://www.sun.com)
 * -------------------------------------------------------------------------- */
package com.evildevil.engines.bubble.texture;

/**
 * <p>DDSCaps2.java Bubble Engine</p>
 * <p><strong>Copyright (c) 2004 - 2005 Benjamin "Evil-Devil" Behrendt<br />
 * All rights reserved</strong><br />
 * Website: <a href="http://www.evil-devil.com" target="_blank">http://www.evil-devil.com</a></p><hr />
 * @author Benjamin "Evil-Devil" Behrendt
 * @version 1.0, 02.09.2005
 */
final class DDSCaps2 implements DDSurface {
    
    public DDSCaps2() {        
    }
    
    protected int caps1 = 0;
    protected int caps2 = 0;
    protected int reserved = 0;       // unused by documentation
    
    protected boolean isVolumeTexture = false;
    
    public void setCaps1(int caps1) throws TextureFormatException {        
        this.caps1 = caps1;
        if ((caps1 & DDSCAPS_TEXTURE) != DDSCAPS_TEXTURE)   // check for DDSCAPS_TEXTURE
            throw new TextureFormatException("DDS file does not contain DDSCAPS_TEXTURE, but it must!");
    }   
    
    public void setCaps2(int caps2) {
        this.caps2 = caps2;
        // check for VolumeTexture
        if ((caps2 & DDSCAPS2_VOLUME) == DDSCAPS2_VOLUME)
            this.isVolumeTexture = true;
    }
}

TextureFormatException.java
/* =============================================================================
 * DDPixelFormat.java Bubble_Engine 
 * com.evildevil.engines.bubble.texture
 * Copyright (c) 2004 - 2005 Benjamin "Evil-Devil" Behrendt
 * All rights reserved
 * -----------------------------------------------------------------------------
 * powered by LWJGL - Copyright (c) LWJGL Team (http://www.lwjgl.org)
 * powered by JAVA - Copyright (c) Sun Microsystems (http://www.sun.com)
 * -------------------------------------------------------------------------- */
package com.evildevil.engines.bubble.texture;

/**
 * <p>DDPixelFormat.java Bubble Engine</p>
 * <p><strong>Copyright (c) 2004 - 2005 Benjamin "Evil-Devil" Behrendt<br />
 * All rights reserved</strong><br />
 * Website: <a href="http://www.evil-devil.com" target="_blank">http://www.evil-devil.com</a></p><hr />
 * @author Benjamin "Evil-Devil" Behrendt
 * @version 1.0, 27.01.2005 
 */
public class TextureFormatException extends Exception {
    
    private static final long serialVersionUID = 24L;
    
    public TextureFormatException() {
        super();
    }
    
    public TextureFormatException(String s) {
        super(s);            
    }
}

Fool Running

Very impressive  :shock:
Programmers will, one day, rule the world... and the world won't notice until its too late.Just testing the marquee option ;D

chaosdeathfish

But DevIL can load DDS textures. Why are you using your own loader?

Evil-Devil

Really? I haven't known.

Ok, then I have to add a DevIL implementation to my TextureLoader.
And if not using DevIL, there are no JNI calls :)

chaosdeathfish

..although having said that, aparently there's some call you have to make before you load the texture to stop DevIL decompressing the textures itself.. I can't remember what it is though. Sorry :(