160 lines
4.9 KiB
C++
160 lines
4.9 KiB
C++
//
|
|
// Created by kj16609 on 11/28/23.
|
|
//
|
|
|
|
#include "Model.hpp"
|
|
|
|
#include <cassert>
|
|
|
|
#include "EngineContext.hpp"
|
|
#include "ModelInstance.hpp"
|
|
#include "builders/ModelBuilder.hpp"
|
|
#include "builders/SceneBuilder.hpp"
|
|
|
|
namespace fgl::engine
|
|
{
|
|
using namespace fgl::literals::size_literals;
|
|
|
|
ModelGPUBuffers& getModelBuffers()
|
|
{
|
|
return EngineContext::getInstance().m_model_buffers;
|
|
}
|
|
|
|
ModelGPUBuffers::ModelGPUBuffers() :
|
|
m_long_buffer(
|
|
32_MiB,
|
|
vk::BufferUsageFlagBits::eStorageBuffer | vk::BufferUsageFlagBits::eTransferDst,
|
|
vk::MemoryPropertyFlagBits::eDeviceLocal ),
|
|
m_short_buffer(
|
|
16_MiB,
|
|
vk::BufferUsageFlagBits::eStorageBuffer | vk::BufferUsageFlagBits::eTransferDst,
|
|
vk::MemoryPropertyFlagBits::eDeviceLocal | vk::MemoryPropertyFlagBits::eHostVisible ),
|
|
m_vertex_buffer(
|
|
2_GiB,
|
|
vk::BufferUsageFlagBits::eVertexBuffer | vk::BufferUsageFlagBits::eStorageBuffer
|
|
| vk::BufferUsageFlagBits::eTransferDst,
|
|
vk::MemoryPropertyFlagBits::eDeviceLocal ),
|
|
m_index_buffer(
|
|
1_GiB,
|
|
vk::BufferUsageFlagBits::eIndexBuffer | vk::BufferUsageFlagBits::eTransferDst,
|
|
vk::MemoryPropertyFlagBits::eDeviceLocal ),
|
|
m_generated_instance_info( constructPerFrame< DeviceVector< PerVertexInstanceInfo > >( m_vertex_buffer ) ),
|
|
m_primitive_info( m_long_buffer ),
|
|
m_primitive_instances( m_short_buffer ),
|
|
m_model_instances( m_short_buffer )
|
|
{
|
|
m_vertex_buffer->setDebugName( "Vertex buffer GPU" );
|
|
m_index_buffer->setDebugName( "Index buffer" );
|
|
|
|
m_primitives_desc = PRIMITIVE_SET.create();
|
|
m_primitives_desc->bindStorageBuffer( 0, m_primitive_info );
|
|
m_primitives_desc->update();
|
|
m_primitives_desc->setName( "Primitives" );
|
|
|
|
m_instances_desc = INSTANCES_SET.create();
|
|
m_instances_desc->bindStorageBuffer( 0, m_primitive_instances );
|
|
m_instances_desc->bindStorageBuffer( 1, m_model_instances );
|
|
m_instances_desc->update();
|
|
m_instances_desc->setName( "Instances, Primitive + Models" );
|
|
}
|
|
|
|
OrientedBoundingBox< CoordinateSpace::Model > Model::buildBoundingBox( const std::vector< Primitive >& primitives )
|
|
{
|
|
ZoneScoped;
|
|
assert( !primitives.empty() );
|
|
if ( primitives.empty() ) return {};
|
|
|
|
OrientedBoundingBox< CoordinateSpace::Model > box { primitives.at( 0 ).m_bounding_box };
|
|
|
|
for ( std::uint64_t i = 1; i < primitives.size(); i++ ) box = box.combine( primitives[ i ].m_bounding_box );
|
|
|
|
return box;
|
|
}
|
|
|
|
bool Model::ready() const
|
|
{
|
|
//Return true if even a single primitive is ready
|
|
for ( auto& primitive : this->m_primitives )
|
|
{
|
|
if ( primitive.ready() ) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
Model::Model( std::vector< Primitive >&& primitives, const std::string& name ) :
|
|
m_name( name ),
|
|
m_primitives( std::forward< std::vector< Primitive > >( primitives ) )
|
|
{}
|
|
|
|
std::shared_ptr< ModelInstance > Model::createInstance()
|
|
{
|
|
ZoneScoped;
|
|
|
|
auto& buffers { getModelBuffers() };
|
|
|
|
std::vector< PrimitiveInstanceInfoIndex > primitive_instances {};
|
|
|
|
WorldTransform transform {};
|
|
transform.translation = Coordinate< CoordinateSpace::World >( glm::vec3( 0.0, 0.0, 0.0 ) );
|
|
transform.scale = glm::vec3( constants::DEFAULT_MODEL_SCALE );
|
|
transform.rotation = { glm::quat( 1.0, 0.0, 0.0, 0.0 ) };
|
|
|
|
const ModelInstanceInfo model_info { transform.mat4() };
|
|
|
|
ModelInstanceInfoIndex model_instance { buffers.m_model_instances.acquire( model_info ) };
|
|
|
|
for ( auto& primitive : m_primitives )
|
|
{
|
|
const auto render_info { primitive.renderInstanceInfo() };
|
|
|
|
PrimitiveInstanceInfo instance_info {};
|
|
instance_info.m_primitive_info = render_info->idx();
|
|
instance_info.m_model_info = model_instance.idx();
|
|
instance_info.m_material = primitive.default_material->getID();
|
|
|
|
primitive_instances.emplace_back( buffers.m_primitive_instances.acquire( instance_info ) );
|
|
}
|
|
|
|
return std::make_shared<
|
|
ModelInstance >( std::move( primitive_instances ), std::move( model_instance ), this->shared_from_this() );
|
|
}
|
|
|
|
std::shared_ptr< Model > Model::createModel( const std::filesystem::path& path )
|
|
{
|
|
ZoneScoped;
|
|
|
|
auto& buffers { getModelBuffers() };
|
|
|
|
log::debug( "Creating model {}", path );
|
|
|
|
ModelBuilder builder { buffers.m_vertex_buffer, buffers.m_index_buffer };
|
|
builder.loadModel( path );
|
|
|
|
//Calculate bounding box
|
|
OrientedBoundingBox bounding_box { buildBoundingBox( builder.m_primitives ) };
|
|
|
|
auto model_ptr { std::make_shared< Model >( std::move( builder.m_primitives ) ) };
|
|
|
|
log::debug( "Finished creating model {}", path );
|
|
|
|
return model_ptr;
|
|
}
|
|
|
|
std::shared_ptr< Model > Model::
|
|
createModelFromVerts( std::vector< ModelVertex > verts, std::vector< std::uint32_t > indicies )
|
|
{
|
|
ZoneScoped;
|
|
|
|
auto& buffers { getModelBuffers() };
|
|
|
|
ModelBuilder builder { buffers.m_vertex_buffer, buffers.m_index_buffer };
|
|
builder.loadVerts( std::move( verts ), std::move( indicies ) );
|
|
|
|
OrientedBoundingBox bounding_box { buildBoundingBox( builder.m_primitives ) };
|
|
|
|
auto model_ptr { std::make_shared< Model >( std::move( builder.m_primitives ) ) };
|
|
|
|
return model_ptr;
|
|
}
|
|
|
|
} // namespace fgl::engine
|