Fixes rotation bug with GUI

This commit is contained in:
2024-08-04 12:56:53 -04:00
parent b631c20c95
commit 8c14caf9c9
6 changed files with 167 additions and 105 deletions

View File

@@ -207,7 +207,10 @@ namespace fgl::engine::gui
void drawObject( GameObject& game_object )
{
ImGui::InputText( "Name", &( game_object.getName() ) );
static std::string name_input_temp { "" };
name_input_temp = game_object.getName();
ImGui::InputText( "Name", &name_input_temp );
if ( game_object.getName() != name_input_temp ) game_object.setName( name_input_temp );
// Transform - Position
dragFloat3( "Position", game_object.getTransform().translation.vec() );

View File

@@ -18,35 +18,40 @@ namespace fgl::engine::gui
enum Axis
{
Pitch = 0,
Roll = 1,
Yaw = 2
Yaw = 1,
Roll = 2
};
float dat[ 3 ] { rot.pitch(), rot.roll(), rot.yaw() };
const float c_dat[ 3 ] { dat[ Pitch ], dat[ Roll ], dat[ Yaw ] };
glm::vec3 dat { rot.euler() };
const glm::vec3 c_dat { dat };
constexpr float speed { 0.01f };
ImGui::DragFloat3( label, dat, speed );
assert( &dat.x + 1 == &dat.y );
assert( &dat.y + 1 == &dat.z );
const float diff[ 3 ] { c_dat[ Pitch ] - dat[ Pitch ], c_dat[ Roll ] - dat[ Roll ], c_dat[ Yaw ] - dat[ Yaw ] };
ImGui::DragFloat3( label, &dat.x, speed );
const glm::vec3 diff { c_dat - dat };
constexpr float epsilon { std::numeric_limits< float >::epsilon() };
const bool changed[ 3 ] { diff[ Pitch ] > epsilon || diff[ Pitch ]< -epsilon, diff[ Roll ] > epsilon
|| diff[ Roll ]< -epsilon, diff[ Yaw ] > epsilon || diff[ Yaw ] < -epsilon };
const glm::vec< 3, bool > changed_high { glm::greaterThanEqual( diff, glm::vec3( epsilon ) ) };
const glm::vec< 3, bool > changed_low { glm::lessThanEqual( diff, glm::vec3( -epsilon ) ) };
const glm::vec< 3, bool > changed { changed_high || changed_low };
if ( changed[ Pitch ] )
{
rot.pitch() += diff[ Pitch ];
rot.pitch() = dat[ Pitch ];
}
if ( changed[ Roll ] )
{
rot.roll() += diff[ Roll ];
rot.roll() = dat[ Roll ];
}
if ( changed[ Yaw ] )
{
rot.yaw() += diff[ Yaw ];
rot.yaw() = dat[ Yaw ];
}
}

View File

@@ -47,7 +47,7 @@ namespace fgl::engine
std::vector< GameObjectComponentPtr > components {};
std::string name {};
std::string m_name {};
explicit GameObject( GameObjectID obj_id ) : m_id( obj_id ) {}
@@ -137,7 +137,9 @@ namespace fgl::engine
GameObjectID getId() const { return m_id; }
//! Returns the name of the game object. If no name is set then the name of the model is used.
std::string& getName() { return name; }
const std::string& getName() const { return m_name; }
void setName( const std::string& name ) { m_name = name; }
// void drawImGui();
};

View File

@@ -467,7 +467,10 @@ namespace fgl::engine
static_cast< float >( translation[ 1 ] ),
static_cast< float >( translation[ 2 ] ) );
obj.getName() = node.name;
if ( node.name.empty() )
obj.setName( "Unnamed Game Object" );
else
obj.setName( node.name );
this->game_objects.emplace_back( std::move( obj ) );
}

View File

