Fixes camera movement system

This commit is contained in:
2024-02-14 07:07:18 -05:00
parent 044078b361
commit 5f6f3787ee
11 changed files with 289 additions and 92 deletions

View File

@@ -108,7 +108,7 @@
#set(FGL_WARNINGS "${FGL_WARNINGS_GENERIC} -Wpessimizing-move -Wpedantic -Weffc++ -pedantic-errors -Wnoexcept -Wuninitialized -Wunused -Wunused-parameter -Winit-self -Wconversion -Wuseless-cast -Wextra-semi -Wsuggest-final-types -Wsuggest-final-methods -Wsuggest-override -Wformat-signedness -Wno-format-zero-length -Wmissing-include-dirs -Wshift-overflow=2 -Walloc-zero -Walloca -Wsign-promo -Wconversion -Wduplicated-branches -Wduplicated-cond -Wshadow -Wshadow=local -Wvirtual-inheritance -Wno-virtual-move-assign -Wunsafe-loop-optimizations -Wnormalized -Wpacked -Wredundant-decls -Wctor-dtor-privacy -Wdeprecated-copy-dtor -Wstrict-null-sentinel -Wold-style-cast -Woverloaded-virtual -Wzero-as-null-pointer-constant -Wconditionally-supported -Wwrite-strings -Wunused-const-variable=2 -Wdouble-promotion -Wpointer-arith -Wcast-align=strict -Wcast-qual -Wconversion -Wsign-conversion -Wimplicit-fallthrough=1 -Wmisleading-indentation -Wdangling-else -Wdate-time -Wformat=2 -Wformat-overflow=2 -Wformat-signedness -Wformat-truncation=2 -Wswitch-default -Wstringop-overflow=4 -Warray-bounds=2 -Wattribute-alias=2 -Wcatch-value=2 -Wplacement-new=2 -Wtrampolines -Winvalid-imported-macros -Winvalid-imported-macros")
set(FGL_CONFIG "-std=c++20 -fmax-errors=1 -fconcepts-diagnostics-depth=8 -Werror")
set(FGL_CONFIG "-std=c++23 -fmax-errors=1 -fconcepts-diagnostics-depth=8 -Werror")
# Optimization flags
set(FGL_OPTIMIZATION_FLAGS_RELEASE "-O2 -s -fdevirtualize-at-ltrans -fdevirtualize-speculatively -funroll-loops") # System agonistc flags

View File

