#ifndef Magnum_SceneGraph_Camera_h #define Magnum_SceneGraph_Camera_h /* Copyright © 2010, 2011, 2012 Vladimír Vondruš This file is part of Magnum. Magnum is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License version 3 only, as published by the Free Software Foundation. Magnum is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License version 3 for more details. */ /** @file * @brief Class Magnum::SceneGraph::Camera, Magnum::SceneGraph::Camera2D, Magnum::SceneGraph::Camera3D */ #include "Object.h" #ifdef WIN32 /* I so HATE windows.h */ #undef near #undef far #endif namespace Magnum { namespace SceneGraph { /** @todo Export implementation symbols only for tests */ #ifndef DOXYGEN_GENERATING_OUTPUT namespace Implementation { enum class AspectRatioPolicy { NotPreserved, Extend, Clip }; template class Camera {}; template MatrixType aspectRatioFix(AspectRatioPolicy aspectRatioPolicy, const Vector2& projectionAspectRatio, const Math::Vector2& viewport); /* These templates are instantiated in source file */ extern template SCENEGRAPH_EXPORT Matrix3 aspectRatioFix(AspectRatioPolicy, const Vector2&, const Math::Vector2&); extern template SCENEGRAPH_EXPORT Matrix4 aspectRatioFix(AspectRatioPolicy, const Vector2&, const Math::Vector2&); } #endif /** @brief %Camera object */ template class SCENEGRAPH_EXPORT Camera: public ObjectType { public: /** * @brief Aspect ratio policy * * @see aspectRatioPolicy(), setAspectRatioPolicy() */ #ifndef DOXYGEN_GENERATING_OUTPUT typedef Implementation::AspectRatioPolicy AspectRatioPolicy; #else enum class AspectRatioPolicy { NotPreserved, /**< Don't preserve aspect ratio (default) */ Extend, /**< Extend on larger side of view */ Clip /**< Clip on smaller side of view */ }; #endif /** @copydoc Object::Object */ Camera(ObjectType* parent = nullptr); /** @brief Aspect ratio policy */ inline AspectRatioPolicy aspectRatioPolicy() const { return _aspectRatioPolicy; } /** @brief Set aspect ratio policy */ void setAspectRatioPolicy(AspectRatioPolicy policy) { _aspectRatioPolicy = policy; } /** * @brief Camera matrix * * Camera matrix describes world position relative to the camera and is * applied as first. */ inline MatrixType cameraMatrix() { this->setClean(); return _cameraMatrix; } /** * @brief Projection matrix * * Projection matrix handles e.g. perspective distortion and is applied * as last. */ inline MatrixType projectionMatrix() const { return _projectionMatrix; } /** @brief Viewport size */ inline Math::Vector2 viewport() const { return _viewport; } /** * @brief Set viewport size * * Call when window size changes. * * Calls Framebuffer::setViewport() and stores viewport size * internally. */ virtual void setViewport(const Math::Vector2& size); /** * @brief Draw the scene * * Calls Framebuffer::clear() and draws the scene using drawChildren(). */ virtual void draw(); using ObjectType::draw; /* Don't hide Object's draw() */ protected: /** * Recalculates camera matrix. */ void clean(const MatrixType& absoluteTransformation); /** * @brief Draw object children * * Recursively draws all children of the object. */ void drawChildren(ObjectType* object, const MatrixType& transformationMatrix); #ifndef DOXYGEN_GENERATING_OUTPUT inline void fixAspectRatio() { _projectionMatrix = Implementation::aspectRatioFix(_aspectRatioPolicy, projectionAspectRatio, _viewport)*rawProjectionMatrix; } Vector2 projectionAspectRatio; MatrixType rawProjectionMatrix; AspectRatioPolicy _aspectRatioPolicy; #endif private: MatrixType _projectionMatrix; MatrixType _cameraMatrix; Math::Vector2 _viewport; }; #ifndef DOXYGEN_GENERATING_OUTPUT /* These templates are instantiated in source file */ extern template class SCENEGRAPH_EXPORT Camera; extern template class SCENEGRAPH_EXPORT Camera; namespace Implementation { template<> class Camera<2> { public: inline constexpr static Matrix3 aspectRatioScale(const Vector2& scale) { return Matrix3::scaling({scale.x(), scale.y()}); } }; template<> class Camera<3> { public: inline constexpr static Matrix4 aspectRatioScale(const Vector2& scale) { return Matrix4::scaling({scale.x(), scale.y(), 1.0f}); } }; } #endif /** @brief %Camera for two-dimensional scenes */ class SCENEGRAPH_EXPORT Camera2D: public Camera { public: /** * @brief Constructor * @param parent Parent object * * Sets orthographic projection to the default OpenGL cube (range @f$ [-1; 1] @f$ in all directions). * @see setOrthographic() */ inline Camera2D(Object2D* parent = nullptr): Camera(parent) {} /** * @brief Set projection * @param size Size of the view * * The area of given size will be scaled down to range @f$ [-1; 1] @f$ * on all directions. */ void setProjection(const Vector2& size); }; /** @brief %Camera for three-dimensional scenes */ class SCENEGRAPH_EXPORT Camera3D: public Camera { public: /** * @brief Constructor * @param parent Parent object * * Sets orthographic projection to the default OpenGL cube (range @f$ [-1; 1] @f$ in all directions). * @see setOrthographic(), setPerspective() */ inline Camera3D(Object3D* parent = nullptr): Camera(parent), _near(0.0f), _far(0.0f) {} /** * @brief Set orthographic projection * @param size Size of the view * @param near Near clipping plane * @param far Far clipping plane * * The volume of given size will be scaled down to range @f$ [-1; 1] @f$ * on all directions. */ void setOrthographic(const Vector2& size, GLfloat near, GLfloat far); /** * @brief Set perspective projection * @param fov Field of view angle * @param near Near clipping plane * @param far Far clipping plane * * @todo Aspect ratio */ void setPerspective(GLfloat fov, GLfloat near, GLfloat far); /** @brief Near clipping plane */ inline GLfloat near() const { return _near; } /** @brief Far clipping plane */ inline GLfloat far() const { return _far; } private: GLfloat _near, _far; }; }} #endif