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.
experimental
Nehon 10 years ago
parent f8dd2542b1
commit 91cf9e645c
  1. 12
      jme3-core/src/main/java/com/jme3/scene/BatchNode.java
  2. 90
      jme3-core/src/tools/java/jme3tools/optimize/GeometryBatchFactory.java

@ -583,11 +583,13 @@ public class BatchNode extends GeometryGroupNode {
useTangents = true; useTangents = true;
} }
} else { } else {
inBuf.copyElements(0, outBuf, globalVertIndex, geomVertCount); if (inBuf == null) {
// for (int vert = 0; vert < geomVertCount; vert++) { 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");
// int curGlobalVertIndex = globalVertIndex + vert; } else if (outBuf == null) {
// inBuf.copyElement(vert, outBuf, curGlobalVertIndex); 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);
}
} }
} }

@ -16,6 +16,7 @@ import java.nio.FloatBuffer;
import java.nio.IntBuffer; import java.nio.IntBuffer;
import java.nio.ShortBuffer; import java.nio.ShortBuffer;
import java.util.*; import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
public class GeometryBatchFactory { public class GeometryBatchFactory {
@ -453,4 +454,93 @@ public class GeometryBatchFactory {
mergeGeometries(geoms, outMesh); mergeGeometries(geoms, outMesh);
printMesh(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;
}
}
} }

Loading…
Cancel
Save