|
@@ -242,27 +242,78 @@ public class TextureHelper extends AbstractBlenderHelper {
|
|
|
depth = 1;
|
|
|
}
|
|
|
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) {
|
|
|
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<DDSTexelData> texelDataList = new ArrayList<DDSTexelData>(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<sizes.length;++sizeIndex) {
|
|
|
+ maxPosition += sizes[sizeIndex];
|
|
|
+ DDSTexelData texelData = new DDSTexelData(sizes[sizeIndex], widthToHeightRatio, format);
|
|
|
+ texelDataList.add(texelData);
|
|
|
+ switch (format) {
|
|
|
+ case DXT1:// BC1
|
|
|
+ case DXT1A:
|
|
|
+ while (data.position() < maxPosition) {
|
|
|
+ TexturePixel[] colors = new TexturePixel[] { new TexturePixel(), new TexturePixel(), new TexturePixel(), new TexturePixel() };
|
|
|
+ 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) {
|
|
|
+ // 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);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|