Unravel Engine C++ Reference
Loading...
Searching...
No Matches
picking_manager.cpp
Go to the documentation of this file.
1#include "picking_manager.h"
2#include "thumbnail_manager.h"
3
6#include <graphics/texture.h>
7#include <logging/logging.h>
8
11#include <engine/events.h>
17namespace unravel
18{
19
20namespace
21{
22auto to_bx(const math::vec3& data) -> bx::Vec3
23{
24 return {data.x, data.y, data.z};
25}
26
27auto from_bx(const bx::Vec3& data) -> math::vec3
28{
29 return {data.x, data.y, data.z};
30}
31
32} // namespace
33
34// Helper functions for different picking types
35namespace
36{
37// Type 1: Position-only picking
38bool is_position_in_selection_area(const math::vec3& world_position,
39 const camera& pick_camera,
40 const math::vec2& pick_position,
41 const math::vec2& pick_area)
42{
43 // Project position to screen space
44 math::vec3 screen_pos = pick_camera.world_to_viewport(world_position);
45
46 // Check if position is within the selection rectangle
47 return (
48 screen_pos.x >= pick_position.x - pick_area.x * 0.5f && screen_pos.x <= pick_position.x + pick_area.x * 0.5f &&
49 screen_pos.y >= pick_position.y - pick_area.y * 0.5f && screen_pos.y <= pick_position.y + pick_area.y * 0.5f);
50}
51
52// Type 3: Global bounds (already world-space)
53bool are_corners_in_selection_area(hpp::span<const math::vec3> corners,
54 const camera& pick_camera,
55 const math::vec2& pick_position,
56 const math::vec2& pick_area)
57{
58 // Check if all corners are in selection area
59 bool all_corners_in_selection = true;
60 for(int i = 0; i < 8; ++i)
61 {
62 // Project to screen space (corners are already in world space)
63 math::vec3 screen_pos = pick_camera.world_to_viewport(corners[i]);
64
65 // Check if this corner is within the selection rectangle
66 bool corner_in_selection = (screen_pos.x >= pick_position.x - pick_area.x * 0.5f &&
67 screen_pos.x <= pick_position.x + pick_area.x * 0.5f &&
68 screen_pos.y >= pick_position.y - pick_area.y * 0.5f &&
69 screen_pos.y <= pick_position.y + pick_area.y * 0.5f);
70
71 all_corners_in_selection &= corner_in_selection;
72 }
73
74 return all_corners_in_selection;
75}
76
77// Type 2: Local bounds with transform (existing logic)
78bool are_local_bounds_in_selection_area(const math::bbox& local_bounds,
79 const math::transform& world_transform,
80 const camera& pick_camera,
81 const math::vec2& pick_position,
82 const math::vec2& pick_area)
83{
84 // Generate bounding box corners
85 math::vec3 corners[8] = {
86 world_transform.transform_coord({local_bounds.min.x, local_bounds.min.y, local_bounds.min.z}),
87 world_transform.transform_coord({local_bounds.max.x, local_bounds.min.y, local_bounds.min.z}),
88 world_transform.transform_coord({local_bounds.min.x, local_bounds.max.y, local_bounds.min.z}),
89 world_transform.transform_coord({local_bounds.max.x, local_bounds.max.y, local_bounds.min.z}),
90 world_transform.transform_coord({local_bounds.min.x, local_bounds.min.y, local_bounds.max.z}),
91 world_transform.transform_coord({local_bounds.max.x, local_bounds.min.y, local_bounds.max.z}),
92 world_transform.transform_coord({local_bounds.min.x, local_bounds.max.y, local_bounds.max.z}),
93 world_transform.transform_coord({local_bounds.max.x, local_bounds.max.y, local_bounds.max.z})};
94
95 return are_corners_in_selection_area(corners, pick_camera, pick_position, pick_area);
96}
97
98// Type 3: Global bounds (already world-space)
99bool are_global_bounds_in_selection_area(const math::bbox& world_bounds,
100 const camera& pick_camera,
101 const math::vec2& pick_position,
102 const math::vec2& pick_area)
103{
104 // Generate bounding box corners (already in world space)
105 math::vec3 corners[8] = {{world_bounds.min.x, world_bounds.min.y, world_bounds.min.z},
106 {world_bounds.max.x, world_bounds.min.y, world_bounds.min.z},
107 {world_bounds.min.x, world_bounds.max.y, world_bounds.min.z},
108 {world_bounds.max.x, world_bounds.max.y, world_bounds.min.z},
109 {world_bounds.min.x, world_bounds.min.y, world_bounds.max.z},
110 {world_bounds.max.x, world_bounds.min.y, world_bounds.max.z},
111 {world_bounds.min.x, world_bounds.max.y, world_bounds.max.z},
112 {world_bounds.max.x, world_bounds.max.y, world_bounds.max.z}};
113
114 return are_corners_in_selection_area(corners, pick_camera, pick_position, pick_area);
115}
116} // namespace
117
118constexpr int picking_manager::tex_id_dim;
123
125{
126 auto& em = ctx.get_cached<editing_manager>();
127
128 // Get the appropriate scene based on edit mode
129 scene* target_scene = em.get_active_scene(ctx);
130
131 if(!target_scene)
132 {
133 return;
134 }
135
136 if(pick_area_.x > 0.0f && pick_area_.y > 0.0f && pick_camera_)
137 {
138 const auto& pick_camera = *pick_camera_;
139
140 auto on_pick_failed = [&](auto e)
141 {
142 auto ue = target_scene->create_handle(e);
143 em.unselect(ue);
144 };
145
146 auto on_pick_success = [&](auto e)
147 {
148 auto id = ENTT_ID_TYPE(e);
149 process_pick_result(ctx, target_scene, id);
150 };
151
152 // Area picking supports three types of entities:
153 // Type 1: Position-only picking for entities with just transform_component (no visual bounds)
154 target_scene->registry->view<transform_component, active_component>().each(
155 [&](auto e, auto&& transform_comp, auto&& active)
156 {
157 const auto& world_transform = transform_comp.get_transform_global();
158 const auto& world_position = world_transform.get_position();
159
160 // if(auto model_comp = target_scene->registry->try_get<model_component>(e))
161 // {
162 // auto& model = model_comp->get_model();
163 // if(!model.is_valid())
164 // {
165 // return;
166 // }
167
168 // auto lod = model.get_lod(0);
169 // if(!lod)
170 // {
171 // return;
172 // }
173
174 // const auto& mesh = lod.get();
175 // const auto& bounds = mesh->get_bounds();
176
177 // if(!pick_camera.test_obb(bounds, world_transform))
178 // {
179 // on_pick_failed(e);
180 // return;
181 // }
182
183 // if(!are_local_bounds_in_selection_area(bounds, world_transform, pick_camera, pick_position_,
184 // pick_area_))
185 // {
186 // on_pick_failed(e);
187 // return;
188 // }
189 // }
190
191 // if(auto particle_comp = target_scene->registry->try_get<particle_emitter_component>(e))
192 // {
193 // const auto& world_bounds = particle_comp->get_world_bounds();
194 // if(!pick_camera.test_aabb(world_bounds))
195 // {
196 // on_pick_failed(e);
197 // return;
198 // }
199
200 // if(!are_global_bounds_in_selection_area(world_bounds, pick_camera, pick_position_, pick_area_))
201 // {
202 // on_pick_failed(e);
203 // return;
204 // }
205 // }
206
207 if(!pick_camera.get_frustum().test_point(world_position))
208 {
209 on_pick_failed(e);
210 return;
211 }
212
213 // Test if position is in selection area
214 if(!is_position_in_selection_area(world_position, pick_camera, pick_position_, pick_area_))
215 {
216 on_pick_failed(e);
217 return;
218 }
219
220 on_pick_success(e);
221 });
222
223 pick_camera_.reset();
224 pick_position_ = {};
225 pick_area_ = {};
226
227 return;
228 }
229
230 const auto render_frame = gfx::get_render_frame();
231
232 if(pick_camera_)
233 {
234 const auto& pick_camera = *pick_camera_;
235
236 const auto& pick_view = pick_camera.get_view();
237 const auto& pick_proj = pick_camera.get_projection();
238
239 gfx::render_pass pass("picking_buffer_pass");
240 // ID buffer clears to black, which represents clicking on nothing (background)
241 pass.clear(BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x000000ff, 1.0f, 0);
242 pass.set_view_proj(pick_view, pick_proj);
243 pass.bind(surface_.get());
244
245 bool anything_picked = false;
246
247 // Regular picking (render-to-texture) supports:
248 // Type 2: Model components - rendered with actual geometry
249 // Type 1 & 3: Other components - handled via gizmo icons (see gizmo section below)
250 target_scene->registry->view<transform_component, model_component, active_component>().each(
251 [&](auto e, auto&& transform_comp, auto&& model_comp, auto&& active)
252 {
253 auto& model = model_comp.get_model();
254 if(!model.is_valid())
255 {
256 return;
257 }
258
259 const auto& world_transform = transform_comp.get_transform_global();
260
261 auto lod = model.get_lod(0);
262 if(!lod)
263 {
264 return;
265 }
266
267 const auto& mesh = lod.get();
268 const auto& bounds = mesh->get_bounds();
269
270 // Test the bounding box of the mesh
271 if(!pick_camera.test_obb(bounds, world_transform))
272 return;
273
274 auto id = ENTT_ID_TYPE(e);
275 std::uint32_t rr = (id) & 0xff;
276 std::uint32_t gg = (id >> 8) & 0xff;
277 std::uint32_t bb = (id >> 16) & 0xff;
278 std::uint32_t aa = (id >> 24) & 0xff;
279
280 math::vec4 color_id = {rr / 255.0f, gg / 255.0f, bb / 255.0f, aa / 255.0f};
281
282 anything_picked = true;
283 const auto& submesh_transforms = model_comp.get_submesh_transforms();
284 const auto& bone_transforms = model_comp.get_bone_transforms();
285 const auto& skinning_transforms = model_comp.get_skinning_transforms();
286
287 model::submit_callbacks callbacks;
288 callbacks.setup_begin = [&](const model::submit_callbacks::params& submit_params)
289 {
290 auto& prog = submit_params.skinned ? program_skinned_ : program_;
291
292 prog->begin();
293 };
294 callbacks.setup_params_per_instance = [&](const model::submit_callbacks::params& submit_params)
295 {
296 auto& prog = submit_params.skinned ? program_skinned_ : program_;
297
298 prog->set_uniform("u_id", math::value_ptr(color_id));
299 };
300 callbacks.setup_params_per_submesh =
301 [&](const model::submit_callbacks::params& submit_params, const material& mat)
302 {
303 auto& prog = submit_params.skinned ? program_skinned_ : program_;
304
305 gfx::set_state(mat.get_render_states());
306 gfx::submit(pass.id, prog->native_handle(), 0, submit_params.preserve_state);
307 };
308 callbacks.setup_end = [&](const model::submit_callbacks::params& submit_params)
309 {
310 auto& prog = submit_params.skinned ? program_skinned_ : program_;
311
312 prog->end();
313 };
314
315 model.submit(world_transform, submesh_transforms, bone_transforms, skinning_transforms, 0, callbacks);
316 });
317
318 gfx::discard();
319
320 if(program_gizmos_)
321 {
322 gfx::dd_raii dd(pass.id);
323
324 target_scene->registry->view<transform_component, text_component, active_component>().each(
325 [&](auto e, auto&& transform_comp, auto&& text_comp, auto&& active)
326 {
327 if(!text_comp.can_be_rendered())
328 {
329 return;
330 }
331 const auto& world_transform = transform_comp.get_transform_global();
332 auto bbox = text_comp.get_bounds();
333
334 if(!pick_camera.test_obb(bbox, world_transform))
335 {
336 return;
337 }
338
339 auto id = ENTT_ID_TYPE(e);
340 math::color color(id);
341
342 dd.encoder.setColor(color);
343 dd.encoder.setState(true, true, false, true, false);
344
345 dd.encoder.pushTransform((const float*)world_transform);
346 bx::Aabb aabb;
347 aabb.min = to_bx(bbox.min);
348 aabb.max = to_bx(bbox.max);
349 dd.encoder.draw(aabb);
351 });
352
353 if(em.show_icon_gizmos)
354 {
355 program_gizmos_->begin();
356 dd.encoder.pushProgram(program_gizmos_->native_handle());
357
358 auto& scn = *target_scene;
359 hpp::for_each_type<camera_component,
364 [&](auto tag)
365 {
366 using type_t = typename std::decay_t<decltype(tag)>::type;
367
368 scn.registry->view<type_t>().each(
369 [&](auto e, auto&& comp)
370 {
371 auto entity = scn.create_handle(e);
372
373 auto& tm = ctx.get_cached<thumbnail_manager>();
374
375 anything_picked = true;
376
377 auto id = ENTT_ID_TYPE(e);
378 math::color color(id);
379
380 dd.encoder.setColor(color);
381 dd.encoder.setState(true, true, false, true);
382 auto& transform_comp = entity.template get<transform_component>();
383 const auto& world_transform = transform_comp.get_transform_global();
384
385 auto icon = tm.get_gizmo_icon(entity);
386 if(icon)
387 {
388 if(!pick_camera.test_billboard(em.billboard_data.size, world_transform))
389 return; // completely outside → skip draw
390
392 icon->native_handle(),
393 to_bx(world_transform.get_position()),
394 to_bx(pick_camera.get_position()),
395 to_bx(pick_camera.z_unit_axis()),
396 em.billboard_data.size);
397 }
398 });
399 });
400
401 dd.encoder.popProgram();
402 program_gizmos_->end();
403 }
404 }
405
406 pick_camera_.reset();
407 start_readback_ = anything_picked;
408
409 if(!anything_picked && !pick_callback_)
410 {
411 em.unselect();
412 }
413 }
414
415 // If the user previously clicked, and we're done reading data from GPU, look at ID buffer on CPU
416 // Whatever mesh has the most pixels in the ID buffer is the one the user clicked on.
417 if((reading_ == 0u) && start_readback_)
418 {
419 bool blit_support = gfx::is_supported(BGFX_CAPS_TEXTURE_BLIT);
420
421 if(blit_support == false)
422 {
423 APPLOG_WARNING("Texture blitting is not supported. Picking will not work");
424 start_readback_ = false;
425 return;
426 }
427
428 gfx::render_pass pass("picking_buffer_blit_pass");
429 pass.touch();
430 // Blit and read
431 gfx::blit(pass.id, blit_tex_->native_handle(), 0, 0, surface_->get_texture()->native_handle());
432 reading_ = gfx::read_texture(blit_tex_->native_handle(), blit_data_.data());
433 start_readback_ = false;
434 }
435
436 if(reading_ && reading_ <= render_frame)
437 {
438 reading_ = 0;
439 std::map<std::uint32_t, std::uint32_t> ids; // This contains all the IDs found in the buffer
440 std::uint32_t max_amount = 0;
441 for(std::uint8_t* x = &blit_data_.front(); x < &blit_data_.back();)
442 {
443 std::uint8_t rr = *x++;
444 std::uint8_t gg = *x++;
445 std::uint8_t bb = *x++;
446 std::uint8_t aa = *x++;
447
448 // Skip background
449 // if(0 == (rr | gg | bb | aa))
450 // {
451 // continue;
452 // }
453
454 auto hash_key = static_cast<std::uint32_t>(rr + (gg << 8) + (bb << 16) + (aa << 24));
455 std::uint32_t amount = 1;
456 auto map_iter = ids.find(hash_key);
457 if(map_iter != ids.end())
458 {
459 amount = map_iter->second + 1;
460 }
461
462 // Amount of times this ID (color) has been clicked on in buffer
463 ids[hash_key] = amount;
464 max_amount = max_amount > amount ? max_amount : amount;
465 }
466
467 ENTT_ID_TYPE id_key = 0;
468 if(max_amount != 0u)
469 {
470 for(auto& pair : ids)
471 {
472 if(pair.second == max_amount)
473 {
474 id_key = pair.first;
475 process_pick_result(ctx, target_scene, id_key);
476 break;
477 }
478 }
479 }
480 else
481 {
482 // If nothing was picked, still call the process_pick_result with id_key = 0
483 // This will create an invalid handle that will be passed to the callback
484 if(pick_callback_)
485 {
486 process_pick_result(ctx, target_scene, id_key);
487 }
488 else
489 {
490 em.unselect();
491 }
492 }
493
494 // Clear the callback after processing
495 pick_callback_ = {};
496 }
497}
498
499void picking_manager::process_pick_result(rtti::context& ctx, scene* target_scene, ENTT_ID_TYPE id_key)
500{
501 // Create entity handle (may be invalid if id_key is 0)
502 auto entity = entt::entity(id_key);
503 entt::handle picked_entity;
504
505 // Only try to create a handle if the entity ID is valid
506 if(id_key != 0)
507 {
508 picked_entity = target_scene->create_handle(entity);
509 }
510
511 if(pick_callback_)
512 {
513 // Call the custom callback with either a valid entity or an invalid handle
514 // Do this because the callback can reassign the pick_callback_ variable
515 auto callback = pick_callback_;
516 callback(picked_entity, pick_position_);
517 }
518 else
519 {
520 // Use the traditional selection mechanism
521 auto& em = ctx.get_cached<editing_manager>();
522 if(picked_entity)
523 {
524 em.select(picked_entity, pick_mode_);
525 }
526 else
527 {
528 em.unselect();
529 }
530 }
531}
532
536
540
542{
543 auto& ev = ctx.get_cached<events>();
544 ev.on_frame_render.connect(sentinel_, 850, this, &picking_manager::on_frame_render);
545
546 auto& am = ctx.get_cached<asset_manager>();
547
548 // Set up ID buffer, which has a color target and depth buffer
549 auto picking_rt =
550 std::make_shared<gfx::texture>(tex_id_dim,
551 tex_id_dim,
552 false,
553 1,
554 gfx::texture_format::RGBA8,
555 0 | BGFX_TEXTURE_RT | BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT |
556 BGFX_SAMPLER_MIP_POINT | BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP);
557
558 auto picking_rt_depth =
559 std::make_shared<gfx::texture>(tex_id_dim,
560 tex_id_dim,
561 false,
562 1,
563 gfx::texture_format::D24S8,
564 0 | BGFX_TEXTURE_RT | BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT |
565 BGFX_SAMPLER_MIP_POINT | BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP);
566
567 std::vector<std::shared_ptr<gfx::texture>> textures{picking_rt, picking_rt_depth};
568 surface_ = std::make_shared<gfx::frame_buffer>(textures);
569
570 // CPU texture for blitting to and reading ID buffer so we can see what was clicked on.
571 // Impossible to read directly from a render target, you *must* blit to a CPU texture
572 // first. Algorithm Overview: Render on GPU -> Blit to CPU texture -> Read from CPU
573 // texture.
574 blit_tex_ = std::make_shared<gfx::texture>(
575 tex_id_dim,
576 tex_id_dim,
577 false,
578 1,
579 gfx::texture_format::RGBA8,
580 0 | BGFX_TEXTURE_BLIT_DST | BGFX_TEXTURE_READ_BACK | BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT |
581 BGFX_SAMPLER_MIP_POINT | BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP);
582
583 auto vs = am.get_asset<gfx::shader>("editor:/data/shaders/vs_picking_id.sc");
584 auto vs_skinned = am.get_asset<gfx::shader>("editor:/data/shaders/vs_picking_id_skinned.sc");
585 auto fs = am.get_asset<gfx::shader>("editor:/data/shaders/fs_picking_id.sc");
586
587 program_ = std::make_unique<gpu_program>(vs, fs);
588 program_skinned_ = std::make_unique<gpu_program>(vs_skinned, fs);
589
590 auto vs_gizmos = am.get_asset<gfx::shader>("editor:/data/shaders/vs_picking_debugdraw_fill_texture.sc");
591 auto fs_gizmos = am.get_asset<gfx::shader>("editor:/data/shaders/fs_picking_debugdraw_fill_texture.sc");
592 program_gizmos_ = std::make_unique<gpu_program>(vs_gizmos, fs_gizmos);
593
594 return true;
595}
596
598{
599 return true;
600}
601
602void picking_manager::setup_pick_camera(const camera& cam, math::vec2 pos, math::vec2 area)
603{
604 camera pick_camera;
605
606 if(area.x > 0.0f && area.y > 0.0f)
607 {
608 // Area picking: copy the passed camera and adjust for the selection area
609 pick_camera = cam; // Copy the passed camera
610 }
611 else
612 {
613 // Single point picking (existing logic)
614 const auto near_clip = cam.get_near_clip();
615 const auto far_clip = cam.get_far_clip();
616 const auto& frustum = cam.get_frustum();
617
618 math::vec3 pick_eye;
619 math::vec3 pick_at;
620 math::vec3 pick_up = cam.y_unit_axis();
621
622 if(!cam.viewport_to_world(pos, frustum.planes[math::volume_plane::near_plane], pick_eye, true))
623 return;
624
625 if(!cam.viewport_to_world(pos, frustum.planes[math::volume_plane::far_plane], pick_at, true))
626 return;
627
628 pick_camera.set_aspect_ratio(1.0f);
629 pick_camera.set_fov(1.0f);
630 pick_camera.set_near_clip(near_clip);
631 pick_camera.set_far_clip(far_clip);
632 pick_camera.look_at(pick_eye, pick_at, pick_up);
633 }
634
635 pick_camera_ = pick_camera;
636 pick_position_ = pos;
637 pick_area_ = area;
638 reading_ = 0;
639 start_readback_ = true;
640}
641
643{
644 pick_camera_.reset();
645 pick_position_ = {};
646 pick_area_ = {};
647 reading_ = 0;
648 start_readback_ = false;
649}
650
653 math::vec2 pos,
654 math::vec2 area)
655{
656 setup_pick_camera(cam, pos, area);
657 pick_mode_ = mode;
658
659 if(area.x > 0.0f && area.y > 0.0f)
660 {
662 }
663
664 pick_callback_ = {}; // Clear any existing callback
665}
666
667void picking_manager::query_pick(math::vec2 pos, const camera& cam, pick_callback callback, bool force)
668{
669 // If already picking, ignore this request
670 if(!force && is_picking())
671 {
672 return;
673 }
674
675 // Set up the pick operation
676 setup_pick_camera(cam, pos);
677 pick_callback_ = callback;
678}
679
680auto picking_manager::is_picking() const -> bool
681{
682 return pick_camera_.has_value() || reading_ != 0;
683}
684
685auto picking_manager::get_pick_texture() const -> const std::shared_ptr<gfx::texture>&
686{
687 return blit_tex_;
688}
689
690} // namespace unravel
manifold_type type
General purpose transformation class designed to maintain each component of the transformation separa...
Definition transform.hpp:27
auto get_position() const noexcept -> const vec3_t &
Get the position component.
auto transform_coord(const vec2_t &v) const noexcept -> vec2_t
Transform a 2D coordinate.
Manages assets, including loading, unloading, and storage.
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
auto get_far_clip() const -> float
Retrieves the distance from the camera to the far clip plane.
Definition camera.cpp:67
auto viewport_to_world(const math::vec2 &point, const math::plane &plane, math::vec3 &position_out, bool clip) const -> bool
Converts a screen position into a world space position on the specified plane.
Definition camera.cpp:523
void set_fov(float degrees)
Sets the field of view angle of this camera (perspective only).
Definition camera.cpp:77
void look_at(const math::vec3 &eye, const math::vec3 &at)
Sets the camera to look at a specified target.
Definition camera.cpp:326
void set_far_clip(float distance)
Sets the far plane distance.
Definition camera.cpp:125
auto y_unit_axis() const -> math::vec3
Retrieves the y-axis unit vector of the camera's local coordinate system.
Definition camera.cpp:355
void set_aspect_ratio(float aspect, bool locked=false)
Sets the aspect ratio to be used for generating the horizontal FOV angle (perspective only).
Definition camera.cpp:165
void set_near_clip(float distance)
Sets the near plane distance.
Definition camera.cpp:105
auto get_frustum() const -> const math::frustum &
Retrieves the current camera object frustum.
Definition camera.cpp:365
auto get_near_clip() const -> float
Retrieves the distance from the camera to the near clip plane.
Definition camera.cpp:62
Class that contains core light data, used for rendering and other purposes.
Base class for materials used in rendering.
Definition material.h:32
Main class representing a 3D mesh with support for different LODs, submeshes, and skinning.
Definition mesh.h:310
auto get_bounds() const -> const math::bbox &
Gets the local bounding box for this mesh.
Definition mesh.cpp:1507
Class that contains core data for meshes.
Structure describing a LOD group (set of meshes), LOD transitions, and their materials.
Definition model.h:42
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
auto is_valid() const -> bool
Checks if the model is valid.
Definition model.cpp:9
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
Component that wraps particle system emitter functionality.
void query_pick(math::vec2 pos, const camera &cam, pick_callback callback, bool force=false)
std::function< void(entt::handle entity, const math::vec2 &screen_pos)> pick_callback
auto init(rtti::context &ctx) -> bool
void request_pick(const camera &cam, editing_manager::select_mode mode, math::vec2 pos, math::vec2 area={})
static constexpr int tex_id_dim
auto is_picking() const -> bool
void on_frame_render(rtti::context &ctx, delta_t dt)
void on_frame_pick(rtti::context &ctx, delta_t dt)
auto get_pick_texture() const -> const std::shared_ptr< gfx::texture > &
auto deinit(rtti::context &ctx) -> bool
Class that contains core reflection probe data, used for rendering and other purposes.
Component that handles transformations (position, rotation, scale, etc.) in the ACE framework.
std::chrono::duration< float > delta_t
std::string tag
Definition hub.cpp:26
const char * icon
#define APPLOG_WARNING(...)
Definition logging.h:19
Definition cache.hpp:11
void submit(view_id _id, program_handle _handle, int32_t _depth, bool _preserveState)
Definition graphics.cpp:900
uint32_t read_texture(texture_handle _handle, void *_data, uint8_t _mip)
Definition graphics.cpp:591
void set_state(uint64_t _state, uint32_t _rgba)
Definition graphics.cpp:764
auto is_supported(uint64_t flag) -> bool
void draw_billboard(DebugDrawEncoder &dd, bgfx::TextureHandle icon_texture, const bx::Vec3 &icon_center, const bx::Vec3 &camera_pos, const bx::Vec3 &camera_look_dir, float half_size)
Definition debugdraw.cpp:25
void blit(view_id _id, texture_handle _dst, uint16_t _dstX, uint16_t _dstY, texture_handle _src, uint16_t _srcX, uint16_t _srcY, uint16_t _width, uint16_t _height)
Definition graphics.cpp:974
void discard(uint8_t _flags)
Definition graphics.cpp:969
uint32_t get_render_frame()
Hash specialization for batch_key to enable use in std::unordered_map.
auto to_bx(const glm::vec3 &data) -> bx::Vec3
Definition gizmos.cpp:8
entt::entity entity
float x
void draw(const bx::Aabb &_aabb)
void setColor(uint32_t _abgr)
void setState(bool _depthTest, bool _depthWrite, bool _clockwise, bool _alphaWrite=false, bool _alphaBlend=true)
void pushTransform(const void *_mtx)
void pushProgram(bgfx::ProgramHandle _handle)
DebugDrawEncoder encoder
Definition debugdraw.h:15
void set_view_proj(const float *v, const float *p)
gfx::view_id id
Definition render_pass.h:98
void clear(uint16_t _flags, uint32_t _rgba=0x000000ff, float _depth=1.0f, uint8_t _stencil=0) const
void touch() const
void bind(const frame_buffer *fb=nullptr) const
Storage for box vector values and wraps up common functionality.
Definition bbox.h:21
vec3 max
The maximum vector value of the bounding box.
Definition bbox.h:311
vec3 min
The minimum vector value of the bounding box.
Definition bbox.h:306
auto get_cached() -> T &
Definition context.hpp:49
hpp::event< void(rtti::context &, delta_t)> on_frame_render
Definition events.h:19
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
Represents a scene in the ACE framework, managing entities and their relationships.
Definition scene.h:21
auto create_handle(entt::entity e) -> entt::handle
Creates an entity in the scene.
Definition scene.cpp:307