소스 검색

BatchNode safe catch of a crash when the batch node geoms don't have the same buffer types.
Added a utility method in GeometryBatchFactory to align the buffers of the subgraph.

Nehon 10 년 전
부모
커밋
91cf9e645c
2개의 변경된 파일97개의 추가작업 그리고 5개의 파일을 삭제
  1. 7 5
      jme3-core/src/main/java/com/jme3/scene/BatchNode.java
  2. 90 0
      jme3-core/src/tools/java/jme3tools/optimize/GeometryBatchFactory.java

+ 7 - 5
jme3-core/src/main/java/com/jme3/scene/BatchNode.java

@@ -583,11 +583,13 @@ public class BatchNode extends GeometryGroupNode {
                         useTangents = true;
                     }
                 } else {
-                    inBuf.copyElements(0, outBuf, globalVertIndex, geomVertCount);
-//                    for (int vert = 0; vert < geomVertCount; vert++) {
-//                        int curGlobalVertIndex = globalVertIndex + vert;
-//                        inBuf.copyElement(vert, outBuf, curGlobalVertIndex);
-//                    }
+                    if (inBuf == null) {
+                        throw new IllegalArgumentException("Geometry " + geom.getName() + " has no " + outBuf.getBufferType() + " buffer whereas other geoms have. all geometries should have the same types of buffers.\n Try to use GeometryBatchFactory.alignBuffer() on the BatchNode before batching");
+                    } else if (outBuf == null) {
+                        throw new IllegalArgumentException("Geometry " + geom.getName() + " has a " + outBuf.getBufferType() + " buffer whereas other geoms don't. all geometries should have the same types of buffers.\n Try to use GeometryBatchFactory.alignBuffer() on the BatchNode before batching");
+                    } else {
+                        inBuf.copyElements(0, outBuf, globalVertIndex, geomVertCount);
+                    }
                 }
             }
 

+ 90 - 0
jme3-core/src/tools/java/jme3tools/optimize/GeometryBatchFactory.java

@@ -16,6 +16,7 @@ import java.nio.FloatBuffer;
 import java.nio.IntBuffer;
 import java.nio.ShortBuffer;
 import java.util.*;
+import java.util.logging.Level;
 import java.util.logging.Logger;
 
 public class GeometryBatchFactory {
@@ -453,4 +454,93 @@ public class GeometryBatchFactory {
         mergeGeometries(geoms, outMesh);
         printMesh(outMesh);
     }
+    
+    /**
+     * Options to align the buffers of geometries' meshes of a sub graph
+     * 
+     */
+    public static enum AlignOption {
+        
+        /**
+         * Will remove the buffers of a type that is not on all the geometries
+         */
+        RemoveUnalignedBuffers,
+        /**
+         * Will create missing buffers and pad with dummy data
+         */
+        CreateMissingBuffers
+    }
+
+    /**
+     * Will ensure that all the geometries' meshes of the n sub graph have the 
+     * same types of buffers
+     * @param n the node to gather geometries from
+     * @param option the align options 
+     * @see AlignOption
+     * 
+     * Very experimental for now.
+     */
+    public static void alignBuffers(Node n, AlignOption option) {
+        List<Geometry> geoms = new ArrayList<Geometry>();
+        gatherGeoms(n, geoms);
+
+        //gather buffer types
+        Map<VertexBuffer.Type, VertexBuffer> types = new EnumMap<VertexBuffer.Type, VertexBuffer>(VertexBuffer.Type.class);
+        Map<VertexBuffer.Type, Integer> typesCount = new EnumMap<VertexBuffer.Type, Integer>(VertexBuffer.Type.class);
+        for (Geometry geom : geoms) {
+            for (VertexBuffer buffer : geom.getMesh().getBufferList()) {
+                if (types.get(buffer.getBufferType()) == null) {
+                    types.put(buffer.getBufferType(), buffer);
+                    logger.log(Level.FINE, buffer.getBufferType().toString());
+                }
+                Integer count = typesCount.get(buffer.getBufferType());
+                if (count == null) {
+                    count = 0;
+                }
+                count++;
+                typesCount.put(buffer.getBufferType(), count);
+            }
+        }
+
+        switch (option) {
+            case RemoveUnalignedBuffers:
+                for (Geometry geom : geoms) {
+
+                    for (VertexBuffer buffer : geom.getMesh().getBufferList()) {
+                        Integer count = typesCount.get(buffer.getBufferType());
+                        if (count != null && count < geoms.size()) {
+                            geom.getMesh().clearBuffer(buffer.getBufferType());
+                            logger.log(Level.FINE, "removing {0} from {1}", new Object[]{buffer.getBufferType(), geom.getName()});
+
+                        }
+                    }
+                }
+                break;
+            case CreateMissingBuffers:
+                for (Geometry geom : geoms) {
+                    for (VertexBuffer.Type type : types.keySet()) {
+                        if (geom.getMesh().getBuffer(type) == null) {
+                            VertexBuffer vb = new VertexBuffer(type);
+                            Buffer b;
+                            switch (type) {
+                                case Index:
+                                case BoneIndex:
+                                case HWBoneIndex:
+                                    b = BufferUtils.createIntBuffer(geom.getMesh().getVertexCount() * types.get(type).getNumComponents());
+                                    break;
+                                case InterleavedData:
+                                    b = BufferUtils.createByteBuffer(geom.getMesh().getVertexCount() * types.get(type).getNumComponents());
+                                    break;
+                                default:
+                                    b = BufferUtils.createFloatBuffer(geom.getMesh().getVertexCount() * types.get(type).getNumComponents());
+                            }
+                            vb.setupData(types.get(type).getUsage(), types.get(type).getNumComponents(), types.get(type).getFormat(), b);
+                            geom.getMesh().setBuffer(vb);
+                            logger.log(Level.FINE, "geom {0} misses buffer {1}. Creating", new Object[]{geom.getName(), type});
+                        }
+                    }
+                }
+                break;
+        }
+    }
 }