Home | History | Annotate | Download | only in blending
      1 package com.jme3.scene.plugins.blender.textures.blending;
      2 
      3 import java.nio.ByteBuffer;
      4 import java.util.ArrayList;
      5 import java.util.logging.Level;
      6 import java.util.logging.Logger;
      7 
      8 import jme3tools.converters.RGB565;
      9 
     10 import com.jme3.scene.plugins.blender.BlenderContext;
     11 import com.jme3.scene.plugins.blender.textures.TexturePixel;
     12 import com.jme3.texture.Image;
     13 import com.jme3.texture.Image.Format;
     14 import com.jme3.texture.Texture;
     15 import com.jme3.texture.Texture2D;
     16 import com.jme3.texture.Texture3D;
     17 import com.jme3.util.BufferUtils;
     18 
     19 /**
     20  * The class that is responsible for blending the following texture types:
     21  * <li> DXT1
     22  * <li> DXT3
     23  * <li> DXT5
     24  * Not yet supported (but will be):
     25  * <li> DXT1A:
     26  * @author Marcin Roguski (Kaelthas)
     27  */
     28 public class TextureBlenderDDS extends AbstractTextureBlender {
     29 	private static final Logger	LOGGER	= Logger.getLogger(TextureBlenderDDS.class.getName());
     30 
     31 	@Override
     32 	public Texture blend(float[] materialColor, Texture texture, float[] color, float affectFactor, int blendType, boolean neg, BlenderContext blenderContext) {
     33 		Format format = texture.getImage().getFormat();
     34 		ByteBuffer data = texture.getImage().getData(0);
     35 		data.rewind();
     36 
     37 		int width = texture.getImage().getWidth();
     38 		int height = texture.getImage().getHeight();
     39 		int depth = texture.getImage().getDepth();
     40 		if (depth == 0) {
     41 			depth = 1;
     42 		}
     43 		ByteBuffer newData = BufferUtils.createByteBuffer(data.remaining());
     44 
     45 		float[] resultPixel = new float[4];
     46 		float[] pixelColor = new float[4];
     47 		TexturePixel[] colors = new TexturePixel[] { new TexturePixel(), new TexturePixel() };
     48 		int dataIndex = 0;
     49 		while (data.hasRemaining()) {
     50 			switch (format) {
     51 				case DXT3:
     52 				case DXT5:
     53 					newData.putLong(dataIndex, data.getLong());// just copy the
     54 																// 8 bytes of
     55 																// alphas
     56 					dataIndex += 8;
     57 				case DXT1:
     58 					int col0 = RGB565.RGB565_to_ARGB8(data.getShort());
     59 					int col1 = RGB565.RGB565_to_ARGB8(data.getShort());
     60 					colors[0].fromARGB8(col0);
     61 					colors[1].fromARGB8(col1);
     62 					break;
     63 				case DXT1A:
     64 					LOGGER.log(Level.WARNING, "Image type not yet supported for blending: {0}", format);
     65 					break;
     66 				default:
     67 					throw new IllegalStateException("Invalid image format type for DDS texture blender: " + format);
     68 			}
     69 
     70 			// blending colors
     71 			for (int i = 0; i < colors.length; ++i) {
     72 				if (neg) {
     73 					colors[i].negate();
     74 				}
     75 				colors[i].toRGBA(pixelColor);
     76 				this.blendPixel(resultPixel, materialColor, pixelColor, affectFactor, blendType, blenderContext);
     77 				colors[i].fromARGB8(1, resultPixel[0], resultPixel[1], resultPixel[2]);
     78 				int argb8 = colors[i].toARGB8();
     79 				short rgb565 = RGB565.ARGB8_to_RGB565(argb8);
     80 				newData.putShort(dataIndex, rgb565);
     81 				dataIndex += 2;
     82 			}
     83 
     84 			// just copy the remaining 4 bytes of the current texel
     85 			newData.putInt(dataIndex, data.getInt());
     86 			dataIndex += 4;
     87 		}
     88 		if (texture.getType() == Texture.Type.TwoDimensional) {
     89 			return new Texture2D(new Image(format, width, height, newData));
     90 		} else {
     91 			ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(1);
     92 			dataArray.add(newData);
     93 			return new Texture3D(new Image(format, width, height, depth, dataArray));
     94 		}
     95 	}
     96 }
     97