Mostly fixes rotation shit and other obscure bugs
This commit is contained in:
@@ -104,7 +104,7 @@
|
||||
AppendFlag("-fdiagnostics-show-template-tree") # Shows the template diagnostic info as a tree instead.
|
||||
AppendFlag("-fdiagnostics-path-format=inline-events")
|
||||
|
||||
set(FGL_CONFIG "-std=c++23 -fmax-errors=6 -fconcepts-diagnostics-depth=8 -flto=auto -ftree-vectorize")
|
||||
set(FGL_CONFIG "-std=c++23 -fmax-errors=6 -fconcepts-diagnostics-depth=8 -ftree-vectorize")
|
||||
|
||||
if (DEFINED USE_WERROR)
|
||||
set(FGL_CONFIG "${FGL_CONFIG} -Werror")
|
||||
@@ -128,7 +128,7 @@
|
||||
#set(FGL_FLAGS "${FGL_OPTIMIZATION_FLAGS_${UPPER_BUILD_TYPE}}" PARENT_SCOPE)
|
||||
set(FGL_CHILD_FLAGS "${FGL_OPTIMIZATION_FLAGS_RELEASE}" PARENT_SCOPE) # Child flags for adding optimization to anything we build ourselves but doesn't follow our standard
|
||||
# We use release flags since we really don't need to be using debug flags for anything not ours
|
||||
set(CMAKE_CXX_FLAGS "${FGL_CHILD_FLAGS}")
|
||||
#set(CMAKE_CXX_FLAGS "${FGL_CHILD_FLAGS}")
|
||||
endif ()
|
||||
endfunction()
|
||||
|
||||
|
||||
@@ -14,3 +14,4 @@ target_link_libraries(TitorEditor PRIVATE FGLEngine)
|
||||
target_include_directories(TitorEditor PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||
target_compile_definitions(TitorEditor PUBLIC TITOR_EDITOR)
|
||||
target_compile_features(TitorEditor PRIVATE cxx_std_23)
|
||||
target_link_libraries(TitorEditor PRIVATE glfw ImGui)
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
|
||||
#include "engine/gameobjects/components/ModelComponent.hpp"
|
||||
|
||||
#include "engine/gameobjects/components/drawers.hpp"
|
||||
#include "engine/assets/model/Model.hpp"
|
||||
#include "engine/gameobjects/components/drawers.hpp"
|
||||
#include "gui/safe_include.hpp"
|
||||
|
||||
namespace fgl::engine
|
||||
@@ -16,15 +16,25 @@ namespace fgl::engine
|
||||
{
|
||||
drawComponentTransform( m_transform );
|
||||
|
||||
ImGui::Text( "MODEL COMPONENT WOOOOOO" );
|
||||
//ImGui::Text( "MODEL COMPONENT WOOOOOO" );
|
||||
|
||||
// TODO: If the model is not set then we should be able to set it to one from the file selection
|
||||
if ( this->m_model == nullptr )
|
||||
{
|
||||
ImGui::Text( "Undefined model" );
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& model { *this->m_model };
|
||||
|
||||
ImGui::Text( "%i primitives", model.m_primitives.size() );
|
||||
}
|
||||
|
||||
std::string_view ModelComponent::name() const
|
||||
{
|
||||
if ( m_model )
|
||||
if ( !m_model ) return "Empty";
|
||||
|
||||
return m_model->getName();
|
||||
else
|
||||
return "Empty Model";
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -28,24 +28,26 @@ namespace fgl::engine::gui
|
||||
constexpr double pitch_rate { 1.0 };
|
||||
constexpr double yaw_rate { 1.0 };
|
||||
|
||||
if ( ImGui::IsKeyDown( ImGuiKey_DownArrow ) )
|
||||
{
|
||||
yaw_change.pitch() -= ( delta_time * pitch_rate );
|
||||
}
|
||||
|
||||
if ( ImGui::IsKeyDown( ImGuiKey_UpArrow ) )
|
||||
{
|
||||
yaw_change.pitch() += ( delta_time * pitch_rate );
|
||||
// yaw_change.xAngle() += ( delta_time * pitch_rate );
|
||||
yaw_change.addY( delta_time * pitch_rate );
|
||||
}
|
||||
|
||||
if ( ImGui::IsKeyDown( ImGuiKey_LeftArrow ) )
|
||||
if ( ImGui::IsKeyDown( ImGuiKey_DownArrow ) )
|
||||
{
|
||||
pitch_change.yaw() -= ( delta_time * yaw_rate );
|
||||
// yaw_change.xAngle() -= ( delta_time * pitch_rate );
|
||||
yaw_change.addY( -( delta_time * pitch_rate ) );
|
||||
}
|
||||
|
||||
if ( ImGui::IsKeyDown( ImGuiKey_RightArrow ) )
|
||||
{
|
||||
pitch_change.yaw() += ( delta_time * yaw_rate );
|
||||
pitch_change.addZ( delta_time * yaw_rate );
|
||||
}
|
||||
|
||||
if ( ImGui::IsKeyDown( ImGuiKey_LeftArrow ) )
|
||||
{
|
||||
pitch_change.addZ( -( delta_time * yaw_rate ) );
|
||||
}
|
||||
|
||||
Vector move_dir { 0.0f };
|
||||
|
||||
@@ -44,17 +44,17 @@ namespace fgl::engine::gui
|
||||
|
||||
if ( changed[ Pitch ] )
|
||||
{
|
||||
rot.pitch() = dat[ Pitch ];
|
||||
//TODO: rot.xAngle() = dat[ Pitch ];
|
||||
}
|
||||
|
||||
if ( changed[ Roll ] )
|
||||
{
|
||||
rot.roll() = dat[ Roll ];
|
||||
//TODO: rot.zAngle() = dat[ Roll ];
|
||||
}
|
||||
|
||||
if ( changed[ Yaw ] )
|
||||
{
|
||||
rot.yaw() = dat[ Yaw ];
|
||||
//TODO: rot.yAngle() = dat[ Yaw ];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,10 +33,11 @@ target_compile_definitions(FGLEngine PUBLIC VULKAN_HPP_FLAGS_MASK_TYPE_AS_PUBLIC
|
||||
include(dependencies/spdlog)
|
||||
include(dependencies/imgui)
|
||||
|
||||
target_link_libraries(FGLEngine PUBLIC Vulkan::Vulkan glfw glm ImGui Tracy::TracyClient VMA FGLLoader spdlog shaderc)
|
||||
target_link_libraries(FGLEngine PUBLIC Vulkan::Vulkan glm ImGui FGLLoader spdlog shaderc)
|
||||
target_link_libraries(FGLEngine PUBLIC glfw Tracy::TracyClient VMA)
|
||||
target_include_directories(FGLEngine PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/..)
|
||||
set_target_properties(FGLEngine PROPERTIES COMPILE_FLAGS ${FGL_FLAGS})
|
||||
target_compile_features(FGLEngine PRIVATE cxx_std_23)
|
||||
target_compile_features(FGLEngine PUBLIC cxx_std_23)
|
||||
|
||||
string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_UPPER_BUILD_TYPE)
|
||||
|
||||
@@ -56,7 +57,6 @@ endif ()
|
||||
|
||||
if (DEFINED FGL_ENABLE_TESTS AND FGL_ENABLE_TESTS)
|
||||
target_compile_definitions(FGLEngine PUBLIC FGL_TESTS=1)
|
||||
target_link_libraries(FGLEngine PUBLIC Catch2)
|
||||
else ()
|
||||
target_compile_definitions(FGLEngine PUBLIC FGL_TESTS=0)
|
||||
endif ()
|
||||
@@ -67,7 +67,7 @@ target_compile_definitions(FGLEngine PUBLIC TRACK_BUFFERS)
|
||||
|
||||
#GLM settings
|
||||
# GLM_FORCE_NO_CTOR_INIT
|
||||
target_compile_definitions(FGLEngine PUBLIC GLM_FORCE_RADIANS GLM_FORCE_DEPTH_ZERO_TO_ONE GLM_FORCE_LEFT_HANDED)
|
||||
target_compile_definitions(FGLEngine PUBLIC GLM_FORCE_RADIANS GLM_FORCE_DEPTH_ZERO_TO_ONE)
|
||||
|
||||
if (DEFINED FGL_ENABLE_CALIBRATED_PROFILING AND FGL_ENABLE_CALIBRATED_PROFILING)
|
||||
target_compile_definitions(FGLEngine PUBLIC ENABLE_CALIBRATED_PROFILING=1)
|
||||
|
||||
@@ -42,8 +42,8 @@
|
||||
|
||||
#ifndef NDEBUG
|
||||
#include <stdexcept>
|
||||
#define FGL_ASSERT( test, msg ) \
|
||||
if ( !( test ) ) throw std::runtime_error( msg );
|
||||
#define FGL_ASSERT( test, msg ) assert( ( test ) && "msg" );
|
||||
//if ( !( test ) ) throw std::runtime_error( msg );
|
||||
#else
|
||||
#define FGL_ASSERT( test, msg )
|
||||
#endif
|
||||
|
||||
@@ -78,19 +78,13 @@ namespace fgl::engine
|
||||
|
||||
if ( cursor_enabled )
|
||||
{
|
||||
const auto& original_rotation { target.getTransform().rotation };
|
||||
Rotation yaw_rotation {};
|
||||
Rotation pitch_rotation {};
|
||||
|
||||
if ( pitch_change > std::numeric_limits< float >::epsilon()
|
||||
|| pitch_change < -std::numeric_limits< float >::epsilon() )
|
||||
pitch_rotation.pitch() += dt * pitch_change;
|
||||
target.getTransform().rotation.addX( dt * pitch_change );
|
||||
|
||||
if ( yaw_change > std::numeric_limits< float >::epsilon()
|
||||
|| yaw_change < -std::numeric_limits< float >::epsilon() )
|
||||
yaw_rotation.yaw() += dt * yaw_change;
|
||||
|
||||
target.getTransform().rotation = yaw_rotation * original_rotation * pitch_rotation;
|
||||
target.getTransform().rotation.addY( dt * yaw_change );
|
||||
}
|
||||
else // No cursor
|
||||
{
|
||||
@@ -100,8 +94,8 @@ namespace fgl::engine
|
||||
|
||||
Rotation target_rotation { target.getTransform().rotation };
|
||||
|
||||
target_rotation.yaw() += ( xpos * 0.006f ) * look_speed;
|
||||
target_rotation.pitch() -= ( ypos * 0.006f ) * look_speed;
|
||||
target_rotation.addZ( ( xpos * 0.006f ) * look_speed );
|
||||
target_rotation.addX( ( ypos * 0.006f ) * look_speed );
|
||||
|
||||
target.getTransform().rotation = target_rotation;
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
|
||||
#include "builders/ModelBuilder.hpp"
|
||||
#include "builders/SceneBuilder.hpp"
|
||||
#include "engine/memory/buffers/Buffer.hpp"
|
||||
#include "engine/assets/image/ImageView.hpp"
|
||||
#include "engine/memory/buffers/Buffer.hpp"
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
@@ -21,8 +21,13 @@ namespace fgl::engine
|
||||
std::vector< vk::DrawIndexedIndirectCommand > draw_parameters {};
|
||||
draw_parameters.reserve( primitives.size() );
|
||||
|
||||
//TODO: Perhaps building the parameter list using the model instead of keeping a list already here would be better in order to reduce allocations
|
||||
|
||||
for ( const auto& primitive : primitives )
|
||||
{
|
||||
// Skip drawing this primitive if draw flag is not set
|
||||
if ( !primitive.draw ) continue;
|
||||
|
||||
vk::DrawIndexedIndirectCommand cmd;
|
||||
cmd.indexCount = primitive.m_index_buffer.size();
|
||||
cmd.firstIndex = primitive.m_index_buffer.getOffsetCount();
|
||||
|
||||
@@ -67,6 +67,7 @@ namespace fgl::engine
|
||||
|
||||
struct Primitive
|
||||
{
|
||||
bool draw { true };
|
||||
VertexBufferSuballocation m_vertex_buffer;
|
||||
IndexBufferSuballocation m_index_buffer;
|
||||
OrientedBoundingBox< CoordinateSpace::Model > m_bounding_box;
|
||||
|
||||
@@ -12,12 +12,12 @@
|
||||
#include "objectloaders/tiny_gltf.h"
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#include "engine/assets/image/ImageView.hpp"
|
||||
#include "engine/assets/stores.hpp"
|
||||
#include "engine/camera/Camera.hpp"
|
||||
#include "engine/debug/logging/logging.hpp"
|
||||
#include "engine/descriptors/DescriptorSet.hpp"
|
||||
#include "engine/gameobjects/GameObject.hpp"
|
||||
#include "engine/assets/image/ImageView.hpp"
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
@@ -173,8 +173,9 @@ namespace fgl::engine
|
||||
const auto mat_idx { prim.material };
|
||||
if ( mat_idx == -1 )
|
||||
{
|
||||
//There is no material for this
|
||||
throw std::runtime_error( "No material for primitive. One was expected" );
|
||||
//There is no textures for this material
|
||||
// throw std::runtime_error( "No material for primitive. One was expected" );
|
||||
return {};
|
||||
}
|
||||
|
||||
const tinygltf::Material& materials { root.materials[ mat_idx ] };
|
||||
|
||||
@@ -19,11 +19,11 @@ namespace fgl::engine
|
||||
constexpr glm::vec3 BOTTOM_LEFT { -0.5f, -0.5f, 0.0f };
|
||||
constexpr float dist_mulpt { 2.0f };
|
||||
|
||||
verts.emplace_back( TOP_LEFT * dist_mulpt, glm::vec3( 1.0f ), constants::WORLD_UP, glm::vec2( 0.0f, 0.0f ) );
|
||||
verts.emplace_back( TOP_RIGHT * dist_mulpt, glm::vec3( 1.0f ), constants::WORLD_UP, glm::vec2( 1.0f, 0.0f ) );
|
||||
verts.emplace_back( TOP_LEFT * dist_mulpt, glm::vec3( 1.0f ), constants::WORLD_Z, glm::vec2( 0.0f, 0.0f ) );
|
||||
verts.emplace_back( TOP_RIGHT * dist_mulpt, glm::vec3( 1.0f ), constants::WORLD_Z, glm::vec2( 1.0f, 0.0f ) );
|
||||
verts
|
||||
.emplace_back( BOTTOM_RIGHT * dist_mulpt, glm::vec3( 1.0f ), constants::WORLD_UP, glm::vec2( 1.0f, 1.0f ) );
|
||||
verts.emplace_back( BOTTOM_LEFT * dist_mulpt, glm::vec3( 1.0f ), constants::WORLD_UP, glm::vec2( 0.0f, 1.0f ) );
|
||||
.emplace_back( BOTTOM_RIGHT * dist_mulpt, glm::vec3( 1.0f ), constants::WORLD_Z, glm::vec2( 1.0f, 1.0f ) );
|
||||
verts.emplace_back( BOTTOM_LEFT * dist_mulpt, glm::vec3( 1.0f ), constants::WORLD_Z, glm::vec2( 0.0f, 1.0f ) );
|
||||
|
||||
std::vector< std::uint32_t > indicies { 0, 1, 2, 3 };
|
||||
|
||||
|
||||
@@ -345,16 +345,16 @@ namespace fgl::engine
|
||||
|
||||
FrustumBase createFrustum( const float aspect, const float fov_y, const float near, const float far )
|
||||
{
|
||||
const Plane< CoordinateSpace::Model > near_plane { ModelCoordinate( constants::WORLD_Y * near ),
|
||||
NormalVector( constants::WORLD_Y ) };
|
||||
const Plane< CoordinateSpace::Model > far_plane { ModelCoordinate( constants::WORLD_Y * far ),
|
||||
NormalVector( constants::WORLD_Y_NEG ) };
|
||||
const Plane< CoordinateSpace::Model > near_plane { ModelCoordinate( constants::WORLD_FORWARD * near ),
|
||||
NormalVector( constants::WORLD_FORWARD ) };
|
||||
const Plane< CoordinateSpace::Model > far_plane { ModelCoordinate( constants::WORLD_FORWARD * far ),
|
||||
NormalVector( -constants::WORLD_FORWARD ) };
|
||||
|
||||
const float half_height { far * glm::tan( fov_y / 2.0f ) };
|
||||
const float half_width { half_height * aspect };
|
||||
|
||||
const ModelCoordinate far_forward { constants::WORLD_Y * far };
|
||||
const ModelCoordinate right_half { constants::WORLD_X * half_width };
|
||||
const ModelCoordinate far_forward { constants::WORLD_FORWARD * far };
|
||||
const ModelCoordinate right_half { constants::WORLD_RIGHT * half_width };
|
||||
|
||||
const Vector right_forward { ( far_forward + right_half ).vec() };
|
||||
const Vector left_forward { ( far_forward - right_half ).vec() };
|
||||
@@ -375,12 +375,12 @@ namespace fgl::engine
|
||||
|
||||
const Plane< CoordinateSpace::Model > top_plane {
|
||||
ModelCoordinate( constants::WORLD_CENTER ),
|
||||
NormalVector( glm::cross( top_forward.vec(), constants::WORLD_X ) )
|
||||
NormalVector( glm::cross( top_forward.vec(), constants::WORLD_RIGHT ) )
|
||||
};
|
||||
|
||||
const Plane< CoordinateSpace::Model > bottom_plane {
|
||||
ModelCoordinate( constants::WORLD_CENTER ),
|
||||
NormalVector( glm::cross( bottom_forward.vec(), constants::WORLD_X_NEG ) )
|
||||
NormalVector( glm::cross( bottom_forward.vec(), -constants::WORLD_RIGHT ) )
|
||||
};
|
||||
|
||||
return { near_plane,
|
||||
|
||||
@@ -18,16 +18,16 @@ namespace fgl::engine::constants
|
||||
constexpr glm::vec3 WORLD_CENTER { 0.0f, 0.0f, 0.0f };
|
||||
|
||||
// X RIGHT
|
||||
constexpr glm::vec3 WORLD_RIGHT { 1.0f, 0.0f, 0.0f };
|
||||
constexpr glm::vec3 WORLD_LEFT { -WORLD_RIGHT };
|
||||
constexpr glm::vec3 WORLD_X { 1.0f, 0.0f, 0.0f };
|
||||
constexpr glm::vec3 WORLD_X_NEG { -WORLD_X };
|
||||
|
||||
// Y FORWARD
|
||||
constexpr glm::vec3 WORLD_FORWARD { 0.0f, 1.0f, 0.0f };
|
||||
constexpr glm::vec3 WORLD_BACKWARD { -WORLD_FORWARD };
|
||||
constexpr glm::vec3 WORLD_Y { 0.0f, 1.0f, 0.0f };
|
||||
constexpr glm::vec3 WORLD_Y_NEG { -WORLD_Y };
|
||||
|
||||
// Z UP
|
||||
constexpr glm::vec3 WORLD_UP { 0.0f, 0.0f, 1.0f };
|
||||
constexpr glm::vec3 WORLD_DOWN { -WORLD_UP };
|
||||
constexpr glm::vec3 WORLD_Z { 0.0f, 0.0f, 1.0f };
|
||||
constexpr glm::vec3 WORLD_Z_NEG { -WORLD_Z };
|
||||
|
||||
constexpr float DEFAULT_FLOAT { std::numeric_limits< float >::max() };
|
||||
|
||||
@@ -42,4 +42,8 @@ namespace fgl::engine::constants
|
||||
constexpr glm::mat4 MAT4_IDENTITY { 1.0f };
|
||||
constexpr glm::mat3 MAT3_IDENTITY { 1.0f };
|
||||
|
||||
constexpr glm::vec3 WORLD_FORWARD { WORLD_X };
|
||||
constexpr glm::vec3 WORLD_RIGHT { WORLD_Y };
|
||||
constexpr glm::vec3 WORLD_UP { WORLD_Z };
|
||||
|
||||
} // namespace fgl::engine::constants
|
||||
|
||||
@@ -12,24 +12,39 @@
|
||||
namespace fgl::engine::debug
|
||||
{
|
||||
|
||||
void drawLine( const LineSegment< CoordinateSpace::World >& line )
|
||||
void drawLine( const LineSegment< CoordinateSpace::World >& line, const glm::vec3 color )
|
||||
{
|
||||
drawLine( line.getStart(), line.getEnd() );
|
||||
}
|
||||
|
||||
void drawBoundingBox( const AxisAlignedBoundingBox< CoordinateSpace::World >& bounding_box )
|
||||
void drawBoundingBox( const AxisAlignedBoundingBox< CoordinateSpace::World >& bounding_box, const glm::vec3 color )
|
||||
{
|
||||
for ( const auto& line : bounding_box.lines() )
|
||||
{
|
||||
drawLine( line.getStart(), line.getEnd() );
|
||||
drawLine( line.getStart(), line.getEnd(), color );
|
||||
}
|
||||
}
|
||||
|
||||
void drawBoundingBox( const OrientedBoundingBox< CoordinateSpace::World >& bounding_box )
|
||||
{
|
||||
constexpr glm::vec3 bounding_box_color { 1.0f, 0.0f, 0.0f };
|
||||
|
||||
for ( const auto& line : bounding_box.lines() )
|
||||
{
|
||||
drawLine( line.getStart(), line.getEnd() );
|
||||
drawLine( line.getStart(), line.getEnd(), bounding_box_color );
|
||||
}
|
||||
}
|
||||
|
||||
void drawAxisHelper()
|
||||
{
|
||||
constexpr WorldCoordinate center { constants::WORLD_CENTER };
|
||||
constexpr WorldCoordinate right { constants::WORLD_X };
|
||||
constexpr WorldCoordinate up { constants::WORLD_Z };
|
||||
constexpr WorldCoordinate forward { constants::WORLD_Y };
|
||||
|
||||
drawLine( center, right, constants::WORLD_X );
|
||||
drawLine( center, up, constants::WORLD_Z );
|
||||
drawLine( center, forward, constants::WORLD_Y );
|
||||
}
|
||||
|
||||
} // namespace fgl::engine::debug
|
||||
|
||||
@@ -10,12 +10,14 @@
|
||||
namespace fgl::engine::debug
|
||||
{
|
||||
|
||||
void drawLine( const WorldCoordinate& p1, const WorldCoordinate& p2 );
|
||||
void drawLine( const WorldCoordinate& p1, const WorldCoordinate& p2, glm::vec3 color = { 1.0f, 1.0f, 1.0f } );
|
||||
|
||||
void drawLine( const LineSegment< CoordinateSpace::World >& line );
|
||||
void drawLine( const LineSegment< CoordinateSpace::World >& line, glm::vec3 color = { 1.0f, 1.0f, 1.0f } );
|
||||
|
||||
void drawBoundingBox( const AxisAlignedBoundingBox< CoordinateSpace::World >& bounding_box );
|
||||
void drawBoundingBox( const OrientedBoundingBox< CoordinateSpace::World >& bounding_box );
|
||||
void drawFrustum( const Frustum& frustum );
|
||||
|
||||
void drawAxisHelper();
|
||||
|
||||
} // namespace fgl::engine::debug
|
||||
@@ -38,17 +38,17 @@ namespace fgl::engine
|
||||
|
||||
if ( changed[ Pitch ] )
|
||||
{
|
||||
rot.pitch() = dat[ Pitch ];
|
||||
rot.setX( dat[ Pitch ] );
|
||||
}
|
||||
|
||||
if ( changed[ Roll ] )
|
||||
{
|
||||
rot.roll() = dat[ Roll ];
|
||||
rot.setZ( dat[ Roll ] );
|
||||
}
|
||||
|
||||
if ( changed[ Yaw ] )
|
||||
{
|
||||
rot.yaw() = dat[ Yaw ];
|
||||
rot.setY( dat[ Yaw ] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,12 +18,12 @@ namespace fgl::engine
|
||||
//! Frustum constructed in model space (To be translated to a World space frustum later)
|
||||
struct FrustumBase
|
||||
{
|
||||
ModelPlane near { ModelCoordinate( constants::WORLD_CENTER ), NormalVector( constants::WORLD_FORWARD ) };
|
||||
ModelPlane far { ModelCoordinate( constants::WORLD_CENTER ), NormalVector( constants::WORLD_FORWARD ) };
|
||||
ModelPlane top { ModelCoordinate( constants::WORLD_CENTER ), NormalVector( constants::WORLD_FORWARD ) };
|
||||
ModelPlane bottom { ModelCoordinate( constants::WORLD_CENTER ), NormalVector( constants::WORLD_FORWARD ) };
|
||||
ModelPlane right { ModelCoordinate( constants::WORLD_CENTER ), NormalVector( constants::WORLD_FORWARD ) };
|
||||
ModelPlane left { ModelCoordinate( constants::WORLD_CENTER ), NormalVector( constants::WORLD_FORWARD ) };
|
||||
ModelPlane near { ModelCoordinate( constants::WORLD_CENTER ), NormalVector( constants::WORLD_Y ) };
|
||||
ModelPlane far { ModelCoordinate( constants::WORLD_CENTER ), NormalVector( constants::WORLD_Y ) };
|
||||
ModelPlane top { ModelCoordinate( constants::WORLD_CENTER ), NormalVector( constants::WORLD_Y ) };
|
||||
ModelPlane bottom { ModelCoordinate( constants::WORLD_CENTER ), NormalVector( constants::WORLD_Y ) };
|
||||
ModelPlane right { ModelCoordinate( constants::WORLD_CENTER ), NormalVector( constants::WORLD_Y ) };
|
||||
ModelPlane left { ModelCoordinate( constants::WORLD_CENTER ), NormalVector( constants::WORLD_Y ) };
|
||||
|
||||
ModelCoordinate m_position {};
|
||||
|
||||
@@ -49,12 +49,12 @@ namespace fgl::engine
|
||||
|
||||
struct Frustum
|
||||
{
|
||||
WorldPlane near { WorldCoordinate( constants::WORLD_CENTER ), NormalVector( constants::WORLD_FORWARD ) };
|
||||
WorldPlane far { WorldCoordinate( constants::WORLD_CENTER ), NormalVector( constants::WORLD_FORWARD ) };
|
||||
WorldPlane top { WorldCoordinate( constants::WORLD_CENTER ), NormalVector( constants::WORLD_FORWARD ) };
|
||||
WorldPlane bottom { WorldCoordinate( constants::WORLD_CENTER ), NormalVector( constants::WORLD_FORWARD ) };
|
||||
WorldPlane right { WorldCoordinate( constants::WORLD_CENTER ), NormalVector( constants::WORLD_FORWARD ) };
|
||||
WorldPlane left { WorldCoordinate( constants::WORLD_CENTER ), NormalVector( constants::WORLD_FORWARD ) };
|
||||
WorldPlane near { WorldCoordinate( constants::WORLD_CENTER ), NormalVector( constants::WORLD_Y ) };
|
||||
WorldPlane far { WorldCoordinate( constants::WORLD_CENTER ), NormalVector( constants::WORLD_Y ) };
|
||||
WorldPlane top { WorldCoordinate( constants::WORLD_CENTER ), NormalVector( constants::WORLD_Y ) };
|
||||
WorldPlane bottom { WorldCoordinate( constants::WORLD_CENTER ), NormalVector( constants::WORLD_Y ) };
|
||||
WorldPlane right { WorldCoordinate( constants::WORLD_CENTER ), NormalVector( constants::WORLD_Y ) };
|
||||
WorldPlane left { WorldCoordinate( constants::WORLD_CENTER ), NormalVector( constants::WORLD_Y ) };
|
||||
|
||||
WorldCoordinate m_position {};
|
||||
|
||||
|
||||
@@ -5,237 +5,45 @@
|
||||
#include "Rotation.hpp"
|
||||
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
#include <glm/gtx/euler_angles.hpp>
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
Rotation::Rotation() : Rotation( 0.0f, 0.0f, 0.0f )
|
||||
Rotation::Rotation() : Rotation( 0.0f )
|
||||
{}
|
||||
|
||||
inline glm::quat buildQuat( const glm::vec3 euler )
|
||||
glm::quat toQuat( const float roll, const float pitch, const float yaw )
|
||||
{
|
||||
// euler should be in `pitch, roll, yaw` order
|
||||
const auto pitch { glm::angleAxis( euler.x, constants::WORLD_RIGHT ) };
|
||||
const auto roll { glm::angleAxis( euler.y, constants::WORLD_FORWARD ) };
|
||||
const auto yaw { glm::angleAxis( euler.z, constants::WORLD_UP ) };
|
||||
/*
|
||||
const glm::vec3 euler { x / 2.0f, y / 2.0f, z / 2.0f };
|
||||
const glm::vec3 sin { glm::sin( euler ) };
|
||||
const glm::vec3 cos { glm::cos( euler ) };
|
||||
|
||||
return pitch * roll * yaw;
|
||||
glm::quat q {};
|
||||
q.w = cos.x * cos.y * cos.z + sin.x * sin.y * sin.z;
|
||||
q.x = sin.x * cos.y * cos.z - cos.x * sin.y * sin.z;
|
||||
q.y = cos.x * sin.y * cos.z + sin.x * cos.y * sin.z;
|
||||
q.z = cos.x * cos.y * sin.z - sin.x * sin.y * cos.z;
|
||||
*/
|
||||
|
||||
const glm::quat identity { 1.0f, 0.0f, 0.0f, 0.0f };
|
||||
const glm::quat q_x { glm::rotate( identity, roll, constants::WORLD_X ) }; // Roll
|
||||
const glm::quat q_y { glm::rotate( identity, pitch, constants::WORLD_Y ) }; // Pitch
|
||||
const glm::quat q_z { glm::rotate( identity, yaw, constants::WORLD_Z ) }; // Yaw
|
||||
|
||||
const glm::quat q { q_z * q_y * q_x };
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
inline float pitch( const glm::quat& q )
|
||||
{
|
||||
const float y { 2.0f * ( q.y * q.z + q.w * q.x ) };
|
||||
const float x { q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z };
|
||||
Rotation::Rotation( const float x, const float y, const float z ) : glm::quat( toQuat( x, y, z ) )
|
||||
{}
|
||||
|
||||
if ( glm::all( glm::equal( glm::vec2( x, y ), glm::vec2( 0.0f ), glm::epsilon< float >() ) ) ) return 0.0f;
|
||||
|
||||
return glm::atan( y, x );
|
||||
}
|
||||
|
||||
inline float roll( const glm::quat& q )
|
||||
{
|
||||
return std::asin( glm::clamp( -2.0f * ( q.x * q.z - q.w * q.y ), -1.0f, 1.0f ) );
|
||||
}
|
||||
|
||||
inline float yaw( const glm::quat& q )
|
||||
{
|
||||
const float y { 2.0f * ( q.x * q.y + q.w * q.z ) };
|
||||
const float x { q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z };
|
||||
|
||||
if ( glm::all( glm::equal( glm::vec2( x, y ), glm::vec2( 0.0f ), glm::epsilon< float >() ) ) ) return 0.0f;
|
||||
|
||||
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 >(), "Rotation axis does not match input" );
|
||||
FGL_ASSERT( ::fgl::engine::yaw( *this ) - yaw < glm::epsilon< float >(), "Rotation axis does not match input" );
|
||||
FGL_ASSERT(
|
||||
::fgl::engine::roll( *this ) - roll < glm::epsilon< float >(), "Rotation axis does not match input" );
|
||||
}
|
||||
|
||||
RotationModifier< RotationModifierType::Roll > Rotation::roll()
|
||||
{
|
||||
return RotationModifier< RotationModifierType::Roll >( *this );
|
||||
}
|
||||
|
||||
ConstRotationModifier< RotationModifierType::Pitch > Rotation::pitch() const
|
||||
{
|
||||
return ConstRotationModifier< RotationModifierType::Pitch >( *this );
|
||||
}
|
||||
|
||||
RotationModifier< RotationModifierType::Pitch > Rotation::pitch()
|
||||
{
|
||||
return RotationModifier< RotationModifierType::Pitch >( *this );
|
||||
}
|
||||
|
||||
ConstRotationModifier< RotationModifierType::Roll > Rotation::roll() const
|
||||
{
|
||||
return ConstRotationModifier< RotationModifierType::Roll >( *this );
|
||||
}
|
||||
|
||||
RotationModifier< RotationModifierType::Yaw > Rotation::yaw()
|
||||
{
|
||||
return RotationModifier< RotationModifierType::Yaw >( *this );
|
||||
}
|
||||
|
||||
ConstRotationModifier< RotationModifierType::Yaw > Rotation::yaw() const
|
||||
{
|
||||
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 );
|
||||
return *this;
|
||||
}
|
||||
|
||||
Rotation& Rotation::operator=( const glm::quat& rotation )
|
||||
{
|
||||
glm::quat::operator=( rotation );
|
||||
return *this;
|
||||
}
|
||||
|
||||
Rotation& Rotation::operator+=( const Rotation& rotation )
|
||||
{
|
||||
glm::quat::operator+=( rotation );
|
||||
|
||||
*this = glm::normalize( *this );
|
||||
|
||||
return *this;
|
||||
}
|
||||
Rotation::Rotation( const float value ) : Rotation( value, value, value )
|
||||
{}
|
||||
|
||||
NormalVector Rotation::forward() const
|
||||
{
|
||||
@@ -252,21 +60,62 @@ namespace fgl::engine
|
||||
return mat() * NormalVector( constants::WORLD_UP );
|
||||
}
|
||||
|
||||
RotationMatrix Rotation::mat() const
|
||||
glm::vec3 Rotation::euler() const
|
||||
{
|
||||
return { glm::mat3_cast( *this ) };
|
||||
return { xAngle(), yAngle(), zAngle() };
|
||||
}
|
||||
|
||||
Rotation Rotation::operator*( const Rotation& other ) const
|
||||
float Rotation::xAngle() const
|
||||
{
|
||||
return Rotation( glm::normalize( static_cast< glm::quat >( *this ) * static_cast< glm::quat >( other ) ) );
|
||||
//Extract X angle from quaternion
|
||||
const float sinr_cosp { 2.0f * ( w * x + y * z ) };
|
||||
const float cosr_cosp { 1.0f - 2.0f * ( x * x + y * y ) };
|
||||
return std::atan2( sinr_cosp, cosr_cosp );
|
||||
}
|
||||
|
||||
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 >;
|
||||
float Rotation::yAngle() const
|
||||
{
|
||||
// Extract Y angle from quaternion
|
||||
const float sinp { std::sqrt( 1.0f + 2.0f * ( w * y - x * z ) ) };
|
||||
const float cosp { std::sqrt( 1.0f - 2.0f * ( w * y - x * z ) ) };
|
||||
|
||||
return 2.0f * std::atan2( sinp, cosp ) - std::numbers::pi_v< float > / 2.0f;
|
||||
}
|
||||
|
||||
float Rotation::zAngle() const
|
||||
{
|
||||
// Extract Z angle from quaternion
|
||||
const float siny_cosp { 2.0f * ( w * z + x * y ) };
|
||||
const float cosy_cosp { 1.0f - 2.0f * ( y * y + z * z ) };
|
||||
return std::atan2( siny_cosp, cosy_cosp );
|
||||
}
|
||||
|
||||
void Rotation::setX( const float value )
|
||||
{}
|
||||
|
||||
void Rotation::setY( const float value )
|
||||
{}
|
||||
|
||||
void Rotation::setZ( const float value )
|
||||
{}
|
||||
|
||||
void Rotation::addX( const float value )
|
||||
{
|
||||
const glm::quat q { glm::angleAxis( value, constants::WORLD_X ) };
|
||||
*this = *this * q;
|
||||
}
|
||||
|
||||
void Rotation::addY( const float value )
|
||||
{
|
||||
// Because the camera is flipped. We must also flip the pitch rotation
|
||||
const glm::quat q { glm::angleAxis( value, -constants::WORLD_Y ) };
|
||||
*this = *this * q;
|
||||
}
|
||||
|
||||
void Rotation::addZ( const float value )
|
||||
{
|
||||
const glm::quat q { glm::angleAxis( value, constants::WORLD_Z ) };
|
||||
*this = *this * q;
|
||||
}
|
||||
|
||||
} // namespace fgl::engine
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#include <glm/gtx/euler_angles.hpp>
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
|
||||
#include <numbers>
|
||||
#include <utility>
|
||||
|
||||
@@ -25,128 +28,52 @@ namespace fgl::engine
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
enum class RotationModifierType
|
||||
|
||||
struct Rotation : private glm::quat
|
||||
{
|
||||
Pitch = 0,
|
||||
Roll = 1,
|
||||
Yaw = 2,
|
||||
};
|
||||
|
||||
struct Rotation;
|
||||
|
||||
template < RotationModifierType ModifierType, bool is_const = false >
|
||||
class RotationModifier;
|
||||
|
||||
template < RotationModifierType ModifierType >
|
||||
using ConstRotationModifier = RotationModifier< ModifierType, true >;
|
||||
|
||||
struct Rotation : public glm::quat
|
||||
{
|
||||
template < RotationModifierType ModifierType, bool is_const >
|
||||
friend class RotationModifier;
|
||||
|
||||
Rotation();
|
||||
|
||||
explicit Rotation( float pitch, float roll, float yaw );
|
||||
Rotation( float x, float y, float z );
|
||||
|
||||
Rotation( const Rotation& other ) = default;
|
||||
Rotation( float value );
|
||||
|
||||
explicit Rotation( const glm::quat other ) : glm::quat( glm::normalize( other ) ) {}
|
||||
Rotation( const glm::quat& quat ) : glm::quat( quat ) {}
|
||||
|
||||
explicit Rotation( const float scalar ) : Rotation( scalar, scalar, scalar ) {}
|
||||
|
||||
enum RotationReference
|
||||
{
|
||||
Local,
|
||||
Global
|
||||
};
|
||||
|
||||
RotationModifier< RotationModifierType::Pitch > pitch();
|
||||
ConstRotationModifier< RotationModifierType::Pitch > pitch() const;
|
||||
|
||||
RotationModifier< RotationModifierType::Roll > roll();
|
||||
ConstRotationModifier< RotationModifierType::Roll > roll() const;
|
||||
|
||||
RotationModifier< RotationModifierType::Yaw > yaw();
|
||||
ConstRotationModifier< RotationModifierType::Yaw > yaw() const;
|
||||
|
||||
glm::vec3 euler() const;
|
||||
|
||||
Rotation& operator=( const Rotation& rotation );
|
||||
Rotation& operator=( const glm::quat& rotation );
|
||||
|
||||
Rotation& operator+=( const Rotation& rotation );
|
||||
RotationMatrix mat() const { return { glm::toMat3( *this ) }; }
|
||||
|
||||
NormalVector forward() const;
|
||||
|
||||
NormalVector back() const { return -forward(); }
|
||||
|
||||
NormalVector right() const;
|
||||
|
||||
NormalVector left() const { return -right(); }
|
||||
|
||||
NormalVector up() const;
|
||||
|
||||
NormalVector down() const { return -up(); }
|
||||
glm::vec3 euler() const;
|
||||
float xAngle() const;
|
||||
float yAngle() const;
|
||||
float zAngle() const;
|
||||
|
||||
RotationMatrix mat() const;
|
||||
void setX( float );
|
||||
void setY( float );
|
||||
void setZ( float );
|
||||
|
||||
Rotation operator*( const Rotation& other ) const;
|
||||
void addX( float );
|
||||
void addY( float );
|
||||
void addZ( float );
|
||||
|
||||
bool operator==( const Rotation& other ) const = default;
|
||||
// internal
|
||||
inline glm::quat internal_quat() const { return static_cast< glm::quat >( *this ); }
|
||||
|
||||
bool operator==( const Rotation& rot ) const
|
||||
{
|
||||
return static_cast< glm::quat >( *this ) == static_cast< glm::quat >( rot );
|
||||
}
|
||||
|
||||
friend bool operator==( const Rotation&, const glm::quat& );
|
||||
};
|
||||
|
||||
inline Rotation operator*( const glm::quat quat, const Rotation rotation )
|
||||
inline bool operator==( const Rotation& rot, const glm::quat& quat )
|
||||
{
|
||||
return Rotation( quat * static_cast< glm::quat >( rotation ) );
|
||||
return static_cast< glm::quat >( rot ) == quat;
|
||||
}
|
||||
|
||||
template < RotationModifierType MT >
|
||||
glm::vec3 getModifierAxis()
|
||||
{
|
||||
switch ( MT )
|
||||
{
|
||||
case RotationModifierType::Pitch:
|
||||
return constants::WORLD_RIGHT;
|
||||
case RotationModifierType::Roll:
|
||||
return constants::WORLD_FORWARD;
|
||||
case RotationModifierType::Yaw:
|
||||
return -constants::WORLD_UP;
|
||||
default:
|
||||
FGL_UNREACHABLE();
|
||||
}
|
||||
|
||||
FGL_UNREACHABLE();
|
||||
}
|
||||
|
||||
template < RotationModifierType ModifierType, bool is_const >
|
||||
class RotationModifier
|
||||
{
|
||||
using enum RotationModifierType;
|
||||
|
||||
using RotationType = std::conditional_t< is_const, const Rotation&, Rotation& >;
|
||||
|
||||
RotationType rot;
|
||||
|
||||
friend struct Rotation;
|
||||
|
||||
RotationModifier() = delete;
|
||||
|
||||
explicit RotationModifier( RotationType& i_rot ) : rot( i_rot ) {}
|
||||
|
||||
public:
|
||||
|
||||
Rotation& operator+=( const float scalar );
|
||||
|
||||
Rotation& operator-=( const float scalar );
|
||||
|
||||
Rotation& operator=( const float scalar );
|
||||
|
||||
operator float() const;
|
||||
|
||||
float value() const;
|
||||
};
|
||||
|
||||
namespace constants
|
||||
{
|
||||
constexpr glm::vec3 DEFAULT_ROTATION { 0.0f, 0.0f, 0.0f };
|
||||
|
||||
@@ -12,6 +12,8 @@ namespace fgl::engine
|
||||
{
|
||||
const glm::mat3 rotation_mat { rotation.mat() };
|
||||
|
||||
// We must flip the z axis in order to match vulkan. Where 0,0 is the top left of the screen and Z+ is down
|
||||
|
||||
return glm::mat4 { { scale.x * rotation_mat[ 0 ], 0.0f },
|
||||
{ scale.y * rotation_mat[ 1 ], 0.0f },
|
||||
{ scale.z * rotation_mat[ 2 ], 0.0f },
|
||||
|
||||
@@ -64,7 +64,8 @@ namespace fgl::engine
|
||||
{
|
||||
const auto combined_matrix { matrix * transform.mat() };
|
||||
|
||||
[[maybe_unused]] glm::vec3 scale {}, translation {}, skew {};
|
||||
glm::vec3 scale {}, translation {};
|
||||
[[maybe_unused]] glm::vec3 skew {};
|
||||
glm::quat quat {};
|
||||
[[maybe_unused]] glm::vec4 perspective {};
|
||||
glm::decompose( combined_matrix, scale, quat, translation, skew, perspective );
|
||||
|
||||
@@ -147,6 +147,7 @@ namespace fgl::engine
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
template < CoordinateSpace CType >
|
||||
AxisAlignedBoundingBox< CType >& AxisAlignedBoundingBox< CType >::combine( const OrientedBoundingBox< CType >&
|
||||
other )
|
||||
@@ -160,6 +161,7 @@ namespace fgl::engine
|
||||
return this->combine( aabb );
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
template class AxisAlignedBoundingBox< CoordinateSpace::Model >;
|
||||
template class AxisAlignedBoundingBox< CoordinateSpace::World >;
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace fgl::engine
|
||||
explicit AxisAlignedBoundingBox( const OrientedBoundingBox< CType >& oobb );
|
||||
|
||||
AxisAlignedBoundingBox& combine( const AxisAlignedBoundingBox& other );
|
||||
AxisAlignedBoundingBox& combine( const OrientedBoundingBox< CType >& other );
|
||||
//AxisAlignedBoundingBox& combine( const OrientedBoundingBox< CType >& other );
|
||||
|
||||
bool operator==( const AxisAlignedBoundingBox< CType >& other ) const
|
||||
{
|
||||
@@ -67,11 +67,11 @@ namespace fgl::engine
|
||||
std::array< Coordinate< CType >, POINT_COUNT > points() const;
|
||||
std::array< LineSegment< CType >, LINE_COUNT > lines() const;
|
||||
|
||||
constexpr NormalVector right() const { return NormalVector( constants::WORLD_RIGHT ); }
|
||||
constexpr NormalVector right() const { return NormalVector( constants::WORLD_X ); }
|
||||
|
||||
constexpr NormalVector up() const { return NormalVector( constants::WORLD_UP ); }
|
||||
constexpr NormalVector up() const { return NormalVector( constants::WORLD_Z ); }
|
||||
|
||||
constexpr NormalVector forward() const { return NormalVector( constants::WORLD_FORWARD ); }
|
||||
constexpr NormalVector forward() const { return NormalVector( constants::WORLD_Y ); }
|
||||
};
|
||||
|
||||
} // namespace fgl::engine
|
||||
@@ -28,11 +28,11 @@ namespace fgl::engine
|
||||
|
||||
float span() const { return this->scale().x; }
|
||||
|
||||
constexpr NormalVector right() const { return NormalVector( constants::WORLD_RIGHT ); }
|
||||
constexpr NormalVector right() const { return NormalVector( constants::WORLD_X ); }
|
||||
|
||||
constexpr NormalVector up() const { return NormalVector( constants::WORLD_UP ); }
|
||||
constexpr NormalVector up() const { return NormalVector( constants::WORLD_Z ); }
|
||||
|
||||
constexpr NormalVector forward() const { return NormalVector( constants::WORLD_FORWARD ); }
|
||||
constexpr NormalVector forward() const { return NormalVector( constants::WORLD_Y ); }
|
||||
};
|
||||
|
||||
} // namespace fgl::engine
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "AxisAlignedBoundingBox.hpp"
|
||||
#include "engine/assets/model/ModelVertex.hpp"
|
||||
#include "engine/debug/logging/logging.hpp"
|
||||
#include "engine/primitives/lines/LineSegment.hpp"
|
||||
@@ -196,6 +197,27 @@ namespace fgl::engine
|
||||
return generateBoundingFromPoints< CType >( combined_points );
|
||||
}
|
||||
|
||||
template < CoordinateSpace CType >
|
||||
AxisAlignedBoundingBox< CType > OrientedBoundingBox< CType >::alignToWorld()
|
||||
{
|
||||
const auto points { this->points() };
|
||||
glm::vec3 max { std::numeric_limits< glm::vec3::type >::infinity() };
|
||||
glm::vec3 min { -std::numeric_limits< glm::vec3::type >::infinity() };
|
||||
|
||||
for ( const auto& point : points )
|
||||
{
|
||||
max.x = glm::max( max.x, point.x );
|
||||
max.y = glm::max( max.y, point.y );
|
||||
max.z = glm::max( max.z, point.z );
|
||||
|
||||
min.x = glm::min( min.x, point.x );
|
||||
min.y = glm::min( min.y, point.y );
|
||||
min.z = glm::min( min.z, point.z );
|
||||
}
|
||||
|
||||
return AxisAlignedBoundingBox< CType >( Coordinate< CType >( max ), Coordinate< CType >( min ) );
|
||||
}
|
||||
|
||||
template < CoordinateSpace CType >
|
||||
std::array< LineSegment< CType >, interface::BoundingBox::LINE_COUNT > OrientedBoundingBox< CType >::lines() const
|
||||
{
|
||||
@@ -229,25 +251,38 @@ namespace fgl::engine
|
||||
{
|
||||
ZoneScoped;
|
||||
|
||||
constexpr auto inf_float { std::numeric_limits< float >::infinity() };
|
||||
|
||||
// neg (min)
|
||||
glm::vec3 top_right_forward { points[ 0 ].vec() };
|
||||
glm::vec3 top_right_forward { -inf_float };
|
||||
// pos (max)
|
||||
glm::vec3 bottom_left_back { points[ 0 ].vec() };
|
||||
glm::vec3 bottom_left_back { inf_float };
|
||||
|
||||
assert( points.size() > 0 );
|
||||
|
||||
for ( const auto& pos : points )
|
||||
{
|
||||
top_right_forward.x = std::max( pos.vec().x, top_right_forward.x );
|
||||
top_right_forward.y = std::max( pos.vec().y, top_right_forward.y );
|
||||
top_right_forward.z = std::max( pos.vec().z, top_right_forward.z );
|
||||
const auto vec { pos.vec() };
|
||||
top_right_forward.x = std::max( vec.x, top_right_forward.x );
|
||||
top_right_forward.y = std::max( vec.y, top_right_forward.y );
|
||||
top_right_forward.z = std::max( vec.z, top_right_forward.z );
|
||||
|
||||
bottom_left_back.x = std::min( pos.vec().x, bottom_left_back.x );
|
||||
bottom_left_back.y = std::min( pos.vec().y, bottom_left_back.y );
|
||||
bottom_left_back.z = std::min( pos.vec().z, bottom_left_back.z );
|
||||
bottom_left_back.x = std::min( vec.x, bottom_left_back.x );
|
||||
bottom_left_back.y = std::min( vec.y, bottom_left_back.y );
|
||||
bottom_left_back.z = std::min( vec.z, bottom_left_back.z );
|
||||
}
|
||||
|
||||
assert( top_right_forward.x != -inf_float );
|
||||
assert( top_right_forward.y != -inf_float );
|
||||
assert( top_right_forward.z != -inf_float );
|
||||
|
||||
assert( bottom_left_back.x != inf_float );
|
||||
assert( bottom_left_back.y != inf_float );
|
||||
assert( bottom_left_back.z != inf_float );
|
||||
|
||||
//Calculate midpoint
|
||||
const glm::vec3 midpoint { ( top_right_forward + bottom_left_back ) / glm::vec3( 2.0f ) };
|
||||
const glm::vec3 scale { bottom_left_back - midpoint };
|
||||
const glm::vec3 scale { glm::abs( bottom_left_back - midpoint ) };
|
||||
|
||||
return { Coordinate< CType >( midpoint ), scale };
|
||||
}
|
||||
@@ -256,10 +291,12 @@ namespace fgl::engine
|
||||
{
|
||||
assert( verts.size() > 0 );
|
||||
log::debug( "Generating bounding box for {} verts", verts.size() );
|
||||
|
||||
constexpr auto inf_float { std::numeric_limits< float >::infinity() };
|
||||
// neg (min)
|
||||
glm::vec3 top_right_forward { verts[ 0 ].m_position };
|
||||
glm::vec3 top_right_forward { -inf_float };
|
||||
// pos (max)
|
||||
glm::vec3 bottom_left_back { verts[ 0 ].m_position };
|
||||
glm::vec3 bottom_left_back { inf_float };
|
||||
|
||||
for ( const auto& vert : verts )
|
||||
{
|
||||
@@ -273,9 +310,17 @@ namespace fgl::engine
|
||||
bottom_left_back.z = std::min( pos.z, bottom_left_back.z );
|
||||
}
|
||||
|
||||
assert( top_right_forward.x != -inf_float );
|
||||
assert( top_right_forward.y != -inf_float );
|
||||
assert( top_right_forward.z != -inf_float );
|
||||
|
||||
assert( bottom_left_back.x != inf_float );
|
||||
assert( bottom_left_back.y != inf_float );
|
||||
assert( bottom_left_back.z != inf_float );
|
||||
|
||||
//Calculate midpoint
|
||||
const glm::vec3 midpoint { ( top_right_forward + bottom_left_back ) / glm::vec3( 2.0f ) };
|
||||
const glm::vec3 scale { bottom_left_back - midpoint };
|
||||
const glm::vec3 scale { glm::abs( bottom_left_back - midpoint ) };
|
||||
|
||||
return OrientedBoundingBox< CoordinateSpace::Model >( Coordinate< CoordinateSpace::Model >( midpoint ), scale );
|
||||
}
|
||||
|
||||
@@ -21,6 +21,9 @@ namespace fgl::engine
|
||||
template < CoordinateSpace CType >
|
||||
class LineSegment;
|
||||
|
||||
template < CoordinateSpace CType >
|
||||
class AxisAlignedBoundingBox;
|
||||
|
||||
struct ModelVertex;
|
||||
|
||||
template < CoordinateSpace CType >
|
||||
@@ -71,7 +74,11 @@ namespace fgl::engine
|
||||
|
||||
NormalVector up() const { return m_transform.up(); }
|
||||
|
||||
Coordinate< CType > center() { return m_transform.translation; }
|
||||
|
||||
OrientedBoundingBox combine( const OrientedBoundingBox& other ) const;
|
||||
|
||||
AxisAlignedBoundingBox< CType > alignToWorld();
|
||||
};
|
||||
|
||||
template < CoordinateSpace CType, MatrixType MType >
|
||||
@@ -81,9 +88,9 @@ namespace fgl::engine
|
||||
assert( bounding_box.m_transform.translation.vec() != constants::DEFAULT_VEC3 );
|
||||
assert( bounding_box.m_transform.scale != glm::vec3( 0.0f ) );
|
||||
|
||||
const auto new_transform { matrix * bounding_box.m_transform };
|
||||
const TransformComponent< EvolvedType< MType >() > new_transform { matrix * bounding_box.m_transform };
|
||||
|
||||
return OrientedBoundingBox< EvolvedType< MType >() >( new_transform );
|
||||
return { new_transform };
|
||||
}
|
||||
|
||||
OrientedBoundingBox< CoordinateSpace::Model > generateBoundingFromVerts( const std::vector< ModelVertex >& verts );
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
#include <glm/gtx/matrix_decompose.hpp>
|
||||
#include <glm/mat4x4.hpp>
|
||||
@@ -54,32 +55,31 @@ namespace fgl::engine
|
||||
//Lines
|
||||
template < CoordinateSpace CType, MatrixType MType >
|
||||
requires can_be_evolved< CType, MType >
|
||||
LineSegment< EvolvedType< MType >() > operator*( const Matrix< MType > mat, const LineSegment< CType > );
|
||||
LineSegment< EvolvedType< MType >() > operator*( Matrix< MType > mat, LineSegment< CType > );
|
||||
|
||||
template < CoordinateSpace CType, MatrixType MType >
|
||||
InfiniteLine< EvolvedType< MType >() > operator*( const Matrix< MType > mat, const InfiniteLine< CType > );
|
||||
InfiniteLine< EvolvedType< MType >() > operator*( Matrix< MType > mat, InfiniteLine< CType > );
|
||||
|
||||
//Planes
|
||||
template < CoordinateSpace CType, MatrixType MType >
|
||||
requires can_be_evolved< CType, MType >
|
||||
OriginDistancePlane< EvolvedType< MType >() >
|
||||
operator*( const Matrix< MType > mat, const OriginDistancePlane< CType > );
|
||||
OriginDistancePlane< EvolvedType< MType >() > operator*( Matrix< MType > mat, OriginDistancePlane< CType > );
|
||||
|
||||
template < CoordinateSpace CType, MatrixType MType >
|
||||
requires can_be_evolved< CType, MType >
|
||||
PointPlane< EvolvedType< MType >() > operator*( const Matrix< MType > mat, const PointPlane< CType > );
|
||||
PointPlane< EvolvedType< MType >() > operator*( Matrix< MType > mat, PointPlane< CType > );
|
||||
|
||||
//Coordinates
|
||||
template < CoordinateSpace CType, MatrixType MType >
|
||||
requires can_be_evolved< CType, MType >
|
||||
Coordinate< EvolvedType< MType >() > operator*( const Matrix< MType > mat, const Coordinate< CType > );
|
||||
Coordinate< EvolvedType< MType >() > operator*( Matrix< MType > mat, Coordinate< CType > );
|
||||
|
||||
//Vector
|
||||
template < MatrixType MType >
|
||||
Vector operator*( const Matrix< MType > mat, const Vector vec );
|
||||
Vector operator*( Matrix< MType > mat, Vector vec );
|
||||
|
||||
template < MatrixType MType >
|
||||
NormalVector operator*( const Matrix< MType > mat, const NormalVector );
|
||||
NormalVector operator*( Matrix< MType > mat, NormalVector );
|
||||
|
||||
inline Matrix< MatrixType::WorldToScreen >
|
||||
operator*( const Matrix< MatrixType::CameraToScreen > lhs, const Matrix< MatrixType::WorldToCamera > rhs )
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace fgl::engine
|
||||
template < CoordinateSpace CType >
|
||||
OriginDistancePlane< CType >::OriginDistancePlane() :
|
||||
m_distance( std::numeric_limits< float >::infinity() ),
|
||||
m_direction( constants::WORLD_FORWARD )
|
||||
m_direction( constants::WORLD_Y )
|
||||
{}
|
||||
|
||||
template < CoordinateSpace CType >
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace fgl::engine
|
||||
template < CoordinateSpace CType >
|
||||
PointPlane< CType >::PointPlane() :
|
||||
coordinate( constants::WORLD_CENTER ),
|
||||
vector( NormalVector( constants::WORLD_FORWARD ) )
|
||||
vector( NormalVector( constants::WORLD_Y ) )
|
||||
{}
|
||||
|
||||
template < CoordinateSpace CType >
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace fgl::engine
|
||||
|
||||
constexpr explicit Vector( const float i_x, const float i_y, const float i_z ) : glm::vec3( i_x, i_y, i_z ) {}
|
||||
|
||||
glm::vec3 right( const Vector up = Vector( constants::WORLD_UP ) ) const;
|
||||
glm::vec3 right( const Vector up = Vector( constants::WORLD_Z ) ) const;
|
||||
glm::vec3 forward() const;
|
||||
|
||||
Vector operator*( const float scalar ) const { return Vector( static_cast< glm::vec3 >( *this ) * scalar ); }
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace fgl::engine
|
||||
info.rasterization_info.rasterizerDiscardEnable = VK_FALSE;
|
||||
info.rasterization_info.polygonMode = vk::PolygonMode::eFill;
|
||||
info.rasterization_info.cullMode = vk::CullModeFlagBits::eBack;
|
||||
info.rasterization_info.frontFace = vk::FrontFace::eCounterClockwise;
|
||||
info.rasterization_info.frontFace = vk::FrontFace::eClockwise;
|
||||
info.rasterization_info.depthBiasEnable = VK_FALSE;
|
||||
info.rasterization_info.depthBiasConstantFactor = 0.0f;
|
||||
info.rasterization_info.depthBiasClamp = 0.0f;
|
||||
|
||||
@@ -5,10 +5,11 @@
|
||||
#include "LineDrawer.hpp"
|
||||
|
||||
#include "engine/FrameInfo.hpp"
|
||||
#include "engine/memory/buffers/vector/HostVector.hpp"
|
||||
#include "engine/camera/CameraDescriptor.hpp"
|
||||
#include "engine/assets/model/ModelVertex.hpp"
|
||||
#include "engine/assets/model/SimpleVertex.hpp"
|
||||
#include "engine/camera/CameraDescriptor.hpp"
|
||||
#include "engine/debug/drawers.hpp"
|
||||
#include "engine/memory/buffers/vector/HostVector.hpp"
|
||||
#include "engine/primitives/points/Coordinate.hpp"
|
||||
|
||||
namespace fgl::engine
|
||||
@@ -48,6 +49,8 @@ namespace fgl::engine
|
||||
|
||||
void LineDrawer::pass( FrameInfo& info )
|
||||
{
|
||||
debug::drawAxisHelper();
|
||||
|
||||
ZoneScopedN( "Debug line drawing" );
|
||||
auto& command_buffer { setupSystem( info ) };
|
||||
TracyVkZone( info.tracy_ctx, *command_buffer, "Draw debug lines" );
|
||||
@@ -69,13 +72,15 @@ namespace fgl::engine
|
||||
|
||||
namespace debug
|
||||
{
|
||||
void drawLine( const WorldCoordinate& p1, const WorldCoordinate& p2 )
|
||||
void drawLine( const WorldCoordinate& p1, const WorldCoordinate& p2, const glm::vec3 color )
|
||||
{
|
||||
VertexLine line {};
|
||||
auto& [ p1v, p2v ] = line;
|
||||
|
||||
p1v.m_position = p1.vec();
|
||||
p1v.m_color = color;
|
||||
p2v.m_position = p2.vec();
|
||||
p2v.m_color = color;
|
||||
|
||||
m_lines.emplace_back( std::move( line ) );
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
#version 450
|
||||
|
||||
layout(location = 0) in vec3 in_color;
|
||||
|
||||
#include "include/gbuffer_out.glsl"
|
||||
|
||||
void main() {
|
||||
out_albedo = vec4(1.0, (20.0 / 255.0), (147.0 / 255.0f), 1.0f);
|
||||
out_albedo = vec4(in_color, 1.0f);
|
||||
out_normal = vec4(1.0f);
|
||||
}
|
||||
@@ -1,10 +1,14 @@
|
||||
#version 450
|
||||
|
||||
layout(location = 0) in vec3 in_pos;
|
||||
layout(location = 1) in vec3 in_color;
|
||||
|
||||
#include "include/camera.glsl"
|
||||
|
||||
layout(location = 0) out vec3 out_color;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = ubo.projection * ubo.view * vec4(in_pos, 1.0);
|
||||
out_color = in_color;
|
||||
}
|
||||
|
||||
@@ -12,8 +12,9 @@ if (FGL_ENABLE_TESTS)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED 23)
|
||||
|
||||
add_executable(FGLTests ${FGL_TEST_SOURCES})
|
||||
target_link_libraries(FGLTests PUBLIC FGLEngine Catch2::Catch2WithMain)
|
||||
target_compile_definitions(FGLTests PUBLIC GLM_FORCE_RADIANS GLM_FORCE_DEPTH_ZERO_TO_ONE GLM_FORCE_LEFT_HANDED)
|
||||
target_link_libraries(FGLTests PUBLIC FGLEngine)
|
||||
target_link_libraries(FGLTests PRIVATE Catch2::Catch2WithMain)
|
||||
target_compile_definitions(FGLTests PUBLIC GLM_FORCE_RADIANS GLM_FORCE_DEPTH_ZERO_TO_ONE)
|
||||
target_compile_features(FGLTests PRIVATE cxx_std_23)
|
||||
|
||||
include(CTest)
|
||||
|
||||
@@ -2,43 +2,58 @@
|
||||
// Created by kj16609 on 2/14/24.
|
||||
//
|
||||
|
||||
#include <catch2/catch_all.hpp>
|
||||
|
||||
#include "engine/assets/model/ModelVertex.hpp"
|
||||
#include "engine/primitives/boxes/OrientedBoundingBox.hpp"
|
||||
#include "gtest_printers.hpp"
|
||||
|
||||
using namespace fgl::engine;
|
||||
|
||||
#include <catch2/catch_all.hpp>
|
||||
ModelVertex createTestVert( const float x, const float y, const float z )
|
||||
{
|
||||
ModelVertex vert {};
|
||||
vert.m_position = { x, y, z };
|
||||
|
||||
#include "gtest_printers.hpp"
|
||||
return vert;
|
||||
}
|
||||
|
||||
TEST_CASE( "BoundingBox", "[boundingbox]" )
|
||||
{
|
||||
SECTION( "Combine test" )
|
||||
{
|
||||
std::vector< Coordinate< CoordinateSpace::Model > > model_points {};
|
||||
std::vector< ModelVertex > model_points {};
|
||||
|
||||
// Top left
|
||||
model_points.push_back( Coordinate< CoordinateSpace::Model >( -1.0f, 1.0f, 1.0f ) );
|
||||
// Bottom right
|
||||
model_points.push_back( Coordinate< CoordinateSpace::Model >( 1.0f, -1.0f, -1.0f ) );
|
||||
model_points.push_back( createTestVert( 1.0f, 1.0f, 1.0f ) );
|
||||
|
||||
OrientedBoundingBox< CoordinateSpace::Model > model_box( generateBoundingFromPoints( model_points ) );
|
||||
// Bottom right
|
||||
model_points.push_back( createTestVert( -1.0f, -1.0f, -1.0f ) );
|
||||
|
||||
OrientedBoundingBox< CoordinateSpace::Model > model_box( generateBoundingFromVerts( model_points ) );
|
||||
|
||||
THEN( "The bounding box center must be at 0,0,0" )
|
||||
{
|
||||
REQUIRE( model_box.center().vec() == glm::vec3( 0.0f, 0.0f, 0.0f ) );
|
||||
}
|
||||
|
||||
model_points.clear();
|
||||
|
||||
// Top left
|
||||
model_points.push_back( Coordinate< CoordinateSpace::Model >( -2.0f, 1.0f, 2.0f ) );
|
||||
// Bottom right
|
||||
model_points.push_back( Coordinate< CoordinateSpace::Model >( 2.0f, -1.0f, -2.0f ) );
|
||||
model_points.push_back( createTestVert( 2.0f, 1.0f, 2.0f ) );
|
||||
|
||||
OrientedBoundingBox< CoordinateSpace::Model > model_box2( generateBoundingFromPoints( model_points ) );
|
||||
// Bottom right
|
||||
model_points.push_back( createTestVert( -2.0f, -1.0f, -2.0f ) );
|
||||
|
||||
OrientedBoundingBox< CoordinateSpace::Model > model_box2( generateBoundingFromVerts( model_points ) );
|
||||
|
||||
auto combined_box = model_box.combine( model_box2 );
|
||||
|
||||
//Check that the points are correct
|
||||
//The middle point should not change
|
||||
REQUIRE( combined_box.middle == model_box.middle );
|
||||
REQUIRE( combined_box.center() == model_box.center() );
|
||||
//The scale should be the max of the two boxes
|
||||
REQUIRE( combined_box.scale == glm::vec3( 2.0f, 1.0f, 2.0f ) );
|
||||
REQUIRE( combined_box.m_transform.scale == glm::vec3( 2.0f, 1.0f, 2.0f ) );
|
||||
|
||||
//Check that the points are correct
|
||||
|
||||
175
src/tests/src/RotationTests.cpp
Normal file
175
src/tests/src/RotationTests.cpp
Normal file
@@ -0,0 +1,175 @@
|
||||
//
|
||||
// Created by kj16609 on 9/28/24.
|
||||
//
|
||||
|
||||
#include "catch2/catch_approx.hpp"
|
||||
#include "catch2/catch_test_macros.hpp"
|
||||
#include "catch2/matchers/catch_matchers.hpp"
|
||||
#include "engine/primitives/Rotation.hpp"
|
||||
#include "gtest_printers.hpp"
|
||||
#include "operators/vector.hpp"
|
||||
|
||||
TEST_CASE( "Rotations", "[transform][rotation]" )
|
||||
{
|
||||
using namespace fgl::engine;
|
||||
|
||||
GIVEN( "A Default Rotation" )
|
||||
{
|
||||
Rotation rot {};
|
||||
|
||||
SECTION( "Check quat" )
|
||||
{
|
||||
glm::quat quat { rot.internal_quat() };
|
||||
|
||||
THEN( "Quat: w should be 1.0" )
|
||||
{
|
||||
REQUIRE( quat.w == Catch::Approx( 1.0 ) );
|
||||
}
|
||||
|
||||
auto is_zero { Catch::Approx( 0.0 ) };
|
||||
|
||||
THEN( "Quat: x should be zero" )
|
||||
{
|
||||
REQUIRE( quat.x == is_zero );
|
||||
}
|
||||
THEN( "Quat: y should be zero" )
|
||||
{
|
||||
REQUIRE( quat.y == is_zero );
|
||||
}
|
||||
THEN( "Quat: z should be zero" )
|
||||
{
|
||||
REQUIRE( quat.z == is_zero );
|
||||
}
|
||||
}
|
||||
|
||||
THEN( "Forward should be WORLD_FORWARD" )
|
||||
{
|
||||
REQUIRE( rot.forward() == NormalVector( constants::WORLD_FORWARD ) );
|
||||
}
|
||||
|
||||
THEN( "Right should be WORLD_RIGHT" )
|
||||
{
|
||||
REQUIRE( rot.right() == NormalVector( constants::WORLD_RIGHT ) );
|
||||
}
|
||||
|
||||
THEN( "Up should be WORLD_UP" )
|
||||
{
|
||||
REQUIRE( rot.up() == NormalVector( constants::WORLD_UP ) );
|
||||
}
|
||||
|
||||
THEN( "Euler X should be 0.0" )
|
||||
{
|
||||
REQUIRE( rot.xAngle() == Catch::Approx( 0.0 ) );
|
||||
}
|
||||
|
||||
THEN( "Euler Y should be 0.0" )
|
||||
{
|
||||
REQUIRE( rot.yAngle() == Catch::Approx( 0.0 ) );
|
||||
}
|
||||
|
||||
THEN( "Euler Z should be 0.0" )
|
||||
{
|
||||
REQUIRE( rot.zAngle() == Catch::Approx( 0.0 ) );
|
||||
}
|
||||
}
|
||||
|
||||
GIVEN( "A rotation with euler angles (X, 0.0f, 0.0f)" )
|
||||
{
|
||||
for ( float i = 0; i < 180.0f; i += 1.0f )
|
||||
{
|
||||
Rotation rot { glm::radians( i ), 0.0f, 0.0f };
|
||||
|
||||
INFO( "Euler Value: " << i );
|
||||
|
||||
INFO( "Euler X: " << rot.xAngle() );
|
||||
INFO( "Euler Y: " << rot.yAngle() );
|
||||
INFO( "Euler Z: " << rot.zAngle() );
|
||||
|
||||
INFO(
|
||||
"Quat: (" << rot.internal_quat().w << ", " << rot.internal_quat().x << ", " << rot.internal_quat().y
|
||||
<< ", " << rot.internal_quat().z << ")" );
|
||||
|
||||
THEN( "Euler X should be " << i )
|
||||
{
|
||||
REQUIRE( rot.xAngle() == Catch::Approx( glm::radians( i ) ) );
|
||||
REQUIRE( rot.yAngle() == Catch::Approx( 0.0 ) );
|
||||
REQUIRE( rot.zAngle() == Catch::Approx( 0.0 ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GIVEN( "A rotation with euler angles (0.0f, Y, 0.0f)" )
|
||||
{
|
||||
for ( float i = 0; i < 180.0f; i += 1.0f )
|
||||
{
|
||||
Rotation rot { 0.0f, glm::radians( i ), 0.0f };
|
||||
|
||||
INFO( "Euler Value: " << i );
|
||||
|
||||
INFO( "Euler X: " << rot.xAngle() );
|
||||
INFO( "Euler Y: " << rot.yAngle() );
|
||||
INFO( "Euler Z: " << rot.zAngle() );
|
||||
|
||||
INFO(
|
||||
"Quat: (" << rot.internal_quat().w << ", " << rot.internal_quat().x << ", " << rot.internal_quat().y
|
||||
<< ", " << rot.internal_quat().z << ")" );
|
||||
|
||||
THEN( "Euler Y should be " << i )
|
||||
{
|
||||
REQUIRE( rot.xAngle() == Catch::Approx( 0.0 ).epsilon( 0.1 ) );
|
||||
REQUIRE( rot.yAngle() == Catch::Approx( glm::radians( i ) ).epsilon( 0.01 ) );
|
||||
REQUIRE( rot.zAngle() == Catch::Approx( glm::radians( 0.0 ) ).epsilon( 0.01 ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GIVEN( "A rotation with euler angles (0.0f, 0.0f, Z)" )
|
||||
{
|
||||
for ( float i = 0; i < 180.0f; i += 1.0f )
|
||||
{
|
||||
Rotation rot { 0.0f, 0.0f, glm::radians( i ) };
|
||||
|
||||
INFO( "Euler Value: " << i );
|
||||
|
||||
INFO( "Euler X: " << rot.xAngle() );
|
||||
INFO( "Euler Y: " << rot.yAngle() );
|
||||
INFO( "Euler Z: " << rot.zAngle() );
|
||||
|
||||
INFO(
|
||||
"Quat: (" << rot.internal_quat().w << ", " << rot.internal_quat().x << ", " << rot.internal_quat().y
|
||||
<< ", " << rot.internal_quat().z << ")" );
|
||||
|
||||
THEN( "Euler Z should be " << i )
|
||||
{
|
||||
REQUIRE( rot.xAngle() == Catch::Approx( 0.0 ) );
|
||||
REQUIRE( rot.yAngle() == Catch::Approx( 0.0 ) );
|
||||
REQUIRE( rot.zAngle() == Catch::Approx( glm::radians( i ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GIVEN( "A rotation with euler angles (0.0f, Y, Z)" )
|
||||
{
|
||||
for ( float i = 0; i < 180.0f; i += 1.0f )
|
||||
{
|
||||
Rotation rot { 0.0f, glm::radians( i ), glm::radians( i ) };
|
||||
|
||||
INFO( "Euler Value: " << i );
|
||||
|
||||
INFO( "Euler X: " << rot.xAngle() );
|
||||
INFO( "Euler Y: " << rot.yAngle() );
|
||||
INFO( "Euler Z: " << rot.zAngle() );
|
||||
|
||||
INFO(
|
||||
"Quat: (" << rot.internal_quat().w << ", " << rot.internal_quat().x << ", " << rot.internal_quat().y
|
||||
<< ", " << rot.internal_quat().z << ")" );
|
||||
|
||||
THEN( "Euler Y should be " << i )
|
||||
{
|
||||
REQUIRE( rot.xAngle() == Catch::Approx( 0.0 ).epsilon( 0.1 ) );
|
||||
REQUIRE( rot.yAngle() == Catch::Approx( glm::radians( i ) ).epsilon( 0.01 ) );
|
||||
REQUIRE( rot.zAngle() == Catch::Approx( glm::radians( i ) ).epsilon( 0.01 ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,63 @@ TEST_CASE( "Matrix", "[transform][rotation][translation][matrix]" )
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
TEST_CASE( "Quaternion Rotations", "[rotation]" )
|
||||
{
|
||||
SECTION( "Quaternion build from euler" )
|
||||
{
|
||||
// euler should be in `pitch, roll, yaw` order
|
||||
const auto q_pitch { glm::angleAxis( 0.0f, constants::WORLD_RIGHT ) };
|
||||
const auto q_roll { glm::angleAxis( 0.0f, constants::WORLD_FORWARD ) };
|
||||
const auto q_yaw { glm::angleAxis( 0.0f, constants::WORLD_UP ) };
|
||||
|
||||
REQUIRE( q_pitch == glm::quat( 1.0f, 0.0f, 0.0f, 0.0f ) );
|
||||
REQUIRE( q_pitch * q_roll == glm::quat( 1.0f, 0.0f, 0.0f, 0.0f ) );
|
||||
REQUIRE( q_pitch * q_roll * q_yaw == glm::quat( 1.0f, 0.0f, 0.0f, 0.0f ) );
|
||||
|
||||
const Rotation rot { 0.0f, 0.0f, 0.0f };
|
||||
|
||||
REQUIRE( glm::quat( 1.0f, 0.0f, 0.0f, 0.0f ) == rot );
|
||||
}
|
||||
|
||||
WHEN( "Building a quat with a 90.0f deg pitch" )
|
||||
{
|
||||
const glm::quat quat { fgl::engine::buildQuat( glm::radians( 90.0f ), 0.0f, 0.0f ) };
|
||||
|
||||
THEN( "The output of glm::yaw should be 90.0f deg" )
|
||||
{
|
||||
REQUIRE( glm::pitch( quat ) == Catch::Approx( glm::radians( 90.0f ) ) );
|
||||
REQUIRE( glm::roll( quat ) == 0.0f );
|
||||
REQUIRE( glm::yaw( quat ) == 0.0f );
|
||||
}
|
||||
}
|
||||
|
||||
WHEN( "Building a quat with a 90.0f deg roll" )
|
||||
{
|
||||
const glm::quat quat { fgl::engine::buildQuat( 0.0f, glm::radians( 90.0f ), 0.0f ) };
|
||||
|
||||
THEN( "The output of glm::roll should be 90.0f deg" )
|
||||
{
|
||||
REQUIRE( glm::pitch( quat ) == 0.0f );
|
||||
REQUIRE( glm::roll( quat ) == Catch::Approx( glm::radians( 90.0f ) ) );
|
||||
REQUIRE( glm::yaw( quat ) == 0.0f );
|
||||
}
|
||||
}
|
||||
|
||||
WHEN( "Building a quat with a 90.0f deg yaw" )
|
||||
{
|
||||
const glm::quat quat { fgl::engine::buildQuat( 0.0f, 0.0f, glm::radians( 90.0f ) ) };
|
||||
|
||||
THEN( "The output of glm::pitch should be 90.0f deg" )
|
||||
{
|
||||
REQUIRE( glm::pitch( quat ) == 0.0f );
|
||||
REQUIRE( glm::roll( quat ) == 0.0f );
|
||||
REQUIRE( glm::yaw( quat ) == Catch::Approx( glm::radians( 90.0f ) ).epsilon( 0.01f ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
TEST_CASE( "Transform", "[transform][rotation][translation]" )
|
||||
{
|
||||
TransformComponent component;
|
||||
@@ -45,112 +102,7 @@ TEST_CASE( "Transform", "[transform][rotation][translation]" )
|
||||
component.scale = glm::vec3( 1.0f );
|
||||
component.rotation = Rotation( 0.0f );
|
||||
|
||||
constexpr auto TEST_POINT { constants::WORLD_FORWARD };
|
||||
|
||||
GIVEN( "A default rotation" )
|
||||
{
|
||||
THEN( "The rotation is (0,0,0)" )
|
||||
{
|
||||
REQUIRE( component.rotation.pitch() == 0.0f );
|
||||
REQUIRE( component.rotation.yaw() == 0.0f );
|
||||
REQUIRE( component.rotation.roll() == 0.0f );
|
||||
}
|
||||
|
||||
THEN( "The rotation matrix is the identity matrix" )
|
||||
{
|
||||
REQUIRE( constants::MAT4_IDENTITY == component.mat4() );
|
||||
}
|
||||
|
||||
// Tests behaviour that a point from WORLD_FORWARD should end up WORLD_UP when pitched 90 degrees
|
||||
WHEN( "Rotated +90 Pitch" )
|
||||
{
|
||||
//Rotate by pitch
|
||||
component.rotation.pitch() = glm::radians( 90.0f );
|
||||
|
||||
THEN( "Forward should be WORLD_UP" )
|
||||
{
|
||||
REQUIRE( component.forward() == NormalVector( constants::WORLD_UP ) );
|
||||
}
|
||||
|
||||
THEN( "WORLD_FORWARD should be rotated to WORLD_UP" )
|
||||
{
|
||||
REQUIRE(
|
||||
component.rotation.mat() * NormalVector( constants::WORLD_FORWARD )
|
||||
== NormalVector( constants::WORLD_UP ) );
|
||||
}
|
||||
|
||||
THEN( "Pitch should be 90.0f" )
|
||||
{
|
||||
REQUIRE( component.rotation.pitch() == glm::radians( 90.0f ) );
|
||||
}
|
||||
}
|
||||
|
||||
// Tests behaviour that a point from WORLD_FORWARD should end up WORLD_DOWN when pitched -90 degrees
|
||||
WHEN( "Rotated -90 Pitch" )
|
||||
{
|
||||
component.rotation.pitch() = -glm::radians( 90.0f );
|
||||
|
||||
const glm::vec3 rotated_point { component.mat4() * glm::vec4( TEST_POINT, 1.0f ) };
|
||||
|
||||
THEN( "Forward should be WORLD_DOWN" )
|
||||
{
|
||||
REQUIRE( rotated_point == constants::WORLD_DOWN );
|
||||
}
|
||||
}
|
||||
|
||||
// Tests behaviour that a point from WORLD_FORWARD should end up WORLD_RIGHT when yawed 90 degrees
|
||||
WHEN( "Rotated +90 Yaw" )
|
||||
{
|
||||
component.rotation.yaw() = glm::radians( 90.0f );
|
||||
|
||||
const glm::vec3 rotated_point { component.mat4() * glm::vec4( TEST_POINT, 1.0f ) };
|
||||
|
||||
THEN( "Forward should be WORLD_RIGHT" )
|
||||
{
|
||||
REQUIRE( rotated_point == constants::WORLD_RIGHT );
|
||||
}
|
||||
}
|
||||
|
||||
// Tests behaviour that a point from WORLD_FORWARD should end up WORLD_LEFT when yawed -90 degrees
|
||||
WHEN( "Rotated -90 Yaw" )
|
||||
{
|
||||
component.rotation.yaw() = -glm::radians( 90.0f );
|
||||
|
||||
const glm::vec3 rotated_point { component.mat4() * glm::vec4( TEST_POINT, 1.0f ) };
|
||||
|
||||
THEN( "Forward should be WORLD_LEFT" )
|
||||
{
|
||||
REQUIRE( rotated_point == constants::WORLD_LEFT );
|
||||
}
|
||||
}
|
||||
|
||||
//Tests behaviour that a point from WORLD_RIGHT should end up WORLD_DOWN when rolled 90 degrees
|
||||
//This behaviour assumes that WORLD_RIGHT is 90 deg YAW+ from WORLD_FORWARD
|
||||
WHEN( "Rotated +90 Roll" )
|
||||
{
|
||||
component.rotation.roll() = glm::radians( 90.0f );
|
||||
|
||||
const glm::vec3 rotated_point { component.mat4() * glm::vec4( constants::WORLD_RIGHT, 1.0f ) };
|
||||
|
||||
THEN( "Forward should be WORLD_DOWN" )
|
||||
{
|
||||
REQUIRE( rotated_point == constants::WORLD_DOWN );
|
||||
}
|
||||
}
|
||||
|
||||
//Tests behaviour that a point from WORLD_RIGHT should end up WORLD_UP when rolled -90 degrees
|
||||
WHEN( "Rotated -90 Roll" )
|
||||
{
|
||||
component.rotation.roll() = -glm::radians( 90.0f );
|
||||
|
||||
const glm::vec3 rotated_point { component.mat4() * glm::vec4( constants::WORLD_RIGHT, 1.0f ) };
|
||||
|
||||
THEN( "Forward should be WORLD_UP" )
|
||||
{
|
||||
REQUIRE( rotated_point == constants::WORLD_UP );
|
||||
}
|
||||
}
|
||||
}
|
||||
constexpr auto TEST_POINT { constants::WORLD_Y };
|
||||
|
||||
SECTION( "Translation" )
|
||||
{
|
||||
@@ -162,7 +114,7 @@ TEST_CASE( "Transform", "[transform][rotation][translation]" )
|
||||
|
||||
THEN( "Forward should be WORLD_FORWARD + WORLD_UP" )
|
||||
{
|
||||
REQUIRE( translated_point == constants::WORLD_FORWARD + constants::WORLD_UP );
|
||||
REQUIRE( translated_point == constants::WORLD_Y + constants::WORLD_Z );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,7 +126,7 @@ TEST_CASE( "Transform", "[transform][rotation][translation]" )
|
||||
|
||||
THEN( "Forward should be WORLD_FORWARD + WORLD_FORWARD" )
|
||||
{
|
||||
REQUIRE( translated_point == constants::WORLD_FORWARD + constants::WORLD_FORWARD );
|
||||
REQUIRE( translated_point == constants::WORLD_Y + constants::WORLD_Y );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,29 +138,30 @@ TEST_CASE( "Transform", "[transform][rotation][translation]" )
|
||||
|
||||
THEN( "Forward should be WORLD_FORWARD + WORLD_RIGHT" )
|
||||
{
|
||||
REQUIRE( translated_point == constants::WORLD_FORWARD + constants::WORLD_RIGHT );
|
||||
REQUIRE( translated_point == constants::WORLD_Y + constants::WORLD_X );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
SECTION( "Mix" )
|
||||
{
|
||||
WHEN( "Translated X+1 and Rotated Y+90" )
|
||||
{
|
||||
component.rotation.yaw() = glm::radians( glm::radians( 90.0f ) );
|
||||
component.rotation.yAngle() = glm::radians( glm::radians( 90.0f ) );
|
||||
component.translation.right() += 1.0f;
|
||||
|
||||
const glm::vec3 translated_point { component.mat4() * glm::vec4( constants::WORLD_FORWARD, 1.0f ) };
|
||||
const glm::vec3 translated_point { component.mat4() * glm::vec4( constants::WORLD_Y, 1.0f ) };
|
||||
|
||||
THEN( "WORLD_FORWARD should be transformed into (WORLD_RIGHT * 2)" )
|
||||
{
|
||||
REQUIRE( translated_point == ( constants::WORLD_RIGHT * 2.0f ) );
|
||||
REQUIRE( translated_point == ( constants::WORLD_X * 2.0f ) );
|
||||
}
|
||||
}
|
||||
|
||||
SECTION( "Translated X+1 Yaw-90" )
|
||||
{
|
||||
component.rotation.yaw() = glm::radians( -glm::radians( 90.0f ) );
|
||||
component.rotation.yAngle() = glm::radians( -glm::radians( 90.0f ) );
|
||||
component.translation.right() += 1.0f;
|
||||
|
||||
const glm::vec3 translated_point { component.mat4() * glm::vec4( TEST_POINT, 1.0f ) };
|
||||
@@ -219,4 +172,5 @@ TEST_CASE( "Transform", "[transform][rotation][translation]" )
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
@@ -1,218 +0,0 @@
|
||||
//
|
||||
// Created by kj16609 on 2/16/24.
|
||||
//
|
||||
|
||||
#include <glm/gtc/epsilon.hpp>
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "engine/primitives/TransformComponent.hpp"
|
||||
#include "engine/primitives/vectors/Vector.hpp"
|
||||
#include "gtest_printers.hpp"
|
||||
#include "operators/vector.hpp"
|
||||
|
||||
using namespace fgl::engine;
|
||||
|
||||
TEST_CASE( "Vector", "[vector][transforms]" )
|
||||
{
|
||||
WHEN( "Vector is default constructed" )
|
||||
{
|
||||
constexpr Vector vec {};
|
||||
THEN( "X should be max floatf" )
|
||||
{
|
||||
REQUIRE( vec.x == constants::DEFAULT_FLOAT );
|
||||
}
|
||||
THEN( "Y should be max float" )
|
||||
{
|
||||
REQUIRE( vec.y == constants::DEFAULT_FLOAT );
|
||||
}
|
||||
THEN( "Z should be max float" )
|
||||
{
|
||||
REQUIRE( vec.z == constants::DEFAULT_FLOAT );
|
||||
}
|
||||
}
|
||||
|
||||
WHEN( "Rotated +90 yaw" )
|
||||
{
|
||||
Vector rotation_vec { NormalVector( constants::WORLD_FORWARD ) };
|
||||
|
||||
//Rotate by 90 degrees on yaw
|
||||
TransformComponent transform;
|
||||
transform.rotation.yaw() += glm::radians( 90.0f );
|
||||
|
||||
const Vector value { transform.mat() * rotation_vec };
|
||||
|
||||
THEN( "Forward should be WORLD_RIGHT" )
|
||||
{
|
||||
REQUIRE( value == Vector( constants::WORLD_RIGHT ) );
|
||||
}
|
||||
}
|
||||
|
||||
WHEN( "Rotated -90 yaw" )
|
||||
{
|
||||
Vector rotation_vec { NormalVector( constants::WORLD_FORWARD ) };
|
||||
|
||||
//Rotate by 90 degrees on yaw
|
||||
TransformComponent transform;
|
||||
transform.rotation.yaw() += glm::radians( -90.0f );
|
||||
|
||||
const Vector value { transform.mat() * rotation_vec };
|
||||
|
||||
THEN( "Forward should be WORLD_LEFT" )
|
||||
{
|
||||
REQUIRE( value == Vector( constants::WORLD_LEFT ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "Rotation", "[vector][transforms]" )
|
||||
{
|
||||
WHEN( "Rotation is default constructed" )
|
||||
{
|
||||
Rotation rot {};
|
||||
|
||||
THEN( "Should match a default quaternion" )
|
||||
{
|
||||
REQUIRE( static_cast< glm::quat >( rot ) == glm::quat( 1.0f, 0.0f, 0.0f, 0.0f ) );
|
||||
}
|
||||
|
||||
THEN( "Yaw should be 0.0f" )
|
||||
{
|
||||
REQUIRE( rot.yaw() == 0.0f );
|
||||
}
|
||||
THEN( "Pitch should be 0.0f" )
|
||||
{
|
||||
REQUIRE( rot.pitch() == 0.0f );
|
||||
}
|
||||
THEN( "Roll should be 0.0f" )
|
||||
{
|
||||
REQUIRE( rot.roll() == 0.0f );
|
||||
}
|
||||
|
||||
THEN( "Forward should be WORLD_FORWARD" )
|
||||
{
|
||||
REQUIRE( rot.forward() == NormalVector( constants::WORLD_FORWARD ) );
|
||||
}
|
||||
|
||||
THEN( "Backwards should be WORLD_BACKWARD" )
|
||||
{
|
||||
REQUIRE( -rot.forward() == NormalVector( constants::WORLD_BACKWARD ) );
|
||||
}
|
||||
|
||||
THEN( "Right should be WORLD_RIGHT" )
|
||||
{
|
||||
REQUIRE( rot.right() == NormalVector( constants::WORLD_RIGHT ) );
|
||||
}
|
||||
|
||||
THEN( "Left should be WORLD_LEFT" )
|
||||
{
|
||||
REQUIRE( -rot.right() == NormalVector( constants::WORLD_LEFT ) );
|
||||
}
|
||||
}
|
||||
|
||||
GIVEN( "A rotation constructed" )
|
||||
{
|
||||
constexpr auto rad_90 { glm::radians( 90.0f ) };
|
||||
|
||||
AND_WHEN( "Given 90.0f pitch" )
|
||||
{
|
||||
Rotation rotation { rad_90, 0.0f, 0.0f };
|
||||
|
||||
THEN( "Pitch should return 90" )
|
||||
{
|
||||
REQUIRE( rotation.pitch() == Catch::Approx( rad_90 ).epsilon( 0.01 ) );
|
||||
}
|
||||
|
||||
/*
|
||||
THEN( "Quaternion should be valid" )
|
||||
{
|
||||
REQUIRE( static_cast< glm::quat >( rotation ) == glm::quat( 0.7071068, 0.7071068, 0, 0 ) );
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
AND_WHEN( "Given 90.0f yaw" )
|
||||
{
|
||||
Rotation rotation { 0.0f, rad_90, 0.0f };
|
||||
|
||||
REQUIRE( rotation.yaw() == Catch::Approx( rad_90 ).epsilon( 0.01 ) );
|
||||
}
|
||||
|
||||
AND_WHEN( "Given 90.0f roll" )
|
||||
{
|
||||
Rotation rotation { 0.0f, 0.0f, rad_90 };
|
||||
|
||||
REQUIRE( rotation.roll() == Catch::Approx( rad_90 ).epsilon( 0.01 ) );
|
||||
}
|
||||
}
|
||||
|
||||
GIVEN( "A default identity matrix" )
|
||||
{
|
||||
const Matrix< MatrixType::ModelToWorld > matrix { 1.0f };
|
||||
|
||||
THEN( "The matrix rot() function should match a default rotation" )
|
||||
{
|
||||
const Rotation default_rot {};
|
||||
REQUIRE( default_rot.mat() == matrix.rotmat() );
|
||||
}
|
||||
|
||||
WHEN( "Multiplied with a default rotation" )
|
||||
{
|
||||
THEN( "Nothing should happen" )
|
||||
{}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION( "Rotation transforms" )
|
||||
{
|
||||
WHEN( "Rotated +90 yaw from default" )
|
||||
{
|
||||
Rotation rot { 0.0f, 0.0f, glm::radians( 90.0f ) };
|
||||
|
||||
THEN( "Forward should be WORLD_RIGHT" )
|
||||
{
|
||||
REQUIRE( rot.forward() == NormalVector( constants::WORLD_RIGHT ) );
|
||||
}
|
||||
|
||||
THEN( "Backwards should be WORLD_LEFT" )
|
||||
{
|
||||
REQUIRE( rot.back() == NormalVector( constants::WORLD_LEFT ) );
|
||||
}
|
||||
|
||||
THEN( "Right should be WORLD_BACKWARD" )
|
||||
{
|
||||
REQUIRE( rot.right() == NormalVector( constants::WORLD_BACKWARD ) );
|
||||
}
|
||||
|
||||
THEN( "Left should be WORLD_FORWARD" )
|
||||
{
|
||||
REQUIRE( rot.left() == NormalVector( constants::WORLD_FORWARD ) );
|
||||
}
|
||||
}
|
||||
|
||||
WHEN( "Rotated -90 yaw from default" )
|
||||
{
|
||||
Rotation rot { 0.0f, 0.0f, glm::radians( -90.0f ) };
|
||||
|
||||
THEN( "Forward should be WORLD_LEFT" )
|
||||
{
|
||||
REQUIRE( rot.forward() == NormalVector( constants::WORLD_LEFT ) );
|
||||
}
|
||||
|
||||
THEN( "Backwards should be WORLD_RIGHT" )
|
||||
{
|
||||
REQUIRE( rot.back() == NormalVector( constants::WORLD_RIGHT ) );
|
||||
}
|
||||
|
||||
THEN( "Right should be WORLD_FORWARD" )
|
||||
{
|
||||
REQUIRE( rot.right() == NormalVector( constants::WORLD_FORWARD ) );
|
||||
}
|
||||
|
||||
THEN( "Left should be WORLD_BACKWARD" )
|
||||
{
|
||||
REQUIRE( rot.left() == NormalVector( constants::WORLD_BACKWARD ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,9 @@
|
||||
#include <glm/gtx/string_cast.hpp>
|
||||
|
||||
#include "engine/primitives/Rotation.hpp"
|
||||
#include "engine/primitives/Scale.hpp"
|
||||
#include "engine/primitives/matricies/Matrix.hpp"
|
||||
#include "engine/primitives/points/Coordinate.hpp"
|
||||
#include "engine/primitives/vectors/Vector.hpp"
|
||||
|
||||
namespace Catch
|
||||
@@ -35,7 +37,7 @@ namespace Catch
|
||||
{
|
||||
static std::string convert( const fgl::engine::Rotation& rot )
|
||||
{
|
||||
return StringMaker< glm::vec3 >::convert( { rot.pitch(), rot.roll(), rot.yaw() } );
|
||||
return StringMaker< glm::vec3 >::convert( { rot.xAngle(), rot.yAngle(), rot.zAngle() } );
|
||||
}
|
||||
};
|
||||
|
||||
@@ -68,7 +70,7 @@ namespace Catch
|
||||
};
|
||||
|
||||
template <>
|
||||
struct StringMaker< fgl::engine::NormalVector >
|
||||
struct StringMaker< ::fgl::engine::NormalVector >
|
||||
{
|
||||
static std::string convert( const fgl::engine::NormalVector vec )
|
||||
{
|
||||
@@ -76,6 +78,24 @@ namespace Catch
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct StringMaker< ::fgl::engine::Scale >
|
||||
{
|
||||
static std::string convert( const fgl::engine::Scale scale )
|
||||
{
|
||||
return StringMaker< glm::vec3 >::convert( static_cast< glm::vec3 >( scale ) );
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct StringMaker< ::fgl::engine::ModelCoordinate >
|
||||
{
|
||||
static std::string convert( const fgl::engine::ModelCoordinate coord )
|
||||
{
|
||||
return StringMaker< glm::vec3 >::convert( coord.vec() );
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Catch
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
||||
Reference in New Issue
Block a user