Lods for GeometryBatchFactory

Hey.

I wanted my batches to retain the lod steps of my original objects, so i’ve made a little patch to GeometryBatchFactory.

It only supports making lods for batched objects of the same kind (due to how it’s set up).

It can still be used as before, but i’ve added a new method called:

optimize(Spatial scene, boolean makeLods);

calling optimize(Spatial scene) will not try to make lods.



[java]Index: GeometryBatchFactory.java

===================================================================

— GeometryBatchFactory.java (revision 6855)

+++ GeometryBatchFactory.java (working copy)

@@ -18,9 +18,12 @@

import com.jme3.scene.mesh.VirtualIndexBuffer;

import com.jme3.scene.mesh.WrappedIndexBuffer;

import com.jme3.scene.shape.Quad;

+import com.jme3.util.BufferUtils;

import com.jme3.util.IntMap.Entry;

import java.nio.Buffer;

import java.nio.FloatBuffer;

+import java.nio.IntBuffer;

+import java.nio.ShortBuffer;

import java.util.ArrayList;

import java.util.Collection;

import java.util.HashMap;

@@ -204,10 +207,58 @@

globalVertIndex += geomVertCount;

globalTriIndex += geomTriCount;

}

+

}


  • public static void makeLods(Collection<Geometry> geometries, Mesh outMesh){
  •    int lodLevels = 0;<br />
    
  •    int[] lodSize = null;<br />
    
  •    int index = 0;<br />
    
  •    for(Geometry g : geometries){<br />
    
  •        if(lodLevels == 0) lodLevels = g.getMesh().getNumLodLevels();<br />
    
  •        if(lodSize == null) lodSize = new int[lodLevels];<br />
    
  •        for(int i = 0; i &lt; lodLevels; i++){<br />
    
  •            lodSize<i> += g.getMesh().getLodLevel(i).getData().capacity();<br />
    
  •            //if( i == 0) System.out.println(index + &quot; &quot; +lodSize<i>);<br />
    
  •        }<br />
    
  •        index++;<br />
    
  •    }<br />
    
  •    int[][] lodData = new int[lodLevels][];<br />
    
  •    for(int i = 0; i &lt; lodLevels; i++){<br />
    
  •        lodData<i> = new int[lodSize<i>];<br />
    
  •    }<br />
    
  •    VertexBuffer[] lods = new VertexBuffer[lodLevels];<br />
    

+ int bufferPos[] = new int[lodLevels];
+ //int index = 0;
+ int numOfVertices = 0;
+ int curGeom = 0;
+ for(Geometry g : geometries){
+ if (numOfVertices == 0) numOfVertices = g.getVertexCount();
+ for(int i = 0; i < lodLevels; i++){
+ ShortBuffer buffer = (ShortBuffer)g.getMesh().getLodLevel(i).getData();
+ buffer.rewind();
+ //System.out.println("buffer: " + buffer.capacity() + " limit: " + lodSize + " " + index);
+ for(int j = 0; j < buffer.capacity(); j++){
+ lodData[bufferPos+j] = buffer.get() + numOfVertices * curGeom;
+ //bufferPos++;
+ }
+ bufferPos += buffer.capacity();
+ }
+ curGeom++;
+ }
+ for(int i = 0; i < lodLevels; i++){
+ lods = new VertexBuffer(Type.Index);
+ lods.setupData(Usage.Dynamic, 1, Format.UnsignedInt, BufferUtils.createIntBuffer(lodData));
+ }
+ outMesh.setLodLevels(lods);
+ }
+
public static List<Geometry> makeBatches(Collection<Geometry> geometries){
+ return makeBatches(geometries, false);
+ }
+
+ public static List<Geometry> makeBatches(Collection<Geometry> geometries, boolean useLods){
ArrayList<Geometry> retVal = new ArrayList<Geometry>();
HashMap<Material, List<Geometry>> matToGeom = new HashMap<Material, List<Geometry>>();

@@ -226,6 +277,10 @@
List<Geometry> geomsForMat = entry.getValue();
Mesh mesh = new Mesh();
mergeGeometries(geomsForMat, mesh);
+
+ // lods
+ if(useLods) makeLods(geomsForMat, mesh);
+
mesh.updateCounts();
mesh.updateBound();

@@ -234,6 +289,7 @@
retVal.add(out);
}

+
return retVal;
}

@@ -249,16 +305,25 @@
}

public static Spatial optimize(Spatial scene){
+ return optimize(scene, false);
+ }
+
+ public static Spatial optimize(Spatial scene, boolean useLods){
ArrayList<Geometry> geoms = new ArrayList<Geometry>();
+ Node node = new Node(scene.getName());
+ try{
gatherGeoms(scene, geoms);
+ System.out.println(scene.getName() + " starting geoms: " + geoms.size());
+ List<Geometry> batchedGeoms = makeBatches(geoms, useLods);

- List<Geometry> batchedGeoms = makeBatches(geoms);
-
- Node node = new Node(scene.getName());
+
for (Geometry geom : batchedGeoms){
node.attachChild(geom);
}
-
+ } catch (OutOfMemoryError e){
+ System.out.println("out of memory");
+ }
+ //System.out.println(scene.getName() + " optimized to " + node.getQuantity());
return node;
}[/java]
1 Like