Added support for multilayered images.
git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9336 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
This commit is contained in:
		
							parent
							
								
									96cfd22510
								
							
						
					
					
						commit
						b09e37c9d9
					
				| @ -236,26 +236,74 @@ 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() }; | ||||
| 		 | ||||
| 		DDSTexelData texelData = new DDSTexelData(data.remaining() / (format.getBitsPerPixel() * 2), image.getWidth(), image.getHeight(), format != Format.DXT1); | ||||
| 		switch (format) {// TODO: DXT1A | ||||
| 			case DXT1:// BC1 | ||||
| 				bytes = new byte[image.getWidth() * image.getHeight() * 4]; | ||||
| 				colors = new TexturePixel[] { new TexturePixel(), new TexturePixel(), new TexturePixel(), new TexturePixel() }; | ||||
| 				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); | ||||
| 		for (int dataLayerIndex = 0; dataLayerIndex < depth; ++dataLayerIndex) { | ||||
| 			ByteBuffer data = image.getData(dataLayerIndex); | ||||
| 			data.rewind(); | ||||
| 			 | ||||
| 			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) { | ||||
| 							// 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.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; | ||||
| 						} | ||||
| 
 | ||||
| 						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); | ||||
| @ -267,106 +315,60 @@ 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.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; | ||||
| 						} | ||||
| 
 | ||||
| 						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 | ||||
| 				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]; | ||||
| 					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); | ||||
| 
 | ||||
| 						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); | ||||
| 			} | ||||
| 
 | ||||
