• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
blend(float[] materialColor, Texture texture, float[] color, float affectFactor, int blendType, boolean neg, BlenderContext blenderContext)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 	 */
setupMaterialColor(ByteBuffer data, Format imageFormat, boolean neg, float[] materialColor)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