demotool/camera.cc
Emmanuel BENOîT 1078ff67b5 Overrides - Further work on camera data
It *should* be ready to be used with the overrides system now.
2017-11-20 08:38:22 +01:00

144 lines
3.4 KiB
C++

#include "externals.hh"
#include "camera.hh"
#include "utilities.hh"
#include <glm/gtc/matrix_access.hpp>
/*= T_Camera =================================================================*/
T_Camera::T_Camera( ) noexcept
{
cvtFov2Np( );
cvtAnglesToVectors( );
}
/*----------------------------------------------------------------------------*/
void T_Camera::camera(
glm::vec3 const& lookAt ,
glm::vec3 const& angles ,
const float distance ) noexcept
{
lookAt_ = lookAt;
angles_ = angles;
distance_ = distance;
cvtAnglesToVectors( );
}
void T_Camera::camera(
glm::vec3 const& position ,
glm::vec3 const& target ,
glm::vec3 const& up ) noexcept
{
pos_ = position;
up_ = up;
lookAt_ = target;
cvtVectorsToAngles( );
}
void T_Camera::cvtAnglesToVectors( ) noexcept
{
anglesToMatrix( &angles_.x , &rotMat_[ 0 ].x );
dir_ = glm::vec3( 0 , 0 , -distance_ ) * rotMat_;
up_ = glm::vec3( 0 , 1 , 0 ) * rotMat_;
pos_ = lookAt_ - dir_;
}
void T_Camera::cvtVectorsToAngles( ) noexcept
{
dir_ = lookAt_ - pos_;
distance_ = dir_.length( );
if ( distance_ == 0 ) {
angles_ = glm::vec3( 0 );
return;
}
const glm::vec3 nDir{ - dir_ / distance_ };
const glm::vec3 side{ normalize( cross( normalize( up_ ) , nDir ) ) };
const glm::vec3 up{ normalize( cross( nDir , side ) ) };
column( rotMat_ , 0 ) = side;
column( rotMat_ , 1 ) = up;
column( rotMat_ , 2 ) = nDir;
glm::vec3 nAngles;
nAngles.x = atan2f( nDir.y , nDir.z );
const float c2{ sqrtf( side.x * side.x + side.y * side.y ) };
nAngles.y = atan2f( -side.z , c2 );
const float s1{ sinf( nAngles.x ) } , c1{ cosf( nAngles.x ) };
nAngles.z = atan2f( s1 * nDir.x - c1 * up.x ,
c1 * up.y - s1 * nDir.y );
angles_ = nAngles * 360.f / float( M_PI );
}
/*------------------------------------------------------------------------------*/
void T_Camera::handleDND(
ImVec2 const& move ,
const bool hasCtrl ,
const bool hasShift ,
const bool lmb ) noexcept
{
if ( move.x == 0 || move.y == 0 ) {
return;
}
const float fdx( move.x * .1f * ( hasCtrl ? 1.f : .1f ) );
const float fdy( move.y * .1f * ( hasCtrl ? 1.f : .1f ) );
if ( lmb && hasShift ) {
// Left mouse button, shift - move camera
const auto side( glm::normalize( glm::cross( up_ , dir_ ) ) );
lookAt_ += .1f * ( side * fdx + up_ * fdy );
} else if ( lmb ) {
// Left mouse button, no shift - change yaw/pitch
updateAngle( angles_.y , fdx );
updateAngle( angles_.x , fdy );
} else {
// Right mouse button - change roll
updateAngle( angles_.z , fdx );
}
cvtAnglesToVectors( );
}
void T_Camera::handleWheel(
const float wheel ,
const bool hasCtrl ,
const bool hasShift ) noexcept
{
const float delta( wheel * ( hasCtrl ? 1.f : .1f) );
if ( hasShift ) {
fov_ = std::max( 1.f , std::min( 179.f , fov_ + delta ) );
cvtFov2Np( );
} else {
distance_ = std::max( .01f , distance_ - delta );
cvtAnglesToVectors( );
}
}
/*----------------------------------------------------------------------------*/
void T_Camera::makeUI( ) noexcept
{
using namespace ImGui;
const bool changed[] = {
DragFloat3( "Target" , &lookAt_.x ) ,
DragFloat( "Distance" , &distance_ , .1f ,
.1f , 1e8 , "%.1f" ) ,
DragFloat3( "Angles" , &angles_.x , .01f , -180 , 180 ) ,
DragFloat( "FoV" , &fov_ , .01f , .01f , 179.9f )
};
for ( unsigned i = 0 ; i < sizeof( changed ) / sizeof( bool ) ; i ++ ) {
if ( changed[ i ] ) {
#warning fix this shit
// FIXME update( );
break;
}
}
}