@@ -9,6 +9,7 @@
#include <cassert>
#include <limits>
#include <utility>
namespace fgl::engine
{
@@ -29,7 +30,7 @@ namespace fgl::engine
base_frustum = createFrustum( *this, aspect, fovy, near, far );
}
void Camera::setViewDirection( glm::vec3 position, glm::vec3 direction, glm::vec3 up )
void Camera::setViewDirection( glm::vec3 position, const Vector direction, glm::vec3 up )
{
ZoneScoped;
glm::lookAt( position, position + direction, up );
@@ -39,35 +40,126 @@ namespace fgl::engine
void Camera::setViewTarget( glm::vec3 position, glm::vec3 target, glm::vec3 up )
{
setViewDirection( position, glm::normalize( target - position ), up );
setViewDirection( position, Vector( glm::normalize( target - position ) ), up );
}
enum RotationOrder
{
XYZ,
XZY,
XYZ,
YXZ,
YZX,
ZYX,
ZXY,
ZYX
END_OF_ENUM,
DEFAULT = XYZ
};
glm::mat4 taitBryanMatrix( const glm::vec3 rotation, const RotationOrder order = XYZ )
template < int N >
inline std::tuple< float, float > extract( const Vector rotation, const RotationOrder order )
{
switch ( order )
{
case XZY:
switch ( N )
{
case 1:
return { glm::cos( rotation.x ), glm::sin( rotation.x ) };
case 2:
return { glm::cos( rotation.z ), glm::sin( rotation.z ) };
case 3:
return { glm::cos( rotation.y ), glm::sin( rotation.y ) };
}
break;
case XYZ:
switch ( N )
{
case 1:
return { glm::cos( rotation.x ), glm::sin( rotation.x ) };
case 2:
return { glm::cos( rotation.y ), glm::sin( rotation.y ) };
case 3:
return { glm::cos( rotation.z ), glm::sin( rotation.z ) };
}
break;
case YXZ:
switch ( N )
{
case 1:
return { glm::cos( rotation.y ), glm::sin( rotation.y ) };
case 2:
return { glm::cos( rotation.x ), glm::sin( rotation.x ) };
case 3:
return { glm::cos( rotation.z ), glm::sin( rotation.z ) };
}
break;
case YZX:
switch ( N )
{
case 1:
return { glm::cos( rotation.y ), glm::sin( rotation.y ) };
case 2:
return { glm::cos( rotation.z ), glm::sin( rotation.z ) };
case 3:
return { glm::cos( rotation.x ), glm::sin( rotation.x ) };
}
break;
case ZYX:
switch ( N )
{
case 1:
return { glm::cos( rotation.z ), glm::sin( rotation.z ) };
case 2:
return { glm::cos( rotation.y ), glm::sin( rotation.y ) };
case 3:
return { glm::cos( rotation.x ), glm::sin( rotation.x ) };
}
break;
case ZXY:
switch ( N )
{
case 1:
return { glm::cos( rotation.z ), glm::sin( rotation.z ) };
case 2:
return { glm::cos( rotation.x ), glm::sin( rotation.x ) };
case 3:
return { glm::cos( rotation.y ), glm::sin( rotation.y ) };
}
break;
case END_OF_ENUM:
throw std::runtime_error( "Unimplemented rotation order" );
}
std::unreachable();
}
glm::mat4 taitBryanMatrix( const Vector rotation, const RotationOrder order = DEFAULT )
{
glm::mat4 mat { 1.0f };
const float c1 { glm::cos( rotation.x ) };
const float s1 { glm::sin( rotation.x ) };
const float c2 { glm::cos( rotation.y ) };
const float s2 { glm::sin( rotation.y ) };
const float c3 { glm::cos( rotation.z ) };
const float s3 { glm::sin( rotation.z ) };
const auto [ c1, s1 ] = extract< 1 >( rotation, order );
const auto [ c2, s2 ] = extract< 2 >( rotation, order );
const auto [ c3, s3 ] = extract< 3 >( rotation, order );
switch ( order )
{
case RotationOrder::XYZ: // Pitch, Yaw, Roll
case RotationOrder::XZY:
{
const glm::vec3 row_0 { ( c2 * c3 ), -( s2 ), ( c2 * s3 ) };
const glm::vec3 row_1 { ( s1 * s3 ) + ( c1 * c3 * s2 ),
( c1 * c2 ),
( c1 * s2 * s3 ) - ( c3 * s1 ) };
const glm::vec3 row_2 { ( c3 * s1 * s2 ) - ( c1 * s3 ),
( c2 * s1 ),
( c1 * c3 ) + ( s1 * s2 * s3 ) };
mat[ 0 ] = glm::vec4( row_0, 0.0f );
mat[ 1 ] = glm::vec4( row_1, 0.0f );
mat[ 2 ] = glm::vec4( row_2, 0.0f );
return mat;
}
case RotationOrder::XYZ:
{
const glm::vec3 row_0 { ( c2 * c3 ), -( c2 * s3 ), s2 };
const glm::vec3 row_1 { ( c1 * s3 ) + ( c3 * s1 * s2 ),
@@ -82,7 +174,33 @@ namespace fgl::engine
mat[ 2 ] = glm::vec4( row_2, 0.0f );
return mat;
}
case RotationOrder::ZYX: // Yaw, Roll, Pitch
case RotationOrder::YXZ:
{
const glm::vec3 row_0 { ( c1 * c3 ) + ( s1 * s2 * s3 ), ( c3 * s1 * s2 ) - ( c1 * s3 ), c2 * s1 };
const glm::vec3 row_1 { c2 * s3, c2 * c3, -s2 };
const glm::vec3 row_2 { ( c1 * s2 * s3 ) - ( c3 * s1 ), ( c1 * c3 * s2 ) + ( s1 * s3 ), c1 * c2 };
mat[ 0 ] = glm::vec4( row_0, 0.0f );
mat[ 1 ] = glm::vec4( row_1, 0.0f );
mat[ 2 ] = glm::vec4( row_2, 0.0f );
return mat;
}
case RotationOrder::YZX:
{
const glm::vec3 row_0 { ( c1 * c2 ),
( s1 * s3 ) - ( c1 * c3 * s2 ),
( c3 * s1 ) + ( c1 * s2 * s3 ) };
const glm::vec3 row_1 { s2, c2 * c3, -( c2 * s3 ) };
const glm::vec3 row_2 { -( c2 * s1 ),
( c1 * s3 ) + ( c3 * s1 * s2 ),
( c1 * c3 ) - ( s1 * s2 * s3 ) };
mat[ 0 ] = glm::vec4( row_0, 0.0f );
mat[ 1 ] = glm::vec4( row_1, 0.0f );
mat[ 2 ] = glm::vec4( row_2, 0.0f );
return mat;
}
case RotationOrder::ZYX: // Roll, Pitch, Yaw
{
const glm::vec3 row_0 { ( c1 * c2 ),
( c1 * s2 * s3 ) - ( c3 * s1 ),
@@ -97,11 +215,17 @@ namespace fgl::engine
mat[ 2 ] = glm::vec4( row_2, 0.0f );
return mat;
}
case RotationOrder::YXZ: // Roll, Pitch, Yaw
case RotationOrder::ZXY: // Roll, Yaw, Pitch
{
const glm::vec3 row_0 { ( c1 * c3 ) + ( s1 * s2 * s3 ), ( c3 * s1 * s2 ) - ( c1 * s3 ), c2 * s1 };
const glm::vec3 row_1 { c2 * s3, c2 * c3, -s2 };
const glm::vec3 row_2 { ( c1 * s2 * s3 ) - ( c3 * s1 ), ( c1 * c3 * s2 ) + ( s1 * s3 ), c1 * c2 };
const glm::vec3 row_0 { ( c1 * c3 ) - ( s1 * s2 * s3 ),
-( c2 * s1 ),
( c1 * s3 ) + ( c3 * s1 * s2 ) };
const glm::vec3 row_1 { ( c3 * s1 ) + ( c1 * s2 * s3 ),
( c1 * c2 ),
( s1 * s3 ) - ( c1 * c3 * s2 ) };
const glm::vec3 row_2 { -( c2 * s3 ), ( s2 ), ( c2 * c3 ) };
mat[ 0 ] = glm::vec4( row_0, 0.0f );
mat[ 1 ] = glm::vec4( row_1, 0.0f );
@@ -113,15 +237,28 @@ namespace fgl::engine
}
}
void Camera::setViewYXZ( glm::vec3 position, glm::vec3 rotation, const ViewMode mode )
void Camera::setViewYXZ( glm::vec3 position, const Vector rotation, const ViewMode mode )
{
ZoneScoped;
//Flip Z due to the fact we use Z+ outside of this function. It must be Z- inside
position.z = -position.z;
switch ( mode )
{
case ViewMode::TaitBryan:
{
const glm::mat4 rotation_matrix { taitBryanMatrix( rotation ) };
static auto current_rotation_order { RotationOrder::DEFAULT };
ImGui::Begin( "CameraRotation" );
ImGui::SliderInt(
"Rotation Order",
reinterpret_cast< int* >( &current_rotation_order ),
0,
static_cast< int >( RotationOrder::END_OF_ENUM - 1 ) );
ImGui::End();
const glm::mat4 rotation_matrix { taitBryanMatrix( rotation, current_rotation_order ) };
const glm::vec3 forward { rotation_matrix * glm::vec4( constants::WORLD_FORWARD, 0.0f ) };

View File

@@ -79,7 +79,7 @@ namespace fgl::engine
const Vector getDown() const { return -getUp(); }
void setViewDirection( glm::vec3 pos, glm::vec3 direction, glm::vec3 up = constants::WORLD_UP );
void setViewDirection( glm::vec3 pos, const Vector direction, glm::vec3 up = constants::WORLD_UP );
void setViewTarget( glm::vec3 pos, glm::vec3 target, glm::vec3 up = constants::WORLD_UP );
enum ViewMode
@@ -88,7 +88,7 @@ namespace fgl::engine
TaitBryan
};
void setViewYXZ( glm::vec3 pos, glm::vec3 rotation, const ViewMode mode = TaitBryan );
void setViewYXZ( glm::vec3 pos, const Vector rotation, const ViewMode mode = TaitBryan );
};
} // namespace fgl::engine

View File

@@ -105,7 +105,9 @@ namespace fgl::engine
//camera.setOrthographicProjection( -aspect, aspect, -1, 1, -1, 1 );
const float aspect { m_renderer.getAspectRatio() };
camera.setPerspectiveProjection( glm::radians( 50.0f ), aspect, 0.1f, 100.f );
camera.setPerspectiveProjection( glm::radians( 90.0f ), aspect, 0.1f, 100.f );
const auto old_aspect_ratio { m_renderer.getAspectRatio() };
while ( !m_window.shouldClose() )
{
@@ -138,6 +140,11 @@ namespace fgl::engine
}
#endif
if ( old_aspect_ratio != m_renderer.getAspectRatio() )
{
camera.setPerspectiveProjection( glm::radians( 90.0f ), m_renderer.getAspectRatio(), 0.1f, 100.f );
}
camera_controller.moveInPlaneXZ( m_window.window(), delta_time, viewer );
camera.setViewYXZ( viewer.transform.translation, viewer.transform.rotation );
@@ -489,23 +496,6 @@ namespace fgl::engine
*/
Device::getInstance().endSingleTimeCommands( command_buffer );
std::vector< glm::vec3 > lightColors {
{ 1.f, .1f, .1f }, { .1f, .1f, 1.f }, { .1f, 1.f, .1f },
{ 1.f, 1.f, .1f }, { .1f, 1.f, 1.f }, { 1.f, 1.f, 1.f } //
};
for ( std::size_t i = 0; i < lightColors.size(); ++i )
{
auto point_light { GameObject::makePointLight( 0.2f ) };
point_light.color = lightColors[ i ];
auto rotate_light = glm::rotate(
glm::mat4( 1.0f ),
( static_cast< float >( i ) * glm::two_pi< float >() ) / static_cast< float >( lightColors.size() ),
{ 0.0f, -1.0f, 0.0f } );
point_light.transform.translation = glm::vec3( rotate_light * glm::vec4( -1.0f, -1.0f, -1.0f, -1.0f ) );
game_objects.emplace( point_light.getId(), std::move( point_light ) );
}
}
void EngineContext::initImGui()

View File

@@ -52,13 +52,4 @@ namespace fgl::engine
};
}
GameObject GameObject::makePointLight( float intensity, float radius, glm::vec3 color )
{
GameObject game_obj { createGameObject() };
game_obj.color = color;
game_obj.transform.scale.x = radius;
game_obj.point_light = std::make_unique< PointLightComponent >();
game_obj.point_light->light_intensity = intensity;
return game_obj;
}
} // namespace fgl::engine

