22auto to_bx(
const math::vec3& data) -> bx::Vec3
24 return {data.x, data.y, data.z};
27auto from_bx(
const bx::Vec3& data) -> math::vec3
29 return {data.x, data.y, data.z};
45 scene* target_scene = em.get_active_scene(ctx);
52 if(pick_area_.x > 0.0f && pick_area_.y > 0.0f && pick_camera_)
54 const auto& pick_camera = *pick_camera_;
57 [&](
auto e,
auto&& transform_comp,
auto&& model_comp,
auto&& active)
59 auto&
model = model_comp.get_model();
65 const auto& world_transform = transform_comp.get_transform_global();
73 const auto&
mesh = lod.get();
77 if(!pick_camera.test_obb(bounds, world_transform))
79 auto ue = target_scene->create_handle(e);
86 const auto& bbox = bounds;
87 math::vec3 corners[8] = {
88 {bbox.min.x, bbox.min.y, bbox.min.z},
89 {bbox.max.x, bbox.min.y, bbox.min.z},
90 {bbox.min.x, bbox.max.y, bbox.min.z},
91 {bbox.max.x, bbox.max.y, bbox.min.z},
92 {bbox.min.x, bbox.min.y, bbox.max.z},
93 {bbox.max.x, bbox.min.y, bbox.max.z},
94 {bbox.min.x, bbox.max.y, bbox.max.z},
95 {bbox.max.x, bbox.max.y, bbox.max.z}
98 bool in_selection_area =
true;
99 for(
int i = 0; i < 8; ++i)
101 bool corner_in_selection_area =
false;
103 math::vec3 world_corner = world_transform.transform_coord(corners[i]);
106 math::vec3 screen_pos = pick_camera.world_to_viewport(world_corner);
109 if(screen_pos.x >= pick_position_.x - pick_area_.x * 0.5f &&
110 screen_pos.x <= pick_position_.x + pick_area_.x * 0.5f &&
111 screen_pos.y >= pick_position_.y - pick_area_.y * 0.5f &&
112 screen_pos.y <= pick_position_.y + pick_area_.y * 0.5f)
114 corner_in_selection_area =
true;
117 in_selection_area &= corner_in_selection_area;
121 if(!in_selection_area)
123 auto ue = target_scene->create_handle(e);
128 auto id = ENTT_ID_TYPE(e);
130 process_pick_result(ctx, target_scene,
id);
133 pick_camera_.reset();
144 const auto& pick_camera = *pick_camera_;
146 const auto& pick_view = pick_camera.get_view();
147 const auto& pick_proj = pick_camera.get_projection();
151 pass.
clear(BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x000000ff, 1.0f, 0);
153 pass.
bind(surface_.get());
155 bool anything_picked =
false;
157 [&](
auto e,
auto&& transform_comp,
auto&& model_comp,
auto&& active)
159 auto&
model = model_comp.get_model();
165 const auto& world_transform = transform_comp.get_transform_global();
173 const auto&
mesh = lod.get();
177 if(!pick_camera.test_obb(bounds, world_transform))
180 auto id = ENTT_ID_TYPE(e);
181 std::uint32_t rr = (id) & 0xff;
182 std::uint32_t gg = (
id >> 8) & 0xff;
183 std::uint32_t bb = (
id >> 16) & 0xff;
184 std::uint32_t aa = (
id >> 24) & 0xff;
186 math::vec4 color_id = {rr / 255.0f, gg / 255.0f, bb / 255.0f, aa / 255.0f};
188 anything_picked =
true;
189 const auto& submesh_transforms = model_comp.get_submesh_transforms();
190 const auto& bone_transforms = model_comp.get_bone_transforms();
191 const auto& skinning_transforms = model_comp.get_skinning_transforms();
196 auto& prog = submit_params.skinned ? program_skinned_ : program_;
202 auto& prog = submit_params.skinned ? program_skinned_ : program_;
204 prog->set_uniform(
"u_id", math::value_ptr(color_id));
209 auto& prog = submit_params.
skinned ? program_skinned_ : program_;
216 auto& prog = submit_params.
skinned ? program_skinned_ : program_;
221 model.
submit(world_transform, submesh_transforms, bone_transforms, skinning_transforms, 0, callbacks);
231 [&](
auto e,
auto&& transform_comp,
auto&& text_comp,
auto&& active)
233 if(!text_comp.can_be_rendered())
237 const auto& world_transform = transform_comp.get_transform_global();
238 auto bbox = text_comp.get_bounds();
240 if(!pick_camera.test_obb(bbox, world_transform))
245 auto id = ENTT_ID_TYPE(e);
253 aabb.min =
to_bx(bbox.min);
254 aabb.max =
to_bx(bbox.max);
259 if(em.show_icon_gizmos)
261 program_gizmos_->begin();
264 auto& scn = *target_scene;
271 using type_t =
typename std::decay_t<
decltype(
tag)>
::type;
273 scn.registry->view<type_t>().each(
274 [&](
auto e,
auto&& comp)
276 auto entity = scn.create_handle(e);
280 anything_picked =
true;
282 auto id = ENTT_ID_TYPE(e);
287 auto& transform_comp =
entity.template get<transform_component>();
288 const auto& world_transform = transform_comp.get_transform_global();
293 if(!pick_camera.test_billboard(em.billboard_data.size, world_transform))
297 icon->native_handle(),
298 to_bx(world_transform.get_position()),
299 to_bx(pick_camera.get_position()),
300 to_bx(pick_camera.z_unit_axis()),
301 em.billboard_data.size);
308 program_gizmos_->end();
313 pick_camera_.reset();
314 start_readback_ = anything_picked;
316 if(!anything_picked && !pick_callback_)
324 if((reading_ == 0u) && start_readback_)
328 if(blit_support ==
false)
330 APPLOG_WARNING(
"Texture blitting is not supported. Picking will not work");
331 start_readback_ =
false;
338 gfx::blit(pass.
id, blit_tex_->native_handle(), 0, 0, surface_->get_texture()->native_handle());
340 start_readback_ =
false;
343 if(reading_ && reading_ <= render_frame)
346 std::map<std::uint32_t, std::uint32_t> ids;
347 std::uint32_t max_amount = 0;
348 for(std::uint8_t*
x = &blit_data_.front();
x < &blit_data_.back();)
350 std::uint8_t rr = *
x++;
351 std::uint8_t gg = *
x++;
352 std::uint8_t bb = *
x++;
353 std::uint8_t aa = *
x++;
361 auto hash_key =
static_cast<std::uint32_t
>(rr + (gg << 8) + (bb << 16) + (aa << 24));
362 std::uint32_t amount = 1;
363 auto map_iter = ids.find(hash_key);
364 if(map_iter != ids.end())
366 amount = map_iter->second + 1;
370 ids[hash_key] = amount;
371 max_amount = max_amount > amount ? max_amount : amount;
374 ENTT_ID_TYPE id_key = 0;
377 for(
auto& pair : ids)
379 if(pair.second == max_amount)
382 process_pick_result(ctx, target_scene, id_key);
393 process_pick_result(ctx, target_scene, id_key);
406void picking_manager::process_pick_result(
rtti::context& ctx,
scene* target_scene, ENTT_ID_TYPE id_key)
409 auto entity = entt::entity(id_key);
410 entt::handle picked_entity;
422 auto callback = pick_callback_;
423 callback(picked_entity, pick_position_);
431 em.select(picked_entity, pick_mode_);
457 std::make_shared<gfx::texture>(tex_id_dim,
461 gfx::texture_format::RGBA8,
462 0 | BGFX_TEXTURE_RT | BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT |
463 BGFX_SAMPLER_MIP_POINT | BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP);
465 auto picking_rt_depth =
466 std::make_shared<gfx::texture>(tex_id_dim,
470 gfx::texture_format::D24S8,
471 0 | BGFX_TEXTURE_RT | BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT |
472 BGFX_SAMPLER_MIP_POINT | BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP);
474 std::vector<std::shared_ptr<gfx::texture>> textures{picking_rt, picking_rt_depth};
475 surface_ = std::make_shared<gfx::frame_buffer>(textures);
481 blit_tex_ = std::make_shared<gfx::texture>(
486 gfx::texture_format::RGBA8,
487 0 | BGFX_TEXTURE_BLIT_DST | BGFX_TEXTURE_READ_BACK | BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT |
488 BGFX_SAMPLER_MIP_POINT | BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP);
490 auto vs = am.get_asset<
gfx::shader>(
"editor:/data/shaders/vs_picking_id.sc");
491 auto vs_skinned = am.get_asset<
gfx::shader>(
"editor:/data/shaders/vs_picking_id_skinned.sc");
492 auto fs = am.get_asset<
gfx::shader>(
"editor:/data/shaders/fs_picking_id.sc");
494 program_ = std::make_unique<gpu_program>(vs,
fs);
495 program_skinned_ = std::make_unique<gpu_program>(vs_skinned,
fs);
497 auto vs_gizmos = am.get_asset<
gfx::shader>(
"editor:/data/shaders/vs_picking_debugdraw_fill_texture.sc");
498 auto fs_gizmos = am.get_asset<
gfx::shader>(
"editor:/data/shaders/fs_picking_debugdraw_fill_texture.sc");
499 program_gizmos_ = std::make_unique<gpu_program>(vs_gizmos, fs_gizmos);
509void picking_manager::setup_pick_camera(
const camera& cam, math::vec2 pos, math::vec2 area)
513 if(area.x > 0.0f && area.y > 0.0f)
540 pick_camera.
look_at(pick_eye, pick_at, pick_up);
543 pick_camera_ = pick_camera;
544 pick_position_ = pos;
547 start_readback_ =
true;
552 pick_camera_.reset();
556 start_readback_ =
false;
561 setup_pick_camera(cam, pos, area);
564 if(area.x > 0.0f && area.y > 0.0f)
581 setup_pick_camera(cam, pos);
582 pick_callback_ = callback;
587 return pick_camera_.has_value() || reading_ != 0;
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....
auto get_far_clip() const -> float
Retrieves the distance from the camera to the far clip plane.
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.
void set_fov(float degrees)
Sets the field of view angle of this camera (perspective only).
void look_at(const math::vec3 &eye, const math::vec3 &at)
Sets the camera to look at a specified target.
void set_far_clip(float distance)
Sets the far plane distance.
auto y_unit_axis() const -> math::vec3
Retrieves the y-axis unit vector of the camera's local coordinate system.
void set_aspect_ratio(float aspect, bool locked=false)
Sets the aspect ratio to be used for generating the horizontal FOV angle (perspective only).
void set_near_clip(float distance)
Sets the near plane distance.
auto get_frustum() const -> const math::frustum &
Retrieves the current camera object frustum.
auto get_near_clip() const -> float
Retrieves the distance from the camera to the near clip plane.
Class that contains core light data, used for rendering and other purposes.
Base class for materials used in rendering.
Main class representing a 3D mesh with support for different LODs, submeshes, and skinning.
auto get_bounds() const -> const math::bbox &
Gets the local bounding box for this mesh.
Class that contains core data for meshes.
Structure describing a LOD group (set of meshes), LOD transitions, and their materials.
auto get_lod(uint32_t lod) const -> asset_handle< mesh >
Gets the LOD (Level of Detail) mesh for the specified level.
auto is_valid() const -> bool
Checks if the model is valid.
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.
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.
std::chrono::duration< float > delta_t
#define APPLOG_WARNING(...)
void submit(view_id _id, program_handle _handle, int32_t _depth, bool _preserveState)
uint32_t read_texture(texture_handle _handle, void *_data, uint8_t _mip)
void set_state(uint64_t _state, uint32_t _rgba)
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)
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)
void discard(uint8_t _flags)
uint32_t get_render_frame()
auto to_bx(const glm::vec3 &data) -> bx::Vec3
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)
void set_view_proj(const float *v, const float *p)
void clear(uint16_t _flags, uint32_t _rgba=0x000000ff, float _depth=1.0f, uint8_t _stencil=0) const
void bind(const frame_buffer *fb=nullptr) const
hpp::event< void(rtti::context &, delta_t)> on_frame_render
Parameters for the submit callbacks.
bool skinned
Indicates if the model is skinned.
Callbacks for submitting the model for rendering.
std::function< void(const params &info, const material &)> setup_params_per_submesh
Callback for setting up per submesh.
std::function< void(const params &info)> setup_begin
Callback for setup begin.
std::function< void(const params &info)> setup_params_per_instance
Callback for setting up per instance.
std::function< void(const params &info)> setup_end
Callback for setup end.
Represents a scene in the ACE framework, managing entities and their relationships.
auto create_handle(entt::entity e) -> entt::handle
Creates an entity in the scene.