Browse Source

SceneGraph: show how to implement object culling on the drawable group.

pull/405/head
Vladimír Vondruš 6 years ago
parent
commit
02a6747b73
  1. 31
      doc/snippets/MagnumSceneGraph.cpp
  2. 12
      src/Magnum/SceneGraph/Camera.h
  3. 21
      src/Magnum/SceneGraph/Drawable.h

31
doc/snippets/MagnumSceneGraph.cpp

@ -26,6 +26,7 @@
#include <algorithm>
#include "Magnum/Math/Matrix4.h"
#include "Magnum/Math/Intersection.h"
#include "Magnum/SceneGraph/Animable.h"
#include "Magnum/SceneGraph/AnimableGroup.h"
#include "Magnum/SceneGraph/AbstractGroupedFeature.h"
@ -349,4 +350,34 @@ camera.draw(drawableTransformations);
/* [Drawable-draw-order] */
}
{
Object3D cameraObject;
SceneGraph::Camera3D camera{cameraObject};
SceneGraph::DrawableGroup3D drawableGroup;
/* [Drawable-culling] */
struct CullableDrawable3D: SceneGraph::Drawable3D {
Range3D aabb; /* Relative to world origin */
// ...
};
/* Camera frustum relative to world origin */
auto frustum = Frustum::fromMatrix(camera.projectionMatrix()*camera.cameraMatrix());
/* Erase all items that don't pass the frustum check */
std::vector<std::pair<std::reference_wrapper<SceneGraph::Drawable3D>, Matrix4>>
drawableTransformations = camera.drawableTransformations(drawableGroup);
drawableTransformations.erase(std::remove_if(
drawableTransformations.begin(), drawableTransformations.end(),
[&](const std::pair<std::reference_wrapper<SceneGraph::Drawable3D>, Matrix4>& a) {
Range3D aabb = static_cast<CullableDrawable3D&>(a.first.get()).aabb;
return !Math::Intersection::rangeFrustum(aabb, frustum);
}),
drawableTransformations.end());
/* Draw just the visible part */
camera.draw(drawableTransformations);
/* [Drawable-culling] */
}
}

12
src/Magnum/SceneGraph/Camera.h

@ -189,10 +189,10 @@ template<UnsignedInt dimensions, class T> class Camera: public AbstractFeature<d
/**
* @brief Drawable transformations
*
* Returns calculated transformations for given group of drawables.
* Useful in combination with @ref draw(const std::vector<std::pair<std::reference_wrapper<Drawable<dimensions, T>>, MatrixTypeFor<dimensions, T>>>&)
* to provide custom draw order. See @ref SceneGraph-Drawable-draw-order
* for more information.
* Returns calculated camera-relative transformations for given group
* of drawables. Useful in combination with @ref draw(const std::vector<std::pair<std::reference_wrapper<Drawable<dimensions, T>>, MatrixTypeFor<dimensions, T>>>&)
* to implement custom draw order or object culling. See
* @ref SceneGraph-Drawable-draw-order for more information.
*/
std::vector<std::pair<std::reference_wrapper<Drawable<dimensions, T>>, MatrixTypeFor<dimensions, T>>> drawableTransformations(DrawableGroup<dimensions, T>& group);
@ -208,8 +208,8 @@ template<UnsignedInt dimensions, class T> class Camera: public AbstractFeature<d
* @brief Draw given drawables with transformations
*
* Useful in combination with @ref drawableTransformations() for
* drawing in a custom order. See @ref SceneGraph-Drawable-draw-order
* for more information.
* implementing custom draw order or object culling. See
* @ref SceneGraph-Drawable-draw-order for more information.
*/
void draw(const std::vector<std::pair<std::reference_wrapper<Drawable<dimensions, T>>, MatrixTypeFor<dimensions, T>>>& drawableTransformations);

21
src/Magnum/SceneGraph/Drawable.h

@ -111,17 +111,28 @@ parameters once for whole group instead of setting them again in each
@snippet MagnumSceneGraph-gl.cpp Drawable-multiple-groups
@section SceneGraph-Drawable-draw-order Custom draw order
@section SceneGraph-Drawable-draw-order Custom draw order and object culling
By default the contents of a drawable group are drawn in the order they were
By default all contents of a drawable group are drawn, in the order they were
added. In some cases you may want to draw them in a different order (for
example to have correctly sorted transparent objects) or draw just a subset
(for example to cull invisible objects way). That can be achieved using @ref Camera::drawableTransformations()
in combination with @ref Camera::draw(const std::vector<std::pair<std::reference_wrapper<Drawable<dimensions, T>>, MatrixTypeFor<dimensions, T>>>&) and applying @ref std::sort() with a custom
predicate on the drawable transformation list:
(for example to cull invisible objects away). That can be achieved using
@ref Camera::drawableTransformations() in combination with
@ref Camera::draw(const std::vector<std::pair<std::reference_wrapper<Drawable<dimensions, T>>, MatrixTypeFor<dimensions, T>>>&).
For example, to have the objects sorted back-to-front, apply @ref std::sort()
with a custom predicate on the drawable transformation list:
@snippet MagnumSceneGraph.cpp Drawable-draw-order
Another use case is object-level culling --- assuming each drawable instance
provides an *absolute* AABB, one can calculate the transformations, cull them
via e.g. @ref Math::Intersection::rangeFrustum() and then pass the filtered
vector to @ref Camera::draw(). To be clear, this approach depends on AABBs
provided as relative to world origin, the actual object transformations don't
get used in any way except being passed to the draw function:
@snippet MagnumSceneGraph.cpp Drawable-culling
@section SceneGraph-Drawable-explicit-specializations Explicit template specializations
The following specializations are explicitly compiled into @ref SceneGraph

Loading…
Cancel
Save