2#ifndef LIBSBX_ANIMATIONS_SKINNED_MESH_DRAW_LIST_HPP_
3#define LIBSBX_ANIMATIONS_SKINNED_MESH_DRAW_LIST_HPP_
6#include <unordered_set>
11#include <easy/profiler.h>
13#include <range/v3/view/enumerate.hpp>
15#include <libsbx/core/engine.hpp>
17#include <libsbx/graphics/graphics_module.hpp>
18#include <libsbx/graphics/subrenderer.hpp>
19#include <libsbx/graphics/pipeline/pipeline.hpp>
20#include <libsbx/graphics/pipeline/graphics_pipeline.hpp>
21#include <libsbx/graphics/descriptor/descriptor_handler.hpp>
23#include <libsbx/assets/assets_module.hpp>
25#include <libsbx/scenes/scenes_module.hpp>
26#include <libsbx/scenes/scene.hpp>
28#include <libsbx/scenes/components/skinned_mesh.hpp>
30#include <libsbx/models/material_draw_list.hpp>
32#include <libsbx/animations/mesh.hpp>
33#include <libsbx/animations/animator.hpp>
35namespace sbx::animations {
42 std::uint32_t skinned_vertex_offset{0u};
46 graphics::buffer::address_type pre_vertices;
47 graphics::buffer::address_type post_vertices;
48 std::uint32_t vertex_count;
49 std::uint32_t bone_offset;
54 template<
typename DrawList>
55 static auto create_shared_buffers(DrawList& draw_list) ->
void {
56 draw_list.create_buffer(bone_matrices_buffer_name, graphics::storage_buffer::min_size, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
59 template<
typename DrawList>
60 static auto destroy_shared_buffers([[maybe_unused]] DrawList& draw_list) ->
void {
61 draw_list.destroy_buffer(bone_matrices_buffer_name);
64 template<
typename DrawList>
65 static auto update_shared_buffers(DrawList& draw_list) ->
void {
66 draw_list.update_buffer(_bone_matrices, bone_matrices_buffer_name);
68 _bone_matrices.clear();
71 template<
typename Callable>
72 static auto for_each_submission(scenes::scene& scene, Callable&& callable) ->
void {
73 auto& assets_module = core::engine::get_module<assets::assets_module>();
75 auto& graph = scene.graph();
77 _skinning_jobs.clear();
79 const auto query = graph.query<
const scenes::skinned_mesh, animations::animator>();
81 auto vertex_cursor = std::uint32_t{0u};
83 for (
auto&& [
node, skinned_mesh, animator] : query.each()) {
84 const auto transform_data = models::transform_data{graph.world_transform(
node), graph.world_normal(
node)};
86 const auto& pose = skinned_mesh.pose();
88 const auto bone_offset =
static_cast<std::uint32_t
>(_bone_matrices.size());
90 utility::append(_bone_matrices, pose);
92 const auto& mesh_id = skinned_mesh.mesh_id();
94 auto& mesh = assets_module.get_asset<animations::mesh>(mesh_id);
96 _skinning_jobs.emplace_back(skinning_job{
97 .pre_vertices = mesh.address(),
99 .vertex_count = mesh.vertex_count(),
100 .bone_offset = bone_offset
103 const auto entity_vertex_offset = vertex_cursor;
104 vertex_cursor += mesh.vertex_count();
106 for (
const auto& submesh : skinned_mesh.submeshes()) {
107 std::invoke(callable,
node, mesh_id, submesh.index, submesh.material, transform_data, instance_payload{entity_vertex_offset});
112 static auto make_instance_data(
const scenes::node
node,
const std::uint32_t transform_index, std::uint32_t material_index,
const instance_payload& payload) -> models::instance_data {
113 return models::instance_data{transform_index, material_index,
static_cast<std::uint32_t
>(
node), payload.skinned_vertex_offset};
116 template<
typename Mesh,
typename Emitter>
117 static auto build_draw_commands(
const Mesh& mesh, std::uint32_t submesh_index, std::vector<models::instance_data>&& instances, Emitter&& emitter) -> std::uint32_t {
118 const auto& submesh = mesh.submesh(submesh_index);
120 for (
auto i = std::uint32_t{0u}; i < static_cast<std::uint32_t>(instances.size()); ++i) {
121 auto command = VkDrawIndexedIndirectCommand{};
122 command.indexCount = submesh.index_count;
123 command.instanceCount = 1u;
124 command.firstIndex = submesh.index_offset;
125 command.vertexOffset =
static_cast<std::int32_t
>(instances[i].payload + submesh.vertex_offset);
126 command.firstInstance = emitter.base_instance;
128 emitter.emit_single(command, instances[i]);
131 return static_cast<std::uint32_t
>(instances.size());
134 static auto skinning_jobs() -> std::vector<skinning_job>& {
135 return _skinning_jobs;
140 inline static auto _bone_matrices = std::vector<math::matrix4x4>{};
141 inline static auto _skinning_jobs = std::vector<skinning_job>{};
145using skinned_mesh_material_draw_list = models::basic_material_draw_list<skinned_mesh_traits>;
Definition: hashed_string.hpp:17
Definition: skinned_mesh_material_draw_list.hpp:41
Definition: skinned_mesh_material_draw_list.hpp:45
Definition: skinned_mesh_material_draw_list.hpp:37