Sfoglia il codice sorgente

* Added Mesh.extractVertexData() to extract vertex data from another mesh based on this mesh's index buffer. Used to "de-share" VertexBuffers.
* Geometry will now automatically de-share VertexBuffers if it detects it

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9003 75d07b2b-3a1a-0410-a2c5-0572b91ccdca

Sha..rd 13 anni fa
parent
commit
ed07d685bf
1 ha cambiato i file con 116 aggiunte e 0 eliminazioni
  1. 116 0
      engine/src/core/com/jme3/scene/Mesh.java

+ 116 - 0
engine/src/core/com/jme3/scene/Mesh.java

@@ -43,6 +43,7 @@ import com.jme3.math.Matrix4f;
 import com.jme3.math.Triangle;
 import com.jme3.math.Vector2f;
 import com.jme3.math.Vector3f;
+import com.jme3.scene.VertexBuffer;
 import com.jme3.scene.VertexBuffer.Format;
 import com.jme3.scene.VertexBuffer.Type;
 import com.jme3.scene.VertexBuffer.Usage;
@@ -54,6 +55,8 @@ import com.jme3.util.SafeArrayList;
 import java.io.IOException;
 import java.nio.*;
 import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
 
 /**
  * <code>Mesh</code> is used to store rendering data.
@@ -1051,6 +1054,110 @@ public class Mesh implements Savable, Cloneable {
         }
     }
 
+    /**
+     * Extracts the vertex attributes from the given mesh into
+     * this mesh, by using this mesh's {@link #getIndexBuffer() index buffer}
+     * to index into the attributes of the other mesh.
+     * Note that this will also change this mesh's index buffer so that
+     * the references to the vertex data match the new indices.
+     * 
+     * @param other The mesh to extract the vertex data from
+     */
+    public void extractVertexData(Mesh other) {
+        // Determine the number of unique vertices need to
+        // be created. Also determine the mappings
+        // between old indices to new indices (since we avoid duplicating
+        // vertices, this is a map and not an array).
+        VertexBuffer oldIdxBuf = getBuffer(Type.Index);
+        IndexBuffer indexBuf = getIndexBuffer();
+        int numIndices = indexBuf.size();
+
+        IntMap<Integer> oldIndicesToNewIndices = new IntMap<Integer>(numIndices);
+        ArrayList<Integer> newIndicesToOldIndices = new ArrayList<Integer>();
+        int newIndex = 0;
+
+        for (int i = 0; i < numIndices; i++) {
+            int oldIndex = indexBuf.get(i);
+
+            if (!oldIndicesToNewIndices.containsKey(oldIndex)) {
+                // this vertex has not been added, so allocate a 
+                // new index for it and add it to the map
+                oldIndicesToNewIndices.put(oldIndex, newIndex);
+                newIndicesToOldIndices.add(oldIndex);
+
+                // increment to have the next index
+                newIndex++;
+            }
+        }
+
+        // Number of unique verts to be created now available
+        int newNumVerts = newIndicesToOldIndices.size();
+
+        if (newIndex != newNumVerts) {
+            throw new AssertionError();
+        }
+
+        // Create the new index buffer. 
+        // Do not overwrite the old one because we might be able to 
+        // convert from int index buffer to short index buffer
+        IndexBuffer newIndexBuf;
+        if (newNumVerts >= 65536) {
+            newIndexBuf = new IndexIntBuffer(BufferUtils.createIntBuffer(numIndices));
+        } else {
+            newIndexBuf = new IndexShortBuffer(BufferUtils.createShortBuffer(numIndices));
+        }
+
+        for (int i = 0; i < numIndices; i++) {
+            // Map the old indices to the new indices
+            int oldIndex = indexBuf.get(i);
+            newIndex = oldIndicesToNewIndices.get(oldIndex);
+
+            newIndexBuf.put(i, newIndex);
+        }
+        
+        VertexBuffer newIdxBuf = new VertexBuffer(Type.Index);
+        newIdxBuf.setupData(oldIdxBuf.getUsage(), 
+                            oldIdxBuf.getNumComponents(), 
+                            newIndexBuf instanceof IndexIntBuffer ? Format.UnsignedInt : Format.UnsignedShort,
+                            newIndexBuf.getBuffer());
+        clearBuffer(Type.Index);
+        setBuffer(newIdxBuf);
+
+        // Now, create the vertex buffers
+        SafeArrayList<VertexBuffer> oldVertexData = other.getBufferList();
+        for (VertexBuffer oldVb : oldVertexData) {
+            if (oldVb.getBufferType() == VertexBuffer.Type.Index) {
+                // ignore the index buffer
+                continue;
+            }
+
+            // Create a new vertex buffer with similar configuration, but
+            // with the capacity of number of unique vertices
+            Buffer buffer = VertexBuffer.createBuffer(oldVb.getFormat(), oldVb.getNumComponents(), newNumVerts);
+
+            VertexBuffer newVb = new VertexBuffer(oldVb.getBufferType());
+            newVb.setNormalized(oldVb.isNormalized());
+            newVb.setupData(oldVb.getUsage(), oldVb.getNumComponents(), oldVb.getFormat(), buffer);
+
+            // Copy the vertex data from the old buffer into the new buffer
+            for (int i = 0; i < newNumVerts; i++) {
+                int oldIndex = newIndicesToOldIndices.get(i);
+
+                // Copy the vertex attribute from the old index
+                // to the new index
+                oldVb.copyElement(oldIndex, newVb, i);
+            }
+            
+            // Set the buffer on the mesh
+            clearBuffer(newVb.getBufferType());
+            setBuffer(newVb);
+        }
+        
+        // The data has been copied over, update informations
+        updateCounts();
+        updateBound();
+    }
+    
     /**
      * Scales the texture coordinate buffer on this mesh by the given
      * scale factor. 
@@ -1138,6 +1245,15 @@ public class Mesh implements Savable, Cloneable {
         return buffers;
     }
     
+    /**
+     * Returns a list of all {@link VertexBuffer vertex buffers} on this Mesh.
+     * Using a list instead an IntMap via the {@link #getBuffers() } method is
+     * better for iteration as there's no need to create an iterator instance.
+     * Note that the returned list is a reference to the list used internally,
+     * modifying it will cause undefined results.
+     * 
+     * @return list of vertex buffers on this mesh.
+     */
     public SafeArrayList<VertexBuffer> getBufferList(){
         return buffersList;
     }