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