Unravel Engine C++ Reference
Loading...
Searching...
No Matches
model.cpp
Go to the documentation of this file.
1#include "model.h"
2#include "gpu_program.h"
3#include "graphics/graphics.h"
4#include "material.h"
5#include "mesh.h"
6
7namespace unravel
8{
9bool model::is_valid() const
10{
11 return !mesh_lods_.empty();
12}
13
14auto model::get_lod(uint32_t lod) const -> asset_handle<mesh>
15{
16 if(mesh_lods_.size() > lod)
17 {
18 auto lodMesh = mesh_lods_[lod];
19 if(lodMesh)
20 {
21 return lodMesh;
22 }
23
24 for(unsigned int i = lod; i < mesh_lods_.size(); ++i)
25 {
26 auto lodMesh = mesh_lods_[i];
27 if(lodMesh)
28 {
29 return lodMesh;
30 }
31 }
32 for(unsigned int i = lod; i > 0; --i)
33 {
34 auto lodMesh = mesh_lods_[i];
35 if(lodMesh)
36 {
37 return lodMesh;
38 }
39 }
40 }
41 return {};
42}
43
45{
46 if(lod >= mesh_lods_.size())
47 {
48 mesh_lods_.resize(lod + 1);
49 recalulate_lod_limits();
50 }
51 mesh_lods_[lod] = mesh;
52
53 resize_materials(mesh);
54}
55
57{
58 if(index >= materials_.size())
59 {
60 materials_.resize(index + 1);
61 }
62
63 materials_[index] = std::move(material);
64}
65
67{
68 if(index >= material_instances_.size())
69 {
70 material_instances_.resize(index + 1, nullptr);
71 }
72
73 material_instances_[index] = std::move(material);
74}
75
76auto model::get_lods() const -> const std::vector<asset_handle<mesh>>&
77{
78 return mesh_lods_;
79}
80
81void model::set_lods(const std::vector<asset_handle<mesh>>& lods)
82{
83 auto sz1 = lods.size();
84 auto sz2 = mesh_lods_.size();
85
86 mesh_lods_ = lods;
87
88 if(sz1 != sz2)
89 {
90 recalulate_lod_limits();
91 }
92
93 if(!mesh_lods_.empty())
94 {
95 auto& mesh = mesh_lods_[0];
96 resize_materials(mesh);
97 }
98}
99
100auto model::get_materials() const -> const std::vector<asset_handle<material>>&
101{
102 return materials_;
103}
104
105auto model::get_material_instances() const -> const std::vector<material::sptr>&
106{
107 return material_instances_;
108}
109
110
111void model::set_materials(const std::vector<asset_handle<material>>& materials)
112{
113 materials_ = materials;
114}
115
116void model::set_material_instances(const std::vector<material::sptr>& materials)
117{
118 material_instances_ = materials;
119}
120
121auto model::get_material(uint32_t index) const -> asset_handle<material>
122{
123 if(materials_.size() <= index)
124 {
125 return {};
126 }
127
128 return materials_[index];
129}
130
131auto model::get_material_instance(uint32_t index) const -> material::sptr
132{
133 if(index < material_instances_.size())
134 {
135 auto instance = material_instances_[index];
136 if(instance)
137 {
138 return instance;
139 }
140 }
141
142 auto instance = get_material(index);
143 if(instance.is_valid())
144 {
145 return instance.get();
146 }
147
148 return nullptr;
149}
150
152{
153 if(index >= material_instances_.size())
154 {
155 auto asset_instance = get_material_instance(index);
156
157 material_instances_.resize(index + 1, nullptr);
158 material_instances_[index] = asset_instance->clone();
159 }
160
161 auto& instance = material_instances_[index];
162
163 if(!instance)
164 {
165 auto asset_instance = get_material_instance(index);
166
167 // if we already have an asset for that slot, promote it to instance
168 if(asset_instance)
169 {
170 instance = asset_instance->clone();
171 }
172 else
173 {
174 // create a new one
175 instance = std::make_shared<pbr_material>();
176 }
177 }
178
179 return instance;
180}
181
182
183auto model::get_lod_limits() const -> const std::vector<urange32_t>&
184{
185 return lod_limits_;
186}
187
188void model::set_lod_limits(const std::vector<urange32_t>& limits)
189{
190 lod_limits_ = limits;
191}
192
193void model::submit(const math::mat4& world_transform,
194 const pose_mat4& submesh_transforms,
195 const pose_mat4& bone_transforms,
196 const std::vector<pose_mat4>& skinning_matrices_per_palette,
197 unsigned int lod,
198 const submit_callbacks& callbacks) const
199{
200 const auto lod_mesh = get_lod(lod);
201 if(!lod_mesh)
202 {
203 return;
204 }
205
206 auto mesh = lod_mesh.get();
207
208 auto skinned_submeshes_count = mesh->get_skinned_submeshes_count();
209 auto non_skinned_submeshes_count = mesh->get_non_skinned_submeshes_count();
210
212
213 // NON SKINNED
214 if(non_skinned_submeshes_count > 0)
215 {
216 params.skinned = false;
217
218 if(callbacks.setup_begin)
219 {
220 callbacks.setup_begin(params);
221 }
222
223 if(callbacks.setup_params_per_instance)
224 {
225 callbacks.setup_params_per_instance(params);
226 }
227
228 auto render_submesh = [this](const std::shared_ptr<unravel::mesh>& mesh,
229 uint32_t group_id,
230 const math::mat4& matrix,
231 const pose_mat4& pose,
233 const submit_callbacks& callbacks)
234 {
235 auto mat = get_material_instance(group_id);
236 if(!mat)
237 {
238 return;
239 }
240
241 const auto& submeshes = mesh->get_submeshes();
242 const auto& indices = mesh->get_non_skinned_submeshes_indices(group_id);
243
244 for(const auto& index : indices)
245 {
246 const auto& submesh = submeshes[index];
247
248 if(index < pose.transforms.size())
249 {
250 const auto& world = pose.transforms[index];
252 }
253 else
254 {
256 }
257
259 params.preserve_state = &index != &indices.back();
260 callbacks.setup_params_per_submesh(params, *mat);
261 }
262 };
263
264 for(uint32_t i = 0; i < mesh->get_data_groups_count(); ++i)
265 {
266 render_submesh(mesh, i, world_transform, submesh_transforms, params, callbacks);
267 }
268
269 if(callbacks.setup_end)
270 {
271 callbacks.setup_end(params);
272 }
273 }
274
275 // SKINNED
276 if(skinned_submeshes_count > 0 && !skinning_matrices_per_palette.empty())
277 {
278 params.skinned = true;
279
280 if(callbacks.setup_begin)
281 {
282 callbacks.setup_begin(params);
283 }
284
285 if(callbacks.setup_params_per_instance)
286 {
287 callbacks.setup_params_per_instance(params);
288 }
289
290 auto render_submesh_skinned = [this](const std::shared_ptr<unravel::mesh>& mesh,
291 uint32_t group_id,
292 const std::vector<pose_mat4>& skinning_matrices_per_palette,
294 const submit_callbacks& callbacks)
295 {
296 auto mat = get_material_instance(group_id);
297 if(!mat)
298 {
299 return;
300 }
301
302 const auto& submeshes = mesh->get_submeshes();
303 const auto& indices = mesh->get_skinned_submeshes_indices(group_id);
304 const auto& palettes = mesh->get_bone_palettes();
305 const auto& skin_data = mesh->get_skin_bind_data();
306
307 for(const auto& index : indices)
308 {
309 const auto& submesh = submeshes[index];
310 const auto& skinning_matrices = skinning_matrices_per_palette[index];
311 gfx::set_world_transform(skinning_matrices.transforms);
312
314 params.preserve_state = &index != &indices.back();
315 callbacks.setup_params_per_submesh(params, *mat);
316 }
317 };
318
319 for(uint32_t i = 0; i < mesh->get_data_groups_count(); ++i)
320 {
321 render_submesh_skinned(mesh, i, skinning_matrices_per_palette, params, callbacks);
322 }
323
324 if(callbacks.setup_end)
325 {
326 callbacks.setup_end(params);
327 }
328 }
329}
330
331void model::recalulate_lod_limits()
332{
333 float upper_limit = 100.0f;
334 lod_limits_.clear();
335 lod_limits_.reserve(mesh_lods_.size());
336
337 float initial = 0.1f;
338 float step = initial / float(mesh_lods_.size());
339 for(size_t i = 0; i < mesh_lods_.size(); ++i)
340 {
341 float lower_limit = 0.0f;
342
343 if(mesh_lods_.size() - 1 != i)
344 {
345 lower_limit = upper_limit * (initial - ((i)*step));
346 }
347
348 lod_limits_.emplace_back(urange32_t::value_type(lower_limit), urange32_t::value_type(upper_limit));
349 upper_limit = lower_limit;
350 }
351}
352
353void model::resize_materials(const asset_handle<mesh>& mesh)
354{
355 const auto m = mesh.get();
356 auto submeshes = m->get_data_groups_count();
357 if(materials_.size() != submeshes)
358 {
359 materials_.resize(submeshes, default_material());
360 }
361}
362
364{
365 static asset_handle<material> asset;
366 return asset;
367}
368
370{
371 static asset_handle<material> asset;
372 return asset;
373}
374
375} // namespace unravel
Base class for materials used in rendering.
Definition material.h:32
std::shared_ptr< material > sptr
Definition material.h:36
Main class representing a 3D mesh with support for different LODs, submeshes, and skinning.
Definition mesh.h:310
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.
Definition mesh.cpp:1404
auto get_skinned_submeshes_indices(uint32_t data_group_id) const -> const submesh_array_indices_t &
Definition mesh.cpp:1478
auto get_non_skinned_submeshes_indices(uint32_t data_group_id) const -> const submesh_array_indices_t &
Definition mesh.cpp:1495
auto get_non_skinned_submeshes_count() const -> size_t
Definition mesh.cpp:1490
void bind_render_buffers_for_submesh(const submesh *submesh)
Binds the mesh data for rendering the selected batch of primitives.
Definition mesh.cpp:2811
auto get_skin_bind_data() const -> const skin_bind_data &
Retrieves the skin bind data if this mesh has been bound as a skin.
Definition mesh.cpp:1399
auto get_data_groups_count() const -> size_t
Gets the number of data groups(materials) for this mesh.
Definition mesh.cpp:1517
auto get_submeshes() const -> const submesh_array_t &
Retrieves information about the submesh of the mesh associated with the specified data group identifi...
Definition mesh.cpp:1443
auto get_skinned_submeshes_count() const -> size_t
Definition mesh.cpp:1473
auto get_material(uint32_t index) const -> asset_handle< material >
Gets the material for the specified index.
Definition model.cpp:121
void set_lod_limits(const std::vector< urange32_t > &limits)
Sets the LOD limits.
Definition model.cpp:188
auto get_lod(uint32_t lod) const -> asset_handle< mesh >
Gets the LOD (Level of Detail) mesh for the specified level.
Definition model.cpp:14
static auto fallback_material() -> asset_handle< material > &
Gets the fallback material.
Definition model.cpp:369
void set_material(asset_handle< material > material, uint32_t index)
Sets the material for the specified index.
Definition model.cpp:56
auto is_valid() const -> bool
Checks if the model is valid.
Definition model.cpp:9
auto get_lod_limits() const -> const std::vector< urange32_t > &
Gets the LOD limits.
Definition model.cpp:183
void set_materials(const std::vector< asset_handle< material > > &materials)
Sets the materials.
Definition model.cpp:111
void set_material_instances(const std::vector< material::sptr > &materials)
Definition model.cpp:116
static auto default_material() -> asset_handle< material > &
Gets the default material.
Definition model.cpp:363
void submit(const math::mat4 &world_transform, const pose_mat4 &submesh_transforms, const pose_mat4 &bone_transforms, const std::vector< pose_mat4 > &skinning_matrices, unsigned int lod, const submit_callbacks &callbacks) const
Submits the model for rendering.
Definition model.cpp:193
auto get_material_instance(uint32_t index) const -> material::sptr
Definition model.cpp:131
auto get_material_instances() const -> const std::vector< material::sptr > &
Definition model.cpp:105
void set_material_instance(material::sptr material, uint32_t index)
Definition model.cpp:66
void set_lods(const std::vector< asset_handle< mesh > > &lods)
Sets the LOD meshes.
Definition model.cpp:81
auto get_or_emplace_material_instance(uint32_t index) -> material::sptr
Definition model.cpp:151
void set_lod(asset_handle< mesh > mesh, uint32_t lod)
Sets the LOD (Level of Detail) mesh for the specified level.
Definition model.cpp:44
auto get_materials() const -> const std::vector< asset_handle< material > > &
Gets all the materials.
Definition model.cpp:100
auto get_lods() const -> const std::vector< asset_handle< mesh > > &
Gets all the LOD meshes.
Definition model.cpp:76
void set_world_transform(const void *_mtx, uint16_t _num)
Represents a handle to an asset, providing access and management functions.
auto get(bool wait=true) const -> std::shared_ptr< T >
Gets the shared pointer to the asset.
std::uint32_t value_type
Definition basetypes.hpp:11
Parameters for the submit callbacks.
Definition model.h:132
bool skinned
Indicates if the model is skinned.
Definition model.h:134
Callbacks for submitting the model for rendering.
Definition model.h:126
std::function< void(const params &info, const material &)> setup_params_per_submesh
Callback for setting up per submesh.
Definition model.h:143
std::function< void(const params &info)> setup_begin
Callback for setup begin.
Definition model.h:139
std::function< void(const params &info)> setup_params_per_instance
Callback for setting up per instance.
Definition model.h:141
std::function< void(const params &info)> setup_end
Callback for setup end.
Definition model.h:145