/*
* Copyright (c) 2003-onwards Shaven Puppy Ltd
* 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 'Shaven Puppy' 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 THE COPYRIGHT OWNER OR
* CONTRIBUTORS 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.shavenpuppy.jglib.opengl;
import org.lwjgl.util.vector.Vector3f;
import com.shavenpuppy.jglib.Image;
import com.shavenpuppy.jglib.resources.ImageResource;
import static org.lwjgl.opengl.GL11.*;
/**
* Normal bump map texture
* @author cas
*/
public class GLBumpMap extends GLTexture {
private static final long serialVersionUID = 1L;
/*
* Resource data
*/
/** The bump map scale factor. The bigger this is, the smaller the bumps are. */
protected float scale;
/*
* Transient data
*/
/**
* Resource constructor
* @param name
*/
public GLBumpMap(String name) {
super(name);
}
/**
* @param name
* @param url
* @param scale
*/
public GLBumpMap(String name, String url, float scale) {
super(name, url, GL_TEXTURE_2D, GL_RGB, GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, true);
this.scale = scale;
}
/**
* @param name
* @param imageResource
* @param scale
*/
public GLBumpMap(String name, ImageResource imageResource, float scale) {
super(name, imageResource, GL_TEXTURE_2D, GL_RGB, GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, true);
this.scale = scale;
}
/**
* @param name
* @param image
* @param scale
*/
public GLBumpMap(String name, Image image, float scale) {
super(name, image, GL_TEXTURE_2D, GL_RGB, GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, true);
this.scale = scale;
}
/**
* Preprocesses the image. The image must be of LUMINANCE type or an assertion
* error is thrown.
* @see com.shavenpuppy.jglib.opengl.GLTexture#preprocess()
*/
@Override
protected Image preprocess() {
int index = 0, srcindex = 0;
final Vector3f[] vec = new Vector3f[image.getWidth() * image.getHeight()];
final Vector3f[] dst = new Vector3f[image.getWidth() * image.getHeight()];
final byte[] nrm = new byte[image.getWidth() * image.getHeight() * 3];
// Create vector3f array first:
for (int j = 0; j < image.getHeight(); ++j) {
for (int i = 0; i < image.getWidth(); ++i) {
vec[index++] = new Vector3f(i, j, (image.getData().get(srcindex++) & 0xff));
}
}
Vector3f a = new Vector3f();
Vector3f b = new Vector3f();
Vector3f c = new Vector3f();
// Now work out normals
for (int j = 0; j < image.getHeight(); j++) {
for (int i = 0; i < image.getWidth(); i++) {
a.x = 2;
a.y = 0;
a.z = vec[index(i + 1, j)].z - vec[index(i - 1, j)].z;
// a = vec(i+1, j) - p(i-1, j);
b.x = 0;
b.y = 2;
b.z = vec[index(i, j + 1)].z - vec[index(i, j - 1)].z;
// b = vec( i, j+1) - p( i, j-1);
Vector3f.cross(a, b, c);
c.z *= scale;
c.normalise();
dst[i + j * image.getWidth()] = new Vector3f(c);
}
}
// Now transform into rgb:
index = 0;
srcindex = 0;
for (int j = 0; j < image.getHeight(); j++) {
for (int i = 0; i < image.getWidth(); i++) {
nrm[index++] = (byte) ((dst[srcindex].x + 1f) * 127.5f);
nrm[index++] = (byte) ((dst[srcindex].y + 1f) * 127.5f);
nrm[index++] = (byte) ((dst[srcindex++].z + 1f) * 127.5f);
}
}
// Create an SpriteImage out of our bump data
return new Image(image.getWidth(), image.getHeight(), Image.RGB, nrm);
}
/**
* Insert the method's description here.
* Creation date: (20/11/2001 15:13:11)
*/
private int index(int x, int y) {
if (x < 0) {
x += image.getWidth();
} else if (x >= image.getWidth()) {
x -= image.getWidth();
}
if (y < 0) {
y += image.getHeight();
} else if (y >= image.getHeight()) {
y -= image.getHeight();
}
return x + (y * image.getWidth());
}
}