12auto get_bone_entity(
const std::string& bone_id,
const std::vector<entt::handle>& entities) -> entt::handle
14 for(
const auto& e : entities)
18 const auto&
tag =
e.get<tag_component>();
19 if(
tag.name == bone_id)
29auto process_node_impl(
const std::unique_ptr<mesh::armature_node>& node,
30 const skin_bind_data& bind_data,
32 std::vector<entt::handle>& nodes,
33 animation_pose& ref_pose) -> entt::handle
35 auto entity_node = parent;
37 if(entity_node == parent)
39 auto& parent_trans_comp = parent.get<transform_component>();
40 const auto& children = parent_trans_comp.get_children();
41 auto found_node = get_bone_entity(node->name, children);
44 entity_node = found_node;
48 auto& reg = *entity_node.registry();
51 auto& trans_comp = entity_node.get<transform_component>();
52 trans_comp.set_transform_local(node->local_transform);
54 nodes.emplace_back(entity_node);
56 if(!node->submeshes.empty())
58 auto& comp = entity_node.get_or_emplace<submesh_component>();
59 comp.submeshes = node->submeshes;
62 auto query = bind_data.find_bone_by_id(node->name);
63 if(query.bone && query.index >= 0)
65 auto& comp = entity_node.get_or_emplace<bone_component>();
66 comp.bone_index = query.index;
71 animation_pose::node ref_node;
72 ref_node.desc.index = node->index;
73 ref_node.transform = node->local_transform;
74 ref_pose.nodes.push_back(ref_node);
80void process_node(
const std::unique_ptr<mesh::armature_node>& node,
81 const skin_bind_data& bind_data,
83 std::vector<entt::handle>& nodes,
84 animation_pose& ref_pose)
89 auto entity_node = process_node_impl(node, bind_data, parent, nodes, ref_pose);
90 for(
auto& child : node->children)
92 process_node(child, bind_data, entity_node, nodes, ref_pose);
96auto process_armature(
const mesh& render_mesh,
98 std::vector<entt::handle>& nodes,
99 animation_pose& ref_pose) ->
bool
101 const auto& root = render_mesh.get_armature();
107 const auto& skin_data = render_mesh.get_skin_bind_data();
108 process_node(root, skin_data, parent, nodes, ref_pose);
113void get_transforms_for_entities(
const std::vector<entt::handle>& entities,
114 size_t submesh_count,
115 pose_mat4& submesh_pose,
117 pose_mat4& bone_pose)
119 size_t entities_count = entities.size();
121 submesh_pose.transforms.clear();
122 submesh_pose.transforms.reserve(submesh_count);
123 bone_pose.transforms.resize(bone_count);
126 std::for_each(entities.begin(),
130 auto&& [transform_comp, submesh_comp, bone_comp] =
131 e.try_get<transform_component, submesh_component, bone_component>();
134 const auto& transform_global = transform_comp->get_transform_global().get_matrix();
138 submesh_pose.transforms.emplace_back(transform_global);
143 auto bone_index = bone_comp->bone_index;
144 if(bone_index < bone_pose.transforms.size())
146 bone_pose.transforms[bone_index] = transform_global;
155auto model_component::create_armature(
bool force) ->
bool
157 bool has_processed_armature = !get_armature_entities().empty();
159 if(force || !has_processed_armature)
161 auto lod = model_.get_lod(0);
166 auto mesh = lod.get();
168 auto owner = get_owner();
170 std::vector<entt::handle> armature_entities;
171 if(process_armature(*mesh, owner, armature_entities, bind_pose_))
173 set_armature_entities(armature_entities);
175 const auto& skin_data = mesh->get_skin_bind_data();
177 if(skin_data.has_bones())
189auto model_component::update_armature() ->
bool
191 auto lod = model_.get_lod(0);
197 auto mesh = lod.get();
199 const auto& armature_entities = get_armature_entities();
202 auto bones_count = skin_data.get_bones().size();
205 get_transforms_for_entities(armature_entities, submeshes_count, submesh_pose_, bones_count, bone_pose_);
208 if(skin_data.has_bones())
211 skinning_pose_.resize(palettes.size());
212 for(
size_t i = 0; i < palettes.size(); ++i)
214 const auto& palette = palettes[i];
216 skinning_pose_[i].transforms = palette.get_skinning_matrices(bone_pose_.transforms, skin_data);
223auto model_component::init_armature(
bool force) ->
bool
225 auto lod = model_.get_lod(0);
231 auto mesh = lod.get();
235 bool recreate_armature =
force;
236 recreate_armature |= armature && submesh_pose_.transforms.empty();
237 recreate_armature |= skin_data.has_bones() && skinning_pose_.empty();
239 if(recreate_armature)
241 if(create_armature(
force))
243 return update_armature();
252 auto lod = model_.get_lod(0);
258 auto mesh = lod.get();
264 world_bounds_transform_ = world_transform;
268auto model_component::get_world_bounds() const -> const
math::bbox&
270 return world_bounds_;
273auto model_component::get_world_bounds_transform() const -> const
math::transform&
275 return world_bounds_transform_;
278auto model_component::get_local_bounds() const -> const
math::bbox&
280 auto lod = model_.get_lod(0);
286 auto mesh = lod.get();
295void model_component::set_last_render_frame(uint64_t
frame)
297 last_render_frame_ =
frame;
300auto model_component::get_last_render_frame() const noexcept -> uint64_t
302 return last_render_frame_;
305auto model_component::was_used_last_frame() const noexcept ->
bool
308 bool is_newly_created = last_render_frame_ == 0;
309 bool was_used_recently = current_frame - last_render_frame_ <= 1;
310 return is_newly_created || was_used_recently;
313auto model_component::is_skinned() const ->
bool
315 auto lod = model_.get_lod(0);
321 auto mesh = lod.get();
335void model_component::on_create_component(entt::registry& r, entt::entity e)
337 entt::handle
entity(r, e);
342 component.set_armature_entities({});
345void model_component::on_destroy_component(entt::registry& r, entt::entity e)
349void model_component::set_enabled(
bool enabled)
351 if(enabled_ == enabled)
361void model_component::set_casts_shadow(
bool cast_shadow)
363 if(casts_shadow_ == cast_shadow)
370 casts_shadow_ = cast_shadow;
373void model_component::set_static(
bool is_static)
375 if(static_ == is_static)
385void model_component::set_casts_reflection(
bool casts_reflection)
387 if(casts_reflection_ == casts_reflection)
394 casts_reflection_ = casts_reflection;
397auto model_component::is_enabled() const ->
bool
402auto model_component::casts_shadow() const ->
bool
404 return casts_shadow_;
407auto model_component::is_static() const ->
bool
412auto model_component::get_model() const -> const
model&
424auto model_component::casts_reflection() const ->
bool
426 return casts_reflection_;
429auto model_component::get_bone_transforms() const -> const
pose_mat4&
434auto model_component::get_skinning_transforms() const -> const
std::vector<
pose_mat4>&
436 return skinning_pose_;
439auto model_component::get_submesh_transforms() const -> const
pose_mat4&
441 return submesh_pose_;
444void model_component::set_armature_entities(
const std::vector<entt::handle>& entities)
446 armature_entities_ = entities;
451auto model_component::get_armature_entities() const -> const
std::vector<
entt::
handle>&
453 return armature_entities_;
456auto model_component::get_armature_by_id(
const std::string& node_id)
const -> entt::handle
458 for(
const auto& e : armature_entities_)
461 if(tag_comp.name == node_id)
470auto model_component::get_armature_index_by_id(
const std::string& node_id)
const ->
int
473 for(
const auto& e : armature_entities_)
476 if(tag_comp.name == node_id)
487auto model_component::get_armature_by_index(
size_t index)
const -> entt::handle
489 if(index >= armature_entities_.size())
494 return armature_entities_[index];
Main class representing a 3D mesh with support for different LODs, submeshes, and skinning.
auto get_bone_palettes() const -> const bone_palette_array_t &
Retrieves the compiled bone combination palette data if this mesh has been bound as a skin.
auto get_submeshes_count() const -> size_t
Gets the number of submeshes for this mesh.
auto get_bounds() const -> const math::bbox &
Gets the local bounding box for this mesh.
auto get_armature() const -> const std::unique_ptr< armature_node > &
Retrieves the armature tree of the mesh.
auto get_skin_bind_data() const -> const skin_bind_data &
Retrieves the skin bind data if this mesh has been bound as a skin.
auto get_skinned_submeshes_count() const -> size_t
Class that contains core data for meshes.
Structure describing a LOD group (set of meshes), LOD transitions, and their materials.
void set_owner(entt::handle owner)
Sets the owner of the component.
uint32_t get_render_frame()
bbox & mul(const transform &t)
Transforms an axis aligned bounding box by the specified matrix.
static bbox empty
An empty bounding box.
auto create_entity(const std::string &tag={}, entt::handle parent={}) -> entt::handle
Creates an entity in the scene with an optional tag and parent.
Component that provides a tag (name or label) for an entity.