diff --git a/src/Camera.cpp b/src/Camera.cpp index 9ca6bd9c8..d3df1d543 100644 --- a/src/Camera.cpp +++ b/src/Camera.cpp @@ -18,27 +18,10 @@ namespace Magnum { -Camera::Camera(Object* parent): Object(parent), _active(nullptr), _aspectRatioPolicy(Extend) { +Camera::Camera(Object* parent): Object(parent), _aspectRatioPolicy(Extend) { setOrthographic(2, 1, 1000); } -void Camera::setActive(Scene* _scene) { - if(_scene == _active || scene() != _scene) return; - - Scene* oldActive = _active; - - /* Set camera active in new scene */ - _active = _scene; - if(_active) _active->setCamera(this); - - /* Remove the camera from current active scene, if the camera is still - active there */ - if(oldActive && oldActive->camera() == this) oldActive->setCamera(nullptr); - - /* Clean the path to scene */ - setClean(); -} - void Camera::setOrthographic(GLfloat size, GLfloat near, GLfloat far) { _near = near; _far = far; @@ -88,28 +71,10 @@ void Camera::setViewport(const Math::Vector2& size) { void Camera::setClean() { if(!isDirty()) return; - _cameraMatrix = transformation(true).inverse(); + _cameraMatrix = absoluteTransformation().inverse(); Object::setClean(); } -void Camera::setDirty() { - Object::setDirty(); - - /* Camera is active */ - if(_active) { - Scene* currentScene = scene(); - - /* Camera is not part of the scene anymore, remove it from there */ - if(!currentScene) _active->setCamera(nullptr); - - /* Otherwise set the scene dirty */ - else _active->setDirty(); - - /* Clean up the path to scene immediately */ - setClean(); - } -} - void Camera::fixAspectRatio() { /* Don't divide by zero */ if(_viewport.x() == 0 || _viewport.y() == 0) { diff --git a/src/Camera.h b/src/Camera.h index 593697152..4e6b5c5f6 100644 --- a/src/Camera.h +++ b/src/Camera.h @@ -50,20 +50,6 @@ class MAGNUM_EXPORT Camera: public Object { */ Camera(Object* parent = nullptr); - /** - * @brief Scene in which the camera is active - * @return If the camera is not active anywhere, returns nullptr. - */ - inline Scene* active() const { return _active; } - - /** - * @brief Make camera active in given scene - * - * If passed nullptr as @c scene and this camera is active in an scene, - * the camera will be removed from that scene. - */ - void setActive(Scene* scene); - /** @brief Aspect ratio policy */ AspectRatioPolicy aspectRatioPolicy() const { return _aspectRatioPolicy; } @@ -135,19 +121,11 @@ class MAGNUM_EXPORT Camera: public Object { */ virtual void setClean(); - /** - * If the camera was active before and is still active, calls - * setDirty() on the scene, if is not part of the scene anymore, calls - * setCamera(nullptr) on the scene. - */ - virtual void setDirty(); - private: Matrix4 rawProjectionMatrix; Matrix4 _projectionMatrix; Matrix4 _cameraMatrix; GLfloat _near, _far; - Scene* _active; Math::Vector2 _viewport; AspectRatioPolicy _aspectRatioPolicy; diff --git a/src/Light.cpp b/src/Light.cpp index 2b4b4f2d7..a9f424fdc 100644 --- a/src/Light.cpp +++ b/src/Light.cpp @@ -19,7 +19,7 @@ namespace Magnum { void Light::setClean() { if(!isDirty()) return; - _position = transformation(true).at(3).xyz(); + _position = absoluteTransformation().at(3).xyz(); Object::setClean(); } diff --git a/src/Light.h b/src/Light.h index a2eeff975..3ea340f5d 100644 --- a/src/Light.h +++ b/src/Light.h @@ -37,7 +37,7 @@ class Light: public Object { inline Light(Object* parent = nullptr): Object(parent) {} /** - * @brief Light position relative to the camera + * @brief Light position relative to root object (scene) */ inline Vector3 position() { setClean(); diff --git a/src/Object.cpp b/src/Object.cpp index eaccf80df..1a05cc84a 100644 --- a/src/Object.cpp +++ b/src/Object.cpp @@ -45,19 +45,20 @@ void Object::setParent(Object* parent) { setDirty(); } -Matrix4 Object::transformation(bool absolute) { - if(!absolute) return _transformation; - +Matrix4 Object::absoluteTransformation(Camera* camera) { Matrix4 t = _transformation; + /* Shortcut for absolute transformation of camera relative to itself */ + if(camera == this) return Matrix4(); + Object* p = parent(); while(p != nullptr) { t = p->transformation()*t; /* We got to the scene, multiply with camera matrix */ if(p->parent() == p) { - Camera* camera = static_cast(p)->camera(); - if(camera && camera != this) t = camera->cameraMatrix()*t; + if(camera && camera->scene() == scene()) + t = camera->cameraMatrix()*t; break; } diff --git a/src/Object.h b/src/Object.h index ffd5b0d21..2ef3ea211 100644 --- a/src/Object.h +++ b/src/Object.h @@ -26,6 +26,7 @@ namespace Magnum { class Scene; +class Camera; /** * @brief Base for all positioned objects @@ -78,14 +79,21 @@ class MAGNUM_EXPORT Object { /** * @brief Transformation matrix * - * If the object is part of an scene and @c absolute is set to true, - * returns absolute transformation matrix (thus relative to actual - * camera), if the object is not part of an scene, returns - * transformation matrix composed of all matrices of parent objects. - * If @c absolute is set to false, returns transformation matrix - * relative to parent. + * @return Transformation matrix relative to parent. */ - virtual Matrix4 transformation(bool absolute = false); + inline Matrix4 transformation() const { + return _transformation; + } + + /** + * @brief Absolute transformation matrix + * + * If both this object and the camera is part of the same scene, + * returns absolute transformation matrix (relative to the camera). + * Otherwise returns transformation matrix relative to root object + * (in most cases this object's scene). + */ + virtual Matrix4 absoluteTransformation(Camera* camera = nullptr); /** @brief Set transformation matrix */ inline void setTransformation(const Matrix4& transformation) { @@ -209,10 +217,14 @@ class MAGNUM_EXPORT Object { /** * @brief Draw object + * @param transformationMatrix %Matrix specifying object + * transformation relative to the scene. + * @param camera Active camera (containing + * projection matrix) * * Default implementation does nothing. */ - virtual void draw(const Matrix4& transformationMatrix, const Matrix4& projectionMatrix) {} + virtual void draw(const Matrix4& transformationMatrix, Camera* camera) {} private: Object* _parent; diff --git a/src/Scene.cpp b/src/Scene.cpp index 63cbfa495..9b47a6d28 100644 --- a/src/Scene.cpp +++ b/src/Scene.cpp @@ -19,7 +19,7 @@ using namespace std; namespace Magnum { -Scene::Scene(): Object(nullptr), _features(0), _camera(nullptr) { +Scene::Scene(): Object(nullptr), _features(0) { _parent = this; setClearColor(0.1f, 0.1f, 0.1f, 1.0f); @@ -45,44 +45,22 @@ void Scene::setClearColor(const Magnum::Vector4& color) { _clearColor = color; } -void Scene::setCamera(Camera* camera) { - /* Don't assign the same camera or camera which is not part of the scene */ - if(camera == _camera || (camera && camera->scene() != this)) return; - - Camera* oldCamera = _camera; - - /* Set new camera active */ - _camera = camera; - if(_camera) { - if(oldCamera) _camera->setViewport(oldCamera->viewport()); - _camera->setActive(this); - } - - /* Set old camera inactive, if it is still active in this scene */ - if(oldCamera && oldCamera->active() == this) oldCamera->setActive(nullptr); - - setDirty(); -} - -void Scene::draw() { - /* No camera available, nothing to do */ - if(!_camera) return; - +void Scene::draw(Camera* camera) { /** @todo Clear only set features */ glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); /* Recursively draw child objects */ - drawChildren(this, _camera->cameraMatrix()); + drawChildren(this, camera->cameraMatrix(), camera); } -void Scene::drawChildren(Object* object, const Matrix4& transformationMatrix) { +void Scene::drawChildren(Object* object, const Matrix4& transformationMatrix, Camera* camera) { for(set::const_iterator it = object->children().begin(); it != object->children().end(); ++it) { /* Transformation matrix for the object */ Matrix4 matrix = transformationMatrix*(*it)->transformation(); /* Draw the object and its children */ - (*it)->draw(matrix, _camera->projectionMatrix()); - drawChildren(*it, matrix); + (*it)->draw(matrix, camera); + drawChildren(*it, matrix, camera); } } diff --git a/src/Scene.h b/src/Scene.h index 981a5d71f..281a98be5 100644 --- a/src/Scene.h +++ b/src/Scene.h @@ -65,9 +65,6 @@ class MAGNUM_EXPORT Scene: public Object { /** @brief Which features are set */ inline unsigned int features() const { return _features; } - /** @brief Camera */ - inline Camera* camera() const { return _camera; } - /** @brief Set feature */ void setFeature(Feature feature, bool enabled); @@ -79,38 +76,20 @@ class MAGNUM_EXPORT Scene: public Object { setClearColor(Vector4(r, g, b, a)); } - /** - * @brief Set viewport size - * - * Just passes the values to active camera. - */ - inline void setViewport(int width, int height) { - if(_camera) _camera->setViewport(width, height); - } - - /** - * @brief Set camera - * - * If the camera is not part of the scene, the function does nothing. - */ - void setCamera(Camera* camera); - /** * @brief Draw whole scene * - * Recursively draws all child objects. If no camera is available, does - * nothing. + * Recursively draws all child objects with given camera. */ - virtual void draw(); + virtual void draw(Camera* camera); private: unsigned int _features; Vector4 _clearColor; - Camera* _camera; GLuint vao; - inline virtual void draw(const Magnum::Matrix4& transformationMatrix, const Magnum::Matrix4& projectionMatrix) {} - void drawChildren(Object* object, const Matrix4& transformationMatrix); + inline virtual void draw(const Magnum::Matrix4& transformationMatrix, Camera* camera) {} + void drawChildren(Object* object, const Matrix4& transformationMatrix, Camera* camera); }; } diff --git a/src/Test/CameraTest.cpp b/src/Test/CameraTest.cpp index e52978df6..19e6bc623 100644 --- a/src/Test/CameraTest.cpp +++ b/src/Test/CameraTest.cpp @@ -52,24 +52,4 @@ void CameraTest::perspective() { QVERIFY(camera.projectionMatrix() == Matrix4(a)); } -void CameraTest::active() { - Object* object = new Object; - Camera* camera = new Camera(object); - - Scene scene; - - /* Camera is not part of the scene, do nothing */ - scene.setCamera(camera); - QVERIFY(scene.camera() == 0); - - /* Add camera if the camera is part of the scene */ - object->setParent(&scene); - scene.setCamera(camera); - QVERIFY(scene.camera() == camera); - - /* When camera is taken out of the scene, remove it */ - object->setParent(0); - QVERIFY(scene.camera() == 0); -} - }} diff --git a/src/Test/CameraTest.h b/src/Test/CameraTest.h index 0099447f4..e6151394e 100644 --- a/src/Test/CameraTest.h +++ b/src/Test/CameraTest.h @@ -25,7 +25,6 @@ class CameraTest: public QObject { private slots: void orthographic(); void perspective(); - void active(); }; }} diff --git a/src/Test/ObjectTest.cpp b/src/Test/ObjectTest.cpp index c61ed66ed..f4a90a7a5 100644 --- a/src/Test/ObjectTest.cpp +++ b/src/Test/ObjectTest.cpp @@ -83,20 +83,6 @@ void ObjectTest::dirty() { childTwo->setDirty(); QVERIFY(childTwo->isDirty()); QVERIFY(childThree->isDirty()); - - /* Set camera, makes everything dirty except path from camera to scene */ - Camera* camera = new Camera(&scene); - scene.setCamera(camera); - QVERIFY(childOne->isDirty()); - QVERIFY(!camera->isDirty()); - QVERIFY(!scene.isDirty()); - - /* Clean up and try to move the camera -> makes all dirty (except path - from camera to scene) */ - childThree->setClean(); - QVERIFY(!scene.isDirty()); - camera->translate(0, 0, 1); - QVERIFY(childOne->isDirty()); } }}