I’m trying to add some icons to the GUI node. I use two Pictures, one for the background and one for the actual content. Both the background and icon have transparency (useAlpha set to true when loading the image for Picture). Then I try to bring the content forward on Z axis so it would be in the foreground. No matter what value I use, the result is always completely random. Some of the icons are proper, but most are not. Which ones are correct also changes every time I relaunch the app.
Probably because it takes your nicely sortable separate objects and turns them into one big object that can no longer be sorted by Z value. So you get whatever sort order it decided to batch.
In my opinion, it would be nice if it provided a way to sort the geometries (custom comparator or whatever)… but I think the version that takes a list probably leaves them in that list order. So you might be able to hack around it.
No, I didn’t really try it since I’m running low on time and I have things with higher priority to do right now than worrying about one batch not working. After I finish the actual editor I will revisit this.
I made a GeometryBatchFactoryUtil that can check useData to see if a geometry should be batched. Pretty happy of the results. Sure could be made better.
package com.cis.pipesandstuff.common;
import com.jme3.math.Transform;
import com.jme3.renderer.queue.RenderQueue.Bucket;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import jme3tools.optimize.GeometryBatchFactory;
/**
*
* @author jo
*/
public class GeometryBatchFactoryUtil {
public final static String FLAG_FOR_OPTIMIZE = "OPTIMIZE";
public enum OptimizeFilter {
OPAQUE, FLAGGED_FOR_OPTIMIZATION;
}
public static Node optimize(Node scene, boolean useLods, OptimizeFilter optimizeFilter){
ArrayList<Geometry> geoms = new ArrayList<Geometry>();
switch(optimizeFilter){
case OPAQUE:
gatherGeomsOpaque(scene, geoms);
break;
case FLAGGED_FOR_OPTIMIZATION:
gatherGeomsFlagged(scene, geoms);
break;
}
List<Geometry> batchedGeoms = GeometryBatchFactory.makeBatches(geoms, useLods);
for (Geometry geom : batchedGeoms) {
scene.attachChild(geom);
}
for (Iterator<Geometry> it = geoms.iterator(); it.hasNext();) {
Geometry geometry = it.next();
geometry.removeFromParent();
}
// Since the scene is returned unaltered the transform must be reset
scene.setLocalTransform(Transform.IDENTITY);
return scene;
}
private static void gatherGeomsOpaque(Spatial scene, List<Geometry> geoms) {
if (scene instanceof Node) {
Node node = (Node) scene;
for (Spatial child : node.getChildren()) {
gatherGeomsOpaque(child, geoms);
}
} else if (scene instanceof Geometry) {
Geometry geometry = (Geometry)scene;
if ( geometry.getQueueBucket() == Bucket.Opaque ) {
geoms.add((Geometry) scene);
}
}
}
private static void gatherGeomsFlagged(Spatial scene, List<Geometry> geoms) {
if (scene instanceof Node) {
Node node = (Node) scene;
for (Spatial child : node.getChildren()) {
gatherGeomsFlagged(child, geoms);
}
} else if (scene instanceof Geometry) {
Geometry geometry = (Geometry)scene;
if ( geometry.getUserData(FLAG_FOR_OPTIMIZE) != null ) {
geoms.add((Geometry) scene);
}
}
}
}
I think I can abandon this, since I don’t need batching anymore. For some reason my phone was falling back to OpenGL ES 1.0. Forcing it to use 2.0 increased my fps a ton and now I’m not really worrying about batching.