From 8c14caf9c91684517c6ee1c8d6c792e6a9bd8383 Mon Sep 17 00:00:00 2001 From: kj16609 Date: Sun, 4 Aug 2024 12:56:53 -0400 Subject: [PATCH] Fixes rotation bug with GUI --- src/editor/src/gui/core.cpp | 5 +- src/editor/src/gui/helpers.hpp | 27 ++-- src/engine/gameobjects/GameObject.hpp | 6 +- src/engine/model/builders/SceneBuilder.cpp | 5 +- src/engine/primitives/Rotation.cpp | 136 ++++++++++++++++++++- src/engine/primitives/Rotation.hpp | 93 +------------- 6 files changed, 167 insertions(+), 105 deletions(-) diff --git a/src/editor/src/gui/core.cpp b/src/editor/src/gui/core.cpp index fcbcae9..7ab29b6 100644 --- a/src/editor/src/gui/core.cpp +++ b/src/editor/src/gui/core.cpp @@ -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() ); diff --git a/src/editor/src/gui/helpers.hpp b/src/editor/src/gui/helpers.hpp index 53c4c7a..846a771 100644 --- a/src/editor/src/gui/helpers.hpp +++ b/src/editor/src/gui/helpers.hpp @@ -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 ]; } } diff --git a/src/engine/gameobjects/GameObject.hpp b/src/engine/gameobjects/GameObject.hpp index 16e08ff..19c37f0 100644 --- a/src/engine/gameobjects/GameObject.hpp +++ b/src/engine/gameobjects/GameObject.hpp @@ -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(); }; diff --git a/src/engine/model/builders/SceneBuilder.cpp b/src/engine/model/builders/SceneBuilder.cpp index fdd3126..2cc1825 100644 --- a/src/engine/model/builders/SceneBuilder.cpp +++ b/src/engine/model/builders/SceneBuilder.cpp @@ -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 ) ); } diff --git a/src/engine/primitives/Rotation.cpp b/src/engine/primitives/Rotation.cpp index 072e8eb..f2ef485 100644 --- a/src/engine/primitives/Rotation.cpp +++ b/src/engine/primitives/Rotation.cpp @@ -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 diff --git a/src/engine/primitives/Rotation.hpp b/src/engine/primitives/Rotation.hpp index 66c0009..1336af5 100644 --- a/src/engine/primitives/Rotation.hpp +++ b/src/engine/primitives/Rotation.hpp @@ -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 };