Support for multilayered textures and textures with mipmaps.

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9402 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
Kae..pl 13 years ago
parent 0090d4eaad
commit 9e2f6b88ef
  1. 23
      engine/src/blender/com/jme3/scene/plugins/blender/textures/CombinedTexture.java
  2. 78
      engine/src/blender/com/jme3/scene/plugins/blender/textures/DDSTexelData.java
  3. 68
      engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureHelper.java
  4. 14
      engine/src/blender/com/jme3/scene/plugins/blender/textures/TriangulatedTexture.java
  5. 23
      engine/src/blender/com/jme3/scene/plugins/blender/textures/blending/AbstractTextureBlender.java
  6. 6
      engine/src/blender/com/jme3/scene/plugins/blender/textures/blending/TextureBlenderAWT.java
  7. 7
      engine/src/blender/com/jme3/scene/plugins/blender/textures/blending/TextureBlenderDDS.java
  8. 5
      engine/src/blender/com/jme3/scene/plugins/blender/textures/blending/TextureBlenderLuminance.java
  9. 60
      engine/src/blender/com/jme3/scene/plugins/blender/textures/io/AWTPixelInputOutput.java
  10. 12
      engine/src/blender/com/jme3/scene/plugins/blender/textures/io/DDSPixelInputOutput.java
  11. 16
      engine/src/blender/com/jme3/scene/plugins/blender/textures/io/LuminancePixelInputOutput.java
  12. 8
      engine/src/blender/com/jme3/scene/plugins/blender/textures/io/PixelInputOutput.java

@ -100,8 +100,7 @@ public class CombinedTexture {
Texture previousTexture = null; Texture previousTexture = null;
UVCoordinatesType masterUVCoordinatesType = null; UVCoordinatesType masterUVCoordinatesType = null;
for (TextureData textureData : textureDatas) { for (TextureData textureData : textureDatas) {
// decompress compressed textures (all will be merged into one // decompress compressed textures (all will be merged into one texture anyway)
// texture anyway)
if (textureDatas.size() > 1 && textureData.texture.getImage().getFormat().isCompressed()) { if (textureDatas.size() > 1 && textureData.texture.getImage().getFormat().isCompressed()) {
textureData.texture.setImage(textureHelper.decompress(textureData.texture.getImage())); textureData.texture.setImage(textureHelper.decompress(textureData.texture.getImage()));
textureData.textureBlender = TextureBlenderFactory.alterTextureType(textureData.texture.getImage().getFormat(), textureData.textureBlender); textureData.textureBlender = TextureBlenderFactory.alterTextureType(textureData.texture.getImage().getFormat(), textureData.textureBlender);
@ -228,19 +227,25 @@ public class CombinedTexture {
* the source texture * the source texture
*/ */
private void merge(Texture2D target, Texture2D source) { 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 sourceImage = source.getImage();
Image targetImage = target.getImage(); Image targetImage = target.getImage();
PixelInputOutput sourceIO = PixelIOFactory.getPixelIO(sourceImage.getFormat()); PixelInputOutput sourceIO = PixelIOFactory.getPixelIO(sourceImage.getFormat());
PixelInputOutput targetIO = PixelIOFactory.getPixelIO(targetImage.getFormat()); PixelInputOutput targetIO = PixelIOFactory.getPixelIO(targetImage.getFormat());
TexturePixel sourcePixel = new TexturePixel(); TexturePixel sourcePixel = new TexturePixel();
TexturePixel targetPixel = new TexturePixel(); TexturePixel targetPixel = new TexturePixel();
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 x = 0; x < sourceImage.getWidth(); ++x) {
for (int y = 0; y < sourceImage.getHeight(); ++y) { for (int y = 0; y < sourceImage.getHeight(); ++y) {
sourceIO.read(sourceImage, sourcePixel, x, y); sourceIO.read(sourceImage, layerIndex, sourcePixel, x, y);
targetIO.read(targetImage, targetPixel, x, y); targetIO.read(targetImage, layerIndex, targetPixel, x, y);
targetPixel.merge(sourcePixel); targetPixel.merge(sourcePixel);
targetIO.write(targetImage, targetPixel, x, y); targetIO.write(targetImage, layerIndex, targetPixel, x, y);
}
} }
} }
} }
@ -299,18 +304,20 @@ public class CombinedTexture {
case RGBA16: case RGBA16:
case RGBA16F: case RGBA16F:
case RGBA32F: case RGBA32F:
case RGBA8:// with these types it is better to make sure if case RGBA8:// with these types it is better to make sure if the texture is or is not transparent
// the texture is or is not transparent
PixelInputOutput pixelInputOutput = PixelIOFactory.getPixelIO(image.getFormat()); PixelInputOutput pixelInputOutput = PixelIOFactory.getPixelIO(image.getFormat());
TexturePixel pixel = new TexturePixel(); TexturePixel pixel = new TexturePixel();
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 x = 0; x < image.getWidth(); ++x) {
for (int y = 0; y < image.getHeight(); ++y) { for (int y = 0; y < image.getHeight(); ++y) {
pixelInputOutput.read(image, pixel, x, y); pixelInputOutput.read(image, layerIndex, pixel, x, y);
if (pixel.alpha < 1.0f) { if (pixel.alpha < 1.0f) {
return false; return false;
} }
} }
} }
}
return true; return true;
} }
} }

