use of com.jme3.texture.Image in project jmonkeyengine by jMonkeyEngine.
the class MaterialLoader method readTextureImage.
private void readTextureImage(String content) {
// texture image def
String path = null;
// find extension
int extStart = content.lastIndexOf(".");
for (int i = extStart; i < content.length(); i++) {
char c = content.charAt(i);
if (Character.isWhitespace(c)) {
// extension ends here
path = content.substring(0, i).trim();
content = content.substring(i + 1).trim();
break;
}
}
if (path == null) {
path = content.trim();
content = "";
}
Scanner lnScan = new Scanner(content);
String mips = null;
String type = null;
if (lnScan.hasNext()) {
// more params
type = lnScan.next();
// if (!lnScan.hasNext("\n") && lnScan.hasNext()){
// mips = lnScan.next();
// if (lnScan.hasNext()){
// even more params..
// will have to ignore
// }
// }
}
boolean genMips = true;
boolean cubic = false;
if (type != null && type.equals("0"))
genMips = false;
if (type != null && type.equals("cubic")) {
cubic = true;
}
TextureKey texKey = new TextureKey(folderName + path, false);
texKey.setGenerateMips(genMips);
if (cubic) {
texKey.setTextureTypeHint(Texture.Type.CubeMap);
}
try {
Texture loadedTexture = assetManager.loadTexture(texKey);
textures[texUnit].setImage(loadedTexture.getImage());
textures[texUnit].setMinFilter(loadedTexture.getMinFilter());
textures[texUnit].setMagFilter(loadedTexture.getMagFilter());
textures[texUnit].setAnisotropicFilter(loadedTexture.getAnisotropicFilter());
textures[texUnit].setKey(loadedTexture.getKey());
// XXX: Is this really neccessary?
textures[texUnit].setWrap(WrapMode.Repeat);
if (texName != null) {
textures[texUnit].setName(texName);
texName = null;
} else {
textures[texUnit].setName(texKey.getName());
}
} catch (AssetNotFoundException ex) {
logger.log(Level.WARNING, "Cannot locate {0} for material {1}", new Object[] { texKey, matName });
textures[texUnit].setImage(PlaceholderAssets.getPlaceholderImage(assetManager));
textures[texUnit].setKey(texKey);
}
}
use of com.jme3.texture.Image in project jmonkeyengine by jMonkeyEngine.
the class MaterialLoader method readTextureUnit.
private void readTextureUnit(Statement statement) {
String[] split = statement.getLine().split(" ", 2);
// name is optional
if (split.length == 2) {
texName = split[1];
} else {
texName = null;
}
textures[texUnit] = new Texture2D();
for (Statement texUnitStat : statement.getContents()) {
readTextureUnitStatement(texUnitStat);
}
if (textures[texUnit].getImage() != null) {
texUnit++;
} else {
// no image was loaded, ignore
textures[texUnit] = null;
}
}
use of com.jme3.texture.Image in project jmonkeyengine by jMonkeyEngine.
the class CombinedTexture method flatten.
/**
* This method flattens the texture and creates a single result of Texture2D
* type.
*
* @param geometry
* the geometry the texture is created for
* @param geometriesOMA
* the old memory address of the geometries list that the given
* geometry belongs to (needed for bounding box creation)
* @param userDefinedUVCoordinates
* the UV's defined by user (null or zero length table if none
* were defined)
* @param blenderContext
* the blender context
* @return the name of the user UV coordinates used (null if the UV's were
* generated)
*/
public String flatten(Geometry geometry, Long geometriesOMA, Map<String, List<Vector2f>> userDefinedUVCoordinates, BlenderContext blenderContext) {
Mesh mesh = geometry.getMesh();
Texture previousTexture = null;
UVCoordinatesType masterUVCoordinatesType = null;
String masterUserUVSetName = null;
for (TextureData textureData : textureDatas) {
// decompress compressed textures (all will be merged into one texture anyway)
if (textureDatas.size() > 1 && textureData.texture.getImage().getFormat().isCompressed()) {
textureData.texture.setImage(ImageUtils.decompress(textureData.texture.getImage()));
textureData.textureBlender = TextureBlenderFactory.alterTextureType(textureData.texture.getImage().getFormat(), textureData.textureBlender);
}
if (previousTexture == null) {
// the first texture will lead the others to its shape
if (textureData.texture instanceof GeneratedTexture) {
resultTexture = ((GeneratedTexture) textureData.texture).triangulate(mesh, geometriesOMA, textureData.uvCoordinatesType, blenderContext);
} else if (textureData.texture instanceof Texture2D) {
resultTexture = textureData.texture;
if (textureData.uvCoordinatesType == UVCoordinatesType.TEXCO_UV && userDefinedUVCoordinates != null && userDefinedUVCoordinates.size() > 0) {
if (textureData.uvCoordinatesName == null) {
// get the first UV available
resultUVS = userDefinedUVCoordinates.values().iterator().next();
} else {
resultUVS = userDefinedUVCoordinates.get(textureData.uvCoordinatesName);
}
if (resultUVS == null && LOGGER.isLoggable(Level.WARNING)) {
LOGGER.warning("The texture " + textureData.texture.getName() + " has assigned non existing UV coordinates group: " + textureData.uvCoordinatesName + ".");
}
masterUserUVSetName = textureData.uvCoordinatesName;
} else {
TemporalMesh temporalMesh = (TemporalMesh) blenderContext.getLoadedFeature(geometriesOMA, LoadedDataType.TEMPORAL_MESH);
resultUVS = UVCoordinatesGenerator.generateUVCoordinatesFor2DTexture(mesh, textureData.uvCoordinatesType, textureData.projectionType, temporalMesh);
}
}
this.blend(resultTexture, textureData.textureBlender, blenderContext);
previousTexture = resultTexture;
masterUVCoordinatesType = textureData.uvCoordinatesType;
} else {
if (textureData.texture instanceof GeneratedTexture) {
if (!(resultTexture instanceof TriangulatedTexture)) {
resultTexture = new TriangulatedTexture((Texture2D) resultTexture, resultUVS, blenderContext);
resultUVS = null;
previousTexture = resultTexture;
}
TriangulatedTexture triangulatedTexture = ((GeneratedTexture) textureData.texture).triangulate(mesh, geometriesOMA, textureData.uvCoordinatesType, blenderContext);
triangulatedTexture.castToUVS((TriangulatedTexture) resultTexture, blenderContext);
triangulatedTexture.blend(textureData.textureBlender, (TriangulatedTexture) resultTexture, blenderContext);
resultTexture = previousTexture = triangulatedTexture;
} else if (textureData.texture instanceof Texture2D) {
if (this.isUVTypesMatch(masterUVCoordinatesType, masterUserUVSetName, textureData.uvCoordinatesType, textureData.uvCoordinatesName) && resultTexture instanceof Texture2D) {
this.scale((Texture2D) textureData.texture, resultTexture.getImage().getWidth(), resultTexture.getImage().getHeight());
ImageUtils.merge(resultTexture.getImage(), textureData.texture.getImage());
previousTexture = resultTexture;
} else {
if (!(resultTexture instanceof TriangulatedTexture)) {
resultTexture = new TriangulatedTexture((Texture2D) resultTexture, resultUVS, blenderContext);
resultUVS = null;
}
// first triangulate the current texture
List<Vector2f> textureUVS = null;
if (textureData.uvCoordinatesType == UVCoordinatesType.TEXCO_UV && userDefinedUVCoordinates != null && userDefinedUVCoordinates.size() > 0) {
if (textureData.uvCoordinatesName == null) {
// get the first UV available
textureUVS = userDefinedUVCoordinates.values().iterator().next();
} else {
textureUVS = userDefinedUVCoordinates.get(textureData.uvCoordinatesName);
}
} else {
TemporalMesh geometries = (TemporalMesh) blenderContext.getLoadedFeature(geometriesOMA, LoadedDataType.TEMPORAL_MESH);
textureUVS = UVCoordinatesGenerator.generateUVCoordinatesFor2DTexture(mesh, textureData.uvCoordinatesType, textureData.projectionType, geometries);
}
TriangulatedTexture triangulatedTexture = new TriangulatedTexture((Texture2D) textureData.texture, textureUVS, blenderContext);
// then move the texture to different UV's
triangulatedTexture.castToUVS((TriangulatedTexture) resultTexture, blenderContext);
// merge triangulated textures
for (int i = 0; i < ((TriangulatedTexture) resultTexture).getFaceTextureCount(); ++i) {
ImageUtils.merge(((TriangulatedTexture) resultTexture).getFaceTextureElement(i).image, triangulatedTexture.getFaceTextureElement(i).image);
}
}
}
}
}
if (resultTexture instanceof TriangulatedTexture) {
if (mappingType == MaterialContext.MTEX_NOR) {
for (int i = 0; i < ((TriangulatedTexture) resultTexture).getFaceTextureCount(); ++i) {
TriangleTextureElement triangleTextureElement = ((TriangulatedTexture) resultTexture).getFaceTextureElement(i);
// TODO: get proper strength factor
triangleTextureElement.image = ImageUtils.convertToNormalMapTexture(triangleTextureElement.image, 1);
}
}
resultUVS = ((TriangulatedTexture) resultTexture).getResultUVS();
resultTexture = ((TriangulatedTexture) resultTexture).getResultTexture();
masterUserUVSetName = null;
}
// setting additional data
resultTexture.setWrap(WrapMode.Repeat);
// the filters are required if generated textures are used because
// otherwise ugly lines appear between the mesh faces
resultTexture.setMagFilter(MagFilter.Nearest);
resultTexture.setMinFilter(MinFilter.NearestNoMipMaps);
return masterUserUVSetName;
}
use of com.jme3.texture.Image in project jmonkeyengine by jMonkeyEngine.
the class ImageLoader method loadImage.
/**
* This method loads the image from the blender file itself. It tries each loader to load the image.
*
* @param inputStream
* blender input stream
* @param startPosition
* position in the stream where the image data starts
* @param flipY
* if the image should be flipped (does not work with DirectX image)
* @return loaded image or null if it could not be loaded
*/
public Image loadImage(BlenderInputStream inputStream, int startPosition, boolean flipY) {
// loading using AWT loader
inputStream.setPosition(startPosition);
Image result = this.loadImage(inputStream, ImageType.AWT, flipY);
// loading using TGA loader
if (result == null) {
inputStream.setPosition(startPosition);
result = this.loadImage(inputStream, ImageType.TGA, flipY);
}
// loading using DDS loader
if (result == null) {
inputStream.setPosition(startPosition);
result = this.loadImage(inputStream, ImageType.DDS, flipY);
}
if (result == null) {
LOGGER.warning("Image could not be loaded by none of available loaders!");
}
return result;
}
use of com.jme3.texture.Image in project jmonkeyengine by jMonkeyEngine.
the class ImageUtils method decompress.
/**
* This method decompresses the given image. If the given image is already
* decompressed nothing happens and it is simply returned.
*
* @param image
* the image to decompress
* @return the decompressed image
*/
public static Image decompress(Image image) {
Format format = image.getFormat();
int depth = image.getDepth();
if (depth == 0) {
depth = 1;
}
ArrayList<ByteBuffer> dataArray = new ArrayList<ByteBuffer>(depth);
int[] sizes = image.getMipMapSizes() != null ? image.getMipMapSizes() : new int[1];
int[] newMipmapSizes = image.getMipMapSizes() != null ? new int[image.getMipMapSizes().length] : null;
for (int dataLayerIndex = 0; dataLayerIndex < depth; ++dataLayerIndex) {
ByteBuffer data = image.getData(dataLayerIndex);
data.rewind();
if (sizes.length == 1) {
sizes[0] = data.remaining();
}
// this should always be constant for each mipmap
float widthToHeightRatio = image.getWidth() / image.getHeight();
List<DDSTexelData> texelDataList = new ArrayList<DDSTexelData>(sizes.length);
int maxPosition = 0, resultSize = 0;
for (int sizeIndex = 0; sizeIndex < sizes.length; ++sizeIndex) {
maxPosition += sizes[sizeIndex];
DDSTexelData texelData = new DDSTexelData(sizes[sizeIndex], widthToHeightRatio, format);
texelDataList.add(texelData);
switch(format) {
// BC1
case DXT1:
case DXT1A:
while (data.position() < maxPosition) {
TexturePixel[] colors = new TexturePixel[] { new TexturePixel(), new TexturePixel(), new TexturePixel(), new TexturePixel() };
short c0 = data.getShort();
short c1 = data.getShort();
int col0 = RGB565.RGB565_to_ARGB8(c0);
int col1 = RGB565.RGB565_to_ARGB8(c1);
colors[0].fromARGB8(col0);
colors[1].fromARGB8(col1);
if (col0 > col1) {
// creating color2 = 2/3color0 + 1/3color1
colors[2].fromPixel(colors[0]);
colors[2].mult(2);
colors[2].add(colors[1]);
colors[2].divide(3);
// creating color3 = 1/3color0 + 2/3color1;
colors[3].fromPixel(colors[1]);
colors[3].mult(2);
colors[3].add(colors[0]);
colors[3].divide(3);
} else {
// creating color2 = 1/2color0 + 1/2color1
colors[2].fromPixel(colors[0]);
colors[2].add(colors[1]);
colors[2].mult(0.5f);
colors[3].fromARGB8(0);
}
// 4-byte table with color indexes in decompressed table
int indexes = data.getInt();
texelData.add(colors, indexes);
}
break;
case // BC2
DXT3:
while (data.position() < maxPosition) {
TexturePixel[] colors = new TexturePixel[] { new TexturePixel(), new TexturePixel(), new TexturePixel(), new TexturePixel() };
long alpha = data.getLong();
float[] alphas = new float[16];
long alphasIndex = 0;
for (int i = 0; i < 16; ++i) {
alphasIndex |= i << i * 4;
byte a = (byte) ((alpha >> i * 4 & 0x0F) << 4);
alphas[i] = a >= 0 ? a / 255.0f : 1.0f - ~a / 255.0f;
}
short c0 = data.getShort();
short c1 = data.getShort();
int col0 = RGB565.RGB565_to_ARGB8(c0);
int col1 = RGB565.RGB565_to_ARGB8(c1);
colors[0].fromARGB8(col0);
colors[1].fromARGB8(col1);
// creating color2 = 2/3color0 + 1/3color1
colors[2].fromPixel(colors[0]);
colors[2].mult(2);
colors[2].add(colors[1]);
colors[2].divide(3);
// creating color3 = 1/3color0 + 2/3color1;
colors[3].fromPixel(colors[1]);
colors[3].mult(2);
colors[3].add(colors[0]);
colors[3].divide(3);
// 4-byte table with color indexes in decompressed table
int indexes = data.getInt();
texelData.add(colors, indexes, alphas, alphasIndex);
}
break;
case // BC3
DXT5:
float[] alphas = new float[8];
while (data.position() < maxPosition) {
TexturePixel[] colors = new TexturePixel[] { new TexturePixel(), new TexturePixel(), new TexturePixel(), new TexturePixel() };
alphas[0] = data.get() * 255.0f;
alphas[1] = data.get() * 255.0f;
//the casts to long must be done here because otherwise 32-bit integers would be shifetd by 32 and 40 bits which would result in improper values
long alphaIndices = data.get() | (long) data.get() << 8 | (long) data.get() << 16 | (long) data.get() << 24 | (long) data.get() << 32 | (long) data.get() << 40;
if (alphas[0] > alphas[1]) {
// 6 interpolated alpha values.
alphas[2] = (6 * alphas[0] + alphas[1]) / 7;
alphas[3] = (5 * alphas[0] + 2 * alphas[1]) / 7;
alphas[4] = (4 * alphas[0] + 3 * alphas[1]) / 7;
alphas[5] = (3 * alphas[0] + 4 * alphas[1]) / 7;
alphas[6] = (2 * alphas[0] + 5 * alphas[1]) / 7;
alphas[7] = (alphas[0] + 6 * alphas[1]) / 7;
} else {
alphas[2] = (4 * alphas[0] + alphas[1]) * 0.2f;
alphas[3] = (3 * alphas[0] + 2 * alphas[1]) * 0.2f;
alphas[4] = (2 * alphas[0] + 3 * alphas[1]) * 0.2f;
alphas[5] = (alphas[0] + 4 * alphas[1]) * 0.2f;
alphas[6] = 0;
alphas[7] = 1;
}
short c0 = data.getShort();
short c1 = data.getShort();
int col0 = RGB565.RGB565_to_ARGB8(c0);
int col1 = RGB565.RGB565_to_ARGB8(c1);
colors[0].fromARGB8(col0);
colors[1].fromARGB8(col1);
// creating color2 = 2/3color0 + 1/3color1
colors[2].fromPixel(colors[0]);
colors[2].mult(2);
colors[2].add(colors[1]);
colors[2].divide(3);
// creating color3 = 1/3color0 + 2/3color1;
colors[3].fromPixel(colors[1]);
colors[3].mult(2);
colors[3].add(colors[0]);
colors[3].divide(3);
// 4-byte table with color indexes in decompressed table
int indexes = data.getInt();
texelData.add(colors, indexes, alphas, alphaIndices);
}
break;
default:
throw new IllegalStateException("Unknown compressed format: " + format);
}
newMipmapSizes[sizeIndex] = texelData.getSizeInBytes();
resultSize += texelData.getSizeInBytes();
}
byte[] bytes = new byte[resultSize];
int offset = 0;
byte[] pixelBytes = new byte[4];
for (DDSTexelData texelData : texelDataList) {
for (int i = 0; i < texelData.getPixelWidth(); ++i) {
for (int j = 0; j < texelData.getPixelHeight(); ++j) {
if (texelData.getRGBA8(i, j, pixelBytes)) {
bytes[offset + (j * texelData.getPixelWidth() + i) * 4] = pixelBytes[0];
bytes[offset + (j * texelData.getPixelWidth() + i) * 4 + 1] = pixelBytes[1];
bytes[offset + (j * texelData.getPixelWidth() + i) * 4 + 2] = pixelBytes[2];
bytes[offset + (j * texelData.getPixelWidth() + i) * 4 + 3] = pixelBytes[3];
} else {
break;
}
}
}
offset += texelData.getSizeInBytes();
}
dataArray.add(BufferUtils.createByteBuffer(bytes));
}
Image result = depth > 1 ? new Image(Format.RGBA8, image.getWidth(), image.getHeight(), depth, dataArray, com.jme3.texture.image.ColorSpace.Linear) : new Image(Format.RGBA8, image.getWidth(), image.getHeight(), dataArray.get(0), com.jme3.texture.image.ColorSpace.Linear);
if (newMipmapSizes != null) {
result.setMipMapSizes(newMipmapSizes);
}
return result;
}
Aggregations