com.jme3.scene.plugins.blender.textures.GeneratedTexture Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jme3-blender Show documentation
Show all versions of jme3-blender Show documentation
jMonkeyEngine is a 3D game engine for adventurous Java developers
The newest version!
package com.jme3.scene.plugins.blender.textures;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import com.jme3.bounding.BoundingBox;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Vector3f;
import com.jme3.scene.Mesh;
import com.jme3.scene.plugins.blender.BlenderContext;
import com.jme3.scene.plugins.blender.BlenderContext.LoadedDataType;
import com.jme3.scene.plugins.blender.file.Structure;
import com.jme3.scene.plugins.blender.meshes.TemporalMesh;
import com.jme3.scene.plugins.blender.textures.TriangulatedTexture.TriangleTextureElement;
import com.jme3.scene.plugins.blender.textures.UVCoordinatesGenerator.UVCoordinatesType;
import com.jme3.scene.plugins.blender.textures.generating.TextureGenerator;
import com.jme3.scene.plugins.blender.textures.io.PixelIOFactory;
import com.jme3.scene.plugins.blender.textures.io.PixelInputOutput;
import com.jme3.texture.Image;
import com.jme3.texture.Image.Format;
import com.jme3.texture.Texture;
import com.jme3.texture.TextureCubeMap;
import com.jme3.util.TempVars;
/**
* The generated texture loaded from blender file. The texture is not generated
* after being read. This class rather stores all required data and can compute
* a pixel in the required 3D space position.
*
* @author Marcin Roguski (Kaelthas)
*/
/* package */class GeneratedTexture extends Texture {
private static final int POSITIVE_X = 0;
private static final int NEGATIVE_X = 1;
private static final int POSITIVE_Y = 2;
private static final int NEGATIVE_Y = 3;
private static final int POSITIVE_Z = 4;
private static final int NEGATIVE_Z = 5;
// flag values
public static final int TEX_COLORBAND = 1;
public static final int TEX_FLIPBLEND = 2;
public static final int TEX_NEGALPHA = 4;
public static final int TEX_CHECKER_ODD = 8;
public static final int TEX_CHECKER_EVEN = 16;
public static final int TEX_PRV_ALPHA = 32;
public static final int TEX_PRV_NOR = 64;
public static final int TEX_REPEAT_XMIR = 128;
public static final int TEX_REPEAT_YMIR = 256;
public static final int TEX_FLAG_MASK = TEX_COLORBAND | TEX_FLIPBLEND | TEX_NEGALPHA | TEX_CHECKER_ODD | TEX_CHECKER_EVEN | TEX_PRV_ALPHA | TEX_PRV_NOR | TEX_REPEAT_XMIR | TEX_REPEAT_YMIR;
/** Material-texture link structure. */
private final Structure mTex;
/** Texture generateo for the specified texture type. */
private final TextureGenerator textureGenerator;
/**
* The generated texture cast functions. They are used to cas a given point on a plane to a specified shape in 3D space.
* The functions should be ordered as the ordinal of a BlenderKey.CastFunction enums.
*/
private final static CastFunction[] CAST_FUNCTIONS = new CastFunction[] {
/**
* The cube casting function (does nothing except scaling if needed because the given points are already on a cube).
*/
new CastFunction() {
@Override
public void cast(Vector3f pointToCast, float radius) {
//computed using the Thales' theorem
float length = 2 * pointToCast.subtractLocal(0.5f, 0.5f, 0.5f).length() * radius;
pointToCast.normalizeLocal().addLocal(0.5f, 0.5f, 0.5f).multLocal(length);
}
},
/**
* The sphere casting function.
*/
new CastFunction() {
/**
* The method casts a point on a plane to a sphere.
* The plane is one of the faces of a cube that has a edge of length 1 and center in (0.5 0.5, 0.5). This cube is a basic 3d area where generated texture
* is created.
* To cast a point on a cube face to a sphere that is inside the cube we perform several easy vector operations.
* 1. create a vector from the cube's center to the point
* 2. setting its length to 0.5 (the radius of the sphere)
* 3. adding the value of the cube's center to get a point on the sphere
*
* The result is stored in the given vector.
*
* @param pointToCast
* the point on a plane that will be cast to a sphere
* @param radius
* the radius of the sphere
*/
@Override
public void cast(Vector3f pointToCast, float radius) {
pointToCast.subtractLocal(0.5f, 0.5f, 0.5f).normalizeLocal().multLocal(radius).addLocal(0.5f, 0.5f, 0.5f);
}
}
};
/**
* Constructor. Reads the required data from the 'tex' structure.
*
* @param tex
* the texture structure
* @param mTex
* the material-texture link data structure
* @param textureGenerator
* the generator for the required texture type
* @param blenderContext
* the blender context
*/
public GeneratedTexture(Structure tex, Structure mTex, TextureGenerator textureGenerator, BlenderContext blenderContext) {
this.mTex = mTex;
this.textureGenerator = textureGenerator;
this.textureGenerator.readData(tex, blenderContext);
super.setImage(new GeneratedTextureImage(textureGenerator.getImageFormat()));
}
/**
* This method computes the textyre color/intensity at the specified (u, v,
* s) position in 3D space.
*
* @param pixel
* the pixel where the result is stored
* @param u
* the U factor
* @param v
* the V factor
* @param s
* the S factor
*/
public void getPixel(TexturePixel pixel, float u, float v, float s) {
textureGenerator.getPixel(pixel, u, v, s);
}
/**
* This method triangulates the texture. In the result we get a set of small
* flat textures for each face of the given mesh. This can be later merged
* into one flat texture.
*
* @param mesh
* the mesh we create the texture for
* @param geometriesOMA
* the old memory address of the geometries group that the given
* mesh belongs to (required for bounding box calculations)
* @param coordinatesType
* the types of UV coordinates
* @param blenderContext
* the blender context
* @return triangulated texture
*/
public TriangulatedTexture triangulate(Mesh mesh, Long geometriesOMA, UVCoordinatesType coordinatesType, BlenderContext blenderContext) {
TemporalMesh geometries = (TemporalMesh) blenderContext.getLoadedFeature(geometriesOMA, LoadedDataType.TEMPORAL_MESH);
int[] coordinatesSwappingIndexes = new int[] { ((Number) mTex.getFieldValue("projx")).intValue(), ((Number) mTex.getFieldValue("projy")).intValue(), ((Number) mTex.getFieldValue("projz")).intValue() };
List uvs = UVCoordinatesGenerator.generateUVCoordinatesFor3DTexture(mesh, coordinatesType, coordinatesSwappingIndexes, geometries);
Vector3f[] uvsArray = uvs.toArray(new Vector3f[uvs.size()]);
BoundingBox boundingBox = UVCoordinatesGenerator.getBoundingBox(geometries);
Set triangleTextureElements = new TreeSet(new Comparator() {
public int compare(TriangleTextureElement o1, TriangleTextureElement o2) {
return o1.faceIndex - o2.faceIndex;
}
});
int[] indices = new int[3];
for (int i = 0; i < mesh.getTriangleCount(); ++i) {
mesh.getTriangle(i, indices);
triangleTextureElements.add(new TriangleTextureElement(i, boundingBox, this, uvsArray, indices, blenderContext));
}
return new TriangulatedTexture(triangleTextureElements, blenderContext);
}
/**
* Creates a texture for the sky. The result texture has 6 layers.
* @param size
* the size of the texture (width and height are equal)
* @param horizontalColor
* the horizon color
* @param zenithColor
* the zenith color
* @param blenderContext
* the blender context
* @return the sky texture
*/
public TextureCubeMap generateSkyTexture(int size, ColorRGBA horizontalColor, ColorRGBA zenithColor, BlenderContext blenderContext) {
Image image = ImageUtils.createEmptyImage(Format.RGB8, size, size, 6);
PixelInputOutput pixelIO = PixelIOFactory.getPixelIO(image.getFormat());
TexturePixel pixel = new TexturePixel();
float delta = 1 / (float) (size - 1);
float sideV, sideS = 1, forwardU = 1, forwardV, upS;
TempVars tempVars = TempVars.get();
CastFunction castFunction = CAST_FUNCTIONS[blenderContext.getBlenderKey().getSkyGeneratedTextureShape().ordinal()];
float castRadius = blenderContext.getBlenderKey().getSkyGeneratedTextureRadius();
for (int x = 0; x < size; ++x) {
sideV = 1;
forwardV = 1;
upS = 0;
for (int y = 0; y < size; ++y) {
castFunction.cast(tempVars.vect1.set(1, sideV, sideS), castRadius);
textureGenerator.getPixel(pixel, tempVars.vect1.x, tempVars.vect1.y, tempVars.vect1.z);
pixelIO.write(image, NEGATIVE_X, ImageUtils.color(pixel, horizontalColor, zenithColor), x, y);// right
castFunction.cast(tempVars.vect1.set(0, sideV, 1 - sideS), castRadius);
textureGenerator.getPixel(pixel, tempVars.vect1.x, tempVars.vect1.y, tempVars.vect1.z);
pixelIO.write(image, POSITIVE_X, ImageUtils.color(pixel, horizontalColor, zenithColor), x, y);// left
castFunction.cast(tempVars.vect1.set(forwardU, forwardV, 0), castRadius);
textureGenerator.getPixel(pixel, tempVars.vect1.x, tempVars.vect1.y, tempVars.vect1.z);
pixelIO.write(image, POSITIVE_Z, ImageUtils.color(pixel, horizontalColor, zenithColor), x, y);// front
castFunction.cast(tempVars.vect1.set(1 - forwardU, forwardV, 1), castRadius);
textureGenerator.getPixel(pixel, tempVars.vect1.x, tempVars.vect1.y, tempVars.vect1.z);
pixelIO.write(image, NEGATIVE_Z, ImageUtils.color(pixel, horizontalColor, zenithColor), x, y);// back
castFunction.cast(tempVars.vect1.set(forwardU, 0, upS), castRadius);
textureGenerator.getPixel(pixel, tempVars.vect1.x, tempVars.vect1.y, tempVars.vect1.z);
pixelIO.write(image, NEGATIVE_Y, ImageUtils.color(pixel, horizontalColor, zenithColor), x, y);// top
castFunction.cast(tempVars.vect1.set(forwardU, 1, 1 - upS), castRadius);
textureGenerator.getPixel(pixel, tempVars.vect1.x, tempVars.vect1.y, tempVars.vect1.z);
pixelIO.write(image, POSITIVE_Y, ImageUtils.color(pixel, horizontalColor, zenithColor), x, y);// bottom
sideV = FastMath.clamp(sideV - delta, 0, 1);
forwardV = FastMath.clamp(forwardV - delta, 0, 1);
upS = FastMath.clamp(upS + delta, 0, 1);
}
sideS = FastMath.clamp(sideS - delta, 0, 1);
forwardU = FastMath.clamp(forwardU - delta, 0, 1);
}
tempVars.release();
return new TextureCubeMap(image);
}
@Override
public void setWrap(WrapAxis axis, WrapMode mode) {
}
@Override
public void setWrap(WrapMode mode) {
}
@Override
public WrapMode getWrap(WrapAxis axis) {
return null;
}
@Override
public Type getType() {
return Type.ThreeDimensional;
}
@Override
public Texture createSimpleClone() {
return null;
}
/**
* Private class to give the format of the 'virtual' 3D texture image.
*
* @author Marcin Roguski (Kaelthas)
*/
private static class GeneratedTextureImage extends Image {
public GeneratedTextureImage(Format imageFormat) {
super.format = imageFormat;
}
}
/**
* The casting functions to create a sky generated texture against selected shape of a selected size.
*
* @author Marcin Roguski (Kaelthas)
*/
private static interface CastFunction {
void cast(Vector3f pointToCast, float radius);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy