diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/textures/CombinedTexture.java b/engine/src/blender/com/jme3/scene/plugins/blender/textures/CombinedTexture.java
index 5394a2cbf..b2ffe8ebc 100644
--- a/engine/src/blender/com/jme3/scene/plugins/blender/textures/CombinedTexture.java
+++ b/engine/src/blender/com/jme3/scene/plugins/blender/textures/CombinedTexture.java
@@ -100,8 +100,7 @@ public class CombinedTexture {
Texture previousTexture = null;
UVCoordinatesType masterUVCoordinatesType = null;
for (TextureData textureData : textureDatas) {
- // decompress compressed textures (all will be merged into one
- // texture anyway)
+ // decompress compressed textures (all will be merged into one texture anyway)
if (textureDatas.size() > 1 && textureData.texture.getImage().getFormat().isCompressed()) {
textureData.texture.setImage(textureHelper.decompress(textureData.texture.getImage()));
textureData.textureBlender = TextureBlenderFactory.alterTextureType(textureData.texture.getImage().getFormat(), textureData.textureBlender);
@@ -228,19 +227,25 @@ public class CombinedTexture {
* the source texture
*/
private void merge(Texture2D target, Texture2D source) {
+ if(target.getImage().getDepth() != source.getImage().getDepth()) {
+ throw new IllegalArgumentException("Cannot merge images with different depths!");
+ }
Image sourceImage = source.getImage();
Image targetImage = target.getImage();
PixelInputOutput sourceIO = PixelIOFactory.getPixelIO(sourceImage.getFormat());
PixelInputOutput targetIO = PixelIOFactory.getPixelIO(targetImage.getFormat());
TexturePixel sourcePixel = new TexturePixel();
TexturePixel targetPixel = new TexturePixel();
-
- for (int x = 0; x < sourceImage.getWidth(); ++x) {
- for (int y = 0; y < sourceImage.getHeight(); ++y) {
- sourceIO.read(sourceImage, sourcePixel, x, y);
- targetIO.read(targetImage, targetPixel, x, y);
- targetPixel.merge(sourcePixel);
- targetIO.write(targetImage, targetPixel, x, y);
+ int depth = target.getImage().getDepth() == 0 ? 1 : target.getImage().getDepth();
+
+ for (int layerIndex = 0; layerIndex < depth; ++layerIndex) {
+ for (int x = 0; x < sourceImage.getWidth(); ++x) {
+ for (int y = 0; y < sourceImage.getHeight(); ++y) {
+ sourceIO.read(sourceImage, layerIndex, sourcePixel, x, y);
+ targetIO.read(targetImage, layerIndex, targetPixel, x, y);
+ targetPixel.merge(sourcePixel);
+ targetIO.write(targetImage, layerIndex, targetPixel, x, y);
+ }
}
}
}
@@ -299,15 +304,17 @@ public class CombinedTexture {
case RGBA16:
case RGBA16F:
case RGBA32F:
- case RGBA8:// with these types it is better to make sure if
- // the texture is or is not transparent
+ case RGBA8:// with these types it is better to make sure if the texture is or is not transparent
PixelInputOutput pixelInputOutput = PixelIOFactory.getPixelIO(image.getFormat());
TexturePixel pixel = new TexturePixel();
- for (int x = 0; x < image.getWidth(); ++x) {
- for (int y = 0; y < image.getHeight(); ++y) {
- pixelInputOutput.read(image, pixel, x, y);
- if (pixel.alpha < 1.0f) {
- return false;
+ int depth = image.getDepth() == 0 ? 1 : image.getDepth();
+ for (int layerIndex = 0; layerIndex < depth; ++layerIndex) {
+ for (int x = 0; x < image.getWidth(); ++x) {
+ for (int y = 0; y < image.getHeight(); ++y) {
+ pixelInputOutput.read(image, layerIndex, pixel, x, y);
+ if (pixel.alpha < 1.0f) {
+ return false;
+ }
}
}
}
diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/textures/DDSTexelData.java b/engine/src/blender/com/jme3/scene/plugins/blender/textures/DDSTexelData.java
index 288d687da..4e4b4247d 100644
--- a/engine/src/blender/com/jme3/scene/plugins/blender/textures/DDSTexelData.java
+++ b/engine/src/blender/com/jme3/scene/plugins/blender/textures/DDSTexelData.java
@@ -1,13 +1,14 @@
package com.jme3.scene.plugins.blender.textures;
import com.jme3.math.FastMath;
+import com.jme3.texture.Image.Format;
/**
* The data that helps in bytes calculations for the result image.
*
* @author Marcin Roguski (Kaelthas)
*/
-/*package*/ class DDSTexelData {
+/* package */class DDSTexelData {
/** The colors of the texes. */
private TexturePixel[][] colors;
/** The indexes of the texels. */
@@ -21,36 +22,33 @@ import com.jme3.math.FastMath;
/** The counter of texel y row. */
private int yCounter;
/** The width of the image in pixels. */
- private int pixelWidth;
+ private int widthInPixels;
/** The height of the image in pixels. */
- private int pixelHeight;
+ private int heightInPixels;
/** The total texel count. */
private int xTexelCount;
/**
- * Constructor. Allocates the required memory. Initializes variables.
+ * Constructor. Allocates memory for data structures.
*
- * @param textelsCount
- * the total count of the texels
- * @param pixelWidth
- * the width of the image in pixels
- * @param pixelHeight
- * the height of the image in pixels
- * @param isAlpha
- * indicates if the memory for alpha values should be
- * allocated
+ * @param compressedSize
+ * the size of compressed image (or its mipmap)
+ * @param widthToHeightRatio
+ * width/height ratio for the image
+ * @param format
+ * the format of the image
*/
- public DDSTexelData(int textelsCount, int pixelWidth, int pixelHeight, boolean isAlpha) {
- textelsCount = pixelWidth * pixelHeight >> 4;
- this.colors = new TexturePixel[textelsCount][];
- this.indexes = new long[textelsCount];
- this.xTexelCount = pixelWidth >> 2;
- this.yCounter = (pixelHeight >> 2) - 1;// xCounter is 0 for now
- this.pixelHeight = pixelHeight;
- this.pixelWidth = pixelWidth;
- if (isAlpha) {
- this.alphas = new float[textelsCount][];
- this.alphaIndexes = new long[textelsCount];
+ public DDSTexelData(int compressedSize, float widthToHeightRatio, Format format) {
+ int texelsCount = compressedSize * 8 / format.getBitsPerPixel() / 16;
+ this.colors = new TexturePixel[texelsCount][];
+ this.indexes = new long[texelsCount];
+ this.widthInPixels = (int) (0.5f * (float) Math.sqrt(this.getSizeInBytes() / widthToHeightRatio));
+ this.heightInPixels = (int) (this.widthInPixels / widthToHeightRatio);
+ this.xTexelCount = widthInPixels >> 2;
+ this.yCounter = (heightInPixels >> 2) - 1;// xCounter is 0 for now
+ if (format == Format.DXT3 || format == Format.DXT5) {
+ this.alphas = new float[texelsCount][];
+ this.alphaIndexes = new long[texelsCount];
}
}
@@ -104,28 +102,56 @@ import com.jme3.math.FastMath;
* the y coordinate of the pixel
* @param result
* the table where the result is stored
+ * @return true if the pixel was correctly read and false if
+ * the position was outside the image sizes
*/
- public void getRGBA8(int x, int y, byte[] result) {
- int xTexetlIndex = x % pixelWidth / 4;
- int yTexelIndex = y % pixelHeight / 4;
+ public boolean getRGBA8(int x, int y, byte[] result) {
+ int xTexetlIndex = x % widthInPixels / 4;
+ int yTexelIndex = y % heightInPixels / 4;
int texelIndex = yTexelIndex * xTexelCount + xTexetlIndex;
- TexturePixel[] colors = this.colors[texelIndex];
+ if (texelIndex < colors.length) {
+ TexturePixel[] colors = this.colors[texelIndex];
- // coordinates of the pixel in the selected texel
- x = x - 4 * xTexetlIndex;// pixels are arranged from left to right
- y = 3 - y - 4 * yTexelIndex;// pixels are arranged from bottom to top (that is why '3 - ...' is at the start)
+ // coordinates of the pixel in the selected texel
+ x = x - 4 * xTexetlIndex;// pixels are arranged from left to right
+ y = 3 - y - 4 * yTexelIndex;// pixels are arranged from bottom to top (that is why '3 - ...' is at the start)
- int pixelIndexInTexel = (y * 4 + x) * (int) FastMath.log(colors.length, 2);
- int alphaIndexInTexel = alphas != null ? (y * 4 + x) * (int) FastMath.log(alphas.length, 2) : 0;
+ int pixelIndexInTexel = (y * 4 + x) * (int) FastMath.log(colors.length, 2);
+ int alphaIndexInTexel = alphas != null ? (y * 4 + x) * (int) FastMath.log(alphas.length, 2) : 0;
- // getting the pixel
- int indexMask = colors.length - 1;
- int colorIndex = (int) (this.indexes[texelIndex] >> pixelIndexInTexel & indexMask);
- float alpha = this.alphas != null ? this.alphas[texelIndex][(int) (this.alphaIndexes[texelIndex] >> alphaIndexInTexel & 0x07)] : colors[colorIndex].alpha;
- result[0] = (byte) (colors[colorIndex].red * 255.0f);
- result[1] = (byte) (colors[colorIndex].green * 255.0f);
- result[2] = (byte) (colors[colorIndex].blue * 255.0f);
- result[3] = (byte) (alpha * 255.0f);
+ // getting the pixel
+ int indexMask = colors.length - 1;
+ int colorIndex = (int) (this.indexes[texelIndex] >> pixelIndexInTexel & indexMask);
+ float alpha = this.alphas != null ? this.alphas[texelIndex][(int) (this.alphaIndexes[texelIndex] >> alphaIndexInTexel & 0x07)] : colors[colorIndex].alpha;
+ result[0] = (byte) (colors[colorIndex].red * 255.0f);
+ result[1] = (byte) (colors[colorIndex].green * 255.0f);
+ result[2] = (byte) (colors[colorIndex].blue * 255.0f);
+ result[3] = (byte) (alpha * 255.0f);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * @return the size of the decompressed texel (in bytes)
+ */
+ public int getSizeInBytes() {
+ // indexes.length == count of texels
+ return indexes.length * 16 * 4;
+ }
+
+ /**
+ * @return image (mipmap) width
+ */
+ public int getPixelWidth() {
+ return widthInPixels;
+ }
+
+ /**
+ * @return image (mipmap) height
+ */
+ public int getPixelHeight() {
+ return heightInPixels;
}
}
diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureHelper.java
index c1b970eee..46b642415 100644
--- a/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureHelper.java
+++ b/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureHelper.java
@@ -242,27 +242,78 @@ public class TextureHelper extends AbstractBlenderHelper {
depth = 1;
}
ArrayList dataArray = new ArrayList(depth);
- TexturePixel[] colors = new TexturePixel[] { new TexturePixel(), new TexturePixel(), new TexturePixel(), new TexturePixel() };
+ int[] sizes = image.getMipMapSizes() != null ? image.getMipMapSizes() : new int[1];
+ int[] newMipmapSizes = image.getMipMapSizes() != null ? new int[image.getMipMapSizes().length] : null;
for (int dataLayerIndex = 0; dataLayerIndex < depth; ++dataLayerIndex) {
ByteBuffer data = image.getData(dataLayerIndex);
data.rewind();
+ if(sizes.length == 1) {
+ sizes[0] = data.remaining();
+ }
+ float widthToHeightRatio = image.getWidth() / image.getHeight();//this should always be constant for each mipmap
+ List texelDataList = new ArrayList(sizes.length);
+ int maxPosition = 0, resultSize = 0;
- byte[] bytes = new byte[image.getWidth() * image.getHeight() << 2];
- DDSTexelData texelData = new DDSTexelData(data.remaining() * 8/format.getBitsPerPixel()/16/*data.remaining() / (format.getBitsPerPixel() << 1)*/,
- image.getWidth(), image.getHeight(), format != Format.DXT1);
- switch (format) {
- case DXT1:// BC1
- case DXT1A:
- while (data.hasRemaining()) {
- short c0 = data.getShort();
- short c1 = data.getShort();
- int col0 = RGB565.RGB565_to_ARGB8(c0);
- int col1 = RGB565.RGB565_to_ARGB8(c1);
- colors[0].fromARGB8(col0);
- colors[1].fromARGB8(col1);
-
- if (col0 > col1) {
+ for(int sizeIndex=0;sizeIndex col1) {
+ // creating color2 = 2/3color0 + 1/3color1
+ colors[2].fromPixel(colors[0]);
+ colors[2].mult(2);
+ colors[2].add(colors[1]);
+ colors[2].divide(3);
+
+ // creating color3 = 1/3color0 + 2/3color1;
+ colors[3].fromPixel(colors[1]);
+ colors[3].mult(2);
+ colors[3].add(colors[0]);
+ colors[3].divide(3);
+ } else {
+ // creating color2 = 1/2color0 + 1/2color1
+ colors[2].fromPixel(colors[0]);
+ colors[2].add(colors[1]);
+ colors[2].mult(0.5f);
+
+ colors[3].fromARGB8(0);
+ }
+ int indexes = data.getInt();// 4-byte table with color indexes in decompressed table
+ texelData.add(colors, indexes);
+ }
+ break;
+ case DXT3:// BC2
+ while (data.position() < maxPosition) {
+ TexturePixel[] colors = new TexturePixel[] { new TexturePixel(), new TexturePixel(), new TexturePixel(), new TexturePixel() };
+ long alpha = data.getLong();
+ float[] alphas = new float[16];
+ long alphasIndex = 0;
+ for (int i = 0; i < 16; ++i) {
+ alphasIndex |= i << i * 4;
+ byte a = (byte) ((alpha >> i * 4 & 0x0F) << 4);
+ alphas[i] = a >= 0 ? a / 255.0f : 1.0f - ~a / 255.0f;
+ }
+
+ short c0 = data.getShort();
+ short c1 = data.getShort();
+ int col0 = RGB565.RGB565_to_ARGB8(c0);
+ int col1 = RGB565.RGB565_to_ARGB8(c1);
+ colors[0].fromARGB8(col0);
+ colors[1].fromARGB8(col1);
+
// creating color2 = 2/3color0 + 1/3color1
colors[2].fromPixel(colors[0]);
colors[2].mult(2);
@@ -274,118 +325,88 @@ public class TextureHelper extends AbstractBlenderHelper {
colors[3].mult(2);
colors[3].add(colors[0]);
colors[3].divide(3);
- } else {
- // creating color2 = 1/2color0 + 1/2color1
+
+ int indexes = data.getInt();// 4-byte table with color indexes in decompressed table
+ texelData.add(colors, indexes, alphas, alphasIndex);
+ }
+ break;
+ case DXT5:// BC3
+ float[] alphas = new float[8];
+ while (data.position() < maxPosition) {
+ TexturePixel[] colors = new TexturePixel[] { new TexturePixel(), new TexturePixel(), new TexturePixel(), new TexturePixel() };
+ alphas[0] = data.get() * 255.0f;
+ alphas[1] = data.get() * 255.0f;
+ long alphaIndices = data.get() | data.get() << 8 | data.get() << 16 | data.get() << 24 | data.get() << 32 | data.get() << 40;
+ if (alphas[0] > alphas[1]) {// 6 interpolated alpha values.
+ alphas[2] = (6 * alphas[0] + alphas[1]) / 7;
+ alphas[3] = (5 * alphas[0] + 2 * alphas[1]) / 7;
+ alphas[4] = (4 * alphas[0] + 3 * alphas[1]) / 7;
+ alphas[5] = (3 * alphas[0] + 4 * alphas[1]) / 7;
+ alphas[6] = (2 * alphas[0] + 5 * alphas[1]) / 7;
+ alphas[7] = (alphas[0] + 6 * alphas[1]) / 7;
+ } else {
+ alphas[2] = (4 * alphas[0] + alphas[1]) * 0.2f;
+ alphas[3] = (3 * alphas[0] + 2 * alphas[1]) * 0.2f;
+ alphas[4] = (2 * alphas[0] + 3 * alphas[1]) * 0.2f;
+ alphas[5] = (alphas[0] + 4 * alphas[1]) * 0.2f;
+ alphas[6] = 0;
+ alphas[7] = 1;
+ }
+
+ short c0 = data.getShort();
+ short c1 = data.getShort();
+ int col0 = RGB565.RGB565_to_ARGB8(c0);
+ int col1 = RGB565.RGB565_to_ARGB8(c1);
+ colors[0].fromARGB8(col0);
+ colors[1].fromARGB8(col1);
+
+ // creating color2 = 2/3color0 + 1/3color1
colors[2].fromPixel(colors[0]);
+ colors[2].mult(2);
colors[2].add(colors[1]);
- colors[2].mult(0.5f);
+ colors[2].divide(3);
- colors[3].fromARGB8(0);
- }
- int indexes = data.getInt();// 4-byte table with color indexes in decompressed table
- texelData.add(colors, indexes);
- }
- break;
- case DXT3:// BC2
- while (data.hasRemaining()) {
- long alpha = data.getLong();
- float[] alphas = new float[16];
- long alphasIndex = 0;
- for (int i = 0; i < 16; ++i) {
- alphasIndex |= i << i * 4;
- byte a = (byte) ((alpha >> i * 4 & 0x0F) << 4);
- alphas[i] = a >= 0 ? a / 255.0f : 1.0f - ~a / 255.0f;
- }
+ // creating color3 = 1/3color0 + 2/3color1;
+ colors[3].fromPixel(colors[1]);
+ colors[3].mult(2);
+ colors[3].add(colors[0]);
+ colors[3].divide(3);
- short c0 = data.getShort();
- short c1 = data.getShort();
- int col0 = RGB565.RGB565_to_ARGB8(c0);
- int col1 = RGB565.RGB565_to_ARGB8(c1);
- colors[0].fromARGB8(col0);
- colors[1].fromARGB8(col1);
-
- // creating color2 = 2/3color0 + 1/3color1
- colors[2].fromPixel(colors[0]);
- colors[2].mult(2);
- colors[2].add(colors[1]);
- colors[2].divide(3);
-
- // creating color3 = 1/3color0 + 2/3color1;
- colors[3].fromPixel(colors[1]);
- colors[3].mult(2);
- colors[3].add(colors[0]);
- colors[3].divide(3);
-
- int indexes = data.getInt();// 4-byte table with color indexes in decompressed table
- texelData.add(colors, indexes, alphas, alphasIndex);
- }
- break;
- case DXT5:// BC3
- float[] alphas = new float[8];
- while (data.hasRemaining()) {
- alphas[0] = data.get() * 255.0f;
- alphas[1] = data.get() * 255.0f;
- long alphaIndices = data.get() | data.get() << 8 | data.get() << 16 | data.get() << 24 | data.get() << 32 | data.get() << 40;
- if (alphas[0] > alphas[1]) {// 6 interpolated alpha values.
- alphas[2] = (6 * alphas[0] + alphas[1]) / 7;
- alphas[3] = (5 * alphas[0] + 2 * alphas[1]) / 7;
- alphas[4] = (4 * alphas[0] + 3 * alphas[1]) / 7;
- alphas[5] = (3 * alphas[0] + 4 * alphas[1]) / 7;
- alphas[6] = (2 * alphas[0] + 5 * alphas[1]) / 7;
- alphas[7] = (alphas[0] + 6 * alphas[1]) / 7;
- } else {
- alphas[2] = (4 * alphas[0] + alphas[1]) * 0.2f;
- alphas[3] = (3 * alphas[0] + 2 * alphas[1]) * 0.2f;
- alphas[4] = (2 * alphas[0] + 3 * alphas[1]) * 0.2f;
- alphas[5] = (alphas[0] + 4 * alphas[1]) * 0.2f;
- alphas[6] = 0;
- alphas[7] = 1;
+ int indexes = data.getInt();// 4-byte table with color indexes in decompressed table
+ texelData.add(colors, indexes, alphas, alphaIndices);
}
-
- short c0 = data.getShort();
- short c1 = data.getShort();
- int col0 = RGB565.RGB565_to_ARGB8(c0);
- int col1 = RGB565.RGB565_to_ARGB8(c1);
- colors[0].fromARGB8(col0);
- colors[1].fromARGB8(col1);
-
- // creating color2 = 2/3color0 + 1/3color1
- colors[2].fromPixel(colors[0]);
- colors[2].mult(2);
- colors[2].add(colors[1]);
- colors[2].divide(3);
-
- // creating color3 = 1/3color0 + 2/3color1;
- colors[3].fromPixel(colors[1]);
- colors[3].mult(2);
- colors[3].add(colors[0]);
- colors[3].divide(3);
-
- int indexes = data.getInt();// 4-byte table with color indexes in decompressed table
- texelData.add(colors, indexes, alphas, alphaIndices);
- }
- break;
- default:
- throw new IllegalStateException("Unknown compressed format: " + format);
+ break;
+ default:
+ throw new IllegalStateException("Unknown compressed format: " + format);
+ }
+ newMipmapSizes[sizeIndex] = texelData.getSizeInBytes();
+ resultSize += texelData.getSizeInBytes();
}
-
+ byte[] bytes = new byte[resultSize];
+ int offset = 0;
byte[] pixelBytes = new byte[4];
- for (int i = 0; i < image.getWidth(); ++i) {
- for (int j = 0; j < image.getHeight(); ++j) {
- texelData.getRGBA8(i, j, pixelBytes);
- bytes[(j * image.getWidth() + i) * 4] = pixelBytes[0];
- bytes[(j * image.getWidth() + i) * 4 + 1] = pixelBytes[1];
- bytes[(j * image.getWidth() + i) * 4 + 2] = pixelBytes[2];
- bytes[(j * image.getWidth() + i) * 4 + 3] = pixelBytes[3];
+ for(DDSTexelData texelData : texelDataList) {
+ for (int i = 0; i < texelData.getPixelWidth(); ++i) {
+ for (int j = 0; j < texelData.getPixelHeight(); ++j) {
+ if(texelData.getRGBA8(i, j, pixelBytes)) {
+ bytes[offset + (j * texelData.getPixelWidth() + i) * 4] = pixelBytes[0];
+ bytes[offset + (j * texelData.getPixelWidth() + i) * 4 + 1] = pixelBytes[1];
+ bytes[offset + (j * texelData.getPixelWidth() + i) * 4 + 2] = pixelBytes[2];
+ bytes[offset + (j * texelData.getPixelWidth() + i) * 4 + 3] = pixelBytes[3];
+ } else {
+ break;
+ }
+ }
}
+ offset += texelData.getSizeInBytes();
}
dataArray.add(BufferUtils.createByteBuffer(bytes));
}
Image result = depth > 1 ? new Image(Format.RGBA8, image.getWidth(), image.getHeight(), depth, dataArray) :
new Image(Format.RGBA8, image.getWidth(), image.getHeight(), dataArray.get(0));
- if(image.getMipMapSizes() != null) {
- result.setMipMapSizes(image.getMipMapSizes().clone());
+ if(newMipmapSizes != null) {
+ result.setMipMapSizes(newMipmapSizes);
}
return result;
}
@@ -500,35 +521,40 @@ public class TextureHelper extends AbstractBlenderHelper {
float gfac = ((Number) tex.getFieldValue("gfac")).floatValue();
float bfac = ((Number) tex.getFieldValue("bfac")).floatValue();
float[][] colorBand = new ColorBand(tex, blenderContext).computeValues();
-
+ int depth = image.getDepth() == 0 ? 1 : image.getDepth();
+
if (colorBand != null) {
TexturePixel pixel = new TexturePixel();
PixelInputOutput imageIO = PixelIOFactory.getPixelIO(image.getFormat());
- for (int x = 0; x < image.getWidth(); ++x) {
- for (int y = 0; y < image.getHeight(); ++y) {
- imageIO.read(image, pixel, x, y);
-
- int colorbandIndex = (int) (pixel.alpha * 1000.0f);
- pixel.red = colorBand[colorbandIndex][0] * rfac;
- pixel.green = colorBand[colorbandIndex][1] * gfac;
- pixel.blue = colorBand[colorbandIndex][2] * bfac;
- pixel.alpha = colorBand[colorbandIndex][3];
-
- imageIO.write(image, pixel, x, y);
+ for (int layerIndex = 0; layerIndex < depth; ++layerIndex) {
+ for (int x = 0; x < image.getWidth(); ++x) {
+ for (int y = 0; y < image.getHeight(); ++y) {
+ imageIO.read(image, layerIndex, pixel, x, y);
+
+ int colorbandIndex = (int) (pixel.alpha * 1000.0f);
+ pixel.red = colorBand[colorbandIndex][0] * rfac;
+ pixel.green = colorBand[colorbandIndex][1] * gfac;
+ pixel.blue = colorBand[colorbandIndex][2] * bfac;
+ pixel.alpha = colorBand[colorbandIndex][3];
+
+ imageIO.write(image, layerIndex, pixel, x, y);
+ }
}
}
} else if (rfac != 1.0f || gfac != 1.0f || bfac != 1.0f) {
TexturePixel pixel = new TexturePixel();
PixelInputOutput imageIO = PixelIOFactory.getPixelIO(image.getFormat());
- for (int x = 0; x < image.getWidth(); ++x) {
- for (int y = 0; y < image.getHeight(); ++y) {
- imageIO.read(image, pixel, x, y);
-
- pixel.red *= rfac;
- pixel.green *= gfac;
- pixel.blue *= bfac;
-
- imageIO.write(image, pixel, x, y);
+ for (int layerIndex = 0; layerIndex < depth; ++layerIndex) {
+ for (int x = 0; x < image.getWidth(); ++x) {
+ for (int y = 0; y < image.getHeight(); ++y) {
+ imageIO.read(image, layerIndex, pixel, x, y);
+
+ pixel.red *= rfac;
+ pixel.green *= gfac;
+ pixel.blue *= bfac;
+
+ imageIO.write(image, layerIndex, pixel, x, y);
+ }
}
}
}
diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/textures/TriangulatedTexture.java b/engine/src/blender/com/jme3/scene/plugins/blender/textures/TriangulatedTexture.java
index 1df706a6c..f6d74588f 100644
--- a/engine/src/blender/com/jme3/scene/plugins/blender/textures/TriangulatedTexture.java
+++ b/engine/src/blender/com/jme3/scene/plugins/blender/textures/TriangulatedTexture.java
@@ -184,10 +184,10 @@ import com.jme3.util.BufferUtils;
for (int x = 0; x < sourceImage.getWidth(); ++x) {
for (int y = 0; y < sourceImage.getHeight(); ++y) {
- sourceIO.read(sourceImage, sourcePixel, x, y);
- targetIO.read(targetImage, targetPixel, x, y);
+ sourceIO.read(sourceImage, 0, sourcePixel, x, y);
+ targetIO.read(targetImage, 0, targetPixel, x, y);
targetPixel.merge(sourcePixel);
- targetIO.write(targetImage, targetPixel, x, y);
+ targetIO.write(targetImage, 0, targetPixel, x, y);
}
}
}
@@ -331,8 +331,8 @@ import com.jme3.util.BufferUtils;
for (int x = 0; x < source.getWidth(); ++x) {
for (int y = 0; y < source.getHeight(); ++y) {
- sourceIO.read(source, pixel, x, y);
- targetIO.write(target, pixel, targetXPos + x, targetYPos + y);
+ sourceIO.read(source, 0, pixel, x, y);
+ targetIO.write(target, 0, pixel, targetXPos + x, targetYPos + y);
}
}
}
@@ -465,7 +465,7 @@ import com.jme3.util.BufferUtils;
for (int x = minX; x < maxX; ++x) {
int xPos = x >= sourceImage.getWidth() ? x - sourceImage.getWidth() : x;
int yPos = y >= sourceImage.getHeight() ? y - sourceImage.getHeight() : y;
- pixelReader.read(sourceImage, pixel, xPos, yPos);
+ pixelReader.read(sourceImage, 0, pixel, xPos, yPos);
data.put(pixel.getR8());
data.put(pixel.getG8());
data.put(pixel.getB8());
@@ -542,7 +542,7 @@ import com.jme3.util.BufferUtils;
for (int y = 0; y < imageHeight; ++y) {
this.toTextureUV(boundingBox, point, uvs);
texture.getPixel(pixel, uvs[0], uvs[1], uvs[2]);
- pixelWriter.write(image, pixel, x, y);
+ pixelWriter.write(image, 0, pixel, x, y);
point.addLocal(hDelta);
}
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
index 9de617404..b52d5a5ee 100644
--- 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
@@ -2,8 +2,11 @@ package com.jme3.scene.plugins.blender.textures.blending;
import java.util.logging.Logger;
+import jme3tools.converters.MipMapGenerator;
+
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.materials.MaterialHelper;
+import com.jme3.texture.Image;
/**
* An abstract class that contains the basic methods used by the classes that
@@ -112,4 +115,24 @@ import com.jme3.scene.plugins.blender.materials.MaterialHelper;
LOGGER.warning("Cannot copy blending data from other types than " + this.getClass());
}
}
+
+ /**
+ * The method prepares images for blending. It generates mipmaps if one of
+ * the images has them defined and the other one has not.
+ *
+ * @param target
+ * the image where the blending result is stored
+ * @param source
+ * the image that is being read only
+ */
+ protected void prepareImagesForBlending(Image target, Image source) {
+ LOGGER.fine("Generating mipmaps if needed!");
+ boolean targetHasMipmaps = target == null ? false : target.getMipMapSizes() != null && target.getMipMapSizes().length > 0;
+ boolean sourceHasMipmaps = source == null ? false : source.getMipMapSizes() != null && source.getMipMapSizes().length > 0;
+ if (target != null && !targetHasMipmaps && sourceHasMipmaps) {
+ MipMapGenerator.generateMipMaps(target);
+ } else if (source != null && !sourceHasMipmaps && targetHasMipmaps) {
+ MipMapGenerator.generateMipMaps(source);
+ }
+ }
}
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
index 4c2356a7d..0f28621b2 100644
--- 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
@@ -40,6 +40,8 @@ public class TextureBlenderAWT extends AbstractTextureBlender {
}
public Image blend(Image image, Image baseImage, BlenderContext blenderContext) {
+ this.prepareImagesForBlending(image, baseImage);
+
float[] pixelColor = new float[] { color[0], color[1], color[2], 1.0f };
Format format = image.getFormat();
@@ -70,12 +72,12 @@ public class TextureBlenderAWT extends AbstractTextureBlender {
while (index < data.limit()) {
//getting the proper material color if the base texture is applied
if(basePixelIO != null) {
- basePixelIO.read(baseImage, basePixel, x, y);
+ basePixelIO.read(baseImage, dataLayerIndex, basePixel, x, y);
basePixel.toRGBA(materialColor);
}
//reading the current texture's pixel
- pixelReader.read(image, pixel, index);
+ pixelReader.read(image, dataLayerIndex, pixel, index);
index += image.getFormat().getBitsPerPixel() >> 3;
pixel.toRGBA(pixelColor);
if (negateTexture) {
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
index 8085d1ef4..4593f1ffe 100644
--- 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
@@ -28,6 +28,8 @@ public class TextureBlenderDDS extends TextureBlenderAWT {
@Override
public Image blend(Image image, Image baseImage, BlenderContext blenderContext) {
+ this.prepareImagesForBlending(image, baseImage);
+
Format format = image.getFormat();
int width = image.getWidth();
int height = image.getHeight();
@@ -55,7 +57,6 @@ public class TextureBlenderDDS extends TextureBlenderAWT {
ByteBuffer data = image.getData(dataLayerIndex);
data.rewind();
ByteBuffer newData = BufferUtils.createByteBuffer(data.remaining());
- System.out.println(dataLayerIndex);
while (data.hasRemaining()) {
if(format == Format.DXT3) {
long alpha = data.getLong();
@@ -84,8 +85,8 @@ public class TextureBlenderDDS extends TextureBlenderAWT {
//compressing 16 pixels from the base texture as if they belonged to a texel
if(baseImage != null) {
//reading pixels (first and last of the 16 colors array)
- basePixelIO.read(baseImage, baseTextureColors[0], baseXTexelIndex << 2, baseYTexelIndex << 2);//first pixel
- basePixelIO.read(baseImage, baseTextureColors[1], baseXTexelIndex << 2 + 4, baseYTexelIndex << 2 + 4);//last pixel
+ basePixelIO.read(baseImage, dataLayerIndex, baseTextureColors[0], baseXTexelIndex << 2, baseYTexelIndex << 2);//first pixel
+ basePixelIO.read(baseImage, dataLayerIndex, baseTextureColors[1], baseXTexelIndex << 2 + 4, baseYTexelIndex << 2 + 4);//last pixel
baseTextureColors[0].toRGBA(compressedMaterialColor[0]);
baseTextureColors[1].toRGBA(compressedMaterialColor[1]);
}
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
index 504d94e52..e2a7a09e6 100644
--- 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
@@ -34,8 +34,9 @@ public class TextureBlenderLuminance extends AbstractTextureBlender {
}
public Image blend(Image image, Image baseImage, BlenderContext blenderContext) {
+ this.prepareImagesForBlending(image, baseImage);
+
Format format = image.getFormat();
-
PixelInputOutput basePixelIO = null;
TexturePixel basePixel = null;
float[] materialColor = this.materialColor;
@@ -64,7 +65,7 @@ public class TextureBlenderLuminance extends AbstractTextureBlender {
while (data.hasRemaining()) {
//getting the proper material color if the base texture is applied
if(basePixelIO != null) {
- basePixelIO.read(baseImage, basePixel, x, y);
+ basePixelIO.read(baseImage, dataLayerIndex, basePixel, x, y);
basePixel.toRGBA(materialColor);
}
diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/textures/io/AWTPixelInputOutput.java b/engine/src/blender/com/jme3/scene/plugins/blender/textures/io/AWTPixelInputOutput.java
index fc98d323b..d075f9c05 100644
--- a/engine/src/blender/com/jme3/scene/plugins/blender/textures/io/AWTPixelInputOutput.java
+++ b/engine/src/blender/com/jme3/scene/plugins/blender/textures/io/AWTPixelInputOutput.java
@@ -1,5 +1,7 @@
package com.jme3.scene.plugins.blender.textures.io;
+import java.nio.ByteBuffer;
+
import com.jme3.scene.plugins.blender.textures.TexturePixel;
import com.jme3.texture.Image;
@@ -8,25 +10,26 @@ import com.jme3.texture.Image;
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class AWTPixelInputOutput implements PixelInputOutput {
- public void read(Image image, TexturePixel pixel, int index) {
+ public void read(Image image, int layer, TexturePixel pixel, int index) {
byte r,g,b,a;
+ ByteBuffer data = image.getData(layer);
switch(image.getFormat()) {//TODO: add other formats
case RGBA8:
- r = image.getData(0).get(index);
- g = image.getData(0).get(index + 1);
- b = image.getData(0).get(index + 2);
- a = image.getData(0).get(index + 3);
+ r = data.get(index);
+ g = data.get(index + 1);
+ b = data.get(index + 2);
+ a = data.get(index + 3);
break;
case ABGR8:
- a = image.getData(0).get(index);
- b = image.getData(0).get(index + 1);
- g = image.getData(0).get(index + 2);
- r = image.getData(0).get(index + 3);
+ a = data.get(index);
+ b = data.get(index + 1);
+ g = data.get(index + 2);
+ r = data.get(index + 3);
break;
case BGR8:
- b = image.getData(0).get(index);
- g = image.getData(0).get(index + 1);
- r = image.getData(0).get(index + 2);
+ b = data.get(index);
+ g = data.get(index + 1);
+ r = data.get(index + 2);
a = (byte)0xFF;
break;
default:
@@ -35,37 +38,38 @@ import com.jme3.texture.Image;
pixel.fromARGB8(a, r, g, b);
}
- public void read(Image image, TexturePixel pixel, int x, int y) {
+ public void read(Image image, int layer, TexturePixel pixel, int x, int y) {
int index = (y * image.getWidth() + x) * (image.getFormat().getBitsPerPixel() >> 3);
- this.read(image, pixel, index);
+ this.read(image, layer, pixel, index);
}
- public void write(Image image, TexturePixel pixel, int index) {
+ public void write(Image image, int layer, TexturePixel pixel, int index) {
+ ByteBuffer data = image.getData(layer);
switch(image.getFormat()) {
case RGBA8:
- image.getData(0).put(index, pixel.getR8());
- image.getData(0).put(index + 1, pixel.getG8());
- image.getData(0).put(index + 2, pixel.getB8());
- image.getData(0).put(index + 3, pixel.getA8());
+ data.put(index, pixel.getR8());
+ data.put(index + 1, pixel.getG8());
+ data.put(index + 2, pixel.getB8());
+ data.put(index + 3, pixel.getA8());
break;
case ABGR8:
- image.getData(0).put(index, pixel.getA8());
- image.getData(0).put(index + 1, pixel.getB8());
- image.getData(0).put(index + 2, pixel.getG8());
- image.getData(0).put(index + 3, pixel.getR8());
+ data.put(index, pixel.getA8());
+ data.put(index + 1, pixel.getB8());
+ data.put(index + 2, pixel.getG8());
+ data.put(index + 3, pixel.getR8());
break;
case BGR8:
- image.getData(0).put(index, pixel.getB8());
- image.getData(0).put(index + 1, pixel.getG8());
- image.getData(0).put(index + 2, pixel.getR8());
+ data.put(index, pixel.getB8());
+ data.put(index + 1, pixel.getG8());
+ data.put(index + 2, pixel.getR8());
break;
default:
throw new IllegalStateException("Unknown image format: " + image.getFormat());
}
}
- public void write(Image image, TexturePixel pixel, int x, int y) {
+ public void write(Image image, int layer, TexturePixel pixel, int x, int y) {
int index = (y * image.getWidth() + x) * (image.getFormat().getBitsPerPixel() >> 3);
- this.write(image, pixel, index);
+ this.write(image, layer, pixel, index);
}
}
diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/textures/io/DDSPixelInputOutput.java b/engine/src/blender/com/jme3/scene/plugins/blender/textures/io/DDSPixelInputOutput.java
index 0f4218848..57ac3efc3 100644
--- a/engine/src/blender/com/jme3/scene/plugins/blender/textures/io/DDSPixelInputOutput.java
+++ b/engine/src/blender/com/jme3/scene/plugins/blender/textures/io/DDSPixelInputOutput.java
@@ -17,11 +17,11 @@ import com.jme3.texture.Image;
/**
* For this class the index should be considered as a pixel index in AWT image format.
*/
- public void read(Image image, TexturePixel pixel, int index) {
- this.read(image, pixel, index % image.getWidth(), index / image.getWidth());
+ public void read(Image image, int layer, TexturePixel pixel, int index) {
+ this.read(image, layer, pixel, index % image.getWidth(), index / image.getWidth());
}
- public void read(Image image, TexturePixel pixel, int x, int y) {
+ public void read(Image image, int layer, TexturePixel pixel, int x, int y) {
int xTexetlIndex = x % image.getWidth() >> 2;
int yTexelIndex = y % image.getHeight() >> 2;
int xTexelCount = image.getWidth() >> 2;
@@ -31,7 +31,7 @@ import com.jme3.texture.Image;
int indexes = 0;
long alphaIndexes = 0;
float[] alphas = null;
- ByteBuffer data = image.getData().get(0);
+ ByteBuffer data = image.getData().get(layer);
switch (image.getFormat()) {
case DXT1: // BC1
@@ -162,11 +162,11 @@ import com.jme3.texture.Image;
pixel.alpha = alpha;
}
- public void write(Image image, TexturePixel pixel, int index) {
+ public void write(Image image, int layer, TexturePixel pixel, int index) {
throw new UnsupportedOperationException("Cannot put the DXT pixel by index because not every index contains the pixel color!");
}
- public void write(Image image, TexturePixel pixel, int x, int y) {
+ public void write(Image image, int layer, TexturePixel pixel, int x, int y) {
throw new UnsupportedOperationException("Writing to DDS texture pixel by pixel is not yet supported!");
}
}
diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/textures/io/LuminancePixelInputOutput.java b/engine/src/blender/com/jme3/scene/plugins/blender/textures/io/LuminancePixelInputOutput.java
index de6c7108d..7088210a1 100644
--- a/engine/src/blender/com/jme3/scene/plugins/blender/textures/io/LuminancePixelInputOutput.java
+++ b/engine/src/blender/com/jme3/scene/plugins/blender/textures/io/LuminancePixelInputOutput.java
@@ -8,22 +8,22 @@ import com.jme3.texture.Image;
* @author Marcin Roguski (Kaelthas)
*/
/*package*/ class LuminancePixelInputOutput implements PixelInputOutput {
- public void read(Image image, TexturePixel pixel, int index) {
- byte intensity = image.getData(0).get(index);
+ public void read(Image image, int layer, TexturePixel pixel, int index) {
+ byte intensity = image.getData(layer).get(index);
pixel.fromIntensity(intensity);
}
- public void read(Image image, TexturePixel pixel, int x, int y) {
+ public void read(Image image, int layer, TexturePixel pixel, int x, int y) {
int index = y * image.getWidth() + x;
- this.read(image, pixel, index);
+ this.read(image, layer, pixel, index);
}
- public void write(Image image, TexturePixel pixel, int index) {
- image.getData(0).put(index, pixel.getInt());
+ public void write(Image image, int layer, TexturePixel pixel, int index) {
+ image.getData(layer).put(index, pixel.getInt());
}
- public void write(Image image, TexturePixel pixel, int x, int y) {
+ public void write(Image image, int layer, TexturePixel pixel, int x, int y) {
int index = y * image.getWidth() + x;
- this.write(image, pixel, index);
+ this.write(image, layer,pixel, index);
}
}
diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/textures/io/PixelInputOutput.java b/engine/src/blender/com/jme3/scene/plugins/blender/textures/io/PixelInputOutput.java
index d259cd170..3eb83945b 100644
--- a/engine/src/blender/com/jme3/scene/plugins/blender/textures/io/PixelInputOutput.java
+++ b/engine/src/blender/com/jme3/scene/plugins/blender/textures/io/PixelInputOutput.java
@@ -19,7 +19,7 @@ public interface PixelInputOutput {
* @param index
* the index where the pixel begins in the image data
*/
- void read(Image image, TexturePixel pixel, int index);
+ void read(Image image, int layer, TexturePixel pixel, int index);
/**
* This method reads a pixel that is located at the given position on the
@@ -34,7 +34,7 @@ public interface PixelInputOutput {
* @param y
* the Y coordinate of the pixel
*/
- void read(Image image, TexturePixel pixel, int x, int y);
+ void read(Image image, int layer, TexturePixel pixel, int x, int y);
/**
* This method writes a pixel that starts at the given index.
@@ -46,7 +46,7 @@ public interface PixelInputOutput {
* @param index
* the index where the pixel begins in the image data
*/
- void write(Image image, TexturePixel pixel, int index);
+ void write(Image image, int layer, TexturePixel pixel, int index);
/**
* This method writes a pixel that is located at the given position on the
@@ -61,5 +61,5 @@ public interface PixelInputOutput {
* @param y
* the Y coordinate of the pixel
*/
- void write(Image image, TexturePixel pixel, int x, int y);
+ void write(Image image, int layer, TexturePixel pixel, int x, int y);
}