@ -37,6 +37,7 @@ import com.jme3.math.Matrix4f;
import com.jme3.math.Transform ;
import com.jme3.math.Vector3f ;
import com.jme3.scene.mesh.IndexBuffer ;
import com.jme3.util.SafeArrayList ;
import com.jme3.util.TempVars ;
import java.io.IOException ;
import java.nio.Buffer ;
@ -68,11 +69,11 @@ public class BatchNode extends Node implements Savable {
private static final Logger logger = Logger . getLogger ( BatchNode . class . getName ( ) ) ;
/ * *
* the map of geometry holding the batched meshes
* the list of geometry holding the batched meshes
* /
protected Map < Material , Batch > batches = new HashMap < Material , Batch > ( ) ;
protected SafeArrayList < Batch > batches = new SafeArrayList < Batch > ( Batch . class ) ;
/ * *
* a map storing he batches by geometry to qickly acces the batch when updating
* a map storing he batches by geometry to qu ickly acces the batch when updating
* /
protected Map < Geometry , Batch > batchesByGeom = new HashMap < Geometry , Batch > ( ) ;
/ * *
@ -119,7 +120,7 @@ public class BatchNode extends Node implements Savable {
child . updateGeometricState ( ) ;
}
for ( Batch batch : batches . values ( ) ) {
for ( Batch batch : batches . getArray ( ) ) {
if ( batch . needMeshUpdate ) {
batch . geometry . getMesh ( ) . updateBound ( ) ;
batch . geometry . updateWorldBound ( ) ;
@ -176,7 +177,7 @@ public class BatchNode extends Node implements Savable {
public void batch ( ) {
doBatch ( ) ;
//we set the batch geometries to ignore transforms to avoid transforms of parent nodes to be applied twice
for ( Batch batch : batches . values ( ) ) {
for ( Batch batch : batches . getArray ( ) ) {
batch . geometry . setIgnoreTransform ( true ) ;
}
}
@ -188,7 +189,7 @@ public class BatchNode extends Node implements Savable {
gatherGeomerties ( matMap , this , needsFullRebatch ) ;
if ( needsFullRebatch ) {
for ( Batch batch : batches . values ( ) ) {
for ( Batch batch : batches . getArray ( ) ) {
batch . geometry . removeFromParent ( ) ;
}
batches . clear ( ) ;
@ -199,15 +200,26 @@ public class BatchNode extends Node implements Savable {
Material material = entry . getKey ( ) ;
List < Geometry > list = entry . getValue ( ) ;
nbGeoms + = list . size ( ) ;
String batchName = name + "-batch" + batches . size ( ) ;
Batch batch ;
if ( ! needsFullRebatch ) {
list . add ( batches . get ( material ) . geometry ) ;
batch = findBatchByMaterial ( material ) ;
if ( batch ! = null ) {
list . add ( 0 , batch . geometry ) ;
batchName = batch . geometry . getName ( ) ;
batch . geometry . removeFromParent ( ) ;
} else {
batch = new Batch ( ) ;
}
} else {
batch = new Batch ( ) ;
}
mergeGeometries ( m , list ) ;
m . setDynamic ( ) ;
Batch batch = new Batch ( ) ;
batch . updateGeomList ( list ) ;
batch . geometry = new Geometry ( name + "-batch" + batches . size ( ) ) ;
batch . geometry = new Geometry ( batchName ) ;
batch . geometry . setMaterial ( material ) ;
this . attachChild ( batch . geometry ) ;
@ -215,9 +227,13 @@ public class BatchNode extends Node implements Savable {
batch . geometry . setMesh ( m ) ;
batch . geometry . getMesh ( ) . updateCounts ( ) ;
batch . geometry . getMesh ( ) . updateBound ( ) ;
batches . put ( material , batch ) ;
batches . add ( batch ) ;
}
if ( batches . size ( ) > 0 ) {
needsFullRebatch = false ;
}
logger . log ( Level . INFO , "Batched {0} geometries in {1} batches." , new Object [ ] { nbGeoms , batches . size ( ) } ) ;
@ -241,9 +257,9 @@ public class BatchNode extends Node implements Savable {
}
List < Geometry > list = map . get ( g . getMaterial ( ) ) ;
if ( list = = null ) {
//trying to compare materials with the contentEquals method
//trying to compare materials with the isEqual method
for ( Map . Entry < Material , List < Geometry > > mat : map . entrySet ( ) ) {
if ( g . getMaterial ( ) . contentEquals ( mat . getKey ( ) ) ) {
if ( g . getMaterial ( ) . dynamicHashCode ( ) = = mat . getKey ( ) . dynamicHashCode ( ) ) {
list = mat . getValue ( ) ;
}
}
@ -268,8 +284,17 @@ public class BatchNode extends Node implements Savable {
}
private Batch findBatchByMaterial ( Material m ) {
for ( Batch batch : batches . getArray ( ) ) {
if ( batch . geometry . getMaterial ( ) . dynamicHashCode ( ) = = m . dynamicHashCode ( ) ) {
return batch ;
}
}
return null ;
}
private boolean isBatch ( Spatial s ) {
for ( Batch batch : batches . values ( ) ) {
for ( Batch batch : batches . getArray ( ) ) {
if ( batch . geometry = = s ) {
return true ;
}
@ -302,7 +327,7 @@ public class BatchNode extends Node implements Savable {
* /
public Material getMaterial ( ) {
if ( ! batches . isEmpty ( ) ) {
Batch b = batches . get ( batches . keySet ( ) . iterator ( ) . next ( ) ) ;
Batch b = batches . iterator ( ) . next ( ) ;
return b . geometry . getMaterial ( ) ;
}
return null ; //material;
@ -466,7 +491,9 @@ public class BatchNode extends Node implements Savable {
for ( Geometry geom : geometries ) {
Mesh inMesh = geom . getMesh ( ) ;
if ( ! isBatch ( geom ) ) {
geom . batch ( this , globalVertIndex ) ;
}
int geomVertCount = inMesh . getVertexCount ( ) ;
int geomTriCount = inMesh . getTriangleCount ( ) ;
@ -658,9 +685,11 @@ public class BatchNode extends Node implements Savable {
* /
void updateGeomList ( List < Geometry > list ) {
for ( Geometry geom : list ) {
if ( ! isBatch ( geom ) ) {
batchesByGeom . put ( geom , this ) ;
}
}
}
Geometry geometry ;
boolean needMeshUpdate = false ;
}