| 					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 | ||||
| 				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; | ||||
| 					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].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: | ||||
| 				LOGGER.fine("Unsupported decompression 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,44 +58,50 @@ 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]; | ||||
| 		int dataIndex = 0, x = 0, y = 0, index = 0; | ||||
| 		while (index < data.limit()) { | ||||
| 			//getting the proper material color if the base texture is applied | ||||
| 			if(basePixelIO != null) { | ||||
| 				basePixelIO.read(baseImage, basePixel, x, y); | ||||
| 				basePixel.toRGBA(materialColor); | ||||
| 			}			 | ||||
| 		for (int dataLayerIndex = 0; dataLayerIndex < depth; ++dataLayerIndex) { | ||||
| 			ByteBuffer data = image.getData(dataLayerIndex); | ||||
| 			data.rewind(); | ||||
| 			ByteBuffer newData = BufferUtils.createByteBuffer(width * height * 4); | ||||
| 			 | ||||
| 			//reading the current texture's pixel | ||||
| 			pixelReader.read(image, pixel, index); | ||||
| 			index += image.getFormat().getBitsPerPixel() >> 3; | ||||
| 			pixel.toRGBA(pixelColor); | ||||
| 			if (negateTexture) { | ||||
| 				pixel.negate(); | ||||
| 			} | ||||
| 			int dataIndex = 0, x = 0, y = 0, index = 0; | ||||
| 			while (index < data.limit()) { | ||||
| 				//getting the proper material color if the base texture is applied | ||||
| 				if(basePixelIO != null) { | ||||
| 					basePixelIO.read(baseImage, basePixel, x, y); | ||||
| 					basePixel.toRGBA(materialColor); | ||||
| 				}			 | ||||
| 				 | ||||
| 			this.blendPixel(resultPixel, materialColor, pixelColor, blenderContext); | ||||
| 			newData.put(dataIndex++, (byte) (resultPixel[0] * 255.0f)); | ||||
| 			newData.put(dataIndex++, (byte) (resultPixel[1] * 255.0f)); | ||||
| 			newData.put(dataIndex++, (byte) (resultPixel[2] * 255.0f)); | ||||
| 			newData.put(dataIndex++, (byte) (pixelColor[3] * 255.0f)); | ||||
| 				//reading the current texture's pixel | ||||
| 				pixelReader.read(image, pixel, index); | ||||
| 				index += image.getFormat().getBitsPerPixel() >> 3; | ||||
| 				pixel.toRGBA(pixelColor); | ||||
| 				if (negateTexture) { | ||||
| 					pixel.negate(); | ||||
| 				} | ||||
| 				 | ||||
| 			++x; | ||||
| 			if(x >= width) { | ||||
| 				x = 0; | ||||
| 				++y; | ||||
| 				this.blendPixel(resultPixel, materialColor, pixelColor, blenderContext); | ||||
| 				newData.put(dataIndex++, (byte) (resultPixel[0] * 255.0f)); | ||||
| 				newData.put(dataIndex++, (byte) (resultPixel[1] * 255.0f)); | ||||
| 				newData.put(dataIndex++, (byte) (resultPixel[2] * 255.0f)); | ||||
| 				newData.put(dataIndex++, (byte) (pixelColor[3] * 255.0f)); | ||||
| 				 | ||||
| 				++x; | ||||
| 				if(x >= width) { | ||||
| 					x = 0; | ||||
| 					++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,77 +49,77 @@ 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}; | ||||
| 		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 | ||||
| 				byte alpha0 = (byte)(alpha << 4 & 0xFF); | ||||
| 				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; | ||||
| 			} 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; | ||||
| 				//only read the next 6 bytes (these are alpha indexes) | ||||
| 				data.getInt(); | ||||
| 				data.getShort(); | ||||
| 				dataIndex += 8; | ||||
| 			} | ||||
| 			int col0 = RGB565.RGB565_to_ARGB8(data.getShort()); | ||||
| 			int col1 = RGB565.RGB565_to_ARGB8(data.getShort()); | ||||
| 			colors[0].fromARGB8(col0); | ||||
| 			colors[1].fromARGB8(col1); | ||||
| 			 | ||||
| 			//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 | ||||
| 				baseTextureColors[0].toRGBA(compressedMaterialColor[0]); | ||||
| 				baseTextureColors[1].toRGBA(compressedMaterialColor[1]); | ||||
| 			} | ||||
| 
 | ||||
| 			// blending colors | ||||
| 			for (int i = 0; i < colors.length; ++i) { | ||||
| 				if (negateTexture) { | ||||
| 					colors[i].negate(); | ||||
| 		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.DXT3) { | ||||
| 					long alpha = data.getLong(); | ||||
| 					//get alpha for first and last pixel that is compressed in the texel | ||||
| 					byte alpha0 = (byte)(alpha << 4 & 0xFF); | ||||
| 					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; | ||||
| 					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) | ||||
| 					newData.putInt(data.getInt()); | ||||
| 					newData.putShort(data.getShort()); | ||||
| 				} | ||||
| 				int col0 = RGB565.RGB565_to_ARGB8(data.getShort()); | ||||
| 				int col1 = RGB565.RGB565_to_ARGB8(data.getShort()); | ||||
| 				colors[0].fromARGB8(col0); | ||||
| 				colors[1].fromARGB8(col1); | ||||
| 				 | ||||
| 				//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 | ||||
| 					baseTextureColors[0].toRGBA(compressedMaterialColor[0]); | ||||
| 					baseTextureColors[1].toRGBA(compressedMaterialColor[1]); | ||||
| 				} | ||||
| 
 | ||||
| 				// blending colors | ||||
| 				for (int i = 0; i < colors.length; ++i) { | ||||
| 					if (negateTexture) { | ||||
| 						colors[i].negate(); | ||||
| 					} | ||||
| 					colors[i].toRGBA(pixelColor); | ||||
| 					pixelColor[3] = alphas[i]; | ||||
| 					this.blendPixel(resultPixel, compressedMaterialColor != null ? compressedMaterialColor[i] : materialColor, pixelColor, blenderContext); | ||||
| 					colors[i].fromARGB8(1, resultPixel[0], resultPixel[1], resultPixel[2]); | ||||
| 					int argb8 = colors[i].toARGB8(); | ||||
| 					short rgb565 = RGB565.ARGB8_to_RGB565(argb8); | ||||
| 					newData.putShort(rgb565); | ||||
| 				} | ||||
| 
 | ||||
| 				// just copy the remaining 4 bytes of the current texel | ||||
| 				newData.putInt(data.getInt()); | ||||
| 				 | ||||
| 				++baseXTexelIndex; | ||||
| 				if(baseXTexelIndex > image.getWidth() >> 2) { | ||||
| 					baseXTexelIndex = 0; | ||||
| 					++baseYTexelIndex; | ||||
| 				} | ||||
| 				colors[i].toRGBA(pixelColor); | ||||
| 				pixelColor[3] = alphas[i]; | ||||
| 				this.blendPixel(resultPixel, compressedMaterialColor != null ? compressedMaterialColor[i] : materialColor, pixelColor, blenderContext); | ||||
| 				colors[i].fromARGB8(1, resultPixel[0], resultPixel[1], resultPixel[2]); | ||||
| 				int argb8 = colors[i].toARGB8(); | ||||
| 				short rgb565 = RGB565.ARGB8_to_RGB565(argb8); | ||||
| 				newData.putShort(dataIndex, rgb565); | ||||
| 				dataIndex += 2; | ||||
| 			} | ||||
| 
 | ||||
