#include "augment_manager_v2_impl.h" #include "core/imgui_utility.hpp" #include "core/math_helper.hpp" #include glm::mat4 augment_manager_v2::impl::item_store_type::extra_transform() const { return to_transform_mat(extra_offset, extra_rotation); } glm::mat4 augment_manager_v2::impl::item_store_type::get_transform() const { return base_transform * extra_transform(); } void augment_manager_v2::impl::item_store_type::update_transform(impl *_pimpl) { if (transform_var.empty()) return; if (_pimpl->sophiar_conn == nullptr) return; auto trans = _pimpl->sophiar_conn-> query_transform_variable(transform_var); if (trans.has_value()) { base_transform = to_mat4(*trans); is_tracked = true; } else { is_tracked = false; } } augment_manager_v2::impl::impl(const create_config &_conf) { conf = _conf; sophiar_conn = conf.sophiar_conn; stream = conf.stream; for (auto &item: conf.item_list) { auto &st = item_list.emplace_back(item); // special hacks if (item.type == ITEM_IMAGE) { st.flip_y = item.flip_y; } } ps_info = query_point_size_info(); } void augment_manager_v2::impl::update(const camera_info &info, bool no_commit) { auto ren_info = std::make_shared(); // load from scene_name in player mode if (conf.player_mode) { auto scene = OBJ_QUERY(scene_ptr, conf.scene_name); if (scene != nullptr) { *ren_info = *scene; } no_commit = true; } if (!conf.player_mode || player_allow_control) { ren_info->camera = info; ren_info->light.follow_camera = enable_light_follow_camera; ren_info->light.direction = to_vec3(light_direction); } ren_info->stream = stream; for (auto &item: item_list) { if (!item.visible) continue; item.update_transform(this); if (!item.is_tracked && !ignore_missing) continue; auto ren_item = scene_render_info::item_type(); ren_item.alpha = item.alpha; ren_item.transform = item.get_transform(); switch (item.type) { case ITEM_IMAGE: { auto image_info = scene_render_info::image_info{ .img = to_image(item.name), .flip_y = item.flip_y, }; ren_item.info = image_info; break; } case ITEM_MESH: { auto mesh_info = scene_render_info::mesh_info{ .mesh = OBJ_QUERY(mesh_ptr, item.name), .enable_depth_alpha = item.enable_depth_alpha, .alpha_factor = item.alpha_factor, }; mesh_info.material = { .ambient = item.color * item.ambient_factor, .diffuse = item.color }; ren_item.info = mesh_info; break; } case ITEM_PC: { auto pc_info = scene_render_info::pc_info{ .pc = OBJ_QUERY(pc_ptr, item.name), .point_size = item.point_size, .color = item.color, }; ren_item.info = pc_info; break; } default: { RET_ERROR; } } ren_info->items.push_back(ren_item); } q_this->pre_render_sig(ren_info); last_scene_info = ren_info; if (!no_commit && conf.scene_name != invalid_obj_name) { OBJ_SAVE(conf.scene_name, ren_info); } } void augment_manager_v2::impl::render() { if (!enable) return; render_scene(last_scene_info); q_this->post_render_sig(last_scene_info); } void augment_manager_v2::impl::show() { ImGui::Checkbox("Enable", &enable); if (!enable) return; ImGui::SameLine(); ImGui::Checkbox("Ignore Missing", &ignore_missing); if (conf.player_mode) { ImGui::SameLine(); ImGui::Checkbox("Allow Control", &player_allow_control); } for (auto &item: item_list) { if (ImGui::TreeNode(item.disp_name.c_str())) { auto tree_close = sg::make_scope_guard([] { ImGui::TreePop(); }); ImGui::Checkbox("Visibility", &item.visible); if (!item.visible) continue; ImGui::DragFloat("Alpha", &item.alpha, 0.005f, 0.0f, 1.0f); if (item.type == ITEM_MESH || item.type == ITEM_PC) { ImGui::ColorEdit3("Color", glm::value_ptr(item.color)); ImGui::DragFloat3("Offset (mm)", glm::value_ptr(item.extra_offset), 0.05f, 0.0f, 0.0f, "%.02f"); ImGui::DragFloat3("Offset (deg)", glm::value_ptr(item.extra_rotation), 0.1f, -180.0f, 180.0f, "%.01f"); } if (item.type == ITEM_MESH) { ImGui::Checkbox("Depth Alpha", &item.enable_depth_alpha); if (item.enable_depth_alpha) { ImGui::DragFloat("Alpha Factor", &item.alpha_factor, 0.005f, 0.0f, 1.0f); } ImGui::DragFloat("Ambient Factor", &item.ambient_factor, 0.005f, 0.0f, 1.0f); } if (item.type == ITEM_PC) { ImGui::DragFloat("Point Size", &item.point_size, ps_info.delta, ps_info.min, ps_info.max, "%.01f"); } } } if (ImGui::TreeNode("Light")) { ImGui::Checkbox("Follow Camera", &enable_light_follow_camera); if (!enable_light_follow_camera) { ImGui::gizmo3D("##direction", light_direction, ImGui::CalcItemWidth()); } ImGui::TreePop(); } } augment_manager_v2::augment_manager_v2(const create_config &conf) : pimpl(std::make_unique(conf)) { pimpl->q_this = this; } augment_manager_v2::~augment_manager_v2() = default; void augment_manager_v2::update(const camera_info &info) { pimpl->update(info); } void augment_manager_v2::render(const camera_info &info) { pimpl->update(info, true); // no commit pimpl->render(); } void augment_manager_v2::show() { pimpl->show(); } augment_manager_v2::item_list_type augment_manager_v2::item_list_from_v1(const item_list_v1_type &items) { auto ret = item_list_type(); ret.reserve(items.size()); auto hasher = std::hash(); using item_type = create_config::item_type; for (auto &v1: items) { auto item = item_type{ .type = ITEM_MESH, .disp_name = v1.name, .name = next_name(), .transform_var = v1.transform_var, }; // TODO: bg_name ignored ret.push_back(item); // create mesh auto mesh = mesh_type::create({.path = v1.model_path}); mesh->set_meta_any(META_SERIES_NAME, (size_t) hasher(v1.name)); mesh->set_meta_any(META_MESH_NO_TRANSFER, true); OBJ_SAVE(item.name, mesh); } return ret; } void augment_manager_v2::record_current_camera_helper(camera_augment_helper_v2 *cam) { pimpl->cam_helper = cam; } camera_augment_helper_v2 *augment_manager_v2::get_current_camera_helper() { return pimpl->cam_helper; }