Unravel Engine C++ Reference
Loading...
Searching...
No Matches
defaults.cpp
Go to the documentation of this file.
1#include "defaults.h"
2
4
21
22#include <logging/logging.h>
23#include <string_utils/utils.h>
24#include <seq/seq.h>
25
26namespace unravel
27{
28
29namespace
30{
31
32void focus_camera_on_bounds(entt::handle camera, const math::bsphere& bounds)
33{
34 auto& trans_comp = camera.get<transform_component>();
35 auto& camera_comp = camera.get<camera_component>();
36 const auto& cam = camera_comp.get_camera();
37
38 math::vec3 cen = bounds.position;
39
40 float aspect = cam.get_aspect_ratio();
41 float fov = cam.get_fov();
42 // Get the radius of a sphere circumscribing the bounds
43 float radius = bounds.radius;
44 // Get the horizontal FOV, since it may be the limiting of the two FOVs to properly
45 // encapsulate the objects
46 float hfov = math::degrees(2.0f * math::atan(math::tan(math::radians(fov) / 2.0f) * aspect));
47 // Use the smaller FOV as it limits what would get cut off by the frustum
48 float mfov = math::min(fov, hfov);
49 float dist = radius / (math::sin(math::radians(mfov) / 2.0f));
50
51 trans_comp.look_at(cen);
52 trans_comp.set_position_global(cen - dist * trans_comp.get_z_axis_global());
53 camera_comp.set_ortho_size(radius);
54 camera_comp.update(trans_comp.get_transform_global());
55}
56
57void focus_camera_on_bounds(entt::handle camera, const math::bbox& bounds)
58{
59 auto& trans_comp = camera.get<transform_component>();
60 auto& camera_comp = camera.get<camera_component>();
61 const auto& cam = camera_comp.get_camera();
62
63 math::vec3 cen = bounds.get_center();
64 math::vec3 size = bounds.get_dimensions();
65
66 float aspect = cam.get_aspect_ratio();
67 float fov = cam.get_fov();
68 // Get the radius of a sphere circumscribing the bounds
69 float radius = math::length(size) / 2.0f;
70 // Get the horizontal FOV, since it may be the limiting of the two FOVs to properly
71 // encapsulate the objects
72 float horizontal_fov = math::degrees(2.0f * math::atan(math::tan(math::radians(fov) / 2.0f) * aspect));
73 // Use the smaller FOV as it limits what would get cut off by the frustum
74 float mfov = math::min(fov, horizontal_fov);
75 float dist = radius / (math::sin(math::radians(mfov) / 2.0f));
76
77 trans_comp.look_at(cen);
78 trans_comp.set_position_global(cen - dist * trans_comp.get_z_axis_global());
79 camera_comp.set_ortho_size(radius);
80 camera_comp.update(trans_comp.get_transform_global());
81}
82
83// Add a shared helper to drive the timed camera focus transition
84void run_camera_focus_transition(entt::handle camera,
85 const math::vec3& target_center,
86 float radius,
87 bool keep_rotation,
88 float duration)
89{
90 if(duration <= 0.0f || !camera.all_of<transform_component, camera_component>())
91 {
92 math::bsphere bs{};
93 bs.position = target_center;
94 bs.radius = radius;
95 ::unravel::focus_camera_on_bounds(camera, bs);
96 return;
97 }
98
99 auto& trans_comp = camera.get<transform_component>();
100 auto& camera_comp = camera.get<camera_component>();
101 const auto& cam = camera_comp.get_camera();
102
103 float aspect = cam.get_aspect_ratio();
104 float fov = cam.get_fov();
105 float horizontal_fov = math::degrees(2.0f * math::atan(math::tan(math::radians(fov) / 2.0f) * aspect));
106 float mfov = math::min(fov, horizontal_fov);
107 float target_distance = radius / (math::sin(math::radians(mfov) / 2.0f));
108
109 math::vec3 start_position = trans_comp.get_position_global();
110 float start_ortho_size = camera_comp.get_ortho_size();
111
112 // Calculate initial target position to check proximity
113 math::vec3 initial_target_position{};
114 if(keep_rotation)
115 {
116 // Keep camera rotation unchanged: move along current forward (Z axis) so center is on view axis
117 math::vec3 forward = math::normalize(trans_comp.get_z_axis_global());
118 if(math::length(forward) < 0.001f)
119 {
120 forward = math::vec3{0.0f, 0.0f, -1.0f};
121 }
122 initial_target_position = target_center - target_distance * forward;
123 }
124 else
125 {
126 // Point camera towards the center using current position direction
127 math::vec3 dir = math::normalize(target_center - start_position);
128 if(math::length(dir) < 0.001f)
129 {
130 dir = math::vec3{0.0f, 0.0f, -1.0f};
131 }
132 initial_target_position = target_center - target_distance * dir;
133 }
134
135 // Check if we're already very close to the calculated target position
136 float distance_to_target = math::length(start_position - initial_target_position);
137 float proximity_threshold = target_distance * 0.15f; // 15% of target distance
138
139 // If we're very close, back away to provide a wider view before focusing
140 float adjusted_target_distance = target_distance;
141 if(distance_to_target < proximity_threshold)
142 {
143 // Increase distance by 50% to back away and provide wider view
144 adjusted_target_distance = target_distance * 3.0f;
145 }
146
147 // Calculate final target position with adjusted distance
148 math::vec3 target_position{};
149 if(keep_rotation)
150 {
151 math::vec3 forward = math::normalize(trans_comp.get_z_axis_global());
152 if(math::length(forward) < 0.001f)
153 {
154 forward = math::vec3{0.0f, 0.0f, -1.0f};
155 }
156 target_position = target_center - adjusted_target_distance * forward;
157 }
158 else
159 {
160 math::vec3 dir = math::normalize(target_center - start_position);
161 if(math::length(dir) < 0.001f)
162 {
163 dir = math::vec3{0.0f, 0.0f, -1.0f};
164 }
165 target_position = target_center - adjusted_target_distance * dir;
166 }
167
168 auto ease = seq::ease::smooth_stop;
169 auto seq_duration = std::chrono::duration_cast<seq::duration_t>(std::chrono::duration<float>(duration));
170
171 struct camera_transition_state
172 {
173 math::vec3 current_position;
174 float current_ortho_size;
175 };
176
177 auto state = std::make_shared<camera_transition_state>();
178 state->current_position = start_position;
179 state->current_ortho_size = start_ortho_size;
180
181 auto position_action = seq::change_to(state->current_position, target_position, seq_duration, state, ease);
182 auto ortho_action = seq::change_to(state->current_ortho_size, radius, seq_duration, state, ease);
183
184 auto combined_action = seq::together(position_action, ortho_action);
185 combined_action.on_update.connect([camera, state, keep_rotation, target_center]()
186 {
187 if(camera.valid())
188 {
189 auto& tc = camera.get<transform_component>();
190 auto& cc = camera.get<camera_component>();
191 tc.set_position_global(state->current_position);
192 if(!keep_rotation)
193 {
194 tc.look_at(target_center);
195 }
196 cc.set_ortho_size(state->current_ortho_size);
197 cc.update(tc.get_transform_global());
198 }
199 });
200
201 seq::scope::stop_all("camera_focus");
202 seq::start(combined_action, "camera_focus");
203}
204
205void focus_camera_on_bounds(entt::handle camera, const math::bsphere& bounds, float duration)
206{
207 run_camera_focus_transition(camera, bounds.position, bounds.radius, /*keep_rotation=*/true, duration);
208}
209
210void focus_camera_on_bounds(entt::handle camera, const math::bbox& bounds, float duration)
211{
212 const math::vec3 center = bounds.get_center();
213 const float radius = math::length(bounds.get_dimensions()) / 2.0f;
214 run_camera_focus_transition(camera, center, radius, /*keep_rotation=*/true, duration);
215}
216
217// Private recursive helper; never emits the 1-unit fallback
218void calc_bounds_global_impl(math::bbox& bounds, entt::handle entity, int depth)
219{
220 auto& tc = entity.get<transform_component>();
221 const auto world_xform = tc.get_transform_global();
222
223 // include this entity's own model AABB if it has one
224 if(auto* mc = entity.try_get<model_component>())
225 {
226 mc->update_world_bounds(world_xform);
227 auto b = mc->get_world_bounds();
228 for(const auto& corner : b.get_corners())
229 {
230 bounds.add_point(corner);
231 }
232 }
233
234 if(auto* tc = entity.try_get<text_component>())
235 {
236 auto b = tc->get_render_bounds();
237 for(const auto& corner : b.get_corners())
238 {
239 bounds.add_point(world_xform.transform_coord(corner));
240 }
241 }
242
243 // recurse into children
244 if(depth != 0) // depth<0 means infinite
245 {
246 for(auto child : tc.get_children())
247 {
248 calc_bounds_global_impl(bounds, child, depth > 0 ? depth - 1 : -1);
249 }
250 }
251}
252} // namespace
253
255{
256 APPLOG_TRACE("{}::{}", hpp::type_name_str<defaults>(), __func__);
257
258 return init_assets(ctx);
259}
260
262{
263 APPLOG_TRACE("{}::{}", hpp::type_name_str<defaults>(), __func__);
264
265 {
266 // 100
267 font::default_thin() = {};
268 // 200
270 // 300
271 font::default_light() = {};
272 // 400
274 // 500
276 // 600
278 // 700
279 font::default_bold() = {};
280 // 800
281 font::default_heavy() = {};
282 // 900
283 font::default_black() = {};
284 }
287 return true;
288}
289
291{
292 auto& manager = ctx.get_cached<asset_manager>();
293 {
294 const auto id = "engine:/embedded/cube";
295 auto instance = std::make_shared<mesh>();
296 instance->create_cube(gfx::mesh_vertex::get_layout(), 1.0f, 1.0f, 1.0f, 1, 1, 1, mesh_create_origin::center);
297 manager.get_asset_from_instance(id, instance);
298 }
299 {
300 const auto id = "engine:/embedded/cube_rounded";
301 auto instance = std::make_shared<mesh>();
302 instance->create_rounded_cube(gfx::mesh_vertex::get_layout(), 1.0f, 1.0f, 1.0f, 1, 1, 1, mesh_create_origin::center);
303 manager.get_asset_from_instance(id, instance);
304 }
305 {
306 const auto id = "engine:/embedded/sphere";
307 auto instance = std::make_shared<mesh>();
308 instance->create_sphere(gfx::mesh_vertex::get_layout(), 0.5f, 20, 20, mesh_create_origin::center);
309 manager.get_asset_from_instance(id, instance);
310 }
311 {
312 const auto id = "engine:/embedded/plane";
313 auto instance = std::make_shared<mesh>();
314 instance->create_plane(gfx::mesh_vertex::get_layout(), 10.0f, 10.0f, 1, 1, mesh_create_origin::center);
315 manager.get_asset_from_instance(id, instance);
316 }
317 {
318 const auto id = "engine:/embedded/cylinder";
319 auto instance = std::make_shared<mesh>();
320 instance->create_cylinder(gfx::mesh_vertex::get_layout(), 0.5f, 2.0f, 20, 20, mesh_create_origin::center);
321 manager.get_asset_from_instance(id, instance);
322 }
323 {
324 const auto id = "engine:/embedded/capsule_2m";
325 auto instance = std::make_shared<mesh>();
326 instance->create_capsule(gfx::mesh_vertex::get_layout(), 0.5f, 2.0f, 20, 20, mesh_create_origin::center);
327 manager.get_asset_from_instance(id, instance);
328 }
329 {
330 const auto id = "engine:/embedded/capsule_1m";
331 auto instance = std::make_shared<mesh>();
332 instance->create_capsule(gfx::mesh_vertex::get_layout(), 0.5f, 1.0f, 20, 20, mesh_create_origin::center);
333 manager.get_asset_from_instance(id, instance);
334 }
335 {
336 const auto id = "engine:/embedded/cone";
337 auto instance = std::make_shared<mesh>();
338 instance->create_cone(gfx::mesh_vertex::get_layout(), 0.5f, 0.0f, 2, 20, 20, mesh_create_origin::bottom);
339 manager.get_asset_from_instance(id, instance);
340 }
341 {
342 const auto id = "engine:/embedded/torus";
343 auto instance = std::make_shared<mesh>();
344 instance->create_torus(gfx::mesh_vertex::get_layout(), 1.0f, 0.5f, 20, 20, mesh_create_origin::center);
345 manager.get_asset_from_instance(id, instance);
346 }
347 {
348 const auto id = "engine:/embedded/teapot";
349 auto instance = std::make_shared<mesh>();
350 instance->create_teapot(gfx::mesh_vertex::get_layout());
351 manager.get_asset_from_instance(id, instance);
352 }
353 {
354 const auto id = "engine:/embedded/icosahedron";
355 auto instance = std::make_shared<mesh>();
356 instance->create_icosahedron(gfx::mesh_vertex::get_layout());
357 manager.get_asset_from_instance(id, instance);
358 }
359 {
360 const auto id = "engine:/embedded/dodecahedron";
361 auto instance = std::make_shared<mesh>();
362 instance->create_dodecahedron(gfx::mesh_vertex::get_layout());
363 manager.get_asset_from_instance(id, instance);
364 }
365
366 for(int i = 0; i < 20; ++i)
367 {
368 const auto id = std::string("engine:/embedded/icosphere") + std::to_string(i);
369 auto instance = std::make_shared<mesh>();
370 instance->create_icosphere(gfx::mesh_vertex::get_layout(), i);
371 manager.get_asset_from_instance(id, instance);
372 }
373
374 {
375 // 100
376 font::default_thin() = manager.get_asset<font>("engine:/data/fonts/Inter/static/Inter-Thin.ttf");
377 // 200
378 font::default_extra_light() = manager.get_asset<font>("engine:/data/fonts/Inter/static/Inter-ExtraLight.ttf");
379 // 300
380 font::default_light() = manager.get_asset<font>("engine:/data/fonts/Inter/static/Inter-Light.ttf");
381 // 400
382 font::default_regular() = manager.get_asset<font>("engine:/data/fonts/Inter/static/Inter-Regular.ttf");
383 // 500
384 font::default_medium() = manager.get_asset<font>("engine:/data/fonts/Inter/static/Inter-Medium.ttf");
385 // 600
386 font::default_semi_bold() = manager.get_asset<font>("engine:/data/fonts/Inter/static/Inter-SemiBold.ttf");
387 // 700
388 font::default_bold() = manager.get_asset<font>("engine:/data/fonts/Inter/static/Inter-Bold.ttf");
389 // 800
390 font::default_heavy() = manager.get_asset<font>("engine:/data/fonts/Inter/static/Inter-ExtraBold.ttf");
391 // 900
392 font::default_black() = manager.get_asset<font>("engine:/data/fonts/Inter/static/Inter-Black.ttf");
393
394 }
395
396 {
397 material::default_color_map() = manager.get_asset<gfx::texture>("engine:/data/textures/default_color.dds");
398 material::default_normal_map() = manager.get_asset<gfx::texture>("engine:/data/textures/default_normal.dds");
399 }
400 {
401 const auto id = "engine:/embedded/standard";
402 auto instance = std::make_shared<pbr_material>();
403 auto asset = manager.get_asset_from_instance<material>(id, instance);
404
405 model::default_material() = asset;
406 }
407
408 {
409 const auto id = "engine:/embedded/fallback";
410 auto instance = std::make_shared<pbr_material>();
411 instance->set_emissive_color(math::color::purple());
412 instance->set_base_color(math::color::purple());
413 instance->set_roughness(1.0f);
414 auto asset = manager.get_asset_from_instance<material>(id, instance);
415
416 model::fallback_material() = asset;
417 }
418
419 return true;
420}
421
422auto defaults::create_embedded_mesh_entity(rtti::context& ctx, scene& scn, const std::string& name) -> entt::handle
423{
424 auto& am = ctx.get_cached<asset_manager>();
425 const auto id = "engine:/embedded/" + string_utils::replace(string_utils::to_lower(name), " ", "_");
426
427 auto lod = am.get_asset<mesh>(id);
428 model model;
429 model.set_lod(lod, 0);
430 model.set_material(am.get_asset<material>("engine:/embedded/standard"), 0);
431 auto object = scn.create_entity(name);
432
433 auto& transf_comp = object.get_or_emplace<transform_component>();
434
435 auto bounds = lod.get()->get_bounds();
436 transf_comp.set_position_local({0.0f, bounds.get_extents().y, 0.0f});
437
438 auto& model_comp = object.get_or_emplace<model_component>();
439 model_comp.set_casts_shadow(true);
440 model_comp.set_casts_reflection(false);
441 model_comp.set_model(model);
442
443 return object;
444}
445
446auto defaults::create_prefab_at(rtti::context& ctx, scene& scn, const std::string& key) -> entt::handle
447{
448 auto& am = ctx.get_cached<asset_manager>();
449 auto asset = am.get_asset<prefab>(key);
450
451 auto object = scn.instantiate(asset);
452 return object;
453}
454
455auto defaults::create_prefab_at(rtti::context& ctx, scene& scn, const std::string& key, math::vec3 pos) -> entt::handle
456{
457 auto& am = ctx.get_cached<asset_manager>();
458 auto asset = am.get_asset<prefab>(key);
459
460 auto object = scn.instantiate(asset);
461
462 auto& trans_comp = object.get<transform_component>();
463 trans_comp.set_position_global(pos);
464
465 return object;
466}
467
469 scene& scn,
470 const std::string& key,
471 const camera& cam,
472 math::vec2 pos) -> entt::handle
473{
474 math::vec3 projected_pos{0.0f, 0.0f, 0.0f};
475 cam.viewport_to_world(pos,
476 math::plane::from_point_normal(math::vec3{0.0f, 0.0f, 0.0f}, math::vec3{0.0f, 1.0f, 0.0f}),
477 projected_pos,
478 false);
479
480 return create_prefab_at(ctx, scn, key, projected_pos);
481}
482
483auto defaults::create_mesh_entity_at(rtti::context& ctx, scene& scn, const std::string& key, math::vec3 pos)
484 -> entt::handle
485{
486 auto& am = ctx.get_cached<asset_manager>();
487 auto asset = am.get_asset<mesh>(key);
488
489 model mdl;
490 mdl.set_lod(asset, 0);
491
492 std::string name = fs::path(key).stem().string();
493 auto object = scn.create_entity(name);
494
495 // Add component and configure it.
496 auto& model_comp = object.emplace<model_component>();
497 model_comp.set_casts_shadow(true);
498 model_comp.set_casts_reflection(false);
499 model_comp.set_model(mdl);
500
501 auto& trans_comp = object.get<transform_component>();
502 trans_comp.set_position_global(pos);
503
504 if(model_comp.is_skinned())
505 {
506 object.emplace<animation_component>();
507 }
508
509 return object;
510}
511
513 scene& scn,
514 const std::string& key,
515 const camera& cam,
516 math::vec2 pos) -> entt::handle
517{
518 math::vec3 projected_pos{0.0f, 0.0f, 0.0f};
519 cam.viewport_to_world(pos,
520 math::plane::from_point_normal(math::vec3{0.0f, 0.0f, 0.0f}, math::vec3{0.0f, 1.0f, 0.0f}),
521 projected_pos,
522 false);
523
524 return create_mesh_entity_at(ctx, scn, key, projected_pos);
525}
526
528 -> entt::handle
529{
530 auto& am = ctx.get_cached<asset_manager>();
531
532 auto object = scn.create_entity(name + " Light");
533
534 auto& transf_comp = object.get_or_emplace<transform_component>();
535 transf_comp.set_position_local({0.0f, 1.0f, 0.0f});
536
538 {
539 transf_comp.rotate_by_euler_local({50.0f, -30.0f + 180.0f, 0.0f});
540 }
541
542
543 light light_data;
544 light_data.color = math::color(255, 244, 214, 255);
545 light_data.type = type;
546
548 {
549 light_data.ambient_intensity = 0.05f;
550 }
551
552
553 auto& light_comp = object.get_or_emplace<light_component>();
554 light_comp.set_light(light_data);
555
556 return object;
557}
558
560 -> entt::handle
561{
562 auto& am = ctx.get_cached<asset_manager>();
563
564 auto object = scn.create_entity(name + " Probe");
565
566 auto& transf_comp = object.get_or_emplace<transform_component>();
567 transf_comp.set_position_local({0.0f, 0.1f, 0.0f});
568
569 reflection_probe probe;
571 probe.type = type;
572
573 auto& reflection_comp = object.get_or_emplace<reflection_probe_component>();
574 reflection_comp.set_probe(probe);
575
576 object.emplace<tonemapping_component>();
577
578 return object;
579}
580
581auto defaults::create_camera_entity(rtti::context& ctx, scene& scn, const std::string& name) -> entt::handle
582{
583 auto object = scn.create_entity(name);
584
585 auto& transf_comp = object.get_or_emplace<transform_component>();
586 transf_comp.set_position_local({0.0f, 1.0f, -10.0f});
587
588 object.emplace<camera_component>();
589 object.emplace<assao_component>();
590 object.emplace<tonemapping_component>();
591 object.emplace<fxaa_component>();
592 object.emplace<ssr_component>();
593
594 return object;
595}
596
597auto defaults::create_ui_document_entity(rtti::context& ctx, scene& scn, const std::string& name) -> entt::handle
598{
599 auto object = scn.create_entity(name);
600 object.emplace<ui_document_component>();
601 return object;
602}
603
604auto defaults::create_text_entity(rtti::context& ctx, scene& scn, const std::string& name) -> entt::handle
605{
606 auto object = scn.create_entity(name);
607
608 auto& text = object.emplace<text_component>();
609 text.set_text("Hello World!");
610
611 return object;
612}
613
614
616{
617 auto camera = create_camera_entity(ctx, scn, "Main Camera");
619
620 {
621 auto object = create_light_entity(ctx, scn, light_type::directional, "Sky & Directional");
622 object.emplace<skylight_component>();
623 }
624
625 {
626 auto object = create_reflection_probe_entity(ctx, scn, probe_type::sphere, "Envinroment");
627 auto& reflection_comp = object.get_or_emplace<reflection_probe_component>();
628 auto probe = reflection_comp.get_probe();
629 probe.method = reflect_method::environment;
630 probe.sphere_data.range = 1000.0f;
631 reflection_comp.set_probe(probe);
632 }
633}
634
636{
637 {
638 auto object = create_light_entity(ctx, scn, light_type::directional, "Sky & Directional");
639 object.emplace<skylight_component>();
640 }
641
642 {
643 auto object = create_reflection_probe_entity(ctx, scn, probe_type::sphere, "Envinroment");
644 auto& reflection_comp = object.get_or_emplace<reflection_probe_component>();
645 auto probe = reflection_comp.get_probe();
646 probe.method = reflect_method::environment;
647 probe.sphere_data.range = 1000.0f;
648 reflection_comp.set_probe(probe);
649 }
650
651}
652
653auto defaults::create_default_3d_scene_for_preview(rtti::context& ctx, scene& scn, const usize32_t& size)
654 -> entt::handle
655{
656 auto camera = create_camera_entity(ctx, scn, "Main Camera");
657 {
658 auto assao_comp = camera.try_get<assao_component>();
659 if(assao_comp)
660 {
661 assao_comp->enabled = false;
662 }
663
664 auto ssr_comp = camera.try_get<ssr_component>();
665 if(ssr_comp)
666 {
667 ssr_comp->enabled = false;
668 }
669 }
670
671 {
672 auto& transf_comp = camera.get<transform_component>();
673 transf_comp.set_position_local({10.0f, 6.6f, 10.0f});
674 transf_comp.rotate_by_euler_local({0.0f, 180.0f, 0.0f});
675 auto& camera_comp = camera.get<camera_component>();
676 camera_comp.set_viewport_size(size);
677 }
678
679 {
680 auto object = create_light_entity(ctx, scn, light_type::directional, "Sky & Directional");
681
682 auto& light_comp = object.get_or_emplace<light_component>();
683 auto light = light_comp.get_light();
684 light.casts_shadows = false;
685 light_comp.set_light(light);
686
687 object.emplace<skylight_component>();
688 }
689
690 {
691 auto object = create_reflection_probe_entity(ctx, scn, probe_type::sphere, "Envinroment");
692 auto& reflection_comp = object.get_or_emplace<reflection_probe_component>();
693 auto probe = reflection_comp.get_probe();
694 probe.method = reflect_method::environment;
695 probe.sphere_data.range = 1000.0f;
696 reflection_comp.set_probe(probe);
697 }
698
699 return camera;
700}
701
702template<>
704 scene& scn,
705 const asset_handle<material>& asset,
706 const usize32_t& size)
707{
708 auto camera = create_default_3d_scene_for_preview(ctx, scn, size);
709
710 {
711 auto object = create_embedded_mesh_entity(ctx, scn, "Sphere");
712 auto& model_comp = object.get<model_component>();
713 auto model = model_comp.get_model();
714 model.set_material(asset, 0);
715 model_comp.set_model(model);
716 model_comp.set_casts_shadow(false);
717 model_comp.set_casts_reflection(false);
718
719 ::unravel::focus_camera_on_bounds(camera, calc_bounds_sphere_global(object, false));
720 }
721}
722
723template<>
725 scene& scn,
726 const asset_handle<prefab>& asset,
727 const usize32_t& size)
728{
729 auto camera = create_default_3d_scene_for_preview(ctx, scn, size);
730
731 {
732 auto object = scn.instantiate(asset);
733
734 if(object)
735 {
736 if(auto model_comp = object.try_get<model_component>())
737 {
738 model_comp->set_casts_shadow(false);
739 model_comp->set_casts_reflection(false);
740 }
741
742 auto bounds = calc_bounds_sphere_global(object);
743 if(bounds.radius < 1.0f)
744 {
745 float scale = 1.0f / bounds.radius;
746 object.get<transform_component>().scale_by_local(math::vec3(scale));
747 }
748
749 ::unravel::focus_camera_on_bounds(camera, calc_bounds_sphere_global(object));
750 }
751 }
752}
753
754template<>
756 scene& scn,
757 const asset_handle<mesh>& asset,
758 const usize32_t& size)
759{
760 auto camera = create_default_3d_scene_for_preview(ctx, scn, size);
761
762 {
763 auto object = create_mesh_entity_at(ctx, scn, asset.id());
764
765 if(auto model_comp = object.try_get<model_component>())
766 {
767 model_comp->set_casts_shadow(false);
768 model_comp->set_casts_reflection(false);
769 }
770
771 auto bounds = calc_bounds_sphere_global(object);
772 if(bounds.radius < 1.0f)
773 {
774 float scale = 1.0f / bounds.radius;
775 object.get<transform_component>().scale_by_local(math::vec3(scale));
776 }
777
778 ::unravel::focus_camera_on_bounds(camera, calc_bounds_sphere_global(object));
779 }
780}
781
782
783void defaults::focus_camera_on_entities(entt::handle camera, const std::vector<entt::handle>& entities)
784{
786 {
787 math::bbox bounds;
788
789 bool valid = false;
790 for(const auto& entity : entities)
791 {
792 if(!entity.valid())
793 {
794 return;
795 }
796 auto ebounds = calc_bounds_global(entity);
797 bounds.add_point(ebounds.min);
798 bounds.add_point(ebounds.max);
799
800 valid = true;
801 }
802 if(valid)
803 {
804 ::unravel::focus_camera_on_bounds(camera, bounds);
805 }
806 }
807}
808
810 const std::vector<entt::handle>& entities,
811 float duration)
812{
814 {
815 math::bbox bounds;
816
817 bool valid = false;
818 for(const auto& entity : entities)
819 {
820 if(!entity.valid())
821 {
822 return;
823 }
824 auto ebounds = calc_bounds_global(entity);
825 bounds.add_point(ebounds.min);
826 bounds.add_point(ebounds.max);
827
828 valid = true;
829 }
830 if(valid)
831 {
832 ::unravel::focus_camera_on_bounds(camera, bounds, duration);
833 }
834 }
835}
836
837auto defaults::calc_bounds_global(entt::handle entity, int depth) -> math::bbox
838{
839 // 1) Get the “true” union of all models (possibly empty)
840 math::bbox bounds;
841 calc_bounds_global_impl(bounds, entity, depth);
842
843 // 2) If nothing was found, fall back *once* here to a unit cube
844 if(!bounds.is_populated())
845 {
846 const math::vec3 one{1, 1, 1};
847 const auto pos = entity.get<transform_component>().get_position_global();
848 bounds = math::bbox{pos - one, pos + one};
849 }
850
851 return bounds;
852}
853
854auto defaults::calc_bounds_sphere_global(entt::handle entity, bool use_bbox_diagonal) -> math::bsphere
855{
856 auto box = calc_bounds_global(entity);
857 math::bsphere result;
858 result.position = box.get_center();
859
860 // 2) radius is half the diagonal length
861 math::vec3 diag = box.get_dimensions();
862 float max_abs = math::max(math::abs(diag.x), math::max(math::abs(diag.y), math::abs(diag.z)));
863 float radius = 0.5f * (use_bbox_diagonal ? math::length(diag) : max_abs);
864 result.radius = radius;
865
866 return result;
867}
868} // namespace unravel
entt::handle b
manifold_type type
const btCollisionObject * object
Provides storage for common representation of spherical bounding volume, and wraps up common function...
Definition bsphere.h:18
float radius
Definition bsphere.h:120
vec3 position
Definition bsphere.h:119
Manages assets, including loading, unloading, and storage.
auto get_asset(const std::string &key, load_flags flags=load_flags::standard) -> asset_handle< T >
Gets an asset by its key.
Class that contains core data for audio listeners. There can only be one instance of it per scene.
Class that contains core camera data, used for rendering and other purposes.
Class representing a camera. Contains functionality for manipulating and updating a camera....
Definition camera.h:35
Class that contains core light data, used for rendering and other purposes.
void set_light(const light &l)
Sets the light object.
Base class for materials used in rendering.
Definition material.h:32
static auto default_normal_map() -> asset_handle< gfx::texture > &
Gets the default normal map.
Definition material.cpp:21
static auto default_color_map() -> asset_handle< gfx::texture > &
Gets the default color map.
Definition material.cpp:15
Main class representing a 3D mesh with support for different LODs, submeshes, and skinning.
Definition mesh.h:310
Class that contains core data for meshes.
void set_casts_shadow(bool cast_shadow)
Sets whether the model casts shadows.
Structure describing a LOD group (set of meshes), LOD transitions, and their materials.
Definition model.h:42
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
static auto default_material() -> asset_handle< material > &
Gets the default material.
Definition model.cpp:363
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
Class that contains core reflection probe data, used for rendering and other purposes.
auto get_probe() const -> const reflection_probe &
Gets the reflection probe object.
void set_probe(const reflection_probe &probe)
Sets the reflection probe object.
Class that contains sky light data.
void set_text(const std::string &text)
Sets the text content to be rendered.
Component that handles transformations (position, rotation, scale, etc.) in the ACE framework.
void set_position_local(const math::vec3 &position) noexcept
Sets the local position.
void set_position_global(const math::vec3 &position) noexcept
Sets the global position.
float scale
Definition hub.cpp:25
std::string name
Definition hub.cpp:27
#define APPLOG_TRACE(...)
Definition logging.h:17
float smooth_stop(float progress)
Modelled after quarter-cycle of sine wave (different phase)
Definition seq_ease.cpp:304
void stop_all(const std::string &scope)
Stops all actions within the specified scope.
Definition seq.cpp:154
auto start(seq_action action, const seq_scope_policy &scope_policy, hpp::source_location location) -> seq_id_t
Starts a new action.
Definition seq.cpp:8
auto together(const std::vector< seq_action > &actions, const sentinel_t &sentinel) -> seq_action
Creates a simultaneous action that executes a list of actions together.
Definition seq_core.cpp:109
auto change_to(T &object, const std::decay_t< T > &end, const duration_t &duration, const sentinel_t &sentinel, const ease_t &ease_func=ease::linear) -> seq_action
Creates an action to change an object to a specified value over a specified duration.
Definition seq_core.hpp:76
auto replace(const std::string &str, const std::string &search, const std::string &replace) -> std::string
Definition utils.cpp:28
auto to_lower(const std::string &str) -> std::string
Definition utils.cpp:42
probe_type
Enum class representing the type of reflection probe.
@ sphere
Sphere type reflection probe.
@ box
Box type reflection probe.
light_type
Enum representing the type of light.
Definition light.h:14
@ environment
Environment reflection method.
@ static_only
Static-only reflection method.
entt::entity entity
Represents a handle to an asset, providing access and management functions.
auto id() const -> const std::string &
Gets the string identifier of the asset.
static auto get_layout() -> const vertex_layout &
Definition vertex_decl.h:15
Storage for box vector values and wraps up common functionality.
Definition bbox.h:21
bbox & add_point(const vec3 &point)
Grows the bounding box based on the point passed.
Definition bbox.cpp:924
bool is_populated() const
Checks if the bounding box is populated.
Definition bbox.cpp:36
vec3 get_dimensions() const
Returns a vector containing the dimensions of the bounding box.
Definition bbox.cpp:941
vec3 get_center() const
Returns a vector containing the exact center point of the box.
Definition bbox.cpp:946
static color purple()
Definition math.h:307
static auto from_point_normal(const vec3 &point, const vec3 &normal) -> plane
Creates a plane from a point and a normal.
Definition plane.cpp:20
static auto create_reflection_probe_entity(rtti::context &ctx, scene &scn, probe_type type, const std::string &name) -> entt::handle
Creates a reflection probe entity.
Definition defaults.cpp:559
static auto init_assets(rtti::context &ctx) -> bool
Initializes default assets.
Definition defaults.cpp:290
static auto init(rtti::context &ctx) -> bool
Initializes default settings and assets.
Definition defaults.cpp:254
static auto create_ui_document_entity(rtti::context &ctx, scene &scn, const std::string &name) -> entt::handle
Creates a UI document entity.
Definition defaults.cpp:597
static void focus_camera_on_entities(entt::handle camera, const std::vector< entt::handle > &entities)
Focuses a camera on a specified entity.
Definition defaults.cpp:783
static auto create_text_entity(rtti::context &ctx, scene &scn, const std::string &name) -> entt::handle
Creates a text entity.
Definition defaults.cpp:604
static void create_default_3d_scene_for_asset_preview(rtti::context &ctx, scene &scn, const asset_handle< T > &asset, const usize32_t &size)
Creates a default 3D scene for asset preview.
static auto create_embedded_mesh_entity(rtti::context &ctx, scene &scn, const std::string &name) -> entt::handle
Creates an embedded mesh entity.
Definition defaults.cpp:422
static auto calc_bounds_sphere_global(entt::handle entity, bool use_bbox_diagonal=true) -> math::bsphere
Calculates the bounding sphere of an entity.
Definition defaults.cpp:854
static auto calc_bounds_global(entt::handle entity, int depth=-1) -> math::bbox
Calculates the bounding box of an entity.
Definition defaults.cpp:837
static auto create_light_entity(rtti::context &ctx, scene &scn, light_type type, const std::string &name) -> entt::handle
Creates a light entity.
Definition defaults.cpp:527
static auto create_prefab_at(rtti::context &ctx, scene &scn, const std::string &key, const camera &cam, math::vec2 pos) -> entt::handle
Creates a prefab entity at a specified position.
Definition defaults.cpp:468
static void create_default_3d_scene_for_editing(rtti::context &ctx, scene &scn)
Creates a default 3D scene for editing.
Definition defaults.cpp:635
static auto create_camera_entity(rtti::context &ctx, scene &scn, const std::string &name) -> entt::handle
Creates a camera entity.
Definition defaults.cpp:581
static auto create_mesh_entity_at(rtti::context &ctx, scene &scn, const std::string &key, const camera &cam, math::vec2 pos) -> entt::handle
Creates a mesh entity at a specified position.
Definition defaults.cpp:512
static void create_default_3d_scene(rtti::context &ctx, scene &scn)
Creates a default 3D scene.
Definition defaults.cpp:615
static auto deinit(rtti::context &ctx) -> bool
Deinitializes default settings and assets.
Definition defaults.cpp:261
static auto default_light() -> asset_handle< font > &
Definition font.cpp:866
static auto default_heavy() -> asset_handle< font > &
Definition font.cpp:891
static auto default_extra_light() -> asset_handle< font > &
Definition font.cpp:861
static auto default_regular() -> asset_handle< font > &
Definition font.cpp:876
static auto default_bold() -> asset_handle< font > &
Definition font.cpp:886
static auto default_semi_bold() -> asset_handle< font > &
Definition font.cpp:881
static auto default_thin() -> asset_handle< font > &
Definition font.cpp:856
static auto default_black() -> asset_handle< font > &
Definition font.cpp:896
static auto default_medium() -> asset_handle< font > &
Definition font.cpp:871
Struct representing a light.
Definition light.h:87
light_type type
The type of the light.
Definition light.h:89
math::color color
The color of the light.
Definition light.h:207
float ambient_intensity
The ambient intensity of the light.
Definition light.h:212
Represents a generic prefab with a buffer for serialized data.
Definition prefab.h:18
Structure representing a reflection probe.
probe_type type
Type of the reflection probe.
reflect_method method
Reflection method.
Represents a scene in the ACE framework, managing entities and their relationships.
Definition scene.h:21
auto instantiate(const asset_handle< prefab > &pfb) -> entt::handle
Definition scene.cpp:192
Component that holds a reference to a UI document for RmlUi rendering.