Sfoglia il codice sorgente

Bugfix: fixed issues with subdivision surface modifier.

kaelthas 11 anni fa
parent
commit
550063367e

+ 18 - 14
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/meshes/TemporalMesh.java

@@ -4,11 +4,14 @@ import java.nio.IntBuffer;
 import java.nio.ShortBuffer;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Set;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -71,9 +74,10 @@ public class TemporalMesh extends Geometry {
     protected List<Edge>               edges                     = new ArrayList<Edge>();
     /** The points of the mesh. */
     protected List<Point>              points                    = new ArrayList<Point>();
-
-    protected Map<Integer, List<Face>> indexToFaceMapping        = new HashMap<Integer, List<Face>>();
-    protected Map<Integer, List<Edge>> indexToEdgeMapping        = new HashMap<Integer, List<Edge>>();
+    /** A map between index and faces that contain it (for faster index - face queries). */
+    protected Map<Integer, Set<Face>>  indexToFaceMapping        = new HashMap<Integer, Set<Face>>();
+    /** A map between index and edges that contain it (for faster index - edge queries). */
+    protected Map<Integer, Set<Edge>>  indexToEdgeMapping        = new HashMap<Integer, Set<Edge>>();
 
     /** The bounding box of the temporal mesh. */
     protected BoundingBox              boundingBox;
@@ -183,7 +187,7 @@ public class TemporalMesh extends Geometry {
     /**
      * @return the faces that contain the given index or null if none contain it
      */
-    public List<Face> getAdjacentFaces(Integer index) {
+    public Collection<Face> getAdjacentFaces(Integer index) {
         return indexToFaceMapping.get(index);
     }
 
@@ -192,10 +196,10 @@ public class TemporalMesh extends Geometry {
      *            edge of the mesh
      * @return a list of faces that contain the given edge or an empty list
      */
-    public List<Face> getAdjacentFaces(Edge edge) {
+    public Collection<Face> getAdjacentFaces(Edge edge) {
         List<Face> result = new ArrayList<Face>(indexToFaceMapping.get(edge.getFirstIndex()));
-        List<Face> secondIndexAdjacentFaces = indexToFaceMapping.get(edge.getSecondIndex());
-        if(secondIndexAdjacentFaces != null) {
+        Set<Face> secondIndexAdjacentFaces = indexToFaceMapping.get(edge.getSecondIndex());
+        if (secondIndexAdjacentFaces != null) {
             result.retainAll(indexToFaceMapping.get(edge.getSecondIndex()));
         }
         return result;
@@ -206,7 +210,7 @@ public class TemporalMesh extends Geometry {
      *            index of the mesh
      * @return a list of edges that contain the index
      */
-    public List<Edge> getAdjacentEdges(Integer index) {
+    public Collection<Edge> getAdjacentEdges(Integer index) {
         return indexToEdgeMapping.get(index);
     }
 
@@ -229,7 +233,7 @@ public class TemporalMesh extends Geometry {
      * @return <b>true</b> if the index is a boundary one and <b>false</b> otherwise
      */
     public boolean isBoundary(Integer index) {
-        List<Edge> adjacentEdges = this.getAdjacentEdges(index);
+        Collection<Edge> adjacentEdges = this.getAdjacentEdges(index);
         for (Edge edge : adjacentEdges) {
             if (this.isBoundary(edge)) {
                 return true;
@@ -287,24 +291,24 @@ public class TemporalMesh extends Geometry {
         indexToFaceMapping.clear();
         for (Face face : faces) {
             for (Integer index : face.getIndexes()) {
-                List<Face> faces = indexToFaceMapping.get(index);
+                Set<Face> faces = indexToFaceMapping.get(index);
                 if (faces == null) {
-                    faces = new ArrayList<Face>();
+                    faces = new HashSet<Face>();
                     indexToFaceMapping.put(index, faces);
                 }
                 faces.add(face);
             }
         }
         for (Edge edge : edges) {
-            List<Edge> edges = indexToEdgeMapping.get(edge.getFirstIndex());
+            Set<Edge> edges = indexToEdgeMapping.get(edge.getFirstIndex());
             if (edges == null) {
-                edges = new ArrayList<Edge>();
+                edges = new HashSet<Edge>();
                 indexToEdgeMapping.put(edge.getFirstIndex(), edges);
             }
             edges.add(edge);
             edges = indexToEdgeMapping.get(edge.getSecondIndex());
             if (edges == null) {
-                edges = new ArrayList<Edge>();
+                edges = new HashSet<Edge>();
                 indexToEdgeMapping.put(edge.getSecondIndex(), edges);
             }
             edges.add(edge);

+ 32 - 15
jme3-blender/src/main/java/com/jme3/scene/plugins/blender/modifiers/SubdivisionSurfaceModifier.java

@@ -4,6 +4,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -41,8 +42,8 @@ public class SubdivisionSurfaceModifier extends Modifier {
     private int                 levels;
     /** Indicates if the UV's should also be subdivided. */
     private boolean             subdivideUVS;
-
-    private List<Integer>       verticesOnOriginalEdges = new ArrayList<Integer>();
+    /** Stores the vertices that are located on original edges of the mesh. */
+    private Set<Integer>        verticesOnOriginalEdges = new HashSet<Integer>();
 
     /**
      * Constructor loads all neccessary modifier data.
@@ -77,7 +78,8 @@ public class SubdivisionSurfaceModifier extends Modifier {
             TemporalMesh temporalMesh = this.getTemporalMesh(node);
             if (temporalMesh != null) {
                 LOGGER.log(Level.FINE, "Applying subdivision surface modifier to: {0}", temporalMesh);
-
+                verticesOnOriginalEdges.clear();//in case the instance of this class was used more than once
+                
                 for (Edge edge : temporalMesh.getEdges()) {
                     verticesOnOriginalEdges.add(edge.getFirstIndex());
                     verticesOnOriginalEdges.add(edge.getSecondIndex());
@@ -109,10 +111,16 @@ public class SubdivisionSurfaceModifier extends Modifier {
      */
     private void subdivideCatmullClark(TemporalMesh temporalMesh) {
         Set<Integer> boundaryVertices = new HashSet<Integer>();
-        for (Face face : temporalMesh.getFaces()) {
-            for (Integer index : face.getIndexes()) {
-                if (temporalMesh.isBoundary(index)) {
-                    boundaryVertices.add(index);
+        for (Edge edge : temporalMesh.getEdges()) {
+            if (!edge.isInFace()) {
+                boundaryVertices.add(edge.getFirstIndex());
+                boundaryVertices.add(edge.getSecondIndex());
+            } else {
+                if (temporalMesh.isBoundary(edge.getFirstIndex())) {
+                    boundaryVertices.add(edge.getFirstIndex());
+                }
+                if (temporalMesh.isBoundary(edge.getSecondIndex())) {
+                    boundaryVertices.add(edge.getSecondIndex());
                 }
             }
         }
@@ -160,7 +168,8 @@ public class SubdivisionSurfaceModifier extends Modifier {
 
                 averageVert[edge.getFirstIndex()] = averageVert[edge.getFirstIndex()] == null ? centroid.clone() : averageVert[edge.getFirstIndex()].addLocal(centroid);
                 averageVert[edge.getSecondIndex()] = averageVert[edge.getSecondIndex()] == null ? centroid.clone() : averageVert[edge.getSecondIndex()].addLocal(centroid);
-                averageCount[edge.getSecondIndex()] += 2;
+                averageCount[edge.getFirstIndex()] += 1;
+                averageCount[edge.getSecondIndex()] += 1;
             }
         }
 
@@ -196,8 +205,8 @@ public class SubdivisionSurfaceModifier extends Modifier {
     private void subdivideSimple(TemporalMesh temporalMesh) {
         Map<Edge, Integer> edgePoints = new HashMap<Edge, Integer>();
         Map<Face, Integer> facePoints = new HashMap<Face, Integer>();
-        List<Face> newFaces = new ArrayList<Face>();
-        List<Edge> newEdges = new ArrayList<Edge>(temporalMesh.getEdges().size() * 2);
+        Set<Face> newFaces = new LinkedHashSet<Face>();
+        Set<Edge> newEdges = new LinkedHashSet<Edge>(temporalMesh.getEdges().size() * 4);
 
         int originalFacesCount = temporalMesh.getFaces().size();
 
@@ -240,7 +249,7 @@ public class SubdivisionSurfaceModifier extends Modifier {
                 Vector3f v = temporalMesh.getVertices().get(vIndex);
                 if (vPrevEdgeVertIndex < 0) {
                     vPrevEdgeVertIndex = vertices.size() + originalFacesCount + edgeVertices.size();
-                    verticesOnOriginalEdges.add(vNextEdgeVertIndex);
+                    verticesOnOriginalEdges.add(vPrevEdgeVertIndex);
                     edgeVertices.add(vertices.get(vPrevIndex).add(v).divideLocal(2));
                     edgeNormals.add(normals.get(vPrevIndex).add(normals.get(vIndex)).normalizeLocal());
                     edgePoints.put(prevEdge, vPrevEdgeVertIndex);
@@ -250,7 +259,7 @@ public class SubdivisionSurfaceModifier extends Modifier {
                 }
                 if (vNextEdgeVertIndex < 0) {
                     vNextEdgeVertIndex = vertices.size() + originalFacesCount + edgeVertices.size();
-                    verticesOnOriginalEdges.add(vPrevEdgeVertIndex);
+                    verticesOnOriginalEdges.add(vNextEdgeVertIndex);
                     edgeVertices.add(vertices.get(vNextIndex).add(v).divideLocal(2));
                     edgeNormals.add(normals.get(vNextIndex).add(normals.get(vIndex)).normalizeLocal());
                     edgePoints.put(nextEdge, vNextEdgeVertIndex);
@@ -312,8 +321,9 @@ public class SubdivisionSurfaceModifier extends Modifier {
                 vertices.add(vertices.get(edge.getFirstIndex()).add(vertices.get(edge.getSecondIndex())).divideLocal(2));
                 normals.add(normals.get(edge.getFirstIndex()).add(normals.get(edge.getSecondIndex())).normalizeLocal());
 
-                newEdges.add(new Edge(edge.getFirstIndex(), newVertexIndex, 0, false, temporalMesh));
-                newEdges.add(new Edge(newVertexIndex, edge.getSecondIndex(), 0, false, temporalMesh));
+                newEdges.add(new Edge(edge.getFirstIndex(), newVertexIndex, edge.getCrease(), false, temporalMesh));
+                newEdges.add(new Edge(newVertexIndex, edge.getSecondIndex(), edge.getCrease(), false, temporalMesh));
+                verticesOnOriginalEdges.add(newVertexIndex);
             }
         }
 
@@ -576,8 +586,10 @@ public class SubdivisionSurfaceModifier extends Modifier {
     private static class CreasePoint {
         private Vector3f target = new Vector3f();
         private float    weight;
+        private int      index;
 
         public CreasePoint(int index, boolean borderIndex, List<Edge> creaseEdges, TemporalMesh temporalMesh) {
+            this.index = index;
             if (creaseEdges == null || creaseEdges.size() <= 1) {
                 target = null;// crease is used when vertex belongs to at least 2 creased edges
             } else {
@@ -596,7 +608,7 @@ public class SubdivisionSurfaceModifier extends Modifier {
                     if (borderIndex) {
                         target.set(temporalMesh.getVertices().get(index));
                     } else {
-                        target.divideLocal(creasedEdgesCount);
+                        target.addLocal(temporalMesh.getVertices().get(index)).divideLocal(creasedEdgesCount + 1);
                     }
                 } else {
                     target.set(temporalMesh.getVertices().get(index));
@@ -614,5 +626,10 @@ public class SubdivisionSurfaceModifier extends Modifier {
         public float getWeight() {
             return weight;
         }
+
+        @Override
+        public String toString() {
+            return "CreasePoint [index = " + index + ", target=" + target + ", weight=" + weight + "]";
+        }
     }
 }