diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/meshes/MeshBuilder.java b/engine/src/blender/com/jme3/scene/plugins/blender/meshes/MeshBuilder.java
index 51f093fcf..65025c7ab 100644
--- a/engine/src/blender/com/jme3/scene/plugins/blender/meshes/MeshBuilder.java
+++ b/engine/src/blender/com/jme3/scene/plugins/blender/meshes/MeshBuilder.java
@@ -259,6 +259,13 @@ import com.jme3.util.BufferUtils;
return uvCoordinates.size() > 0;
}
+ /**
+ * @return true if the mesh has no vertices and false otherwise
+ */
+ public boolean isEmpty() {
+ 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.
*
diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/meshes/MeshHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/meshes/MeshHelper.java
index 152d80445..1b4ca6fbc 100644
--- a/engine/src/blender/com/jme3/scene/plugins/blender/meshes/MeshHelper.java
+++ b/engine/src/blender/com/jme3/scene/plugins/blender/meshes/MeshHelper.java
@@ -112,59 +112,18 @@ public class MeshHelper extends AbstractBlenderHelper {
MeshBuilder meshBuilder = new MeshBuilder(vertices, verticesColors, this.areGeneratedTexturesPresent(materials));
Pointer pMFace = (Pointer) structure.getFieldValue("mface");
- List mFaces = null;
- if (pMFace.isNotNull()) {
- mFaces = pMFace.fetchData(blenderContext.getInputStream());
- if (mFaces == null || mFaces.size() == 0) {
- return new ArrayList(0);
- }
- } else{
- mFaces = new ArrayList(0);
- }
-
- Pointer pMTFace = (Pointer) structure.getFieldValue("mtface");
- List mtFaces = null;
-
- if (pMTFace.isNotNull()) {
- mtFaces = pMTFace.fetchData(blenderContext.getInputStream());
- int facesAmount = ((Number) structure.getFieldValue("totface")).intValue();
- if (mtFaces.size() != facesAmount) {
- throw new BlenderFileException("The amount of faces uv coordinates is not equal to faces amount!");
- }
+ if(pMFace.isNotNull()) {
+ this.readTraditionalFaces(meshBuilder, structure, blenderContext);
+ } else {
+ this.readBMesh(meshBuilder, structure, blenderContext);
}
-
- // indicates if the material with the specified number should have a texture attached
- Vector2f[] uvCoordinatesForFace = new Vector2f[3];
- for (int i = 0; i < mFaces.size(); ++i) {
- Structure mFace = mFaces.get(i);
- int materialNumber = ((Number) mFace.getFieldValue("mat_nr")).intValue();
- boolean smooth = (((Number) mFace.getFieldValue("flag")).byteValue() & 0x01) != 0x00;
- DynamicArray uvs = null;
-
- if (mtFaces != null) {
- Structure mtFace = mtFaces.get(i);
- // uvs always must be added wheater we have texture or not
- uvs = (DynamicArray) mtFace.getFieldValue("uv");
- uvCoordinatesForFace[0] = new Vector2f(uvs.get(0, 0).floatValue(), uvs.get(0, 1).floatValue());
- uvCoordinatesForFace[1] = new Vector2f(uvs.get(1, 0).floatValue(), uvs.get(1, 1).floatValue());
- uvCoordinatesForFace[2] = new Vector2f(uvs.get(2, 0).floatValue(), uvs.get(2, 1).floatValue());
- }
-
- int v1 = ((Number) mFace.getFieldValue("v1")).intValue();
- int v2 = ((Number) mFace.getFieldValue("v2")).intValue();
- 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, 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, true, i);
- }
+ if(meshBuilder.isEmpty()) {
+ geometries = new ArrayList(0);
+ blenderContext.addLoadedFeatures(structure.getOldMemoryAddress(), structure.getName(), structure, geometries);
+ blenderContext.setMeshContext(structure.getOldMemoryAddress(), meshContext);
+ return geometries;
}
+
meshContext.setVertexReferenceMap(meshBuilder.getVertexReferenceMap());
// reading vertices groups (from the parent)
@@ -275,6 +234,136 @@ public class MeshHelper extends AbstractBlenderHelper {
return geometries;
}
+
+ /**
+ * This method reads the mesh from the new BMesh system.
+ *
+ * @param meshBuilder
+ * the mesh builder
+ * @param meshStructure
+ * the mesh structure
+ * @param blenderContext
+ * the blender context
+ * @throws BlenderFileException
+ * an exception is thrown when there are problems with the
+ * blender file
+ */
+ @SuppressWarnings("unchecked")
+ private void readBMesh(MeshBuilder meshBuilder, Structure meshStructure, BlenderContext blenderContext) throws BlenderFileException {
+ Pointer pMLoop = (Pointer) meshStructure.getFieldValue("mloop");
+ Pointer pMPoly = (Pointer) meshStructure.getFieldValue("mpoly");
+ Pointer pMEdge = (Pointer) meshStructure.getFieldValue("medge");
+ Pointer pMLoopUV = (Pointer) meshStructure.getFieldValue("mloopuv");
+ Vector2f[] uvCoordinatesForFace = new Vector2f[3];
+
+ if (pMPoly.isNotNull() && pMLoop.isNotNull() && pMEdge.isNotNull()) {
+ int faceIndex = 0;
+ List polys = pMPoly.fetchData(blenderContext.getInputStream());
+ List loops = pMLoop.fetchData(blenderContext.getInputStream());
+ List loopuvs = pMLoopUV.isNotNull() ? pMLoopUV.fetchData(blenderContext.getInputStream()) : null;
+ for (Structure poly : polys) {
+ int materialNumber = ((Number) poly.getFieldValue("mat_nr")).intValue();
+ int loopStart = ((Number) poly.getFieldValue("loopstart")).intValue();
+ int totLoop = ((Number) poly.getFieldValue("totloop")).intValue();
+ boolean smooth = (((Number) poly.getFieldValue("flag")).byteValue() & 0x01) != 0x00;
+ int[] vertexIndexes = new int[totLoop];
+ Vector2f[] uvs = loopuvs != null ? new Vector2f[totLoop] : null;
+
+ for (int i = loopStart; i < loopStart + totLoop; ++i) {
+ vertexIndexes[i - loopStart] = ((Number) loops.get(i).getFieldValue("v")).intValue();
+ if (uvs != null) {
+ DynamicArray loopUVS = (DynamicArray) loopuvs.get(i).getFieldValue("uv");
+ uvs[i - loopStart] = new Vector2f(loopUVS.get(0).floatValue(), loopUVS.get(1).floatValue());
+ }
+ }
+
+ int i = 0;
+ while (i < totLoop - 2) {
+ int v1 = vertexIndexes[0];
+ int v2 = vertexIndexes[i + 1];
+ int v3 = vertexIndexes[i + 2];
+
+ if (uvs != null) {// uvs always must be added wheater we
+ // have texture or not
+ uvCoordinatesForFace[0] = uvs[0];
+ uvCoordinatesForFace[1] = uvs[i + 1];
+ uvCoordinatesForFace[2] = uvs[i + 2];
+ }
+
+ meshBuilder.appendFace(v1, v2, v3, smooth, materialNumber, uvs == null ? null : uvCoordinatesForFace, false, faceIndex);
+
+ ++i;
+ }
+ ++faceIndex;
+ }
+ }
+ }
+
+ /**
+ * This method reads the mesh from traditional triangle/quad storing
+ * structures.
+ *
+ * @param meshBuilder
+ * the mesh builder
+ * @param meshStructure
+ * the mesh structure
+ * @param blenderContext
+ * the blender context
+ * @throws BlenderFileException
+ * an exception is thrown when there are problems with the
+ * blender file
+ */
+ @SuppressWarnings("unchecked")
+ private void readTraditionalFaces(MeshBuilder meshBuilder, Structure meshStructure, BlenderContext blenderContext) throws BlenderFileException {
+ Pointer pMFace = (Pointer) meshStructure.getFieldValue("mface");
+ List mFaces = pMFace.fetchData(blenderContext.getInputStream());
+ if (mFaces != null && mFaces.size() > 0) {
+ Pointer pMTFace = (Pointer) meshStructure.getFieldValue("mtface");
+ List mtFaces = null;
+
+ if (pMTFace.isNotNull()) {
+ mtFaces = pMTFace.fetchData(blenderContext.getInputStream());
+ int facesAmount = ((Number) meshStructure.getFieldValue("totface")).intValue();
+ if (mtFaces.size() != facesAmount) {
+ throw new BlenderFileException("The amount of faces uv coordinates is not equal to faces amount!");
+ }
+ }
+
+ // indicates if the material with the specified number should have a
+ // texture attached
+ Vector2f[] uvCoordinatesForFace = new Vector2f[3];
+ for (int i = 0; i < mFaces.size(); ++i) {
+ Structure mFace = mFaces.get(i);
+ int materialNumber = ((Number) mFace.getFieldValue("mat_nr")).intValue();
+ boolean smooth = (((Number) mFace.getFieldValue("flag")).byteValue() & 0x01) != 0x00;
+ DynamicArray uvs = null;
+
+ if (mtFaces != null) {
+ Structure mtFace = mtFaces.get(i);
+ // uvs always must be added wheater we have texture or not
+ uvs = (DynamicArray) mtFace.getFieldValue("uv");
+ uvCoordinatesForFace[0] = new Vector2f(uvs.get(0, 0).floatValue(), uvs.get(0, 1).floatValue());
+ uvCoordinatesForFace[1] = new Vector2f(uvs.get(1, 0).floatValue(), uvs.get(1, 1).floatValue());
+ uvCoordinatesForFace[2] = new Vector2f(uvs.get(2, 0).floatValue(), uvs.get(2, 1).floatValue());
+ }
+
+ int v1 = ((Number) mFace.getFieldValue("v1")).intValue();
+ int v2 = ((Number) mFace.getFieldValue("v2")).intValue();
+ 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, 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, true, i);
+ }
+ }
+ }
+ }
/**
* @return true if the material has at least one generated component and false otherwise