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