Преглед изворни кода

Automatic generation of UV-coordinates (not the best solution yet, but working on it ;) )

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7941 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
Kae..pl пре 14 година
родитељ
комит
821dc08553

+ 32 - 1
engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/MaterialHelper.java

@@ -410,6 +410,37 @@ public class MaterialHelper extends AbstractBlenderHelper {
 		}
 		}
 		return result;
 		return result;
 	}
 	}
+	
+	/**
+	 * This method indicates if the material has any kind of texture.
+	 * 
+	 * @param material
+	 *        the material
+	 * @return <b>true</b> if the texture exists in the material and <B>false</b> otherwise
+	 */
+	public boolean hasTexture(Material material) {
+		if (material != null) {
+			if(material.getTextureParam(TEXTURE_TYPE_ALPHA) != null) {
+				return true;
+			}
+			if(material.getTextureParam(TEXTURE_TYPE_COLOR) != null) {
+				return true;
+			}
+			if(material.getTextureParam(TEXTURE_TYPE_DIFFUSE) != null) {
+				return true;
+			}
+			if(material.getTextureParam(TEXTURE_TYPE_GLOW) != null) {
+				return true;
+			}
+			if(material.getTextureParam(TEXTURE_TYPE_NORMAL) != null) {
+				return true;
+			}
+			if(material.getTextureParam(TEXTURE_TYPE_SPECULAR) != null) {
+				return true;
+			}
+		}
+		return false;
+	}
 
 
 	/**
 	/**
 	 * This method indicates if the material has a texture of a specified type.
 	 * This method indicates if the material has a texture of a specified type.
@@ -426,7 +457,7 @@ public class MaterialHelper extends AbstractBlenderHelper {
 		}
 		}
 		return false;
 		return false;
 	}
 	}
-
+	
 	/**
 	/**
 	 * This method returns the diffuse color
 	 * This method returns the diffuse color
 	 * 
 	 * 

+ 78 - 6
engine/src/blender/com/jme3/scene/plugins/blender/helpers/v249/MeshHelper.java

@@ -41,8 +41,13 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Map.Entry;
 
 
 import com.jme3.asset.BlenderKey.FeaturesToLoad;
 import com.jme3.asset.BlenderKey.FeaturesToLoad;
+import com.jme3.bounding.BoundingBox;
+import com.jme3.bounding.BoundingSphere;
+import com.jme3.bounding.BoundingVolume;
+import com.jme3.collision.CollisionResults;
 import com.jme3.material.Material;
 import com.jme3.material.Material;
 import com.jme3.math.FastMath;
 import com.jme3.math.FastMath;
+import com.jme3.math.Ray;
 import com.jme3.math.Vector2f;
 import com.jme3.math.Vector2f;
 import com.jme3.math.Vector3f;
 import com.jme3.math.Vector3f;
 import com.jme3.renderer.queue.RenderQueue.Bucket;
 import com.jme3.renderer.queue.RenderQueue.Bucket;
@@ -301,7 +306,7 @@ public class MeshHelper extends AbstractBlenderHelper {
 		FloatBuffer verticesColorsBuffer = this.createFloatBuffer(verticesColors);
 		FloatBuffer verticesColorsBuffer = this.createFloatBuffer(verticesColors);
 		for (Entry<Integer, List<Integer>> meshEntry : meshesMap.entrySet()) {
 		for (Entry<Integer, List<Integer>> meshEntry : meshesMap.entrySet()) {
 			Mesh mesh = new Mesh();
 			Mesh mesh = new Mesh();
-
+			
 			// creating vertices indices for this mesh
 			// creating vertices indices for this mesh
 			List<Integer> indexList = meshEntry.getValue();
 			List<Integer> indexList = meshEntry.getValue();
 			int[] indices = new int[indexList.size()];
 			int[] indices = new int[indexList.size()];
@@ -330,11 +335,6 @@ public class MeshHelper extends AbstractBlenderHelper {
 			mesh.setBuffer(normalsBuffer);
 			mesh.setBuffer(normalsBuffer);
 			mesh.setBuffer(normalsBind);
 			mesh.setBuffer(normalsBind);
 
 
-			// setting uvCoords
-			if (uvCoordsBuffer != null) {
-				mesh.setBuffer(uvCoordsBuffer);
-			}
-
 			// creating the result
 			// creating the result
 			Geometry geometry = new Geometry(name + (geometries.size() + 1), mesh);
 			Geometry geometry = new Geometry(name + (geometries.size() + 1), mesh);
 			if (materials != null) {
 			if (materials != null) {
@@ -377,9 +377,81 @@ public class MeshHelper extends AbstractBlenderHelper {
 			}
 			}
 			geometries.add(geometry);
 			geometries.add(geometry);
 		}
 		}
+		
+		//applying uvCoordinates for all the meshes
+		if (uvCoordsBuffer != null) {
+			for(Geometry geom : geometries) {
+				geom.getMesh().setBuffer(uvCoordsBuffer);
+			}
+		} else {
+			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<geom.getMesh().getIndexBuffer().size();++i) {
+						int index = geom.getMesh().getIndexBuffer().get(i);
+						
+						ray.setOrigin(vertexList.get(index));
+						ray.setDirection(normalList.get(index));
+						
+						//finding collision point
+						cr.clear();
+						bs.collideWith(ray, cr);//there is ALWAYS one collision
+						Vector3f p = cr.getCollision(0).getContactPoint();
+						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 the sphere)
+						//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
+						//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;
+						//we use similiar method to compute v
+						//the only difference is that we need to cast the p vector on ZX plane
+						//and use its length instead of r
+						p.y = 0;
+						float v = FastMath.acos(p.dot(zVec)/(bs.getRadius()*p.length())) / FastMath.PI;
+						uvTable[index] = new Vector2f(u, v);
+					}
+				}
+			}
+			
+			//creating and applying the buffer
+			uvCoordsBuffer = new VertexBuffer(Type.TexCoord);
+			uvCoordsBuffer.setupData(Usage.Static, 2, Format.Float, BufferUtils.createFloatBuffer(uvTable));
+			for(Geometry geom : geometries) {
+				geom.getMesh().setBuffer(uvCoordsBuffer);
+			}
+		}
+		
 		dataRepository.addLoadedFeatures(structure.getOldMemoryAddress(), structure.getName(), structure, geometries);
 		dataRepository.addLoadedFeatures(structure.getOldMemoryAddress(), structure.getName(), structure, geometries);
 		return geometries;
 		return geometries;
 	}
 	}
+	
+	/**
+	 * This method returns bounding shpere of a given mesh.
+	 * @param mesh the mesh to read the bounding sphere from
+	 * @return the bounding sphere of the given mesh
+	 */
+	protected BoundingSphere getBoundingSphere(Mesh mesh) {
+		BoundingVolume bv = mesh.getBound();
+		if(bv instanceof BoundingSphere) {
+			return (BoundingSphere)bv;
+		} else if(bv instanceof BoundingBox) {
+			BoundingBox bb = (BoundingBox)bv;
+			return new BoundingSphere(bb.getCenter().subtract(bb.getMin(null)).length(), bb.getCenter());
+		}
+		throw new IllegalStateException("Unknown bounding volume type: " + bv.getClass().getName());
+	}
 
 
 	/**
 	/**
 	 * This method adds a normal to a normals' map. This map is used to merge normals of a vertor that should be rendered smooth.
 	 * This method adds a normal to a normals' map. This map is used to merge normals of a vertor that should be rendered smooth.