| 			// just copy the remaining 4 bytes of the current texel | ||||
| 			newData.putInt(dataIndex, data.getInt()); | ||||
| 			dataIndex += 4; | ||||
| 			 | ||||
| 			++baseXTexelIndex; | ||||
| 			if(baseXTexelIndex > image.getWidth() >> 2) { | ||||
| 				baseXTexelIndex = 0; | ||||
| 				++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,39 +51,44 @@ 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]; | ||||
| 		int dataIndex = 0, x = 0, y = 0; | ||||
| 		while (data.hasRemaining()) { | ||||
| 			//getting the proper material color if the base texture is applied | ||||
| 			if(basePixelIO != null) { | ||||
| 				basePixelIO.read(baseImage, basePixel, x, y); | ||||
| 				basePixel.toRGBA(materialColor); | ||||
| 		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 | ||||
| 				if(basePixelIO != null) { | ||||
| 					basePixelIO.read(baseImage, basePixel, x, y); | ||||
| 					basePixel.toRGBA(materialColor); | ||||
| 				} | ||||
| 				 | ||||
| 				this.getTinAndAlpha(data, format, negateTexture, tinAndAlpha); | ||||
| 				this.blendPixel(resultPixel, materialColor, color, tinAndAlpha[0], blendFactor, blendType, blenderContext); | ||||
| 				newData.put(dataIndex++, (byte) (resultPixel[0] * 255.0f)); | ||||
| 				newData.put(dataIndex++, (byte) (resultPixel[1] * 255.0f)); | ||||
| 				newData.put(dataIndex++, (byte) (resultPixel[2] * 255.0f)); | ||||
| 				newData.put(dataIndex++, (byte) (tinAndAlpha[1] * 255.0f)); | ||||
| 				 | ||||
| 				++x; | ||||
| 				if(x >= width) { | ||||
| 					x = 0; | ||||
| 					++y; | ||||
| 				} | ||||
| 			} | ||||
| 			 | ||||
| 			this.getTinAndAlpha(data, format, negateTexture, tinAndAlpha); | ||||
| 			this.blendPixel(resultPixel, materialColor, color, tinAndAlpha[0], blendFactor, blendType, blenderContext); | ||||
| 			newData.put(dataIndex++, (byte) (resultPixel[0] * 255.0f)); | ||||
| 			newData.put(dataIndex++, (byte) (resultPixel[1] * 255.0f)); | ||||
| 			newData.put(dataIndex++, (byte) (resultPixel[2] * 255.0f)); | ||||
| 			newData.put(dataIndex++, (byte) (tinAndAlpha[1] * 255.0f)); | ||||
| 			 | ||||
| 			++x; | ||||
| 			if(x >= width) { | ||||
| 				x = 0; | ||||
| 				++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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user