Переглянути джерело

Reduced the amount of warnings being logged during mesh triangulation.
The warnings are now collected and displayed only once for each mesh
they appear in.

jmekaelthas 9 роки тому
батько
коміт
2024fe7acf

+ 38 - 5
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/meshes/Face.java

@@ -265,15 +265,16 @@ public class Face implements Comparator<Integer> {
     /**
      * The method triangulates the face.
      */
-    public void triangulate() {
+    public TriangulationWarning triangulate() {
         LOGGER.fine("Triangulating face.");
         assert indexes.size() >= 3 : "Invalid indexes amount for face. 3 is the required minimum!";
         triangulatedFaces = new ArrayList<IndexesLoop>(indexes.size() - 2);
         Integer[] indexes = new Integer[3];
-
+        TriangulationWarning warning = TriangulationWarning.NONE;
+        
         try {
             List<Face> facesToTriangulate = new ArrayList<Face>(Arrays.asList(this.clone()));
-            while (facesToTriangulate.size() > 0) {
+            while (facesToTriangulate.size() > 0 && warning == TriangulationWarning.NONE) {
                 Face face = facesToTriangulate.remove(0);
                 // two special cases will improve the computations speed
                 if(face.getIndexes().size() == 3) {
@@ -287,10 +288,12 @@ public class Face implements Comparator<Integer> {
 
                         LOGGER.finer("Veryfying improper triangulation of the temporal mesh.");
                         if (indexes[0] < 0 || indexes[1] < 0 || indexes[2] < 0) {
-                            throw new BlenderFileException("Unable to find two closest vertices while triangulating face in mesh: " + temporalMesh + "Please apply triangulation modifier in blender as a workaround and load again!");
+                            warning = TriangulationWarning.CLOSEST_VERTS;
+                            break;
                         }
                         if (previousIndex1 == indexes[0] && previousIndex2 == indexes[1] && previousIndex3 == indexes[2]) {
-                            throw new BlenderFileException("Infinite loop detected during triangulation of mesh: " + temporalMesh + "Please apply triangulation modifier in blender as a workaround and load again!");
+                            warning = TriangulationWarning.INFINITE_LOOP;
+                            break;
                         }
                         previousIndex1 = indexes[0];
                         previousIndex2 = indexes[1];
@@ -304,6 +307,10 @@ public class Face implements Comparator<Integer> {
             }
         } catch (BlenderFileException e) {
             LOGGER.log(Level.WARNING, "Errors occured during face triangulation: {0}. The face will be triangulated with the most direct algorithm, but the results might not be identical to blender.", e.getLocalizedMessage());
+            warning = TriangulationWarning.UNKNOWN;
+        }
+        if(warning != TriangulationWarning.NONE) {
+            LOGGER.finest("Triangulation the face using the most direct algorithm.");
             indexes[0] = this.getIndex(0);
             for (int i = 1; i < this.vertexCount() - 1; ++i) {
                 indexes[1] = this.getIndex(i);
@@ -311,6 +318,32 @@ public class Face implements Comparator<Integer> {
                 triangulatedFaces.add(new IndexesLoop(indexes));
             }
         }
+        return warning;
+    }
+    
+    /**
+     * A warning that indicates a problem with face triangulation. The warnings are collected and displayed once for each type for a mesh to
+     * avoid multiple warning loggings during triangulation. The amount of iterations can be really huge and logging every single failure would
+     * really slow down the importing process and make logs unreadable.
+     * 
+     * @author Marcin Roguski (Kaelthas)
+     */
+    public static enum TriangulationWarning {
+        NONE(null), 
+        CLOSEST_VERTS("Unable to find two closest vertices while triangulating face."), 
+        INFINITE_LOOP("Infinite loop detected during triangulation."), 
+        UNKNOWN("There was an unknown problem with face triangulation. Please see log for details.");
+
+        private String description;
+
+        private TriangulationWarning(String description) {
+            this.description = description;
+        }
+
+        @Override
+        public String toString() {
+            return description;
+        }
     }
     
     /**

+ 15 - 1
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/meshes/TemporalMesh.java

@@ -34,6 +34,7 @@ import com.jme3.scene.plugins.blender.BlenderContext.LoadedDataType;
 import com.jme3.scene.plugins.blender.file.BlenderFileException;
 import com.jme3.scene.plugins.blender.file.Structure;
 import com.jme3.scene.plugins.blender.materials.MaterialContext;
+import com.jme3.scene.plugins.blender.meshes.Face.TriangulationWarning;
 import com.jme3.scene.plugins.blender.meshes.MeshBuffers.BoneBuffersData;
 import com.jme3.scene.plugins.blender.modifiers.Modifier;
 import com.jme3.scene.plugins.blender.objects.Properties;
@@ -357,9 +358,22 @@ public class TemporalMesh extends Geometry {
      * Triangulates the mesh.
      */
     public void triangulate() {
+        Set<TriangulationWarning> warnings = new HashSet<>(TriangulationWarning.values().length - 1);
         LOGGER.fine("Triangulating temporal mesh.");
         for (Face face : faces) {
-            face.triangulate();
+            TriangulationWarning warning = face.triangulate();
+            if(warning != TriangulationWarning.NONE) {
+                warnings.add(warning);
+            }
+        }
+        
+        if(warnings.size() > 0 && LOGGER.isLoggable(Level.WARNING)) {
+            StringBuilder sb = new StringBuilder(512);
+            sb.append("There were problems with triangulating the faces of a mesh: ").append(name);
+            for(TriangulationWarning w : warnings) {
+                sb.append("\n\t").append(w);
+            }
+            LOGGER.warning(sb.toString());
         }
     }