template<UnsignedInt dimensions, class T>
Magnum::SceneGraph::Drawable class

Drawable.

Adds drawing functionality to the object. Each Drawable is part of some DrawableGroup and the whole group can be drawn with particular camera using Camera::draw().

Usage

First thing is to add Drawable feature to some object and implement draw() function. You can do it conveniently using multiple inheritance (see Object features for introduction). Example drawable object that draws blue sphere:

typedef SceneGraph::Object<SceneGraph::MatrixTransformation3D> Object3D;
typedef SceneGraph::Scene<SceneGraph::MatrixTransformation3D> Scene3D;

class RedCube: public Object3D, public SceneGraph::Drawable3D {
    public:
        explicit RedCube(Object3D* parent, SceneGraph::DrawableGroup3D* group): Object3D{parent}, SceneGraph::Drawable3D{*this, group} {
            _mesh = MeshTools::compile(Primitives::cubeSolid());
        }

    private:
        void draw(const Matrix4& transformationMatrix, SceneGraph::Camera3D& camera) override {
            _shader.setDiffuseColor(Color3::fromHsv(216.0_degf, 0.85f, 1.0f))
                .setLightPosition(camera.cameraMatrix().transformPoint({5.0f, 5.0f, 7.0f}))
                .setTransformationMatrix(transformationMatrix)
                .setNormalMatrix(transformationMatrix.rotation())
                .setProjectionMatrix(camera.projectionMatrix());
            _mesh.draw(_shader);
        }

        GL::Mesh _mesh;
        Shaders::Phong _shader;
};

The transformationMatrix parameter in draw() function contains transformation of the object (to which the drawable is attached) relative to camera. The camera contains projection matrix. Some shaders (like the Shaders::Phong used in the example) have separate functions for setting transformation and projection matrix, but some (such as Shaders::Flat) have single function to set composite transformation and projection matrix. In that case you need to combine the two matrices manually like in the following code. Some shaders have additional requirements for various transformation matrices, see their respective documentation for details.

Shaders::Flat3D shader;
shader.setTransformationProjectionMatrix(camera.projectionMatrix()*transformationMatrix);

There is no way to just draw all the drawables in the scene, you need to create some drawable group and add the drawable objects to both the scene and the group. You can also use DrawableGroup::add() and DrawableGroup::remove() instead of passing the group in the constructor.

Scene3D scene;
SceneGraph::DrawableGroup3D drawables;

(new RedCube(&scene, &drawables))
    ->translate(Vector3::yAxis(-0.3f))
    .rotateX(30.0_degf);

// ...

The last thing you need is camera attached to some object (thus using its transformation). Using the camera and the drawable group you can perform drawing in your drawEvent() implementation. See Camera2D and Camera3D documentation for more information.

MyApplication::MyApplication(const Arguments& arguments): Platform::Application{arguments} {
    // ...

    _cameraObject = new Object3D{&_scene};
    _cameraObject->translate(Vector3::zAxis(5.0f));
    _camera = new SceneGraph::Camera3D(*_cameraObject);
    _camera->setProjectionMatrix(Matrix4::perspectiveProjection(35.0_degf, 1.0f, 0.001f, 100.0f));
}

void MyApplication::drawEvent() {
    _camera->draw(_drawables);

    // ...

    swapBuffers();
}

Using multiple drawable groups to improve performance

You can organize your drawables to multiple groups to minimize OpenGL state changes — for example put all objects using the same shader, the same light setup etc into one group, then put all transparent into another and set common parameters once for whole group instead of setting them again in each draw() implementation. Example:

    // ...

    Shaders::Phong _shader;
    SceneGraph::DrawableGroup3D _phongObjects, _transparentObjects;
};

void MyApplication::drawEvent() {
    _shader.setProjectionMatrix(_camera->projectionMatrix())
           .setLightPosition(_lightPositionRelativeToCamera)
           .setLightColor(_lightColor)
           .setAmbientColor(_ambientColor);

    /* Each drawable sets only unique properties such as transformation matrix
       and diffuse color */
    _camera->draw(_phongObjects);

    GL::Renderer::enable(GL::Renderer::Feature::Blending);

    /* Also here */
    _camera->draw(_transparentObjects);

    GL::Renderer::disable(GL::Renderer::Feature::Blending);

    // ...
}

Explicit template specializations

The following specializations are explicitly compiled into SceneGraph library. For other specializations (e.g. using Double type) you have to use Drawable.hpp implementation file to avoid linker errors. See also Template headers and implementation files for more information.

Base classes

template<UnsignedInt dimensions, class Derived, class T>
class AbstractGroupedFeature
Base for grouped features.

Constructors, destructors, conversion operators

Drawable(AbstractObject<dimensions, T>& object, DrawableGroup<dimensions, T>* drawables = nullptr) explicit
Constructor.

Public functions

auto drawables() -> DrawableGroup<dimensions, T>*
Group containing this drawable.
auto drawables() const -> const DrawableGroup<dimensions, T>*
void draw(const MatrixTypeFor<dimensions, T>& transformationMatrix, Camera<dimensions, T>& camera) pure virtual
Draw the object using given camera.

Function documentation

template<UnsignedInt dimensions, class T>
Magnum::SceneGraph::Drawable<dimensions, T>::Drawable(AbstractObject<dimensions, T>& object, DrawableGroup<dimensions, T>* drawables = nullptr) explicit

Constructor.

Parameters
object Object this drawable belongs to
drawables Group this drawable belongs to

Adds the feature to the object and also to the group, if specified. Otherwise you can use DrawableGroup::add().

template<UnsignedInt dimensions, class T>
DrawableGroup<dimensions, T>* Magnum::SceneGraph::Drawable<dimensions, T>::drawables()

Group containing this drawable.

If the drawable doesn't belong to any group, returns nullptr.

template<UnsignedInt dimensions, class T>
const DrawableGroup<dimensions, T>* Magnum::SceneGraph::Drawable<dimensions, T>::drawables() const

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

template<UnsignedInt dimensions, class T>
void Magnum::SceneGraph::Drawable<dimensions, T>::draw(const MatrixTypeFor<dimensions, T>& transformationMatrix, Camera<dimensions, T>& camera) pure virtual

Draw the object using given camera.

Parameters
transformationMatrix Object transformation relative to camera
camera Camera

Projection matrix can be retrieved from Camera::projectionMatrix().