#include "externals.hh" #include "camera.hh" #include "utilities.hh" #include /*= 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; } } }