Added transformables

This commit is contained in:
Robert 2021-01-22 01:13:01 +01:00
parent 98425f45c8
commit f86fcad89f
5 changed files with 544 additions and 3 deletions

View file

@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.10)
project(OpenGLUtility)
# set(CMAKE_CXX_STANDARD 17)
set(build_examples ON CACHE BOOL "Build examples")
set(build_documentation ON CACHE BOOL "Generate documentation")
@ -26,7 +28,7 @@ add_library(openglu SHARED
${include_files}
${source_files}
"cpp.hint"
)
"src/transformable.cpp")
target_compile_definitions(openglu PRIVATE OGLU_BUILD_DLL)

View file

@ -1,8 +1,12 @@
#include <iostream>
#include "openglu.hpp"
#include "transformable.hpp"
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
@ -79,16 +83,32 @@ int main(int argc, char** argv)
oglu::Texture crate = oglu::MakeTexture("assets/crate.jpg");
oglu::Texture opengl = oglu::MakeTexture("assets/opengl.png");
oglu::Transformable model;
//model.SetRotation(-55.0f, 0.0f, 0.0f);
glm::mat4 view = glm::mat4(1.0f);
view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));
glm::mat4 projection;
projection = glm::perspective(glm::radians(45.f), 1.0f, 0.1f, 100.0f);
glm::mat4 test = glm::make_mat4(model.GetMatrix());
// Window loop
while (!glfwWindowShouldClose(window))
{
processInput(window);
oglu::ClearScreen(GL_COLOR_BUFFER_BIT, oglu::Color(0.29f, 0.13f, 0.23f));
oglu::ClearScreen(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, oglu::Color(0.29f, 0.13f, 0.23f));
model.Rotate(6.0f, 0.0f, 0.0f);
shader->Use();
shader->SetUniform("texture1", crate, 0);
shader->SetUniform("texture2", opengl, 1);
shader->SetUniformMatrix4fv("model", 1, GL_FALSE, model.GetMatrix());
shader->SetUniformMatrix4fv("view", 1, GL_FALSE, glm::value_ptr(view));
shader->SetUniformMatrix4fv("projection", 1, GL_FALSE, glm::value_ptr(projection));
square->BindAndDraw();

View file

@ -6,9 +6,13 @@ layout (location = 2) in vec2 aUV;
out vec3 oCol;
out vec2 oUV;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
oCol = aCol;
oUV = aUV;
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
gl_Position = projection * view * model * vec4(aPos, 1.0);
}

248
include/transformable.hpp Normal file
View file

