Get debugging information mostly working
This commit is contained in:
@@ -12,6 +12,7 @@ namespace fgl::engine
|
||||
|
||||
void Camera::setOrthographicProjection( float left, float right, float top, float bottom, float near, float far )
|
||||
{
|
||||
ZoneScoped;
|
||||
projection_matrix = glm::mat4 { 1.0f };
|
||||
projection_matrix[ 0 ][ 0 ] = 2.0f / ( right - left );
|
||||
projection_matrix[ 1 ][ 1 ] = 2.0f / ( bottom - top );
|
||||
@@ -19,10 +20,13 @@ namespace fgl::engine
|
||||
projection_matrix[ 3 ][ 0 ] = -( right + left ) / ( right - left );
|
||||
projection_matrix[ 3 ][ 1 ] = -( bottom + top ) / ( bottom - top );
|
||||
projection_matrix[ 3 ][ 2 ] = -near / ( far - near );
|
||||
|
||||
//TODO: Figure out frustum culling for orthographic projection. (If we even wanna use it)
|
||||
}
|
||||
|
||||
void Camera::setPerspectiveProjection( float fovy, float aspect, float near, float far )
|
||||
{
|
||||
ZoneScoped;
|
||||
assert( glm::abs( aspect - std::numeric_limits< float >::epsilon() ) > 0 );
|
||||
const float tan_half_fovy { std::tan( fovy / 2.0f ) };
|
||||
projection_matrix = glm::mat4 { 0.0f };
|
||||
@@ -31,50 +35,57 @@ namespace fgl::engine
|
||||
projection_matrix[ 2 ][ 2 ] = far / ( far - near );
|
||||
projection_matrix[ 2 ][ 3 ] = 1.0f;
|
||||
projection_matrix[ 3 ][ 2 ] = -( far * near ) / ( far - near );
|
||||
|
||||
base_frustum = createFrustum( *this, aspect, fovy, near, far );
|
||||
}
|
||||
|
||||
void Camera::setViewDirection( glm::vec3 position, glm::vec3 direction, glm::vec3 up )
|
||||
{
|
||||
const glm::vec3 w { glm::normalize( direction ) };
|
||||
const glm::vec3 u { glm::normalize( glm::cross( w, up ) ) };
|
||||
const glm::vec3 v { glm::cross( w, u ) };
|
||||
ZoneScoped;
|
||||
const glm::vec3 w_direction { glm::normalize( direction ) };
|
||||
const glm::vec3 u_right { glm::normalize( glm::cross( w_direction, up ) ) };
|
||||
const glm::vec3 v_up { glm::cross( w_direction, u_right ) };
|
||||
|
||||
/*
|
||||
* view_matrix
|
||||
* u_r = view_right
|
||||
* v_u = view_up
|
||||
* w_d = view_direction
|
||||
*
|
||||
* | u_r.x u_r.y u_r.z 0 |
|
||||
* | v_u.x v_u.y v_u.z 0 |
|
||||
* | w_d.x w_d.y w_d.z 0 |
|
||||
* | 0 0 0 1 |
|
||||
*/
|
||||
|
||||
view_matrix = glm::mat4 { 1.0f };
|
||||
view_matrix[ 0 ][ 0 ] = u.x;
|
||||
view_matrix[ 1 ][ 0 ] = u.y;
|
||||
view_matrix[ 2 ][ 0 ] = u.z;
|
||||
view_matrix[ 0 ][ 1 ] = v.x;
|
||||
view_matrix[ 1 ][ 1 ] = v.y;
|
||||
view_matrix[ 2 ][ 1 ] = v.z;
|
||||
view_matrix[ 0 ][ 2 ] = w.x;
|
||||
view_matrix[ 1 ][ 2 ] = w.y;
|
||||
view_matrix[ 2 ][ 2 ] = w.z;
|
||||
view_matrix[ 3 ][ 0 ] = -glm::dot( u, position );
|
||||
view_matrix[ 3 ][ 1 ] = -glm::dot( v, position );
|
||||
view_matrix[ 3 ][ 2 ] = -glm::dot( w, position );
|
||||
view_matrix[ 0 ][ 0 ] = u_right.x;
|
||||
view_matrix[ 1 ][ 0 ] = u_right.y;
|
||||
view_matrix[ 2 ][ 0 ] = u_right.z;
|
||||
|
||||
inverse_view_matrix = glm::mat4 { 1.0f };
|
||||
inverse_view_matrix[ 0 ][ 0 ] = u.x;
|
||||
inverse_view_matrix[ 0 ][ 1 ] = u.y;
|
||||
inverse_view_matrix[ 0 ][ 2 ] = u.z;
|
||||
inverse_view_matrix[ 1 ][ 0 ] = v.x;
|
||||
inverse_view_matrix[ 1 ][ 1 ] = v.y;
|
||||
inverse_view_matrix[ 1 ][ 2 ] = v.z;
|
||||
inverse_view_matrix[ 2 ][ 0 ] = w.x;
|
||||
inverse_view_matrix[ 2 ][ 1 ] = w.y;
|
||||
inverse_view_matrix[ 2 ][ 2 ] = w.z;
|
||||
inverse_view_matrix[ 3 ][ 0 ] = position.x;
|
||||
inverse_view_matrix[ 3 ][ 1 ] = position.y;
|
||||
inverse_view_matrix[ 3 ][ 2 ] = position.z;
|
||||
view_matrix[ 0 ][ 1 ] = v_up.x;
|
||||
view_matrix[ 1 ][ 1 ] = v_up.y;
|
||||
view_matrix[ 2 ][ 1 ] = v_up.z;
|
||||
|
||||
view_matrix[ 0 ][ 2 ] = w_direction.x;
|
||||
view_matrix[ 1 ][ 2 ] = w_direction.y;
|
||||
view_matrix[ 2 ][ 2 ] = w_direction.z;
|
||||
|
||||
view_matrix[ 3 ][ 0 ] = -glm::dot( u_right, position );
|
||||
view_matrix[ 3 ][ 1 ] = -glm::dot( v_up, position );
|
||||
view_matrix[ 3 ][ 2 ] = -glm::dot( w_direction, position );
|
||||
|
||||
frustum = base_frustum * view_matrix;
|
||||
}
|
||||
|
||||
void Camera::setViewTarget( glm::vec3 position, glm::vec3 target, glm::vec3 up )
|
||||
{
|
||||
setViewDirection( position, target - position, up );
|
||||
setViewDirection( position, glm::normalize( target - position ), up );
|
||||
}
|
||||
|
||||
void Camera::setViewYXZ( glm::vec3 position, glm::vec3 rotation )
|
||||
{
|
||||
ZoneScoped;
|
||||
const float c3 { glm::cos( rotation.z ) };
|
||||
const float s3 { glm::sin( rotation.z ) };
|
||||
const float c2 { glm::cos( rotation.x ) };
|
||||
@@ -84,33 +95,52 @@ namespace fgl::engine
|
||||
const glm::vec3 u { ( c1 * c3 + s1 * s2 * s3 ), ( c2 * s3 ), ( c1 * s2 * s3 - c3 * s1 ) };
|
||||
const glm::vec3 v { ( c3 * s1 * s2 - c1 * s3 ), ( c2 * c3 ), ( c1 * c3 * s2 + s1 * s3 ) };
|
||||
const glm::vec3 w { ( c2 * s1 ), ( -s2 ), ( c1 * c2 ) };
|
||||
|
||||
view_matrix = glm::mat4 { 1.0f };
|
||||
view_matrix[ 0 ][ 0 ] = u.x;
|
||||
view_matrix[ 1 ][ 0 ] = u.y;
|
||||
view_matrix[ 2 ][ 0 ] = u.z;
|
||||
|
||||
view_matrix[ 0 ][ 1 ] = v.x;
|
||||
view_matrix[ 1 ][ 1 ] = v.y;
|
||||
view_matrix[ 2 ][ 1 ] = v.z;
|
||||
|
||||
view_matrix[ 0 ][ 2 ] = w.x;
|
||||
view_matrix[ 1 ][ 2 ] = w.y;
|
||||
view_matrix[ 2 ][ 2 ] = w.z;
|
||||
|
||||
view_matrix[ 3 ][ 0 ] = -glm::dot( u, position );
|
||||
view_matrix[ 3 ][ 1 ] = -glm::dot( v, position );
|
||||
view_matrix[ 3 ][ 2 ] = -glm::dot( w, position );
|
||||
|
||||
inverse_view_matrix = glm::mat4 { 1.0f };
|
||||
inverse_view_matrix[ 0 ][ 0 ] = u.x;
|
||||
inverse_view_matrix[ 0 ][ 1 ] = u.y;
|
||||
inverse_view_matrix[ 0 ][ 2 ] = u.z;
|
||||
inverse_view_matrix[ 1 ][ 0 ] = v.x;
|
||||
inverse_view_matrix[ 1 ][ 1 ] = v.y;
|
||||
inverse_view_matrix[ 1 ][ 2 ] = v.z;
|
||||
inverse_view_matrix[ 2 ][ 0 ] = w.x;
|
||||
inverse_view_matrix[ 2 ][ 1 ] = w.y;
|
||||
inverse_view_matrix[ 2 ][ 2 ] = w.z;
|
||||
inverse_view_matrix[ 3 ][ 0 ] = position.x;
|
||||
inverse_view_matrix[ 3 ][ 1 ] = position.y;
|
||||
inverse_view_matrix[ 3 ][ 2 ] = position.z;
|
||||
frustum = base_frustum * view_matrix;
|
||||
}
|
||||
|
||||
Frustum
|
||||
createFrustum( const Camera& camera, const float aspect, const float fov_y, const float near, const float far )
|
||||
{
|
||||
Plane near_plane { camera.getForward(), near };
|
||||
Plane far_plane { camera.getBackward(), far };
|
||||
|
||||
const float half_width { near * glm::tan( fov_y / 2.0f ) }; // halfHSide
|
||||
const float half_height { half_width / aspect }; //halfVSide
|
||||
|
||||
constexpr glm::vec3 ZERO { 0.0f, 0.0f, 0.0f };
|
||||
|
||||
const auto far_forward { camera.getForward() * far };
|
||||
|
||||
//top_dir is the direction pointing at the highest point on the far plane
|
||||
const auto far_up { camera.getUp() * half_height };
|
||||
const glm::vec3 top_dir { glm::normalize( far_up + far_forward ) };
|
||||
|
||||
Plane top_plane { glm::cross( top_dir, camera.getUp() ), 0.0f };
|
||||
Plane bottom_plane { glm::cross( top_dir, camera.getDown() ), 0.0f };
|
||||
|
||||
const glm::vec3 right_dir { glm::normalize( camera.getRight() * half_width + far_forward ) };
|
||||
Plane right_plane { glm::cross( right_dir, camera.getRight() ), 0.0f };
|
||||
Plane left_plane { glm::cross( right_dir, camera.getLeft() ), 0.0f };
|
||||
|
||||
return { near_plane, far_plane, top_plane, bottom_plane, right_plane, left_plane };
|
||||
}
|
||||
|
||||
} // namespace fgl::engine
|
||||
@@ -8,29 +8,70 @@
|
||||
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "engine/coordinates/WorldCoordinate.hpp"
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
constexpr static auto WORLD_UP { glm::vec3 { 0.0f, 1.0f, 0.0f } };
|
||||
|
||||
class Camera;
|
||||
|
||||
Frustum
|
||||
createFrustum( const Camera& camera, const float aspect, const float fovy, const float near, const float far );
|
||||
|
||||
class Camera
|
||||
{
|
||||
glm::mat4 projection_matrix { 1.0f };
|
||||
|
||||
glm::mat4 view_matrix { 1.0f };
|
||||
glm::mat4 inverse_view_matrix { 1.0f };
|
||||
|
||||
//! Frustum of the camera in model space relative to the camera
|
||||
//! @note Must be transformed by the inverse view matrix to get the frustum in world space
|
||||
Frustum base_frustum {};
|
||||
Frustum frustum {};
|
||||
|
||||
friend Frustum createFrustum(
|
||||
const Camera& camera, const float aspect, const float fovy, const float near, const float far );
|
||||
|
||||
public:
|
||||
|
||||
//! Returns the frustum of the camera in world space
|
||||
const Frustum& getFrustumBounds() const { return frustum; }
|
||||
|
||||
const glm::mat4& getProjectionMatrix() const { return projection_matrix; }
|
||||
|
||||
const glm::mat4& getViewMatrix() const { return view_matrix; }
|
||||
|
||||
const glm::mat4& getInverseView() const { return inverse_view_matrix; }
|
||||
const glm::mat4 getProjectionViewMatrix() const { return projection_matrix * view_matrix; }
|
||||
|
||||
void setOrthographicProjection( float left, float right, float top, float bottom, float near, float far );
|
||||
void setPerspectiveProjection( float fovy, float aspect, float near, float far );
|
||||
|
||||
const glm::vec3 getPosition() const { return glm::vec3( inverse_view_matrix[ 3 ] ); }
|
||||
const glm::vec3 getPosition() const { return glm::vec3( -view_matrix[ 3 ] ); }
|
||||
|
||||
void setViewDirection( glm::vec3 pos, glm::vec3 direction, glm::vec3 up = glm::vec3 { 0.0f, -1.0f, 0.0f } );
|
||||
void setViewTarget( glm::vec3 pos, glm::vec3 target, glm::vec3 up = glm::vec3 { 0.0f, -1.0f, 0.0f } );
|
||||
const glm::vec3 getUp() const
|
||||
{
|
||||
return glm::normalize( glm::vec3( view_matrix[ 0 ][ 1 ], view_matrix[ 1 ][ 1 ], view_matrix[ 2 ][ 1 ] ) );
|
||||
}
|
||||
|
||||
const glm::vec3 getRight() const
|
||||
{
|
||||
return glm::normalize( glm::vec3( view_matrix[ 0 ][ 0 ], view_matrix[ 1 ][ 0 ], view_matrix[ 2 ][ 0 ] ) );
|
||||
}
|
||||
|
||||
const glm::vec3 getForward() const
|
||||
{
|
||||
return glm::normalize( glm::vec3( view_matrix[ 0 ][ 2 ], view_matrix[ 1 ][ 2 ], view_matrix[ 2 ][ 2 ] ) );
|
||||
}
|
||||
|
||||
const glm::vec3 getLeft() const { return -getRight(); }
|
||||
|
||||
const glm::vec3 getBackward() const { return -getForward(); }
|
||||
|
||||
const glm::vec3 getDown() const { return -getUp(); }
|
||||
|
||||
void setViewDirection( glm::vec3 pos, glm::vec3 direction, glm::vec3 up = WORLD_UP );
|
||||
void setViewTarget( glm::vec3 pos, glm::vec3 target, glm::vec3 up = WORLD_UP );
|
||||
void setViewYXZ( glm::vec3 pos, glm::vec3 rotation );
|
||||
};
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#pragma GCC diagnostic ignored "-Weffc++"
|
||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
#pragma GCC diagnostic ignored "-Wconversion"
|
||||
#include "engine/debug/drawers.hpp"
|
||||
#include "imgui/imgui.h"
|
||||
#include "imgui/imgui_impl_glfw.h"
|
||||
#include "imgui/imgui_impl_vulkan.h"
|
||||
@@ -104,6 +105,10 @@ namespace fgl::engine
|
||||
|
||||
auto previous_frame_start { std::chrono::high_resolution_clock::now() };
|
||||
|
||||
//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 );
|
||||
|
||||
while ( !m_window.shouldClose() )
|
||||
{
|
||||
ZoneScopedN( "Poll" );
|
||||
@@ -127,20 +132,25 @@ namespace fgl::engine
|
||||
current_time = new_time;
|
||||
delta_time = glm::min( delta_time, MAX_DELTA_TIME );
|
||||
|
||||
#if ENABLE_IMGUI
|
||||
{
|
||||
ImGui_ImplVulkan_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
}
|
||||
#endif
|
||||
|
||||
camera_controller.moveInPlaneXZ( m_window.window(), delta_time, viewer );
|
||||
camera.setViewYXZ( viewer.transform.translation, viewer.transform.rotation );
|
||||
|
||||
const float aspect { m_renderer.getAspectRatio() };
|
||||
|
||||
//camera.setOrthographicProjection( -aspect, aspect, -1, 1, -1, 1 );
|
||||
camera.setPerspectiveProjection( glm::radians( 50.0f ), aspect, 0.1f, 100.f );
|
||||
|
||||
if ( auto command_buffer = m_renderer.beginFrame(); command_buffer )
|
||||
{
|
||||
ZoneScopedN( "Render" );
|
||||
//Update
|
||||
const std::uint16_t frame_index { m_renderer.getFrameIndex() };
|
||||
|
||||
const auto view_frustum { camera.getFrustumBounds() };
|
||||
|
||||
FrameInfo frame_info { frame_index,
|
||||
delta_time,
|
||||
command_buffer,
|
||||
@@ -150,177 +160,184 @@ namespace fgl::engine
|
||||
m_renderer.getCurrentTracyCTX(),
|
||||
matrix_info_buffers[ frame_index ],
|
||||
draw_parameter_buffers[ frame_index ],
|
||||
m_renderer.getGBufferDescriptor( frame_index ) };
|
||||
m_renderer.getGBufferDescriptor( frame_index ),
|
||||
view_frustum };
|
||||
|
||||
#if TRACY_ENABLE
|
||||
auto& tracy_ctx { frame_info.tracy_ctx };
|
||||
#endif
|
||||
|
||||
CameraInfo current_camera_info { .projection = camera.getProjectionMatrix(),
|
||||
.view = camera.getViewMatrix(),
|
||||
.inverse_view = camera.getInverseView() };
|
||||
.view = camera.getViewMatrix() };
|
||||
|
||||
camera_info[ frame_index ] = current_camera_info;
|
||||
|
||||
#if ENABLE_IMGUI
|
||||
{
|
||||
ZoneScopedN( "ImGui recording" );
|
||||
ImGui_ImplVulkan_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
ImGui::Begin( "Titor Dev Menu" );
|
||||
|
||||
ImGui::Text( "Framerate" );
|
||||
ImGui::SameLine();
|
||||
ImGui::Text( "%.1f FPS", ImGui::GetIO().Framerate );
|
||||
|
||||
ImGui::Text( "Frame Time" );
|
||||
ImGui::SameLine();
|
||||
ImGui::Text( "%.3f ms", 1000.0f / ImGui::GetIO().Framerate );
|
||||
ImGui::Text( "Average rolling frametime: %.3f ms", rolling_ms_average.average() );
|
||||
|
||||
if ( ImGui::CollapsingHeader( "Camera" ) )
|
||||
{
|
||||
ImGui::Begin( "Titor Dev Menu" );
|
||||
|
||||
ImGui::Text( "Framerate" );
|
||||
ImGui::PushItemWidth( 80 );
|
||||
ImGui::DragFloat( "Pos X", &viewer.transform.translation.x, 0.1f );
|
||||
ImGui::SameLine();
|
||||
ImGui::Text( "%.1f FPS", ImGui::GetIO().Framerate );
|
||||
|
||||
ImGui::Text( "Frame Time" );
|
||||
ImGui::DragFloat( "Pos Y", &viewer.transform.translation.y, 0.1f );
|
||||
ImGui::SameLine();
|
||||
ImGui::Text( "%.3f ms", 1000.0f / ImGui::GetIO().Framerate );
|
||||
ImGui::Text( "Average rolling frametime: %.3f ms", rolling_ms_average.average() );
|
||||
ImGui::DragFloat( "Pos Z", &viewer.transform.translation.z, 0.1f );
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
if ( ImGui::CollapsingHeader( "Camera" ) )
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::PushItemWidth( 80 );
|
||||
ImGui::DragFloat( "Rot X", &viewer.transform.rotation.x, 0.1f, 0.0f, glm::two_pi< float >() );
|
||||
ImGui::SameLine();
|
||||
ImGui::DragFloat( "Rot Y", &viewer.transform.rotation.y, 0.1f, 0.0f, glm::two_pi< float >() );
|
||||
ImGui::SameLine();
|
||||
ImGui::DragFloat( "Rot Z", &viewer.transform.rotation.z, 0.1f, 0.0f, glm::two_pi< float >() );
|
||||
ImGui::PopItemWidth();
|
||||
}
|
||||
|
||||
if ( ImGui::CollapsingHeader( "View Frustum" ) )
|
||||
{
|
||||
const auto& frustum { camera.getFrustumBounds() };
|
||||
|
||||
auto printVec3 = []( const glm::vec3& vec )
|
||||
{ ImGui::Text( "(%.2f, %.2f, %.2f)", vec.x, vec.y, vec.z ); };
|
||||
|
||||
auto printPlane = [ printVec3 ]( const Plane& plane, const std::string name )
|
||||
{
|
||||
ImGui::PushItemWidth( 80 );
|
||||
ImGui::DragFloat( "Pos X", &viewer.transform.translation.x, 0.1f );
|
||||
ImGui::SameLine();
|
||||
ImGui::DragFloat( "Pos Y", &viewer.transform.translation.y, 0.1f );
|
||||
ImGui::SameLine();
|
||||
ImGui::DragFloat( "Pos Z", &viewer.transform.translation.z, 0.1f );
|
||||
ImGui::PopItemWidth();
|
||||
const std::string name_str { "Plane " + name + ": " };
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::PushItemWidth( 80 );
|
||||
ImGui::
|
||||
DragFloat( "Rot X", &viewer.transform.rotation.x, 0.1f, 0.0f, glm::two_pi< float >() );
|
||||
ImGui::Text( name_str.c_str() );
|
||||
ImGui::SameLine( 120.0f );
|
||||
printVec3( plane.direction() );
|
||||
ImGui::SameLine();
|
||||
ImGui::
|
||||
DragFloat( "Rot Y", &viewer.transform.rotation.y, 0.1f, 0.0f, glm::two_pi< float >() );
|
||||
ImGui::SameLine();
|
||||
ImGui::
|
||||
DragFloat( "Rot Z", &viewer.transform.rotation.z, 0.1f, 0.0f, glm::two_pi< float >() );
|
||||
ImGui::PopItemWidth();
|
||||
}
|
||||
ImGui::Text( "Distance: %.6f", plane.distance() );
|
||||
};
|
||||
|
||||
if ( ImGui::CollapsingHeader( "Models" ) )
|
||||
printPlane( frustum.near, "Near" );
|
||||
printPlane( frustum.far, "Far" );
|
||||
printPlane( frustum.top, "Top" );
|
||||
printPlane( frustum.bottom, "Bottom" );
|
||||
printPlane( frustum.right, "Right" );
|
||||
printPlane( frustum.left, "Left" );
|
||||
}
|
||||
|
||||
if ( ImGui::CollapsingHeader( "Models" ) )
|
||||
{
|
||||
for ( auto& [ id, game_object ] : game_objects )
|
||||
{
|
||||
for ( auto& [ id, game_object ] : game_objects )
|
||||
if ( game_object.model == nullptr ) continue;
|
||||
|
||||
ImGui::PushID( std::to_string( id ).c_str() );
|
||||
|
||||
if ( ImGui::TreeNode( game_object.model->getName().c_str() ) )
|
||||
{
|
||||
if ( game_object.model == nullptr ) continue;
|
||||
|
||||
ImGui::PushID( std::to_string( id ).c_str() );
|
||||
|
||||
if ( ImGui::TreeNode( game_object.model->getName().c_str() ) )
|
||||
ImGui::PushID( game_object.model->getName().c_str() );
|
||||
{
|
||||
ImGui::PushID( game_object.model->getName().c_str() );
|
||||
ImGui::PushID( "Position" );
|
||||
ImGui::PushItemWidth( 80 );
|
||||
ImGui::Text( "Position" );
|
||||
ImGui::SameLine();
|
||||
ImGui::DragFloat( "X", &game_object.transform.translation.x, 0.1f );
|
||||
ImGui::SameLine();
|
||||
ImGui::DragFloat( "Y", &game_object.transform.translation.y, 0.1f );
|
||||
ImGui::SameLine();
|
||||
ImGui::DragFloat( "Z", &game_object.transform.translation.z, 0.1f );
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
{
|
||||
ImGui::PushID( "Rotation" );
|
||||
ImGui::PushItemWidth( 80 );
|
||||
ImGui::Text( "Rotation" );
|
||||
ImGui::SameLine();
|
||||
ImGui::DragFloat(
|
||||
"X", &game_object.transform.rotation.x, 0.1f, 0.0f, glm::two_pi< float >() );
|
||||
ImGui::SameLine();
|
||||
ImGui::DragFloat(
|
||||
"Y", &game_object.transform.rotation.y, 0.1f, 0.0f, glm::two_pi< float >() );
|
||||
ImGui::SameLine();
|
||||
ImGui::DragFloat(
|
||||
"Z", &game_object.transform.rotation.z, 0.1f, 0.0f, glm::two_pi< float >() );
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
{
|
||||
ImGui::PushID( "Scale" );
|
||||
ImGui::PushItemWidth( 80 );
|
||||
ImGui::Text( "Scale" );
|
||||
ImGui::SameLine();
|
||||
ImGui::DragFloat( "X", &game_object.transform.scale.x, 0.1f );
|
||||
ImGui::SameLine();
|
||||
ImGui::DragFloat( "Y", &game_object.transform.scale.y, 0.1f );
|
||||
ImGui::SameLine();
|
||||
ImGui::DragFloat( "Z", &game_object.transform.scale.z, 0.1f );
|
||||
ImGui::TreePop();
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
if ( ImGui::CollapsingHeader( "Textures" ) )
|
||||
{
|
||||
std::vector< TextureID > textures;
|
||||
|
||||
ImGui::PushID( "Textures" );
|
||||
|
||||
for ( auto& primitive : game_object.model->m_primitives )
|
||||
{
|
||||
ImGui::PushID( "Position" );
|
||||
ImGui::PushItemWidth( 80 );
|
||||
ImGui::Text( "Position" );
|
||||
ImGui::SameLine();
|
||||
ImGui::DragFloat( "X", &game_object.transform.translation.x, 0.1f );
|
||||
ImGui::SameLine();
|
||||
ImGui::DragFloat( "Y", &game_object.transform.translation.y, 0.1f );
|
||||
ImGui::SameLine();
|
||||
ImGui::DragFloat( "Z", &game_object.transform.translation.z, 0.1f );
|
||||
ImGui::PopID();
|
||||
}
|
||||
if ( !primitive.m_texture.has_value() ) continue;
|
||||
|
||||
ImGui::Separator();
|
||||
auto& texture { primitive.m_texture.value() };
|
||||
|
||||
{
|
||||
ImGui::PushID( "Rotation" );
|
||||
ImGui::PushItemWidth( 80 );
|
||||
ImGui::Text( "Rotation" );
|
||||
ImGui::SameLine();
|
||||
ImGui::DragFloat(
|
||||
"X",
|
||||
&game_object.transform.rotation.x,
|
||||
0.1f,
|
||||
0.0f,
|
||||
glm::two_pi< float >() );
|
||||
ImGui::SameLine();
|
||||
ImGui::DragFloat(
|
||||
"Y",
|
||||
&game_object.transform.rotation.y,
|
||||
0.1f,
|
||||
0.0f,
|
||||
glm::two_pi< float >() );
|
||||
ImGui::SameLine();
|
||||
ImGui::DragFloat(
|
||||
"Z",
|
||||
&game_object.transform.rotation.z,
|
||||
0.1f,
|
||||
0.0f,
|
||||
glm::two_pi< float >() );
|
||||
ImGui::PopID();
|
||||
}
|
||||
const auto& extent { texture.getExtent() };
|
||||
|
||||
ImGui::Separator();
|
||||
auto& image_view { texture.getImageView() };
|
||||
auto& sampler { image_view.getSampler() };
|
||||
|
||||
{
|
||||
ImGui::PushID( "Scale" );
|
||||
ImGui::PushItemWidth( 80 );
|
||||
ImGui::Text( "Scale" );
|
||||
ImGui::SameLine();
|
||||
ImGui::DragFloat( "X", &game_object.transform.scale.x, 0.1f );
|
||||
ImGui::SameLine();
|
||||
ImGui::DragFloat( "Y", &game_object.transform.scale.y, 0.1f );
|
||||
ImGui::SameLine();
|
||||
ImGui::DragFloat( "Z", &game_object.transform.scale.z, 0.1f );
|
||||
ImGui::TreePop();
|
||||
ImGui::PopID();
|
||||
}
|
||||
if ( !sampler.has_value() ) continue;
|
||||
|
||||
if ( ImGui::CollapsingHeader( "Textures" ) )
|
||||
{
|
||||
std::vector< TextureID > textures;
|
||||
ImVec2 size;
|
||||
size.x = extent.width;
|
||||
size.y = extent.height;
|
||||
|
||||
ImGui::PushID( "Textures" );
|
||||
|
||||
for ( auto& primitive : game_object.model->m_primitives )
|
||||
if ( std::find( textures.begin(), textures.end(), texture.getID() )
|
||||
== textures.end() )
|
||||
{
|
||||
if ( !primitive.m_texture.has_value() ) continue;
|
||||
textures.emplace_back( texture.getID() );
|
||||
|
||||
auto& texture { primitive.m_texture.value() };
|
||||
|
||||
const auto& extent { texture.getExtent() };
|
||||
|
||||
auto& image_view { texture.getImageView() };
|
||||
auto& sampler { image_view.getSampler() };
|
||||
|
||||
if ( !sampler.has_value() ) continue;
|
||||
|
||||
ImVec2 size;
|
||||
size.x = extent.width;
|
||||
size.y = extent.height;
|
||||
|
||||
if ( std::find( textures.begin(), textures.end(), texture.getID() )
|
||||
== textures.end() )
|
||||
{
|
||||
textures.emplace_back( texture.getID() );
|
||||
|
||||
ImGui::Image(
|
||||
static_cast< ImTextureID >( primitive.m_texture
|
||||
->getImGuiDescriptorSet() ),
|
||||
size );
|
||||
}
|
||||
ImGui::Image(
|
||||
static_cast< ImTextureID >( primitive.m_texture
|
||||
->getImGuiDescriptorSet() ),
|
||||
size );
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: Add in a collapsable header to view all buffers, And their suballocations
|
||||
/*
|
||||
//TODO: Add in a collapsable header to view all buffers, And their suballocations
|
||||
/*
|
||||
if ( ImGui::CollapsingHeader( "Buffer allocations" ) )
|
||||
{
|
||||
for ( const auto& buffer : Buffer::getActiveBufferHandles() )
|
||||
@@ -329,14 +346,7 @@ namespace fgl::engine
|
||||
ImGui::Text( "Size: %zu", buffer.lock()->size() );
|
||||
}
|
||||
}*/
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
//Render
|
||||
ImGui::Render();
|
||||
}
|
||||
ImDrawData* data { ImGui::GetDrawData() };
|
||||
#endif
|
||||
|
||||
m_renderer.beginSwapchainRendererPass( command_buffer );
|
||||
@@ -348,6 +358,13 @@ namespace fgl::engine
|
||||
#if TRACY_ENABLE
|
||||
TracyVkZone( tracy_ctx, command_buffer, "ImGui Rendering" );
|
||||
#endif
|
||||
|
||||
debug::world::drawPointText( { 0.0f, 0.0f, 0.0f }, camera, { 1.0f, 0.0f, 0.0f } );
|
||||
|
||||
ImGui::End();
|
||||
ImGui::Render();
|
||||
|
||||
ImDrawData* data { ImGui::GetDrawData() };
|
||||
ImGui_ImplVulkan_RenderDrawData( data, command_buffer );
|
||||
}
|
||||
#endif
|
||||
@@ -359,6 +376,9 @@ namespace fgl::engine
|
||||
#endif
|
||||
|
||||
m_renderer.endFrame();
|
||||
|
||||
std::this_thread::sleep_until( new_time + std::chrono::milliseconds( 16 ) );
|
||||
|
||||
FrameMark;
|
||||
}
|
||||
}
|
||||
@@ -398,9 +418,9 @@ namespace fgl::engine
|
||||
m_entity_renderer.getVertexBuffer(),
|
||||
m_entity_renderer.getIndexBuffer() ) };
|
||||
|
||||
for ( int x = 0; x < 4; ++x )
|
||||
for ( int x = 0; x < 1; ++x )
|
||||
{
|
||||
for ( int y = 0; y < 4; ++y )
|
||||
for ( int y = 0; y < 1; ++y )
|
||||
{
|
||||
auto sponza = GameObject::createGameObject();
|
||||
sponza.model = model;
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
|
||||
#include "Device.hpp"
|
||||
#include "GameObject.hpp"
|
||||
#include "Model.hpp"
|
||||
#include "Renderer.hpp"
|
||||
#include "Window.hpp"
|
||||
#include "engine/descriptors/DescriptorPool.hpp"
|
||||
#include "engine/model/Model.hpp"
|
||||
#include "engine/systems/EntityRendererSystem.hpp"
|
||||
|
||||
namespace fgl::engine
|
||||
|
||||
@@ -32,7 +32,6 @@ namespace fgl::engine
|
||||
{
|
||||
glm::mat4 projection { 1.0f };
|
||||
glm::mat4 view { 1.0f };
|
||||
glm::mat4 inverse_view { 1.0f };
|
||||
glm::vec4 ambient_light_color { 1.0f, 1.0f, 1.0f, 0.02f };
|
||||
};
|
||||
|
||||
@@ -79,6 +78,8 @@ namespace fgl::engine
|
||||
Buffer& draw_parameter_buffer;
|
||||
|
||||
DescriptorSet& gbuffer_descriptor_set;
|
||||
|
||||
const Frustum& camera_frustum;
|
||||
};
|
||||
|
||||
} // namespace fgl::engine
|
||||
|
||||
49
src/engine/coordinates/WorldCoordinate.cpp
Normal file
49
src/engine/coordinates/WorldCoordinate.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// Created by kj16609 on 1/27/24.
|
||||
//
|
||||
|
||||
#include "WorldCoordinate.hpp"
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
|
||||
double Plane::distanceFrom( const Coordinate& coord ) const
|
||||
{
|
||||
return -( glm::dot( coord.position, m_direction ) - m_distance );
|
||||
}
|
||||
|
||||
bool Plane::isForward( const Coordinate& coord ) const
|
||||
{
|
||||
return distanceFrom( coord ) > 0.0;
|
||||
}
|
||||
|
||||
bool Plane::isBehind( const Coordinate& coord ) const
|
||||
{
|
||||
return !isForward( coord );
|
||||
}
|
||||
|
||||
Plane Plane::operator*( glm::mat4 matrix ) const
|
||||
{
|
||||
assert( m_distance != std::numeric_limits< float >::max() );
|
||||
assert( m_direction != DEFAULT_COORDINATE_VEC3 );
|
||||
|
||||
Plane result = *this;
|
||||
const glm::vec3 new_direction { matrix * glm::vec4( m_direction, 1.0f ) };
|
||||
|
||||
const auto new_distance { glm::dot( new_direction, m_direction ) + m_distance };
|
||||
result.m_direction = glm::normalize( new_direction );
|
||||
result.m_distance = new_distance;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Frustum::pointInside( const Coordinate& coord ) const
|
||||
{
|
||||
// clang-format off
|
||||
return
|
||||
near.isForward( coord ) && far.isForward( coord )
|
||||
&& top.isForward( coord ) && bottom.isForward( coord )
|
||||
&& right.isForward( coord ) && left.isForward( coord );
|
||||
// clang-format on
|
||||
}
|
||||
} // namespace fgl::engine
|
||||
129
src/engine/coordinates/WorldCoordinate.hpp
Normal file
129
src/engine/coordinates/WorldCoordinate.hpp
Normal file
@@ -0,0 +1,129 @@
|
||||
//
|
||||
// Created by kj16609 on 1/26/24.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <glm/mat4x4.hpp>
|
||||
#include <glm/vec3.hpp>
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
constexpr static auto DEFAULT_COORDINATE_VEC3 { glm::vec3( std::numeric_limits< float >::max() ) };
|
||||
|
||||
struct Coordinate
|
||||
{
|
||||
glm::vec3 position { DEFAULT_COORDINATE_VEC3 };
|
||||
|
||||
Coordinate() = default;
|
||||
|
||||
Coordinate( glm::vec3 position ) : position( position ) {}
|
||||
|
||||
Coordinate( const Coordinate& other ) = default;
|
||||
|
||||
Coordinate( Coordinate&& other ) : position( std::move( other.position ) )
|
||||
{
|
||||
other.position = DEFAULT_COORDINATE_VEC3;
|
||||
}
|
||||
};
|
||||
|
||||
class Plane
|
||||
{
|
||||
float m_distance { std::numeric_limits< float >::max() };
|
||||
glm::vec3 m_direction { DEFAULT_COORDINATE_VEC3 };
|
||||
|
||||
public:
|
||||
|
||||
bool valid() const
|
||||
{
|
||||
return m_distance != std::numeric_limits< float >::max() && m_direction != DEFAULT_COORDINATE_VEC3;
|
||||
}
|
||||
|
||||
Plane( const glm::vec3 vector, const float distance ) : m_distance( distance ), m_direction( vector ) {}
|
||||
|
||||
Plane( const glm::vec3 normal, const glm::vec3 point ) :
|
||||
Plane( glm::normalize( normal ), glm::dot( glm::normalize( normal ), point ) )
|
||||
{}
|
||||
|
||||
Plane() = default;
|
||||
|
||||
Plane operator*( glm::mat4 matrix ) const;
|
||||
|
||||
//! Returns the closest point on the plane to the 0,0,0 origin
|
||||
glm::vec3 getPosition() const
|
||||
{
|
||||
assert( m_distance != std::numeric_limits< float >::max() );
|
||||
assert( m_direction != DEFAULT_COORDINATE_VEC3 );
|
||||
return m_direction * m_distance;
|
||||
}
|
||||
|
||||
bool isForward( const Coordinate& coord ) const;
|
||||
bool isBehind( const Coordinate& coord ) const;
|
||||
|
||||
//! Returns the distance from a point to the plane. Negative if behind, positive if in front
|
||||
double distanceFrom( const Coordinate& coord ) const;
|
||||
|
||||
glm::vec3 direction() const { return m_direction; }
|
||||
|
||||
float distance() const { return m_distance; }
|
||||
};
|
||||
|
||||
struct Frustum
|
||||
{
|
||||
Plane near;
|
||||
Plane far;
|
||||
|
||||
Plane top;
|
||||
Plane bottom;
|
||||
|
||||
Plane right;
|
||||
Plane left;
|
||||
|
||||
friend class Camera;
|
||||
|
||||
public:
|
||||
|
||||
Frustum() = default;
|
||||
|
||||
Frustum(
|
||||
const Plane near_plane,
|
||||
const Plane far_plane,
|
||||
const Plane top_plane,
|
||||
const Plane bottom_plane,
|
||||
const Plane right_plane,
|
||||
const Plane left_plane ) :
|
||||
near( near_plane ),
|
||||
far( far_plane ),
|
||||
top( top_plane ),
|
||||
bottom( bottom_plane ),
|
||||
right( right_plane ),
|
||||
left( left_plane )
|
||||
{
|
||||
assert( near.valid() );
|
||||
assert( far.valid() );
|
||||
assert( top.valid() );
|
||||
assert( bottom.valid() );
|
||||
assert( right.valid() );
|
||||
assert( left.valid() );
|
||||
|
||||
assert( right_plane.direction() != left_plane.direction() );
|
||||
assert( top_plane.direction() != bottom_plane.direction() );
|
||||
assert( near_plane.direction() != far_plane.direction() );
|
||||
}
|
||||
|
||||
Frustum operator*( glm::mat4 matrix ) const
|
||||
{
|
||||
Frustum result = *this;
|
||||
result.near = near * matrix;
|
||||
result.far = far * matrix;
|
||||
result.top = top * matrix;
|
||||
result.bottom = bottom * matrix;
|
||||
result.right = right * matrix;
|
||||
result.left = left * matrix;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool pointInside( const Coordinate& coord ) const;
|
||||
};
|
||||
} // namespace fgl::engine
|
||||
232
src/engine/model/BoundingBox.cpp
Normal file
232
src/engine/model/BoundingBox.cpp
Normal file
@@ -0,0 +1,232 @@
|
||||
//
|
||||
// Created by kj16609 on 1/27/24.
|
||||
//
|
||||
|
||||
#include "BoundingBox.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "engine/coordinates/WorldCoordinate.hpp"
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
|
||||
bool engine::BoundingBox::isInFrustum( const Frustum& frustum ) const
|
||||
{
|
||||
ZoneScoped;
|
||||
const auto points { this->points() };
|
||||
for ( const auto& point : points )
|
||||
{
|
||||
if ( frustum.pointInside( point ) ) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
consteval std::array< std::uint32_t, BoundingBox::indicies_count > BoundingBox::triangleIndicies()
|
||||
{
|
||||
/**
|
||||
* Order (Top)
|
||||
* 1 =========== 0
|
||||
* || ||
|
||||
* || ||
|
||||
* 2 =========== 3
|
||||
*
|
||||
* Order (Bottom)
|
||||
* 5 =========== 4
|
||||
* || ||
|
||||
* || ||
|
||||
* 6 =========== 7
|
||||
*
|
||||
* Order (Side - 1)
|
||||
* 2 =========== 3
|
||||
* || ||
|
||||
* || ||
|
||||
* 6 =========== 7
|
||||
*
|
||||
* Order (Side - 2)
|
||||
* 1 =========== 0
|
||||
* || ||
|
||||
* || ||
|
||||
* 5 =========== 4
|
||||
*
|
||||
* Order (Side - 3)
|
||||
* 3 =========== 0
|
||||
* || ||
|
||||
* || ||
|
||||
* 7 =========== 4
|
||||
*
|
||||
* Order (Side - 4)
|
||||
* 2 =========== 1
|
||||
* || ||
|
||||
* || ||
|
||||
* 6 =========== 5
|
||||
*/
|
||||
|
||||
// clang-format off
|
||||
std::array< std::uint32_t, indicies_count > data {
|
||||
//Top tris
|
||||
0, 1, 2,
|
||||
1, 2, 3,
|
||||
//Bottom tris
|
||||
4, 5, 6,
|
||||
5, 6, 7,
|
||||
//Side 1
|
||||
2, 3, 6,
|
||||
3, 6, 7,
|
||||
//Side 2
|
||||
1, 0, 5,
|
||||
0, 5, 4,
|
||||
//Side 3
|
||||
3, 0, 7,
|
||||
0, 7, 4,
|
||||
//Side 4
|
||||
2, 1, 6,
|
||||
1, 6, 5
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
std::vector< glm::vec3 > BoundingBox::points() const
|
||||
{
|
||||
assert( middle != DEFAULT_COORDINATE_VEC3 );
|
||||
assert( scale != glm::vec3( 0.0f ) );
|
||||
std::vector< glm::vec3 > points;
|
||||
|
||||
// xp == x positive (Highest x point)
|
||||
// xn == x negative (Lowest x point)
|
||||
|
||||
const glm::vec3 xp_yp_zp { middle + scale };
|
||||
const glm::vec3 xn_yn_zn { middle - scale };
|
||||
|
||||
const auto xn { xn_yn_zn.x };
|
||||
const auto yn { xn_yn_zn.y };
|
||||
const auto zn { xn_yn_zn.z };
|
||||
|
||||
const auto xp { xp_yp_zp.x };
|
||||
const auto yp { xp_yp_zp.y };
|
||||
const auto zp { xp_yp_zp.z };
|
||||
|
||||
//Top
|
||||
const glm::vec3 xn_yp_zp { xn, yp, zp }; // (- + +)
|
||||
const glm::vec3 xn_yp_zn { xn, yp, zn }; // (- + -)
|
||||
const glm::vec3 xp_yp_zn { xp, yp, zn }; // (+ + -)
|
||||
|
||||
/*
|
||||
* Top-Down view (X,Y,Z)
|
||||
* (-,+,+) =========== (+,+,+)
|
||||
* || ||
|
||||
* || ||
|
||||
* (-,+,-) =========== (+,+,-)
|
||||
*
|
||||
* Order (Top)
|
||||
* 1 =========== 0
|
||||
* || ||
|
||||
* || ||
|
||||
* 2 =========== 3
|
||||
*
|
||||
* Order (Bottom)
|
||||
* 5 =========== 4
|
||||
* || ||
|
||||
* || ||
|
||||
* 6 =========== 7
|
||||
*/
|
||||
|
||||
points.resize( 8 );
|
||||
points[ 0 ] = xp_yp_zp;
|
||||
points[ 1 ] = xn_yp_zp;
|
||||
points[ 2 ] = xn_yp_zn;
|
||||
points[ 3 ] = xp_yp_zn;
|
||||
|
||||
//Bottom
|
||||
const glm::vec3 xn_yn_zp { xn, yn, zp }; // (- - +)
|
||||
const glm::vec3 xp_yn_zn { xp, yn, zn }; // (+ - -)
|
||||
const glm::vec3 xp_yn_zp { xp, yn, zp }; // (+ - +)
|
||||
|
||||
/*
|
||||
* Bottom-Top view (X,Y,Z)
|
||||
* (-,-,+) =========== (+,-,+)
|
||||
* || ||
|
||||
* || ||
|
||||
* (-,-,-) =========== (+,-,-)
|
||||
*/
|
||||
|
||||
points[ 4 ] = xp_yn_zp;
|
||||
points[ 5 ] = xn_yn_zp;
|
||||
points[ 6 ] = xn_yn_zn;
|
||||
points[ 7 ] = xp_yn_zn;
|
||||
|
||||
return points;
|
||||
}
|
||||
|
||||
BoundingBox BoundingBox::combine( const BoundingBox& other ) const
|
||||
{
|
||||
ZoneScoped;
|
||||
if ( middle == DEFAULT_COORDINATE_VEC3 )
|
||||
return other;
|
||||
else
|
||||
{
|
||||
const auto& other_points { other.points() };
|
||||
std::vector< glm::vec3 > points { this->points() };
|
||||
points.insert( points.end(), other_points.begin(), other_points.end() );
|
||||
|
||||
//TODO: There might be a way to do this without needing to do yet another point calculation.
|
||||
return generateBoundingFromPoints( points );
|
||||
}
|
||||
}
|
||||
|
||||
BoundingBox BoundingBox::operator*( const glm::mat4 matrix ) const
|
||||
{
|
||||
ZoneScoped;
|
||||
const glm::vec3 new_middle { matrix * glm::vec4( middle, 1.0f ) };
|
||||
const glm::vec3 new_scale { matrix * glm::vec4( scale, 0.0f ) };
|
||||
return { new_middle, new_scale };
|
||||
}
|
||||
|
||||
std::vector< std::pair< glm::vec3, glm::vec3 > > BoundingBox::lines() const
|
||||
{
|
||||
const auto points { this->points() };
|
||||
std::vector< std::pair< glm::vec3, glm::vec3 > > lines;
|
||||
for ( std::uint32_t i = 0; i < points.size() - 1; ++i )
|
||||
{
|
||||
lines.emplace_back( points[ i ], points[ i + 1 ] );
|
||||
}
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
BoundingBox generateBoundingFromPoints( std::vector< glm::vec3 >& points )
|
||||
{
|
||||
ZoneScoped;
|
||||
assert( points.size() > 0 );
|
||||
|
||||
// neg (min)
|
||||
glm::vec3 top_left_front { points[ 0 ] };
|
||||
// pos (max)
|
||||
glm::vec3 bottom_right_back { points[ 0 ] };
|
||||
|
||||
for ( const auto& pos : points )
|
||||
{
|
||||
top_left_front.x = std::min( pos.x, top_left_front.x );
|
||||
top_left_front.y = std::min( pos.y, top_left_front.y );
|
||||
top_left_front.z = std::min( pos.z, top_left_front.z );
|
||||
|
||||
bottom_right_back.x = std::max( pos.x, bottom_right_back.x );
|
||||
bottom_right_back.y = std::max( pos.y, bottom_right_back.y );
|
||||
bottom_right_back.z = std::max( pos.z, bottom_right_back.z );
|
||||
}
|
||||
|
||||
//Calculate midpoint
|
||||
const glm::vec3 midpoint { ( top_left_front + bottom_right_back ) / glm::vec3( 2.0f ) };
|
||||
const glm::vec3 scale { bottom_right_back - midpoint };
|
||||
|
||||
std::cout << "Generated bounding box from " << points.size() << "points. Output:\n\tMidpoint:" << midpoint.x
|
||||
<< " " << midpoint.y << " " << midpoint.z << "\n\tScale:" << scale.x << " " << scale.y << " "
|
||||
<< scale.z << std::endl;
|
||||
|
||||
return { midpoint, scale };
|
||||
}
|
||||
|
||||
} // namespace fgl::engine
|
||||
46
src/engine/model/BoundingBox.hpp
Normal file
46
src/engine/model/BoundingBox.hpp
Normal file
@@ -0,0 +1,46 @@
|
||||
//
|
||||
// Created by kj16609 on 1/27/24.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <glm/vec3.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
|
||||
#include "engine/coordinates/WorldCoordinate.hpp"
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
class Frustum;
|
||||
|
||||
struct BoundingBox
|
||||
{
|
||||
glm::vec3 middle { DEFAULT_COORDINATE_VEC3 };
|
||||
glm::vec3 scale { 0.0f };
|
||||
|
||||
//! Returns the top left (-x, -y, -z) coordinate
|
||||
inline glm::vec3 topLeftFront() const { return middle - scale; }
|
||||
|
||||
//! Returns the bottom right (x, y, z) coordinate
|
||||
inline glm::vec3 bottomRightBack() const { return middle + scale; }
|
||||
|
||||
// 6 sides, 2 triangles each, 3 verts per triangle
|
||||
constexpr static std::uint32_t indicies_count { 6 * 2 * 3 };
|
||||
|
||||
consteval static std::array< std::uint32_t, indicies_count > triangleIndicies();
|
||||
|
||||
std::vector< glm::vec3 > points() const;
|
||||
std::vector< std::pair< glm::vec3, glm::vec3 > > lines() const;
|
||||
|
||||
bool isInFrustum( const Frustum& frustum ) const;
|
||||
|
||||
BoundingBox combine( const BoundingBox& other ) const;
|
||||
|
||||
BoundingBox operator*( glm::mat4 matrix ) const;
|
||||
};
|
||||
|
||||
BoundingBox generateBoundingFromPoints( std::vector< glm::vec3 >& points );
|
||||
|
||||
} // namespace fgl::engine
|
||||
@@ -28,7 +28,7 @@
|
||||
#include "objectloaders/tiny_obj_loader.h"
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#include "utils.hpp"
|
||||
#include "engine/utils.hpp"
|
||||
|
||||
namespace std
|
||||
{
|
||||
@@ -69,6 +69,19 @@ namespace fgl::engine
|
||||
return draw_parameters;
|
||||
}
|
||||
|
||||
BoundingBox Model::buildBoundingBox( const std::vector< Primitive >& primitives )
|
||||
{
|
||||
//TODO:
|
||||
BoundingBox box;
|
||||
|
||||
for ( const auto& primitive : primitives )
|
||||
{
|
||||
box = box.combine( primitive.m_bounding_box );
|
||||
}
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
std::vector< vk::DrawIndexedIndirectCommand > Model::getDrawCommand( const std::uint32_t index ) const
|
||||
{
|
||||
std::vector< vk::DrawIndexedIndirectCommand > draw_commands;
|
||||
@@ -84,20 +97,25 @@ namespace fgl::engine
|
||||
return draw_commands;
|
||||
}
|
||||
|
||||
Model::Model( Device& device, Builder& builder ) :
|
||||
Model::Model( Device& device, ModelBuilder& builder, const BoundingBox bounding_box ) :
|
||||
m_device( device ),
|
||||
m_draw_parameters( buildParameters( builder.m_primitives ) )
|
||||
m_draw_parameters( buildParameters( builder.m_primitives ) ),
|
||||
m_bounding_box( bounding_box )
|
||||
{
|
||||
assert( bounding_box.middle != DEFAULT_COORDINATE_VEC3 );
|
||||
m_primitives = std::move( builder.m_primitives );
|
||||
}
|
||||
|
||||
std::unique_ptr< Model > Model::
|
||||
createModel( Device& device, const std::filesystem::path& path, Buffer& vertex_buffer, Buffer& index_buffer )
|
||||
{
|
||||
Builder builder { vertex_buffer, index_buffer };
|
||||
ModelBuilder builder { vertex_buffer, index_buffer };
|
||||
builder.loadModel( path );
|
||||
|
||||
return std::make_unique< Model >( device, builder );
|
||||
//Calculate bounding box
|
||||
BoundingBox bounding_box { buildBoundingBox( builder.m_primitives ) };
|
||||
|
||||
return std::make_unique< Model >( device, builder, bounding_box );
|
||||
}
|
||||
|
||||
void Model::syncBuffers( vk::CommandBuffer& cmd_buffer )
|
||||
@@ -141,7 +159,7 @@ namespace fgl::engine
|
||||
return attribute_descriptions;
|
||||
}
|
||||
|
||||
void Model::Builder::loadModel( const std::filesystem::path& filepath )
|
||||
void ModelBuilder::loadModel( const std::filesystem::path& filepath )
|
||||
{
|
||||
if ( filepath.extension() == ".obj" )
|
||||
{
|
||||
@@ -220,7 +238,7 @@ namespace fgl::engine
|
||||
}
|
||||
};
|
||||
|
||||
void Model::Builder::loadGltf( const std::filesystem::path& filepath )
|
||||
void ModelBuilder::loadGltf( const std::filesystem::path& filepath )
|
||||
{
|
||||
std::cout << "Loading gltf model " << filepath << std::endl;
|
||||
|
||||
@@ -244,6 +262,8 @@ namespace fgl::engine
|
||||
|
||||
for ( const tinygltf::Mesh& mesh : model.meshes )
|
||||
{
|
||||
std::vector< glm::vec3 > model_positions;
|
||||
|
||||
for ( const tinygltf::Primitive& primitive : mesh.primitives )
|
||||
{
|
||||
//TODO: Implement modes
|
||||
@@ -279,6 +299,9 @@ namespace fgl::engine
|
||||
//Load positions
|
||||
auto& position_accessor { model.accessors.at( primitive.attributes.at( "POSITION" ) ) };
|
||||
std::vector< glm::vec3 > position_data { extractData< glm::vec3 >( model, position_accessor ) };
|
||||
model_positions.insert( model_positions.end(), position_data.begin(), position_data.end() );
|
||||
|
||||
BoundingBox bounding_box { generateBoundingFromPoints( position_data ) };
|
||||
|
||||
std::vector< glm::vec3 > normals;
|
||||
|
||||
@@ -399,7 +422,9 @@ namespace fgl::engine
|
||||
Device::getInstance().endSingleTimeCommands( cmd );
|
||||
tex.dropStaging();
|
||||
|
||||
Primitive prim { std::move( vertex_buffer ), std::move( index_buffer ), std::move( tex ) };
|
||||
Primitive prim {
|
||||
std::move( vertex_buffer ), std::move( index_buffer ), bounding_box, std::move( tex )
|
||||
};
|
||||
|
||||
m_primitives.emplace_back( std::move( prim ) );
|
||||
|
||||
@@ -409,7 +434,7 @@ namespace fgl::engine
|
||||
else
|
||||
std::cout << "No material" << std::endl;
|
||||
|
||||
Primitive prim { std::move( vertex_buffer ), std::move( index_buffer ) };
|
||||
Primitive prim { std::move( vertex_buffer ), std::move( index_buffer ), bounding_box };
|
||||
|
||||
m_primitives.emplace_back( std::move( prim ) );
|
||||
}
|
||||
@@ -433,7 +458,7 @@ namespace fgl::engine
|
||||
std::cout << "Meshes: " << model.meshes.size() << std::endl;
|
||||
}
|
||||
|
||||
void Model::Builder::loadObj( const std::filesystem::path& filepath )
|
||||
void ModelBuilder::loadObj( const std::filesystem::path& filepath )
|
||||
{
|
||||
m_primitives.clear();
|
||||
|
||||
@@ -507,9 +532,18 @@ namespace fgl::engine
|
||||
}
|
||||
}
|
||||
|
||||
std::vector< glm::vec3 > vert_pos;
|
||||
for ( const auto& vert : verts )
|
||||
{
|
||||
vert_pos.emplace_back( vert.m_position );
|
||||
}
|
||||
|
||||
BoundingBox bounding_box { generateBoundingFromPoints( vert_pos ) };
|
||||
|
||||
m_primitives.emplace_back(
|
||||
VertexBufferSuballocation( m_vertex_buffer, std::move( verts ) ),
|
||||
IndexBufferSuballocation( m_index_buffer, std::move( indicies ) ) );
|
||||
IndexBufferSuballocation( m_index_buffer, std::move( indicies ) ),
|
||||
bounding_box );
|
||||
|
||||
std::cout << unique_verts.size() << " unique verts" << std::endl;
|
||||
}
|
||||
@@ -14,13 +14,14 @@
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include "Device.hpp"
|
||||
#include "BoundingBox.hpp"
|
||||
#include "engine/Device.hpp"
|
||||
#include "engine/buffers/Buffer.hpp"
|
||||
#include "engine/buffers/BufferSuballocation.hpp"
|
||||
#include "engine/buffers/vector/DeviceVector.hpp"
|
||||
#include "engine/buffers/vector/HostVector.hpp"
|
||||
#include "engine/texture/Texture.hpp"
|
||||
#include "utils.hpp"
|
||||
#include "engine/utils.hpp"
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
@@ -62,18 +63,27 @@ namespace fgl::engine
|
||||
{
|
||||
VertexBufferSuballocation m_vertex_buffer;
|
||||
IndexBufferSuballocation m_index_buffer;
|
||||
BoundingBox m_bounding_box;
|
||||
|
||||
std::optional< Texture > m_texture { std::nullopt };
|
||||
|
||||
Primitive( VertexBufferSuballocation&& vertex_buffer, IndexBufferSuballocation&& index_buffer ) :
|
||||
Primitive(
|
||||
VertexBufferSuballocation&& vertex_buffer,
|
||||
IndexBufferSuballocation&& index_buffer,
|
||||
BoundingBox& bounding_box ) :
|
||||
m_vertex_buffer( std::move( vertex_buffer ) ),
|
||||
m_index_buffer( std::move( index_buffer ) )
|
||||
m_index_buffer( std::move( index_buffer ) ),
|
||||
m_bounding_box( bounding_box )
|
||||
{}
|
||||
|
||||
Primitive(
|
||||
VertexBufferSuballocation&& vertex_buffer, IndexBufferSuballocation&& index_buffer, Texture&& texture ) :
|
||||
VertexBufferSuballocation&& vertex_buffer,
|
||||
IndexBufferSuballocation&& index_buffer,
|
||||
BoundingBox& bounding_box,
|
||||
Texture&& texture ) :
|
||||
m_vertex_buffer( std::move( vertex_buffer ) ),
|
||||
m_index_buffer( std::move( index_buffer ) ),
|
||||
m_bounding_box( bounding_box ),
|
||||
m_texture( std::move( texture ) )
|
||||
{}
|
||||
|
||||
@@ -82,39 +92,49 @@ namespace fgl::engine
|
||||
Primitive( Primitive&& other ) = default;
|
||||
};
|
||||
|
||||
struct ModelBuilder
|
||||
{
|
||||
Buffer& m_vertex_buffer;
|
||||
Buffer& m_index_buffer;
|
||||
|
||||
std::vector< ::fgl::engine::Primitive > m_primitives {};
|
||||
|
||||
ModelBuilder() = delete;
|
||||
|
||||
ModelBuilder( Buffer& parent_vertex_buffer, Buffer& parent_index_buffer ) :
|
||||
m_vertex_buffer( parent_vertex_buffer ),
|
||||
m_index_buffer( parent_index_buffer )
|
||||
{}
|
||||
|
||||
void loadModel( const std::filesystem::path& filepath );
|
||||
void loadObj( const std::filesystem::path& filepath );
|
||||
void loadGltf( const std::filesystem::path& filepath );
|
||||
};
|
||||
|
||||
class Model
|
||||
{
|
||||
Device& m_device;
|
||||
|
||||
std::vector< vk::DrawIndexedIndirectCommand > buildParameters( const std::vector< Primitive >& primitives );
|
||||
static std::vector< vk::DrawIndexedIndirectCommand > buildParameters( const std::vector< Primitive >&
|
||||
primitives );
|
||||
static BoundingBox buildBoundingBox( const std::vector< Primitive >& primitives );
|
||||
|
||||
std::vector< vk::DrawIndexedIndirectCommand > m_draw_parameters;
|
||||
|
||||
std::string m_name { "Unnamed model" };
|
||||
|
||||
//! Bounding box of the model
|
||||
BoundingBox m_bounding_box;
|
||||
|
||||
public:
|
||||
|
||||
//! Returns the bounding box in model space
|
||||
const BoundingBox& getBoundingBox() const { return m_bounding_box; }
|
||||
|
||||
BoundingBox getBoundingBox( const glm::mat4 matrix ) const { return m_bounding_box * matrix; }
|
||||
|
||||
std::vector< ::fgl::engine::Primitive > m_primitives {};
|
||||
|
||||
struct Builder
|
||||
{
|
||||
Buffer& m_vertex_buffer;
|
||||
Buffer& m_index_buffer;
|
||||
|
||||
std::vector< ::fgl::engine::Primitive > m_primitives {};
|
||||
|
||||
Builder() = delete;
|
||||
|
||||
Builder( Buffer& parent_vertex_buffer, Buffer& parent_index_buffer ) :
|
||||
m_vertex_buffer( parent_vertex_buffer ),
|
||||
m_index_buffer( parent_index_buffer )
|
||||
{}
|
||||
|
||||
void loadModel( const std::filesystem::path& filepath );
|
||||
void loadObj( const std::filesystem::path& filepath );
|
||||
void loadGltf( const std::filesystem::path& filepath );
|
||||
};
|
||||
|
||||
std::vector< vk::DrawIndexedIndirectCommand > getDrawCommand( const std::uint32_t index ) const;
|
||||
|
||||
static std::unique_ptr< Model > createModel(
|
||||
@@ -124,7 +144,7 @@ namespace fgl::engine
|
||||
|
||||
const std::string& getName() const { return m_name; }
|
||||
|
||||
Model( Device& device, Builder& builder );
|
||||
Model( Device& device, ModelBuilder& builder, const BoundingBox bounding_box );
|
||||
|
||||
~Model() = default;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include <array>
|
||||
#include <fstream>
|
||||
|
||||
#include "engine/Model.hpp"
|
||||
#include "engine/model/Model.hpp"
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#include "PipelineConfigInfo.hpp"
|
||||
|
||||
#include "engine/Model.hpp"
|
||||
#include "engine/model/Model.hpp"
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
#define GLM_FORCE_DEPTH_ZERO_TO_ON
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/constants.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtx/intersect.hpp>
|
||||
#include <imgui/imgui.h>
|
||||
#include <tracy/TracyC.h>
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
@@ -18,6 +21,7 @@
|
||||
#include <stdexcept>
|
||||
#include <thread>
|
||||
|
||||
#include "engine/debug/drawers.hpp"
|
||||
#include "engine/literals/size.hpp"
|
||||
|
||||
namespace fgl::engine
|
||||
@@ -94,6 +98,12 @@ namespace fgl::engine
|
||||
TracyVkZone( info.tracy_ctx, command_buffer, "Render game object" );
|
||||
if ( obj.model == nullptr ) continue;
|
||||
|
||||
const BoundingBox model_bounding_box { obj.model->getBoundingBox( obj.transform.mat4() ) };
|
||||
|
||||
debug::world::drawBoundingBox( model_bounding_box, info.camera );
|
||||
|
||||
if ( !model_bounding_box.isInFrustum( info.camera_frustum ) ) continue;
|
||||
|
||||
for ( const auto& primitive : obj.model->m_primitives )
|
||||
{
|
||||
ZoneScopedN( "Queue Primitive" );
|
||||
@@ -157,6 +167,13 @@ namespace fgl::engine
|
||||
}
|
||||
}
|
||||
|
||||
if ( draw_pairs.empty() )
|
||||
{
|
||||
std::cout << "Nothing to draw!" << std::endl;
|
||||
command_buffer.nextSubpass( vk::SubpassContents::eInline );
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector< vk::DrawIndexedIndirectCommand > draw_commands;
|
||||
std::vector< ModelMatrixInfo > model_matrices;
|
||||
|
||||
@@ -172,8 +189,6 @@ namespace fgl::engine
|
||||
}
|
||||
TracyCZoneEnd( filter_zone_TRACY );
|
||||
|
||||
assert( draw_commands.size() > 0 && "No draw commands to render" );
|
||||
|
||||
TracyCZoneN( draw_zone_TRACY, "Submit draw data", true );
|
||||
auto& draw_parameter_buffer { m_draw_parameter_buffers[ info.frame_idx ] };
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
#include "engine/Device.hpp"
|
||||
#include "engine/FrameInfo.hpp"
|
||||
#include "engine/GameObject.hpp"
|
||||
#include "engine/Model.hpp"
|
||||
#include "engine/SwapChain.hpp"
|
||||
#include "engine/model/Model.hpp"
|
||||
#include "engine/pipeline/PipelineT.hpp"
|
||||
|
||||
namespace fgl::engine
|
||||
|
||||
Reference in New Issue
Block a user