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
This commit is contained in:
parent
446c03935e
commit
03da8d5316
@ -80,6 +80,7 @@ public class BatchNode extends Node implements Savable {
|
|||||||
private float[] tmpFloatT;
|
private float[] tmpFloatT;
|
||||||
int maxVertCount = 0;
|
int maxVertCount = 0;
|
||||||
boolean useTangents = false;
|
boolean useTangents = false;
|
||||||
|
boolean needsFullRebatch = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a batchNode
|
* Construct a batchNode
|
||||||
@ -178,16 +179,25 @@ public class BatchNode extends Node implements Savable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void doBatch() {
|
protected void doBatch() {
|
||||||
///List<Geometry> tmpList = new ArrayList<Geometry>();
|
|
||||||
Map<Material, List<Geometry>> matMap = new HashMap<Material, List<Geometry>>();
|
Map<Material, List<Geometry>> matMap = new HashMap<Material, List<Geometry>>();
|
||||||
maxVertCount = 0;
|
maxVertCount = 0;
|
||||||
gatherGeomerties(matMap, this);
|
|
||||||
batches.clear();
|
|
||||||
int nbGeoms = 0;
|
int nbGeoms = 0;
|
||||||
|
|
||||||
|
gatherGeomerties(matMap, this, needsFullRebatch);
|
||||||
|
if (needsFullRebatch) {
|
||||||
|
for (Batch batch : batches.values()) {
|
||||||
|
batch.geometry.removeFromParent();
|
||||||
|
}
|
||||||
|
batches.clear();
|
||||||
|
}
|
||||||
|
|
||||||
for (Material material : matMap.keySet()) {
|
for (Material material : matMap.keySet()) {
|
||||||
Mesh m = new Mesh();
|
Mesh m = new Mesh();
|
||||||
List<Geometry> list = matMap.get(material);
|
List<Geometry> list = matMap.get(material);
|
||||||
nbGeoms += list.size();
|
nbGeoms += list.size();
|
||||||
|
if (!needsFullRebatch) {
|
||||||
|
list.add(batches.get(material).geometry);
|
||||||
|
}
|
||||||
mergeGeometries(m, list);
|
mergeGeometries(m, list);
|
||||||
m.setDynamic();
|
m.setDynamic();
|
||||||
Batch batch = new Batch();
|
Batch batch = new Batch();
|
||||||
@ -202,30 +212,36 @@ public class BatchNode extends Node implements Savable {
|
|||||||
batch.geometry.getMesh().updateBound();
|
batch.geometry.getMesh().updateBound();
|
||||||
batches.put(material, batch);
|
batches.put(material, batch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.log(Level.INFO, "Batched {0} geometries in {1} batches.", new Object[]{nbGeoms, batches.size()});
|
||||||
|
|
||||||
|
|
||||||
//init temp float arrays
|
//init temp float arrays
|
||||||
tmpFloat = new float[maxVertCount * 3];
|
tmpFloat = new float[maxVertCount * 3];
|
||||||
tmpFloatN = new float[maxVertCount * 3];
|
tmpFloatN = new float[maxVertCount * 3];
|
||||||
if (useTangents) {
|
if (useTangents) {
|
||||||
tmpFloatT = new float[maxVertCount * 4];
|
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 (n.getClass() == Geometry.class) {
|
||||||
|
|
||||||
if (!isBatch(n) && n.getBatchHint() != BatchHint.Never) {
|
if (!isBatch(n) && n.getBatchHint() != BatchHint.Never) {
|
||||||
Geometry g = (Geometry) n;
|
Geometry g = (Geometry) n;
|
||||||
if (g.getMaterial() == null) {
|
if (!g.isBatched() || rebatch) {
|
||||||
throw new IllegalStateException("No material is set for Geometry: " + g.getName() + " please set a material before batching");
|
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<Geometry> list = map.get(g.getMaterial());
|
|
||||||
if (list == null) {
|
|
||||||
list = new ArrayList<Geometry>();
|
|
||||||
map.put(g.getMaterial(), list);
|
|
||||||
}
|
|
||||||
list.add(g);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (n instanceof Node) {
|
} else if (n instanceof Node) {
|
||||||
@ -233,7 +249,7 @@ public class BatchNode extends Node implements Savable {
|
|||||||
if (child instanceof BatchNode) {
|
if (child instanceof BatchNode) {
|
||||||
continue;
|
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) {
|
} else if (VertexBuffer.Type.Position.ordinal() == bufType) {
|
||||||
FloatBuffer inPos = (FloatBuffer) inBuf.getData();
|
FloatBuffer inPos = (FloatBuffer) inBuf.getData();
|
||||||
FloatBuffer outPos = (FloatBuffer) outBuf.getData();
|
FloatBuffer outPos = (FloatBuffer) outBuf.getData();
|
||||||
doCopyBuffer(inPos, globalVertIndex, outPos,3);
|
doCopyBuffer(inPos, globalVertIndex, outPos, 3);
|
||||||
} else if (VertexBuffer.Type.Normal.ordinal() == bufType || VertexBuffer.Type.Tangent.ordinal() == bufType) {
|
} else if (VertexBuffer.Type.Normal.ordinal() == bufType || VertexBuffer.Type.Tangent.ordinal() == bufType) {
|
||||||
FloatBuffer inPos = (FloatBuffer) inBuf.getData();
|
FloatBuffer inPos = (FloatBuffer) inBuf.getData();
|
||||||
FloatBuffer outPos = (FloatBuffer) outBuf.getData();
|
FloatBuffer outPos = (FloatBuffer) outBuf.getData();
|
||||||
doCopyBuffer(inPos, globalVertIndex, outPos,compsForBuf[bufType]);
|
doCopyBuffer(inPos, globalVertIndex, outPos, compsForBuf[bufType]);
|
||||||
if (VertexBuffer.Type.Tangent.ordinal() == bufType) {
|
if (VertexBuffer.Type.Tangent.ordinal() == bufType) {
|
||||||
useTangents = true;
|
useTangents = true;
|
||||||
}
|
}
|
||||||
@ -584,9 +600,9 @@ public class BatchNode extends Node implements Savable {
|
|||||||
tmpFloatT[tanIndex++] = tan.x;
|
tmpFloatT[tanIndex++] = tan.x;
|
||||||
tmpFloatT[tanIndex++] = tan.y;
|
tmpFloatT[tanIndex++] = tan.y;
|
||||||
tmpFloatT[tanIndex++] = tan.z;
|
tmpFloatT[tanIndex++] = tan.z;
|
||||||
|
|
||||||
//Skipping 4th element of tangent buffer (handedness)
|
//Skipping 4th element of tangent buffer (handedness)
|
||||||
tanIndex++;
|
tanIndex++;
|
||||||
|
|
||||||
}
|
}
|
||||||
vars.release();
|
vars.release();
|
||||||
@ -626,4 +642,12 @@ public class BatchNode extends Node implements Savable {
|
|||||||
Geometry geometry;
|
Geometry geometry;
|
||||||
boolean needMeshUpdate = false;
|
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;
|
this.startIndex = 0;
|
||||||
prevBatchTransforms = null;
|
prevBatchTransforms = null;
|
||||||
cachedOffsetMat = null;
|
cachedOffsetMat = null;
|
||||||
//once the geometry is removed from the screnegraph we call batch on the batchNode before unreferencing it.
|
//once the geometry is removed from the screnegraph the batchNode needs to be rebatched.
|
||||||
this.batchNode.batch();
|
this.batchNode.setNeedsFullRebatch(true);
|
||||||
this.batchNode = null;
|
this.batchNode = null;
|
||||||
setCullHint(CullHint.Dynamic);
|
setCullHint(CullHint.Dynamic);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user