Fixes to normals loading.

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9521 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
Kae..pl 13 years ago
parent 0e24cf969b
commit fde6b4a447
  1. 54
      engine/src/blender/com/jme3/scene/plugins/blender/meshes/MeshBuilder.java
  2. 32
      engine/src/blender/com/jme3/scene/plugins/blender/meshes/MeshHelper.java

@ -13,7 +13,7 @@ import com.jme3.util.BufferUtils;
/*package*/ class MeshBuilder {
/** An array of reference vertices. */
private Vector3f[] vertices;
private Vector3f[][] verticesAndNormals;
/** An list of vertices colors. */
private List<byte[]> verticesColors;
/** A variable that indicates if the model uses generated textures. */
@ -22,8 +22,6 @@ import com.jme3.util.BufferUtils;
/** This map's key is the vertex index from 'vertices 'table and the value are indices from 'vertexList'
positions (it simply tells which vertex is referenced where in the result list). */
private Map<Integer, Map<Integer, List<Integer>>> globalVertexReferenceMap;
/** A map between vertex and its normal vector. */
private Map<Vector3f, Vector3f> globalNormalMap = new HashMap<Vector3f, Vector3f>();
/** A map between vertex index and its UV coordinates. */
private Map<Integer, Vector2f> uvsMap = new HashMap<Integer, Vector2f>();
@ -42,17 +40,17 @@ import com.jme3.util.BufferUtils;
* Constructor. Stores the given array (not copying it).
* The second argument describes if the model uses generated textures. If yes then no vertex amount optimisation is applied.
* The amount of vertices is always faceCount * 3.
* @param vertices the reference vertices array
* @param verticesAndNormals the reference vertices and normals array
* @param usesGeneratedTextures a variable that indicates if the model uses generated textures or not
*/
public MeshBuilder(Vector3f[] vertices, List<byte[]> verticesColors, boolean usesGeneratedTextures) {
if(vertices == null || vertices.length == 0) {
public MeshBuilder(Vector3f[][] verticesAndNormals, List<byte[]> verticesColors, boolean usesGeneratedTextures) {
if(verticesAndNormals == null || verticesAndNormals.length == 0) {
throw new IllegalArgumentException("No vertices loaded to build mesh.");
}
this.vertices = vertices;
this.verticesAndNormals = verticesAndNormals;
this.verticesColors = verticesColors;
this.usesGeneratedTextures = usesGeneratedTextures;
globalVertexReferenceMap = new HashMap<Integer, Map<Integer, List<Integer>>>(vertices.length);
globalVertexReferenceMap = new HashMap<Integer, Map<Integer, List<Integer>>>(verticesAndNormals.length);
}
/**
@ -115,17 +113,15 @@ import com.jme3.util.BufferUtils;
//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]);
if(smooth && !usesGeneratedTextures) {
for (int i = 0; i < 3; ++i) {
if(!vertexReferenceMap.containsKey(index[i])) {
this.appendVertexReference(index[i], vertexList.size(), vertexReferenceMap);
vertexList.add(vertices[index[i]]);
vertexList.add(verticesAndNormals[index[i]][0]);
if(verticesColors != null) {
vertexColorsList.add(verticesColors.get(faceIndex + vertexColorIndex[i]));
}
normalList.add(globalNormalMap.get(vertices[index[i]]));
normalList.add(verticesAndNormals[index[i]][1]);
if(uvCoordinatesList != null) {
uvsMap.put(vertexList.size(), uvs[i]);
uvCoordinatesList.add(uvs[i]);
@ -143,20 +139,21 @@ import com.jme3.util.BufferUtils;
if(!vertexAlreadyUsed) {
this.appendVertexReference(index[i], vertexList.size(), vertexReferenceMap);
uvsMap.put(vertexList.size(), uvs[i]);
vertexList.add(vertices[index[i]]);
vertexList.add(verticesAndNormals[index[i]][0]);
if(verticesColors != null) {
vertexColorsList.add(verticesColors.get(faceIndex + vertexColorIndex[i]));
}
normalList.add(globalNormalMap.get(vertices[index[i]]));
normalList.add(verticesAndNormals[index[i]][1]);
uvCoordinatesList.add(uvs[i]);
index[i] = vertexList.size() - 1;
}
} else {
index[i] = vertexList.indexOf(vertices[index[i]]);
index[i] = vertexList.indexOf(verticesAndNormals[index[i]]);
}
indexList.add(index[i]);
}
} else {
Vector3f n = FastMath.computeNormal(verticesAndNormals[v1][0], verticesAndNormals[v2][0], verticesAndNormals[v3][0]);
for (int i = 0; i < 3; ++i) {
indexList.add(vertexList.size());
this.appendVertexReference(index[i], vertexList.size(), vertexReferenceMap);
@ -164,11 +161,11 @@ import com.jme3.util.BufferUtils;
uvCoordinatesList.add(uvs[i]);
uvsMap.put(vertexList.size(), uvs[i]);
}
vertexList.add(vertices[index[i]]);
vertexList.add(verticesAndNormals[index[i]][0]);
if(verticesColors != null) {
vertexColorsList.add(verticesColors.get(faceIndex + vertexColorIndex[i]));
}
normalList.add(globalNormalMap.get(vertices[index[i]]));
normalList.add(n);
}
}
}
@ -266,29 +263,6 @@ import com.jme3.util.BufferUtils;
return vertexMap.size() == 0;
}
/**
* This method adds a normal to a normals' map. This map is used to merge normals of a vertor that should be rendered smooth.
*
* @param normalToAdd
* a normal to be added
* @param normalMap
* merges normals of faces that will be rendered smooth; the key is the vertex and the value - its normal vector
* @param smooth
* the variable that indicates wheather to merge normals (creating the smooth mesh) or not
* @param vertices
* a list of vertices read from the blender file
*/
private void addNormal(Vector3f normalToAdd, Map<Vector3f, Vector3f> normalMap, boolean smooth, Vector3f... vertices) {
for (Vector3f v : vertices) {
Vector3f n = normalMap.get(v);
if (!smooth || n == null) {
normalMap.put(v, normalToAdd.clone());
} else {
n.addLocal(normalToAdd).normalizeLocal();
}
}
}
/**
* This method fills the vertex reference map. The vertices are loaded once and referenced many times in the model. This map is created
* to tell where the basic vertices are referenced in the result vertex lists. The key of the map is the basic vertex index, and its key

@ -106,10 +106,10 @@ public class MeshHelper extends AbstractBlenderHelper {
}
// reading vertices and their colors
Vector3f[] vertices = this.getVertices(structure, blenderContext);
Vector3f[][] verticesAndNormals = this.getVerticesAndNormals(structure, blenderContext);
List<byte[]> verticesColors = this.getVerticesColors(structure, blenderContext);
MeshBuilder meshBuilder = new MeshBuilder(vertices, verticesColors, this.areGeneratedTexturesPresent(materials));
MeshBuilder meshBuilder = new MeshBuilder(verticesAndNormals, verticesColors, this.areGeneratedTexturesPresent(materials));
Pointer pMFace = (Pointer) structure.getFieldValue("mface");
if(pMFace.isNotNull()) {
@ -415,32 +415,38 @@ public class MeshHelper extends AbstractBlenderHelper {
* the structure containing the mesh data
* @param blenderContext
* the blender context
* @return a list of vertices colors, each color belongs to a single vertex
* @return a list of two - element arrays, the first element is the vertex and the second - its normal
* @throws BlenderFileException
* this exception is thrown when the blend file structure is somehow invalid or corrupted
*/
@SuppressWarnings("unchecked")
private Vector3f[] getVertices(Structure meshStructure, BlenderContext blenderContext) throws BlenderFileException {
int verticesAmount = ((Number) meshStructure.getFieldValue("totvert")).intValue();
Vector3f[] vertices = new Vector3f[verticesAmount];
if (verticesAmount == 0) {
return vertices;
private Vector3f[][] getVerticesAndNormals(Structure meshStructure, BlenderContext blenderContext) throws BlenderFileException {
int count = ((Number) meshStructure.getFieldValue("totvert")).intValue();
Vector3f[][] result = new Vector3f[count][2];
if (count == 0) {
return result;
}
Pointer pMVert = (Pointer) meshStructure.getFieldValue("mvert");
List<Structure> mVerts = pMVert.fetchData(blenderContext.getInputStream());
if(this.fixUpAxis) {
for (int i = 0; i < verticesAmount; ++i) {
for (int i = 0; i < count; ++i) {
DynamicArray<Number> coordinates = (DynamicArray<Number>) mVerts.get(i).getFieldValue("co");
vertices[i] = new Vector3f(coordinates.get(0).floatValue(), coordinates.get(2).floatValue(), -coordinates.get(1).floatValue());
result[i][0] = new Vector3f(coordinates.get(0).floatValue(), coordinates.get(2).floatValue(), -coordinates.get(1).floatValue());
DynamicArray<Number> normals = (DynamicArray<Number>) mVerts.get(i).getFieldValue("no");
result[i][1] = new Vector3f(normals.get(0).shortValue()/32767.0f, normals.get(2).shortValue()/32767.0f, -normals.get(1).shortValue()/32767.0f);
}
} else {
for (int i = 0; i < verticesAmount; ++i) {
for (int i = 0; i < count; ++i) {
DynamicArray<Number> coordinates = (DynamicArray<Number>) mVerts.get(i).getFieldValue("co");
vertices[i] = new Vector3f(coordinates.get(0).floatValue(), coordinates.get(1).floatValue(), coordinates.get(2).floatValue());
result[i][0] = new Vector3f(coordinates.get(0).floatValue(), coordinates.get(1).floatValue(), coordinates.get(2).floatValue());
DynamicArray<Number> normals = (DynamicArray<Number>) mVerts.get(i).getFieldValue("no");
result[i][1] = new Vector3f(normals.get(0).shortValue()/32767.0f, normals.get(1).shortValue()/32767.0f, normals.get(2).shortValue()/32767.0f);
}
}
return vertices;
return result;
}
@Override

Loading…
Cancel
Save