/***********************************************************************
* mt4j Copyright (c) 2008 - 2009 C.Ruff, Fraunhofer-Gesellschaft All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
***********************************************************************/
package org.mt4j.util.opengl;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import javax.media.opengl.GL;
import javax.media.opengl.glu.GLU;
import processing.core.PApplet;
import processing.core.PConstants;
import processing.core.PImage;
import processing.opengl.PGraphicsOpenGL;
import com.sun.opengl.util.BufferUtil;
/**
* This class adds an opengl texture to a PImage object. The texture is handled in a similar way to the
* pixels property: image data can be copied to and from the texture using loadTexture and updateTexture methods.
* However, bringing the texture down to image or pixels data can slow down the application considerably (since
* involves copying texture data from GPU to CPU), especially when handling large textures. So it is recommended
* to do all the texture handling without calling updateTexture, and doing so only at the end if the texture
* is needed as a regular image.
* Original file Copyright (c) by Andr�s Colubri
*/
public class GLTexture extends PImage implements PConstants , GLConstants{
//FIXME TEST
/** The initialized. */
private boolean glTextureInitialized = false;
/**
* Checks if is initialized.
*
* @return true, if is initialized
*/
public boolean isGLTexObjectInitialized() {
return glTextureInitialized;
}
/**
* Creates an instance of GLTexture with size 1x1. The texture is not initialized.
*
* @param parent PApplet
*/
public GLTexture(PApplet parent){
this(parent, 1, 1, new GLTextureParameters(), false);
}
/**
* Creates an instance of GLTexture with size width x height. The texture is initialized (empty) to that size.
*
* @param parent PApplet
* @param width int
* @param height int
*/
public GLTexture(PApplet parent, int width, int height){
this(parent, width, height, new GLTextureParameters(), true);
}
/**
* Creates an instance of GLTexture with size width x height and with the specified parameters.
* The texture is initialized (empty) to that size.
*
* @param parent PApplet
* @param width int
* @param height int
* @param params GLTextureParameters
*/
public GLTexture(PApplet parent, int width, int height, GLTextureParameters params){
this(parent, width, height, params, true);
}
// FIXME ENABLE
/**
* Creates an instance of GLTexture with size width x height and with the specified parameters.
* The texture is initialized (empty) to that size.
*
* @param parent PApplet
* @param width int
* @param height int
* @param params GLTextureParameters
* @param initGLTextureObject indicates whether to also create a openGL texture object (needed if using opengl)
*/
public GLTexture(PApplet parent, int width, int height, GLTextureParameters params, boolean initGLTextureObject){
super(width, height, ARGB);
// super(width, height, RGB);
this.parent = parent;
pgl = (PGraphicsOpenGL)parent.g;
gl = pgl.gl;
setTextureParams(params);
if (initGLTextureObject){
initTexture(width, height);
}
}
/**
* Creates an instance of GLTexture with size width x height and with the specified parameters.
* The texture is initialized (empty) to that size.
* The last paramter is a dummy parameter, that isnt used.
* This constructor initialized the textures internal PImage object (used by processing to texture stuff)
* with 1,1, dimensions. This is useful if we really only intend to use the texture for opengl dawing.
*
* @param parent PApplet
* @param width int
* @param height int
* @param params GLTextureParameters
* @param initGLTextureObject indicates whether to also create a openGL texture object (needed if using opengl)
* @param dummy the dummy
*/
public GLTexture(PApplet parent, int width, int height, GLTextureParameters params, boolean initGLTextureObject, int dummy){
//FIXME TEST DO DIFFERENT!
//this texture for opengl!
// super(width, height, ARGB);
super(1, 1, ARGB);
this.width = width;
this.height = height;
this.parent = parent;
pgl = (PGraphicsOpenGL)parent.g;
gl = pgl.gl;
setTextureParams(params);
if (initGLTextureObject){
initTexture(width, height);
}
}
/** Creates an instance of GLTexture using image file filename as source.
*
* @param parent PApplet
* @param filename String
*/
public GLTexture(PApplet parent, String filename){
this(parent, filename, new GLTextureParameters());
}
/**
* Creates an instance of GLTexture with power-of-two width and height that such that width * height is the closest to size, and with the specified parameters.
* The texture is initialized (empty) to that size.
*
* @param parent PApplet
* @param params GLTextureParameters
* @param fileName the file name
*/
public GLTexture(PApplet parent, String fileName, GLTextureParameters params){
super(1, 1, ARGB);
this.parent = parent;
pgl = (PGraphicsOpenGL)parent.g;
gl = pgl.gl;
setTextureParams(params); //TODO change params to use texture_recangle_arb if image is non power of two?
loadTexture(fileName);
// init(width, height, params); //INIT OR NOT? -> initialized in loadtexture already?
}
/**
* Creates an instance of GLTexture with power-of-two width and height that such that width * height is the closest to size.
* The texture is initialized (empty) to that size.
*
* @param parent PApplet
* @param size int
*/
public GLTexture(PApplet parent, int size){
super(1, 1, ARGB);
this.parent = parent;
pgl = (PGraphicsOpenGL)parent.g;
gl = pgl.gl;
calculateWidthHeight(size);
init(width, height);
}
/**
* Sets the size of the image and texture to width x height. If the texture is already initialized,
* it first destroys the current opengl texture object and then creates a new one with the specified
* size.
*
* @param width int
* @param height int
*/
public void init(int width, int height){
init(width, height, new GLTextureParameters());
}
/**
* Sets the size of the image and texture to width x height, and the parameters of the texture to params .
* If the texture is already initialized, it first destroys the current opengl texture object and then creates
* a new one with the specified size.
*
* @param width int
* @param height int
* @param params GLTextureParameters
*/
public void init(int width, int height, GLTextureParameters params){
super.init(width, height, ARGB);
setTextureParams(params);
initTexture(width, height);
}
/**
* Returns true if the texture has been initialized.
*
* @return boolean
*/
public boolean available()
{
return 0 < tex[0];
}
/**
* Provides the ID of the opegl texture object.
*
* @return int
*/
public int getTextureID()
{
return tex[0];
}
/**
* Returns the texture target.
*
* @return int
*/
public int getTextureTarget()
{
return texTarget;
}
/**
* Returns the texture internal format.
*
* @return int
*/
public int getTextureInternalFormat()
{
return texInternalFormat;
}
/**
* Returns the texture minimization filter.
*
* @return int
*/
public int getTextureMinFilter()
{
return minFilter;
}
/**
* Returns the texture magnification filter.
*
* @return int
*/
public int getTextureMagFilter()
{
return magFilter;
}
/**
* Returns true or false whether or not the texture is using mipmaps.
*
* @return boolean
*/
public boolean usingMipmaps()
{
return usingMipmaps;
}
/**
* Returns the maximum possible value for the texture coordinate S.
*
* @return float
*/
public float getMaxTextureCoordS()
{
return maxTexCoordS;
}
/**
* Returns the maximum possible value for the texture coordinate T.
*
* @return float
*/
public float getMaxTextureCoordT()
{
return maxTexCoordT;
}
/**
* Returns true if the texture is flipped along the horizontal direction.
*
* @return boolean;
*/
public boolean isFlippedX()
{
return flippedX;
}
/**
* Sets the texture as flipped or not flipped on the horizontal direction.
*
* @param v boolean;
*/
public void setFlippedX(boolean v)
{
flippedX = v;
}
/**
* Returns true if the texture is flipped along the vertical direction.
*
* @return boolean;
*/
public boolean isFlippedY()
{
return flippedY;
}
/**
* Sets the texture as flipped or not flipped on the vertical direction.
*
* @param v boolean;
*/
public void setFlippedY(boolean v)
{
flippedY = v;
}
/**
* Puts img into texture, pixels and image.
*
* @param img PImage
*/
public void putImage(PImage img){
// System.out.println("putting image in glTexture, img format: " + img.format);
img.loadPixels();
if ((img.width != width) || (img.height != height))
{
//System.out.println("put pixels into texture..dimensions are different from former texture!");
GLTextureParameters p = new GLTextureParameters();
p.format = this.textureParams.format;
p.magFilter = this.textureParams.magFilter;
p.minFilter = this.textureParams.minFilter;
p.target = this.textureParams.target;
p.wrap_s = this.textureParams.wrap_s;
p.wrap_t = this.textureParams.wrap_t;
init(img.width, img.height, p);
}
// Putting img into pixels...
PApplet.arraycopy(img.pixels, pixels);
// ...into texture...
loadTexture();
// ...and into image.
updatePixels();
}
/**
* Puts img into texture, pixels and image.
*
* @param img PImage
*/
public void putImageOnly(PImage img){
// /*
img.loadPixels();
if ((img.width != width) || (img.height != height))
{
System.out.println("put pixels into texture..dimensions are different from former texture!");
GLTextureParameters p = new GLTextureParameters();
p.format = this.textureParams.format;
p.magFilter = this.textureParams.magFilter;
p.minFilter = this.textureParams.minFilter;
p.target = this.textureParams.target;
p.wrap_s = this.textureParams.wrap_s;
p.wrap_t = this.textureParams.wrap_t;
init(img.width, img.height, p);
}
// Putting img into pixels...
PApplet.arraycopy(img.pixels, pixels);
// ...into texture...
// loadTexture();
// ...and into image.
updatePixels();
// */
}
/**
* Puts pixels of img into openGL texture object only.
*
* @param img PImage
*/
public void putPixelsIntoTexture(PImage img){
if ((img.width != width) || (img.height != height)){
//FIXME THIS WAS ADDED
System.out.println("put pixels into texture..dimensions are different from former texture!");
GLTextureParameters p = new GLTextureParameters();
p.format = this.textureParams.format;
p.magFilter = this.textureParams.magFilter;
p.minFilter = this.textureParams.minFilter;
p.target = this.textureParams.target;
p.wrap_s = this.textureParams.wrap_s;
p.wrap_t = this.textureParams.wrap_t;
init(img.width, img.height, p);
// init(img.width, img.height, new GLTextureParameters());
}
// Putting into texture.
putBuffer(img.pixels);
}
/**
* Puts the pixels of img inside the rectangle (x, y, x+w, y+h) into texture only.
*
* @param img PImage
* @param x int
* @param y int
* @param w int
* @param h int
*/
public void putPixelsIntoTexture(PImage img, int x, int y, int w, int h){
x = PApplet.constrain(x, 0, img.width);
y = PApplet.constrain(y, 0, img.height);
w = PApplet.constrain(w, 0, img.width - x);
h = PApplet.constrain(h, 0, img.height - y);
if ((w != width) || (h != height))
{
init(w, h, new GLTextureParameters());
}
int p0;
int dest[] = new int[w * h];
for (int j = 0; j < h; j++)
{
p0 = y * img.width + x + (img.width - w) * j;
PApplet.arraycopy(img.pixels, p0 + w * j, dest, w * j, w);
}
// Putting into texture.
putBuffer(dest);
}
/*
public PImage getPImage(){
int w = width;
int h = height;
PImage img = new PImage(width, height);
int size = w * h;
IntBuffer buffer = BufferUtil.newIntBuffer(size);
gl.glBindTexture(texTarget, tex[0]);
gl.glGetTexImage(texTarget, 0, GL.GL_BGRA, GL.GL_UNSIGNED_BYTE, buffer);
gl.glBindTexture(texTarget, 0);
buffer.get(img.pixels);
img.updatePixels();
return img;
}
*/
/**
* Copies texture to img.
*
* @param img PImage
*/
public void getImage(PImage img){
int w = width;
int h = height;
if ((img.width != w) || (img.height != h))
{
img.init(w, h, ARGB);
}
int size = w * h;
IntBuffer buffer = BufferUtil.newIntBuffer(size);
gl.glBindTexture(texTarget, tex[0]);
gl.glGetTexImage(texTarget, 0, GL.GL_BGRA, GL.GL_UNSIGNED_BYTE, buffer);
gl.glBindTexture(texTarget, 0);
buffer.get(img.pixels);
if (flippedX)
flipArrayOnX(img.pixels, 1);
if (flippedY)
flipArrayOnY(img.pixels, 1);
img.updatePixels();
}
/**
* Load texture, pixels and image from file.
*
* @param filename String
*/
public void loadTexture(String filename){
PImage img = parent.loadImage(filename);
putImage(img);
}
/**
* Copy pixels to openGL texture (loadPixels should have been called beforehand).
*/
public void loadTexture(){
putBuffer(pixels);
}
/**
* Copy texture to pixels (doesn't call updatePixels).
*/
public void updateTexture(){
int size = width * height;
IntBuffer buffer = BufferUtil.newIntBuffer(size);
gl.glBindTexture(texTarget, tex[0]);
gl.glGetTexImage(texTarget, 0, GL.GL_BGRA, GL.GL_UNSIGNED_BYTE, buffer);
gl.glBindTexture(texTarget, 0);
buffer.get(pixels);
if (flippedX) flipArrayOnX(pixels, 1);
if (flippedY) flipArrayOnY(pixels, 1);
}
// /**
// * Applies filter texFilter using this texture as source and destTex as destination.
// * @param texFilter GLTextureFilter
// * @param destTex GLTexture
// */
// public void filter(GLTextureFilter texFilter, GLTexture destTex)
// {
// texFilter.apply(new GLTexture[] { this }, new GLTexture[] { destTex });
// }
//
// /**
// * Applies filter texFilter using this texture as source and destTex as multiple destinations.
// * @param texFilter GLTextureFilter
// * @param destTexArray GLTexture[]
// */
// public void filter(GLTextureFilter texFilter, GLTexture[] destTexArray)
// {
// texFilter.apply(new GLTexture[] { this }, destTexArray);
// }
//
// /**
// * Applies filter texFilter using this texture as source, destTex as destination and params as the
// * parameters for the filter.
// * @param texFilter GLTextureFilter
// * @param destTex GLTexture
// * @param params GLTextureFilterParameters
// */
// public void filter(GLTextureFilter texFilter, GLTexture destTex, GLTextureFilterParameters params)
// {
// texFilter.apply(new GLTexture[] { this }, new GLTexture[] { destTex }, params);
// }
//
// /**
// * Applies filter texFilter using this texture as source, destTex as multiple destinations and params as the
// * parameters for the filter.
// * @param texFilter GLTextureFilter
// * @param destTexArray GLTexture[]
// * @param params GLTextureFilterParameters
// */
// public void filter(GLTextureFilter texFilter, GLTexture[] destTexArray, GLTextureFilterParameters params)
// {
// texFilter.apply(new GLTexture[] { this }, destTexArray, params);
// }
//
// /**
// * Applies filter texFilter using this texture as source, destTex as destination and fadeConst as the
// * fading constant for the filter.
// * @param texFilter GLTextureFilter
// * @param destTex GLTexture
// * @param fadeConst float
// */
// public void filter(GLTextureFilter texFilter, GLTexture destTex, float fadeConst)
// {
// texFilter.apply(new GLTexture[] { this }, new GLTexture[] { destTex }, fadeConst);
// }
//
// /**
// * Applies filter texFilter using this texture as source, destTex as multiple destinations and fadeConst as the
// * fading constant for the filter.
// * @param texFilter GLTextureFilter
// * @param destTexArray GLTexture[]
// * @param fadeConst float
// */
// public void filter(GLTextureFilter texFilter, GLTexture[] destTexArray, float fadeConst)
// {
// texFilter.apply(new GLTexture[] { this }, destTexArray, fadeConst);
// }
//
// /**
// * Applies filter texFilter using this texture as source, destTex as destination, fadeConst as the
// * fading constant for the filter and params as the parameters for the filter.
// * @param texFilter GLTextureFilter
// * @param destTex GLTexture
// * @param fadeConst float
// */
// public void filter(GLTextureFilter texFilter, GLTexture destTex, float fadeConst, GLTextureFilterParameters params)
// {
// texFilter.apply(new GLTexture[] { this }, new GLTexture[] { destTex }, fadeConst, params);
// }
//
// /**
// * Applies filter texFilter using this texture as source, destTex as multiple destinations, fadeConst as the
// * fading constant for the filter and params as the parameters for the filter.
// * @param texFilter GLTextureFilter
// * @param destTexArray GLTexture[]
// * @param fadeConst float
// */
// public void filter(GLTextureFilter texFilter, GLTexture[] destTexArray, float fadeConst, GLTextureFilterParameters params)
// {
// texFilter.apply(new GLTexture[] { this }, destTexArray, fadeConst, params);
// }
//
/**
* Draws the texture using the opengl commands, inside a rectangle of width w and height h
* located at (x,y).
*
* @param x float
* @param y float
* @param w float
* @param h float
*/
/**
* Copies intArray into the texture, assuming that the array contains 4 color components and pixels are unsigned bytes.
*
* @param intArray int[]
*/
public void putBuffer(int[] intArray){
putBuffer(intArray, TEX4, TEX_UBYTE);
}
/**
* Copies intArray into the texture, using the specified format and assuming that the pixels are unsigned bytes.
*
* @param intArray int[]
* @param format int
*/
public void putBuffer(int[] intArray, int format){
putBuffer(intArray, format, TEX_UBYTE);
}
/**
* Copies intArray into the texture, using the specified format and assuming that the pixels are unsigned bytes.
*
* @param intArray int[]
* @param format int
*/
public void putByteBuffer(int[] intArray, int format){
putBuffer(intArray, format, TEX_UBYTE);
}
/**
* Copies intArray into the texture, using the specified format and assuming that the pixels are integers.
*
* @param intArray int[]
* @param format int
*/
public void putIntBuffer(int[] intArray, int format){
putBuffer(intArray, format, TEX_INT);
}
/**
* Copies intArray into the texture, using the format and type specified.
*
* @param intArray int[]
* @param format int
* @param type int
*/
public void putBuffer(int[] intArray, int format, int type){
this.putBuffer(IntBuffer.wrap(intArray), format, type);
//
// if (tex[0] == 0){
// initTexture(width, height);
// }
//
// int glFormat;
// if (format == TEX1)
// glFormat = GL.GL_LUMINANCE;
// else if (format == TEX3)
// glFormat = GL.GL_RGB;
// else
// glFormat = GL.GL_BGRA;
//// glFormat = GL.GL_RGB;
//
// int glType;
// if (type == TEX_INT)
// glType = GL.GL_INT;
// else
// glType = GL.GL_UNSIGNED_BYTE;
//
// gl.glBindTexture(texTarget, tex[0]);
//
// //FIXME REMOVE
//// System.out.println("Formats: ");
//// System.out.println(GL.GL_RGB);
//// System.out.println(GL.GL_BGRA);
//// System.out.println(GL.GL_INT);
//// System.out.println(GL.GL_UNSIGNED_BYTE);
////
//// System.out.println("glFormat: " + glFormat);
//// System.out.println("glType: " + glType);
//
//// glFormat = GL.GL_RGB;
//// glFormat = GL.GL_RGBA;
//// glFormat = GL.GL_BGR;
//// glFormat = GL.GL_BGRA;
//// glFormat = GL.GL_ABGR_EXT;
//
//// glType = GL.GL_UNSIGNED_BYTE;
//// glType = GL.GL_BYTE;
//
// if (texTarget == GL.GL_TEXTURE_1D){
// if (glFormat == GL.GL_BGRA){
// glFormat = GL.GL_RGBA;
// }
// gl.glTexSubImage1D(texTarget, 0, 0, width, glFormat, glType, IntBuffer.wrap(intArray));
// }else{
// if (usingMipmaps){
//// System.out.println("usingmipmaps - gluBuild2DMipmaps");
// GLU glu = ((PGraphicsOpenGL)this.parent.g).glu;
// glu.gluBuild2DMipmaps(texTarget, texInternalFormat, width, height, glFormat, glType, IntBuffer.wrap(intArray));
//// glstate.glu.gluBuild2DMipmaps(texTarget, texInternalFormat, width, height, glFormat, glType, IntBuffer.wrap(intArray));
// }
// else{
//// System.out.println("glTexSubImage2D - no mipmaps; rectangular: " + (texTarget==GL.GL_TEXTURE_RECTANGLE_ARB));
// gl.glTexSubImage2D(texTarget, 0, 0, 0, width, height, glFormat, glType, IntBuffer.wrap(intArray));
//
// //FIXME TEST
//// gl.glTexSubImage2D(texTarget, 0, 0, 0, width, height, GL.GL_LUMINANCE, glType, IntBuffer.wrap(intArray));
//// gl.glTexSubImage2D(texTarget, 0, 0, 0, width, height, GL.GL_ALPHA, glType, IntBuffer.wrap(intArray));
//
//// gl.glTexImage2D(texTarget, 0, texInternalFormat, width, height, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, IntBuffer.wrap(intArray));
// }
// }
// gl.glBindTexture(texTarget, 0);
}
/**
* Copies buffer into the texture, using the format and type specified.
*
* @param buffer IntBuffer
* @param format int
* @param type int
*/
public void putBuffer(IntBuffer buffer, int format, int type){
if (tex[0] == 0){
initTexture(width, height);
}
int glFormat;
if (format == TEX1)
glFormat = GL.GL_LUMINANCE;
else if (format == TEX3)
glFormat = GL.GL_RGB;
else
glFormat = GL.GL_BGRA;
int glType;
if (type == TEX_INT)
glType = GL.GL_INT;
else
glType = GL.GL_UNSIGNED_BYTE;
gl.glBindTexture(texTarget, tex[0]);
if (texTarget == GL.GL_TEXTURE_1D){
if (glFormat == GL.GL_BGRA){
glFormat = GL.GL_RGBA;
}
gl.glTexSubImage1D(texTarget, 0, 0, width, glFormat, glType, buffer);
}else{
if (usingMipmaps){
// System.out.println("usingmipmaps - gluBuild2DMipmaps");
GLU glu = ((PGraphicsOpenGL)this.parent.g).glu;
glu.gluBuild2DMipmaps(texTarget, texInternalFormat, width, height, glFormat, glType, buffer);
// glstate.glu.gluBuild2DMipmaps(texTarget, texInternalFormat, width, height, glFormat, glType, buffer);
}
else{
gl.glTexSubImage2D(texTarget, 0, 0, 0, width, height, glFormat, glType, buffer);
}
}
gl.glBindTexture(texTarget, 0);
}
/**
* Copies floatArray into the texture, assuming that the array has 4 components.
*
* @param floatArray float[]
*/
public void putBuffer(float[] floatArray){
putBuffer(floatArray, TEX4);
}
/**
* Copies floatArray into the texture, using the specified format.
*
* @param floatArray float[]
* @param format int
*/
public void putBuffer(float[] floatArray, int format){
if (tex[0] == 0){
initTexture(width, height);
}
int glFormat;
if (format == TEX1)
glFormat = GL.GL_LUMINANCE;
else if
(format == TEX3) glFormat = GL.GL_RGB;
else
glFormat = GL.GL_RGBA;
gl.glBindTexture(texTarget, tex[0]);
if (texTarget == GL.GL_TEXTURE_1D)
gl.glTexSubImage1D(texTarget, 0, 0, width, glFormat, GL.GL_FLOAT, FloatBuffer.wrap(floatArray));
else
gl.glTexSubImage2D(texTarget, 0, 0, 0, width, height, glFormat, GL.GL_FLOAT, FloatBuffer.wrap(floatArray));
gl.glBindTexture(texTarget, 0);
}
/**
* Copies the texture into intArray, assuming that the array has 4 components and the pixels are unsigned bytes.
*
* @param intArray int[]
*/
public void getBuffer(int[] intArray){
getBuffer(intArray, TEX4, TEX_UBYTE);
}
/**
* Copies the texture into intArray, using the specified format and assuming that the pixels are unsigned bytes.
*
* @param intArray int[]
* @param format int
*/
public void getBuffer(int[] intArray, int format){
getBuffer(intArray, format, TEX_UBYTE);
}
/**
* Copies the texture into intArray, using the specified format and assuming that the pixels are unsigned bytes.
*
* @param intArray int[]
* @param format int
*/
public void getByteBuffer(int[] intArray, int format){
getBuffer(intArray, format, TEX_UBYTE);
}
/**
* Copies the texture into intArray, using the specified format and assuming that the pixels are integers.
*
* @param intArray int[]
* @param format int
*/
public void getIntBuffer(int[] intArray, int format){
getBuffer(intArray, format, TEX_INT);
}
/**
* Copies the texture into intArray, using the specified format and type.
*
* @param intArray int[]
* @param format int
* @param type int
*/
public void getBuffer(int[] intArray, int format, int type){
int mult;
int glFormat;
if (format == TEX1){
mult = 1;
glFormat = GL.GL_LUMINANCE;
}else if (format == TEX3){
mult = 3;
glFormat = GL.GL_RGB;
}else{
mult = 4;
glFormat = GL.GL_RGBA;
}
int size;
int glType;
if (type == TEX_INT){
glType = GL.GL_INT;
}else{
mult = 1;
glType = GL.GL_UNSIGNED_BYTE;
}
size = mult * width * height;
if (intArray.length != size){
System.err.println("Wrong size of buffer!");
return;
}
IntBuffer buffer = BufferUtil.newIntBuffer(size);
gl.glBindTexture(texTarget, tex[0]);
gl.glGetTexImage(texTarget, 0, glFormat, glType, buffer);
gl.glBindTexture(texTarget, 0);
buffer.get(intArray);
if (flippedX) flipArrayOnX(intArray, mult);
if (flippedY) flipArrayOnY(intArray, mult);
}
/**
* Copies the texture into floatArray.
*
* @param floatArray float[]
* @param format int
*/
public void getBuffer(float[] floatArray, int format){
int mult;
int glFormat;
if (format == TEX1){
mult = 1;
glFormat = GL.GL_LUMINANCE;
}else if (format == TEX3){
mult = 3;
glFormat = GL.GL_RGB;
}else{
mult = 4;
glFormat = GL.GL_RGBA;
}
int size = mult * width * height;
if (floatArray.length != size){
System.err.println("Wrong size of buffer!");
return;
}
FloatBuffer buffer = BufferUtil.newFloatBuffer(size);
gl.glBindTexture(texTarget, tex[0]);
gl.glGetTexImage(texTarget, 0, glFormat, GL.GL_FLOAT, buffer);
gl.glBindTexture(texTarget, 0);
buffer.get(floatArray);
if (flippedX)
flipArrayOnX(floatArray, mult);
if (flippedY)
flipArrayOnY(floatArray, mult);
}
/**
* Sets the texture to have the same given float value in each component.
*
* @param r float
* @param g float
* @param b float
* @param a float
*/
public void setValue(float r, float g, float b, float a){
float valBuffer[] = new float[4 * width * height];
for (int j = 0; j < height; j++)
for (int i = 0; i < width; i++)
{
valBuffer[i * 4 + j * width * 4] = r;
valBuffer[i * 4 + j * width * 4 + 1] = g;
valBuffer[i * 4 + j * width * 4 + 2] = b;
valBuffer[i * 4 + j * width * 4 + 3] = a;
}
putBuffer(valBuffer);
}
/**
* Flips intArray along the X axis.
*
* @param intArray int[]
* @param mult int
*/
protected void flipArrayOnX(int[] intArray, int mult){
int index = 0;
int xindex = mult * (width - 1);
for (int x = 0; x < width / 2; x++)
{
for (int y = 0; y < height; y++)
{
int i = index + mult * y * width;
int j = xindex + mult * y * width;
for (int c = 0; c < mult; c++)
{
int temp = intArray[i];
intArray[i] = intArray[j];
intArray[j] = temp;
i++;
j++;
}
}
index += mult;
xindex -= mult;
}
}
/**
* Flips intArray along the Y axis.
*
* @param intArray int[]
* @param mult int
*/
protected void flipArrayOnY(int[] intArray, int mult){
int index = 0;
int yindex = mult * (height - 1) * width;
for (int y = 0; y < height / 2; y++)
{
for (int x = 0; x < mult * width; x++)
{
int temp = intArray[index];
intArray[index] = intArray[yindex];
intArray[yindex] = temp;
index++;
yindex++;
}
yindex -= mult * width * 2;
}
}
/**
* Flips floatArray along the X axis.
*
* @param mult int
* @param floatArray the float array
*/
protected void flipArrayOnX(float[] floatArray, int mult){
int index = 0;
int xindex = mult * (width - 1);
for (int x = 0; x < width / 2; x++){
for (int y = 0; y < height; y++){
int i = index + mult * y * width;
int j = xindex + mult * y * width;
for (int c = 0; c < mult; c++){
float temp = floatArray[i];
floatArray[i] = floatArray[j];
floatArray[j] = temp;
i++;
j++;
}
}
index += mult;
xindex -= mult;
}
}
/**
* Flips floatArray along the Y axis.
*
* @param mult int
* @param floatArray the float array
*/
protected void flipArrayOnY(float[] floatArray, int mult){
int index = 0;
int yindex = mult * (height - 1) * width;
for (int y = 0; y < height / 2; y++){
for (int x = 0; x < mult * width; x++){
float temp = floatArray[index];
floatArray[index] = floatArray[yindex];
floatArray[yindex] = temp;
index++;
yindex++;
}
yindex -= mult * width * 2;
}
}
/**
* Inits the opengl texture object.
*
* @param w int
* @param h int
*
* @invisible
* Creates an empty opengl texture object.
* Deletes the an already existing gl texture object if this object contained one.
* The gl texture object can be filled with a call to <code>putPixelsIntoTexture</code>.
* It then uses the PImage pixels to fill the texture.
*/
public void initTexture(int w, int h){
this.glTextureInitialized = true;
if (tex[0] != 0){
deleteTextureGL();
}
//Give me a free texture allocation adress ID and save it into the int array (tex)
//1 is for the number of ids to generate, since it is "1" here, it will
//place one id in the arrays first index tex[0] will be the id we can use
gl.glGenTextures(1, tex, 0);
//tells opengl which texture to reference in following calls from now on!
//the first parameter is eigher GL.GL_TEXTURE_2D or ..1D
gl.glBindTexture(texTarget, tex[0]);
//SET texture mag/min FILTER mode
gl.glTexParameteri(texTarget, GL.GL_TEXTURE_MAG_FILTER, magFilter);
gl.glTexParameteri(texTarget, GL.GL_TEXTURE_MIN_FILTER, minFilter);
//SET texture WRAP mode
//GL_REPEAT with a RECTANGULAR texture target are not supported! -> so use GL_CLAMP then.
if (this.texTarget == GL.GL_TEXTURE_RECTANGLE_ARB){
//FIXME gluBuildmipmaps staucht NPOT texture auf pot zusammen?
//BEi clamp komischer wasser fbo error
if (this.wrap_s == GL.GL_REPEAT){
this.wrap_s = GL.GL_CLAMP;
}
if (this.wrap_t == GL.GL_REPEAT){
this.wrap_t = GL.GL_CLAMP;
}
maxTexCoordS = w;
maxTexCoordT = h;
}else{
maxTexCoordS = 1.0f;
maxTexCoordT = 1.0f;
}
gl.glTexParameteri(texTarget, GL.GL_TEXTURE_WRAP_S, this.wrap_s);
gl.glTexParameteri(texTarget, GL.GL_TEXTURE_WRAP_T, this.wrap_t);
//Load image DATA into texture
if (texTarget == GL.GL_TEXTURE_1D) {
gl.glTexImage1D(texTarget, 0, texInternalFormat, w, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, null);
}
else{
//This call will upload the texture to the video memory where it
//will be ready for us to use in our programs.
// gl.glTexImage2D(texTarget, 0, texInternalFormat, w, h, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, null);
gl.glTexImage2D(texTarget, 0, texInternalFormat, w, h, 0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, null);//ORIGINAL
//FIXME TEST
// gl.glTexImage2D(texTarget, 0, GL.GL_INTENSITY, w, h, 0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, null);
// gl.glTexImage2D(texTarget, 0, GL.GL_INTENSITY, w, h, 0, GL.GL_LUMINANCE_ALPHA, GL.GL_UNSIGNED_BYTE, null);
// gl.glTexImage2D(texTarget, 0, GL.GL_ALPHA8, w, h, 0, GL.GL_ALPHA, GL.GL_UNSIGNED_BYTE, null);
// gl.glTexImage2D(texTarget, 0, GL.GL_LUMINANCE, w, h, 0, GL.GL_LUMINANCE, GL.GL_UNSIGNED_BYTE, null);
// gl.glTexImage2D(texTarget, 0, 4, w, h, 0, 4, GL.GL_UNSIGNED_BYTE, null);
// gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_ALPHA8, w, h, 0, GL.GL_ALPHA, GL.GL_INT, null); //von fbo code REMOVE!
}
gl.glBindTexture(texTarget, 0); //Unbind texture
}
/**
* Delete texture gl.
*
* @invisible
* Deletes the opengl texture object.
*/
public void deleteTextureGL(){
if (tex[0] != 0){
gl.glDeleteTextures(1, tex, 0);
tex[0] = 0;
}
}
/** The texture params. */
private GLTextureParameters textureParams;//FIXME THIS WAS ADDED
/**
* Sets the texture params.
*
* @param params GLTextureParameters
*
* @invisible
* Sets texture target and internal format according to the target and type specified.
*/
protected void setTextureParams(GLTextureParameters params){
textureParams = params;//FIXME THIS WAS ADDED
//Set texture TARGET
if (params.target == GLConstants.NORMAL){
texTarget = GL.GL_TEXTURE_2D;
}else if (params.target == RECTANGULAR){
texTarget = GL.GL_TEXTURE_RECTANGLE_ARB;
}else if (params.target == ONEDIM){
texTarget = GL.GL_TEXTURE_1D;
}
//Set texture color FOMRAT
if (params.format == COLOR){
texInternalFormat = GL.GL_RGBA;
}else if (params.format == FLOAT4){
texInternalFormat = GL.GL_RGBA16F_ARB;
}else if (params.format == DOUBLE4){
texInternalFormat = GL.GL_RGBA32F_ARB;
}
minFilter = GL.GL_LINEAR;
//Set texture MIN filter
if (params.minFilter == NEAREST){
minFilter = GL.GL_NEAREST;
}else if (params.minFilter == LINEAR){
minFilter = GL.GL_LINEAR;
}else if (params.minFilter == NEAREST_MIPMAP_NEAREST && texTarget != GL.GL_TEXTURE_RECTANGLE_ARB){
minFilter = GL.GL_NEAREST_MIPMAP_NEAREST;
}else if (params.minFilter == LINEAR_MIPMAP_NEAREST && texTarget != GL.GL_TEXTURE_RECTANGLE_ARB){
minFilter = GL.GL_LINEAR_MIPMAP_NEAREST;
}else if (params.minFilter == NEAREST_MIPMAP_LINEAR && texTarget != GL.GL_TEXTURE_RECTANGLE_ARB){
minFilter = GL.GL_NEAREST_MIPMAP_LINEAR;
}else if (params.minFilter == LINEAR_MIPMAP_LINEAR && texTarget != GL.GL_TEXTURE_RECTANGLE_ARB){
minFilter = GL.GL_LINEAR_MIPMAP_LINEAR;
}
// minFilter = GL.GL_LINEAR_MIPMAP_NEAREST; //FIXME REMOVE
//FIXME glubuild2dMipmaps seems to work with rectangle_arb textures!?
magFilter = GL.GL_LINEAR;
//Set texture MAG filter
if (params.magFilter == NEAREST){
magFilter = GL.GL_NEAREST;
}else if (params.magFilter == LINEAR){
magFilter = GL.GL_LINEAR;
}
//Set MipMapping
usingMipmaps = (minFilter == GL.GL_NEAREST_MIPMAP_NEAREST) ||
(minFilter == GL.GL_LINEAR_MIPMAP_NEAREST) ||
(minFilter == GL.GL_NEAREST_MIPMAP_LINEAR) ||
(minFilter == GL.GL_LINEAR_MIPMAP_LINEAR);
flippedX = false;
flippedY = false;
//Set texture WRAP mode
this.wrap_s = params.wrap_s;
this.wrap_t = params.wrap_t;
/*
if (params.wrap_s == GL.GL_CLAMP){
this.wrap_s = GL.GL_CLAMP;
}else if (params.wrap_s == GL.GL_REPEAT){
this.wrap_s = GL.GL_REPEAT;
}else{
this.wrap_s = GL.GL_CLAMP;
}
if (params.wrap_t == GL.GL_CLAMP){
this.wrap_t = GL.GL_CLAMP;
}else if (params.wrap_t == GL.GL_REPEAT){
this.wrap_t = GL.GL_REPEAT;
}else{
this.wrap_t = GL.GL_CLAMP;
}
*/
}
public void setWrap(int wrap_s, int wrap_t){
this.wrap_s = wrap_s;
this.textureParams.wrap_s = this.wrap_s;
this.wrap_t = wrap_t;
this.textureParams.wrap_s = this.wrap_t;
if (this.isGLTexObjectInitialized()){
gl.glBindTexture(this.getTextureTarget(), this.getTextureID());
gl.glTexParameteri(texTarget, GL.GL_TEXTURE_WRAP_S, this.wrap_s);
gl.glTexParameteri(texTarget, GL.GL_TEXTURE_WRAP_T, this.wrap_t);
gl.glBindTexture(this.getTextureTarget(), 0);
}
}
public void setFilter(int minFilter, int magFilter){
this.minFilter = minFilter;
this.textureParams.minFilter = this.minFilter;
this.magFilter = magFilter;
this.textureParams.magFilter = this.magFilter;
if (this.isGLTexObjectInitialized()){
gl.glBindTexture(this.getTextureTarget(), this.getTextureID());
gl.glTexParameteri(texTarget, GL.GL_TEXTURE_MAG_FILTER, this.magFilter);
gl.glTexParameteri(texTarget, GL.GL_TEXTURE_MIN_FILTER, this.minFilter);
gl.glBindTexture(this.getTextureTarget(), 0);
}
boolean usedMipMapPreviously = usingMipmaps;
usingMipmaps = (minFilter == GL.GL_NEAREST_MIPMAP_NEAREST) ||
(minFilter == GL.GL_LINEAR_MIPMAP_NEAREST) ||
(minFilter == GL.GL_NEAREST_MIPMAP_LINEAR) ||
(minFilter == GL.GL_LINEAR_MIPMAP_LINEAR);
if (!usedMipMapPreviously && usingMipmaps){
putBuffer(this.pixels);
}
}
/**
* Calculate width height.
*
* @param size int
*
* @invisible
* Generates a power-of-two box width and height so that width * height is closest to size.
*/
protected void calculateWidthHeight(int size){
int w, h;
float l = PApplet.sqrt(size);
for (w = 2; w < l; w *= 2);
int n0 = w * w;
int n1 = w * w / 2;
if (Math.abs(n0 - size) < Math.abs(n1 - size)) h = w;
else h = w / 2;
width = w;
height = h;
}
/** The gl. */
protected GL gl;
/** The pgl. */
protected PGraphicsOpenGL pgl;
/** The tex. */
// protected int[] tex = { 0 };
public int[] tex = { 0 }; //FIXME REMOVE!!
/** The tex target. */
protected int texTarget;
/** The tex internal format. */
protected int texInternalFormat;
/** The min filter. */
protected int minFilter;
/** The mag filter. */
protected int magFilter;
/** The using mipmaps. */
protected boolean usingMipmaps;
/** The max tex coord s. */
protected float maxTexCoordS;
/** The max tex coord t. */
protected float maxTexCoordT;
/** The flipped x. */
protected boolean flippedX;
/** The flipped y. */
protected boolean flippedY;
protected int wrap_s = GL.GL_CLAMP;
protected int wrap_t = GL.GL_CLAMP;
/**
* Gets the texture params.
*
* @return the texture params
*/
public GLTextureParameters getTextureParams() {
return textureParams;
}
// /**
// * @invisible
// */
// protected GLState glstate;
}