View File

@@ -10,17 +10,19 @@
#include <unordered_map>
#include "constants.hpp"
#include "engine/primitives/Vector.hpp"
namespace fgl::engine
{
class Model;
//TransformComponent is always in world space
struct TransformComponent
{
glm::vec3 translation { constants::DEFAULT_VEC3 };
WorldCoordinate translation { constants::DEFAULT_VEC3 };
glm::vec3 scale { 1.0f, 1.0f, 1.0f };
glm::vec3 rotation { 0.0f, 0.0f, 0.0f };
Vector rotation { 0.0f, 0.0f, 0.0f };
//TODO: Figure this out and replace TransformComponent with a template of CType instead
glm::mat4 mat4() const;
@@ -28,11 +30,6 @@ namespace fgl::engine
glm::mat3 normalMatrix() const;
};
struct PointLightComponent
{
float light_intensity { 1.0f };
};
class GameObject
{
public:
@@ -46,7 +43,6 @@ namespace fgl::engine
std::shared_ptr< Model > model {};
glm::vec3 color {};
TransformComponent transform {};
std::unique_ptr< PointLightComponent > point_light { nullptr };
private:
@@ -66,9 +62,6 @@ namespace fgl::engine
return { current_id++ };
}
static GameObject
makePointLight( float intensity = 10.0f, float radius = 0.1f, glm::vec3 color = glm::vec3( 1.0f ) );
ID getId() const { return m_id; }
};

