diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/textures/UVCoordinatesGenerator.java b/engine/src/blender/com/jme3/scene/plugins/blender/textures/UVCoordinatesGenerator.java index 1447871f0..7746431bd 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/textures/UVCoordinatesGenerator.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/textures/UVCoordinatesGenerator.java @@ -38,7 +38,6 @@ import java.util.logging.Logger; import com.jme3.bounding.BoundingBox; import com.jme3.bounding.BoundingSphere; import com.jme3.bounding.BoundingVolume; -import com.jme3.math.Triangle; import com.jme3.math.Vector2f; import com.jme3.math.Vector3f; import com.jme3.scene.Geometry; @@ -109,16 +108,17 @@ public class UVCoordinatesGenerator { if (textureDimension == 2) { switch (projection) { case PROJECTION_FLAT: - uvCoordinates = UVCoordinatesGenerator.flatProjection(mesh, bb); + uvCoordinates = UVProjectionGenerator.flatProjection(mesh, bb); break; case PROJECTION_CUBE: - uvCoordinates = UVCoordinatesGenerator.cubeProjection(mesh, bb); + uvCoordinates = UVProjectionGenerator.cubeProjection(mesh, bb); break; case PROJECTION_TUBE: - uvCoordinates = UVCoordinatesGenerator.tubeProjection(mesh, bb); + // TODO: implement + // uvCoordinates = UVProjectionGenerator.tubeProjection(mesh, bb); break; case PROJECTION_SPHERE: - uvCoordinates = UVCoordinatesGenerator.sphereProjection(mesh, bb); + uvCoordinates = UVProjectionGenerator.sphereProjection(mesh, bb); break; default: throw new IllegalStateException("Unknown projection type: " + projection); @@ -188,165 +188,13 @@ public class UVCoordinatesGenerator { } } - /** - * 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 - */ - private static float[] flatProjection(Mesh mesh, BoundingBox bb) { - if (bb == null) { - bb = UVCoordinatesGenerator.getBoundingBox(mesh); - } - Vector3f min = bb.getMin(null); - float[] ext = new float[] { bb.getXExtent() * 2.0f, bb.getYExtent() * 2.0f }; - FloatBuffer positions = mesh.getFloatBuffer(com.jme3.scene.VertexBuffer.Type.Position); - float[] uvCoordinates = new float[positions.limit() / 3 * 2]; - for (int i = 0, j = 0; i < positions.limit(); i += 3, j += 2) { - uvCoordinates[j] = (positions.get(i) - min.x) / ext[0]; - uvCoordinates[j + 1] = (positions.get(i + 1) - min.y) / ext[1]; - // skip the Z-coordinate - } - return uvCoordinates; - } - - /** - * Cube 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 - */ - private static float[] cubeProjection(Mesh mesh, 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[mesh.getTriangleCount() * 6];// 6 == 3 * 2 - float borderAngle = (float)Math.sqrt(2.0f)/2.0f; - for (int i = 0, pointIndex = 0; i < mesh.getTriangleCount(); ++i) { - mesh.getTriangle(i, triangle); - 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 mesh - * mesh that is to be projected - * @param bb - * the bounding box for projecting - * @return UV coordinates after the projection - */ - - private static float[] tubeProjection(Mesh mesh, BoundingBox bb) { - return null;// TODO: implement - } - - /** - * Sphere 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 - */ - private static float[] sphereProjection(Mesh mesh, BoundingBox bb) { - return null;// TODO: implement - // Vector2f[] uvTable = new Vector2f[vertexList.size()]; - // Ray ray = new Ray(); - // CollisionResults cr = new CollisionResults(); - // Vector3f yVec = new Vector3f(); - // Vector3f zVec = new Vector3f(); - // for(Geometry geom : geometries) { - // if(materialHelper.hasTexture(geom.getMaterial())) {//generate only when material has a texture - // geom.getMesh().updateBound(); - // BoundingSphere bs = this.getBoundingSphere(geom.getMesh()); - // float r2 = bs.getRadius() * bs.getRadius(); - // yVec.set(0, -bs.getRadius(), 0); - // zVec.set(0, 0, -bs.getRadius()); - // Vector3f center = bs.getCenter(); - // ray.setOrigin(center); - // //we cast each vertex of the current mesh on the bounding box to determine the UV-coordinates - // for(int i=0;i geometries) { + /* package */static BoundingBox getBoundingBox(List geometries) { BoundingBox result = null; for (Geometry geometry : geometries) { BoundingBox bb = UVCoordinatesGenerator.getBoundingBox(geometry.getMesh()); @@ -365,7 +213,7 @@ public class UVCoordinatesGenerator { * the mesh * @return bounding box of the given mesh */ - private static BoundingBox getBoundingBox(Mesh mesh) { + /* package */static BoundingBox getBoundingBox(Mesh mesh) { mesh.updateBound(); BoundingVolume bv = mesh.getBound(); if (bv instanceof BoundingBox) { @@ -385,7 +233,7 @@ public class UVCoordinatesGenerator { * the list of geometries * @return bounding spheres of the given geometries */ - private static BoundingSphere getBoundingSphere(List geometries) { + /* package */static BoundingSphere getBoundingSphere(List geometries) { BoundingSphere result = null; for (Geometry geometry : geometries) { BoundingSphere bs = UVCoordinatesGenerator.getBoundingSphere(geometry.getMesh()); @@ -404,7 +252,7 @@ public class UVCoordinatesGenerator { * the mesh * @return bounding sphere of the given mesh */ - private static BoundingSphere getBoundingSphere(Mesh mesh) { + /* package */static BoundingSphere getBoundingSphere(Mesh mesh) { mesh.updateBound(); BoundingVolume bv = mesh.getBound(); if (bv instanceof BoundingBox) { @@ -418,4 +266,70 @@ public class UVCoordinatesGenerator { throw new IllegalStateException("Unknown bounding volume type: " + bv.getClass().getName()); } } + + /** + * This method returns the bounding tube of the given mesh. + * @param mesh + * the mesh + * @return bounding tube of the given mesh + */ + /* package */static BoundingTube getBoundingTube(Mesh mesh) { + Vector3f center = new Vector3f(); + float maxx = -Float.MAX_VALUE, minx = Float.MAX_VALUE; + float maxy = -Float.MAX_VALUE, miny = Float.MAX_VALUE; + float maxz = -Float.MAX_VALUE, minz = Float.MAX_VALUE; + + FloatBuffer positions = mesh.getFloatBuffer(VertexBuffer.Type.Position); + int limit = positions.limit(); + for (int i = 0; i < limit; i += 3) { + float x = positions.get(i); + float y = positions.get(i + 1); + float z = positions.get(i + 2); + center.addLocal(x, y, z); + maxx = x > maxx ? x : maxx; + minx = x < minx ? x : minx; + maxy = y > maxy ? y : maxy; + miny = x < miny ? y : miny; + maxz = x > maxz ? z : maxz; + minz = x < minz ? z : minz; + } + center.divideLocal(limit); + + float radius = Math.max(maxx - minx, maxy - miny) * 0.5f; + return new BoundingTube(radius, maxz - minz, center); + } + + /** + * A very simple bounding tube. Id holds only the basic data bout the bounding tube + * and does not provide full functionality of a BoundingVolume. + * Should be replaced with a bounding tube that extends the BoundingVolume if it is ever created. + * @author Marcin Roguski (Kaelthas) + */ + /* package */static class BoundingTube { + private float radius; + private float height; + private Vector3f center; + + public BoundingTube(float radius, float height, Vector3f center) { + this.radius = radius; + this.height = height; + this.center = center; + } + + public void merge(BoundingTube boundingTube) { + // TODO: implement + } + + public float getRadius() { + return radius; + } + + public float getHeight() { + return height; + } + + public Vector3f getCenter() { + return center; + } + } } diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/textures/UVProjectionGenerator.java b/engine/src/blender/com/jme3/scene/plugins/blender/textures/UVProjectionGenerator.java new file mode 100644 index 000000000..8bd28491c --- /dev/null +++ b/engine/src/blender/com/jme3/scene/plugins/blender/textures/UVProjectionGenerator.java @@ -0,0 +1,167 @@ +package com.jme3.scene.plugins.blender.textures; + +import java.nio.FloatBuffer; + +import com.jme3.bounding.BoundingBox; +import com.jme3.math.Triangle; +import com.jme3.math.Vector3f; +import com.jme3.scene.Mesh; +import com.jme3.scene.plugins.blender.textures.UVCoordinatesGenerator.BoundingTube; + +/** + * This class helps with projection calculations. + * @author Marcin Roguski (Kaelthas) + */ +/* package */class UVProjectionGenerator { + /** + * 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(Mesh mesh, BoundingBox bb) { + if (bb == null) { + bb = UVCoordinatesGenerator.getBoundingBox(mesh); + } + Vector3f min = bb.getMin(null); + float[] ext = new float[] { bb.getXExtent() * 2.0f, bb.getYExtent() * 2.0f }; + FloatBuffer positions = mesh.getFloatBuffer(com.jme3.scene.VertexBuffer.Type.Position); + float[] uvCoordinates = new float[positions.limit() / 3 * 2]; + for (int i = 0, j = 0; i < positions.limit(); i += 3, j += 2) { + uvCoordinates[j] = (positions.get(i) - min.x) / ext[0]; + uvCoordinates[j + 1] = (positions.get(i + 1) - min.y) / ext[1]; + // skip the Z-coordinate + } + return uvCoordinates; + } + + /** + * Cube 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[] cubeProjection(Mesh mesh, 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[mesh.getTriangleCount() * 6];// 6 == 3 * 2 + float borderAngle = (float) Math.sqrt(2.0f) / 2.0f; + for (int i = 0, pointIndex = 0; i < mesh.getTriangleCount(); ++i) { + mesh.getTriangle(i, triangle); + 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 mesh + * mesh that is to be projected + * @param bb + * the bounding box for projecting + * @return UV coordinates after the projection + */ + + public static float[] tubeProjection(Mesh mesh, BoundingTube bb) { + return null;// TODO: implement + } + + /** + * Sphere 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[] sphereProjection(Mesh mesh, BoundingBox bb) { + return null;// TODO: implement + // Vector2f[] uvTable = new Vector2f[vertexList.size()]; + // Ray ray = new Ray(); + // CollisionResults cr = new CollisionResults(); + // Vector3f yVec = new Vector3f(); + // Vector3f zVec = new Vector3f(); + // for(Geometry geom : geometries) { + // if(materialHelper.hasTexture(geom.getMaterial())) {//generate only when material has a texture + // geom.getMesh().updateBound(); + // BoundingSphere bs = this.getBoundingSphere(geom.getMesh()); + // float r2 = bs.getRadius() * bs.getRadius(); + // yVec.set(0, -bs.getRadius(), 0); + // zVec.set(0, 0, -bs.getRadius()); + // Vector3f center = bs.getCenter(); + // ray.setOrigin(center); + // //we cast each vertex of the current mesh on the bounding box to determine the UV-coordinates + // for(int i=0;i