Overrides - Camera UI

Camera control using the input overrides panel works, although the
controls are a bit too sensitive (and there's a risk of fucking things
up with bad Up vectors)
This commit is contained in:
Emmanuel BENOîT 2017-11-20 11:12:27 +01:00
parent b954f20e0e
commit aa58b016c2
4 changed files with 165 additions and 19 deletions

View file

@ -27,13 +27,13 @@ void T_Camera::camera(
} }
void T_Camera::camera( void T_Camera::camera(
glm::vec3 const& lookAt ,
glm::vec3 const& position , glm::vec3 const& position ,
glm::vec3 const& target ,
glm::vec3 const& up ) noexcept glm::vec3 const& up ) noexcept
{ {
pos_ = position; pos_ = position;
up_ = up; up_ = up;
lookAt_ = target; lookAt_ = lookAt;
cvtVectorsToAngles( ); cvtVectorsToAngles( );
} }
@ -48,7 +48,7 @@ void T_Camera::cvtAnglesToVectors( ) noexcept
void T_Camera::cvtVectorsToAngles( ) noexcept void T_Camera::cvtVectorsToAngles( ) noexcept
{ {
dir_ = lookAt_ - pos_; dir_ = lookAt_ - pos_;
distance_ = dir_.length( ); distance_ = glm::length( dir_ );
if ( distance_ == 0 ) { if ( distance_ == 0 ) {
angles_ = glm::vec3( 0 ); angles_ = glm::vec3( 0 );
return; return;
@ -71,7 +71,7 @@ void T_Camera::cvtVectorsToAngles( ) noexcept
nAngles.z = atan2f( s1 * nDir.x - c1 * up.x , nAngles.z = atan2f( s1 * nDir.x - c1 * up.x ,
c1 * up.y - s1 * nDir.y ); c1 * up.y - s1 * nDir.y );
angles_ = nAngles * 360.f / float( M_PI ); angles_ = nAngles * 180.f / float( M_PI );
} }
/*------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------*/
@ -121,24 +121,77 @@ void T_Camera::handleWheel(
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
void T_Camera::makeUI( ) noexcept T_Camera::T_Changes T_Camera::makeUI( ) noexcept
{ {
using namespace ImGui; using namespace ImGui;
const bool changed[] = { // What gets changed
DragFloat3( "Target" , &lookAt_.x ) , static const T_Changes changeFlags[] = {
DragFloat( "Distance" , &distance_ , .1f , E_Changes::MATRIX ,
.1f , 1e8 , "%.1f" ) , {} ,
DragFloat3( "Angles" , &angles_.x , .01f , -180 , 180 ) , E_Changes::MATRIX ,
E_Changes::MATRIX ,
DragFloat( "FoV" , &fov_ , .01f , .01f , 179.9f ) {} ,
E_Changes::MATRIX ,
E_Changes::MATRIX ,
{} ,
E_Changes::FOV ,
E_Changes::FOV ,
}; };
// Which update gets called.
enum E_ChangeCall_ {
CC_NONE ,
CC_FROM_VECTORS ,
CC_FROM_ANGLES ,
CC_FROM_FOV ,
CC_FROM_NP ,
};
static const E_ChangeCall_ changeCalls[] = {
CC_FROM_ANGLES ,
CC_NONE ,
CC_FROM_ANGLES ,
CC_FROM_ANGLES ,
CC_NONE ,
CC_FROM_VECTORS ,
CC_FROM_VECTORS ,
CC_NONE ,
CC_FROM_FOV ,
CC_FROM_NP ,
};
static_assert( sizeof( changeFlags ) / sizeof( T_Changes ) == sizeof( changeCalls ) / sizeof( E_ChangeCall_ ) ,
"invalid configuration" );
// Changes (also draws the fields)
const bool changed[] = {
DragFloat3( "Target" , &lookAt_.x ) ,
( Separator( ) , false ) ,
DragFloat( "Distance" , &distance_ , .1f , .1f , 1e8 , "%.1f" ) ,
DragFloat3( "Angles" , &angles_.x , .01f , -180 , 180 ) ,
( Separator( ) , false ) ,
DragFloat3( "Position" , &pos_.x ) ,
DragFloat3( "Up vector" , &up_.x ) ,
( Separator( ) , false ) ,
DragFloat( "FoV" , &fov_ , .01f , .01f , 179.9f ) ,
DragFloat( "Near plane" , &np_ , .00001f , .001f , 1e6f ) ,
};
static_assert( sizeof( changeFlags ) / sizeof( T_Changes ) == sizeof( changed ) / sizeof( bool ) ,
"invalid configuration" );
T_Changes changes;
for ( unsigned i = 0 ; i < sizeof( changed ) / sizeof( bool ) ; i ++ ) { for ( unsigned i = 0 ; i < sizeof( changed ) / sizeof( bool ) ; i ++ ) {
if ( changed[ i ] ) { if ( changed[ i ] ) {
#warning fix this shit switch ( changeCalls[ i ] ) {
// FIXME update( ); case CC_NONE: break;
break; case CC_FROM_VECTORS: cvtVectorsToAngles( ); break;
case CC_FROM_ANGLES: cvtAnglesToVectors( ); break;
case CC_FROM_FOV: cvtFov2Np( ); break;
case CC_FROM_NP: cvtNp2Fov( ); break;
}
changes = changes | changeFlags[ i ];
} }
} }
return changes;
} }

View file

@ -62,10 +62,23 @@ struct T_Camera
void camera( glm::vec3 const& lookAt , void camera( glm::vec3 const& lookAt ,
glm::vec3 const& angles , glm::vec3 const& angles ,
float distance ) noexcept; float distance ) noexcept;
void camera( glm::vec3 const& position , void camera( glm::vec3 const& lookAt ,
glm::vec3 const& target , glm::vec3 const& position ,
glm::vec3 const& up ) noexcept; glm::vec3 const& up ) noexcept;
glm::vec3 const& lookAt( ) const noexcept
{ return lookAt_; }
glm::vec3 const& angles( ) const noexcept
{ return angles_; }
float distance( ) const noexcept
{ return distance_; }
glm::vec3 const& position( ) const noexcept
{ return pos_; }
glm::vec3 const& upVector( ) const noexcept
{ return up_; }
private: private:
glm::vec3 lookAt_ = glm::vec3( 0 ); glm::vec3 lookAt_ = glm::vec3( 0 );
glm::vec3 angles_ = glm::vec3( 0 ); glm::vec3 angles_ = glm::vec3( 0 );
@ -84,7 +97,13 @@ struct T_Camera
// UI & MOUSE CONTROLS // UI & MOUSE CONTROLS
public: public:
void makeUI( ) noexcept; enum class E_Changes {
FOV ,
MATRIX
};
using T_Changes = T_Flags< E_Changes >;
T_Changes makeUI( ) noexcept;
void handleDND( void handleDND(
ImVec2 const& move , ImVec2 const& move ,

View file

@ -1124,5 +1124,72 @@ void T_CamOverride::makeEditWidgets(
uint32_t& counter , uint32_t& counter ,
T_StringBuilder& sb ) noexcept T_StringBuilder& sb ) noexcept
{ {
#warning implement the fuck auto& sinp( Globals::Sync( ).inputs( ) );
// Set field of view / near plane
auto const& fc( *fovConfig_ );
if ( fc.mode == FM_FOV ) {
camera_.fieldOfView( sinp[ inputPos_[ fc.inputIndex ] ] );
} else {
camera_.nearPlane( sinp[ inputPos_[ fc.inputIndex ] ] );
}
// Set camera parameters
const glm::vec3 lookAt{ vectorFromInputs( *target_ ) };
if ( camMode_ == CM_ANGLES ) {
const glm::vec3 angles{ vectorFromInputs( *angles_ ) };
const float distance{ sinp[ inputPos_[ *distance_ ] ] };
camera_.camera( lookAt , angles , distance );
} else {
const glm::vec3 position{ vectorFromInputs( *position_ ) };
const glm::vec3 up{ vectorFromInputs( *upVector_ ) };
camera_.camera( lookAt , position , up );
}
// Draw UI
char const* const name( buildLabel( counter , sb ) );
using namespace ImGui;
PushItemWidth( 0 ); // Compensate for -1
PushID( GetCurrentWindow( )->GetID( name ) );
const auto changes{ camera_.makeUI( ) };
PopID( );
PopItemWidth( );
if ( changes & T_Camera::E_Changes::FOV ) {
if ( fc.mode == FM_FOV ) {
sinp[ inputPos_[ fc.inputIndex ] ] = camera_.fieldOfView( );
} else {
sinp[ inputPos_[ fc.inputIndex ] ] = camera_.nearPlane( );
}
}
if ( changes & T_Camera::E_Changes::MATRIX ) {
inputsFromVector( *target_ , camera_.lookAt( ) );
if ( camMode_ == CM_ANGLES ) {
inputsFromVector( *angles_ , camera_.angles( ) );
sinp[ inputPos_[ *distance_ ] ] = camera_.distance( );
} else {
inputsFromVector( *position_ , camera_.position( ) );
inputsFromVector( *upVector_ , camera_.upVector( ) );
}
}
}
glm::vec3 T_CamOverride::vectorFromInputs(
T_VectorConfig_ const& vc ) noexcept
{
auto& sinp( Globals::Sync( ).inputs( ) );
return glm::vec3{
sinp[ inputPos_[ vc.x ] ] ,
sinp[ inputPos_[ vc.y ] ] ,
sinp[ inputPos_[ vc.z ] ] };
}
void T_CamOverride::inputsFromVector(
T_VectorConfig_ const& vc ,
glm::vec3 const& v ) noexcept
{
auto& sinp( Globals::Sync( ).inputs( ) );
sinp[ inputPos_[ vc.x ] ] = v.x;
sinp[ inputPos_[ vc.y ] ] = v.y;
sinp[ inputPos_[ vc.z ] ] = v.z;
} }

View file

@ -318,6 +318,13 @@ class T_CamOverride : public A_SyncOverride
void makeEditWidgets( void makeEditWidgets(
uint32_t& counter , uint32_t& counter ,
T_StringBuilder& sb ) noexcept override; T_StringBuilder& sb ) noexcept override;
private:
glm::vec3 vectorFromInputs(
T_VectorConfig_ const& inputs ) noexcept;
void inputsFromVector(
T_VectorConfig_ const& inputs ,
glm::vec3 const& vector ) noexcept;
}; };