View File

@@ -6,6 +6,8 @@
#include <functional>
#include "engine/primitives/Vector.hpp"
namespace fgl::engine
{
@@ -25,12 +27,14 @@ namespace fgl::engine
void KeyboardMovementController::moveInPlaneXZ( GLFWwindow* window, float dt, fgl::engine::GameObject& target )
{
glm::vec3 rotate { 0.0f };
ImGui::Begin( "CameraMovement" );
if ( glfwGetKey( window, key_mappings.look_right ) == GLFW_PRESS ) rotate.y += 1.f;
if ( glfwGetKey( window, key_mappings.look_left ) == GLFW_PRESS ) rotate.y -= 1.f;
if ( glfwGetKey( window, key_mappings.look_up ) == GLFW_PRESS ) rotate.x += 1.f;
if ( glfwGetKey( window, key_mappings.look_down ) == GLFW_PRESS ) rotate.x -= 1.f;
Vector rotate { 0.0f };
if ( glfwGetKey( window, key_mappings.look_right ) == GLFW_PRESS ) rotate.yaw -= 1.f;
if ( glfwGetKey( window, key_mappings.look_left ) == GLFW_PRESS ) rotate.yaw += 1.f;
if ( glfwGetKey( window, key_mappings.look_up ) == GLFW_PRESS ) rotate.pitch += 1.f;
if ( glfwGetKey( window, key_mappings.look_down ) == GLFW_PRESS ) rotate.pitch -= 1.f;
static bool cursor_enabled { true };
static bool cursor_restored { false };
@@ -73,26 +77,26 @@ namespace fgl::engine
const auto xpos { pos.x };
const auto ypos { pos.y };
target.transform.rotation.y +=
target.transform.rotation.yaw +=
static_cast< float >( ( xpos * 0.006 ) * static_cast< double >( look_speed ) );
target.transform.rotation.x -=
target.transform.rotation.pitch -=
static_cast< float >( ( ypos * 0.006 ) * static_cast< double >( look_speed ) );
setCursorPos( window, { 0, 0 } );
}
else
{
if ( glm::dot( rotate, rotate ) > std::numeric_limits< float >::epsilon() )
if ( glm::dot( static_cast< glm::vec3 >( rotate ), static_cast< glm::vec3 >( rotate ) )
> std::numeric_limits< float >::epsilon() )
target.transform.rotation += look_speed * dt * glm::normalize( rotate );
target.transform.rotation.x = glm::clamp( target.transform.rotation.x, -1.5f, 1.5f );
target.transform.rotation.y = glm::mod( target.transform.rotation.y, glm::two_pi< float >() );
target.transform.rotation.pitch = glm::clamp( target.transform.rotation.pitch, -1.5f, 1.5f );
target.transform.rotation.yaw = glm::mod( target.transform.rotation.yaw, glm::two_pi< float >() );
}
const float yaw { target.transform.rotation.y };
const glm::vec3 forward_dir { std::sin( yaw ), 0.0f, std::cos( yaw ) };
const glm::vec3 right_dir { forward_dir.z, 0.0f, -forward_dir.x };
const glm::vec3 up_dir { 0.0f, -0.1f, 0.0f };
const glm::vec3 forward_dir { target.transform.rotation.forward() };
const glm::vec3 right_dir { target.transform.rotation.right() };
const glm::vec3 up_dir { constants::WORLD_UP };
glm::vec3 move_dir { 0.0f };
if ( glfwGetKey( window, key_mappings.move_forward ) == GLFW_PRESS ) move_dir += forward_dir;
@@ -104,6 +108,13 @@ namespace fgl::engine
if ( glm::dot( move_dir, move_dir ) > std::numeric_limits< float >::epsilon() )
target.transform.translation += ( move_speed * dt ) * glm::normalize( move_dir );
ImGui::Text( "Transform" );
ImGui::InputFloat( "X", &target.transform.translation.x, -10.0, 10.0 );
ImGui::InputFloat( "Y", &target.transform.translation.y, -10.0, 10.0 );
ImGui::InputFloat( "Z", &target.transform.translation.z, -10.0, 10.0 );
ImGui::End();
}
} // namespace fgl::engine

