Browse Source

SceneGraph: ability to affect order of items drawn by Camera.

pull/272/head
Vladimír Vondruš 8 years ago
parent
commit
fafcdcfa1c
  1. 2
      doc/changelog.dox
  2. 20
      doc/snippets/MagnumSceneGraph.cpp
  3. 20
      src/Magnum/SceneGraph/Camera.h
  4. 29
      src/Magnum/SceneGraph/Camera.hpp
  5. 11
      src/Magnum/SceneGraph/Drawable.h
  6. 59
      src/Magnum/SceneGraph/Test/CameraTest.cpp

2
doc/changelog.dox

@ -84,6 +84,8 @@ See also:
@ref SceneGraph::TranslationRotationScalingTransformation3D transformation
implementations that store separate translation, rotation and scaling
parameters for easier use with animated scenes
- Ability to affect order of items drawn by @ref SceneGraph::Camera --- see
@ref SceneGraph-Drawable-draw-order for more information
@subsubsection changelog-latest-new-shaders Shaders library

20
doc/snippets/MagnumSceneGraph.cpp

@ -23,6 +23,8 @@
DEALINGS IN THE SOFTWARE.
*/
#include <algorithm>
#include "Magnum/Math/Matrix4.h"
#include "Magnum/SceneGraph/Animable.h"
#include "Magnum/SceneGraph/AnimableGroup.h"
@ -329,4 +331,22 @@ camera.setProjectionMatrix(Matrix4::perspectiveProjection(35.0_degf, 1.0f, 0.001
}
{
Object3D cameraObject;
SceneGraph::Camera3D camera{cameraObject};
SceneGraph::DrawableGroup3D drawableGroup;
/* [Drawable-draw-order] */
std::vector<std::pair<std::reference_wrapper<SceneGraph::Drawable3D>, Matrix4>>
drawableTransformations = camera.drawableTransformations(drawableGroup);
std::sort(drawableTransformations.begin(), drawableTransformations.end(),
[](const std::pair<std::reference_wrapper<SceneGraph::Drawable3D>, Matrix4>& a,
const std::pair<std::reference_wrapper<SceneGraph::Drawable3D>, Matrix4>& b) {
return a.second.translation().z() < b.second.translation().z();
});
camera.draw(drawableTransformations);
/* [Drawable-draw-order] */
}
}

20
src/Magnum/SceneGraph/Camera.h

@ -186,13 +186,33 @@ template<UnsignedInt dimensions, class T> class Camera: public AbstractFeature<d
*/
void setViewport(const Vector2i& size);
/**
* @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.
*/
std::vector<std::pair<std::reference_wrapper<Drawable<dimensions, T>>, MatrixTypeFor<dimensions, T>>> drawableTransformations(DrawableGroup<dimensions, T>& group);
/**
* @brief Draw
*
* Draws given group of drawables.
* @see @ref draw(const std::vector<std::pair<std::reference_wrapper<Drawable<dimensions, T>>, MatrixTypeFor<dimensions, T>>>&)
*/
void draw(DrawableGroup<dimensions, T>& group);
/**
* @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.
*/
void draw(const std::vector<std::pair<std::reference_wrapper<Drawable<dimensions, T>>, MatrixTypeFor<dimensions, T>>>& drawableTransformations);
private:
/** Recalculates camera matrix */
void cleanInverted(const MatrixTypeFor<dimensions, T>& invertedAbsoluteTransformationMatrix) override {

29
src/Magnum/SceneGraph/Camera.hpp

@ -82,6 +82,30 @@ template<UnsignedInt dimensions, class T> void Camera<dimensions, T>::setViewpor
fixAspectRatio();
}
template<UnsignedInt dimensions, class T> std::vector<std::pair<std::reference_wrapper<Drawable<dimensions, T>>, MatrixTypeFor<dimensions, T>>> Camera<dimensions, T>::drawableTransformations(DrawableGroup<dimensions, T>& group) {
AbstractObject<dimensions, T>* scene = AbstractFeature<dimensions, T>::object().scene();
CORRADE_ASSERT(scene, "Camera::draw(): cannot draw when camera is not part of any scene", {});
/* Compute camera matrix */
AbstractFeature<dimensions, T>::object().setClean();
/* Compute transformations of all objects in the group relative to the camera */
std::vector<std::reference_wrapper<AbstractObject<dimensions, T>>> objects;
objects.reserve(group.size());
for(std::size_t i = 0; i != group.size(); ++i)
objects.push_back(group[i].object());
std::vector<MatrixTypeFor<dimensions, T>> transformations =
scene->transformationMatrices(objects, _cameraMatrix);
/* Combine drawable references and transformation matrices */
std::vector<std::pair<std::reference_wrapper<Drawable<dimensions, T>>, MatrixTypeFor<dimensions, T>>> combined;
combined.reserve(group.size());
for(std::size_t i = 0; i != group.size(); ++i)
combined.emplace_back(group[i], transformations[i]);
return combined;
}
template<UnsignedInt dimensions, class T> void Camera<dimensions, T>::draw(DrawableGroup<dimensions, T>& group) {
AbstractObject<dimensions, T>* scene = AbstractFeature<dimensions, T>::object().scene();
CORRADE_ASSERT(scene, "Camera::draw(): cannot draw when camera is not part of any scene", );
@ -102,6 +126,11 @@ template<UnsignedInt dimensions, class T> void Camera<dimensions, T>::draw(Drawa
group[i].draw(transformations[i], *this);
}
template<UnsignedInt dimensions, class T> void Camera<dimensions, T>::draw(const std::vector<std::pair<std::reference_wrapper<Drawable<dimensions, T>>, MatrixTypeFor<dimensions, T>>>& drawableTransformations) {
for(auto&& drawableTransformation: drawableTransformations)
drawableTransformation.first.get().draw(drawableTransformation.second, *this);
}
}}
#endif

