Pārlūkot izejas kodu

Fixes to vertex color buffer applying. This functionality is also moved from MEshHelper to MeshBuilder.

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9518 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
Kae..pl 13 gadi atpakaļ
vecāks
revīzija
691ebcb53d

+ 0 - 48
engine/src/blender/com/jme3/scene/plugins/blender/AbstractBlenderHelper.java

@@ -37,10 +37,6 @@ import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
 import com.jme3.scene.plugins.blender.file.Pointer;
 import com.jme3.scene.plugins.blender.file.Structure;
 import com.jme3.scene.plugins.blender.objects.Properties;
-import com.jme3.util.BufferUtils;
-import java.nio.ByteBuffer;
-import java.nio.FloatBuffer;
-import java.util.List;
 
 /**
  * A purpose of the helper class is to split calculation code into several classes. Each helper after use should be cleared because it can
@@ -95,50 +91,6 @@ public abstract class AbstractBlenderHelper {
 		return true;
 	}
 
-        /**
-	 * Generate a new ByteBuffer using the given array of byte[4] objects. The ByteBuffer will be 4 * data.length
-	 * long and contain the vector data as data[0][0], data[0][1], data[0][2], data[0][3], data[1][0]... etc.
-	 * @param data
-	 *        list of byte[4] objects to place into a new ByteBuffer
-	 */
-	protected ByteBuffer createByteBuffer(List<byte[]> data) {
-		if (data == null) {
-			return null;
-		}
-		ByteBuffer buff = BufferUtils.createByteBuffer(4 * data.size());
-		for (byte[] v : data) {
-			if (v != null) {
-				buff.put(v[0]).put(v[1]).put(v[2]).put(v[3]);
-			} else {
-				buff.put((byte)0).put((byte)0).put((byte)0).put((byte)0);
-			}
-		}
-		buff.flip();
-		return buff;
-	}
-        
-	/**
-	 * Generate a new FloatBuffer using the given array of float[4] objects. The FloatBuffer will be 4 * data.length
-	 * long and contain the vector data as data[0][0], data[0][1], data[0][2], data[0][3], data[1][0]... etc.
-	 * @param data
-	 *        list of float[4] objects to place into a new FloatBuffer
-	 */
-	protected FloatBuffer createFloatBuffer(List<float[]> data) {
-		if (data == null) {
-			return null;
-		}
-		FloatBuffer buff = BufferUtils.createFloatBuffer(4 * data.size());
-		for (float[] v : data) {
-			if (v != null) {
-				buff.put(v[0]).put(v[1]).put(v[2]).put(v[3]);
-			} else {
-				buff.put(0).put(0).put(0).put(0);
-			}
-		}
-		buff.flip();
-		return buff;
-	}
-
 	/**
 	 * This method loads the properties if they are available and defined for the structure.
 	 * @param structure

+ 65 - 4
engine/src/blender/com/jme3/scene/plugins/blender/meshes/MeshBuilder.java

@@ -1,5 +1,6 @@
 package com.jme3.scene.plugins.blender.meshes;
 
+import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -8,10 +9,13 @@ import java.util.Map;
 import com.jme3.math.FastMath;
 import com.jme3.math.Vector2f;
 import com.jme3.math.Vector3f;
+import com.jme3.util.BufferUtils;
 
 /*package*/ class MeshBuilder {
 	/** An array of reference vertices. */
 	private Vector3f[] vertices;
+	/** An list of vertices colors. */
+	private List<byte[]> verticesColors;
 	/** A variable that indicates if the model uses generated textures. */
 	private boolean usesGeneratedTextures;
 	
@@ -27,6 +31,8 @@ import com.jme3.math.Vector3f;
     private Map<Integer, List<Vector3f>> normalMap = new HashMap<Integer, List<Vector3f>>();
     /** The following map sorts vertices by material number (because in jme Mesh can have only one material). */
     private Map<Integer, List<Vector3f>> vertexMap = new HashMap<Integer, List<Vector3f>>();
+    /** The following map sorts vertices colors by material number (because in jme Mesh can have only one material). */
+    private Map<Integer, List<byte[]>> vertexColorsMap = new HashMap<Integer, List<byte[]>>();
     /** The following map sorts indexes by material number (because in jme Mesh can have only one material). */
     private Map<Integer, List<Integer>> indexMap = new HashMap<Integer, List<Integer>>();
     /** A map between material number and UV coordinates of mesh that has this material applied. */
@@ -39,11 +45,12 @@ import com.jme3.math.Vector3f;
      * @param vertices the reference vertices array
      * @param usesGeneratedTextures a variable that indicates if the model uses generated textures or not
      */
-	public MeshBuilder(Vector3f[] vertices, boolean usesGeneratedTextures) {
+	public MeshBuilder(Vector3f[] vertices, List<byte[]> verticesColors, boolean usesGeneratedTextures) {
 		if(vertices == null || vertices.length == 0) {
 			throw new IllegalArgumentException("No vertices loaded to build mesh.");
 		}
 		this.vertices = vertices;
+		this.verticesColors = verticesColors;
 		this.usesGeneratedTextures = usesGeneratedTextures;
 		globalVertexReferenceMap = new HashMap<Integer, Map<Integer, List<Integer>>>(vertices.length);
 	}
@@ -56,11 +63,15 @@ import com.jme3.math.Vector3f;
 	 * @param smooth indicates if this face should have smooth shading or flat shading
 	 * @param materialNumber the material number for this face
 	 * @param uvs a 3-element array of vertices UV coordinates
+	 * @param quad indicates if the appended face is a part of a quad face (used for creating vertex colors buffer)
+	 * @param faceIndex the face index (used for creating vertex colors buffer)
 	 */
-	public void appendFace(int v1, int v2, int v3, boolean smooth, int materialNumber, Vector2f[] uvs) {
+	public void appendFace(int v1, int v2, int v3, boolean smooth, int materialNumber, Vector2f[] uvs, boolean quad, int faceIndex) {
 		if(uvs != null && uvs.length != 3) {
 			throw new IllegalArgumentException("UV coordinates must be a 3-element array!");
 		}
+		
+		//getting the required lists
 		List<Integer> indexList = indexMap.get(materialNumber);
         if (indexList == null) {
             indexList = new ArrayList<Integer>();
@@ -71,6 +82,12 @@ import com.jme3.math.Vector3f;
             vertexList = new ArrayList<Vector3f>();
             vertexMap.put(materialNumber, vertexList);
         }
+        List<byte[]> vertexColorsList = vertexColorsMap != null ? vertexColorsMap.get(materialNumber) : null;
+        int[] vertexColorIndex = new int[] { 0, 1, 2 };
+        if(vertexColorsList == null && vertexColorsMap != null) {
+        	vertexColorsList = new ArrayList<byte[]>();
+        	vertexColorsMap.put(materialNumber, vertexColorsList);
+        }
         List<Vector3f> normalList = normalMap.get(materialNumber);
         if (normalList == null) {
         	normalList = new ArrayList<Vector3f>();
@@ -81,7 +98,6 @@ import com.jme3.math.Vector3f;
         	vertexReferenceMap = new HashMap<Integer, List<Integer>>();
         	globalVertexReferenceMap.put(materialNumber, vertexReferenceMap);
         }
-        
         List<Vector2f> uvCoordinatesList = null;
         if(uvs != null) {
 	        uvCoordinatesList = uvCoordinates.get(Integer.valueOf(materialNumber));
@@ -91,6 +107,13 @@ import com.jme3.math.Vector3f;
 	        }
         }
         
+        faceIndex *= 4;
+        if(quad) {
+        	vertexColorIndex[1] = 2;
+        	vertexColorIndex[2] = 3;
+        }
+        
+        //creating faces
         Integer[] index = new Integer[] {v1, v2, v3};
 		Vector3f n = FastMath.computeNormal(vertices[v1], vertices[v2], vertices[v3]);
         this.addNormal(n, globalNormalMap, smooth, vertices[v1], vertices[v2], vertices[v3]);
@@ -99,6 +122,9 @@ import com.jme3.math.Vector3f;
         		if(!vertexReferenceMap.containsKey(index[i])) {
             		this.appendVertexReference(index[i], vertexList.size(), vertexReferenceMap);
             		vertexList.add(vertices[index[i]]);
+            		if(verticesColors != null) {
+            			vertexColorsList.add(verticesColors.get(faceIndex + vertexColorIndex[i]));
+            		}
             		normalList.add(globalNormalMap.get(vertices[index[i]]));
             		if(uvCoordinatesList != null) {
             			uvsMap.put(vertexList.size(), uvs[i]);
@@ -118,6 +144,9 @@ import com.jme3.math.Vector3f;
             			this.appendVertexReference(index[i], vertexList.size(), vertexReferenceMap);
             			uvsMap.put(vertexList.size(), uvs[i]);
             			vertexList.add(vertices[index[i]]);
+            			if(verticesColors != null) {
+            				vertexColorsList.add(verticesColors.get(faceIndex + vertexColorIndex[i]));
+            			}
                 		normalList.add(globalNormalMap.get(vertices[index[i]]));
             			uvCoordinatesList.add(uvs[i]);
             			index[i] = vertexList.size() - 1;
@@ -136,6 +165,9 @@ import com.jme3.math.Vector3f;
         			uvsMap.put(vertexList.size(), uvs[i]);
         		}
         		vertexList.add(vertices[index[i]]);
+        		if(verticesColors != null) {
+        			vertexColorsList.add(verticesColors.get(faceIndex + vertexColorIndex[i]));
+        		}
         		normalList.add(globalNormalMap.get(vertices[index[i]]));
         	}
         }
@@ -149,6 +181,8 @@ import com.jme3.math.Vector3f;
 	}
 	
 	/**
+	 * @param materialNumber
+	 *            the material index
 	 * @return result vertices array
 	 */
 	public Vector3f[] getVertices(int materialNumber) {
@@ -156,6 +190,8 @@ import com.jme3.math.Vector3f;
 	}
 	
 	/**
+	 * @param materialNumber
+	 *            the material index
 	 * @return the amount of result vertices
 	 */
 	public int getVerticesAmount(int materialNumber) {
@@ -163,12 +199,36 @@ import com.jme3.math.Vector3f;
 	}
 	
 	/**
+	 * @param materialNumber
+	 *            the material index
 	 * @return normals result array
 	 */
 	public Vector3f[] getNormals(int materialNumber) {
 		return normalMap.get(materialNumber).toArray(new Vector3f[normalMap.get(materialNumber).size()]);
 	}
 	
+	/**
+	 * @param materialNumber
+	 *            the material index
+	 * @return the vertices colors buffer or null if no vertex colors is set
+	 */
+	public ByteBuffer getVertexColorsBuffer(int materialNumber) {
+		ByteBuffer result = null;
+		if (verticesColors != null && vertexColorsMap.get(materialNumber) != null) {
+			List<byte[]> data = vertexColorsMap.get(materialNumber);
+			result = BufferUtils.createByteBuffer(4 * data.size());
+			for (byte[] v : data) {
+				if (v != null) {
+					result.put(v[0]).put(v[1]).put(v[2]).put(v[3]);
+				} else {
+					result.put((byte)0).put((byte)0).put((byte)0).put((byte)0);
+				}
+			}
+			result.flip();
+		}
+		return result;
+	}
+	
 	/**
 	 * @return a map between material number and the mesh part vertices indices
 	 */
@@ -184,7 +244,8 @@ import com.jme3.math.Vector3f;
 	}
 	
 	/**
-	 * @param materialNumber the material number that is appied to the mesh
+	 * @param materialNumber
+	 *            the material number that is appied to the mesh
 	 * @return UV coordinates of vertices that belong to the required mesh part
 	 */
 	public List<Vector2f> getUVCoordinates(int materialNumber) {

+ 9 - 26
engine/src/blender/com/jme3/scene/plugins/blender/meshes/MeshHelper.java

@@ -31,9 +31,7 @@
  */
 package com.jme3.scene.plugins.blender.meshes;
 
-import java.nio.ByteBuffer;
 import java.util.ArrayList;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Map.Entry;
 
@@ -87,8 +85,7 @@ public class MeshHelper extends AbstractBlenderHelper {
      */
     @SuppressWarnings("unchecked")
     public List<Geometry> toMesh(Structure structure, BlenderContext blenderContext) throws BlenderFileException {
-        List<Geometry> geometries = (List<Geometry>) blenderContext.getLoadedFeature(structure.getOldMemoryAddress(),
-                LoadedFeatureDataType.LOADED_FEATURE);
+        List<Geometry> geometries = (List<Geometry>) blenderContext.getLoadedFeature(structure.getOldMemoryAddress(), LoadedFeatureDataType.LOADED_FEATURE);
         if (geometries != null) {
             List<Geometry> copiedGeometries = new ArrayList<Geometry>(geometries.size());
             for (Geometry geometry : geometries) {
@@ -108,12 +105,11 @@ public class MeshHelper extends AbstractBlenderHelper {
             materials = materialHelper.getMaterials(structure, blenderContext);
         }
         
-        // reading vertices
+        // reading vertices and their colors
         Vector3f[] vertices = this.getVertices(structure, blenderContext);
-        MeshBuilder meshBuilder = new MeshBuilder(vertices, this.areGeneratedTexturesPresent(materials));
-        
-        // vertices Colors
         List<byte[]> verticesColors = this.getVerticesColors(structure, blenderContext);
+        
+        MeshBuilder meshBuilder = new MeshBuilder(vertices, verticesColors, this.areGeneratedTexturesPresent(materials));
 
         Pointer pMFace = (Pointer) structure.getFieldValue("mface");
         List<Structure> mFaces = null;
@@ -138,7 +134,6 @@ public class MeshHelper extends AbstractBlenderHelper {
         }
 
         // indicates if the material with the specified number should have a texture attached
-        int vertexColorIndex = 0;
         Vector2f[] uvCoordinatesForFace = new Vector2f[3];
         for (int i = 0; i < mFaces.size(); ++i) {
             Structure mFace = mFaces.get(i);
@@ -160,25 +155,14 @@ public class MeshHelper extends AbstractBlenderHelper {
             int v3 = ((Number) mFace.getFieldValue("v3")).intValue();
             int v4 = ((Number) mFace.getFieldValue("v4")).intValue();
 
-            meshBuilder.appendFace(v1, v2, v3, smooth, materialNumber, uvs == null ? null : uvCoordinatesForFace);
+            meshBuilder.appendFace(v1, v2, v3, smooth, materialNumber, uvs == null ? null : uvCoordinatesForFace, false, i);
             if (v4 > 0) {
                 if (uvs != null) {
                 	uvCoordinatesForFace[0] = new Vector2f(uvs.get(0, 0).floatValue(), uvs.get(0, 1).floatValue());
                 	uvCoordinatesForFace[1] = new Vector2f(uvs.get(2, 0).floatValue(), uvs.get(2, 1).floatValue());
                 	uvCoordinatesForFace[2] = new Vector2f(uvs.get(3, 0).floatValue(), uvs.get(3, 1).floatValue());
                 }
-                meshBuilder.appendFace(v1, v3, v4, smooth, materialNumber, uvs == null ? null : uvCoordinatesForFace);
-
-                if (verticesColors != null) {
-                    verticesColors.add(vertexColorIndex + 3, verticesColors.get(vertexColorIndex));
-                    verticesColors.add(vertexColorIndex + 4, verticesColors.get(vertexColorIndex + 2));
-                }
-                vertexColorIndex += 6;
-            } else {
-                if (verticesColors != null) {
-                    verticesColors.remove(vertexColorIndex + 3);
-                    vertexColorIndex += 3;
-                }
+                meshBuilder.appendFace(v1, v3, v4, smooth, materialNumber, uvs == null ? null : uvCoordinatesForFace, true, i);
             }
         }
         meshContext.setVertexReferenceMap(meshBuilder.getVertexReferenceMap());
@@ -200,7 +184,6 @@ public class MeshHelper extends AbstractBlenderHelper {
         Properties properties = this.loadProperties(structure, blenderContext);
 
         // generating meshes
-        ByteBuffer verticesColorsBuffer = this.createByteBuffer(verticesColors);
         for (Entry<Integer, List<Integer>> meshEntry : meshBuilder.getMeshesMap().entrySet()) {
         	int materialIndex = meshEntry.getKey();
         	//key is the material index (or -1 if the material has no texture)
@@ -241,8 +224,8 @@ public class MeshHelper extends AbstractBlenderHelper {
             meshContext.setBindPoseBuffer(verticesBind);//this is stored in the context and applied when needed (when animation is applied to the mesh)
 
             // setting vertices colors
-            if (verticesColorsBuffer != null) {
-                mesh.setBuffer(Type.Color, 4, verticesColorsBuffer);
+            if (verticesColors != null) {
+                mesh.setBuffer(Type.Color, 4, meshBuilder.getVertexColorsBuffer(materialIndex));
                 mesh.getBuffer(Type.Color).setNormalized(true);
             }
 
@@ -323,7 +306,7 @@ public class MeshHelper extends AbstractBlenderHelper {
         List<byte[]> verticesColors = null;
         List<Structure> mCol = null;
         if (pMCol.isNotNull()) {
-            verticesColors = new LinkedList<byte[]>();
+            verticesColors = new ArrayList<byte[]>();
             mCol = pMCol.fetchData(blenderContext.getInputStream());
             for (Structure color : mCol) {
                 byte r = ((Number)color.getFieldValue("r")).byteValue();