• 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 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
blend(float[] materialColor, Texture texture, float[] color, float affectFactor, int blendType, boolean neg, BlenderContext blenderContext)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