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 {
43 graphics::buffer::address_type pre_vertices;
44 graphics::buffer::address_type post_vertices;
45 std::uint32_t vertex_count;
46 std::uint32_t bone_offset;
51 template<
typename DrawList>
52 static auto create_shared_buffers(DrawList& draw_list) ->
void {
53 draw_list.create_buffer(bone_matrices_buffer_name, graphics::storage_buffer::min_size, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
56 template<
typename DrawList>
57 static auto destroy_shared_buffers([[maybe_unused]] DrawList& draw_list) ->
void {
58 draw_list.destroy_buffer(bone_matrices_buffer_name);
61 template<
typename DrawList>
62 static auto update_shared_buffers(DrawList& draw_list) ->
void {
63 draw_list.update_buffer(_bone_matrices, bone_matrices_buffer_name);
65 _bone_matrices.clear();
68 template<
typename Callable>
69 static auto for_each_submission(scenes::scene& scene, Callable&& callable) ->
void {
70 auto& assets_module = core::engine::get_module<assets::assets_module>();
72 _skinning_jobs.clear();
74 const auto query = scene.query<
const scenes::skinned_mesh, animations::animator>();
76 for (
auto&& [
node, skinned_mesh, animator] : query.each()) {
77 const auto transform_data = models::transform_data{scene.world_transform(
node), scene.world_normal(
node)};
79 const auto& pose = skinned_mesh.pose();
81 const auto bone_offset =
static_cast<std::uint32_t
>(_bone_matrices.size());
83 utility::append(_bone_matrices, pose);
85 const auto& mesh_id = skinned_mesh.mesh_id();
87 auto& mesh = assets_module.get_asset<animations::mesh>(mesh_id);
89 _skinning_jobs.emplace_back(skinning_job{
90 .pre_vertices = mesh.address(),
92 .vertex_count = mesh.vertex_count(),
93 .bone_offset = bone_offset
96 for (
const auto& submesh : skinned_mesh.submeshes()) {
97 std::invoke(callable,
node, mesh_id, submesh.index, submesh.material, transform_data, instance_payload{});
102 static auto make_instance_data(
const scenes::node
node,
const std::uint32_t transform_index, std::uint32_t material_index, [[maybe_unused]]
const instance_payload& payload) -> models::instance_data {
103 return models::instance_data{transform_index, material_index,
static_cast<std::uint32_t
>(
node), 0u};
106 template<
typename Mesh,
typename Emitter>
107 static auto build_draw_commands(
const Mesh& mesh, std::uint32_t submesh_index, std::vector<models::instance_data>&& instances, Emitter&& emitter) -> std::uint32_t {
108 auto base_instance_offset = std::uint32_t{0};
110 const auto& submesh = mesh.submesh(submesh_index);
112 for (
const auto& instance : instances) {
113 const auto instance_index = emitter.base_instance + base_instance_offset;
115 auto command = VkDrawIndexedIndirectCommand{};
116 command.indexCount = submesh.index_count;
117 command.instanceCount = 1u;
118 command.firstIndex = submesh.index_offset;
119 command.vertexOffset =
static_cast<std::int32_t
>(instance_index * mesh.vertex_count());
120 command.firstInstance = instance_index;
122 emitter.emit_single(command, instance);
124 base_instance_offset++;
127 return base_instance_offset;
130 static auto skinning_jobs() -> std::vector<skinning_job>& {
131 return _skinning_jobs;
136 inline static auto _bone_matrices = std::vector<math::matrix4x4>{};
137 inline static auto _skinning_jobs = std::vector<skinning_job>{};
141using 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:40
Definition: skinned_mesh_material_draw_list.hpp:42
Definition: skinned_mesh_material_draw_list.hpp:37