2
0
Эх сурвалжийг харах

Support for texture's tube projection.

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@8059 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
Kae..pl 14 жил өмнө
parent
commit
11b250ffe1

+ 6 - 6
engine/src/blender/com/jme3/scene/plugins/blender/textures/UVCoordinatesGenerator.java

@@ -114,8 +114,8 @@ public class UVCoordinatesGenerator {
 							uvCoordinates = UVProjectionGenerator.cubeProjection(mesh, bb);
 							uvCoordinates = UVProjectionGenerator.cubeProjection(mesh, bb);
 							break;
 							break;
 						case PROJECTION_TUBE:
 						case PROJECTION_TUBE:
-							// TODO: implement
-							// uvCoordinates = UVProjectionGenerator.tubeProjection(mesh, bb);
+							 BoundingTube bt = UVCoordinatesGenerator.getBoundingTube(mesh);
+							 uvCoordinates = UVProjectionGenerator.tubeProjection(mesh, bt);
 							break;
 							break;
 						case PROJECTION_SPHERE:
 						case PROJECTION_SPHERE:
 							uvCoordinates = UVProjectionGenerator.sphereProjection(mesh, bb);
 							uvCoordinates = UVProjectionGenerator.sphereProjection(mesh, bb);
@@ -289,11 +289,11 @@ public class UVCoordinatesGenerator {
 			maxx = x > maxx ? x : maxx;
 			maxx = x > maxx ? x : maxx;
 			minx = x < minx ? x : minx;
 			minx = x < minx ? x : minx;
 			maxy = y > maxy ? y : maxy;
 			maxy = y > maxy ? y : maxy;
-			miny = x < miny ? y : miny;
-			maxz = x > maxz ? z : maxz;
-			minz = x < minz ? z : minz;
+			miny = y < miny ? y : miny;
+			maxz = z > maxz ? z : maxz;
+			minz = z < minz ? z : minz;
 		}
 		}
-		center.divideLocal(limit);
+		center.divideLocal(limit/3);
 
 
 		float radius = Math.max(maxx - minx, maxy - miny) * 0.5f;
 		float radius = Math.max(maxx - minx, maxy - miny) * 0.5f;
 		return new BoundingTube(radius, maxz - minz, center);
 		return new BoundingTube(radius, maxz - minz, center);

+ 80 - 19
engine/src/blender/com/jme3/scene/plugins/blender/textures/UVProjectionGenerator.java

@@ -3,22 +3,26 @@ package com.jme3.scene.plugins.blender.textures;
 import java.nio.FloatBuffer;
 import java.nio.FloatBuffer;
 
 
 import com.jme3.bounding.BoundingBox;
 import com.jme3.bounding.BoundingBox;
+import com.jme3.math.FastMath;
 import com.jme3.math.Triangle;
 import com.jme3.math.Triangle;
 import com.jme3.math.Vector3f;
 import com.jme3.math.Vector3f;
 import com.jme3.scene.Mesh;
 import com.jme3.scene.Mesh;
