package com.cookbook.box2d;
import java.util.Comparator;
import java.util.PriorityQueue;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.RayCastCallback;
import com.badlogic.gdx.physics.box2d.World;
import com.badlogic.gdx.utils.TimeUtils;
/*
* @brief Deferred Raycaster implemented with a priority queue whose elements
* are processed within a budget-time frame per update
*
*/
public class RayCastManager {
private class RayCastRequest {
final public int priority;
final public Vector2 point1;
final public Vector2 point2;
final public RayCastCallback callback;
public RayCastRequest(int priority, Vector2 point1, Vector2 point2, RayCastCallback callback) {
this.priority = priority;
this.point1 = point1;
this.point2 = point2;
this.callback = callback;
}
}
private static final String TAG = "RaycastManager";
private float budgetTime;
private World world;
private PriorityQueue<RayCastRequest> requestQueue;
/**
* @param budgetTime limit time (in seconds) for processing requests each update tick.
*/
public RayCastManager(World world, float budgetTime) {
this.world = world;
this.budgetTime = budgetTime;
this.requestQueue = new PriorityQueue<RayCastRequest>(1, new Comparator<RayCastRequest>() {
@Override
public int compare(RayCastRequest o1, RayCastRequest o2) {
return o2.priority - o1.priority; // Reverse because head will be the least
}
});
}
public boolean addRequest(int priority, Vector2 point1, Vector2 point2, RayCastCallback callback) {
return requestQueue.add(new RayCastRequest(priority, new Vector2(point1), new Vector2(point2), callback));
}
public void update() {
long startTime = TimeUtils.nanoTime();
Gdx.app.log(TAG, " -- Begining of Update tick (" + requestQueue.size() + ") --");
RayCastRequest rr = requestQueue.poll();
while(rr != null && TimeUtils.timeSinceNanos(startTime) < budgetTime * 1000000000f){ //budgetTime * seconds to nano
world.rayCast(rr.callback, rr.point1, rr.point2);
Gdx.app.log(TAG, " " + rr.point1 + " - " + rr.point2 + " processed at (" + (TimeUtils.timeSinceNanos(startTime) / 1000000000f) + ") with priority: " + rr.priority);
rr = requestQueue.poll();
}
Gdx.app.log(TAG, " -- End of Update tick --");
}
}