diff --git a/examples/model_loading/main.cpp b/examples/model_loading/main.cpp index e0e29a2..ab63ac5 100644 --- a/examples/model_loading/main.cpp +++ b/examples/model_loading/main.cpp @@ -69,28 +69,26 @@ int main(int argc, char** argv) return -1; } - glm::mat4 view = glm::mat4(1.0f); - view = glm::translate(view, glm::vec3(0.0f, -2.0f, -10.0f)); + oglu::Enable(GL_DEPTH_TEST); - glm::mat4 projection; - projection = glm::perspective(glm::radians(45.f), 1.0f, 0.1f, 100.0f); + oglu::Camera camera(60.0f, 0.0f, 0.1f, 100.0f); + camera.Move(0.0f, -4.0f, -10.0f); + //camera.LookAt(utah); + //camera.GetMatrix(); // Window loop - oglu::Enable(GL_DEPTH_TEST); while (!glfwWindowShouldClose(window)) { processInput(window); oglu::ClearScreen(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, oglu::Color(0.29f, 0.13f, 0.23f)); - // view = glm::rotate(view, glm::radians(1.0f), glm::vec3(0.0f, 1.0f, 0.0f)); - utah.Rotate(0.0f, 1.0f, 0.0f); shader->Use(); shader->SetUniform("model", utah); - shader->SetUniformMatrix4fv("view", 1, GL_FALSE, glm::value_ptr(view)); - shader->SetUniformMatrix4fv("projection", 1, GL_FALSE, glm::value_ptr(projection)); + shader->SetUniformMatrix4fv("view", 1, GL_FALSE, camera.GetMatrix()); + shader->SetUniformMatrix4fv("projection", 1, GL_FALSE, camera.GetProjectionMatrix()); oglu::PolygonMode(GL_FRONT_AND_BACK, GL_LINE); utah.Render(); diff --git a/include/camera.hpp b/include/camera.hpp new file mode 100644 index 0000000..f5c6567 --- /dev/null +++ b/include/camera.hpp @@ -0,0 +1,110 @@ +/*****************************************************************//** + * \file camera.hpp + * \brief Contains anything relevant to cameras + * + * \author Lauchmelder + * \date January 2021 + *********************************************************************/ +#ifndef CAMERA_HPP +#define CAMERA_HPP + +#include +#include + +namespace oglu +{ + class Object; + + /** + * @brief A camera object in 3D space. + * + * This class unites a world- and projection matrix. + */ + class OGLU_API Camera : public Transformable + { + public: + /** + * @brief Create a default camera. + * + * Sits at the origin, looks in negative z-direction. + * FOV: 45.0° + * Aspect ratio: Matches the viewport + * zNear: 0.1f + * zFar: 100.0f + */ + Camera(); + + /** + * @brief Copy another camera. + * + * Every property of @p other is copied. + * + * @param[in] other The camera to copy from + */ + Camera(const Camera& other); + + /** + * @brief Create a new camera. + * + * Sits at the origin, looks in negative z-direction. + * The other properties are set from the parameters + * + * @param[in] fov The FOV (field of view) of the camera + * @param[in] aspectRatio The aspect ratio of the camera. (Setting this to 0.f will use your viewport's aspect ratio) + * @param[in] zNear Near z clipping plane + * @param[in] zNear Far z clipping plane + */ + Camera(float fov, float aspectRatio, float zNear, float zFar); + + ~Camera(); + + /** + * @brief Have camera face at a certain position. + * + * This will adjust the camera's rotation in order to put the + * specified coordinate at the center of the screen. + * + * @param[in] x Target x coordinate + * @param[in] y Target y coordinate + * @param[in] z Target z coordinate + */ + void LookAt(GLfloat x, GLfloat y, GLfloat z); + + /** + * @brief Have camera face at a certain position. + * + * This will adjust the camera's rotation in order to put the + * specified coordinate at the center of the screen. + * + * @param[in] target 3D vector with the target position + */ + void LookAt(const GLfloat* target); + + /** + * @brief Have camera face at a certain position. + * + * This will adjust the camera's rotation in order to put the + * specified coordinate at the center of the screen. + * + * @param[in] target An object to target + */ + void LookAt(const Object& target); + + /** + * @brief Gets the projection matrix of the camera. + * + * @returns a 4x4 projection matrix. + */ + const float* GetProjectionMatrix(); + + private: + float aspectRatio; ///< Aspect ration of the camera + float fov; ///< FOV of the camera + float zNear; ///< Near z clipping plane + float zFar; ///< Far z clipping plane + + float* projection; + }; +} + +#endif \ No newline at end of file diff --git a/include/core.hpp b/include/core.hpp index 39d00b4..c7f2f4a 100644 --- a/include/core.hpp +++ b/include/core.hpp @@ -13,9 +13,7 @@ #include #include -#ifdef OGLU_BUILD_DLL #include -#endif #ifdef OGLU_WIN32 #ifdef OGLU_BUILD_DLL diff --git a/include/openglu.hpp b/include/openglu.hpp index 51a5840..46c93bd 100644 --- a/include/openglu.hpp +++ b/include/openglu.hpp @@ -13,6 +13,7 @@ #include #include #include +#include namespace oglu { diff --git a/include/transformable.hpp b/include/transformable.hpp index 4b91f1b..c5137a9 100644 --- a/include/transformable.hpp +++ b/include/transformable.hpp @@ -262,6 +262,7 @@ namespace oglu float* rotation; ///< Rotation matrix float* scaling; ///< Scaling vector + float* transformation; bool calculateMatrix; ///< Wether GetMatrix() needs to re-calculate the transformation matrix }; } diff --git a/src/camera.cpp b/src/camera.cpp new file mode 100644 index 0000000..b924a76 --- /dev/null +++ b/src/camera.cpp @@ -0,0 +1,68 @@ +#include "camera.hpp" + +#include + +#include +#include +#include + +namespace oglu +{ + Camera::Camera() : + fov(45.0f), aspectRatio(0.0f), zNear(0.1f), zFar(100.0f), projection(new float[16]{ 0.0f }) + { + memcpy( + projection, + glm::value_ptr(glm::perspective(glm::radians(fov), aspectRatio, zNear, zFar)), + 16 * sizeof(float) + ); + } + + Camera::Camera(const Camera& other) : + fov(other.fov), aspectRatio(other.aspectRatio), zNear(other.zNear), zFar(other.zFar), projection(new float[16]{ 0.0f }) + { + memcpy( + projection, + other.projection, + 16 * sizeof(float) + ); + } + + Camera::Camera(float fov, float aspectRatio, float zNear, float zFar) : + fov(fov), aspectRatio(aspectRatio), zNear(zNear), zFar(zFar), projection(new float[16]{ 0.0f }) + { + if (aspectRatio == 0.0f) + { + GLint viewport[4]; + glGetIntegerv(GL_VIEWPORT, viewport); + aspectRatio = (float)viewport[2] / (float)viewport[3]; + } + + memcpy( + projection, + glm::value_ptr(glm::perspective(glm::radians(fov), aspectRatio, zNear, zFar)), + 16 * sizeof(float) + ); + } + + Camera::~Camera() + { + } + + void Camera::LookAt(GLfloat x, GLfloat y, GLfloat z) + { + } + + void Camera::LookAt(const GLfloat* target) + { + } + + void Camera::LookAt(const Object& target) + { + } + + const float* Camera::GetProjectionMatrix() + { + return projection; + } +} diff --git a/src/transformable.cpp b/src/transformable.cpp index a8b13c8..844e66a 100644 --- a/src/transformable.cpp +++ b/src/transformable.cpp @@ -9,7 +9,7 @@ namespace oglu { oglu::Transformable::Transformable() : - position(new float[3]{ 0.f }), rotation(new float[16]), scaling(new float[3]{ 1.f, 1.f, 1.f }), calculateMatrix(false) + position(new float[3]{ 0.f }), rotation(new float[16]), scaling(new float[3]{ 1.f, 1.f, 1.f }), transformation(new float[16]), calculateMatrix(false) { glm::mat4 identity(1.0f); memcpy( @@ -17,10 +17,15 @@ namespace oglu glm::value_ptr(identity), 16 * sizeof(float) ); + memcpy( + transformation, + glm::value_ptr(identity), + 16 * sizeof(float) + ); } Transformable::Transformable(const Transformable& other) : - position(new float[3]), rotation(new float[16]), scaling(new float[3]), calculateMatrix(true) + position(new float[3]), rotation(new float[16]), scaling(new float[3]), transformation(new float[16]), calculateMatrix(true) { memcpy( this->position, @@ -232,15 +237,17 @@ namespace oglu const float* Transformable::GetMatrix() { - static glm::mat4 transformation(1.0f); - if (calculateMatrix) { - transformation = glm::translate(glm::mat4(1.0f), glm::make_vec3(position)) * glm::make_mat4(rotation) * glm::scale(glm::mat4(1.0f), glm::make_vec3(scaling)); + memcpy( + transformation, + glm::value_ptr(glm::translate(glm::mat4(1.0f), glm::make_vec3(position)) * glm::make_mat4(rotation) * glm::scale(glm::mat4(1.0f), glm::make_vec3(scaling))), + 16 * sizeof(float) + ); calculateMatrix = false; } - return glm::value_ptr(transformation); + return transformation; } const float* Transformable::GetPosition()