@ -1,6 +1,7 @@
package com.jme3.scene.plugins.blender.textures; package com.jme3.scene.plugins.blender.textures;
import com.jme3.math.FastMath; import com.jme3.math.FastMath;
import com.jme3.texture.Image.Format;
/** /**
* The data that helps in bytes calculations for the result image. * The data that helps in bytes calculations for the result image.
@ -21,36 +22,33 @@ import com.jme3.math.FastMath;
/** The counter of texel y row. */ /** The counter of texel y row. */
private int yCounter; private int yCounter;
/** The width of the image in pixels. */ /** The width of the image in pixels. */
private int pixelWidth; private int widthInPixels;
/** The height of the image in pixels. */ /** The height of the image in pixels. */
private int pixelHeight; private int heightInPixels;
/** The total texel count. */ /** The total texel count. */
private int xTexelCount; private int xTexelCount;
/** /**
* Constructor. Allocates the required memory. Initializes variables. * Constructor. Allocates memory for data structures.
* *
* @param textelsCount * @param compressedSize
* the total count of the texels * the size of compressed image (or its mipmap)
* @param pixelWidth * @param widthToHeightRatio
* the width of the image in pixels * width/height ratio for the image
* @param pixelHeight * @param format
* the height of the image in pixels * the format of the image
* @param isAlpha
* indicates if the memory for alpha values should be
* allocated
*/ */
public DDSTexelData(int textelsCount, int pixelWidth, int pixelHeight, boolean isAlpha) { public DDSTexelData(int compressedSize, float widthToHeightRatio, Format format) {
textelsCount = pixelWidth * pixelHeight >> 4; int texelsCount = compressedSize * 8 / format.getBitsPerPixel() / 16;
this.colors = new TexturePixel[textelsCount][]; this.colors = new TexturePixel[texelsCount][];
this.indexes = new long[textelsCount]; this.indexes = new long[texelsCount];
this.xTexelCount = pixelWidth >> 2; this.widthInPixels = (int) (0.5f * (float) Math.sqrt(this.getSizeInBytes() / widthToHeightRatio));
this.yCounter = (pixelHeight >> 2) - 1;// xCounter is 0 for now this.heightInPixels = (int) (this.widthInPixels / widthToHeightRatio);
this.pixelHeight = pixelHeight; this.xTexelCount = widthInPixels >> 2;
this.pixelWidth = pixelWidth; this.yCounter = (heightInPixels >> 2) - 1;// xCounter is 0 for now
if (isAlpha) { if (format == Format.DXT3 || format == Format.DXT5) {
this.alphas = new float[textelsCount][]; this.alphas = new float[texelsCount][];
this.alphaIndexes = new long[textelsCount]; this.alphaIndexes = new long[texelsCount];
} }
} }
@ -104,12 +102,15 @@ import com.jme3.math.FastMath;
* the y coordinate of the pixel * the y coordinate of the pixel
* @param result * @param result
* the table where the result is stored * the table where the result is stored
* @return <b>true</b> if the pixel was correctly read and <b>false</b> if
* the position was outside the image sizes
*/ */
public void getRGBA8(int x, int y, byte[] result) { public boolean getRGBA8(int x, int y, byte[] result) {
int xTexetlIndex = x % pixelWidth / 4; int xTexetlIndex = x % widthInPixels / 4;
int yTexelIndex = y % pixelHeight / 4; int yTexelIndex = y % heightInPixels / 4;
int texelIndex = yTexelIndex * xTexelCount + xTexetlIndex; int texelIndex = yTexelIndex * xTexelCount + xTexetlIndex;
if (texelIndex < colors.length) {
TexturePixel[] colors = this.colors[texelIndex]; TexturePixel[] colors = this.colors[texelIndex];
// coordinates of the pixel in the selected texel // coordinates of the pixel in the selected texel
@ -127,5 +128,30 @@ import com.jme3.math.FastMath;
result[1] = (byte) (colors[colorIndex].green * 255.0f); result[1] = (byte) (colors[colorIndex].green * 255.0f);
result[2] = (byte) (colors[colorIndex].blue * 255.0f); result[2] = (byte) (colors[colorIndex].blue * 255.0f);
result[3] = (byte) (alpha * 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;
} }
} }

