Skip to content

Commit

Permalink
Add flag to toggle using the quadtree for object culling
Browse files Browse the repository at this point in the history
  • Loading branch information
ultraq committed Jun 27, 2024
1 parent 9024f39 commit 5a46468
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ class RenderPipeline implements AutoCloseable {
private class SceneRenderPass implements RenderPass<Void> {

final Framebuffer framebuffer
private final boolean traverseScene = true
private final FrustumIntersection frustumIntersection = new FrustumIntersection()

Scene scene
Expand Down Expand Up @@ -201,17 +202,29 @@ class RenderPipeline implements AutoCloseable {
// Cull the list of renderable items to those just visible in the scene
average('objectCulling', 1f, logger) { ->
visibleElements.clear()
frustumIntersection.set(camera.viewProjection, false)
scene.traverse { Node element ->
if (element.isVisible(frustumIntersection)) {

if (traverseScene) {
frustumIntersection.set(camera.viewProjection, false)
scene.traverse { Node element ->
if (element.isVisible(frustumIntersection)) {
if (element instanceof GraphicsElement) {
element.update()
element.script?.update()
visibleElements << element
}
return true
}
return false
}
}
else {
scene.quadTree.query(camera.viewBox).each { Node element ->
if (element instanceof GraphicsElement) {
element.update()
element.script?.update()
visibleElements << element
}
return true
}
return false
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import nz.net.ultraq.redhorizon.engine.scenegraph.Scene

import org.joml.Matrix4f
import org.joml.Vector3f
import org.joml.primitives.Rectanglef
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import static org.lwjgl.system.MemoryStack.stackPush
Expand All @@ -39,21 +40,21 @@ class Camera extends Node<Camera> {

private static final Logger logger = LoggerFactory.getLogger(Camera)

private final Rectanglef box
private final Matrix4f projection
private final Matrix4f view
private final Matrix4f viewTransform = new Matrix4f()
private final Matrix4f viewProjection = new Matrix4f()
private UniformBuffer viewProjectionBuffer
private final Rectanglef boxTransform = new Rectanglef()

/**
* Constructor, build a camera to work with the given dimensions.
*/
Camera(Dimension size) {

projection = new Matrix4f().setOrtho2D(
-size.width() / 2, size.width() / 2,
-size.height() / 2, size.height() / 2
)
box = new Rectanglef(-size.width() / 2, -size.height() / 2, size.width() / 2, size.height() / 2)
projection = new Matrix4f().setOrtho2D(box.minX, box.maxX, box.minY, box.maxY)
logger.debug('Establishing an orthographic projection of {}x{}', size.width(), size.height())

view = new Matrix4f().setLookAt(
Expand Down Expand Up @@ -81,6 +82,16 @@ class Camera extends Node<Camera> {
return view.mulAffine(transform, viewTransform)
}

/**
* Return a rectangle that represents the 2D area being viewed by this
* orthographic projection camera.
*/
Rectanglef getViewBox() {

var position = getPosition()
return box.translate(position.x, position.y, boxTransform)
}

/**
* Return a matrix that is the projection * view * local transform of this
* camera. Note that the returned matrix is a live value, so be sure to wrap
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,22 @@ class QuadTree {
return quadrants.any { quadrant -> quadrant.add(node) }
}

/**
* Return all nodes that are within the bounding box of {@code range}.
*/
List<Node> query(Rectanglef range, List<Node> results = new ArrayList<>()) {

if (area.intersectsRectangle(range)) {
if (children) {
results.addAll(children)
}
else if (quadrants) {
quadrants*.query(range, results)
}
}
return results
}

/**
* Removes a node from this quadtree. Nodes will attempt to rebalance
* themselves if quadrants can also be removed.
Expand All @@ -148,7 +164,7 @@ class QuadTree {
children.remove(node)

// If all children removed, rebalance the parent node
if (!children && !parent.size()) {
if (!children && !parent?.size()) {
// TODO: There are probably some smarts we can do here, but for now
// the only rebalancing we're doing is to collapse a node with
// 4 empty quadrants
Expand Down

0 comments on commit 5a46468

Please sign in to comment.