@ -0,0 +1,248 @@
/*****************************************************************//**
* \file transformable.hpp
* \brief Contains utility for anything that has a geometry
*
* \author Lauchmelder
* \date January 2021
*********************************************************************/
#ifndef TRANSFORMABLE_HPP
#define TRANSFORMABLE_HPP
#include <core.hpp>
namespace oglu
{
/**
* @brief Defines position, rotation and scale.
*
* This class wraps a 4x4 transformation matrix and provides useful
* helper functions to perform translations, rotations and scalings.
*/
class OGLU_API Transformable
{
public:
/**
* @brief Create new identity transformation.
*
* An identity transformation is a matrix with all 1's on the diagonal.
* When applied to a vector it leaves it unchanged.
*/
Transformable();
/**
* @brief Copies another transformation.
*
* The transformation matrix of @p other is copied.
*/
Transformable(const Transformable& other);
~Transformable();
/**
* @brief Sets the position.
*
* This sets an absolute position, means that it resets any previous
* translations.
*
* @param[in] x New x position
* @param[in] y New y position
* @param[in] z New z position
*/
void SetPosition(float x, float y, float z);
/**
* @brief Sets the position.
*
* This sets an absolute position, means that it resets any previous
* translations.
*
* @param[in] position An array of floats containing three scalars
*/
void SetPosition(const float* translation);
/**
* @brief Sets the rotation.
*
* This sets an absolute rotation, means that it resets any previous
* rotations.
*
* @param[in] rotX New rotation around x axis
* @param[in] rotY New rotation around y axis
* @param[in] rotZ New rotation around z axis
*/
void SetRotation(float rotX, float rotY, float rotZ);
/**
* @brief Sets the rotation.
*
* This sets an absolute rotation, means that it resets any previous
* rotations.
*
* @param[in] rotation An array of floats containing three scalars
*/
void SetRotation(const float* rotation);
/**
* @brief Sets the rotation.
*
* This sets an absolute rotation, means that it resets any previous
* rotations.
*
* @param[in] angle The angle to rotate by
* @param[in] xAxis The x component of the rotation axis
* @param[in] yAxis The y component of the rotation axis
* @param[in] zAxis The z component of the rotation axis
*/
void SetRotation(float angle, float xAxis, float yAxis, float zAxis);
/**
* @brief Sets the rotation.
*
* This sets an absolute rotation, means that it resets any previous
* rotations.
*
* @param[in] angle The angle to rotate by
* @param[in] axis An array of floats containing the three rotation axis components
*/
void SetRotation(float angle, const float* axis);
/**
* @brief Sets the scaling.
*
* This sets an absolute scaling, means that it resets any previous
* scaling.
*
* @param[in] scaleX The scaling in x direction
* @param[in] scaleY The scaling in y direction
* @param[in] scaleZ The scaling in z direction
*/
void SetScale(float scaleX, float scaleY, float scaleZ);
/**
* @brief Sets the scaling.
*
* This sets an absolute scaling, means that it resets any previous
* scaling.
*
* @param[in] scale An array of floats containing three scalars
*/
void SetScale(const float* scale);
/**
* @brief Performs a translation.
*
* This function applies a translation to the object, it operates
* operates on the current position.
*
* @param[in] x Offset along the x axis
* @param[in] y Offset along the y axis
* @param[in] z Offset along the z axis
*/
void Move(float x, float y, float z);
/**
* @brief Performs a translation.
*
* This function applies a translation to the object, it operates
* operates on the current position.
*
* @param[in] position An array of floats containing the offset values
*/
void Move(const float* translation);
/**
* @brief Performs a rotation.
*
* This function applies a rotation to the object, it operates
* operates on the current rotation.
*
* @param[in] rotX Rotation around the x axis
* @param[in] rotY Rotation around the y axis
* @param[in] rotZ Rotation around the z axis
*/
void Rotate(float rotX, float rotY, float rotZ);
/**
* @brief Performs a rotation.
*
* This function applies a rotation to the object, it operates
* operates on the current rotation.
*
* @param[in] rotation An array of floats containing the rotation values
*/
void Rotate(const float* rotation);
/**
* @brief Performs a rotation.
*
* This function applies a rotation to the object, it operates
* operates on the current rotation.
*
* @param[in] angle The angle to rotate by
* @param[in] xAxis x component of the rotation axis
* @param[in] yAxis y component of the rotation axis
* @param[in] zAxis z component of the rotation axis
*/
void Rotate(float angle, float xAxis, float yAxis, float zAxis);
/**
* @brief Performs a rotation.
*
* This function applies a rotation to the object, it operates
* operates on the current rotation.
*
* @param[in] angle The angle to rotate by
* @param[in] An array of floats containing the components of the rotation axis
*/
void Rotate(float angle, const float* axis);
/**
* @brief Performs scaling.
*
* This function applies scaling to the object, it operates
* operates on the current scaling.
*
* @param[in] scaleX Scaling in x direction
* @param[in] scaleX Scaling in y direction
* @param[in] scaleX Scaling in z direction
*/
void Scale(float scaleX, float scaleY, float scaleZ);
/**
* @brief Performs scaling.
*
* This function applies scaling to the object, it operates
* operates on the current scaling.
*
* @param[in] scale An array of floats containing three scaling values
*/
void Scale(const float* scale);
/**
* @brief Returns a transformation matrix.
*
* Internally, this function multiplies the translation, rotation,
* and scaling matrices into one transformation matrix which is
* then returned.
*
* This multiplication is only performed when a change occured to one
* of those matrices (so when there was a translation, rotation or scaling).
* So it is okay to call this function multiple times without huge performance
* loss, as long as no transformations occur inbetween.
*
* @return An array of 16 floats representing the transformation matrix
*/
const float* GetMatrix();
private:
// TODO: Separate translation, rotation and scaling matrices.
// Combine them only when the user wants the transformation matrix
float* translation; ///< Translation matrix
float* rotation; ///< Rotation matrix
float* scaling; ///< Scaling matrix
bool calculateMatrix; ///< Wether GetMatrix() needs to re-calculate the transformation matrix
};
}
#endif

267
src/transformable.cpp Normal file
View file

@ -0,0 +1,267 @@
#include "transformable.hpp"
#include <algorithm>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
namespace oglu
{
oglu::Transformable::Transformable() :
translation(new float[16]), rotation(new float[16]), scaling(new float[16]), calculateMatrix(false)
{
glm::mat4 identity(1.0f);
memcpy(
translation,
glm::value_ptr(identity),
16 * sizeof(float)
);
memcpy(
rotation,
glm::value_ptr(identity),
16 * sizeof(float)
);
memcpy(
scaling,
glm::value_ptr(identity),
16 * sizeof(float)
);
}
Transformable::Transformable(const Transformable& other) :
translation(new float[16]), rotation(new float[16]), scaling(new float[16]), calculateMatrix(true)
{
memcpy(
this->translation,
other.translation,
16 * sizeof(float)
);
memcpy(
this->rotation,
other.rotation,
16 * sizeof(float)
);
memcpy(
this->scaling,
other.scaling,
16 * sizeof(float)
);
}
Transformable::~Transformable()
{
delete[] scaling;
delete[] rotation;
delete[] translation;
}
void Transformable::SetPosition(float x, float y, float z)
{
memcpy(
this->translation,
glm::value_ptr(glm::translate(glm::mat4(1.0f), glm::vec3(x, y, z))),
16 * sizeof(float)
);
calculateMatrix = true;
}
void Transformable::SetPosition(const float* translation)
{
memcpy(
this->translation,
glm::value_ptr(glm::translate(glm::mat4(1.0f), glm::make_vec3(translation))),
16 * sizeof(float)
);
calculateMatrix = true;
}
void Transformable::SetRotation(float rotX, float rotY, float rotZ)
{
// TODO: Using rotation matrices is stupid. Eventually this could (should) be done with quaternions
// For now we'll just risk gimbal locking the model
memcpy(
this->rotation,
glm::value_ptr(
glm::rotate(
glm::rotate(
glm::rotate(
glm::mat4(1.0f), glm::radians(rotX), glm::vec3(1.0f, 0.0f, 0.0f)
), glm::radians(rotY), glm::vec3(0.0f, 1.0f, 0.0f)
), glm::radians(rotZ), glm::vec3(0.0f, 0.0f, 1.0f)
)
),
16 * sizeof(float)
);
calculateMatrix = true;
}
void Transformable::SetRotation(const float* rotation)
{
memcpy(
this->rotation,
glm::value_ptr(
glm::rotate(
glm::rotate(
glm::rotate(
glm::mat4(1.0f), glm::radians(rotation[0]), glm::vec3(1.0f, 0.0f, 0.0f)
), glm::radians(rotation[1]), glm::vec3(0.0f, 1.0f, 0.0f)
), glm::radians(rotation[2]), glm::vec3(0.0f, 0.0f, 1.0f)
)
),
16 * sizeof(float)
);
calculateMatrix = true;
}
void Transformable::SetRotation(float angle, float xAxis, float yAxis, float zAxis)
{
memcpy(
this->rotation,
glm::value_ptr(glm::rotate(glm::mat4(1.0f), glm::radians(angle), glm::vec3(xAxis, yAxis, zAxis))),
16 * sizeof(float)
);
calculateMatrix = true;
}
void Transformable::SetRotation(float angle, const float* axis)
{
memcpy(
this->rotation,
glm::value_ptr(glm::rotate(glm::mat4(1.0f), glm::radians(angle), glm::make_vec3(axis))),
16 * sizeof(float)
);
calculateMatrix = true;
}
void Transformable::SetScale(float scaleX, float scaleY, float scaleZ)
{
memcpy(
this->scaling,
glm::value_ptr(glm::scale(glm::mat4(1.0f), glm::vec3(scaleX, scaleY, scaleZ))),
16 * sizeof(float)
);
calculateMatrix = true;
}
void Transformable::SetScale(const float* scale)
{
memcpy(
this->scaling,
glm::value_ptr(glm::scale(glm::mat4(1.0f), glm::make_vec3(scale))),
16 * sizeof(float)
);
calculateMatrix = true;
}
void Transformable::Move(float x, float y, float z)
{
memcpy(
this->translation,
glm::value_ptr(glm::translate(glm::make_mat4(this->translation), glm::vec3(x, y, z))),
16 * sizeof(float)
);
calculateMatrix = true;
}
void Transformable::Move(const float* translation)
{
memcpy(
this->translation,
glm::value_ptr(glm::translate(glm::make_mat4(this->translation), glm::make_vec3(translation))),
16 * sizeof(float)
);
calculateMatrix = true;
}
void Transformable::Rotate(float rotX, float rotY, float rotZ)
{
memcpy(
this->rotation,
glm::value_ptr(
glm::rotate(
glm::rotate(
glm::rotate(
glm::make_mat4(this->rotation), glm::radians(rotX), glm::vec3(1.0f, 0.0f, 0.0f)
), glm::radians(rotY), glm::vec3(0.0f, 1.0f, 0.0f)
), glm::radians(rotZ), glm::vec3(0.0f, 0.0f, 1.0f)
)
),
16 * sizeof(float)
);
calculateMatrix = true;
}
void Transformable::Rotate(const float* rotation)
{
memcpy(
this->rotation,
glm::value_ptr(
glm::rotate(
glm::rotate(
glm::rotate(
glm::make_mat4(this->rotation), glm::radians(rotation[0]), glm::vec3(1.0f, 0.0f, 0.0f)
), glm::radians(rotation[1]), glm::vec3(0.0f, 1.0f, 0.0f)
), glm::radians(rotation[2]), glm::vec3(0.0f, 0.0f, 1.0f)
)
),
16 * sizeof(float)
);
calculateMatrix = true;
}
void Transformable::Rotate(float angle, float xAxis, float yAxis, float zAxis)
{
memcpy(
this->rotation,
glm::value_ptr(glm::rotate(glm::make_mat4(this->rotation), glm::radians(angle), glm::vec3(xAxis, yAxis, zAxis))),
16 * sizeof(float)
);
calculateMatrix = true;
}
void Transformable::Rotate(float angle, const float* axis)
{
memcpy(
this->rotation,
glm::value_ptr(glm::rotate(glm::make_mat4(this->rotation), glm::radians(angle), glm::make_vec3(axis))),
16 * sizeof(float)
);
calculateMatrix = true;
}
void Transformable::Scale(float scaleX, float scaleY, float scaleZ)
{
memcpy(
this->scaling,
glm::value_ptr(glm::scale(glm::make_mat4(this->scaling), glm::vec3(scaleX, scaleY, scaleZ))),
16 * sizeof(float)
);
calculateMatrix = true;
}
void Transformable::Scale(const float* scale)
{
memcpy(
this->scaling,
glm::value_ptr(glm::translate(glm::make_mat4(this->scaling), glm::make_vec3(scale))),
16 * sizeof(float)
);
calculateMatrix = true;
}
const float* Transformable::GetMatrix()
{
static glm::mat4 transformation(1.0f);
if (calculateMatrix)
{
transformation = glm::make_mat4(translation) * glm::make_mat4(rotation) * glm::make_mat4(scaling);
calculateMatrix = false;
}
return glm::value_ptr(transformation);
}
}