com.cyphercove.gdx.flexbatch.utils.BatchableSorter Maven / Gradle / Ivy
Show all versions of flexbatch Show documentation
/*******************************************************************************
* Copyright 2017 See AUTHORS file.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package com.cyphercove.gdx.flexbatch.utils;
import java.util.Comparator;
import com.badlogic.gdx.graphics.Camera;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.ObjectMap;
import com.badlogic.gdx.utils.ObjectSet;
import com.badlogic.gdx.utils.Pool;
import com.cyphercove.gdx.flexbatch.Batchable;
import com.cyphercove.gdx.flexbatch.FlexBatch;
/** Sorts 3D {@link Batchable Batchables} to ensure proper render order before passing them to a {@link FlexBatch}.
*
* Opaque Batchables are sorted by texture configuration to minimize flushes and drawn first. Blended Batchables are sorted by
* distance from camera and drawn far to near.
*
* @author cypherdare */
public class BatchableSorter> {
protected final int opaqueInitialCapacityPerTexture;
private final ObjectMap> opaqueBatchables; // first entered to material group
private final Array blendedBatchables;
private final Comparator comparator;
protected Vector3 cameraPosition;
private boolean needSort;
private Pool> objectSetPool = new Pool>() {
protected void reset (ObjectSet object) {
object.clear();
}
protected ObjectSet newObject () {
return new ObjectSet(opaqueInitialCapacityPerTexture);
}
};
public BatchableSorter (Camera camera) {
this(camera, 2, 1000, 1000);
}
public BatchableSorter (Camera camera, int opaqueIntialTextureCapacity, int opaqueInitialCapacityPerTexture,
int blendedInitialCapacity) {
this.cameraPosition = camera.position;
this.opaqueInitialCapacityPerTexture = opaqueInitialCapacityPerTexture;
opaqueBatchables = new ObjectMap>();
for (int i = 0; i < opaqueIntialTextureCapacity; i++) { // seed the pool to avoid delay on first use
objectSetPool.free(objectSetPool.obtain());
}
blendedBatchables = new Array(blendedInitialCapacity);
comparator = new Comparator() {
public int compare (T o1, T o2) {
return (int)Math.signum(o2.calculateDistanceSquared(cameraPosition) - o1.calculateDistanceSquared(cameraPosition));
}
};
}
/** Clear the queue without drawing anything. */
public void clear () {
for (ObjectSet set : opaqueBatchables.values())
objectSetPool.free(set);
opaqueBatchables.clear();
blendedBatchables.clear();
}
/** Sort (if necessary) and draw the queued Batchables without clearing them. Must be called in between
* {@link FlexBatch#begin()} and {@link FlexBatch#end()}. */
public void draw (FlexBatch flexBatch) {
if (needSort) {
blendedBatchables.sort(comparator);
needSort = false;
}
for (ObjectSet set : opaqueBatchables.values())
for (T batchable : set)
flexBatch.draw(batchable);
for (T batchable : blendedBatchables)
flexBatch.draw(batchable);
}
/** Sort (if necessary), draw, and clear references to the queued Batchables. Must be called in between
* {@link FlexBatch#begin()} and {@link FlexBatch#end()}. */
public void flush (FlexBatch flexBatch) {
draw(flexBatch);
clear();
}
/** Add a Batchable to the queue. */
public void add (T batchable) {
if (batchable.isOpaque()) {
for (ObjectMap.Entry> entry : opaqueBatchables) {
if (batchable.hasEquivalentTextures(entry.key)) {
entry.value.add((T)batchable);
return;
}
}
ObjectSet set = objectSetPool.obtain();
set.add(batchable);
opaqueBatchables.put(batchable, set);
} else {
blendedBatchables.add(batchable);
}
needSort = true;
}
/** Sets the camera that is used for distance comparisons to sort the blended Batchables. */
public void setCamera (Camera camera) {
cameraPosition = camera.position;
}
}