blob: 7724d7e30233c6a9d68ff626c4a3a349ca40c539 [file] [log] [blame] [raw]
/**
* Copyright (c) 2010-2011, Vincent Vollers and Christopher J. Kucera
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Minecraft X-Ray team nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL VINCENT VOLLERS OR CJ KUCERA BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.plusminus.craft;
import java.awt.Graphics2D;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.ComponentColorModel;
import java.awt.image.DataBuffer;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
/***
* Convenience class to quickly load/generate textures
*
* @author Vincent
*/
public class TextureTool {
public static double invln2 = 1.0 / Math.log(2.0);
public static ColorModel glAlphaColorModel= new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
new int[] {8,8,8,8},
true,
false,
ComponentColorModel.TRANSLUCENT,
DataBuffer.TYPE_BYTE);
public static ColorModel glColorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
new int[] {8,8,8,0},
false,
false,
ComponentColorModel.OPAQUE,
DataBuffer.TYPE_BYTE);
public static Texture allocateTexture(Texture frame) {
return TextureTool.allocateTexture(frame, GL11.GL_RGBA, // dst pixel format
GL11.GL_LINEAR, // min filter (unused)
GL11.GL_LINEAR, // mag filter (unused)
true);
}
public static Texture allocateTexture(Texture frame, int dstPixelFormat,
int minFilter,
int magFilter,
boolean wrap) {
int srcPixelFormat = 0;
// create the texture ID for this texture
int textureId = TextureTool.createTextureID();
//System.out.println("frame: " + frame.getFrameNum());
frame.setTextureId(textureId);
frame.bind();
frame.initializeTextureCompatibleBuffer();
frame.updateTextureCompatibleBuffer();
if (frame.getImage().getColorModel().hasAlpha()) {
srcPixelFormat = GL11.GL_RGBA;
} else {
srcPixelFormat = GL11.GL_RGB;
}
// convert that image into a byte buffer of texture data
//ByteBuffer textureBuffer = TextureLoader.convertImageData(bufferedImage,texture);
int wrapMode = wrap ? GL11.GL_REPEAT : GL11.GL_CLAMP;
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, wrapMode);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, wrapMode);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, minFilter);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, magFilter);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D,
0,
dstPixelFormat,
frame.getTextureWidth(),
frame.getTextureHeight(),
0,
srcPixelFormat,
GL11.GL_UNSIGNED_BYTE,
frame.getTextureCompatibleBuffer());
return frame;
}
public static Texture allocateTexture(int width, int height) throws IOException {
return TextureTool.allocateTexture(
GL11.GL_RGBA, // dst pixel format
GL11.GL_LINEAR, // min filter (unused)
GL11.GL_LINEAR, // mag filter (unused)
width,
height,
true); // wrap?
}
public static Texture allocateTexture(BufferedImage image) throws IOException {
Texture tex = TextureTool.allocateTexture(
GL11.GL_RGBA, // dst pixel format
GL11.GL_LINEAR, // min filter (unused)
GL11.GL_LINEAR, // mag filter (unused)
image.getWidth(),
image.getHeight(),
true); // wrap?
Graphics2D g = tex.getImage().createGraphics();
g.drawImage(image, 0, 0, null);
return tex;
}
public static Texture allocateTexture(BufferedImage image, int filter) throws IOException {
Texture tex = TextureTool.allocateTexture(
GL11.GL_RGBA, // dst pixel format
filter,
filter,
image.getWidth(),
image.getHeight(),
true); // wrap?
Graphics2D g = tex.getImage().createGraphics();
g.drawImage(image, 0, 0, null);
return tex;
}
public static int TEXTURETYPE=BufferedImage.TYPE_4BYTE_ABGR;
public static Texture allocateTexture(
int dstPixelFormat,
int minFilter,
int magFilter,
int width,
int height,
boolean wrap) throws IOException {
int srcPixelFormat = 0;
// create the texture ID for this texture
int textureId = TextureTool.createTextureID();
BufferedImage bufferedImage = new BufferedImage(width, height, TEXTURETYPE);
Texture frame = new Texture(bufferedImage);
frame.setTextureId(textureId);
//gl.glBindTexture(GL.GL_TEXTURE_2D, textureID);
frame.bind();
frame.initializeTextureCompatibleBuffer();
frame.updateTextureCompatibleBuffer();
//System.out.println(realWidth);
//System.out.println(realHeight);
if (bufferedImage.getColorModel().hasAlpha()) {
srcPixelFormat = GL11.GL_RGBA;
} else {
srcPixelFormat = GL11.GL_RGB;
}
// convert that image into a byte buffer of texture data
//ByteBuffer textureBuffer = TextureLoader.convertImageData(bufferedImage,texture);
int wrapMode = wrap ? GL11.GL_REPEAT : GL11.GL_CLAMP;
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, wrapMode);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, wrapMode);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, minFilter);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, magFilter);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D,
0,
dstPixelFormat,
frame.getTextureWidth(),
frame.getTextureHeight(),
0,
srcPixelFormat,
GL11.GL_UNSIGNED_BYTE,
frame.getTextureCompatibleBuffer());
return frame;
}
private static int createTextureID()
{
IntBuffer newBuffer = BufferUtils.createIntBuffer(1);//ByteBuffer.allocateDirect(Integer.SIZE/8).asIntBuffer();
GL11.glGenTextures(newBuffer);
return newBuffer.get(0);
}
public static void updateTexture(Texture frame){
frame.bind();
GL11.glTexSubImage2D(GL11.GL_TEXTURE_2D, 0, 0, 0, frame.getTextureWidth(), frame.getTextureHeight(), GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, frame.getTextureCompatibleBuffer());
}
public static void updateTexture(Texture frame, BufferedImage image){
frame.setImage(image);
frame.updateTextureCompatibleBuffer();
frame.bind();
GL11.glTexSubImage2D(GL11.GL_TEXTURE_2D, 0, 0, 0, frame.getTextureWidth(), frame.getTextureHeight(), GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, frame.getTextureCompatibleBuffer());
}
public static int get2Fold2(int num) {
return (int) Math.pow(2, Math.ceil(Math.log(num) * invln2));
}
/**
* Calculate how many bits wide a number is, i.e. position of highest 1 bit.
* Fully unraveled binary search method.
*
* @return p where 2**p is first power of two >= n. e.g. binary 0001_0101 ->
* 5, 0xffffffff -> 32, 0 -> 0, 1 -> 1, 2 -> 2, 3 -> 2, 4 -> 3
* (Vincent) Changed to return 2^n instead of n
* @author Dirk Bosmans Dirk.Bosmans@tijd.com
* @author Vincent Vollers
*/
static public final int get2Fold(int n) {
if (n < 0)
return 32;
if (n > 0x00010000) {
if (n > 0x01000000) {
if (n > 0x10000000) {
if (n > 0x40000000) {
// if ( n > 0x7fffffff )
// return 32
// else
// return 2147483648; is too much, so return -1
return -1;
} else {
// !( n > 0x3fffffff )
if (n > 0x20000000)
return 1073741824;
else
return 536870912;
}
} else {
// !( n > 0x0fffffff )
if (n > 0x04000000) {
if (n > 0x08000000)
return 268435456;
else
return 134217728;
} else {
// !( n > 0x03ffffff )
if (n > 0x02000000)
return 67108864;
else
return 33554432;
}
}
} else {
// !( n > 0x00ffffff )
if (n > 0x00100000) {
if (n > 0x00400000) {
if (n > 0x00800000)
return 16777216;
else
return 8388608;
} else {
// !( n > 0x003fffff )
if (n > 0x00200000)
return 4194304;
else
return 2097152;
}
} else {
// !( n > 0x000fffff )
if (n > 0x00040000) {
if (n > 0x00080000)
return 1048576;
else
return 524288;
} else {
// !( n > 0x0003ffff )
if (n > 0x00020000)
return 262144;
else
return 131072;
}
}
}
} else {
// !( n > 0x0000ffff )
if (n > 0x00000100) {
if (n > 0x00001000) {
if (n > 0x00004000) {
if (n > 0x00008000)
return 65536;
else
return 32768;
} else {
// !( n > 0x00003fff )
if (n > 0x00002000)
return 16384;
else
return 8192;
}
} else {
// !( n > 0x00000fff )
if (n > 0x00000400) {
if (n > 0x00000800)
return 4096;
else
return 2048;
} else {
// !( n > 0x000003ff )
if (n > 0x00000200)
return 1024;
else
return 512;
}
}
} else {
// !( n > 0x000000ff )
if (n > 0x00000010) {
if (n > 0x00000040) {
if (n > 0x00000080)
return 256;
else
return 128;
} else {
// !( n > 0x0000003f )
if (n > 0x00000020)
return 64;
else
return 32;
}
} else {
// !( n > 0x0000000f )
if (n > 0x00000004) {
if (n > 0x00000008)
return 16;
else
return 8;
} else {
// !( n > 0x00000003 )
if (n > 0x00000002)
return 4;
return n;
}
}
}
}
} // end widthInBits
}