View File

@@ -29,6 +29,12 @@ namespace fgl::engine
public:
float& up() { return y; }
float& right() { return x; }
float& forward() { return z; }
Coordinate() : glm::vec3( constants::DEFAULT_VEC3 ) {}
explicit Coordinate( const glm::vec3 position ) : glm::vec3( position ) {}

View File

@@ -37,21 +37,6 @@ namespace fgl::engine
Plane() = default;
/*
Plane operator*( glm::mat4 matrix ) const
{
assert( valid() );
Plane result = *this;
const glm::vec3 new_direction { matrix * glm::vec4( m_direction, 1.0f ) };
const float new_distance { glm::dot( new_direction, m_direction ) + m_distance };
result.m_direction = glm::normalize( new_direction );
result.m_distance = new_distance;
return result;
}*/
//! Returns the closest point on the plane to the 0,0,0 origin
Coordinate< CType > getPosition() const
{

View File

@@ -0,0 +1,61 @@
//
// Created by kj16609 on 2/12/24.
//
#include "Vector.hpp"
namespace fgl::engine
{
Vector::Vector( const Vector& other )
{
x = other.x;
y = other.y;
z = other.z;
}
Vector& Vector::operator=( const Vector& other )
{
x = other.x;
y = other.y;
z = other.z;
return *this;
}
Vector::Vector( Vector&& other )
{
x = other.x;
y = other.y;
z = other.z;
}
Vector& Vector::operator=( const Vector&& other )
{
x = other.x;
y = other.y;
z = other.z;
return *this;
}
Vector& Vector::operator=( const std::initializer_list< float > list )
{
assert( list.size() == 3 );
x = *( list.begin() );
y = *( list.begin() + 1 );
z = *( list.begin() + 2 );
return *this;
}
glm::vec3 Vector::forward() const
{
//TODO: Figure out Z shit
return { std::sin( yaw ), std::cos( yaw ), 0.0f };
}
glm::vec3 Vector::right() const
{
const auto forward_dir { forward() };
return { -forward_dir.y, forward_dir.x, 0.0f };
}
} // namespace fgl::engine

View File

@@ -4,6 +4,8 @@
#pragma once
#include "Coordinate.hpp"
namespace fgl::engine
{
@@ -14,13 +16,34 @@ namespace fgl::engine
{
public:
explicit Vector( const glm::vec3 direction ) : glm::vec3( direction ) {}
float& roll { y };
float& pitch { x };
float& yaw { z };
explicit Vector( const float value ) : glm::vec3( value ) {}
explicit Vector( const glm::vec3 vec ) : glm::vec3( vec ) {}
explicit Vector( const float x, const float y, const float z ) : glm::vec3( x, y, z ) {}
operator glm::vec4() const { return glm::vec4( static_cast< glm::vec3 >( *this ), 0.0f ); }
Vector norm() const { return Vector( glm::normalize( static_cast< glm::vec3 >( *this ) ) ); }
Vector operator*( const float scalar ) const { return Vector( static_cast< glm::vec3 >( *this ) * scalar ); }
glm::vec3 right() const;
glm::vec3 forward() const;
//Copy
Vector( const Vector& other );
Vector& operator=( const Vector& other );
//Move (Should never really move?)
Vector( Vector&& other );
Vector& operator=( const Vector&& other );
Vector& operator=( const std::initializer_list< float > list );
};
inline Vector operator-( const Vector vec )