diff --git a/CMakeLists.txt b/CMakeLists.txt index cdcb5da2..e007ce80 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,6 +41,7 @@ set(SOURCES src/volume_node.cpp src/forces_visualizer_node.cpp src/coordinate_system_node.cpp + src/camera_node.cpp src/nodes.cpp src/abstract_scene.h src/scene.cpp diff --git a/src/camera.cpp b/src/camera.cpp index 82d226c8..f72f5995 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -2,13 +2,31 @@ #include #include +#include + Camera::Camera() : origin(0, 0, 0), position(0, 0, -1), direction(0, 0, 1), up(0, 1, 0), - radius(1.0f), azimuth(-M_PI / 2.0f), declination(0), - fieldOfView(M_PI / 2.0f) + radius(1.0f), azimuth(-M_PI / 2.0f), declination(0) { projection = createProjection(fieldOfView, aspectRatio, near, far); // projection = createOrthographicProjection(aspectRatio, near, far); + + update(); +} + +Camera::Camera(Eigen::Matrix4f viewMatrix, Eigen::Matrix4f projectionMatrix, + Eigen::Vector3f origin) + : projection(projectionMatrix), view(viewMatrix), origin(origin) +{ + position = -viewMatrix.inverse().col(3).head<3>(); + direction = viewMatrix.col(2).head<3>(); + up = viewMatrix.col(1).head<3>(); + + radius = (position - origin).norm(); + + Eigen::Vector3f diff = (position - origin) / radius; + declination = asin(diff.y()); + azimuth = -acos(diff.x() / cos(declination)); } Camera::~Camera() @@ -47,11 +65,13 @@ Eigen::Matrix4f Camera::createOrthographicProjection(float aspectRatio, void Camera::moveForward(float distance) { position += distance * direction; + update(); } void Camera::moveBackward(float distance) { position -= distance * direction; + update(); } void Camera::strafe(float distance) @@ -59,6 +79,7 @@ void Camera::strafe(float distance) auto right = direction.cross(up); position += distance * right; origin += distance * right; + update(); } void Camera::strafeLeft(float distance) @@ -75,6 +96,7 @@ void Camera::moveVertical(float distance) { position += distance * up; origin += distance * up; + update(); } void Camera::changeAzimuth(float deltaAngle) @@ -107,10 +129,7 @@ void Camera::update() float upDeclination = declination - M_PI / 2.0f; up = -Eigen::Vector3f(cos(azimuth) * cos(upDeclination), sin(upDeclination), sin(azimuth) * cos(upDeclination)).normalized(); -} -Eigen::Matrix4f Camera::getViewMatrix() -{ auto n = direction.normalized(); auto u = up.cross(n).normalized(); auto v = n.cross(u); @@ -118,21 +137,29 @@ Eigen::Matrix4f Camera::getViewMatrix() view << u.x(), u.y(), u.z(), u.dot(e), v.x(), v.y(), v.z(), v.dot(e), n.x(), n.y(), n.z(), n.dot(e), 0, 0, 0, 1; +} +Eigen::Matrix4f Camera::getViewMatrix() const +{ return view; } -Eigen::Matrix4f Camera::getProjectionMatrix() +Eigen::Matrix4f Camera::getProjectionMatrix() const { return projection; } -Eigen::Vector3f Camera::getPosition() +Eigen::Vector3f Camera::getPosition() const { return position; } -float Camera::getRadius() +Eigen::Vector3f Camera::getOrigin() const +{ + return origin; +} + +float Camera::getRadius() const { return (position - origin).norm(); } @@ -151,3 +178,8 @@ void Camera::updateNearAndFarPlanes(float near, float far) projection = createProjection(fieldOfView, aspectRatio, near, far); } +bool Camera::needsResizing() +{ + return aspectRatio == 0.0f; +} + diff --git a/src/camera.h b/src/camera.h index 60d4a24e..129a138e 100644 --- a/src/camera.h +++ b/src/camera.h @@ -13,14 +13,16 @@ class Camera { public: Camera(); + Camera(Eigen::Matrix4f viewMatrix, Eigen::Matrix4f projectionMatrix, + Eigen::Vector3f origin); virtual ~Camera(); - Eigen::Matrix4f getProjectionMatrix(); - Eigen::Matrix4f getViewMatrix(); - Eigen::Vector3f getPosition(); - float getRadius(); + Eigen::Matrix4f getProjectionMatrix() const; + Eigen::Matrix4f getViewMatrix() const; + Eigen::Vector3f getPosition() const; + Eigen::Vector3f getOrigin() const; + float getRadius() const; - public: void moveForward(float distance); void moveBackward(float distance); void strafeLeft(float distance); @@ -35,6 +37,9 @@ class Camera void resize(float width, float height); void updateNearAndFarPlanes(float near, float far); + + bool needsResizing(); + private: float near = 0.1f; float far = 5.0f; @@ -50,8 +55,8 @@ class Camera float azimuth; float declination; - float fieldOfView; - float aspectRatio = 16.0f / 9.0f; + float fieldOfView = 0.5 * M_PI; + float aspectRatio = 0.0f; Eigen::Matrix4f createProjection(float fov, float aspectRatio, float nearPlane, float farPlane); diff --git a/src/camera_controller.cpp b/src/camera_controller.cpp index d3e7be1c..91899833 100644 --- a/src/camera_controller.cpp +++ b/src/camera_controller.cpp @@ -1,56 +1,55 @@ #include "./camera_controller.h" #include +#include "./camera.h" -CameraController::CameraController(Camera &camera) : camera(camera) +CameraController::CameraController(std::shared_ptr camera) + : camera(camera) { } -CameraController::~CameraController() -{ -} - -void CameraController::setFrameTime(double frameTime) +void CameraController::update(std::shared_ptr camera, double frameTime) { + this->camera = camera; this->frameTime = frameTime; } void CameraController::moveForward() { - camera.moveForward(frameTime * cameraSpeed); + camera->moveForward(frameTime * cameraSpeed); } void CameraController::moveBackward() { - camera.moveBackward(frameTime * cameraSpeed); + camera->moveBackward(frameTime * cameraSpeed); } void CameraController::strafeLeft() { - camera.strafeLeft(frameTime * cameraSpeed); + camera->strafeLeft(frameTime * cameraSpeed); } void CameraController::strafeRight() { - camera.strafeRight(frameTime * cameraSpeed); + camera->strafeRight(frameTime * cameraSpeed); } void CameraController::azimuthLeft() { - camera.changeAzimuth(frameTime); + camera->changeAzimuth(frameTime); } void CameraController::azimuthRight() { - camera.changeAzimuth(-frameTime); + camera->changeAzimuth(-frameTime); } void CameraController::increaseDeclination() { - camera.changeDeclination(-frameTime); + camera->changeDeclination(-frameTime); } void CameraController::decreaseDeclination() { - camera.changeDeclination(frameTime); + camera->changeDeclination(frameTime); } diff --git a/src/camera_controller.h b/src/camera_controller.h index c9ba62a0..38ef4a36 100644 --- a/src/camera_controller.h +++ b/src/camera_controller.h @@ -3,7 +3,9 @@ #define SRC_CAMERA_CONTROLLER_H_ #include -#include "./camera.h" +#include + +class Camera; /** * \brief Provides slots to control the given camera from @@ -16,10 +18,9 @@ class CameraController : public QObject { Q_OBJECT public: - explicit CameraController(Camera &camera); - virtual ~CameraController(); + explicit CameraController(std::shared_ptr camera); - void setFrameTime(double frameTime); + void update(std::shared_ptr camera, double frameTime); public slots: void moveForward(); @@ -32,7 +33,7 @@ class CameraController : public QObject void decreaseDeclination(); private: - Camera &camera; + std::shared_ptr camera; double cameraSpeed = 10.0f; double frameTime; }; diff --git a/src/camera_controllers.cpp b/src/camera_controllers.cpp index b35eb48a..34b42a3a 100644 --- a/src/camera_controllers.cpp +++ b/src/camera_controllers.cpp @@ -6,7 +6,8 @@ #include "./camera_move_controller.h" CameraControllers::CameraControllers( - std::shared_ptr invokeManager, Camera &camera) + std::shared_ptr invokeManager, + std::shared_ptr camera) { cameraController = std::make_shared(camera); cameraRotationController = std::make_shared(camera); @@ -19,11 +20,11 @@ CameraControllers::CameraControllers( invokeManager->addHandler("cameraMove", cameraMoveController.get()); } -void CameraControllers::update(double frameTime) +void CameraControllers::update(std::shared_ptr camera, double frameTime) { - cameraController->setFrameTime(frameTime); - cameraRotationController->setFrameTime(frameTime); - cameraZoomController->setFrameTime(frameTime); - cameraMoveController->setFrameTime(frameTime); + cameraController->update(camera, frameTime); + cameraRotationController->update(camera, frameTime); + cameraZoomController->update(camera, frameTime); + cameraMoveController->update(camera, frameTime); } diff --git a/src/camera_controllers.h b/src/camera_controllers.h index ae76df4c..7272659c 100644 --- a/src/camera_controllers.h +++ b/src/camera_controllers.h @@ -19,9 +19,9 @@ class CameraControllers { public: CameraControllers(std::shared_ptr invokeManager, - Camera &camera); + std::shared_ptr camera); - void update(double frameTime); + void update(std::shared_ptr camera, double frameTime); private: std::shared_ptr cameraController; diff --git a/src/camera_move_controller.cpp b/src/camera_move_controller.cpp index a6254b65..ed19c9b5 100644 --- a/src/camera_move_controller.cpp +++ b/src/camera_move_controller.cpp @@ -1,15 +1,16 @@ #include "./camera_move_controller.h" #include "./camera.h" -CameraMoveController::CameraMoveController(Camera &camera) : camera(camera) +CameraMoveController::CameraMoveController(std::shared_ptr camera) + : MouseDraggingController(camera, 0.2) { } -void CameraMoveController::update(Eigen::Vector2f diff) +void CameraMoveController::updateFromDiff(Eigen::Vector2f diff) { Eigen::Vector2f delta = -frameTime * speedFactor * diff; - camera.strafe(delta.x()); - camera.moveVertical(delta.y()); + camera->strafe(delta.x()); + camera->moveVertical(delta.y()); } diff --git a/src/camera_move_controller.h b/src/camera_move_controller.h index 5b8b34f8..2e8454b8 100644 --- a/src/camera_move_controller.h +++ b/src/camera_move_controller.h @@ -15,14 +15,10 @@ class Camera; class CameraMoveController : public MouseDraggingController { public: - explicit CameraMoveController(Camera &camera); + explicit CameraMoveController(std::shared_ptr camera); protected: - virtual void update(Eigen::Vector2f diff); - - private: - Camera &camera; - double speedFactor = 0.2; + virtual void updateFromDiff(Eigen::Vector2f diff); }; #endif // SRC_CAMERA_MOVE_CONTROLLER_H_ diff --git a/src/camera_node.cpp b/src/camera_node.cpp new file mode 100644 index 00000000..b3127710 --- /dev/null +++ b/src/camera_node.cpp @@ -0,0 +1,22 @@ +#include "./camera_node.h" + +CameraNode::CameraNode() +{ + camera = std::make_shared(); +} + +CameraNode::CameraNode(std::shared_ptr camera) + : camera(camera) +{ +} + +void CameraNode::render(Graphics::Gl *gl, + std::shared_ptr managers, + RenderData renderData) +{ +} + +std::shared_ptr CameraNode::getCamera() +{ + return camera; +} diff --git a/src/camera_node.h b/src/camera_node.h new file mode 100644 index 00000000..fc6580ab --- /dev/null +++ b/src/camera_node.h @@ -0,0 +1,81 @@ +#ifndef SRC_CAMERA_NODE_H_ + +#define SRC_CAMERA_NODE_H_ + +#include +#include +#include "./node.h" +#include "./graphics/gl.h" +#include "./graphics/managers.h" +#include "./camera.h" + +/** + * \brief + * + * + */ +class CameraNode : public Node +{ + public: + CameraNode(); + explicit CameraNode(std::shared_ptr camera); + + std::shared_ptr getCamera(); + + virtual void render(Graphics::Gl *gl, + std::shared_ptr managers, + RenderData renderData); + + template void save_construct_data(Archive &ar) const + { + Eigen::Matrix4f viewMatrix = camera->getViewMatrix(); + Eigen::Matrix4f projectionMatrix = camera->getProjectionMatrix(); + Eigen::Vector3f origin = camera->getOrigin(); + + ar << BOOST_SERIALIZATION_NVP(viewMatrix); + ar << BOOST_SERIALIZATION_NVP(projectionMatrix); + ar << BOOST_SERIALIZATION_NVP(origin); + }; + + private: + std::shared_ptr camera; + + friend class boost::serialization::access; + template + void serialize(Archive &ar, unsigned int version) const + { + boost::serialization::void_cast_register( + static_cast(NULL), static_cast(NULL)); + }; +}; + +namespace boost +{ +namespace serialization +{ + +template +inline void save_construct_data(Archive &ar, const CameraNode *cameraNode, + const unsigned int file_version) +{ + cameraNode->save_construct_data(ar); +} + +template +inline void load_construct_data(Archive &ar, CameraNode *t, + const unsigned int version) +{ + Eigen::Matrix4f viewMatrix; + ar >> BOOST_SERIALIZATION_NVP(viewMatrix); + Eigen::Matrix4f projectionMatrix; + ar >> BOOST_SERIALIZATION_NVP(projectionMatrix); + Eigen::Vector3f origin; + ar >> BOOST_SERIALIZATION_NVP(origin); + + ::new (t) CameraNode( + std::make_shared(viewMatrix, projectionMatrix, origin)); +} +} // namespace serialization +} // namespace boost + +#endif // SRC_CAMERA_NODE_H_ diff --git a/src/camera_rotation_controller.cpp b/src/camera_rotation_controller.cpp index dbed5786..05d7e4d0 100644 --- a/src/camera_rotation_controller.cpp +++ b/src/camera_rotation_controller.cpp @@ -2,17 +2,18 @@ #include #include "./camera.h" -CameraRotationController::CameraRotationController(Camera &camera) - : camera(camera) +CameraRotationController::CameraRotationController( + std::shared_ptr camera) + : MouseDraggingController(camera, 0.04) { } -void CameraRotationController::update(Eigen::Vector2f diff) +void CameraRotationController::updateFromDiff(Eigen::Vector2f diff) { - double scaling = frameTime * speedFactor / camera.getRadius(); + double scaling = frameTime * speedFactor / camera->getRadius(); Eigen::Vector2f delta = scaling * diff; - camera.changeAzimuth(atan(delta.x())); - camera.changeDeclination(-atan(delta.y())); + camera->changeAzimuth(atan(delta.x())); + camera->changeDeclination(-atan(delta.y())); } diff --git a/src/camera_rotation_controller.h b/src/camera_rotation_controller.h index 8da4ccee..49c41eba 100644 --- a/src/camera_rotation_controller.h +++ b/src/camera_rotation_controller.h @@ -15,14 +15,10 @@ class Camera; class CameraRotationController : public MouseDraggingController { public: - explicit CameraRotationController(Camera &camera); + explicit CameraRotationController(std::shared_ptr camera); protected: - virtual void update(Eigen::Vector2f diff); - - private: - Camera &camera; - double speedFactor = 0.04; + virtual void updateFromDiff(Eigen::Vector2f diff); }; #endif // SRC_CAMERA_ROTATION_CONTROLLER_H_ diff --git a/src/camera_zoom_controller.cpp b/src/camera_zoom_controller.cpp index 51e89cee..007f299d 100644 --- a/src/camera_zoom_controller.cpp +++ b/src/camera_zoom_controller.cpp @@ -4,25 +4,26 @@ #include #include "./camera.h" -CameraZoomController::CameraZoomController(Camera &camera) : camera(camera) +CameraZoomController::CameraZoomController(std::shared_ptr camera) + : MouseDraggingController(camera, 0.1) { } -void CameraZoomController::update(Eigen::Vector2f diff) +void CameraZoomController::updateFromDiff(Eigen::Vector2f diff) { double scaling = frameTime * speedFactor; Eigen::Vector2f delta = scaling * diff; - camera.changeRadius(delta.y()); + camera->changeRadius(delta.y()); } void CameraZoomController::wheelZoom(QEvent *event) { - QWheelEvent *wheelEvent = static_cast(event); + QWheelEvent *wheelEvent = static_cast(event); - double scaling = -0.02f * frameTime * speedFactor * camera.getRadius(); + double scaling = -0.02f * frameTime * speedFactor * camera->getRadius(); float delta = scaling * wheelEvent->angleDelta().y(); - camera.changeRadius(delta); + camera->changeRadius(delta); } diff --git a/src/camera_zoom_controller.h b/src/camera_zoom_controller.h index bf059dbc..e44baeac 100644 --- a/src/camera_zoom_controller.h +++ b/src/camera_zoom_controller.h @@ -17,17 +17,13 @@ class CameraZoomController : public MouseDraggingController Q_OBJECT public: - explicit CameraZoomController(Camera &camera); + explicit CameraZoomController(std::shared_ptr camera); public slots: void wheelZoom(QEvent *event); protected: - virtual void update(Eigen::Vector2f diff); - - private: - Camera &camera; - double speedFactor = 0.1; + virtual void updateFromDiff(Eigen::Vector2f diff); }; #endif // SRC_CAMERA_ZOOM_CONTROLLER_H_ diff --git a/src/default_scene_creator.cpp b/src/default_scene_creator.cpp index 7d71ab4b..b0ee8e9d 100644 --- a/src/default_scene_creator.cpp +++ b/src/default_scene_creator.cpp @@ -6,11 +6,13 @@ #include "./mesh_node.h" #include "./label_node.h" #include "./volume_node.h" +#include "./camera_node.h" #include "./utils/persister.h" BOOST_CLASS_EXPORT_GUID(LabelNode, "LabelNode") BOOST_CLASS_EXPORT_GUID(MeshNode, "MeshNode") BOOST_CLASS_EXPORT_GUID(VolumeNode, "VolumeNode") +BOOST_CLASS_EXPORT_GUID(CameraNode, "CameraNode") DefaultSceneCreator::DefaultSceneCreator(std::shared_ptr nodes, std::shared_ptr labels) diff --git a/src/mouse_dragging_controller.cpp b/src/mouse_dragging_controller.cpp index b59c7868..d17de09a 100644 --- a/src/mouse_dragging_controller.cpp +++ b/src/mouse_dragging_controller.cpp @@ -1,8 +1,17 @@ #include "./mouse_dragging_controller.h" #include +#include "./camera.h" -void MouseDraggingController::setFrameTime(double frameTime) +MouseDraggingController::MouseDraggingController(std::shared_ptr camera, + double speedFactor) + : camera(camera), speedFactor(speedFactor) { +} + +void MouseDraggingController::update(std::shared_ptr camera, + double frameTime) +{ + this->camera = camera; this->frameTime = frameTime; } @@ -24,7 +33,7 @@ void MouseDraggingController::updateDragging(QEvent *event) Eigen::Vector2f diff = mousePosition - lastMousePosition; - update(diff); + updateFromDiff(diff); lastMousePosition = mousePosition; } diff --git a/src/mouse_dragging_controller.h b/src/mouse_dragging_controller.h index 3432418f..55e76829 100644 --- a/src/mouse_dragging_controller.h +++ b/src/mouse_dragging_controller.h @@ -3,8 +3,11 @@ #define SRC_MOUSE_DRAGGING_CONTROLLER_H_ #include +#include #include "./math/eigen.h" +class Camera; + /** * \brief Base class for controllers which are based on mouse dragging * @@ -20,19 +23,21 @@ class MouseDraggingController : public QObject public: EIGEN_MAKE_ALIGNED_OPERATOR_NEW - MouseDraggingController() = default; + MouseDraggingController(std::shared_ptr camera, double speedFactor); - void setFrameTime(double frameTime); + void update(std::shared_ptr camera, double frameTime); public slots: void startDragging(); void updateDragging(QEvent *event); protected: - virtual void update(Eigen::Vector2f diff) = 0; + virtual void updateFromDiff(Eigen::Vector2f diff) = 0; + std::shared_ptr camera; Eigen::Vector2f lastMousePosition; double frameTime; + double speedFactor; private: bool start = false; diff --git a/src/nodes.cpp b/src/nodes.cpp index 95e28ce8..f2102aa1 100644 --- a/src/nodes.cpp +++ b/src/nodes.cpp @@ -7,11 +7,14 @@ #include "./mesh_node.h" #include "./label_node.h" #include "./obb_node.h" +#include "./camera_node.h" #include "./coordinate_system_node.h" Nodes::Nodes() { addNode(std::make_shared()); + cameraNode = std::make_shared(); + addNode(cameraNode); } Nodes::~Nodes() @@ -50,6 +53,20 @@ std::vector> Nodes::getNodes() return nodes; } +std::shared_ptr Nodes::getCameraNode() +{ + return cameraNode; +} + +void Nodes::setCameraNode(std::shared_ptr node) +{ + if (cameraNode.get()) + removeNode(cameraNode); + + cameraNode = node; + addNode(node); +} + void Nodes::addSceneNodesFrom(QUrl url) { addSceneNodesFrom(url.path().toStdString()); @@ -61,8 +78,15 @@ void Nodes::addSceneNodesFrom(std::string filename) auto loadedNodes = Persister::load>>(filename); - for (auto &m : loadedNodes) - addNode(m); + for (auto &node : loadedNodes) + { + std::shared_ptr camera = + std::dynamic_pointer_cast(node); + if (camera.get()) + setCameraNode(camera); + + addNode(node); + } } void Nodes::importFrom(std::string filename) diff --git a/src/nodes.h b/src/nodes.h index 25bfa221..d93bb2dc 100644 --- a/src/nodes.h +++ b/src/nodes.h @@ -13,6 +13,7 @@ #include "./graphics/gl.h" class LabelNode; +class CameraNode; /** * \brief Manages a collection of nodes which is rendered @@ -39,6 +40,9 @@ class Nodes : public QObject std::vector> getLabelNodes(); void removeNode(std::shared_ptr node); std::vector> getNodes(); + std::shared_ptr getCameraNode(); + void setCameraNode(std::shared_ptr node); + public slots: void addSceneNodesFrom(std::string filename); void addSceneNodesFrom(QUrl url); @@ -65,6 +69,7 @@ class Nodes : public QObject bool showBoundingVolumes = false; std::vector> obbNodes; std::shared_ptr forcesVisualizerNode; + std::shared_ptr cameraNode; }; #endif // SRC_NODES_H_ diff --git a/src/scene.cpp b/src/scene.cpp index 1a9ee6fc..23451501 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -12,6 +12,7 @@ #include "./graphics/buffer_drawer.h" #include "./camera_controllers.h" #include "./nodes.h" +#include "./camera_node.h" #include "./labelling/labeller_frame_data.h" #include "./label_node.h" #include "./eigen_qdebug.h" @@ -35,7 +36,7 @@ Scene::Scene(std::shared_ptr invokeManager, textureMapperManager(textureMapperManager) { cameraControllers = - std::make_shared(invokeManager, camera); + std::make_shared(invokeManager, getCamera()); fbo = std::make_shared(); constraintBufferObject = std::make_shared(); @@ -106,12 +107,14 @@ void Scene::cleanup() void Scene::update(double frameTime, QSet keysPressed) { + auto camera = getCamera(); + this->frameTime = frameTime; - cameraControllers->update(frameTime); + cameraControllers->update(camera, frameTime); - frustumOptimizer.update(camera.getViewMatrix()); - camera.updateNearAndFarPlanes(frustumOptimizer.getNear(), - frustumOptimizer.getFar()); + frustumOptimizer.update(camera->getViewMatrix()); + camera->updateNearAndFarPlanes(frustumOptimizer.getNear(), + frustumOptimizer.getFar()); haBuffer->updateNearAndFarPlanes(frustumOptimizer.getNear(), frustumOptimizer.getFar()); @@ -128,12 +131,18 @@ void Scene::update(double frameTime, QSet keysPressed) void Scene::render() { + auto camera = getCamera(); + if (shouldResize) { - camera.resize(width, height); + camera->resize(width, height); fbo->resize(width, height); shouldResize = false; } + + if (camera->needsResizing()) + camera->resize(width, height); + glAssert(gl->glViewport(0, 0, width, height)); glAssert(gl->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)); @@ -149,7 +158,7 @@ void Scene::render() constraintBufferObject->bind(); placementLabeller->update(LabellerFrameData( - frameTime, camera.getProjectionMatrix(), camera.getViewMatrix())); + frameTime, camera->getProjectionMatrix(), camera->getViewMatrix())); constraintBufferObject->unbind(); @@ -256,9 +265,10 @@ void Scene::resize(int width, int height) RenderData Scene::createRenderData() { RenderData renderData; - renderData.projectionMatrix = camera.getProjectionMatrix(); - renderData.viewMatrix = camera.getViewMatrix(); - renderData.cameraPosition = camera.getPosition(); + auto camera = getCamera(); + renderData.projectionMatrix = camera->getProjectionMatrix(); + renderData.viewMatrix = camera->getViewMatrix(); + renderData.cameraPosition = camera->getPosition(); renderData.modelMatrix = Eigen::Matrix4f::Identity(); renderData.windowPixelSize = Eigen::Vector2f(width, height); @@ -281,3 +291,8 @@ void Scene::enableConstraingOverlay(bool enable) showConstraintOverlay = enable; } +std::shared_ptr Scene::getCamera() +{ + return nodes->getCameraNode()->getCamera(); +} + diff --git a/src/scene.h b/src/scene.h index 4220a781..1461bb02 100644 --- a/src/scene.h +++ b/src/scene.h @@ -54,7 +54,6 @@ class Scene : public AbstractScene void enableConstraingOverlay(bool enable); private: - Camera camera; std::shared_ptr cameraControllers; double frameTime; @@ -86,6 +85,7 @@ class Scene : public AbstractScene void renderDebuggingViews(const RenderData &renderData); RenderData createRenderData(); + std::shared_ptr getCamera(); std::shared_ptr textureMapperManager; }; diff --git a/test/test_camera.cc b/test/test_camera.cc new file mode 100644 index 00000000..195c4f84 --- /dev/null +++ b/test/test_camera.cc @@ -0,0 +1,49 @@ +#include "./test.h" +#include "../src/camera.h" + +TEST(Test_Camera, ConstructorFromMatricesWithDefaultValues) +{ + Camera expected; + expected.resize(1, 1); + + Camera camera(expected.getViewMatrix(), expected.getProjectionMatrix(), + expected.getOrigin()); + + EXPECT_Vector3f_NEAR(expected.getPosition(), camera.getPosition(), 1e-5f); + EXPECT_NEAR(expected.getRadius(), camera.getRadius(), 1e-5f); + + // just to recalculate the view matrix from the angles and test them + camera.changeAzimuth(0); + + EXPECT_Matrix4f_NEAR(expected.getViewMatrix(), camera.getViewMatrix(), 1e-5f); + EXPECT_Vector3f_NEAR(expected.getPosition(), camera.getPosition(), 1e-5f); + EXPECT_TRUE(camera.needsResizing()); + + camera.resize(1, 1); + + EXPECT_Matrix4f_NEAR(expected.getProjectionMatrix(), + camera.getProjectionMatrix(), 1e-5f); +} + +TEST(Test_Camera, ConstructorFromMatricesAfterRotation) +{ + Camera expected; + expected.resize(1, 1); + expected.changeAzimuth(M_PI * 0.25f); + + Camera camera(expected.getViewMatrix(), expected.getProjectionMatrix(), + expected.getOrigin()); + + EXPECT_Vector3f_NEAR(expected.getPosition(), camera.getPosition(), 1e-5f); + EXPECT_NEAR(expected.getRadius(), camera.getRadius(), 1e-5f); + + // just to recalculate the view matrix from the angles and test them + camera.changeAzimuth(0); + + EXPECT_Matrix4f_NEAR(expected.getViewMatrix(), camera.getViewMatrix(), 1e-5f); + EXPECT_Matrix4f_NEAR(expected.getProjectionMatrix(), + camera.getProjectionMatrix(), 1e-5f); + EXPECT_Vector3f_NEAR(expected.getPosition(), camera.getPosition(), 1e-5f); + EXPECT_TRUE(camera.needsResizing()); +} +