11
src/Magnum/SceneGraph/Drawable.h

@ -111,6 +111,17 @@ 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
By default the 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:
@snippet MagnumSceneGraph.cpp Drawable-draw-order
@section SceneGraph-Drawable-explicit-specializations Explicit template specializations
The following specializations are explicitly compiled into @ref SceneGraph

59
src/Magnum/SceneGraph/Test/CameraTest.cpp

@ -23,7 +23,9 @@
DEALINGS IN THE SOFTWARE.
*/
#include <algorithm>
#include <Corrade/TestSuite/Tester.h>
#include <Corrade/TestSuite/Compare/Container.h>
#include "Magnum/SceneGraph/Camera.hpp" /* only for aspectRatioFix(), so it doesn't have to be exported */
#include "Magnum/SceneGraph/Camera.h"
@ -45,7 +47,9 @@ struct CameraTest: TestSuite::Tester {
void projectionSizeOrthographic();
void projectionSizePerspective();
void projectionSizeViewport();
void draw();
void drawOrdered();
};
typedef SceneGraph::Object<SceneGraph::MatrixTransformation2D> Object2D;
@ -61,7 +65,9 @@ CameraTest::CameraTest() {
&CameraTest::projectionSizeOrthographic,
&CameraTest::projectionSizePerspective,
&CameraTest::projectionSizeViewport,
&CameraTest::draw});
&CameraTest::draw,
&CameraTest::drawOrdered});
}
void CameraTest::fixAspectRatio() {
@ -210,6 +216,57 @@ void CameraTest::draw() {
CORRADE_COMPARE(thirdTransformation, Matrix4());
}
void CameraTest::drawOrdered() {
class Drawable: public SceneGraph::Drawable3D {
public:
Drawable(AbstractObject3D& object, DrawableGroup3D* group, std::vector<Matrix4>& result): SceneGraph::Drawable3D(object, group), _result(result) {}
protected:
void draw(const Matrix4& transformationMatrix, Camera3D&) override {
_result.push_back(transformationMatrix);
}
private:
std::vector<Matrix4>& _result;
};
DrawableGroup3D group;
Scene3D scene;
std::vector<Matrix4> transformations;
Object3D first(&scene);
first.scale(Vector3(5.0f))
.translate(Vector3::zAxis(-1.0f));
new Drawable{first, &group, transformations};
Object3D second(&scene);
second.translate(Vector3::zAxis(3.0f));
new Drawable{second, &group, transformations};
Object3D third(&second);
third.translate(Vector3::zAxis(-1.5f));
new Drawable{third, &group, transformations};
Camera3D camera(third);
std::vector<std::pair<std::reference_wrapper<SceneGraph::Drawable3D>, Matrix4>> drawableTransformations = camera.drawableTransformations(group);
std::sort(drawableTransformations.begin(), drawableTransformations.end(),
[](const std::pair<std::reference_wrapper<SceneGraph::Drawable3D>, Matrix4>& a,
const std::pair<std::reference_wrapper<SceneGraph::Drawable3D>, Matrix4>& b) {
return a.second.translation().z() < b.second.translation().z();
});
camera.draw(drawableTransformations);
/* Should be ordered front to back, most negative Z first */
CORRADE_COMPARE_AS(transformations, (std::vector<Matrix4>{
Matrix4::translation(Vector3::zAxis(-2.5f))*Matrix4::scaling(Vector3{5.0f}), /* first */
Matrix4{}, /* third */
Matrix4::translation(Vector3::zAxis(1.5f)) /* second */
}), TestSuite::Compare::Container);
}
}}}
CORRADE_TEST_MAIN(Magnum::SceneGraph::Test::CameraTest)

Loading…
Cancel
Save