Added support for multilayered images.

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9336 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
Kae..pl 13 years ago
parent 96cfd22510
commit b09e37c9d9
  1. 42
      engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureHelper.java
  2. 19
      engine/src/blender/com/jme3/scene/plugins/blender/textures/blending/TextureBlenderAWT.java
  3. 50
      engine/src/blender/com/jme3/scene/plugins/blender/textures/blending/TextureBlenderDDS.java
  4. 21
      engine/src/blender/com/jme3/scene/plugins/blender/textures/blending/TextureBlenderLuminance.java
  5. 5
      engine/src/blender/com/jme3/scene/plugins/blender/textures/io/DDSPixelInputOutput.java

@ -236,17 +236,24 @@ public class TextureHelper extends AbstractBlenderHelper {
* @return the decompressed image
*/
public Image decompress(Image image) {
byte[] bytes = null;
TexturePixel[] colors = null;
ByteBuffer data = image.getData(0);// TODO: support decompression of all data 'layers'
data.rewind();
Format format = image.getFormat();
int depth = image.getDepth();
if(depth == 0) {
depth = 1;
}
ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(depth);
TexturePixel[] colors = new TexturePixel[] { new TexturePixel(), new TexturePixel(), new TexturePixel(), new TexturePixel() };
for (int dataLayerIndex = 0; dataLayerIndex < depth; ++dataLayerIndex) {
ByteBuffer data = image.getData(dataLayerIndex);
data.rewind();
DDSTexelData texelData = new DDSTexelData(data.remaining() / (format.getBitsPerPixel() * 2), image.getWidth(), image.getHeight(), format != Format.DXT1);
switch (format) {// TODO: DXT1A
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
bytes = new byte[image.getWidth() * image.getHeight() * 4];
colors = new TexturePixel[] { new TexturePixel(), new TexturePixel(), new TexturePixel(), new TexturePixel() };
case DXT1A:
while (data.hasRemaining()) {
short c0 = data.getShort();
short c1 = data.getShort();
@ -280,8 +287,6 @@ public class TextureHelper extends AbstractBlenderHelper {
}
break;
case DXT3:// BC2
bytes = new byte[image.getWidth() * image.getHeight() * 4];
colors = new TexturePixel[] { new TexturePixel(), new TexturePixel(), new TexturePixel(), new TexturePixel() };
while (data.hasRemaining()) {
long alpha = data.getLong();
float[] alphas = new float[16];
@ -316,8 +321,6 @@ public class TextureHelper extends AbstractBlenderHelper {
}
break;
case DXT5:// BC3
bytes = new byte[image.getWidth() * image.getHeight() * 4];
colors = new TexturePixel[] { new TexturePixel(), new TexturePixel(), new TexturePixel(), new TexturePixel() };
float[] alphas = new float[8];
while (data.hasRemaining()) {
alphas[0] = data.get() * 255.0f;
@ -363,10 +366,9 @@ public class TextureHelper extends AbstractBlenderHelper {
}
break;
default:
LOGGER.fine("Unsupported decompression format.");
throw new IllegalStateException("Unknown compressed format: " + format);
}
if (bytes != null) {// writing the data to the result table
byte[] pixelBytes = new byte[4];
for (int i = 0; i < image.getWidth(); ++i) {
for (int j = 0; j < image.getHeight(); ++j) {
@ -377,11 +379,15 @@ public class TextureHelper extends AbstractBlenderHelper {
bytes[(j * image.getWidth() + i) * 4 + 3] = pixelBytes[3];
}
}
// TODO: think of other image formats (ie. RGB if the texture has no
// alpha values)
return new Image(Format.RGBA8, image.getWidth(), image.getHeight(), BufferUtils.createByteBuffer(bytes));
dataArray.add(BufferUtils.createByteBuffer(bytes));
}
return image;
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());
}
return result;
}
/**

@ -42,7 +42,6 @@ public class TextureBlenderAWT extends AbstractTextureBlender {
public Image blend(Image image, Image baseImage, BlenderContext blenderContext) {
float[] pixelColor = new float[] { color[0], color[1], color[2], 1.0f };
Format format = image.getFormat();
ByteBuffer data = image.getData(0);
PixelInputOutput basePixelIO = null, pixelReader = PixelIOFactory.getPixelIO(format);
TexturePixel basePixel = null, pixel = new TexturePixel();
@ -59,9 +58,14 @@ public class TextureBlenderAWT extends AbstractTextureBlender {
if (depth == 0) {
depth = 1;
}
ByteBuffer newData = BufferUtils.createByteBuffer(width * height * depth * 4);
ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(depth);
float[] resultPixel = new float[4];
for (int dataLayerIndex = 0; dataLayerIndex < depth; ++dataLayerIndex) {
ByteBuffer data = image.getData(dataLayerIndex);
data.rewind();
ByteBuffer newData = BufferUtils.createByteBuffer(width * height * 4);
int dataIndex = 0, x = 0, y = 0, index = 0;
while (index < data.limit()) {
//getting the proper material color if the base texture is applied
@ -90,13 +94,14 @@ public class TextureBlenderAWT extends AbstractTextureBlender {
++y;
}
}
if(depth > 1) {
ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(1);
dataArray.add(newData);
return new Image(Format.RGBA8, width, height, depth, dataArray);
} else {
return new Image(Format.RGBA8, width, height, newData);
}
Image result = depth > 1 ? new Image(Format.RGBA8, width, height, depth, dataArray) : new Image(Format.RGBA8, width, height, dataArray.get(0));
if(image.getMipMapSizes() != null) {
result.setMipMapSizes(image.getMipMapSizes().clone());
}
return result;
}
/**

@ -2,8 +2,6 @@ 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;
@ -18,15 +16,12 @@ import com.jme3.util.BufferUtils;
/**
* The class that is responsible for blending the following texture types:
* <li> DXT1
* <li> DXT1A
* <li> DXT3
* <li> DXT5
* Not yet supported (but will be):
* <li> DXT1A:
* @author Marcin Roguski (Kaelthas)
*/
public class TextureBlenderDDS extends TextureBlenderAWT {
private static final Logger LOGGER = Logger.getLogger(TextureBlenderDDS.class.getName());
public TextureBlenderDDS(int flag, boolean negateTexture, int blendType, float[] materialColor, float[] color, float blendFactor) {
super(flag, negateTexture, blendType, materialColor, color, blendFactor);
}
@ -34,16 +29,13 @@ public class TextureBlenderDDS extends TextureBlenderAWT {
@Override
public Image blend(Image image, Image baseImage, BlenderContext blenderContext) {
Format format = image.getFormat();
ByteBuffer data = image.getData(0);
data.rewind();
int width = image.getWidth();
int height = image.getHeight();
int depth = image.getDepth();
if (depth == 0) {
depth = 1;
}
ByteBuffer newData = BufferUtils.createByteBuffer(data.remaining());
ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(depth);
PixelInputOutput basePixelIO = null;
float[][] compressedMaterialColor = null;
@ -57,13 +49,14 @@ public class TextureBlenderDDS extends TextureBlenderAWT {
float[] resultPixel = new float[4];
float[] pixelColor = new float[4];
TexturePixel[] colors = new TexturePixel[] { new TexturePixel(), new TexturePixel() };
int dataIndex = 0, baseXTexelIndex = 0, baseYTexelIndex = 0;
int baseXTexelIndex = 0, baseYTexelIndex = 0;
float[] alphas = new float[] {1, 1};
for (int dataLayerIndex = 0; dataLayerIndex < depth; ++dataLayerIndex) {
ByteBuffer data = image.getData(dataLayerIndex);
data.rewind();
ByteBuffer newData = BufferUtils.createByteBuffer(data.remaining());
System.out.println(dataLayerIndex);
while (data.hasRemaining()) {
if(format == Format.DXT1A) {
LOGGER.log(Level.WARNING, "Image type not yet supported for blending: {0}", format);
break;
}
if(format == Format.DXT3) {
long alpha = data.getLong();
//get alpha for first and last pixel that is compressed in the texel
@ -71,16 +64,17 @@ public class TextureBlenderDDS extends TextureBlenderAWT {
byte alpha1 = (byte)(alpha >> 60 & 0xFF);
alphas[0] = alpha0 >= 0 ? alpha0 / 255.0f : 1.0f - ~alpha0 / 255.0f;
alphas[1] = alpha1 >= 0 ? alpha1 / 255.0f : 1.0f - ~alpha1 / 255.0f;
dataIndex += 8;
newData.putLong(alpha);
} else if(format == Format.DXT5) {
byte alpha0 = data.get();
byte alpha1 = data.get();
alphas[0] = alpha0 >= 0 ? alpha0 / 255.0f : 1.0f - ~alpha0 / 255.0f;
alphas[1] = alpha1 >= 0 ? alpha0 / 255.0f : 1.0f - ~alpha0 / 255.0f;
newData.put(alpha0);
newData.put(alpha1);
//only read the next 6 bytes (these are alpha indexes)
data.getInt();
data.getShort();
dataIndex += 8;
newData.putInt(data.getInt());
newData.putShort(data.getShort());
}
int col0 = RGB565.RGB565_to_ARGB8(data.getShort());
int col1 = RGB565.RGB565_to_ARGB8(data.getShort());
@ -107,13 +101,11 @@ public class TextureBlenderDDS extends TextureBlenderAWT {
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;
newData.putShort(rgb565);
}
// just copy the remaining 4 bytes of the current texel
newData.putInt(dataIndex, data.getInt());
dataIndex += 4;
newData.putInt(data.getInt());
++baseXTexelIndex;
if(baseXTexelIndex > image.getWidth() >> 2) {
@ -121,13 +113,13 @@ public class TextureBlenderDDS extends TextureBlenderAWT {
++baseYTexelIndex;
}
}
if(depth > 1) {
ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(1);
dataArray.add(newData);
return new Image(format, width, height, depth, dataArray);
} else {
return new Image(format, width, height, newData);
}
Image result = dataArray.size() > 1 ? new Image(format, width, height, depth, dataArray) : new Image(format, width, height, dataArray.get(0));
if(image.getMipMapSizes() != null) {
result.setMipMapSizes(image.getMipMapSizes().clone());
}
return result;
}
}

@ -35,8 +35,6 @@ public class TextureBlenderLuminance extends AbstractTextureBlender {
public Image blend(Image image, Image baseImage, BlenderContext blenderContext) {
Format format = image.getFormat();
ByteBuffer data = image.getData(0);
data.rewind();
PixelInputOutput basePixelIO = null;
TexturePixel basePixel = null;
@ -53,10 +51,15 @@ public class TextureBlenderLuminance extends AbstractTextureBlender {
if (depth == 0) {
depth = 1;
}
ByteBuffer newData = BufferUtils.createByteBuffer(width * height * depth * 4);
ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(depth);
float[] resultPixel = new float[4];
float[] tinAndAlpha = new float[2];
for (int dataLayerIndex = 0; dataLayerIndex < depth; ++dataLayerIndex) {
ByteBuffer data = image.getData(dataLayerIndex);
data.rewind();
ByteBuffer newData = BufferUtils.createByteBuffer(width * height * 4);
int dataIndex = 0, x = 0, y = 0;
while (data.hasRemaining()) {
//getting the proper material color if the base texture is applied
@ -78,14 +81,14 @@ public class TextureBlenderLuminance extends AbstractTextureBlender {
++y;
}
}
if(depth > 1) {
ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(1);
dataArray.add(newData);
return new Image(Format.RGBA8, width, height, depth, dataArray);
} else {
return new Image(Format.RGBA8, width, height, newData);
}
Image result = depth > 1 ? new Image(Format.RGBA8, width, height, depth, dataArray) : new Image(Format.RGBA8, width, height, dataArray.get(0));
if(image.getMipMapSizes() != null) {
result.setMipMapSizes(image.getMipMapSizes().clone());
}
return result;
}
/**

@ -34,7 +34,8 @@ import com.jme3.texture.Image;
ByteBuffer data = image.getData().get(0);
switch (image.getFormat()) {
case DXT1: {// BC1
case DXT1: // BC1
case DXT1A:{
data.position(texelIndex * 8);
short c0 = data.getShort();
short c1 = data.getShort();
@ -142,8 +143,6 @@ import com.jme3.texture.Image;
indexes = data.getInt();// 4-byte table with color indexes in decompressed table
break;
}
case DXT1A://TODO: implement
break;
default:
throw new IllegalStateException("Unsupported decompression format.");
}

Loading…
Cancel
Save