+import com.jme3.scene.VertexBuffer;
 import com.jme3.scene.plugins.blender.textures.UVCoordinatesGenerator.BoundingTube;
 import com.jme3.scene.plugins.blender.textures.UVCoordinatesGenerator.BoundingTube;
 
 
 /**
 /**
  * This class helps with projection calculations.
  * This class helps with projection calculations.
+ * 
  * @author Marcin Roguski (Kaelthas)
  * @author Marcin Roguski (Kaelthas)
  */
  */
 /* package */class UVProjectionGenerator {
 /* package */class UVProjectionGenerator {
 	/**
 	/**
 	 * Flat projection for 2D textures.
 	 * Flat projection for 2D textures.
+	 * 
 	 * @param mesh
 	 * @param mesh
-	 *        mesh that is to be projected
+	 *            mesh that is to be projected
 	 * @param bb
 	 * @param bb
-	 *        the bounding box for projecting
+	 *            the bounding box for projecting
 	 * @return UV coordinates after the projection
 	 * @return UV coordinates after the projection
 	 */
 	 */
 	public static float[] flatProjection(Mesh mesh, BoundingBox bb) {
 	public static float[] flatProjection(Mesh mesh, BoundingBox bb) {
@@ -27,7 +31,7 @@ import com.jme3.scene.plugins.blender.textures.UVCoordinatesGenerator.BoundingTu
 		}
 		}
 		Vector3f min = bb.getMin(null);
 		Vector3f min = bb.getMin(null);
 		float[] ext = new float[] { bb.getXExtent() * 2.0f, bb.getYExtent() * 2.0f };
 		float[] ext = new float[] { bb.getXExtent() * 2.0f, bb.getYExtent() * 2.0f };
-		FloatBuffer positions = mesh.getFloatBuffer(com.jme3.scene.VertexBuffer.Type.Position);
+		FloatBuffer positions = mesh.getFloatBuffer(VertexBuffer.Type.Position);
 		float[] uvCoordinates = new float[positions.limit() / 3 * 2];
 		float[] uvCoordinates = new float[positions.limit() / 3 * 2];
 		for (int i = 0, j = 0; i < positions.limit(); i += 3, j += 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] = (positions.get(i) - min.x) / ext[0];
@@ -39,10 +43,11 @@ import com.jme3.scene.plugins.blender.textures.UVCoordinatesGenerator.BoundingTu
 
 
 	/**
 	/**
 	 * Cube projection for 2D textures.
 	 * Cube projection for 2D textures.
+	 * 
 	 * @param mesh
 	 * @param mesh
-	 *        mesh that is to be projected
+	 *            mesh that is to be projected
 	 * @param bb
 	 * @param bb
-	 *        the bounding box for projecting
+	 *            the bounding box for projecting
 	 * @return UV coordinates after the projection
 	 * @return UV coordinates after the projection
 	 */
 	 */
 	public static float[] cubeProjection(Mesh mesh, BoundingBox bb) {
 	public static float[] cubeProjection(Mesh mesh, BoundingBox bb) {
@@ -101,23 +106,72 @@ import com.jme3.scene.plugins.blender.textures.UVCoordinatesGenerator.BoundingTu
 
 
 	/**
 	/**
 	 * Tube projection for 2D textures.
 	 * Tube projection for 2D textures.
+	 * 
 	 * @param mesh
 	 * @param mesh
-	 *        mesh that is to be projected
-	 * @param bb
-	 *        the bounding box for projecting
+	 *            mesh that is to be projected
+	 * @param bt
+	 *            the bounding tube for projecting
 	 * @return UV coordinates after the projection
 	 * @return UV coordinates after the projection
 	 */
 	 */
+	public static float[] tubeProjection(Mesh mesh, BoundingTube bt) {
+		FloatBuffer positions = mesh.getFloatBuffer(VertexBuffer.Type.Position);
+		float[] uvCoordinates = new float[positions.limit() / 3 * 2];
+		Vector3f v = new Vector3f();
+		float cx = bt.getCenter().x, cy = bt.getCenter().y;
+		Vector3f uBase = new Vector3f(0, -1, 0);
+		
+		//the key is the Z-ccordinate of the vertex and the value a map between the vertex's angle nad indexes of its UV-coordinates
+//		Map<Float, Map<Float, Integer[]>> lowestAnglesUVCoordinatesMap = new HashMap<Float, Map<Float,Integer[]>>();
+		float vBase = bt.getCenter().z - bt.getHeight() * 0.5f;
+		for (int i = 0, j = 0; i < positions.limit(); i += 3, j += 2) {
+			// calculating U
+			v.set(positions.get(i)-cx, positions.get(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;
 
 
-	public static float[] tubeProjection(Mesh mesh, BoundingTube bb) {
-		return null;// TODO: implement
+			// calculating V
+			float z = positions.get(i + 2);
+			uvCoordinates[j + 1] = (vBase - z) / bt.getHeight();
+		}
+		
+		//looking for splitted triangles
+		Triangle triangle = new Triangle();
+		for(int i=0;i<mesh.getTriangleCount();++i) {
+			mesh.getTriangle(i, triangle);
+			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
+				//indexOfUcoord = (indexOfTriangle*3 + indexOfTrianglesVertex)*2
+				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.
 	 * Sphere projection for 2D textures.
+	 * 
 	 * @param mesh
 	 * @param mesh
-	 *        mesh that is to be projected
+	 *            mesh that is to be projected
 	 * @param bb
 	 * @param bb
-	 *        the bounding box for projecting
+	 *            the bounding box for projecting
 	 * @return UV coordinates after the projection
 	 * @return UV coordinates after the projection
 	 */
 	 */
 	public static float[] sphereProjection(Mesh mesh, BoundingBox bb) {
 	public static float[] sphereProjection(Mesh mesh, BoundingBox bb) {
@@ -128,7 +182,8 @@ import com.jme3.scene.plugins.blender.textures.UVCoordinatesGenerator.BoundingTu
 		// Vector3f yVec = new Vector3f();
 		// Vector3f yVec = new Vector3f();
 		// Vector3f zVec = new Vector3f();
 		// Vector3f zVec = new Vector3f();
 		// for(Geometry geom : geometries) {
 		// for(Geometry geom : geometries) {
-		// if(materialHelper.hasTexture(geom.getMaterial())) {//generate only when material has a texture
+		// if(materialHelper.hasTexture(geom.getMaterial())) {//generate only
+		// when material has a texture
 		// geom.getMesh().updateBound();
 		// geom.getMesh().updateBound();
 		// BoundingSphere bs = this.getBoundingSphere(geom.getMesh());
 		// BoundingSphere bs = this.getBoundingSphere(geom.getMesh());
 		// float r2 = bs.getRadius() * bs.getRadius();
 		// float r2 = bs.getRadius() * bs.getRadius();
@@ -136,7 +191,8 @@ import com.jme3.scene.plugins.blender.textures.UVCoordinatesGenerator.BoundingTu
 		// zVec.set(0, 0, -bs.getRadius());
 		// zVec.set(0, 0, -bs.getRadius());
 		// Vector3f center = bs.getCenter();
 		// Vector3f center = bs.getCenter();
 		// ray.setOrigin(center);
 		// ray.setOrigin(center);
-		// //we cast each vertex of the current mesh on the bounding box to determine the UV-coordinates
+		// //we cast each vertex of the current mesh on the bounding box to
+		// determine the UV-coordinates
 		// for(int i=0;i<geom.getMesh().getIndexBuffer().size();++i) {
 		// for(int i=0;i<geom.getMesh().getIndexBuffer().size();++i) {
 		// int index = geom.getMesh().getIndexBuffer().get(i);
 		// int index = geom.getMesh().getIndexBuffer().get(i);
 		//
 		//
@@ -148,17 +204,22 @@ import com.jme3.scene.plugins.blender.textures.UVCoordinatesGenerator.BoundingTu
 		// bs.collideWith(ray, cr);//there is ALWAYS one collision
 		// bs.collideWith(ray, cr);//there is ALWAYS one collision
 		// Vector3f p = cr.getCollision(0).getContactPoint();
 		// Vector3f p = cr.getCollision(0).getContactPoint();
 		// p.subtractLocal(center);
 		// p.subtractLocal(center);
-		// //arcLength = FastMath.acos(p.dot(yVec)/(p.length * yVec.length)) * r <- an arc length on the sphere (from top to the point on
+		// //arcLength = FastMath.acos(p.dot(yVec)/(p.length * yVec.length)) * r
+		// <- an arc length on the sphere (from top to the point on
 		// the sphere)
 		// the sphere)
-		// //but yVec.length == r and p.length == r so: arcLength = FastMath.acos(p.dot(yVec)/r^2)/r
+		// //but yVec.length == r and p.length == r so: arcLength =
+		// FastMath.acos(p.dot(yVec)/r^2)/r
 		// //U coordinate is as follows: u = arcLength / PI*r
 		// //U coordinate is as follows: u = arcLength / PI*r
-		// //so to compute it faster we just write: u = FastMath.acos(p.dot(yVec)/r^2) / PI;
+		// //so to compute it faster we just write: u =
+		// FastMath.acos(p.dot(yVec)/r^2) / PI;
 		// float u = FastMath.acos(p.dot(yVec)/r2) / FastMath.PI;
 		// float u = FastMath.acos(p.dot(yVec)/r2) / FastMath.PI;
 		// //we use similiar method to compute v
 		// //we use similiar method to compute v
-		// //the only difference is that we need to cast the p vector on ZX plane
+		// //the only difference is that we need to cast the p vector on ZX
+		// plane
 		// //and use its length instead of r
 		// //and use its length instead of r
 		// p.y = 0;
 		// p.y = 0;
-		// float v = FastMath.acos(p.dot(zVec)/(bs.getRadius()*p.length())) / FastMath.PI;
+		// float v = FastMath.acos(p.dot(zVec)/(bs.getRadius()*p.length())) /
+		// FastMath.PI;
 		// uvTable[index] = new Vector2f(u, v);
 		// uvTable[index] = new Vector2f(u, v);
 		// }
 		// }
 		// }
 		// }