159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/*
259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Copyright (c) 2009-2010 jMonkeyEngine
359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * All rights reserved.
459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Redistribution and use in source and binary forms, with or without
659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * modification, are permitted provided that the following conditions are
759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * met:
859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions of source code must retain the above copyright
1059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   notice, this list of conditions and the following disclaimer.
1159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
1259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions in binary form must reproduce the above copyright
1359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   notice, this list of conditions and the following disclaimer in the
1459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   documentation and/or other materials provided with the distribution.
1559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
1659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
1759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   may be used to endorse or promote products derived from this software
1859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   without specific prior written permission.
1959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
2059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
2459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
2859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
2959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */
3259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapackage com.jme3.scene.plugins.blender.textures;
3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
3459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.FastMath;
3559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.plugins.blender.BlenderContext;
3659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
3759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.plugins.blender.file.DynamicArray;
3859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.plugins.blender.file.Pointer;
3959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.plugins.blender.file.Structure;
4059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.texture.Texture;
4159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.Map;
4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.TreeMap;
4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.logging.Level;
4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.logging.Logger;
4559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/**
4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This class is a base class for texture generators.
4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @author Marcin Roguski (Kaelthas)
4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */
5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/* package */abstract class TextureGenerator {
5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	private static final Logger	LOGGER	= Logger.getLogger(TextureGenerator.class.getName());
5259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	protected NoiseGenerator	noiseGenerator;
5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	public TextureGenerator(NoiseGenerator noiseGenerator) {
5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		this.noiseGenerator = noiseGenerator;
5759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	}
5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
5959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	/**
6059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 * This method generates the texture.
6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 * @param tex
6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 *        texture's structure
6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 * @param width
6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 *        the width of the result texture
6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 * @param height
6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 *        the height of the result texture
6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 * @param depth
6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 *        the depth of the texture
6959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 * @param blenderContext
7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 *        the blender context
7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 * @return newly generated texture
7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 */
7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	protected abstract Texture generate(Structure tex, int width, int height, int depth, BlenderContext blenderContext);
7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	/**
7659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 * This method reads the colorband data from the given texture structure.
7759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 *
7859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 * @param tex
7959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 *        the texture structure
8059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 * @param blenderContext
8159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 *        the blender context
8259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 * @return read colorband or null if not present
8359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 */
8459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	private ColorBand readColorband(Structure tex, BlenderContext blenderContext) {
8559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		ColorBand result = null;
8659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		int flag = ((Number) tex.getFieldValue("flag")).intValue();
8759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		if ((flag & NoiseGenerator.TEX_COLORBAND) != 0) {
8859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			Pointer pColorband = (Pointer) tex.getFieldValue("coba");
8959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			Structure colorbandStructure;
9059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			try {
9159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				colorbandStructure = pColorband.fetchData(blenderContext.getInputStream()).get(0);
9259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				result = new ColorBand(colorbandStructure);
9359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			} catch (BlenderFileException e) {
9459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				LOGGER.log(Level.WARNING, "Cannot fetch the colorband structure. The reason: {0}", e.getLocalizedMessage());
9559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			}
9659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		}
9759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		return result;
9859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	}
9959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
10059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	protected float[][] computeColorband(Structure tex, BlenderContext blenderContext) {
10159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		ColorBand colorBand = this.readColorband(tex, blenderContext);
10259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		float[][] result = null;
10359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		if(colorBand!=null) {
10459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			result = new float[1001][4];//1001 - amount of possible cursor positions; 4 = [r, g, b, a]
10559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			ColorBandData[] dataArray = colorBand.data;
10659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
10759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			if(dataArray.length==1) {//special case; use only one color for all types of colorband interpolation
10859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				for(int i=0;i<result.length;++i) {
10959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta					result[i][0] = dataArray[0].r;
11059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta					result[i][1] = dataArray[0].g;
11159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta					result[i][2] = dataArray[0].b;
11259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta					result[i][3] = dataArray[0].a;
11359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				}
11459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			} else {
11559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				int currentCursor = 0;
11659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				ColorBandData currentData = dataArray[0];
11759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				ColorBandData nextData = dataArray[0];
11859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				switch(colorBand.ipoType) {
11959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta					case ColorBand.IPO_LINEAR:
12059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta						float rDiff = 0, gDiff = 0, bDiff = 0, aDiff = 0, posDiff;
12159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta						for(int i=0;i<result.length;++i) {
12259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							posDiff = i - currentData.pos;
12359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							result[i][0] = currentData.r + rDiff * posDiff;
12459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							result[i][1] = currentData.g + gDiff * posDiff;
12559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							result[i][2] = currentData.b + bDiff * posDiff;
12659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							result[i][3] = currentData.a + aDiff * posDiff;
12759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							if(nextData.pos==i) {
12859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta								currentData = dataArray[currentCursor++];
12959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta								if(currentCursor < dataArray.length) {
13059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta									nextData = dataArray[currentCursor];
13159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta									//calculate differences
13259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta									int d = nextData.pos - currentData.pos;
13359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta									rDiff = (nextData.r - currentData.r)/d;
13459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta									gDiff = (nextData.g - currentData.g)/d;
13559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta									bDiff = (nextData.b - currentData.b)/d;
13659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta									aDiff = (nextData.a - currentData.a)/d;
13759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta								} else {
13859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta									rDiff = gDiff = bDiff = aDiff = 0;
13959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta								}
14059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							}
14159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta						}
14259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta						break;
14359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta					case ColorBand.IPO_BSPLINE:
14459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta					case ColorBand.IPO_CARDINAL:
14559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta						Map<Integer, ColorBandData> cbDataMap = new TreeMap<Integer, ColorBandData>();
14659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta						for(int i=0;i<colorBand.data.length;++i) {
14759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							cbDataMap.put(Integer.valueOf(i), colorBand.data[i]);
14859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta						}
14959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
15059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta						if(colorBand.data[0].pos==0) {
15159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							cbDataMap.put(Integer.valueOf(-1), colorBand.data[0]);
15259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta						} else {
15359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							ColorBandData cbData = colorBand.data[0].clone();
15459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							cbData.pos = 0;
15559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							cbDataMap.put(Integer.valueOf(-1), cbData);
15659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							cbDataMap.put(Integer.valueOf(-2), cbData);
15759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta						}
15859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
15959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta						if(colorBand.data[colorBand.data.length - 1].pos==1000) {
16059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							cbDataMap.put(Integer.valueOf(colorBand.data.length), colorBand.data[colorBand.data.length - 1]);
16159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta						} else {
16259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							ColorBandData cbData = colorBand.data[colorBand.data.length - 1].clone();
16359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							cbData.pos = 1000;
16459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							cbDataMap.put(Integer.valueOf(colorBand.data.length), cbData);
16559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							cbDataMap.put(Integer.valueOf(colorBand.data.length + 1), cbData);
16659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta						}
16759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
16859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta						float[] ipoFactors = new float[4];
16959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta						float f;
17059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
17159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta						ColorBandData data0 = cbDataMap.get(currentCursor - 2);
17259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta						ColorBandData data1 = cbDataMap.get(currentCursor - 1);
17359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta						ColorBandData data2 = cbDataMap.get(currentCursor);
17459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta						ColorBandData data3 = cbDataMap.get(currentCursor + 1);
17559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
17659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta						for(int i=0;i<result.length;++i) {
17759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							if (data2.pos != data1.pos) {
17859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		                        f = (i - data2.pos) / (float)(data1.pos - data2.pos);
17959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		                    } else {
18059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		                        f = 0.0f;
18159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		                    }
18259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
18359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							f = FastMath.clamp(f, 0.0f, 1.0f);
18459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
18559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							this.getIpoData(colorBand, f, ipoFactors);
18659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							result[i][0] = ipoFactors[3] * data0.r + ipoFactors[2] * data1.r + ipoFactors[1] * data2.r + ipoFactors[0] * data3.r;
18759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							result[i][1] = ipoFactors[3] * data0.g + ipoFactors[2] * data1.g + ipoFactors[1] * data2.g + ipoFactors[0] * data3.g;
18859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							result[i][2] = ipoFactors[3] * data0.b + ipoFactors[2] * data1.b + ipoFactors[1] * data2.b + ipoFactors[0] * data3.b;
18959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							result[i][3] = ipoFactors[3] * data0.a + ipoFactors[2] * data1.a + ipoFactors[1] * data2.a + ipoFactors[0] * data3.a;
19059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							result[i][0] = FastMath.clamp(result[i][0], 0.0f, 1.0f);
19159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							result[i][1] = FastMath.clamp(result[i][1], 0.0f, 1.0f);
19259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							result[i][2] = FastMath.clamp(result[i][2], 0.0f, 1.0f);
19359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							result[i][3] = FastMath.clamp(result[i][3], 0.0f, 1.0f);
19459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
19559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							if(nextData.pos==i) {
19659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta								++currentCursor;
19759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta								data0 = cbDataMap.get(currentCursor - 2);
19859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta								data1 = cbDataMap.get(currentCursor - 1);
19959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta								data2 = cbDataMap.get(currentCursor);
20059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta								data3 = cbDataMap.get(currentCursor + 1);
20159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							}
20259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta						}
20359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta						break;
20459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta					case ColorBand.IPO_EASE:
20559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta						float d, a, b, d2;
20659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta						for(int i=0;i<result.length;++i) {
20759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							if(nextData.pos != currentData.pos) {
20859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta								d = (i - currentData.pos) / (float)(nextData.pos - currentData.pos);
20959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta								d2 = d * d;
21059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta								a = 3.0f * d2 - 2.0f * d * d2;
21159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta								b = 1.0f - a;
21259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							} else {
21359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta								d = a = 0.0f;
21459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta								b = 1.0f;
21559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							}
21659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
21759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							result[i][0] = b * currentData.r + a * nextData.r;
21859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							result[i][1] = b * currentData.g + a * nextData.g;
21959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							result[i][2] = b * currentData.b + a * nextData.b;
22059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							result[i][3] = b * currentData.a + a * nextData.a;
22159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							if(nextData.pos==i) {
22259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta								currentData = dataArray[currentCursor++];
22359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta								if(currentCursor < dataArray.length) {
22459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta									nextData = dataArray[currentCursor];
22559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta								}
22659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							}
22759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta						}
22859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta						break;
22959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta					case ColorBand.IPO_CONSTANT:
23059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta						for(int i=0;i<result.length;++i) {
23159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							result[i][0] = currentData.r;
23259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							result[i][1] = currentData.g;
23359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							result[i][2] = currentData.b;
23459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							result[i][3] = currentData.a;
23559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							if(nextData.pos==i) {
23659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta								currentData = dataArray[currentCursor++];
23759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta								if(currentCursor < dataArray.length) {
23859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta									nextData = dataArray[currentCursor];
23959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta								}
24059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta							}
24159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta						}
24259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta						break;
24359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta					default:
24459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta						throw new IllegalStateException("Unknown interpolation type: " + colorBand.ipoType);
24559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				}
24659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			}
24759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		}
24859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		return result;
24959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	}
25059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
25159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	/**
25259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 * This method returns the data for either B-spline of Cardinal interpolation.
25359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 * @param colorBand the color band
25459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 * @param d distance factor for the current intensity
25559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 * @param ipoFactors table to store the results (size of the table must be at least 4)
25659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 */
25759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	private void getIpoData(ColorBand colorBand, float d, float[] ipoFactors) {
25859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		float d2 = d * d;
25959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		float d3 = d2 * d;
26059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		if(colorBand.ipoType==ColorBand.IPO_BSPLINE) {
26159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			ipoFactors[0] = -0.71f * d3 + 1.42f * d2 - 0.71f * d;
26259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			ipoFactors[1] = 1.29f * d3 - 2.29f * d2 + 1.0f;
26359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			ipoFactors[2] = -1.29f * d3 + 1.58f * d2 + 0.71f * d;
26459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			ipoFactors[3] = 0.71f * d3 - 0.71f * d2;
26559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		} else if(colorBand.ipoType==ColorBand.IPO_CARDINAL) {
26659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			ipoFactors[0] = -0.16666666f * d3 + 0.5f * d2 - 0.5f * d + 0.16666666f;
26759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			ipoFactors[1] = 0.5f * d3 - d2 + 0.6666666f;
26859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			ipoFactors[2] = -0.5f * d3 + 0.5f * d2 + 0.5f * d + 0.16666666f;
26959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			ipoFactors[3] = 0.16666666f * d3;
27059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		} else {
27159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			throw new IllegalStateException("Cannot get interpolation data for other colorband types than B-spline and Cardinal!");
27259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		}
27359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	}
27459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
27559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	/**
27659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 * This method applies brightness and contrast for RGB textures.
27759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 * @param tex texture structure
27859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 * @param texres
27959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 */
28059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	protected void applyBrightnessAndContrast(BrightnessAndContrastData bacd, TexturePixel texres) {
28159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        texres.red = (texres.red - 0.5f) * bacd.contrast + bacd.brightness;
28259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (texres.red < 0.0f) {
28359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            texres.red = 0.0f;
28459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
28559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        texres.green =(texres.green - 0.5f) * bacd.contrast + bacd.brightness;
28659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (texres.green < 0.0f) {
28759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            texres.green = 0.0f;
28859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
28959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        texres.blue = (texres.blue - 0.5f) * bacd.contrast + bacd.brightness;
29059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (texres.blue < 0.0f) {
29159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            texres.blue = 0.0f;
29259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
29359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
29459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
29559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	/**
29659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 * This method applies brightness and contrast for Luminance textures.
29759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 * @param texres
29859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 * @param contrast
29959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 * @param brightness
30059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 */
30159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	protected void applyBrightnessAndContrast(TexturePixel texres, float contrast, float brightness) {
30259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        texres.intensity = (texres.intensity - 0.5f) * contrast + brightness;
30359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (texres.intensity < 0.0f) {
30459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            texres.intensity = 0.0f;
30559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } else if (texres.intensity > 1.0f) {
30659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            texres.intensity = 1.0f;
30759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
30859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
30959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
31059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	/**
31159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 * A class constaining the colorband data.
31259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 *
31359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 * @author Marcin Roguski (Kaelthas)
31459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 */
31559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	protected static class ColorBand {
31659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		//interpolation types
31759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		public static final int IPO_LINEAR 		= 0;
31859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		public static final int IPO_EASE 		= 1;
31959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		public static final int IPO_BSPLINE 	= 2;
32059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		public static final int IPO_CARDINAL 	= 3;
32159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		public static final int IPO_CONSTANT 	= 4;
32259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
32359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		public int		cursorsAmount, ipoType;
32459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		public ColorBandData[]	data;
32559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
32659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		/**
32759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		 * Constructor. Loads the data from the given structure.
32859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		 *
32959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		 * @param cbdataStructure
33059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		 *        the colorband structure
33159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		 */
33259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		@SuppressWarnings("unchecked")
33359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		public ColorBand(Structure colorbandStructure) {
33459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			this.cursorsAmount = ((Number) colorbandStructure.getFieldValue("tot")).intValue();
33559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			this.ipoType = ((Number) colorbandStructure.getFieldValue("ipotype")).intValue();
33659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			this.data = new ColorBandData[this.cursorsAmount];
33759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			DynamicArray<Structure> data = (DynamicArray<Structure>) colorbandStructure.getFieldValue("data");
33859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			for (int i = 0; i < this.cursorsAmount; ++i) {
33959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				this.data[i] = new ColorBandData(data.get(i));
34059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			}
34159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		}
34259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	}
34359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
34459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	/**
34559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 * Class to store the single colorband cursor data.
34659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 *
34759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 * @author Marcin Roguski (Kaelthas)
34859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 */
34959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	protected static class ColorBandData implements Cloneable {
35059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		public final float	r, g, b, a;
35159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		public int 	pos;
35259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
35359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		/**
35459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		 * Copy constructor.
35559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		 */
35659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		private ColorBandData(ColorBandData data) {
35759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			this.r = data.r;
35859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			this.g = data.g;
35959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			this.b = data.b;
36059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			this.a = data.a;
36159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			this.pos = data.pos;
36259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		}
36359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
36459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		/**
36559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		 * Constructor. Loads the data from the given structure.
36659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		 *
36759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		 * @param cbdataStructure
36859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		 *        the structure containing the CBData object
36959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		 */
37059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		public ColorBandData(Structure cbdataStructure) {
37159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			this.r = ((Number) cbdataStructure.getFieldValue("r")).floatValue();
37259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			this.g = ((Number) cbdataStructure.getFieldValue("g")).floatValue();
37359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			this.b = ((Number) cbdataStructure.getFieldValue("b")).floatValue();
37459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			this.a = ((Number) cbdataStructure.getFieldValue("a")).floatValue();
37559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			this.pos = (int) (((Number) cbdataStructure.getFieldValue("pos")).floatValue() * 1000.0f);
37659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		}
37759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
37859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		@Override
37959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		public ColorBandData clone() {
38059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			try {
38159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				return (ColorBandData) super.clone();
38259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			} catch (CloneNotSupportedException e) {
38359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta				return new ColorBandData(this);
38459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			}
38559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		}
38659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
38759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		@Override
38859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		public String toString() {
38959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			return "P: " + this.pos + " [" + this.r+", "+this.g+", "+this.b+", "+this.a+"]";
39059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		}
39159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	}
39259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
39359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	/**
39459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 * This class contains brightness and contrast data.
39559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 * @author Marcin Roguski (Kaelthas)
39659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	 */
39759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	protected static class BrightnessAndContrastData {
39859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		public final float contrast;
39959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        public final float brightness;
40059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        public final float rFactor;
40159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        public final float gFactor;
40259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        public final float bFactor;
40359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
40459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        /**
40559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta         * Constructor reads the required data from the given structure.
40659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta         * @param tex texture structure
40759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta         */
40859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		public BrightnessAndContrastData(Structure tex) {
40959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta			contrast = ((Number) tex.getFieldValue("contrast")).floatValue();
41059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	        brightness = ((Number) tex.getFieldValue("bright")).floatValue() - 0.5f;
41159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	        rFactor = ((Number) tex.getFieldValue("rfac")).floatValue();
41259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	        gFactor = ((Number) tex.getFieldValue("gfac")).floatValue();
41359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	        bFactor = ((Number) tex.getFieldValue("bfac")).floatValue();
41459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta		}
41559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta	}
41659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta}
417