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 com.jme3.scene.plugins.blender.BlenderContext; 9 import com.jme3.texture.Image; 10 import com.jme3.texture.Texture; 11 import com.jme3.texture.Texture2D; 12 import com.jme3.texture.Texture3D; 13 import com.jme3.texture.Image.Format; 14 import com.jme3.util.BufferUtils; 15 16 /** 17 * The class that is responsible for blending the following texture types: 18 * <li> RGBA8 19 * <li> ABGR8 20 * <li> BGR8 21 * <li> RGB8 22 * Not yet supported (but will be): 23 * <li> ARGB4444: 24 * <li> RGB10: 25 * <li> RGB111110F: 26 * <li> RGB16: 27 * <li> RGB16F: 28 * <li> RGB16F_to_RGB111110F: 29 * <li> RGB16F_to_RGB9E5: 30 * <li> RGB32F: 31 * <li> RGB565: 32 * <li> RGB5A1: 33 * <li> RGB9E5: 34 * <li> RGBA16: 35 * <li> RGBA16F 36 * @author Marcin Roguski (Kaelthas) 37 */ 38 public class TextureBlenderAWT extends AbstractTextureBlender { 39 private static final Logger LOGGER = Logger.getLogger(TextureBlenderAWT.class.getName()); 40 41 @Override 42 public Texture blend(float[] materialColor, Texture texture, float[] color, float affectFactor, int blendType, boolean neg, BlenderContext blenderContext) { 43 float[] pixelColor = new float[] { color[0], color[1], color[2], 1.0f }; 44 Format format = texture.getImage().getFormat(); 45 ByteBuffer data = texture.getImage().getData(0); 46 data.rewind(); 47 48 int width = texture.getImage().getWidth(); 49 int height = texture.getImage().getHeight(); 50 int depth = texture.getImage().getDepth(); 51 if (depth == 0) { 52 depth = 1; 53 } 54 ByteBuffer newData = BufferUtils.createByteBuffer(width * height * depth * 4); 55 56 float[] resultPixel = new float[4]; 57 int dataIndex = 0; 58 while (data.hasRemaining()) { 59 this.setupMaterialColor(data, format, neg, pixelColor); 60 this.blendPixel(resultPixel, materialColor, pixelColor, affectFactor, blendType, blenderContext); 61 newData.put(dataIndex++, (byte) (resultPixel[0] * 255.0f)); 62 newData.put(dataIndex++, (byte) (resultPixel[1] * 255.0f)); 63 newData.put(dataIndex++, (byte) (resultPixel[2] * 255.0f)); 64 newData.put(dataIndex++, (byte) (pixelColor[3] * 255.0f)); 65 } 66 if (texture.getType() == Texture.Type.TwoDimensional) { 67 return new Texture2D(new Image(Format.RGBA8, width, height, newData)); 68 } else { 69 ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(1); 70 dataArray.add(newData); 71 return new Texture3D(new Image(Format.RGBA8, width, height, depth, dataArray)); 72 } 73 } 74 75 /** 76 * This method alters the material color in a way dependent on the type of 77 * the image. For example the color remains untouched if the texture is of 78 * Luminance type. The luminance defines the interaction between the 79 * material color and color defined for texture blending. If the type has 3 80 * or more color channels then the material color is replaced with the 81 * texture's color and later blended with the defined blend color. All alpha 82 * values (if present) are ignored and not used during blending. 83 * 84 * @param data 85 * the image data 86 * @param imageFormat 87 * the format of the image 88 * @param neg 89 * defines it the result color should be nagated 90 * @param materialColor 91 * the material's color (value may be changed) 92 * @return texture intensity for the current pixel 93 */ 94 protected float setupMaterialColor(ByteBuffer data, Format imageFormat, boolean neg, float[] materialColor) { 95 float tin = 0.0f; 96 byte pixelValue = data.get();// at least one byte is always taken :) 97 float firstPixelValue = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; 98 switch (imageFormat) { 99 case RGBA8: 100 materialColor[0] = firstPixelValue; 101 pixelValue = data.get(); 102 materialColor[1] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; 103 pixelValue = data.get(); 104 materialColor[2] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; 105 pixelValue = data.get(); 106 materialColor[3] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; 107 break; 108 case ABGR8: 109 materialColor[3] = firstPixelValue; 110 pixelValue = data.get(); 111 materialColor[2] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; 112 pixelValue = data.get(); 113 materialColor[1] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; 114 pixelValue = data.get(); 115 materialColor[0] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; 116 break; 117 case BGR8: 118 materialColor[2] = firstPixelValue; 119 pixelValue = data.get(); 120 materialColor[1] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; 121 pixelValue = data.get(); 122 materialColor[0] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; 123 materialColor[3] = 1.0f; 124 break; 125 case RGB8: 126 materialColor[0] = firstPixelValue; 127 pixelValue = data.get(); 128 materialColor[1] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; 129 pixelValue = data.get(); 130 materialColor[2] = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f; 131 materialColor[3] = 1.0f; 132 break; 133 case ARGB4444: 134 case RGB10: 135 case RGB111110F: 136 case RGB16: 137 case RGB16F: 138 case RGB16F_to_RGB111110F: 139 case RGB16F_to_RGB9E5: 140 case RGB32F: 141 case RGB565: 142 case RGB5A1: 143 case RGB9E5: 144 case RGBA16: 145 case RGBA16F: 146 case RGBA32F:// TODO: implement these textures 147 LOGGER.log(Level.WARNING, "Image type not yet supported for blending: {0}", imageFormat); 148 break; 149 default: 150 throw new IllegalStateException("Invalid image format type for AWT texture blender: " + imageFormat); 151 } 152 if (neg) { 153 materialColor[0] = 1.0f - materialColor[0]; 154 materialColor[1] = 1.0f - materialColor[1]; 155 materialColor[2] = 1.0f - materialColor[2]; 156 } 157 // Blender formula for texture intensity calculation: 158 // 0.35*texres.tr+0.45*texres.tg+0.2*texres.tb 159 tin = 0.35f * materialColor[0] + 0.45f * materialColor[1] + 0.2f * materialColor[2]; 160 return tin; 161 } 162 } 163