BatchNode enhancements :

- batching after adding a new geometry only does an incremental batch instead of rebatching all geometries
- there is now a getOffsetIndex(geometry) method that returns the index of the first vertex of the geometry in the batch.

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9176 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
rem..om 13 years ago
parent 446c03935e
commit 03da8d5316
  1. 64
      engine/src/core/com/jme3/scene/BatchNode.java
  2. 4
      engine/src/core/com/jme3/scene/Geometry.java

@ -80,6 +80,7 @@ public class BatchNode extends Node implements Savable {
private float[] tmpFloatT;
int maxVertCount = 0;
boolean useTangents = false;
boolean needsFullRebatch = true;
/**
* Construct a batchNode
@ -178,16 +179,25 @@ public class BatchNode extends Node implements Savable {
}
protected void doBatch() {
///List<Geometry> tmpList = new ArrayList<Geometry>();
Map<Material, List<Geometry>> matMap = new HashMap<Material, List<Geometry>>();
maxVertCount = 0;
gatherGeomerties(matMap, this);
batches.clear();
int nbGeoms = 0;
gatherGeomerties(matMap, this, needsFullRebatch);
if (needsFullRebatch) {
for (Batch batch : batches.values()) {
batch.geometry.removeFromParent();
}
batches.clear();
}
for (Material material : matMap.keySet()) {
Mesh m = new Mesh();
List<Geometry> list = matMap.get(material);
nbGeoms += list.size();
if (!needsFullRebatch) {
list.add(batches.get(material).geometry);
}
mergeGeometries(m, list);
m.setDynamic();
Batch batch = new Batch();
@ -202,30 +212,36 @@ public class BatchNode extends Node implements Savable {
batch.geometry.getMesh().updateBound();
batches.put(material, batch);
}
logger.log(Level.INFO, "Batched {0} geometries in {1} batches.", new Object[]{nbGeoms, batches.size()});
//init temp float arrays
tmpFloat = new float[maxVertCount * 3];
tmpFloatN = new float[maxVertCount * 3];
if (useTangents) {
tmpFloatT = new float[maxVertCount * 4];
}
logger.log(Level.INFO, "Batched {0} geometries in {1} batches.", new Object[]{nbGeoms, batches.size()});
}
private void gatherGeomerties(Map<Material, List<Geometry>> map, Spatial n) {
private void gatherGeomerties(Map<Material, List<Geometry>> map, Spatial n, boolean rebatch) {
if (n.getClass() == Geometry.class) {
if (!isBatch(n) && n.getBatchHint() != BatchHint.Never) {
Geometry g = (Geometry) n;
if (g.getMaterial() == null) {
throw new IllegalStateException("No material is set for Geometry: " + g.getName() + " please set a material before batching");
}
List<Geometry> list = map.get(g.getMaterial());
if (list == null) {
list = new ArrayList<Geometry>();
map.put(g.getMaterial(), list);
if (!g.isBatched() || rebatch) {
if (g.getMaterial() == null) {
throw new IllegalStateException("No material is set for Geometry: " + g.getName() + " please set a material before batching");
}
List<Geometry> list = map.get(g.getMaterial());
if (list == null) {
list = new ArrayList<Geometry>();
map.put(g.getMaterial(), list);
}
g.setTransformRefresh();
list.add(g);
}
list.add(g);
}
} else if (n instanceof Node) {
@ -233,7 +249,7 @@ public class BatchNode extends Node implements Savable {
if (child instanceof BatchNode) {
continue;
}
gatherGeomerties(map, child);
gatherGeomerties(map, child, rebatch);
}
}
@ -465,12 +481,12 @@ public class BatchNode extends Node implements Savable {
}
} else if (VertexBuffer.Type.Position.ordinal() == bufType) {
FloatBuffer inPos = (FloatBuffer) inBuf.getData();
FloatBuffer outPos = (FloatBuffer) outBuf.getData();
doCopyBuffer(inPos, globalVertIndex, outPos,3);
FloatBuffer outPos = (FloatBuffer) outBuf.getData();
doCopyBuffer(inPos, globalVertIndex, outPos, 3);
} else if (VertexBuffer.Type.Normal.ordinal() == bufType || VertexBuffer.Type.Tangent.ordinal() == bufType) {
FloatBuffer inPos = (FloatBuffer) inBuf.getData();
FloatBuffer outPos = (FloatBuffer) outBuf.getData();
doCopyBuffer(inPos, globalVertIndex, outPos,compsForBuf[bufType]);
FloatBuffer outPos = (FloatBuffer) outBuf.getData();
doCopyBuffer(inPos, globalVertIndex, outPos, compsForBuf[bufType]);
if (VertexBuffer.Type.Tangent.ordinal() == bufType) {
useTangents = true;
}
@ -584,9 +600,9 @@ public class BatchNode extends Node implements Savable {
tmpFloatT[tanIndex++] = tan.x;
tmpFloatT[tanIndex++] = tan.y;
tmpFloatT[tanIndex++] = tan.z;
//Skipping 4th element of tangent buffer (handedness)
tanIndex++;
tanIndex++;
}
vars.release();
@ -626,4 +642,12 @@ public class BatchNode extends Node implements Savable {
Geometry geometry;
boolean needMeshUpdate = false;
}
protected void setNeedsFullRebatch(boolean needsFullRebatch) {
this.needsFullRebatch = needsFullRebatch;
}
public int getOffsetIndex(Geometry batchedGeometry){
return batchedGeometry.startIndex;
}
}

@ -322,8 +322,8 @@ public class Geometry extends Spatial {
this.startIndex = 0;
prevBatchTransforms = null;
cachedOffsetMat = null;
//once the geometry is removed from the screnegraph we call batch on the batchNode before unreferencing it.
this.batchNode.batch();
//once the geometry is removed from the screnegraph the batchNode needs to be rebatched.
this.batchNode.setNeedsFullRebatch(true);
this.batchNode = null;
setCullHint(CullHint.Dynamic);
}

Loading…
Cancel
Save