com.jme3.scene.plugins.blender.textures.UVProjectionGenerator 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 com.jme3.bounding.BoundingBox;
import com.jme3.bounding.BoundingSphere;
import com.jme3.math.FastMath;
import com.jme3.math.Triangle;
import com.jme3.math.Vector3f;
import com.jme3.scene.plugins.blender.textures.UVCoordinatesGenerator.BoundingTube;
/**
* This class helps with projection calculations.
*
* @author Marcin Roguski (Kaelthas)
*/
/* package */class UVProjectionGenerator {
/**
* 2D texture mapping (projection)
* @author Marcin Roguski (Kaelthas)
*/
public static enum UVProjectionType {
PROJECTION_FLAT(0), PROJECTION_CUBE(1), PROJECTION_TUBE(2), PROJECTION_SPHERE(3);
public final int blenderValue;
private UVProjectionType(int blenderValue) {
this.blenderValue = blenderValue;
}
public static UVProjectionType valueOf(int blenderValue) {
for (UVProjectionType projectionType : UVProjectionType.values()) {
if (projectionType.blenderValue == blenderValue) {
return projectionType;
}
}
return null;
}
}
/**
* Flat projection for 2D textures.
*
* @param mesh
* mesh that is to be projected
* @param bb
* the bounding box for projecting
* @return UV coordinates after the projection
*/
public static float[] flatProjection(float[] positions, BoundingBox bb) {
Vector3f min = bb.getMin(null);
float[] ext = new float[] { bb.getXExtent() * 2.0f, bb.getZExtent() * 2.0f };
float[] uvCoordinates = new float[positions.length / 3 * 2];
for (int i = 0, j = 0; i < positions.length; i += 3, j += 2) {
uvCoordinates[j] = (positions[i] - min.x) / ext[0];
// skip the Y-coordinate
uvCoordinates[j + 1] = (positions[i + 2] - min.z) / ext[1];
}
return uvCoordinates;
}
/**
* Cube projection for 2D textures.
*
* @param positions
* points to be projected
* @param bb
* the bounding box for projecting
* @return UV coordinates after the projection
*/
public static float[] cubeProjection(float[] positions, BoundingBox bb) {
Triangle triangle = new Triangle();
Vector3f x = new Vector3f(1, 0, 0);
Vector3f y = new Vector3f(0, 1, 0);
Vector3f z = new Vector3f(0, 0, 1);
Vector3f min = bb.getMin(null);
float[] ext = new float[] { bb.getXExtent() * 2.0f, bb.getYExtent() * 2.0f, bb.getZExtent() * 2.0f };
float[] uvCoordinates = new float[positions.length / 3 * 2];
float borderAngle = (float) Math.sqrt(2.0f) / 2.0f;
for (int i = 0, pointIndex = 0; i < positions.length; i += 9) {
triangle.set(0, positions[i], positions[i + 1], positions[i + 2]);
triangle.set(1, positions[i + 3], positions[i + 4], positions[i + 5]);
triangle.set(2, positions[i + 6], positions[i + 7], positions[i + 8]);
Vector3f n = triangle.getNormal();
float dotNX = Math.abs(n.dot(x));
float dorNY = Math.abs(n.dot(y));
float dotNZ = Math.abs(n.dot(z));
if (dotNX > borderAngle) {
if (dotNZ < borderAngle) {// discard X-coordinate
uvCoordinates[pointIndex++] = (triangle.get1().y - min.y) / ext[1];
uvCoordinates[pointIndex++] = (triangle.get1().z - min.z) / ext[2];
uvCoordinates[pointIndex++] = (triangle.get2().y - min.y) / ext[1];
uvCoordinates[pointIndex++] = (triangle.get2().z - min.z) / ext[2];
uvCoordinates[pointIndex++] = (triangle.get3().y - min.y) / ext[1];
uvCoordinates[pointIndex++] = (triangle.get3().z - min.z) / ext[2];
} else {// discard Z-coordinate
uvCoordinates[pointIndex++] = (triangle.get1().x - min.x) / ext[0];
uvCoordinates[pointIndex++] = (triangle.get1().y - min.y) / ext[1];
uvCoordinates[pointIndex++] = (triangle.get2().x - min.x) / ext[0];
uvCoordinates[pointIndex++] = (triangle.get2().y - min.y) / ext[1];
uvCoordinates[pointIndex++] = (triangle.get3().x - min.x) / ext[0];
uvCoordinates[pointIndex++] = (triangle.get3().y - min.y) / ext[1];
}
} else {
if (dorNY > borderAngle) {// discard Y-coordinate
uvCoordinates[pointIndex++] = (triangle.get1().x - min.x) / ext[0];
uvCoordinates[pointIndex++] = (triangle.get1().z - min.z) / ext[2];
uvCoordinates[pointIndex++] = (triangle.get2().x - min.x) / ext[0];
uvCoordinates[pointIndex++] = (triangle.get2().z - min.z) / ext[2];
uvCoordinates[pointIndex++] = (triangle.get3().x - min.x) / ext[0];
uvCoordinates[pointIndex++] = (triangle.get3().z - min.z) / ext[2];
} else {// discard Z-coordinate
uvCoordinates[pointIndex++] = (triangle.get1().x - min.x) / ext[0];
uvCoordinates[pointIndex++] = (triangle.get1().y - min.y) / ext[1];
uvCoordinates[pointIndex++] = (triangle.get2().x - min.x) / ext[0];
uvCoordinates[pointIndex++] = (triangle.get2().y - min.y) / ext[1];
uvCoordinates[pointIndex++] = (triangle.get3().x - min.x) / ext[0];
uvCoordinates[pointIndex++] = (triangle.get3().y - min.y) / ext[1];
}
}
triangle.setNormal(null);// clear the previous normal vector
}
return uvCoordinates;
}
/**
* Tube projection for 2D textures.
*
* @param positions
* points to be projected
* @param bt
* the bounding tube for projecting
* @return UV coordinates after the projection
*/
public static float[] tubeProjection(float[] positions, BoundingTube bt) {
float[] uvCoordinates = new float[positions.length / 3 * 2];
Vector3f v = new Vector3f();
float cx = bt.getCenter().x, cz = bt.getCenter().z;
Vector3f uBase = new Vector3f(0, 0, -1);
float vBase = bt.getCenter().y - bt.getHeight() * 0.5f;
for (int i = 0, j = 0; i < positions.length; i += 3, j += 2) {
// calculating U
v.set(positions[i] - cx, 0, positions[i + 2] - cz);
v.normalizeLocal();
float angle = v.angleBetween(uBase);// result between [0; PI]
if (v.x < 0) {// the angle should be greater than PI, we're on the other part of the image then
angle = FastMath.TWO_PI - angle;
}
uvCoordinates[j] = angle / FastMath.TWO_PI;
// calculating V
float y = positions[i + 1];
uvCoordinates[j + 1] = (y - vBase) / bt.getHeight();
}
// looking for splitted triangles
Triangle triangle = new Triangle();
for (int i = 0; i < positions.length; i += 9) {
triangle.set(0, positions[i], positions[i + 1], positions[i + 2]);
triangle.set(1, positions[i + 3], positions[i + 4], positions[i + 5]);
triangle.set(2, positions[i + 6], positions[i + 7], positions[i + 8]);
float sgn1 = Math.signum(triangle.get1().x - cx);
float sgn2 = Math.signum(triangle.get2().x - cx);
float sgn3 = Math.signum(triangle.get3().x - cx);
float xSideFactor = sgn1 + sgn2 + sgn3;
float ySideFactor = Math.signum(triangle.get1().z - cz) + Math.signum(triangle.get2().z - cz) + Math.signum(triangle.get3().z - cz);
if ((xSideFactor > -3 || xSideFactor < 3) && ySideFactor < 0) {// the triangle is on the splitting plane
if (sgn1 == 1.0f) {
uvCoordinates[i / 3 * 2] += 1.0f;
}
if (sgn2 == 1.0f) {
uvCoordinates[(i / 3 + 1) * 2] += 1.0f;
}
if (sgn3 == 1.0f) {
uvCoordinates[(i / 3 + 2) * 2] += 1.0f;
}
}
}
return uvCoordinates;
}
/**
* Sphere projection for 2D textures.
*
* @param positions
* points to be projected
* @param bb
* the bounding box for projecting
* @return UV coordinates after the projection
*/
public static float[] sphereProjection(float[] positions, BoundingSphere bs) {// TODO: rotate it to be vertical
float[] uvCoordinates = new float[positions.length / 3 * 2];
Vector3f v = new Vector3f();
float cx = bs.getCenter().x, cy = bs.getCenter().y, cz = bs.getCenter().z;
Vector3f uBase = new Vector3f(0, -1, 0);
Vector3f vBase = new Vector3f(0, 0, -1);
for (int i = 0, j = 0; i < positions.length; i += 3, j += 2) {
// calculating U
v.set(positions[i] - cx, positions[i + 1] - cy, 0);
v.normalizeLocal();
float angle = v.angleBetween(uBase);// result between [0; PI]
if (v.x < 0) {// the angle should be greater than PI, we're on the other part of the image then
angle = FastMath.TWO_PI - angle;
}
uvCoordinates[j] = angle / FastMath.TWO_PI;
// calculating V
v.set(positions[i] - cx, positions[i + 1] - cy, positions[i + 2] - cz);
v.normalizeLocal();
angle = v.angleBetween(vBase);// result between [0; PI]
uvCoordinates[j + 1] = angle / FastMath.PI;
}
// looking for splitted triangles
Triangle triangle = new Triangle();
for (int i = 0; i < positions.length; i += 9) {
triangle.set(0, positions[i], positions[i + 1], positions[i + 2]);
triangle.set(1, positions[i + 3], positions[i + 4], positions[i + 5]);
triangle.set(2, positions[i + 6], positions[i + 7], positions[i + 8]);
float sgn1 = Math.signum(triangle.get1().x - cx);
float sgn2 = Math.signum(triangle.get2().x - cx);
float sgn3 = Math.signum(triangle.get3().x - cx);
float xSideFactor = sgn1 + sgn2 + sgn3;
float ySideFactor = Math.signum(triangle.get1().y - cy) + Math.signum(triangle.get2().y - cy) + Math.signum(triangle.get3().y - cy);
if ((xSideFactor > -3 || xSideFactor < 3) && ySideFactor < 0) {// the triangle is on the splitting plane
if (sgn1 == 1.0f) {
uvCoordinates[i / 3 * 2] += 1.0f;
}
if (sgn2 == 1.0f) {
uvCoordinates[(i / 3 + 1) * 2] += 1.0f;
}
if (sgn3 == 1.0f) {
uvCoordinates[(i / 3 + 2) * 2] += 1.0f;
}
}
}
return uvCoordinates;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy