diff --git a/include/ACGL/Scene/MoveableObject.hh b/include/ACGL/Scene/MoveableObject.hh new file mode 100644 index 0000000000000000000000000000000000000000..f91d27cb4a5acda4a003854f266f763367dbdfc7 --- /dev/null +++ b/include/ACGL/Scene/MoveableObject.hh @@ -0,0 +1,153 @@ +/*********************************************************************** + * Copyright 2014 Computer Graphics Group RWTH Aachen University. * + * All rights reserved. * + * Distributed under the terms of the MIT License (see LICENSE.TXT). * + **********************************************************************/ + +/* + * A moveable object is an interface for something that can be moved around and has an orientation. + * This means it has access functions for a modelmatrix containing a position and orientation as + * well as just getting the position or the rotation. + * It can be moved relative to its own orientation. + * + * + * ModelMatrix = Rotation * Translation + * ( it is translated in space and then rotated around that spot ) + * + */ + +#pragma once +#include <ACGL/ACGL.hh> +#include <ACGL/Math/Math.hh> +#include <glm/gtx/quaternion.hpp> + +namespace ACGL{ +namespace Scene{ + +class MoveableObject +{ +public: + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // + // Constructor / Destructor / save&store + // + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Default Constructor. + */ + MoveableObject(); + + /** + * Destructor. + */ + ~MoveableObject() {} + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // + // Set / Get the matrices: + // + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////////////////////////////// + // + // Generic rotation and translation matrices. + // + + /// Gets the orthonormal rotation matrix (mat3) + const glm::mat3 &getRotationMatrix3() const { return mRotationMatrix; } + + /// Gets the inverse orthonormal rotation matrix (mat3) + glm::mat3 getInverseRotationMatrix3() const { return glm::transpose(mRotationMatrix); } + + /// Gets the orthonormal rotation matrix as a mat4 + glm::mat4 getRotationMatrix4() const { return glm::mat4(mRotationMatrix); } + + + /// Sets the rotation matrix (mat3) + void setRotationMatrix( glm::mat3 _matrix ); + + /// Sets the rotation matrix (mat3-part of a mat4) + void setRotationMatrix( glm::mat4 _matrix ); + + /// Sets the complete lookat (position and rotation) + void setLookAtMatrix( const glm::vec3 &_position, const glm::vec3 &_target, const glm::vec3 &_up ); + + /// Gets the translation matrix of this object (no rotational element) + glm::mat4 getTranslationMatrix4() const; + + /////////////////////////////////////////////////////////////////////////////////////////// + // + // Generic model matrices. + // + + /// Gets the currently active view matrix (depends on stereo mode and current eye) + glm::mat4 getModelMatrix() const; + + /// Gets the currently active view matrix (depends on stereo mode and current eye) + glm::mat4 getInverseModelMatrix() const; + + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // + // Set / Get properties that move the object around (or rotate etc.) + // + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * Set the position of the camera. + * @param _position New position of the object. + */ + void setPosition( const glm::vec3 &_position ) { mPosition = _position; } + glm::vec3 getPosition() const { return mPosition; } + + /// Moves the object by a given vector (relative to own orientation) + void move( const glm::vec3 &_vector ); + void moveRight( float _distance ) { move( glm::vec3(_distance,0,0) ); } + void moveBack( float _distance ) { move( glm::vec3(0,0,_distance) ); } + void moveUp( float _distance ) { move( glm::vec3(0,_distance,0) ); } + void moveLeft( float _distance ) { move( glm::vec3(-_distance,0,0) ); } + void moveForward( float _distance ) { move( glm::vec3(0,0,-_distance) ); } + void moveDown( float _distance ) { move( glm::vec3(0,-_distance,0) ); } + + /** + * Set the distance of the object to the object it's looking at. + * Will change the target! + * @param _distance New distance of the object this is pointed at. + */ + void setLookAtDistance( float _distance ); + /// Gets the look-at distance + float getLookAtDistance() const { return mLookAtDistance; } + + /// Will change the look at distance! + /// Will change the rotation! + /// Uses stored up-vector as reference + void setTarget( const glm::vec3 &_target ) { setTarget(_target, getUpDirection()); } + + /// Will change the look at distance! + /// Will change the rotation! + /// Uses given up-vector as reference + void setTarget( const glm::vec3 &_target, const glm::vec3 &_up ); + + /// Gets the reconstructed target + glm::vec3 getTarget() const { return mPosition + getForwardDirection() * getLookAtDistance(); } + + /// Get the unit up direction + glm::vec3 getUpDirection () const; + /// Get the unit right direction + glm::vec3 getRightDirection () const; + /// Get the unit forward direction + glm::vec3 getForwardDirection() const; + +private: + /// Current position + glm::vec3 mPosition; + + /// Current rotation + glm::mat3 mRotationMatrix; + + /// might be used later to rotate around this position: + float mLookAtDistance; +}; + +} // Scene +} // ACGL diff --git a/src/ACGL/Scene/MoveableObject.cc b/src/ACGL/Scene/MoveableObject.cc new file mode 100644 index 0000000000000000000000000000000000000000..58c21d772d2d4bbdc0cd0783924d155df1204567 --- /dev/null +++ b/src/ACGL/Scene/MoveableObject.cc @@ -0,0 +1,123 @@ +/*********************************************************************** + * Copyright 2014 Computer Graphics Group RWTH Aachen University. * + * All rights reserved. * + * Distributed under the terms of the MIT License (see LICENSE.TXT). * + **********************************************************************/ + +#include <ACGL/Scene/MoveableObject.hh> + +#include <cassert> + +#include <ACGL/Math/Math.hh> +#include <glm/gtc/matrix_transform.hpp> +#include <glm/gtc/quaternion.hpp> +#include <glm/gtx/euler_angles.hpp> + +using namespace ACGL; +using namespace ACGL::Math::Functions; +using namespace ACGL::Scene; +using namespace std; + + +void MoveableObject::setRotationMatrix(glm::mat3 _matrix) +{ + mRotationMatrix = _matrix; + assert(isOrthonormalMatrix(mRotationMatrix)); +} + +void MoveableObject::setRotationMatrix(glm::mat4 _matrix) +{ + mRotationMatrix = glm::mat3(_matrix); + assert(isOrthonormalMatrix(mRotationMatrix)); +} + +void MoveableObject::setLookAtMatrix(const glm::vec3 &_position, const glm::vec3 &_target, const glm::vec3 &_up) +{ + setPosition(_position); + setTarget(_target, _up); +} + +glm::mat4 MoveableObject::getTranslationMatrix4() const +{ + glm::mat4 trans; + trans[3][0] = -mPosition.x; + trans[3][1] = -mPosition.y; + trans[3][2] = -mPosition.z; + return trans; +} + +glm::vec3 MoveableObject::getUpDirection () const +{ + glm::vec3 up(mRotationMatrix[0][1], mRotationMatrix[1][1], mRotationMatrix[2][1]); + assert(glm::distance(getInverseRotationMatrix3() * glm::vec3(0.0f, 1.0f, 0.0f), up) < .01); + return up; +} +glm::vec3 MoveableObject::getRightDirection () const +{ + glm::vec3 right(mRotationMatrix[0][0], mRotationMatrix[1][0], mRotationMatrix[2][0]); + assert(glm::distance(getInverseRotationMatrix3() * glm::vec3(1.0f, 0.0f, 0.0f), right) < .01); + return right; +} +glm::vec3 MoveableObject::getForwardDirection() const +{ + glm::vec3 forward(-mRotationMatrix[0][2], -mRotationMatrix[1][2], -mRotationMatrix[2][2]); + assert(glm::distance(getInverseRotationMatrix3() * glm::vec3(0.0f, 0.0f, -1.0f), forward) < .01); + return forward; +} + +void MoveableObject::setTarget(const glm::vec3 &_target, const glm::vec3 &_up) +{ + glm::vec3 forwardVector = _target - mPosition; + mLookAtDistance = glm::length( forwardVector ); + + forwardVector = forwardVector / (float)mLookAtDistance; // normalize + glm::vec3 rightVector = glm::normalize(glm::cross( forwardVector, _up )); + glm::vec3 upVector = glm::cross( rightVector, forwardVector ); + + glm::mat3 rotMatrix; + rotMatrix[0][0] = rightVector.x; + rotMatrix[0][1] = upVector.x; + rotMatrix[0][2] = -forwardVector.x; + rotMatrix[1][0] = rightVector.y; + rotMatrix[1][1] = upVector.y; + rotMatrix[1][2] = -forwardVector.y; + rotMatrix[2][0] = rightVector.z; + rotMatrix[2][1] = upVector.z; + rotMatrix[2][2] = -forwardVector.z; + + setRotationMatrix( rotMatrix ); +} + +void MoveableObject::setLookAtDistance(float _distance) +{ + assert (_distance > 0.0f); + mLookAtDistance = _distance; +} + +glm::mat4 MoveableObject::getModelMatrix() const +{ + glm::mat4 m(mRotationMatrix); + m[3][0] = -(m[0][0] * mPosition.x + m[1][0] * mPosition.y + m[2][0] * mPosition.z); + m[3][1] = -(m[0][1] * mPosition.x + m[1][1] * mPosition.y + m[2][1] * mPosition.z); + m[3][2] = -(m[0][2] * mPosition.x + m[1][2] * mPosition.y + m[2][2] * mPosition.z); + assert( isApproxEqual( getRotationMatrix4() * getTranslationMatrix4(), m ) ); + return m; +} + + +glm::mat4 MoveableObject::getInverseModelMatrix() const +{ + glm::mat4 modelMatrix = getModelMatrix(); + return glm::inverse( modelMatrix ); +} + + +void MoveableObject::move( const glm::vec3 &_vector ) +{ + glm::mat3 inverseRotation = getInverseRotationMatrix3(); + mPosition += (inverseRotation * _vector); +} + + + +