aboutsummaryrefslogtreecommitdiff
path: root/engine/src/blender/com/jme3/scene/plugins/blender/textures/blending
diff options
context:
space:
mode:
authorScott Barta <sbarta@google.com>2012-03-01 12:35:35 -0800
committerScott Barta <sbarta@google.com>2012-03-01 12:40:08 -0800
commit59b2e6871c65f58fdad78cd7229c292f6a177578 (patch)
tree2d4e7bfc05b93f40b34675d77e403dd1c25efafd /engine/src/blender/com/jme3/scene/plugins/blender/textures/blending
parentf9b30489e75ac1eabc365064959804e99534f7ab (diff)
downloadjmonkeyengine-59b2e6871c65f58fdad78cd7229c292f6a177578.tar.gz
Adds the jMonkeyEngine library to the build.
Adds the jMonkeyEngine open source 3D game engine to the build. This is built as a static library and is only used by the Finsky client. Change-Id: I06a3f054df7b8a67757267d884854f70c5a16ca0
Diffstat (limited to 'engine/src/blender/com/jme3/scene/plugins/blender/textures/blending')
-rw-r--r--engine/src/blender/com/jme3/scene/plugins/blender/textures/blending/AbstractTextureBlender.java195
-rw-r--r--engine/src/blender/com/jme3/scene/plugins/blender/textures/blending/TextureBlender.java51
-rw-r--r--engine/src/blender/com/jme3/scene/plugins/blender/textures/blending/TextureBlenderAWT.java162
-rw-r--r--engine/src/blender/com/jme3/scene/plugins/blender/textures/blending/TextureBlenderDDS.java96
-rw-r--r--engine/src/blender/com/jme3/scene/plugins/blender/textures/blending/TextureBlenderFactory.java81
-rw-r--r--engine/src/blender/com/jme3/scene/plugins/blender/textures/blending/TextureBlenderLuminance.java221
6 files changed, 806 insertions, 0 deletions
diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/textures/blending/AbstractTextureBlender.java b/engine/src/blender/com/jme3/scene/plugins/blender/textures/blending/AbstractTextureBlender.java
new file mode 100644
index 0000000..505c94b
--- /dev/null
+++ b/engine/src/blender/com/jme3/scene/plugins/blender/textures/blending/AbstractTextureBlender.java
@@ -0,0 +1,195 @@
+package com.jme3.scene.plugins.blender.textures.blending;
+
+import com.jme3.math.FastMath;
+import com.jme3.scene.plugins.blender.BlenderContext;
+import com.jme3.scene.plugins.blender.materials.MaterialHelper;
+
+/**
+ * An abstract class that contains the basic methods used by the classes that
+ * will derive from it.
+ *
+ * @author Marcin Roguski (Kaelthas)
+ */
+/* package */abstract class AbstractTextureBlender implements TextureBlender {
+ /**
+ * This method blends the single pixel depending on the blending type.
+ *
+ * @param result
+ * the result pixel
+ * @param materialColor
+ * the material color
+ * @param pixelColor
+ * the pixel color
+ * @param blendFactor
+ * the blending factor
+ * @param blendtype
+ * the blending type
+ * @param blenderContext
+ * the blender context
+ */
+ protected void blendPixel(float[] result, float[] materialColor, float[] pixelColor, float blendFactor, int blendtype, BlenderContext blenderContext) {
+ float oneMinusFactor = 1.0f - blendFactor, col;
+
+ switch (blendtype) {
+ case MTEX_BLEND:
+ result[0] = blendFactor * pixelColor[0] + oneMinusFactor * materialColor[0];
+ result[1] = blendFactor * pixelColor[1] + oneMinusFactor * materialColor[1];
+ result[2] = blendFactor * pixelColor[2] + oneMinusFactor * materialColor[2];
+ break;
+ case MTEX_MUL:
+ result[0] = (oneMinusFactor + blendFactor * materialColor[0]) * pixelColor[0];
+ result[1] = (oneMinusFactor + blendFactor * materialColor[1]) * pixelColor[1];
+ result[2] = (oneMinusFactor + blendFactor * materialColor[2]) * pixelColor[2];
+ break;
+ case MTEX_DIV:
+ if (pixelColor[0] != 0.0) {
+ result[0] = (oneMinusFactor * materialColor[0] + blendFactor * materialColor[0] / pixelColor[0]) * 0.5f;
+ }
+ if (pixelColor[1] != 0.0) {
+ result[1] = (oneMinusFactor * materialColor[1] + blendFactor * materialColor[1] / pixelColor[1]) * 0.5f;
+ }
+ if (pixelColor[2] != 0.0) {
+ result[2] = (oneMinusFactor * materialColor[2] + blendFactor * materialColor[2] / pixelColor[2]) * 0.5f;
+ }
+ break;
+ case MTEX_SCREEN:
+ result[0] = 1.0f - (oneMinusFactor + blendFactor * (1.0f - materialColor[0])) * (1.0f - pixelColor[0]);
+ result[1] = 1.0f - (oneMinusFactor + blendFactor * (1.0f - materialColor[1])) * (1.0f - pixelColor[1]);
+ result[2] = 1.0f - (oneMinusFactor + blendFactor * (1.0f - materialColor[2])) * (1.0f - pixelColor[2]);
+ break;
+ case MTEX_OVERLAY:
+ if (materialColor[0] < 0.5f) {
+ result[0] = pixelColor[0] * (oneMinusFactor + 2.0f * blendFactor * materialColor[0]);
+ } else {
+ result[0] = 1.0f - (oneMinusFactor + 2.0f * blendFactor * (1.0f - materialColor[0])) * (1.0f - pixelColor[0]);
+ }
+ if (materialColor[1] < 0.5f) {
+ result[1] = pixelColor[1] * (oneMinusFactor + 2.0f * blendFactor * materialColor[1]);
+ } else {
+ result[1] = 1.0f - (oneMinusFactor + 2.0f * blendFactor * (1.0f - materialColor[1])) * (1.0f - pixelColor[1]);
+ }
+ if (materialColor[2] < 0.5f) {
+ result[2] = pixelColor[2] * (oneMinusFactor + 2.0f * blendFactor * materialColor[2]);
+ } else {
+ result[2] = 1.0f - (oneMinusFactor + 2.0f * blendFactor * (1.0f - materialColor[2])) * (1.0f - pixelColor[2]);
+ }
+ break;
+ case MTEX_SUB:
+ result[0] = materialColor[0] - blendFactor * pixelColor[0];
+ result[1] = materialColor[1] - blendFactor * pixelColor[1];
+ result[2] = materialColor[2] - blendFactor * pixelColor[2];
+ result[0] = FastMath.clamp(result[0], 0.0f, 1.0f);
+ result[1] = FastMath.clamp(result[1], 0.0f, 1.0f);
+ result[2] = FastMath.clamp(result[2], 0.0f, 1.0f);
+ break;
+ case MTEX_ADD:
+ result[0] = (blendFactor * pixelColor[0] + materialColor[0]) * 0.5f;
+ result[1] = (blendFactor * pixelColor[1] + materialColor[1]) * 0.5f;
+ result[2] = (blendFactor * pixelColor[2] + materialColor[2]) * 0.5f;
+ break;
+ case MTEX_DIFF:
+ result[0] = oneMinusFactor * materialColor[0] + blendFactor * Math.abs(materialColor[0] - pixelColor[0]);
+ result[1] = oneMinusFactor * materialColor[1] + blendFactor * Math.abs(materialColor[1] - pixelColor[1]);
+ result[2] = oneMinusFactor * materialColor[2] + blendFactor * Math.abs(materialColor[2] - pixelColor[2]);
+ break;
+ case MTEX_DARK:
+ col = blendFactor * pixelColor[0];
+ result[0] = col < materialColor[0] ? col : materialColor[0];
+ col = blendFactor * pixelColor[1];
+ result[1] = col < materialColor[1] ? col : materialColor[1];
+ col = blendFactor * pixelColor[2];
+ result[2] = col < materialColor[2] ? col : materialColor[2];
+ break;
+ case MTEX_LIGHT:
+ col = blendFactor * pixelColor[0];
+ result[0] = col > materialColor[0] ? col : materialColor[0];
+ col = blendFactor * pixelColor[1];
+ result[1] = col > materialColor[1] ? col : materialColor[1];
+ col = blendFactor * pixelColor[2];
+ result[2] = col > materialColor[2] ? col : materialColor[2];
+ break;
+ case MTEX_BLEND_HUE:
+ case MTEX_BLEND_SAT:
+ case MTEX_BLEND_VAL:
+ case MTEX_BLEND_COLOR:
+ System.arraycopy(materialColor, 0, result, 0, 3);
+ this.blendHSV(blendtype, result, blendFactor, pixelColor, blenderContext);
+ break;
+ default:
+ throw new IllegalStateException("Unknown blend type: " + blendtype);
+ }
+ }
+
+ /**
+ * The method that performs the ramp blending.
+ *
+ * @param type
+ * the blend type
+ * @param materialRGB
+ * the rgb value of the material, here the result is stored too
+ * @param fac
+ * color affection factor
+ * @param pixelColor
+ * the texture color
+ * @param blenderContext
+ * the blender context
+ */
+ protected void blendHSV(int type, float[] materialRGB, float fac, float[] pixelColor, BlenderContext blenderContext) {
+ float oneMinusFactor = 1.0f - fac;
+ MaterialHelper materialHelper = blenderContext.getHelper(MaterialHelper.class);
+
+ switch (type) {
+ case MTEX_BLEND_HUE: {// FIXME: not working well for image textures
+ // (works fine for generated textures)
+ float[] colorTransformResult = new float[3];
+ materialHelper.rgbToHsv(pixelColor[0], pixelColor[1], pixelColor[2], colorTransformResult);
+ if (colorTransformResult[0] != 0.0f) {
+ float colH = colorTransformResult[0];
+ materialHelper.rgbToHsv(materialRGB[0], materialRGB[1], materialRGB[2], colorTransformResult);
+ materialHelper.hsvToRgb(colH, colorTransformResult[1], colorTransformResult[2], colorTransformResult);
+ materialRGB[0] = oneMinusFactor * materialRGB[0] + fac * colorTransformResult[0];
+ materialRGB[1] = oneMinusFactor * materialRGB[1] + fac * colorTransformResult[1];
+ materialRGB[2] = oneMinusFactor * materialRGB[2] + fac * colorTransformResult[2];
+ }
+ break;
+ }
+ case MTEX_BLEND_SAT: {
+ float[] colorTransformResult = new float[3];
+ materialHelper.rgbToHsv(materialRGB[0], materialRGB[1], materialRGB[2], colorTransformResult);
+ float h = colorTransformResult[0];
+ float s = colorTransformResult[1];
+ float v = colorTransformResult[2];
+ if (s != 0.0f) {
+ materialHelper.rgbToHsv(pixelColor[0], pixelColor[1], pixelColor[2], colorTransformResult);
+ materialHelper.hsvToRgb(h, (oneMinusFactor * s + fac * colorTransformResult[1]), v, materialRGB);
+ }
+ break;
+ }
+ case MTEX_BLEND_VAL: {
+ float[] rgbToHsv = new float[3];
+ float[] colToHsv = new float[3];
+ materialHelper.rgbToHsv(materialRGB[0], materialRGB[1], materialRGB[2], rgbToHsv);
+ materialHelper.rgbToHsv(pixelColor[0], pixelColor[1], pixelColor[2], colToHsv);
+ materialHelper.hsvToRgb(rgbToHsv[0], rgbToHsv[1], (oneMinusFactor * rgbToHsv[2] + fac * colToHsv[2]), materialRGB);
+ break;
+ }
+ case MTEX_BLEND_COLOR: {// FIXME: not working well for image
+ // textures (works fine for generated
+ // textures)
+ float[] rgbToHsv = new float[3];
+ float[] colToHsv = new float[3];
+ materialHelper.rgbToHsv(pixelColor[0], pixelColor[1], pixelColor[2], colToHsv);
+ if (colToHsv[2] != 0) {
+ materialHelper.rgbToHsv(materialRGB[0], materialRGB[1], materialRGB[2], rgbToHsv);
+ materialHelper.hsvToRgb(colToHsv[0], colToHsv[1], rgbToHsv[2], rgbToHsv);
+ materialRGB[0] = oneMinusFactor * materialRGB[0] + fac * rgbToHsv[0];
+ materialRGB[1] = oneMinusFactor * materialRGB[1] + fac * rgbToHsv[1];
+ materialRGB[2] = oneMinusFactor * materialRGB[2] + fac * rgbToHsv[2];
+ }
+ break;
+ }
+ default:
+ throw new IllegalStateException("Unknown ramp type: " + type);
+ }
+ }
+}
diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/textures/blending/TextureBlender.java b/engine/src/blender/com/jme3/scene/plugins/blender/textures/blending/TextureBlender.java
new file mode 100644
index 0000000..08e25d3
--- /dev/null
+++ b/engine/src/blender/com/jme3/scene/plugins/blender/textures/blending/TextureBlender.java
@@ -0,0 +1,51 @@
+package com.jme3.scene.plugins.blender.textures.blending;
+
+import com.jme3.scene.plugins.blender.BlenderContext;
+import com.jme3.texture.Texture;
+
+/**
+ * An interface for texture blending classes (the classes that mix the texture
+ * pixels with the material colors).
+ *
+ * @author Marcin Roguski (Kaelthas)
+ */
+public interface TextureBlender {
+ // types of blending
+ int MTEX_BLEND = 0;
+ int MTEX_MUL = 1;
+ int MTEX_ADD = 2;
+ int MTEX_SUB = 3;
+ int MTEX_DIV = 4;
+ int MTEX_DARK = 5;
+ int MTEX_DIFF = 6;
+ int MTEX_LIGHT = 7;
+ int MTEX_SCREEN = 8;
+ int MTEX_OVERLAY = 9;
+ int MTEX_BLEND_HUE = 10;
+ int MTEX_BLEND_SAT = 11;
+ int MTEX_BLEND_VAL = 12;
+ int MTEX_BLEND_COLOR = 13;
+ int MTEX_NUM_BLENDTYPES = 14;
+
+ /**
+ * This method blends the given texture with material color and the defined
+ * color in 'map to' panel. As a result of this method a new texture is
+ * created. The input texture is NOT.
+ *
+ * @param materialColor
+ * the material diffuse color
+ * @param texture
+ * the texture we use in blending
+ * @param color
+ * the color defined for the texture
+ * @param affectFactor
+ * the factor that the color affects the texture (value form 0.0
+ * to 1.0)
+ * @param blendType
+ * the blending type
+ * @param blenderContext
+ * the blender context
+ * @return new texture that was created after the blending
+ */
+ Texture blend(float[] materialColor, Texture texture, float[] color, float affectFactor, int blendType, boolean neg, BlenderContext blenderContext);
+}
diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/textures/blending/TextureBlenderAWT.java b/engine/src/blender/com/jme3/scene/plugins/blender/textures/blending/TextureBlenderAWT.java
new file mode 100644
index 0000000..75fc0c5
--- /dev/null
+++ b/engine/src/blender/com/jme3/scene/plugins/blender/textures/blending/TextureBlenderAWT.java
@@ -0,0 +1,162 @@
+package com.jme3.scene.plugins.blender.textures.blending;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.jme3.scene.plugins.blender.BlenderContext;
+import com.jme3.texture.Image;
+import com.jme3.texture.Texture;
+import com.jme3.texture.Texture2D;
+import com.jme3.texture.Texture3D;
+import com.jme3.texture.Image.Format;
+import com.jme3.util.BufferUtils;
+
+/**
+ * The class that is responsible for blending the following texture types:
+ * <li> RGBA8
+ * <li> ABGR8
+ * <li> BGR8
+ * <li> RGB8
+ * Not yet supported (but will be):
+ * <li> ARGB4444:
+ * <li> RGB10:
+ * <li> RGB111110F:
+ * <li> RGB16:
+ * <li> RGB16F:
+ * <li> RGB16F_to_RGB111110F:
+ * <li> RGB16F_to_RGB9E5:
+ * <li> RGB32F:
+ * <li> RGB565:
+ * <li> RGB5A1:
+ * <li> RGB9E5:
+ * <li> RGBA16:
+ * <li> RGBA16F
+ * @author Marcin Roguski (Kaelthas)
+ */
+public class TextureBlenderAWT extends AbstractTextureBlender {
+ private static final Logger LOGGER = Logger.getLogger(TextureBlenderAWT.class.getName());
+
+ @Override
+ public Texture blend(float[] materialColor, Texture texture, float[] color, float affectFactor, int blendType, boolean neg, BlenderContext blenderContext) {
+ float[] pixelColor = new float[] { color[0], color[1], color[2], 1.0f };
+ Format format = texture.getImage().getFormat();
+ ByteBuffer data = texture.getImage().getData(0);
+ data.rewind();
+
+ int width = texture.getImage().getWidth();
+ int height = texture.getImage().getHeight();
+ int depth = texture.getImage().getDepth();
+ if (depth == 0) {
+ depth = 1;
+ }
+ ByteBuffer newData = BufferUtils.createByteBuffer(width * height * depth * 4);
+
+ float[] resultPixel = new float[4];
+ int dataIndex = 0;
+ while (data.hasRemaining()) {
+ float tin = this.setupMaterialColor(data, format, neg, pixelColor);
+ this.blendPixel(resultPixel, materialColor, color, tin, blendType, blenderContext);
+ newData.put(dataIndex++, (byte) (resultPixel[0] * 255.0f));
+ newData.put(dataIndex++, (byte) (resultPixel[1] * 255.0f));
+ newData.put(dataIndex++, (byte) (resultPixel[2] * 255.0f));
+ newData.put(dataIndex++, (byte) (pixelColor[3] * 255.0f));
+ }
+ if (texture.getType() == Texture.Type.TwoDimensional) {
+ return new Texture2D(new Image(Format.RGBA8, width, height, newData));
+ } else {
+ ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(1);
+ dataArray.add(newData);
+ return new Texture3D(new Image(Format.RGBA8, width, height, depth, dataArray));
+ }
+ }
+
+ /**
+ * This method alters the material color in a way dependent on the type of
+ * the image. For example the color remains untouched if the texture is of
+ * Luminance type. The luminance defines the interaction between the
+ * material color and color defined for texture blending. If the type has 3
+ * or more color channels then the material color is replaced with the
+ * texture's color and later blended with the defined blend color. All alpha
+ * values (if present) are ignored and not used during blending.
+ *
+ * @param data
+ * the image data
+ * @param imageFormat
+ * the format of the image
+ * @param neg
+ * defines it the result color should be nagated
+ * @param materialColor
+ * the material's color (value may be changed)
+ * @return texture intensity for the current pixel
+ */
+ protected float setupMaterialColor(ByteBuffer data, Format imageFormat, boolean neg, float[] materialColor) {
+ float tin = 0.0f;
+ byte pixelValue = data.get();// at least one byte is always taken :)
+ float firstPixelValue = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
+ switch (imageFormat) {
+ case RGBA8:
+ materialColor[0] = firstPixelValue;
+ pixelValue = data.get();
+ materialColor[1] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
+ pixelValue = data.get();
+ materialColor[2] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
+ pixelValue = data.get();
+ materialColor[3] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
+ break;
+ case ABGR8:
+ materialColor[3] = firstPixelValue;
+ pixelValue = data.get();
+ materialColor[2] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
+ pixelValue = data.get();
+ materialColor[1] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
+ pixelValue = data.get();
+ materialColor[0] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
+ break;
+ case BGR8:
+ materialColor[2] = firstPixelValue;
+ pixelValue = data.get();
+ materialColor[1] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
+ pixelValue = data.get();
+ materialColor[0] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
+ materialColor[3] = 1.0f;
+ break;
+ case RGB8:
+ materialColor[0] = firstPixelValue;
+ pixelValue = data.get();
+ materialColor[1] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
+ pixelValue = data.get();
+ materialColor[2] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
+ materialColor[3] = 1.0f;
+ break;
+ case ARGB4444:
+ case RGB10:
+ case RGB111110F:
+ case RGB16:
+ case RGB16F:
+ case RGB16F_to_RGB111110F:
+ case RGB16F_to_RGB9E5:
+ case RGB32F:
+ case RGB565:
+ case RGB5A1:
+ case RGB9E5:
+ case RGBA16:
+ case RGBA16F:
+ case RGBA32F:// TODO: implement these textures
+ LOGGER.log(Level.WARNING, "Image type not yet supported for blending: {0}", imageFormat);
+ break;
+ default:
+ throw new IllegalStateException("Invalid image format type for AWT texture blender: " + imageFormat);
+ }
+ if (neg) {
+ materialColor[0] = 1.0f - materialColor[0];
+ materialColor[1] = 1.0f - materialColor[1];
+ materialColor[2] = 1.0f - materialColor[2];
+ }
+ // Blender formula for texture intensity calculation:
+ // 0.35*texres.tr+0.45*texres.tg+0.2*texres.tb
+ tin = 0.35f * materialColor[0] + 0.45f * materialColor[1] + 0.2f * materialColor[2];
+ return tin;
+ }
+}
diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/textures/blending/TextureBlenderDDS.java b/engine/src/blender/com/jme3/scene/plugins/blender/textures/blending/TextureBlenderDDS.java
new file mode 100644
index 0000000..a532cfb
--- /dev/null
+++ b/engine/src/blender/com/jme3/scene/plugins/blender/textures/blending/TextureBlenderDDS.java
@@ -0,0 +1,96 @@
+package com.jme3.scene.plugins.blender.textures.blending;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import jme3tools.converters.RGB565;
+
+import com.jme3.scene.plugins.blender.BlenderContext;
+import com.jme3.scene.plugins.blender.textures.TexturePixel;
+import com.jme3.texture.Image;
+import com.jme3.texture.Image.Format;
+import com.jme3.texture.Texture;
+import com.jme3.texture.Texture2D;
+import com.jme3.texture.Texture3D;
+import com.jme3.util.BufferUtils;
+
+/**
+ * The class that is responsible for blending the following texture types:
+ * <li> DXT1
+ * <li> DXT3
+ * <li> DXT5
+ * Not yet supported (but will be):
+ * <li> DXT1A:
+ * @author Marcin Roguski (Kaelthas)
+ */
+public class TextureBlenderDDS extends AbstractTextureBlender {
+ private static final Logger LOGGER = Logger.getLogger(TextureBlenderDDS.class.getName());
+
+ @Override
+ public Texture blend(float[] materialColor, Texture texture, float[] color, float affectFactor, int blendType, boolean neg, BlenderContext blenderContext) {
+ Format format = texture.getImage().getFormat();
+ ByteBuffer data = texture.getImage().getData(0);
+ data.rewind();
+
+ int width = texture.getImage().getWidth();
+ int height = texture.getImage().getHeight();
+ int depth = texture.getImage().getDepth();
+ if (depth == 0) {
+ depth = 1;
+ }
+ ByteBuffer newData = BufferUtils.createByteBuffer(data.remaining());
+
+ float[] resultPixel = new float[4];
+ float[] pixelColor = new float[4];
+ TexturePixel[] colors = new TexturePixel[] { new TexturePixel(), new TexturePixel() };
+ int dataIndex = 0;
+ while (data.hasRemaining()) {
+ switch (format) {
+ case DXT3:
+ case DXT5:
+ newData.putLong(dataIndex, data.getLong());// just copy the
+ // 8 bytes of
+ // alphas
+ dataIndex += 8;
+ case DXT1:
+ int col0 = RGB565.RGB565_to_ARGB8(data.getShort());
+ int col1 = RGB565.RGB565_to_ARGB8(data.getShort());
+ colors[0].fromARGB8(col0);
+ colors[1].fromARGB8(col1);
+ break;
+ case DXT1A:
+ LOGGER.log(Level.WARNING, "Image type not yet supported for blending: {0}", format);
+ break;
+ default:
+ throw new IllegalStateException("Invalid image format type for DDS texture blender: " + format);
+ }
+
+ // blending colors
+ for (int i = 0; i < colors.length; ++i) {
+ if (neg) {
+ colors[i].negate();
+ }
+ colors[i].toRGBA(pixelColor);
+ this.blendPixel(resultPixel, materialColor, pixelColor, affectFactor, blendType, blenderContext);
+ colors[i].fromARGB8(1, resultPixel[0], resultPixel[1], resultPixel[2]);
+ int argb8 = colors[i].toARGB8();
+ short rgb565 = RGB565.ARGB8_to_RGB565(argb8);
+ newData.putShort(dataIndex, rgb565);
+ dataIndex += 2;
+ }
+
+ // just copy the remaining 4 bytes of the current texel
+ newData.putInt(dataIndex, data.getInt());
+ dataIndex += 4;
+ }
+ if (texture.getType() == Texture.Type.TwoDimensional) {
+ return new Texture2D(new Image(format, width, height, newData));
+ } else {
+ ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(1);
+ dataArray.add(newData);
+ return new Texture3D(new Image(format, width, height, depth, dataArray));
+ }
+ }
+}
diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/textures/blending/TextureBlenderFactory.java b/engine/src/blender/com/jme3/scene/plugins/blender/textures/blending/TextureBlenderFactory.java
new file mode 100644
index 0000000..c9ad61a
--- /dev/null
+++ b/engine/src/blender/com/jme3/scene/plugins/blender/textures/blending/TextureBlenderFactory.java
@@ -0,0 +1,81 @@
+package com.jme3.scene.plugins.blender.textures.blending;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.jme3.scene.plugins.blender.BlenderContext;
+import com.jme3.texture.Texture;
+import com.jme3.texture.Image.Format;
+
+/**
+ * This class creates the texture blending class depending on the texture type.
+ *
+ * @author Marcin Roguski (Kaelthas)
+ */
+public class TextureBlenderFactory {
+ private static final Logger LOGGER = Logger.getLogger(TextureBlenderFactory.class.getName());
+
+ /**
+ * This method creates the blending class.
+ *
+ * @param format
+ * the texture format
+ * @returntexture blending class
+ */
+ public static TextureBlender createTextureBlender(Format format) {
+ switch (format) {
+ case Luminance8:
+ case Luminance8Alpha8:
+ case Luminance16:
+ case Luminance16Alpha16:
+ case Luminance16F:
+ case Luminance16FAlpha16F:
+ case Luminance32F:
+ return new TextureBlenderLuminance();
+ case RGBA8:
+ case ABGR8:
+ case BGR8:
+ case RGB8:
+ case RGB10:
+ case RGB111110F:
+ case RGB16:
+ case RGB16F:
+ case RGB16F_to_RGB111110F:
+ case RGB16F_to_RGB9E5:
+ case RGB32F:
+ case RGB565:
+ case RGB5A1:
+ case RGB9E5:
+ case RGBA16:
+ case RGBA16F:
+ case RGBA32F:
+ return new TextureBlenderAWT();
+ case DXT1:
+ case DXT1A:
+ case DXT3:
+ case DXT5:
+ return new TextureBlenderDDS();
+ case Alpha16:
+ case Alpha8:
+ case ARGB4444:
+ case Depth:
+ case Depth16:
+ case Depth24:
+ case Depth32:
+ case Depth32F:
+ case Intensity16:
+ case Intensity8:
+ case LATC:
+ case LTC:
+ LOGGER.log(Level.WARNING, "Image type not yet supported for blending: {0}. Returning a blender that does not change the texture.", format);
+ return new TextureBlender() {
+ @Override
+ public Texture blend(float[] materialColor, Texture texture, float[] color, float affectFactor, int blendType, boolean neg, BlenderContext blenderContext) {
+ return texture;
+ }
+ };
+ default:
+ throw new IllegalStateException("Unknown image format type: " + format);
+ }
+ }
+}
diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/textures/blending/TextureBlenderLuminance.java b/engine/src/blender/com/jme3/scene/plugins/blender/textures/blending/TextureBlenderLuminance.java
new file mode 100644
index 0000000..a616685
--- /dev/null
+++ b/engine/src/blender/com/jme3/scene/plugins/blender/textures/blending/TextureBlenderLuminance.java
@@ -0,0 +1,221 @@
+package com.jme3.scene.plugins.blender.textures.blending;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.jme3.math.FastMath;
+import com.jme3.scene.plugins.blender.BlenderContext;
+import com.jme3.texture.Image;
+import com.jme3.texture.Texture;
+import com.jme3.texture.Texture2D;
+import com.jme3.texture.Texture3D;
+import com.jme3.texture.Image.Format;
+import com.jme3.util.BufferUtils;
+
+/**
+ * The class that is responsible for blending the following texture types:
+ * <li> Luminance8
+ * <li> Luminance8Alpha8
+ * Not yet supported (but will be):
+ * <li> Luminance16:
+ * <li> Luminance16Alpha16:
+ * <li> Luminance16F:
+ * <li> Luminance16FAlpha16F:
+ * <li> Luminance32F:
+ * @author Marcin Roguski (Kaelthas)
+ */
+public class TextureBlenderLuminance extends AbstractTextureBlender {
+ private static final Logger LOGGER = Logger.getLogger(TextureBlenderLuminance.class.getName());
+
+ @Override
+ public Texture blend(float[] materialColor, Texture texture, float[] color, float affectFactor, int blendType, boolean neg, BlenderContext blenderContext) {
+ Format format = texture.getImage().getFormat();
+ ByteBuffer data = texture.getImage().getData(0);
+ data.rewind();
+
+ int width = texture.getImage().getWidth();
+ int height = texture.getImage().getHeight();
+ int depth = texture.getImage().getDepth();
+ if (depth == 0) {
+ depth = 1;
+ }
+ ByteBuffer newData = BufferUtils.createByteBuffer(width * height * depth * 4);
+
+ float[] resultPixel = new float[4];
+ float[] tinAndAlpha = new float[2];
+ int dataIndex = 0;
+ while (data.hasRemaining()) {
+ this.getTinAndAlpha(data, format, neg, tinAndAlpha);
+ this.blendPixel(resultPixel, materialColor, color, tinAndAlpha[0], affectFactor, blendType, blenderContext);
+ newData.put(dataIndex++, (byte) (resultPixel[0] * 255.0f));
+ newData.put(dataIndex++, (byte) (resultPixel[1] * 255.0f));
+ newData.put(dataIndex++, (byte) (resultPixel[2] * 255.0f));
+ newData.put(dataIndex++, (byte) (tinAndAlpha[1] * 255.0f));
+ }
+ if (texture.getType() == Texture.Type.TwoDimensional) {
+ return new Texture2D(new Image(Format.RGBA8, width, height, newData));
+ } else {
+ ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(1);
+ dataArray.add(newData);
+ return new Texture3D(new Image(Format.RGBA8, width, height, depth, dataArray));
+ }
+ }
+
+ /**
+ * This method return texture intensity and alpha value.
+ *
+ * @param data
+ * the texture data
+ * @param imageFormat
+ * the image format
+ * @param neg
+ * indicates if the texture is negated
+ * @param result
+ * the table (2 elements) where the result is being stored
+ */
+ protected void getTinAndAlpha(ByteBuffer data, Format imageFormat, boolean neg, float[] result) {
+ byte pixelValue = data.get();// at least one byte is always taken
+ float firstPixelValue = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
+ switch (imageFormat) {
+ case Luminance8:
+ result[0] = neg ? 1.0f - firstPixelValue : firstPixelValue;
+ result[1] = 1.0f;
+ break;
+ case Luminance8Alpha8:
+ result[0] = neg ? 1.0f - firstPixelValue : firstPixelValue;
+ pixelValue = data.get();
+ result[1] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
+ break;
+ case Luminance16:
+ case Luminance16Alpha16:
+ case Luminance16F:
+ case Luminance16FAlpha16F:
+ case Luminance32F:
+ LOGGER.log(Level.WARNING, "Image type not yet supported for blending: {0}", imageFormat);
+ break;
+ default:
+ throw new IllegalStateException("Invalid image format type for DDS texture blender: " + imageFormat);
+ }
+ }
+
+ /**
+ * This method blends the texture with an appropriate color.
+ *
+ * @param result
+ * the result color (variable 'in' in blender source code)
+ * @param materialColor
+ * the texture color (variable 'out' in blender source coude)
+ * @param color
+ * the previous color (variable 'tex' in blender source code)
+ * @param textureIntensity
+ * texture intensity (variable 'fact' in blender source code)
+ * @param textureFactor
+ * texture affection factor (variable 'facg' in blender source
+ * code)
+ * @param blendtype
+ * the blend type
+ * @param blenderContext
+ * the blender context
+ */
+ protected void blendPixel(float[] result, float[] materialColor, float[] color, float textureIntensity, float textureFactor, int blendtype, BlenderContext blenderContext) {
+ float oneMinusFactor, col;
+ textureIntensity *= textureFactor;
+
+ switch (blendtype) {
+ case MTEX_BLEND:
+ oneMinusFactor = 1.0f - textureIntensity;
+ result[0] = textureIntensity * color[0] + oneMinusFactor * materialColor[0];
+ result[1] = textureIntensity * color[1] + oneMinusFactor * materialColor[1];
+ result[2] = textureIntensity * color[2] + oneMinusFactor * materialColor[2];
+ break;
+ case MTEX_MUL:
+ oneMinusFactor = 1.0f - textureFactor;
+ result[0] = (oneMinusFactor + textureIntensity * materialColor[0]) * color[0];
+ result[1] = (oneMinusFactor + textureIntensity * materialColor[1]) * color[1];
+ result[2] = (oneMinusFactor + textureIntensity * materialColor[2]) * color[2];
+ break;
+ case MTEX_DIV:
+ oneMinusFactor = 1.0f - textureIntensity;
+ if (color[0] != 0.0) {
+ result[0] = (oneMinusFactor * materialColor[0] + textureIntensity * materialColor[0] / color[0]) * 0.5f;
+ }
+ if (color[1] != 0.0) {
+ result[1] = (oneMinusFactor * materialColor[1] + textureIntensity * materialColor[1] / color[1]) * 0.5f;
+ }
+ if (color[2] != 0.0) {
+ result[2] = (oneMinusFactor * materialColor[2] + textureIntensity * materialColor[2] / color[2]) * 0.5f;
+ }
+ break;
+ case MTEX_SCREEN:
+ oneMinusFactor = 1.0f - textureFactor;
+ result[0] = 1.0f - (oneMinusFactor + textureIntensity * (1.0f - materialColor[0])) * (1.0f - color[0]);
+ result[1] = 1.0f - (oneMinusFactor + textureIntensity * (1.0f - materialColor[1])) * (1.0f - color[1]);
+ result[2] = 1.0f - (oneMinusFactor + textureIntensity * (1.0f - materialColor[2])) * (1.0f - color[2]);
+ break;
+ case MTEX_OVERLAY:
+ oneMinusFactor = 1.0f - textureFactor;
+ if (materialColor[0] < 0.5f) {
+ result[0] = color[0] * (oneMinusFactor + 2.0f * textureIntensity * materialColor[0]);
+ } else {
+ result[0] = 1.0f - (oneMinusFactor + 2.0f * textureIntensity * (1.0f - materialColor[0])) * (1.0f - color[0]);
+ }
+ if (materialColor[1] < 0.5f) {
+ result[1] = color[1] * (oneMinusFactor + 2.0f * textureIntensity * materialColor[1]);
+ } else {
+ result[1] = 1.0f - (oneMinusFactor + 2.0f * textureIntensity * (1.0f - materialColor[1])) * (1.0f - color[1]);
+ }
+ if (materialColor[2] < 0.5f) {
+ result[2] = color[2] * (oneMinusFactor + 2.0f * textureIntensity * materialColor[2]);
+ } else {
+ result[2] = 1.0f - (oneMinusFactor + 2.0f * textureIntensity * (1.0f - materialColor[2])) * (1.0f - color[2]);
+ }
+ break;
+ case MTEX_SUB:
+ result[0] = materialColor[0] - textureIntensity * color[0];
+ result[1] = materialColor[1] - textureIntensity * color[1];
+ result[2] = materialColor[2] - textureIntensity * color[2];
+ result[0] = FastMath.clamp(result[0], 0.0f, 1.0f);
+ result[1] = FastMath.clamp(result[1], 0.0f, 1.0f);
+ result[2] = FastMath.clamp(result[2], 0.0f, 1.0f);
+ break;
+ case MTEX_ADD:
+ result[0] = (textureIntensity * color[0] + materialColor[0]) * 0.5f;
+ result[1] = (textureIntensity * color[1] + materialColor[1]) * 0.5f;
+ result[2] = (textureIntensity * color[2] + materialColor[2]) * 0.5f;
+ break;
+ case MTEX_DIFF:
+ oneMinusFactor = 1.0f - textureIntensity;
+ result[0] = oneMinusFactor * materialColor[0] + textureIntensity * Math.abs(materialColor[0] - color[0]);
+ result[1] = oneMinusFactor * materialColor[1] + textureIntensity * Math.abs(materialColor[1] - color[1]);
+ result[2] = oneMinusFactor * materialColor[2] + textureIntensity * Math.abs(materialColor[2] - color[2]);
+ break;
+ case MTEX_DARK:
+ col = textureIntensity * color[0];
+ result[0] = col < materialColor[0] ? col : materialColor[0];
+ col = textureIntensity * color[1];
+ result[1] = col < materialColor[1] ? col : materialColor[1];
+ col = textureIntensity * color[2];
+ result[2] = col < materialColor[2] ? col : materialColor[2];
+ break;
+ case MTEX_LIGHT:
+ col = textureIntensity * color[0];
+ result[0] = col > materialColor[0] ? col : materialColor[0];
+ col = textureIntensity * color[1];
+ result[1] = col > materialColor[1] ? col : materialColor[1];
+ col = textureIntensity * color[2];
+ result[2] = col > materialColor[2] ? col : materialColor[2];
+ break;
+ case MTEX_BLEND_HUE:
+ case MTEX_BLEND_SAT:
+ case MTEX_BLEND_VAL:
+ case MTEX_BLEND_COLOR:
+ System.arraycopy(materialColor, 0, result, 0, 3);
+ this.blendHSV(blendtype, result, textureIntensity, color, blenderContext);
+ break;
+ default:
+ throw new IllegalStateException("Unknown blend type: " + blendtype);
+ }
+ }
+}