@ -242,19 +242,28 @@ public class TextureHelper extends AbstractBlenderHelper {
depth = 1; depth = 1;
} }
ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(depth); ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(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) { for (int dataLayerIndex = 0; dataLayerIndex < depth; ++dataLayerIndex) {
ByteBuffer data = image.getData(dataLayerIndex); ByteBuffer data = image.getData(dataLayerIndex);
data.rewind(); 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<DDSTexelData> texelDataList = new ArrayList<DDSTexelData>(sizes.length);
int maxPosition = 0, resultSize = 0;
byte[] bytes = new byte[image.getWidth() * image.getHeight() << 2]; for(int sizeIndex=0;sizeIndex<sizes.length;++sizeIndex) {
DDSTexelData texelData = new DDSTexelData(data.remaining() * 8/format.getBitsPerPixel()/16/*data.remaining() / (format.getBitsPerPixel() << 1)*/, maxPosition += sizes[sizeIndex];
image.getWidth(), image.getHeight(), format != Format.DXT1); DDSTexelData texelData = new DDSTexelData(sizes[sizeIndex], widthToHeightRatio, format);
texelDataList.add(texelData);
switch (format) { switch (format) {
case DXT1:// BC1 case DXT1:// BC1
case DXT1A: case DXT1A:
while (data.hasRemaining()) { while (data.position() < maxPosition) {
TexturePixel[] colors = new TexturePixel[] { new TexturePixel(), new TexturePixel(), new TexturePixel(), new TexturePixel() };
short c0 = data.getShort(); short c0 = data.getShort();
short c1 = data.getShort(); short c1 = data.getShort();
int col0 = RGB565.RGB565_to_ARGB8(c0); int col0 = RGB565.RGB565_to_ARGB8(c0);
@ -287,7 +296,8 @@ public class TextureHelper extends AbstractBlenderHelper {
} }
break; break;
case DXT3:// BC2 case DXT3:// BC2
while (data.hasRemaining()) { while (data.position() < maxPosition) {
TexturePixel[] colors = new TexturePixel[] { new TexturePixel(), new TexturePixel(), new TexturePixel(), new TexturePixel() };
long alpha = data.getLong(); long alpha = data.getLong();
float[] alphas = new float[16]; float[] alphas = new float[16];
long alphasIndex = 0; long alphasIndex = 0;
@ -322,7 +332,8 @@ public class TextureHelper extends AbstractBlenderHelper {
break; break;
case DXT5:// BC3 case DXT5:// BC3
float[] alphas = new float[8]; float[] alphas = new float[8];
while (data.hasRemaining()) { while (data.position() < maxPosition) {
TexturePixel[] colors = new TexturePixel[] { new TexturePixel(), new TexturePixel(), new TexturePixel(), new TexturePixel() };
alphas[0] = data.get() * 255.0f; alphas[0] = data.get() * 255.0f;
alphas[1] = 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; long alphaIndices = data.get() | data.get() << 8 | data.get() << 16 | data.get() << 24 | data.get() << 32 | data.get() << 40;
@ -368,24 +379,34 @@ public class TextureHelper extends AbstractBlenderHelper {
default: default:
throw new IllegalStateException("Unknown compressed format: " + format); 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]; byte[] pixelBytes = new byte[4];
for (int i = 0; i < image.getWidth(); ++i) { for(DDSTexelData texelData : texelDataList) {
for (int j = 0; j < image.getHeight(); ++j) { for (int i = 0; i < texelData.getPixelWidth(); ++i) {
texelData.getRGBA8(i, j, pixelBytes); for (int j = 0; j < texelData.getPixelHeight(); ++j) {
bytes[(j * image.getWidth() + i) * 4] = pixelBytes[0]; if(texelData.getRGBA8(i, j, pixelBytes)) {
bytes[(j * image.getWidth() + i) * 4 + 1] = pixelBytes[1]; bytes[offset + (j * texelData.getPixelWidth() + i) * 4] = pixelBytes[0];
bytes[(j * image.getWidth() + i) * 4 + 2] = pixelBytes[2]; bytes[offset + (j * texelData.getPixelWidth() + i) * 4 + 1] = pixelBytes[1];
bytes[(j * image.getWidth() + i) * 4 + 3] = pixelBytes[3]; 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)); dataArray.add(BufferUtils.createByteBuffer(bytes));
} }
Image result = depth > 1 ? new Image(Format.RGBA8, image.getWidth(), image.getHeight(), depth, dataArray) : 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)); new Image(Format.RGBA8, image.getWidth(), image.getHeight(), dataArray.get(0));
if(image.getMipMapSizes() != null) { if(newMipmapSizes != null) {
result.setMipMapSizes(image.getMipMapSizes().clone()); result.setMipMapSizes(newMipmapSizes);
} }
return result; return result;
} }
@ -500,13 +521,15 @@ public class TextureHelper extends AbstractBlenderHelper {
float gfac = ((Number) tex.getFieldValue("gfac")).floatValue(); float gfac = ((Number) tex.getFieldValue("gfac")).floatValue();
float bfac = ((Number) tex.getFieldValue("bfac")).floatValue(); float bfac = ((Number) tex.getFieldValue("bfac")).floatValue();
float[][] colorBand = new ColorBand(tex, blenderContext).computeValues(); float[][] colorBand = new ColorBand(tex, blenderContext).computeValues();
int depth = image.getDepth() == 0 ? 1 : image.getDepth();
if (colorBand != null) { if (colorBand != null) {
TexturePixel pixel = new TexturePixel(); TexturePixel pixel = new TexturePixel();
PixelInputOutput imageIO = PixelIOFactory.getPixelIO(image.getFormat()); PixelInputOutput imageIO = PixelIOFactory.getPixelIO(image.getFormat());
for (int layerIndex = 0; layerIndex < depth; ++layerIndex) {
for (int x = 0; x < image.getWidth(); ++x) { for (int x = 0; x < image.getWidth(); ++x) {
for (int y = 0; y < image.getHeight(); ++y) { for (int y = 0; y < image.getHeight(); ++y) {
imageIO.read(image, pixel, x, y); imageIO.read(image, layerIndex, pixel, x, y);
int colorbandIndex = (int) (pixel.alpha * 1000.0f); int colorbandIndex = (int) (pixel.alpha * 1000.0f);
pixel.red = colorBand[colorbandIndex][0] * rfac; pixel.red = colorBand[colorbandIndex][0] * rfac;
@ -514,21 +537,24 @@ public class TextureHelper extends AbstractBlenderHelper {
pixel.blue = colorBand[colorbandIndex][2] * bfac; pixel.blue = colorBand[colorbandIndex][2] * bfac;
pixel.alpha = colorBand[colorbandIndex][3]; pixel.alpha = colorBand[colorbandIndex][3];
imageIO.write(image, pixel, x, y); imageIO.write(image, layerIndex, pixel, x, y);
}
} }
} }
} else if (rfac != 1.0f || gfac != 1.0f || bfac != 1.0f) { } else if (rfac != 1.0f || gfac != 1.0f || bfac != 1.0f) {
TexturePixel pixel = new TexturePixel(); TexturePixel pixel = new TexturePixel();
PixelInputOutput imageIO = PixelIOFactory.getPixelIO(image.getFormat()); PixelInputOutput imageIO = PixelIOFactory.getPixelIO(image.getFormat());
for (int layerIndex = 0; layerIndex < depth; ++layerIndex) {
for (int x = 0; x < image.getWidth(); ++x) { for (int x = 0; x < image.getWidth(); ++x) {
for (int y = 0; y < image.getHeight(); ++y) { for (int y = 0; y < image.getHeight(); ++y) {
imageIO.read(image, pixel, x, y); imageIO.read(image, layerIndex, pixel, x, y);
pixel.red *= rfac; pixel.red *= rfac;
pixel.green *= gfac; pixel.green *= gfac;
pixel.blue *= bfac; pixel.blue *= bfac;
imageIO.write(image, pixel, x, y); imageIO.write(image, layerIndex, pixel, x, y);
}
} }
} }
} }

@ -184,10 +184,10 @@ import com.jme3.util.BufferUtils;
for (int x = 0; x < sourceImage.getWidth(); ++x) { for (int x = 0; x < sourceImage.getWidth(); ++x) {
for (int y = 0; y < sourceImage.getHeight(); ++y) { for (int y = 0; y < sourceImage.getHeight(); ++y) {
sourceIO.read(sourceImage, sourcePixel, x, y); sourceIO.read(sourceImage, 0, sourcePixel, x, y);
targetIO.read(targetImage, targetPixel, x, y); targetIO.read(targetImage, 0, targetPixel, x, y);
targetPixel.merge(sourcePixel); 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 x = 0; x < source.getWidth(); ++x) {
for (int y = 0; y < source.getHeight(); ++y) { for (int y = 0; y < source.getHeight(); ++y) {
sourceIO.read(source, pixel, x, y); sourceIO.read(source, 0, pixel, x, y);
targetIO.write(target, pixel, targetXPos + x, targetYPos + 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) { for (int x = minX; x < maxX; ++x) {
int xPos = x >= sourceImage.getWidth() ? x - sourceImage.getWidth() : x; int xPos = x >= sourceImage.getWidth() ? x - sourceImage.getWidth() : x;
int yPos = y >= sourceImage.getHeight() ? y - sourceImage.getHeight() : y; 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.getR8());
data.put(pixel.getG8()); data.put(pixel.getG8());
data.put(pixel.getB8()); data.put(pixel.getB8());
@ -542,7 +542,7 @@ import com.jme3.util.BufferUtils;
for (int y = 0; y < imageHeight; ++y) { for (int y = 0; y < imageHeight; ++y) {
this.toTextureUV(boundingBox, point, uvs); this.toTextureUV(boundingBox, point, uvs);
texture.getPixel(pixel, uvs[0], uvs[1], uvs[2]); 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); point.addLocal(hDelta);
} }

@ -2,8 +2,11 @@ package com.jme3.scene.plugins.blender.textures.blending;
import java.util.logging.Logger; import java.util.logging.Logger;
import jme3tools.converters.MipMapGenerator;
import com.jme3.scene.plugins.blender.BlenderContext; import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.materials.MaterialHelper; 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 * 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()); 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);
}
}
} }

@ -40,6 +40,8 @@ public class TextureBlenderAWT extends AbstractTextureBlender {
} }
public Image blend(Image image, Image baseImage, BlenderContext blenderContext) { 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 }; float[] pixelColor = new float[] { color[0], color[1], color[2], 1.0f };
Format format = image.getFormat(); Format format = image.getFormat();
@ -70,12 +72,12 @@ public class TextureBlenderAWT extends AbstractTextureBlender {
while (index < data.limit()) { while (index < data.limit()) {
//getting the proper material color if the base texture is applied //getting the proper material color if the base texture is applied
if(basePixelIO != null) { if(basePixelIO != null) {
basePixelIO.read(baseImage, basePixel, x, y); basePixelIO.read(baseImage, dataLayerIndex, basePixel, x, y);
basePixel.toRGBA(materialColor); basePixel.toRGBA(materialColor);
} }
//reading the current texture's pixel //reading the current texture's pixel
pixelReader.read(image, pixel, index); pixelReader.read(image, dataLayerIndex, pixel, index);
index += image.getFormat().getBitsPerPixel() >> 3; index += image.getFormat().getBitsPerPixel() >> 3;
pixel.toRGBA(pixelColor); pixel.toRGBA(pixelColor);
if (negateTexture) { if (negateTexture) {

@ -28,6 +28,8 @@ public class TextureBlenderDDS extends TextureBlenderAWT {
@Override @Override
public Image blend(Image image, Image baseImage, BlenderContext blenderContext) { public Image blend(Image image, Image baseImage, BlenderContext blenderContext) {
this.prepareImagesForBlending(image, baseImage);
Format format = image.getFormat(); Format format = image.getFormat();
int width = image.getWidth(); int width = image.getWidth();
int height = image.getHeight(); int height = image.getHeight();
@ -55,7 +57,6 @@ public class TextureBlenderDDS extends TextureBlenderAWT {
ByteBuffer data = image.getData(dataLayerIndex); ByteBuffer data = image.getData(dataLayerIndex);
data.rewind(); data.rewind();
ByteBuffer newData = BufferUtils.createByteBuffer(data.remaining()); ByteBuffer newData = BufferUtils.createByteBuffer(data.remaining());
System.out.println(dataLayerIndex);
while (data.hasRemaining()) { while (data.hasRemaining()) {
if(format == Format.DXT3) { if(format == Format.DXT3) {
long alpha = data.getLong(); 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 //compressing 16 pixels from the base texture as if they belonged to a texel
if(baseImage != null) { if(baseImage != null) {
//reading pixels (first and last of the 16 colors array) //reading pixels (first and last of the 16 colors array)
basePixelIO.read(baseImage, baseTextureColors[0], baseXTexelIndex << 2, baseYTexelIndex << 2);//first pixel basePixelIO.read(baseImage, dataLayerIndex, 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[1], baseXTexelIndex << 2 + 4, baseYTexelIndex << 2 + 4);//last pixel
baseTextureColors[0].toRGBA(compressedMaterialColor[0]); baseTextureColors[0].toRGBA(compressedMaterialColor[0]);
baseTextureColors[1].toRGBA(compressedMaterialColor[1]); baseTextureColors[1].toRGBA(compressedMaterialColor[1]);
} }

@ -34,8 +34,9 @@ public class TextureBlenderLuminance extends AbstractTextureBlender {
} }
public Image blend(Image image, Image baseImage, BlenderContext blenderContext) { public Image blend(Image image, Image baseImage, BlenderContext blenderContext) {
Format format = image.getFormat(); this.prepareImagesForBlending(image, baseImage);
Format format = image.getFormat();
PixelInputOutput basePixelIO = null; PixelInputOutput basePixelIO = null;
TexturePixel basePixel = null; TexturePixel basePixel = null;
float[] materialColor = this.materialColor; float[] materialColor = this.materialColor;
@ -64,7 +65,7 @@ public class TextureBlenderLuminance extends AbstractTextureBlender {
while (data.hasRemaining()) { while (data.hasRemaining()) {
//getting the proper material color if the base texture is applied //getting the proper material color if the base texture is applied
if(basePixelIO != null) { if(basePixelIO != null) {
basePixelIO.read(baseImage, basePixel, x, y); basePixelIO.read(baseImage, dataLayerIndex, basePixel, x, y);
basePixel.toRGBA(materialColor); basePixel.toRGBA(materialColor);
} }

@ -1,5 +1,7 @@
package com.jme3.scene.plugins.blender.textures.io; package com.jme3.scene.plugins.blender.textures.io;
import java.nio.ByteBuffer;
import com.jme3.scene.plugins.blender.textures.TexturePixel; import com.jme3.scene.plugins.blender.textures.TexturePixel;
import com.jme3.texture.Image; import com.jme3.texture.Image;
@ -8,25 +10,26 @@ import com.jme3.texture.Image;
* @author Marcin Roguski (Kaelthas) * @author Marcin Roguski (Kaelthas)
*/ */
/*package*/ class AWTPixelInputOutput implements PixelInputOutput { /*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; byte r,g,b,a;
ByteBuffer data = image.getData(layer);
switch(image.getFormat()) {//TODO: add other formats switch(image.getFormat()) {//TODO: add other formats
case RGBA8: case RGBA8:
r = image.getData(0).get(index); r = data.get(index);
g = image.getData(0).get(index + 1); g = data.get(index + 1);
b = image.getData(0).get(index + 2); b = data.get(index + 2);
a = image.getData(0).get(index + 3); a = data.get(index + 3);
break; break;
case ABGR8: case ABGR8:
a = image.getData(0).get(index); a = data.get(index);
b = image.getData(0).get(index + 1); b = data.get(index + 1);
g = image.getData(0).get(index + 2); g = data.get(index + 2);
r = image.getData(0).get(index + 3); r = data.get(index + 3);
break; break;
case BGR8: case BGR8:
b = image.getData(0).get(index); b = data.get(index);
g = image.getData(0).get(index + 1); g = data.get(index + 1);
r = image.getData(0).get(index + 2); r = data.get(index + 2);
a = (byte)0xFF; a = (byte)0xFF;
break; break;
default: default:
@ -35,37 +38,38 @@ import com.jme3.texture.Image;
pixel.fromARGB8(a, r, g, b); 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); 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()) { switch(image.getFormat()) {
case RGBA8: case RGBA8:
image.getData(0).put(index, pixel.getR8()); data.put(index, pixel.getR8());
image.getData(0).put(index + 1, pixel.getG8()); data.put(index + 1, pixel.getG8());
image.getData(0).put(index + 2, pixel.getB8()); data.put(index + 2, pixel.getB8());
image.getData(0).put(index + 3, pixel.getA8()); data.put(index + 3, pixel.getA8());
break; break;
case ABGR8: case ABGR8:
image.getData(0).put(index, pixel.getA8()); data.put(index, pixel.getA8());
image.getData(0).put(index + 1, pixel.getB8()); data.put(index + 1, pixel.getB8());
image.getData(0).put(index + 2, pixel.getG8()); data.put(index + 2, pixel.getG8());
image.getData(0).put(index + 3, pixel.getR8()); data.put(index + 3, pixel.getR8());
break; break;
case BGR8: case BGR8:
image.getData(0).put(index, pixel.getB8()); data.put(index, pixel.getB8());
image.getData(0).put(index + 1, pixel.getG8()); data.put(index + 1, pixel.getG8());
image.getData(0).put(index + 2, pixel.getR8()); data.put(index + 2, pixel.getR8());
break; break;
default: default:
throw new IllegalStateException("Unknown image format: " + image.getFormat()); 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); int index = (y * image.getWidth() + x) * (image.getFormat().getBitsPerPixel() >> 3);
this.write(image, pixel, index); this.write(image, layer, pixel, index);
} }
} }

@ -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. * 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) { public void read(Image image, int layer, TexturePixel pixel, int index) {
this.read(image, pixel, index % image.getWidth(), index / image.getWidth()); 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 xTexetlIndex = x % image.getWidth() >> 2;
int yTexelIndex = y % image.getHeight() >> 2; int yTexelIndex = y % image.getHeight() >> 2;
int xTexelCount = image.getWidth() >> 2; int xTexelCount = image.getWidth() >> 2;
@ -31,7 +31,7 @@ import com.jme3.texture.Image;
int indexes = 0; int indexes = 0;
long alphaIndexes = 0; long alphaIndexes = 0;
float[] alphas = null; float[] alphas = null;
ByteBuffer data = image.getData().get(0); ByteBuffer data = image.getData().get(layer);
switch (image.getFormat()) { switch (image.getFormat()) {
case DXT1: // BC1 case DXT1: // BC1
@ -162,11 +162,11 @@ import com.jme3.texture.Image;
pixel.alpha = alpha; 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!"); 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!"); throw new UnsupportedOperationException("Writing to DDS texture pixel by pixel is not yet supported!");
} }
} }

@ -8,22 +8,22 @@ import com.jme3.texture.Image;
* @author Marcin Roguski (Kaelthas) * @author Marcin Roguski (Kaelthas)
*/ */
/*package*/ class LuminancePixelInputOutput implements PixelInputOutput { /*package*/ class LuminancePixelInputOutput implements PixelInputOutput {
public void read(Image image, TexturePixel pixel, int index) { public void read(Image image, int layer, TexturePixel pixel, int index) {
byte intensity = image.getData(0).get(index); byte intensity = image.getData(layer).get(index);
pixel.fromIntensity(intensity); 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; 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) { public void write(Image image, int layer, TexturePixel pixel, int index) {
image.getData(0).put(index, pixel.getInt()); 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; int index = y * image.getWidth() + x;
this.write(image, pixel, index); this.write(image, layer,pixel, index);
} }
} }

@ -19,7 +19,7 @@ public interface PixelInputOutput {
* @param index * @param index
* the index where the pixel begins in the image data * 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 * This method reads a pixel that is located at the given position on the
@ -34,7 +34,7 @@ public interface PixelInputOutput {
* @param y * @param y
* the Y coordinate of the pixel * 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. * This method writes a pixel that starts at the given index.
@ -46,7 +46,7 @@ public interface PixelInputOutput {
* @param index * @param index
* the index where the pixel begins in the image data * 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 * This method writes a pixel that is located at the given position on the
@ -61,5 +61,5 @@ public interface PixelInputOutput {
* @param y * @param y
* the Y coordinate of the pixel * 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);
} }

Loading…
Cancel
Save