@@ -11,7 +11,6 @@
namespace fgl::engine
{
Rotation::Rotation() : glm::quat( 1.0f, 0.0f, 0.0f, 0.0f )
{}
@@ -50,13 +49,18 @@ namespace fgl::engine
return glm::atan( y, x );
}
inline glm::vec3 eulerAngles( const glm::quat& quat )
{
return { pitch( quat ), roll( quat ), yaw( quat ) };
}
// Because of how glm does stuff. We need to invert the roll.
Rotation::Rotation( const float pitch, const float roll, const float yaw ) :
glm::quat( buildQuat( { pitch, roll, yaw } ) )
{
FGL_ASSERT( ::fgl::engine::pitch( *this ) - pitch < glm::epsilon< float >() );
FGL_ASSERT( ::fgl::engine::yaw( *this ) - yaw < glm::epsilon< float >() );
FGL_ASSERT( ::fgl::engine::roll( *this ) - roll < glm::epsilon< float >() );
FGL_ASSERT( ::fgl::engine::roll( *this ) - roll < glm::epsilon< float >() );
}
RotationModifier< RotationModifierType::Roll > Rotation::roll()
@@ -89,6 +93,127 @@ namespace fgl::engine
return ConstRotationModifier< RotationModifierType::Yaw >( *this );
}
template < RotationModifierType ModifierType, bool is_const >
Rotation& RotationModifier< ModifierType, is_const >::operator+=( const float scalar )
{
if constexpr ( is_const )
{
// We should never be in this function if we are attempting to modify a const rotation
FGL_UNREACHABLE();
}
else
{
const glm::quat modifier { glm::angleAxis( scalar, getModifierAxis< ModifierType >() ) };
switch ( ModifierType )
{
case Pitch:
[[fallthrough]];
case Roll:
rot = static_cast< glm::quat >( rot ) * modifier; // local
break;
case Yaw:
rot = modifier * static_cast< glm::quat >( rot ); // global
break;
default:
FGL_UNREACHABLE();
}
return rot;
}
}
template < RotationModifierType ModifierType, bool is_const >
Rotation& RotationModifier< ModifierType, is_const >::operator-=( const float scalar )
{
if constexpr ( is_const )
{
// We should never be in this function if we are attempting to modify a const rotation
FGL_UNREACHABLE();
}
else
{
const auto modifier { glm::angleAxis( -scalar, getModifierAxis< ModifierType >() ) };
switch ( ModifierType )
{
case Pitch:
[[fallthrough]];
case Roll:
rot = static_cast< glm::quat >( rot ) * modifier; // local
break;
case Yaw:
rot = modifier * static_cast< glm::quat >( rot ); // global
break;
default:
FGL_UNREACHABLE();
}
return rot;
}
}
template < RotationModifierType ModifierType, bool is_const >
Rotation& RotationModifier< ModifierType, is_const >::operator=( const float scalar )
{
if constexpr ( is_const )
{
// We should never be in this function if we are attempting to modify a const rotation
FGL_UNREACHABLE();
}
else
{
glm::vec3 euler { ::fgl::engine::eulerAngles( rot ) };
switch ( ModifierType )
{
default:
FGL_UNREACHABLE();
case Pitch:
euler.x = scalar;
break;
case Roll:
euler.y = scalar;
break;
case Yaw:
euler.z = scalar;
break;
}
rot = { euler };
return rot;
}
}
template < RotationModifierType ModifierType, bool is_const >
FGL_FORCE_INLINE_FLATTEN inline RotationModifier< ModifierType, is_const >::operator float() const
{
return value();
}
template < RotationModifierType ModifierType, bool is_const >
float RotationModifier< ModifierType, is_const >::value() const
{
switch ( ModifierType )
{
default:
FGL_UNREACHABLE();
case Pitch:
return glm::pitch( rot );
case Roll:
return glm::roll( rot );
case Yaw:
return glm::yaw( rot );
}
FGL_UNREACHABLE();
}
glm::vec3 Rotation::euler() const
{
return { pitch(), roll(), yaw() };
}
Rotation& Rotation::operator=( const Rotation& rotation )
{
glm::quat::operator=( rotation );
@@ -135,4 +260,11 @@ namespace fgl::engine
return Rotation( glm::normalize( static_cast< glm::quat >( *this ) * static_cast< glm::quat >( other ) ) );
}
template class RotationModifier< RotationModifierType::Pitch, false >;
template class RotationModifier< RotationModifierType::Roll, false >;
template class RotationModifier< RotationModifierType::Yaw, false >;
template class RotationModifier< RotationModifierType::Pitch, true >;
template class RotationModifier< RotationModifierType::Roll, true >;
template class RotationModifier< RotationModifierType::Yaw, true >;
} // namespace fgl::engine

View File

@@ -70,6 +70,8 @@ namespace fgl::engine
RotationModifier< RotationModifierType::Yaw > yaw();
ConstRotationModifier< RotationModifierType::Yaw > yaw() const;
glm::vec3 euler() const;
Rotation& operator=( const Rotation& rotation );
Rotation& operator=( const glm::quat& rotation );
@@ -129,102 +131,17 @@ namespace fgl::engine
public:
Rotation& operator+=( const float scalar )
{
static_assert( !is_const, "Cannot perform operator-= on a const rotation" );
Rotation& operator+=( const float scalar );
const glm::quat modifier { glm::angleAxis( scalar, getModifierAxis< ModifierType >() ) };
Rotation& operator-=( const float scalar );
switch ( ModifierType )
{
case Pitch:
[[fallthrough]];
case Roll:
rot = static_cast< glm::quat >( rot ) * modifier; // local
break;
case Yaw:
rot = modifier * static_cast< glm::quat >( rot ); // global
break;
default:
FGL_UNREACHABLE();
}
return rot;
}
Rotation& operator-=( const float scalar )
{
static_assert( !is_const, "Cannot perform operator-= on a const rotation" );
const auto modifier { glm::angleAxis( -scalar, getModifierAxis< ModifierType >() ) };
switch ( ModifierType )
{
case Pitch:
[[fallthrough]];
case Roll:
rot = static_cast< glm::quat >( rot ) * modifier; // local
break;
case Yaw:
rot = modifier * static_cast< glm::quat >( rot ); // global
break;
default:
FGL_UNREACHABLE();
}
return rot;
}
Rotation& operator=( const float scalar )
{
glm::vec3 euler { glm::eulerAngles( rot ) };
switch ( ModifierType )
{
default:
FGL_UNREACHABLE();
case Pitch:
euler.x = scalar;
break;
case Roll:
euler.y = scalar;
break;
case Yaw:
euler.z = scalar;
break;
}
return rot;
}
Rotation& operator=( const float scalar );
operator float() const;
float value() const;
};
template < RotationModifierType ModifierType, bool is_const >
FGL_FORCE_INLINE_FLATTEN inline RotationModifier< ModifierType, is_const >::operator float() const
{
return value();
}
template < RotationModifierType ModifierType, bool is_const >
float RotationModifier< ModifierType, is_const >::value() const
{
switch ( ModifierType )
{
default:
FGL_UNREACHABLE();
case Pitch:
return glm::pitch( rot );
case Roll:
return glm::roll( rot );
case Yaw:
return glm::yaw( rot );
}
FGL_UNREACHABLE();
}
namespace constants
{
constexpr glm::vec3 DEFAULT_ROTATION { 0.0f, 0.0f, 0.0f };