From 0d5efd0897f2ea6205cb4fd1b27ba703b2446072 Mon Sep 17 00:00:00 2001 From: "k.koide" Date: Sat, 27 Dec 2025 13:07:55 +0900 Subject: [PATCH 01/40] add numpy interfaces --- src/python/glk.cpp | 123 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) diff --git a/src/python/glk.cpp b/src/python/glk.cpp index bd24a79a..fc2095da 100644 --- a/src/python/glk.cpp +++ b/src/python/glk.cpp @@ -18,6 +18,30 @@ namespace py = pybind11; +bool check_valid_points(const py::array_t& points) { + if (points.ndim() != 2) { + std::cerr << "points must be 2-dimensional (ndim=" << points.ndim() << ")" << std::endl; + return false; + } + if (points.shape(1) != 3 && points.shape(1) != 4) { + std::cerr << "points must have 3 or 4 columns (cols=" << points.shape(1) << ")" << std::endl; + return false; + } + return true; +} + +bool check_valid_colors(const py::array_t& points) { + if (points.ndim() != 2) { + std::cerr << "points must be 2-dimensional (ndim=" << points.ndim() << ")" << std::endl; + return false; + } + if (points.shape(1) != 4) { + std::cerr << "points must have 4 columns (cols=" << points.shape(1) << ")" << std::endl; + return false; + } + return true; +} + void define_glk(py::module_& m) { py::module_ gl_ = m.def_submodule("gl", ""); py::module_ glk_ = m.def_submodule("glk", ""); @@ -67,6 +91,36 @@ void define_glk(py::module_& m) { // glk::ThinLines py::class_>(glk_, "ThinLines") + .def( + py::init([](const py::array_t& points, bool line_strip) { + if (!check_valid_points(points)) { + throw std::runtime_error("invalid points array"); + } + + return std::make_shared(points.data(), points.shape(0), line_strip); + }), + py::arg("points"), + py::arg("line_strip") = false) + .def( + py::init([]( + const py::array_t& points, + const py::array_t& colors, + bool line_strip) { + if (!check_valid_points(points)) { + throw std::runtime_error("invalid points array"); + } + if (!check_valid_colors(colors)) { + throw std::runtime_error("invalid colors array"); + } + if (points.shape(0) != colors.shape(0)) { + throw std::runtime_error("points and colors must have the same number of rows"); + } + + return std::make_shared(points.data(), colors.data(), points.shape(0), line_strip); + }), + py::arg("points"), + py::arg("colors"), + py::arg("line_strip") = false) .def( py::init([](const std::vector& points, bool line_strip) { return std::make_shared(points, line_strip); }), "", @@ -134,6 +188,34 @@ void define_glk(py::module_& m) { py::arg("thickness"), py::arg("vertices"), py::arg("colors")) + .def( + py::init([]( + float thickness, + const py::array_t& vertices, + const py::array_t& colors) { + if (!check_valid_points(vertices)) { + throw std::runtime_error("invalid vertices array"); + } + if (!check_valid_colors(colors)) { + throw std::runtime_error("invalid colors array"); + } + if (vertices.shape(0) != colors.shape(0)) { + throw std::runtime_error("vertices and colors must have the same number of rows"); + } + + std::vector> vertices_vec(vertices.shape(0)); + std::vector> colors_vec(colors.shape(0)); + + for (int i = 0; i < vertices.shape(0); i++) { + vertices_vec[i] = Eigen::Vector3f(vertices.at(i, 0), vertices.at(i, 1), vertices.at(i, 2)); + colors_vec[i] = Eigen::Vector4f(colors.at(i, 0), colors.at(i, 1), colors.at(i, 2), colors.at(i, 3)); + } + + return std::make_shared(thickness, vertices_vec, colors_vec); + }), + py::arg("thickness"), + py::arg("vertices"), + py::arg("colors")) // pyplot-like constructor .def( py::init([](const Eigen::VectorXf& x, const Eigen::VectorXf& y, const Eigen::VectorXf& z, const Eigen::VectorXf& c, float line_width, bool line_strip) { @@ -185,15 +267,55 @@ void define_glk(py::module_& m) { // glk::PointCloudBuffer py::class_>(glk_, "PointCloudBuffer") + .def( + py::init([](const py::array_t& points) { + if (!check_valid_points(points)) { + throw std::runtime_error("invalid points array"); + } + + return std::make_shared(points.data(), sizeof(float) * points.shape(1), points.shape(0)); + }), + py::arg("points")) .def(py::init>&>()) + .def( + py::init([](const std::vector>& points) { return std::make_shared(points); }), + py::arg("points")) .def( "add_normals", [](glk::PointCloudBuffer& buffer, const std::vector>& normals) { buffer.add_normals(normals); }, py::arg("normals")) + .def( + "add_normals", + [](glk::PointCloudBuffer& buffer, const py::array_t& normals) { + if (!check_valid_points(normals)) { + throw std::runtime_error("invalid normals array"); + } + + std::vector> normals_vec(normals.shape(0)); + for (int i = 0; i < normals.shape(0); i++) { + normals_vec[i] = Eigen::Vector3f(normals.at(i, 0), normals.at(i, 1), normals.at(i, 2)); + } + buffer.add_normals(normals_vec); + }, + py::arg("normals")) .def( "add_color", [](glk::PointCloudBuffer& buffer, const std::vector>& colors) { buffer.add_color(colors); }, py::arg("colors")) + .def( + "add_color", + [](glk::PointCloudBuffer& buffer, const py::array_t& colors) { + if (!check_valid_colors(colors)) { + throw std::runtime_error("invalid colors array"); + } + + std::vector> colors_vec(colors.shape(0)); + for (int i = 0; i < colors.shape(0); i++) { + colors_vec[i] = Eigen::Vector4f(colors.at(i, 0), colors.at(i, 1), colors.at(i, 2), colors.at(i, 3)); + } + buffer.add_color(colors_vec); + }, + py::arg("colors")) .def( "add_intensity", [](glk::PointCloudBuffer& buffer, glk::COLORMAP colormap, const std::vector& intensities, float scale) { buffer.add_intensity(colormap, intensities, scale); }, @@ -308,6 +430,7 @@ void define_glk(py::module_& m) { .def("set_roughness", &glk::ScreenSpaceLighting::set_roughness, ""); // methods + glk_.def("get_data_path", glk::get_data_path, ""); glk_.def("set_data_path", &glk::set_data_path, ""); glk_.def( "create_pointcloud_buffer", From 36e6e07679317a88fcdd1899084c2e8fea2b3fc8 Mon Sep 17 00:00:00 2001 From: "k.koide" Date: Sun, 28 Dec 2025 17:59:41 +0900 Subject: [PATCH 02/40] more imgui bindings --- src/python/glk.cpp | 38 ++ src/python/imgui.cpp | 1269 ++++++++++++++++++++++++++++++++++++------ src/test/ui_test.py | 575 +++++++++++++++++++ 3 files changed, 1706 insertions(+), 176 deletions(-) create mode 100644 src/test/ui_test.py diff --git a/src/python/glk.cpp b/src/python/glk.cpp index fc2095da..7df80098 100644 --- a/src/python/glk.cpp +++ b/src/python/glk.cpp @@ -381,6 +381,44 @@ void define_glk(py::module_& m) { }, py::arg("image_uint8")); + glk_.def( + "create_texture_f", + [](py::array_t arr) -> std::shared_ptr { + if (arr.ndim() != 2 && arr.ndim() != 3) { + std::cerr << "ndim must be 2 or 3 (ndim=" << arr.ndim() << ")" << std::endl; + return nullptr; + } + + const int height = arr.shape(0); + const int width = arr.shape(1); + + if (arr.ndim() == 2) { + return std::make_shared(Eigen::Vector2i(width, height), GL_RGBA, GL_RED, GL_FLOAT, arr.data()); + } + + GLuint format = GL_BGR; + switch (arr.shape(2)) { + default: + std::cerr << "warning: invalid ch=" << arr.shape(2) << std::endl; + break; + case 1: + format = GL_RED; + break; + case 2: + format = GL_RG; + break; + case 3: + format = GL_BGR; + break; + case 4: + format = GL_BGRA; + break; + } + + return std::make_shared(Eigen::Vector2i(width, height), GL_RGBA, format, GL_FLOAT, arr.data()); + }, + py::arg("image_float")); + // glk::ScreenEffect py::class_>(glk_, "ScreenEffect"); py::class_>(glk_, "NaiveScreenSpaceAmbientOcclusion") diff --git a/src/python/imgui.cpp b/src/python/imgui.cpp index e90faf6b..8c2f8dbf 100644 --- a/src/python/imgui.cpp +++ b/src/python/imgui.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -77,6 +78,43 @@ void define_imgui(py::module_& m) { imgui_.attr("ColorEditFlags_InputRGB") = py::int_(static_cast(ImGuiColorEditFlags_NoAlpha)); imgui_.attr("ColorEditFlags_InputHSV") = py::int_(static_cast(ImGuiColorEditFlags_NoAlpha)); + imgui_.attr("TableFlags_None") = py::int_(static_cast(ImGuiTableFlags_None)); + imgui_.attr("TableFlags_Resizable") = py::int_(static_cast(ImGuiTableFlags_Resizable)); + imgui_.attr("TableFlags_Reorderable") = py::int_(static_cast(ImGuiTableFlags_Reorderable)); + imgui_.attr("TableFlags_Hideable") = py::int_(static_cast(ImGuiTableFlags_Hideable)); + imgui_.attr("TableFlags_Sortable") = py::int_(static_cast(ImGuiTableFlags_Sortable)); + imgui_.attr("TableFlags_NoSavedSettings") = py::int_(static_cast(ImGuiTableFlags_NoSavedSettings)); + imgui_.attr("TableFlags_ContextMenuInBody") = py::int_(static_cast(ImGuiTableFlags_ContextMenuInBody)); + imgui_.attr("TableFlags_RowBg") = py::int_(static_cast(ImGuiTableFlags_RowBg)); + imgui_.attr("TableFlags_BordersInnerH") = py::int_(static_cast(ImGuiTableFlags_BordersInnerH)); + imgui_.attr("TableFlags_BordersOuterH") = py::int_(static_cast(ImGuiTableFlags_BordersOuterH)); + imgui_.attr("TableFlags_BordersInnerV") = py::int_(static_cast(ImGuiTableFlags_BordersInnerV)); + imgui_.attr("TableFlags_BordersOuterV") = py::int_(static_cast(ImGuiTableFlags_BordersOuterV)); + imgui_.attr("TableFlags_BordersH") = py::int_(static_cast(ImGuiTableFlags_BordersH)); + imgui_.attr("TableFlags_BordersV") = py::int_(static_cast(ImGuiTableFlags_BordersV)); + imgui_.attr("TableFlags_BordersInner") = py::int_(static_cast(ImGuiTableFlags_BordersInner)); + imgui_.attr("TableFlags_BordersOuter") = py::int_(static_cast(ImGuiTableFlags_BordersOuter)); + imgui_.attr("TableFlags_Borders") = py::int_(static_cast(ImGuiTableFlags_Borders)); + imgui_.attr("TableFlags_NoBordersInBody") = py::int_(static_cast(ImGuiTableFlags_NoBordersInBody)); + imgui_.attr("TableFlags_NoBordersInBodyUntilResize") = py::int_(static_cast(ImGuiTableFlags_NoBordersInBodyUntilResize)); + imgui_.attr("TableFlags_SizingFixedFit") = py::int_(static_cast(ImGuiTableFlags_SizingFixedFit)); + imgui_.attr("TableFlags_SizingFixedSame") = py::int_(static_cast(ImGuiTableFlags_SizingFixedSame)); + imgui_.attr("TableFlags_SizingStretchProp") = py::int_(static_cast(ImGuiTableFlags_SizingStretchProp)); + imgui_.attr("TableFlags_SizingStretchSame") = py::int_(static_cast(ImGuiTableFlags_SizingStretchSame)); + imgui_.attr("TableFlags_NoHostExtendX") = py::int_(static_cast(ImGuiTableFlags_NoHostExtendX)); + imgui_.attr("TableFlags_NoHostExtendY") = py::int_(static_cast(ImGuiTableFlags_NoHostExtendY)); + imgui_.attr("TableFlags_NoKeepColumnsVisible") = py::int_(static_cast(ImGuiTableFlags_NoKeepColumnsVisible)); + imgui_.attr("TableFlags_PreciseWidths") = py::int_(static_cast(ImGuiTableFlags_PreciseWidths)); + imgui_.attr("TableFlags_NoClip") = py::int_(static_cast(ImGuiTableFlags_NoClip)); + imgui_.attr("TableFlags_PadOuterX") = py::int_(static_cast(ImGuiTableFlags_PadOuterX)); + imgui_.attr("TableFlags_NoPadOuterX") = py::int_(static_cast(ImGuiTableFlags_NoPadOuterX)); + imgui_.attr("TableFlags_NoPadInnerX") = py::int_(static_cast(ImGuiTableFlags_NoPadInnerX)); + imgui_.attr("TableFlags_ScrollX") = py::int_(static_cast(ImGuiTableFlags_ScrollX)); + imgui_.attr("TableFlags_ScrollY") = py::int_(static_cast(ImGuiTableFlags_ScrollY)); + imgui_.attr("TableFlags_SortMulti") = py::int_(static_cast(ImGuiTableFlags_SortMulti)); + imgui_.attr("TableFlags_SortTristate") = py::int_(static_cast(ImGuiTableFlags_SortTristate)); + imgui_.attr("TableFlags_SizingMask_") = py::int_(static_cast(ImGuiTableFlags_SizingMask_)); + // macros imgui_.def("IM_COL32", [](int r, int g, int b, int a) { return IM_COL32(r, g, b, a); }, py::arg("r"), py::arg("g"), py::arg("b"), py::arg("a")); @@ -87,9 +125,169 @@ void define_imgui(py::module_& m) { .def(py::init([](py::array_t x) { auto r = x.unchecked<1>(); return std::make_unique(r(0), r(1)); - })); + })) + .def_readwrite("x", &ImVec2::x) + .def_readwrite("y", &ImVec2::y); + + py::class_(imgui_, "ImVec4", py::buffer_protocol()) + .def_buffer([](ImVec4& m) -> py::buffer_info { return py::buffer_info(&m.x, sizeof(float), py::format_descriptor::format(), 1, {4}, {sizeof(float)}); }) + .def(py::init([](float x, float y, float z, float w) { return std::make_unique(x, y, z, w); })) + .def(py::init([](py::array_t x) { + auto r = x.unchecked<1>(); + return std::make_unique(r(0), r(1), r(2), r(3)); + })) + .def_readwrite("x", &ImVec4::x) + .def_readwrite("y", &ImVec4::y) + .def_readwrite("z", &ImVec4::z) + .def_readwrite("w", &ImVec4::w); + + // IO + py::class_(imgui_, "IO") + .def_readonly("want_capture_mouse", &ImGuiIO::WantCaptureMouse) + .def_readonly("want_capture_keyboard", &ImGuiIO::WantCaptureKeyboard) + .def_readonly("framerate", &ImGuiIO::Framerate) + .def_readonly("delta_time", &ImGuiIO::DeltaTime) + + .def_property_readonly("mouse_pos", [](const ImGuiIO& io) { return py::array(2, &io.MousePos.x); }) + .def_property_readonly("mouse_down", [](const ImGuiIO& io) { return py::array(5, io.MouseDown); }) + .def_property_readonly("mouse_clicked", [](const ImGuiIO& io) { return py::array(5, io.MouseClicked); }) + + .def_readonly("mouse_wheel", &ImGuiIO::MouseWheel) + .def_readonly("mouse_wheel_h", &ImGuiIO::MouseWheelH) + .def_readonly("key_ctrl", &ImGuiIO::KeyCtrl) + .def_readonly("key_shift", &ImGuiIO::KeyShift) + .def_readonly("key_alt", &ImGuiIO::KeyAlt) + .def_readonly("key_super", &ImGuiIO::KeySuper) + .def_property_readonly("keys_down", [](const ImGuiIO& io) { return py::array(512, io.KeysDown); }) + .def_property_readonly("nav_inputs", [](const ImGuiIO& io) { return py::array(ImGuiNavInput_COUNT, io.NavInputs); }); + + py::class_(imgui_, "Style") + .def_readwrite("alpha", &ImGuiStyle::Alpha) + .def_readwrite("disabled_alpha", &ImGuiStyle::DisabledAlpha) + .def_readwrite("window_padding", &ImGuiStyle::WindowPadding) + .def_readwrite("window_rounding", &ImGuiStyle::WindowRounding) + .def_readwrite("window_border_size", &ImGuiStyle::WindowBorderSize) + .def_readwrite("window_min_size", &ImGuiStyle::WindowMinSize) + .def_readwrite("window_title_align", &ImGuiStyle::WindowTitleAlign) + .def_readwrite("window_menu_button_position", &ImGuiStyle::WindowMenuButtonPosition) + .def_readwrite("child_rounding", &ImGuiStyle::ChildRounding) + .def_readwrite("child_border_size", &ImGuiStyle::ChildBorderSize) + .def_readwrite("popup_rounding", &ImGuiStyle::PopupRounding) + .def_readwrite("popup_border_size", &ImGuiStyle::PopupBorderSize) + .def_readwrite("frame_padding", &ImGuiStyle::FramePadding) + .def_readwrite("frame_rounding", &ImGuiStyle::FrameRounding) + .def_readwrite("frame_border_size", &ImGuiStyle::FrameBorderSize) + .def_readwrite("item_spacing", &ImGuiStyle::ItemSpacing) + .def_readwrite("item_inner_spacing", &ImGuiStyle::ItemInnerSpacing) + .def_readwrite("cell_padding", &ImGuiStyle::CellPadding) + .def_readwrite("touch_extra_padding", &ImGuiStyle::TouchExtraPadding) + .def_readwrite("indent_spacing", &ImGuiStyle::IndentSpacing) + .def_readwrite("columns_min_spacing", &ImGuiStyle::ColumnsMinSpacing) + .def_readwrite("scrollbar_size", &ImGuiStyle::ScrollbarSize) + .def_readwrite("scrollbar_rounding", &ImGuiStyle::ScrollbarRounding) + .def_readwrite("grab_min_size", &ImGuiStyle::GrabMinSize) + .def_readwrite("grab_rounding", &ImGuiStyle::GrabRounding) + .def_readwrite("tab_rounding", &ImGuiStyle::TabRounding) + .def_readwrite("tab_border_size", &ImGuiStyle::TabBorderSize) + .def_readwrite("tab_min_width_for_close_button", &ImGuiStyle::TabMinWidthForCloseButton) + .def_readwrite("color_button_position", &ImGuiStyle::ColorButtonPosition) + .def_readwrite("button_text_align", &ImGuiStyle::ButtonTextAlign) + .def_readwrite("selectable_text_align", &ImGuiStyle::SelectableTextAlign) + .def_readwrite("display_window_padding", &ImGuiStyle::DisplayWindowPadding) + .def_readwrite("display_safe_area_padding", &ImGuiStyle::DisplaySafeAreaPadding) + .def_readwrite("mouse_cursor_scale", &ImGuiStyle::MouseCursorScale) + .def_readwrite("anti_aliased_lines", &ImGuiStyle::AntiAliasedLines) + .def_readwrite("anti_aliased_lines_use_tex", &ImGuiStyle::AntiAliasedLinesUseTex) + .def_readwrite("anti_aliased_fill", &ImGuiStyle::AntiAliasedFill) + .def_readwrite("curve_tessellation_tol", &ImGuiStyle::CurveTessellationTol) + .def_readwrite("circle_tessellation_max_error", &ImGuiStyle::CircleTessellationMaxError) + .def_property_readonly("colors", [](ImGuiStyle& style) { + py::list color_list; + for (int i = 0; i < ImGuiCol_COUNT; ++i) { + color_list.append(py::array(4, &style.Colors[i].x)); + } + return color_list; + }); + + // DrawList + py::class_>(imgui_, "ImDrawList") + .def( + "add_line", + [](ImDrawList* draw_list, const Eigen::Vector2i& p0, const Eigen::Vector2i& p1, unsigned int color, float thickness) { + draw_list->AddLine(ImVec2(p0[0], p0[1]), ImVec2(p1[0], p1[1]), color, thickness); + }, + py::arg("p0"), + py::arg("p1"), + py::arg("col"), + py::arg("thickness") = 1.0f) + .def( + "add_rect_filled", + [](ImDrawList* draw_list, const Eigen::Vector2i& p0, const Eigen::Vector2i& p1, unsigned int color, float rounding, int flags) { + draw_list->AddRectFilled(ImVec2(p0[0], p0[1]), ImVec2(p1[0], p1[1]), color, rounding, flags); + }, + py::arg("p0"), + py::arg("p1"), + py::arg("color"), + py::arg("rounding") = 0.0f, + py::arg("flags") = 0) + .def( + "add_rect", + [](ImDrawList* draw_list, const Eigen::Vector2i& p0, const Eigen::Vector2i& p1, unsigned int color, float rounding, int flags, float thickness) { + draw_list->AddRect(ImVec2(p0[0], p0[1]), ImVec2(p1[0], p1[1]), color, rounding, flags, thickness); + }, + py::arg("p0"), + py::arg("p1"), + py::arg("color"), + py::arg("rounding") = 0.0f, + py::arg("flags") = 0, + py::arg("thickness") = 1.0f) + .def( + "add_circle", + [](ImDrawList* draw_list, const Eigen::Vector2i& center, float radius, unsigned int color, int num_segments, float thickness) { + draw_list->AddCircle(ImVec2(center[0], center[1]), radius, color, num_segments, thickness); + }, + py::arg("center"), + py::arg("radius"), + py::arg("color"), + py::arg("num_segments") = 0, + py::arg("thickness") = 1.0f) + .def( + "add_circle_filled", + [](ImDrawList* draw_list, const Eigen::Vector2i& center, float radius, unsigned int color, int num_segments) { + draw_list->AddCircleFilled(ImVec2(center[0], center[1]), radius, color, num_segments); + }, + py::arg("center"), + py::arg("radius"), + py::arg("color"), + py::arg("num_segments") = 0) + .def( + "add_text", + [](ImDrawList* draw_list, const Eigen::Vector2i& pos, unsigned int color, const std::string& text) { draw_list->AddText(ImVec2(pos[0], pos[1]), color, text.c_str()); }, + py::arg("pos"), + py::arg("color"), + py::arg("text")) + // + ; // functions + imgui_.def("get_io", [] { return ImGui::GetIO(); }); + imgui_.def("get_style", [] { return ImGui::GetStyle(); }); + + // Demo, Debug, Information + imgui_.def("show_demo_window", [] { ImGui::ShowDemoWindow(); }); + imgui_.def("show_metrics_window", [] { ImGui::ShowMetricsWindow(); }); + imgui_.def("show_debug_log_window", [] { ImGui::ShowDebugLogWindow(); }); + imgui_.def("show_style_editor", [] { ImGui::ShowStyleEditor(); }); + imgui_.def("show_style_selector", [](const std::string& label) { ImGui::ShowStyleSelector(label.c_str()); }, py::arg("label")); + imgui_.def("show_font_selector", [](const std::string& label) { ImGui::ShowFontSelector(label.c_str()); }, py::arg("label")); + imgui_.def("get_version", [] { return ImGui::GetVersion(); }); + + // Styles + imgui_.def("style_colors_dark", &ImGui::StyleColorsDark, py::arg("dst") = nullptr); + imgui_.def("style_colors_light", &ImGui::StyleColorsLight, py::arg("dst") = nullptr); + imgui_.def("style_colors_classic", &ImGui::StyleColorsClassic, py::arg("dst") = nullptr); + + // Windows imgui_.def( "begin", [](const std::string& name, bool open, int flags) { return std::make_tuple(ImGui::Begin(name.c_str(), &open, flags), open); }, @@ -97,19 +295,35 @@ void define_imgui(py::module_& m) { py::arg("open") = true, py::arg("flags") = 0); imgui_.def("end", [] { ImGui::End(); }); - imgui_.def("get_id", [](const std::string& name) { return ImGui::GetID(name.c_str()); }, py::arg("name")); - imgui_.def("open_popup", [](const std::string& name) { ImGui::OpenPopup(name.c_str()); }, py::arg("name")); - imgui_.def("begin_popup", &ImGui::BeginPopup, py::arg("id"), py::arg("flags")); + // Child Windows imgui_.def( - "begin_popup_modal", - [](const std::string& name, bool open, int flags) { return std::make_tuple(ImGui::BeginPopupModal(name.c_str(), &open, flags), open); }, - py::arg("name"), - py::arg("open") = true, + "begin_child", + [](const std::string& str_id, const Eigen::Vector2i& size, bool border, int flags) { return ImGui::BeginChild(str_id.c_str(), ImVec2(size[0], size[1]), border, flags); }, + py::arg("str_id"), + py::arg("size") = Eigen::Vector2i(0, 0), + py::arg("border") = false, py::arg("flags") = 0); - imgui_.def("end_popup", &ImGui::EndPopup); - imgui_.def("close_current_popup", &ImGui::CloseCurrentPopup); + imgui_.def("end_child", &ImGui::EndChild); + + // Windows Utilities + imgui_.def("is_window_appearing", &ImGui::IsWindowAppearing); + imgui_.def("is_window_collapsed", &ImGui::IsWindowCollapsed); + imgui_.def("is_window_focused", &ImGui::IsWindowFocused, py::arg("flags") = 0); + imgui_.def("is_window_hovered", &ImGui::IsWindowHovered, py::arg("flags") = 0); + imgui_.def("get_window_draw_list", &ImGui::GetWindowDrawList, py::return_value_policy::reference); + imgui_.def("get_window_pos", [] { + ImVec2 pos = ImGui::GetWindowPos(); + return Eigen::Vector2i(static_cast(pos.x), static_cast(pos.y)); + }); + imgui_.def("get_window_size", [] { + ImVec2 size = ImGui::GetWindowSize(); + return Eigen::Vector2i(static_cast(size.x), static_cast(size.y)); + }); + imgui_.def("get_window_width", &ImGui::GetWindowWidth); + imgui_.def("get_window_height", &ImGui::GetWindowHeight); + // Window manipulation imgui_.def( "set_next_window_pos", [](const Eigen::Vector2i& pos, int cond, const Eigen::Vector2i& pivot) { ImGui::SetNextWindowPos(ImVec2(pos[0], pos[1]), cond, ImVec2(pivot[0], pivot[1])); }, @@ -119,29 +333,130 @@ void define_imgui(py::module_& m) { py::arg("pivot") = Eigen::Vector2i(0, 0)); imgui_ .def("set_next_window_size", [](const Eigen::Vector2i& size, int cond) { ImGui::SetNextWindowSize(ImVec2(size[0], size[1]), cond); }, "", py::arg("size"), py::arg("cond") = 0); + imgui_.def( + "set_next_window_size_constraints", + [](const Eigen::Vector2i& size_min, const Eigen::Vector2i& size_max) { + ImGui::SetNextWindowSizeConstraints(ImVec2(size_min[0], size_min[1]), ImVec2(size_max[0], size_max[1])); + }, + "", + py::arg("size_min"), + py::arg("size_max")); + imgui_.def("set_next_window_content_size", [](const Eigen::Vector2i& size) { ImGui::SetNextWindowContentSize(ImVec2(size[0], size[1])); }, "", py::arg("size")); + imgui_.def("set_next_window_collapsed", &ImGui::SetNextWindowCollapsed, py::arg("collapsed"), py::arg("cond") = 0); + imgui_.def("set_next_window_focus", &ImGui::SetNextWindowFocus); + imgui_.def("set_next_window_scroll", [](const Eigen::Vector2i& scroll) { ImGui::SetNextWindowScroll(ImVec2(scroll[0], scroll[1])); }, py::arg("scroll")); + imgui_.def("set_next_window_bg_alpha", &ImGui::SetNextWindowBgAlpha, py::arg("alpha")); + imgui_.def("set_window_pos", [](const Eigen::Vector2i& pos, int cond) { ImGui::SetWindowPos(ImVec2(pos[0], pos[1]), cond); }, py::arg("pos"), py::arg("cond") = 0); + imgui_.def("set_window_size", [](const Eigen::Vector2i& size, int cond) { ImGui::SetWindowSize(ImVec2(size[0], size[1]), cond); }, py::arg("size"), py::arg("cond") = 0); + imgui_.def("set_window_collapsed", [](bool collapsed, int cond) { ImGui::SetWindowCollapsed(collapsed, cond); }, py::arg("collapsed"), py::arg("cond") = 0); + imgui_.def("set_window_focus", [] { ImGui::SetWindowFocus(); }); + imgui_.def("set_window_font_scale", &ImGui::SetWindowFontScale, py::arg("scale")); + imgui_.def( + "set_window_pos", + [](const std::string& name, const Eigen::Vector2i& pos, int cond) { ImGui::SetWindowPos(name.c_str(), ImVec2(pos[0], pos[1]), cond); }, + py::arg("name"), + py::arg("pos"), + py::arg("cond") = 0); + imgui_.def( + "set_window_size", + [](const std::string& name, const Eigen::Vector2i& size, int cond) { ImGui::SetWindowSize(name.c_str(), ImVec2(size[0], size[1]), cond); }, + py::arg("name"), + py::arg("size"), + py::arg("cond") = 0); + imgui_.def( + "set_window_collapsed", + [](const std::string& name, bool collapsed, int cond) { ImGui::SetWindowCollapsed(name.c_str(), collapsed, cond); }, + py::arg("name"), + py::arg("collapsed"), + py::arg("cond") = 0); + imgui_.def("set_window_focus", [](const std::string& name) { ImGui::SetWindowFocus(name.c_str()); }, py::arg("name")); + + // Content region + imgui_.def("get_content_region_avail", [] { + ImVec2 size = ImGui::GetContentRegionAvail(); + return Eigen::Vector2f(size.x, size.y); + }); + imgui_.def("get_content_region_max", [] { + ImVec2 size = ImGui::GetContentRegionMax(); + return Eigen::Vector2f(size.x, size.y); + }); + imgui_.def("get_window_content_region_min", [] { + ImVec2 size = ImGui::GetWindowContentRegionMin(); + return Eigen::Vector2f(size.x, size.y); + }); + imgui_.def("get_window_content_region_max", [] { + ImVec2 size = ImGui::GetWindowContentRegionMax(); + return Eigen::Vector2f(size.x, size.y); + }); + + // Parameters stacks (shared) + imgui_.def("push_button_repeat", &ImGui::PushButtonRepeat, py::arg("repeat")); + imgui_.def("pop_button_repeat", &ImGui::PopButtonRepeat); + // Parameters stacks (current window) + imgui_.def("push_item_width", &ImGui::PushItemWidth, py::arg("item_width")); + imgui_.def("pop_item_width", &ImGui::PopItemWidth); + imgui_.def("set_next_item_width", &ImGui::SetNextItemWidth, py::arg("item_width")); + imgui_.def("calc_item_width", &ImGui::CalcItemWidth); + imgui_.def("push_text_wrap_pos", &ImGui::PushTextWrapPos, py::arg("wrap_local_pos_x") = 0.0f); + imgui_.def("pop_text_wrap_pos", &ImGui::PopTextWrapPos); + + // Cursor / Layout imgui_.def("separator", &ImGui::Separator); imgui_.def("same_line", &ImGui::SameLine, "", py::arg("offset_from_start_x") = 0.0, py::arg("spacing") = -1.0); imgui_.def("newline", &ImGui::NewLine); imgui_.def("spacing", &ImGui::Spacing); + imgui_.def("dummy", [](const Eigen::Vector2i& size) { ImGui::Dummy(ImVec2(size[0], size[1])); }, py::arg("size")); + imgui_.def("indent", &ImGui::Indent, py::arg("indent_w") = 0.0f); + imgui_.def("unindent", &ImGui::Unindent, py::arg("indent_w") = 0.0f); + imgui_.def("begin_group", &ImGui::BeginGroup); + imgui_.def("end_group", &ImGui::EndGroup); + imgui_.def("get_cursor_pos", [] { + ImVec2 pos = ImGui::GetCursorPos(); + return Eigen::Vector2f(pos.x, pos.y); + }); + imgui_.def("get_cursor_pos_x", &ImGui::GetCursorPosX); + imgui_.def("get_cursor_pos_y", &ImGui::GetCursorPosY); + imgui_.def("set_cursor_pos", [](const Eigen::Vector2f& pos) { ImGui::SetCursorPos(ImVec2(pos[0], pos[1])); }, py::arg("pos")); + imgui_.def("set_cursor_pos_x", &ImGui::SetCursorPosX, py::arg("x")); + imgui_.def("set_cursor_pos_y", &ImGui::SetCursorPosY, py::arg("y")); + imgui_.def("get_cursor_screen_pos", [] { + ImVec2 pos = ImGui::GetCursorScreenPos(); + return Eigen::Vector2f(pos.x, pos.y); + }); + imgui_.def("set_cursor_screen_pos", [](const Eigen::Vector2f& pos) { ImGui::SetCursorScreenPos(ImVec2(pos[0], pos[1])); }, py::arg("pos")); + imgui_.def("align_text_to_frame_padding", &ImGui::AlignTextToFramePadding); + imgui_.def("get_text_line_height", &ImGui::GetTextLineHeight); + imgui_.def("get_text_line_height_with_spacing", &ImGui::GetTextLineHeightWithSpacing); + imgui_.def("get_frame_height", &ImGui::GetFrameHeight); + imgui_.def("get_frame_height_with_spacing", &ImGui::GetFrameHeightWithSpacing); + + // ID stack/scopes + imgui_.def("push_id", [](const std::string& str_id) { ImGui::PushID(str_id.c_str()); }, py::arg("str_id")); + imgui_.def("pop_id", &ImGui::PopID); + imgui_.def("get_id", [](const std::string& name) { return ImGui::GetID(name.c_str()); }, py::arg("name")); + // Widgets: Text + imgui_.def("text_unformatted", [](const std::string& text) { ImGui::TextUnformatted(text.c_str()); }, py::arg("text")); imgui_.def("text", [](const std::string& text) { ImGui::Text("%s", text.c_str()); }, py::arg("text")); imgui_.def( - "input_text", - [](const std::string& label, const std::string& text, int flags, int buffer_size) { - std::vector buffer(buffer_size, 0); - std::copy(text.begin(), text.end(), buffer.begin()); - const bool changed = ImGui::InputText(label.c_str(), buffer.data(), buffer_size, flags); - return std::make_pair(changed, std::string(buffer.data())); - }, + "text_colored", + [](const Eigen::Vector4f& col, const std::string& text) { ImGui::TextColored(ImVec4(col[0], col[1], col[2], col[3]), "%s", text.c_str()); }, + py::arg("col"), + py::arg("text")); + imgui_.def("text_disabled", [](const std::string& text) { ImGui::TextDisabled("%s", text.c_str()); }, py::arg("text")); + imgui_.def("text_wrapped", [](const std::string& text) { ImGui::TextWrapped("%s", text.c_str()); }, py::arg("text")); + imgui_.def("label_text", [](const std::string& label, const std::string& text) { ImGui::LabelText(label.c_str(), "%s", text.c_str()); }, py::arg("label"), py::arg("text")); + imgui_.def("bullet_text", [](const std::string& text) { ImGui::BulletText("%s", text.c_str()); }, py::arg("text")); + + // Widgets: Main + imgui_.def( + "button", + [](const std::string& label, const Eigen::Vector2i& size) { return ImGui::Button(label.c_str(), ImVec2(size[0], size[1])); }, "", py::arg("label"), - py::arg("text"), - py::arg("flags") = 0, - py::arg("buffer_size") = 256); - imgui_.def("button", [](const std::string& label) { return ImGui::Button(label.c_str()); }, py::arg("label")); - imgui_.def("arrow_button", ImGui::ArrowButton, py::arg("id"), py::arg("dir")); - + py::arg("size") = Eigen::Vector2i(0, 0)); + imgui_.def("small_button", [](const std::string& label) { return ImGui::SmallButton(label.c_str()); }, "", py::arg("label")); imgui_.def( "invisible_button", [](const std::string& id, const Eigen::Vector2i& size, int flags) { return ImGui::InvisibleButton(id.c_str(), ImVec2(size[0], size[1]), flags); }, @@ -149,37 +464,30 @@ void define_imgui(py::module_& m) { py::arg("id"), py::arg("size"), py::arg("flags") = 0); - + imgui_.def("arrow_button", ImGui::ArrowButton, py::arg("id"), py::arg("dir")); imgui_.def("checkbox", [](const std::string& label, bool v) { return std::make_tuple(ImGui::Checkbox(label.c_str(), &v), v); }, py::arg("label"), py::arg("v")); imgui_.def( - "drag_int", - [](const std::string& label, int v, int v_speed, int v_min, int v_max, const std::string& format) { - return std::make_tuple(ImGui::DragInt(label.c_str(), &v, v_speed, v_min, v_max, format.c_str()), v); - }, - "", + "checkbox_flags", + [](const std::string& label, int flags, int flags_value) { return std::make_tuple(ImGui::CheckboxFlags(label.c_str(), &flags, flags_value), flags); }, py::arg("label"), - py::arg("v"), - py::arg("v_speed") = 1, - py::arg("v_min") = 0, - py::arg("v_max") = 0, - py::arg("format") = "%d"); + py::arg("flags"), + py::arg("flags_value")); + imgui_.def("radio_button", [](const std::string& label, bool active) { return ImGui::RadioButton(label.c_str(), active); }, py::arg("label"), py::arg("active")); imgui_.def( - "drag_float", - [](const std::string& label, float v, float v_speed, float v_min, float v_max, const std::string& format, float power) { - return std::make_tuple(ImGui::DragFloat(label.c_str(), &v, v_speed, v_min, v_max, format.c_str(), power), v); - }, - "", + "radio_button_int", + [](const std::string& label, int v, int v_button) { return std::make_tuple(ImGui::RadioButton(label.c_str(), &v, v_button), v); }, py::arg("label"), py::arg("v"), - py::arg("v_speed") = 1.0f, - py::arg("v_min") = 0.0f, - py::arg("v_max") = 0.0f, - py::arg("format") = "%.3f", - py::arg("power") = 1.0f); - - imgui_.def("push_button_repeat", &ImGui::PushButtonRepeat, py::arg("repeat")); - imgui_.def("pop_button_repeat", &ImGui::PopButtonRepeat); + py::arg("v_button")); + imgui_.def( + "progress_bar", + [](float fraction, const Eigen::Vector2i& size, const std::string& overlay) { ImGui::ProgressBar(fraction, ImVec2(size[0], size[1]), overlay.c_str()); }, + py::arg("fraction"), + py::arg("size") = Eigen::Vector2i(-FLT_MIN, 0), + py::arg("overlay") = ""); + imgui_.def("bullet", &ImGui::Bullet); + // Widgets: Images imgui_.def( "image", []( @@ -204,157 +512,766 @@ void define_imgui(py::module_& m) { py::arg("uv1") = Eigen::Vector2f(1.0, 1.0), py::arg("tint_col") = Eigen::Vector4f(1.0f, 1.0f, 1.0f, 1.0f), py::arg("border_col") = Eigen::Vector4f(0.0f, 0.0f, 0.0f, 1.0f)); - - // Tab bars - imgui_.def("begin_tab_bar", &ImGui::BeginTabBar, py::arg("id"), py::arg("flags") = 0); - imgui_.def("end_tab_bar", &ImGui::EndTabBar); - imgui_.def("begin_tab_item", [](const char* label) { return ImGui::BeginTabItem(label); }, py::arg("label")); - imgui_.def("end_tab_item", &ImGui::EndTabItem); - imgui_.def("tab_item_button", &ImGui::TabItemButton, py::arg("label"), py::arg("flags") = 0); - - // color imgui_.def( - "color_edit4", - [](const std::string& label, const Eigen::Vector4f& color, int flags) { - Eigen::Vector4f col = color; - const bool changed = ImGui::ColorEdit4(label.c_str(), col.data(), flags); - return std::make_pair(changed, col); + "image_button", + []( + const std::string& str_id, + const std::shared_ptr& texture, + const Eigen::Vector2i& size, + const Eigen::Vector2f& uv0, + const Eigen::Vector2f& uv1, + const Eigen::Vector4f& bg_col, + const Eigen::Vector4f& tint_col) { + return ImGui::ImageButton( + str_id.c_str(), + reinterpret_cast(texture->id()), + ImVec2(size[0], size[1]), + ImVec2(uv0[0], uv0[1]), + ImVec2(uv1[0], uv1[1]), + ImVec4(bg_col[0], bg_col[1], bg_col[2], bg_col[3]), + ImVec4(tint_col[0], tint_col[1], tint_col[2], tint_col[3])); }, - py::arg("label"), - py::arg("color"), - py::arg("flags") = 0); - - imgui_.def("show_demo_window", [] { ImGui::ShowDemoWindow(); }); + "", + py::arg("str_id"), + py::arg("texture"), + py::arg("size"), + py::arg("uv0") = Eigen::Vector2f(0.0, 0.0), + py::arg("uv1") = Eigen::Vector2f(1.0, 1.0), + py::arg("bg_col") = Eigen::Vector4f(0.0f, 0.0f, 0.0f, 0.0f), + py::arg("tint_col") = Eigen::Vector4f(1.0f, 1.0f, 1.0f, 1.0f)); - // Docking + // Widgets: Combo Box (Dropdown) imgui_.def( - "dockspace", - [](unsigned int id, const Eigen::Vector2i& size, int flags) { return ImGui::DockSpace(id, ImVec2(size[0], size[1]), flags); }, - py::arg("id"), - py::arg("size") = Eigen::Vector2i(0, 0), + "begin_combo", + [](const std::string& label, const std::string& preview_value, int flags) { return ImGui::BeginCombo(label.c_str(), preview_value.c_str(), flags); }, + "", + py::arg("label"), + py::arg("preview_value"), py::arg("flags") = 0); - imgui_.def("dockspace_over_viewport", [](int flags) { return ImGui::DockSpaceOverViewport(nullptr, flags); }, py::arg("flags") = 0); - imgui_.def("set_next_window_dock_id", &ImGui::SetNextWindowDockID, py::arg("dock_id"), py::arg("cond") = 0); - - // Dock builder - imgui_.def("dock_builder_dock_window", &ImGui::DockBuilderDockWindow, py::arg("window_name"), py::arg("node_id")); - imgui_.def("dock_builder_add_node", &ImGui::DockBuilderAddNode, py::arg("node_id") = 0, py::arg("flags") = 0); - imgui_.def("dock_builder_remove_node", &ImGui::DockBuilderRemoveNode, py::arg("node_id")); + imgui_.def("end_combo", &ImGui::EndCombo); imgui_.def( - "dock_builder_split_node", - [](unsigned int node_id, int split_dir, float size_ratio_for_node_at_dir) -> std::pair { - ImGuiID id_at_dir, id_at_opposite_dir; - ImGui::DockBuilderSplitNode(node_id, split_dir, size_ratio_for_node_at_dir, &id_at_dir, &id_at_opposite_dir); - return std::make_pair(id_at_dir, id_at_opposite_dir); + "combo", + [](const std::string& label, int current_item, const std::vector& items, int popup_max_height_in_items) { + std::vector item_cstrs; + for (const auto& item : items) { + item_cstrs.push_back(item.c_str()); + } + return std::make_tuple(ImGui::Combo(label.c_str(), ¤t_item, item_cstrs.data(), static_cast(item_cstrs.size()), popup_max_height_in_items), current_item); }, - py::arg("node_id"), - py::arg("split_dir"), - py::arg("size_ratio_for_node_at_dir")); - imgui_.def("dock_builder_finish", [](unsigned int node_id) { ImGui::DockBuilderFinish(node_id); }, py::arg("node_id")); + "", + py::arg("label"), + py::arg("current_item"), + py::arg("items"), + py::arg("popup_max_height_in_items") = -1); - // DrawList - py::class_>(imgui_, "ImDrawList") - .def( - "add_line", - [](ImDrawList* draw_list, const Eigen::Vector2i& p0, const Eigen::Vector2i& p1, unsigned int color, float thickness) { - draw_list->AddLine(ImVec2(p0[0], p0[1]), ImVec2(p1[0], p1[1]), color, thickness); - }, - py::arg("p0"), - py::arg("p1"), - py::arg("col"), - py::arg("thickness") = 1.0f) - .def( - "add_rect_filled", - [](ImDrawList* draw_list, const Eigen::Vector2i& p0, const Eigen::Vector2i& p1, unsigned int color) { - draw_list->AddRectFilled(ImVec2(p0[0], p0[1]), ImVec2(p1[0], p1[1]), color); - }, - py::arg("p0"), - py::arg("p1"), - py::arg("color")) - .def( - "add_rect", - [](ImDrawList* draw_list, const Eigen::Vector2i& p0, const Eigen::Vector2i& p1, unsigned int color) { - draw_list->AddRect(ImVec2(p0[0], p0[1]), ImVec2(p1[0], p1[1]), color); - }, - py::arg("p0"), - py::arg("p1"), - py::arg("color")) - .def( - "add_circle", - [](ImDrawList* draw_list, const Eigen::Vector2i& center, float radius, unsigned int color, int num_segments, float thickness) { - draw_list->AddCircle(ImVec2(center[0], center[1]), radius, color, num_segments, thickness); - }, - py::arg("center"), - py::arg("radius"), - py::arg("color"), - py::arg("num_segments") = 0, - py::arg("thickness") = 1.0f) - .def( - "add_circle_filled", - [](ImDrawList* draw_list, const Eigen::Vector2i& center, float radius, unsigned int color, int num_segments) { - draw_list->AddCircleFilled(ImVec2(center[0], center[1]), radius, color, num_segments); - }, - py::arg("center"), - py::arg("radius"), - py::arg("color"), - py::arg("num_segments") = 0) - .def( - "add_text", - [](ImDrawList* draw_list, const Eigen::Vector2i& pos, unsigned int color, const std::string& text) { draw_list->AddText(ImVec2(pos[0], pos[1]), color, text.c_str()); }, - py::arg("pos"), - py::arg("color"), - py::arg("text")) - // - ; + // Widgets: Drag Sliders + imgui_.def( + "drag_float", + [](const std::string& label, float v, float v_speed, float v_min, float v_max, const std::string& format, float power) { + return std::make_tuple(ImGui::DragFloat(label.c_str(), &v, v_speed, v_min, v_max, format.c_str(), power), v); + }, + "", + py::arg("label"), + py::arg("v"), + py::arg("v_speed") = 1.0f, + py::arg("v_min") = 0.0f, + py::arg("v_max") = 0.0f, + py::arg("format") = "%.3f", + py::arg("power") = 1.0f); + imgui_.def( + "drag_float2", + [](const std::string& label, const Eigen::Vector2f& v, float v_speed, float v_min, float v_max, const std::string& format, float power) { + Eigen::Vector2f val = v; + const bool changed = ImGui::DragFloat2(label.c_str(), val.data(), v_speed, v_min, v_max, format.c_str(), power); + return std::make_pair(changed, val); + }, + "", + py::arg("label"), + py::arg("v"), + py::arg("v_speed") = 1.0f, + py::arg("v_min") = 0.0f, + py::arg("v_max") = 0.0f, + py::arg("format") = "%.3f", + py::arg("power") = 1.0f); + imgui_.def( + "drag_float3", + [](const std::string& label, const Eigen::Vector3f& v, float v_speed, float v_min, float v_max, const std::string& format, float power) { + Eigen::Vector3f val = v; + const bool changed = ImGui::DragFloat3(label.c_str(), val.data(), v_speed, v_min, v_max, format.c_str(), power); + return std::make_pair(changed, val); + }, + "", + py::arg("label"), + py::arg("v"), + py::arg("v_speed") = 1.0f, + py::arg("v_min") = 0.0f, + py::arg("v_max") = 0.0f, + py::arg("format") = "%.3f", + py::arg("power") = 1.0f); + imgui_.def( + "drag_float4", + [](const std::string& label, const Eigen::Vector4f& v, float v_speed, float v_min, float v_max, const std::string& format, float power) { + Eigen::Vector4f val = v; + const bool changed = ImGui::DragFloat4(label.c_str(), val.data(), v_speed, v_min, v_max, format.c_str(), power); + return std::make_pair(changed, val); + }, + "", + py::arg("label"), + py::arg("v"), + py::arg("v_speed") = 1.0f, + py::arg("v_min") = 0.0f, + py::arg("v_max") = 0.0f, + py::arg("format") = "%.3f", + py::arg("power") = 1.0f); + imgui_.def( + "drag_float_range2", + [](const std::string& label, const Eigen::Vector2f& v, float v_speed, float v_min, float v_max, const std::string& format, const std::string& format_max, float power) { + Eigen::Vector2f val = v; + const bool changed = ImGui::DragFloatRange2(label.c_str(), &val[0], &val[1], v_speed, v_min, v_max, format.c_str(), format_max.c_str(), power); + return std::make_pair(changed, val); + }, + "", + py::arg("label"), + py::arg("v"), + py::arg("v_speed") = 1.0f, + py::arg("v_min") = 0.0f, + py::arg("v_max") = 0.0f, + py::arg("format") = "%.3f", + py::arg("format_max") = "%.3f", + py::arg("power") = 1.0f); - imgui_.def("get_window_draw_list", [] { - auto draw_list = ImGui::GetWindowDrawList(); - return std::shared_ptr(draw_list, [](ImDrawList* ptr) {}); - }); + imgui_.def( + "drag_int", + [](const std::string& label, int v, int v_speed, int v_min, int v_max, const std::string& format) { + return std::make_tuple(ImGui::DragInt(label.c_str(), &v, v_speed, v_min, v_max, format.c_str()), v); + }, + "", + py::arg("label"), + py::arg("v"), + py::arg("v_speed") = 1, + py::arg("v_min") = 0, + py::arg("v_max") = 0, + py::arg("format") = "%d"); + imgui_.def( + "drag_int2", + [](const std::string& label, const Eigen::Vector2i& v, int v_speed, int v_min, int v_max, const std::string& format) { + Eigen::Vector2i val = v; + const bool changed = ImGui::DragInt2(label.c_str(), val.data(), v_speed, v_min, v_max, format.c_str()); + return std::make_pair(changed, val); + }, + "", + py::arg("label"), + py::arg("v"), + py::arg("v_speed") = 1, + py::arg("v_min") = 0, + py::arg("v_max") = 0, + py::arg("format") = "%d"); + imgui_.def( + "drag_int3", + [](const std::string& label, const Eigen::Vector3i& v, int v_speed, int v_min, int v_max, const std::string& format) { + Eigen::Vector3i val = v; + const bool changed = ImGui::DragInt3(label.c_str(), val.data(), v_speed, v_min, v_max, format.c_str()); + return std::make_pair(changed, val); + }, + "", + py::arg("label"), + py::arg("v"), + py::arg("v_speed") = 1, + py::arg("v_min") = 0, + py::arg("v_max") = 0, + py::arg("format") = "%d"); + imgui_.def( + "drag_int4", + [](const std::string& label, const Eigen::Vector4i& v, int v_speed, int v_min, int v_max, const std::string& format) { + Eigen::Vector4i val = v; + const bool changed = ImGui::DragInt4(label.c_str(), val.data(), v_speed, v_min, v_max, format.c_str()); + return std::make_pair(changed, val); + }, + "", + py::arg("label"), + py::arg("v"), + py::arg("v_speed") = 1, + py::arg("v_min") = 0, + py::arg("v_max") = 0, + py::arg("format") = "%d"); + imgui_.def( + "drag_int_range2", + [](const std::string& label, const Eigen::Vector2i& v, int v_speed, int v_min, int v_max, const std::string& format, const std::string& format_max) { + Eigen::Vector2i val = v; + const bool changed = ImGui::DragIntRange2(label.c_str(), &val[0], &val[1], v_speed, v_min, v_max, format.c_str(), format_max.c_str()); + return std::make_pair(changed, val); + }, + "", + py::arg("label"), + py::arg("v"), + py::arg("v_speed") = 1, + py::arg("v_min") = 0, + py::arg("v_max") = 0, + py::arg("format") = "%d", + py::arg("format_max") = "%d"); - // IO - py::class_(imgui_, "IO") - .def_readonly("want_capture_keyboard", &ImGuiIO::WantCaptureKeyboard) - .def_readonly("want_capture_mouse", &ImGuiIO::WantCaptureMouse) - .def_readonly("framerate", &ImGuiIO::Framerate) - .def_readonly("delta_time", &ImGuiIO::DeltaTime) + // Widgets: Regular Sliders + imgui_.def( + "slider_float", + [](const std::string& label, float v, float v_min, float v_max, const std::string& format, float power) { + return std::make_tuple(ImGui::SliderFloat(label.c_str(), &v, v_min, v_max, format.c_str(), power), v); + }, + "", + py::arg("label"), + py::arg("v"), + py::arg("v_min"), + py::arg("v_max"), + py::arg("format") = "%.3f", + py::arg("power") = 1.0f); + imgui_.def( + "slider_float2", + [](const std::string& label, const Eigen::Vector2f& v, float v_min, float v_max, const std::string& format, float power) { + Eigen::Vector2f val = v; + const bool changed = ImGui::SliderFloat2(label.c_str(), val.data(), v_min, v_max, format.c_str(), power); + return std::make_pair(changed, val); + }, + "", + py::arg("label"), + py::arg("v"), + py::arg("v_min"), + py::arg("v_max"), + py::arg("format") = "%.3f", + py::arg("power") = 1.0f); + imgui_.def( + "slider_float3", + [](const std::string& label, const Eigen::Vector3f& v, float v_min, float v_max, const std::string& format, int flags) { + Eigen::Vector3f val = v; + const bool changed = ImGui::SliderFloat3(label.c_str(), val.data(), v_min, v_max, format.c_str(), flags); + return std::make_pair(changed, val); + }, + "", + py::arg("label"), + py::arg("v"), + py::arg("v_min"), + py::arg("v_max"), + py::arg("format") = "%.3f", + py::arg("flags") = 0); + imgui_.def( + "slider_float4", + [](const std::string& label, const Eigen::Vector4f& v, float v_min, float v_max, const std::string& format, int flags) { + Eigen::Vector4f val = v; + const bool changed = ImGui::SliderFloat4(label.c_str(), val.data(), v_min, v_max, format.c_str(), flags); + return std::make_pair(changed, val); + }, + "", + py::arg("label"), + py::arg("v"), + py::arg("v_min"), + py::arg("v_max"), + py::arg("format") = "%.3f", + py::arg("flags") = 0); + imgui_.def( + "slider_angle", + [](const std::string& label, float v_rad, float v_degrees_min, float v_degrees_max, const std::string& format, int flags) { + float val = v_rad; + const bool changed = ImGui::SliderAngle(label.c_str(), &val, v_degrees_min, v_degrees_max, format.c_str(), flags); + return std::make_pair(changed, val); + }, + "", + py::arg("label"), + py::arg("v_rad"), + py::arg("v_degrees_min") = -360.0f, + py::arg("v_degrees_max") = 360.0f, + py::arg("format") = "%.0f deg", + py::arg("flags") = 0); + imgui_.def( + "slider_int", + [](const std::string& label, int v, int v_min, int v_max, const std::string& format, int flags) { + int val = v; + const bool changed = ImGui::SliderInt(label.c_str(), &val, v_min, v_max, format.c_str(), flags); + return std::make_pair(changed, val); + }, + "", + py::arg("label"), + py::arg("v"), + py::arg("v_min"), + py::arg("v_max"), + py::arg("format") = "%d", + py::arg("flags") = 0); + imgui_.def( + "slider_int2", + [](const std::string& label, const Eigen::Vector2i& v, int v_min, int v_max, const std::string& format, int flags) { + Eigen::Vector2i val = v; + const bool changed = ImGui::SliderInt2(label.c_str(), val.data(), v_min, v_max, format.c_str(), flags); + return std::make_pair(changed, val); + }, + "", + py::arg("label"), + py::arg("v"), + py::arg("v_min"), + py::arg("v_max"), + py::arg("format") = "%d", + py::arg("flags") = 0); + imgui_.def( + "slider_int3", + [](const std::string& label, const Eigen::Vector3i& v, int v_min, int v_max, const std::string& format, int flags) { + Eigen::Vector3i val = v; + const bool changed = ImGui::SliderInt3(label.c_str(), val.data(), v_min, v_max, format.c_str(), flags); + return std::make_pair(changed, val); + }, + "", + py::arg("label"), + py::arg("v"), + py::arg("v_min"), + py::arg("v_max"), + py::arg("format") = "%d", + py::arg("flags") = 0); + imgui_.def( + "slider_int4", + [](const std::string& label, const Eigen::Vector4i& v, int v_min, int v_max, const std::string& format, int flags) { + Eigen::Vector4i val = v; + const bool changed = ImGui::SliderInt4(label.c_str(), val.data(), v_min, v_max, format.c_str(), flags); + return std::make_pair(changed, val); + }, + "", + py::arg("label"), + py::arg("v"), + py::arg("v_min"), + py::arg("v_max"), + py::arg("format") = "%d", + py::arg("flags") = 0); - .def_property_readonly("mouse_pos", [](const ImGuiIO& io) { return py::array(2, &io.MousePos.x); }) - .def_property_readonly("mouse_down", [](const ImGuiIO& io) { return py::array(5, io.MouseDown); }) - .def_property_readonly("mouse_clicked", [](const ImGuiIO& io) { return py::array(5, io.MouseClicked); }) + // Widgets: Input with Keyboard + imgui_.def( + "input_text", + [](const std::string& label, const std::string& text, int flags, int buffer_size) { + std::vector buffer(buffer_size, 0); + std::copy(text.begin(), text.end(), buffer.begin()); + const bool changed = ImGui::InputText(label.c_str(), buffer.data(), buffer_size, flags); + return std::make_pair(changed, std::string(buffer.data())); + }, + "", + py::arg("label"), + py::arg("text"), + py::arg("flags") = 0, + py::arg("buffer_size") = 256); + imgui_.def( + "input_text_multiline", + [](const std::string& label, const std::string& text, const Eigen::Vector2i& size, int flags, int buffer_size) { + std::vector buffer(buffer_size, 0); + std::copy(text.begin(), text.end(), buffer.begin()); + const bool changed = ImGui::InputTextMultiline(label.c_str(), buffer.data(), buffer_size, ImVec2(size[0], size[1]), flags); + return std::make_pair(changed, std::string(buffer.data())); + }, + "", + py::arg("label"), + py::arg("text"), + py::arg("size") = Eigen::Vector2i(0, 0), + py::arg("flags") = 0, + py::arg("buffer_size") = 256); + imgui_.def( + "input_text_with_hint", + [](const std::string& label, const std::string& hint, const std::string& text, int flags, int buffer_size) { + std::vector buffer(buffer_size, 0); + std::copy(text.begin(), text.end(), buffer.begin()); + const bool changed = ImGui::InputTextWithHint(label.c_str(), hint.c_str(), buffer.data(), buffer_size, flags); + return std::make_pair(changed, std::string(buffer.data())); + }, + "", + py::arg("label"), + py::arg("hint"), + py::arg("text"), + py::arg("flags") = 0, + py::arg("buffer_size") = 256); + imgui_.def( + "input_float", + [](const std::string& label, float v, float step, float step_fast, const std::string& format, int flags) { + float val = v; + const bool changed = ImGui::InputFloat(label.c_str(), &val, step, step_fast, format.c_str(), flags); + return std::make_pair(changed, val); + }, + "", + py::arg("label"), + py::arg("v"), + py::arg("step") = 0.0f, + py::arg("step_fast") = 0.0f, + py::arg("format") = "%.3f", + py::arg("flags") = 0); + imgui_.def( + "input_float2", + [](const std::string& label, const Eigen::Vector2f& v, const std::string& format, int flags) { + Eigen::Vector2f val = v; + const bool changed = ImGui::InputFloat2(label.c_str(), val.data(), format.c_str(), flags); + return std::make_pair(changed, val); + }, + "", + py::arg("label"), + py::arg("v"), + py::arg("format") = "%.3f", + py::arg("flags") = 0); + imgui_.def( + "input_float3", + [](const std::string& label, const Eigen::Vector3f& v, const std::string& format, int flags) { + Eigen::Vector3f val = v; + const bool changed = ImGui::InputFloat3(label.c_str(), val.data(), format.c_str(), flags); + return std::make_pair(changed, val); + }, + "", + py::arg("label"), + py::arg("v"), + py::arg("format") = "%.3f", + py::arg("flags") = 0); + imgui_.def( + "input_float4", + [](const std::string& label, const Eigen::Vector4f& v, const std::string& format, int flags) { + Eigen::Vector4f val = v; + const bool changed = ImGui::InputFloat4(label.c_str(), val.data(), format.c_str(), flags); + return std::make_pair(changed, val); + }, + "", + py::arg("label"), + py::arg("v"), + py::arg("format") = "%.3f", + py::arg("flags") = 0); + imgui_.def( + "input_int", + [](const std::string& label, int v, int step, int step_fast, int flags) { + int val = v; + const bool changed = ImGui::InputInt(label.c_str(), &val, step, step_fast, flags); + return std::make_pair(changed, val); + }, + "", + py::arg("label"), + py::arg("v"), + py::arg("step") = 1, + py::arg("step_fast") = 100, + py::arg("flags") = 0); + imgui_.def( + "input_int2", + [](const std::string& label, const Eigen::Vector2i& v, int flags) { + Eigen::Vector2i val = v; + const bool changed = ImGui::InputInt2(label.c_str(), val.data(), flags); + return std::make_pair(changed, val); + }, + "", + py::arg("label"), + py::arg("v"), + py::arg("flags") = 0); + imgui_.def( + "input_int3", + [](const std::string& label, const Eigen::Vector3i& v, int flags) { + Eigen::Vector3i val = v; + const bool changed = ImGui::InputInt3(label.c_str(), val.data(), flags); + return std::make_pair(changed, val); + }, + "", + py::arg("label"), + py::arg("v"), + py::arg("flags") = 0); + imgui_.def( + "input_int4", + [](const std::string& label, const Eigen::Vector4i& v, int flags) { + Eigen::Vector4i val = v; + const bool changed = ImGui::InputInt4(label.c_str(), val.data(), flags); + return std::make_pair(changed, val); + }, + "", + py::arg("label"), + py::arg("v"), + py::arg("flags") = 0); + imgui_.def( + "input_double", + [](const std::string& label, double v, double step, double step_fast, const std::string& format, int flags) { + double val = v; + const bool changed = ImGui::InputDouble(label.c_str(), &val, step, step_fast, format.c_str(), flags); + return std::make_pair(changed, val); + }, + "", + py::arg("label"), + py::arg("v"), + py::arg("step") = 0.0, + py::arg("step_fast") = 0.0, + py::arg("format") = "%.6f", + py::arg("flags") = 0); - .def_readonly("mouse_wheel", &ImGuiIO::MouseWheel) - .def_readonly("mouse_wheel_h", &ImGuiIO::MouseWheelH) - .def_readonly("key_ctrl", &ImGuiIO::KeyCtrl) - .def_readonly("key_shift", &ImGuiIO::KeyShift) - .def_readonly("key_alt", &ImGuiIO::KeyAlt) - .def_readonly("key_super", &ImGuiIO::KeySuper) - .def_property_readonly("keys_down", [](const ImGuiIO& io) { return py::array(512, io.KeysDown); }) - .def_property_readonly("nav_inputs", [](const ImGuiIO& io) { return py::array(ImGuiNavInput_COUNT, io.NavInputs); }); + // Widgets: Color Editor/Picker + imgui_.def( + "color_edit3", + [](const std::string& label, const Eigen::Vector3f& color, int flags) { + Eigen::Vector3f col = color; + const bool changed = ImGui::ColorEdit3(label.c_str(), col.data(), flags); + return std::make_pair(changed, col); + }, + py::arg("label"), + py::arg("color"), + py::arg("flags") = 0); + imgui_.def( + "color_edit4", + [](const std::string& label, const Eigen::Vector4f& color, int flags) { + Eigen::Vector4f col = color; + const bool changed = ImGui::ColorEdit4(label.c_str(), col.data(), flags); + return std::make_pair(changed, col); + }, + py::arg("label"), + py::arg("color"), + py::arg("flags") = 0); + imgui_.def( + "color_picker3", + [](const std::string& label, const Eigen::Vector3f& color, int flags) { + Eigen::Vector3f col = color; + const bool changed = ImGui::ColorPicker3(label.c_str(), col.data(), flags); + return std::make_pair(changed, col); + }, + py::arg("label"), + py::arg("color"), + py::arg("flags") = 0); + imgui_.def( + "color_picker4", + [](const std::string& label, const Eigen::Vector4f& color, int flags) { + Eigen::Vector4f col = color; + const bool changed = ImGui::ColorPicker4(label.c_str(), col.data(), flags); + return std::make_pair(changed, col); + }, + py::arg("label"), + py::arg("color"), + py::arg("flags") = 0); + imgui_.def( + "color_button", + [](const std::string& desc_id, const Eigen::Vector4f& color, int flags, const Eigen::Vector2i& size) { + return ImGui::ColorButton(desc_id.c_str(), ImVec4(color[0], color[1], color[2], color[3]), flags, ImVec2(size[0], size[1])); + }, + py::arg("desc_id"), + py::arg("color"), + py::arg("flags") = 0, + py::arg("size") = Eigen::Vector2i(0, 0)); - imgui_.def("get_io", [] { return ImGui::GetIO(); }); - imgui_.def("is_mouse_clicked", [](int button, bool repeat) { return ImGui::IsMouseClicked(button, repeat); }, "", py::arg("button") = 0, py::arg("repeat") = false); + // Widgets: Trees + imgui_.def("tree_node", [](const std::string& label) { return ImGui::TreeNode(label.c_str()); }, py::arg("label")); + imgui_.def("tree_push_str", [](const std::string& str_id) { ImGui::TreePush(str_id.c_str()); }, py::arg("str_id")); + imgui_.def("tree_pop", &ImGui::TreePop); + imgui_.def("get_tree_node_to_label_spacing", &ImGui::GetTreeNodeToLabelSpacing); + imgui_.def("collapsing_header", [](const std::string& label, int flags) { return ImGui::CollapsingHeader(label.c_str(), flags); }, py::arg("label"), py::arg("flags") = 0); + imgui_.def( + "collapsing_header_bool", + [](const std::string& label, bool open, int flags) { return std::make_tuple(ImGui::CollapsingHeader(label.c_str(), &open, flags), open); }, + py::arg("label"), + py::arg("open"), + py::arg("flags") = 0); + imgui_.def("set_next_item_open", &ImGui::SetNextItemOpen, py::arg("is_open"), py::arg("cond") = 0); - imgui_.def("get_mouse_pos", [] { - auto pos = ImGui::GetMousePos(); + // Widgets: Selectables + imgui_.def( + "selectable", + [](const std::string& label, bool selected, int flags, const Eigen::Vector2i& size) { return ImGui::Selectable(label.c_str(), selected, flags, ImVec2(size[0], size[1])); }, + "", + py::arg("label"), + py::arg("selected") = false, + py::arg("flags") = 0, + py::arg("size") = Eigen::Vector2i(0, 0)); + + // Widgets: Menus + imgui_.def("begin_menu_bar", &ImGui::BeginMenuBar); + imgui_.def("end_menu_bar", &ImGui::EndMenuBar); + imgui_.def("begin_main_menu_bar", &ImGui::BeginMainMenuBar); + imgui_.def("end_main_menu_bar", &ImGui::EndMainMenuBar); + imgui_.def("begin_menu", [](const std::string& label, bool enabled) { return ImGui::BeginMenu(label.c_str(), enabled); }, py::arg("label"), py::arg("enabled") = true); + imgui_.def("end_menu", &ImGui::EndMenu); + imgui_.def( + "menu_item", + [](const std::string& label, const std::string& shortcut, bool selected, bool enabled) { return ImGui::MenuItem(label.c_str(), shortcut.c_str(), &selected, enabled); }, + py::arg("label"), + py::arg("shortcut") = "", + py::arg("selected") = false, + py::arg("enabled") = true); + + // Tooltips + imgui_.def("begin_tooltip", &ImGui::BeginTooltip); + imgui_.def("end_tooltip", &ImGui::EndTooltip); + imgui_.def("set_tooltip", [](const std::string& fmt) { ImGui::SetTooltip("%s", fmt.c_str()); }, py::arg("fmt")); + + // Popups: begin/end functions + imgui_.def("begin_popup", &ImGui::BeginPopup, py::arg("id"), py::arg("flags")); + imgui_.def("begin_popup_modal", [](const std::string& name, int flags) { return ImGui::BeginPopupModal(name.c_str(), nullptr, flags); }, py::arg("name"), py::arg("flags") = 0); + imgui_.def("end_popup", &ImGui::EndPopup); + + // Popups: open/close functions + imgui_.def("open_popup", [](const std::string& name) { ImGui::OpenPopup(name.c_str()); }, py::arg("name")); + imgui_.def( + "open_popup_on_item_click", + [](const std::string& str_id, int mouse_button) { ImGui::OpenPopupOnItemClick(str_id.c_str(), mouse_button); }, + py::arg("str_id"), + py::arg("mouse_button") = 0); + imgui_.def("close_current_popup", &ImGui::CloseCurrentPopup); + + // Popups: query functions + imgui_.def("is_popup_open", [](const std::string& name, int flags) { return ImGui::IsPopupOpen(name.c_str(), flags); }, py::arg("name"), py::arg("flags") = 0); + + // Tables + imgui_.def("begin_table", &ImGui::BeginTable, py::arg("str_id"), py::arg("column_n"), py::arg("flags") = 0, py::arg("outer_size") = ImVec2(0, 0), py::arg("inner_width") = 0.0f); + imgui_.def("end_table", &ImGui::EndTable); + imgui_.def("table_next_row", &ImGui::TableNextRow, py::arg("row_flags") = 0, py::arg("min_row_height") = 0.0f); + imgui_.def("table_next_column", &ImGui::TableNextColumn); + imgui_.def("table_set_column_index", &ImGui::TableSetColumnIndex, py::arg("column_index")); + imgui_.def("table_setup_column", &ImGui::TableSetupColumn, py::arg("label"), py::arg("flags") = 0, py::arg("init_width_or_weight") = 0.0f, py::arg("user_id") = 0); + imgui_.def("table_setup_scroll_freeze", &ImGui::TableSetupScrollFreeze, py::arg("cols"), py::arg("rows")); + imgui_.def("table_headers_row", &ImGui::TableHeadersRow); + imgui_.def("table_header", &ImGui::TableHeader, py::arg("label")); + + // Tab Bars, Tabs + imgui_.def("begin_tab_bar", &ImGui::BeginTabBar, py::arg("id"), py::arg("flags") = 0); + imgui_.def("end_tab_bar", &ImGui::EndTabBar); + imgui_.def("begin_tab_item", [](const char* label) { return ImGui::BeginTabItem(label); }, py::arg("label")); + imgui_.def("end_tab_item", &ImGui::EndTabItem); + imgui_.def("tab_item_button", &ImGui::TabItemButton, py::arg("label"), py::arg("flags") = 0); + imgui_.def("set_tab_item_closed", &ImGui::SetTabItemClosed, py::arg("tab_or_dockspace_id")); + + // Docking + imgui_.def( + "dockspace", + [](unsigned int id, const Eigen::Vector2i& size, int flags) { return ImGui::DockSpace(id, ImVec2(size[0], size[1]), flags); }, + py::arg("id"), + py::arg("size") = Eigen::Vector2i(0, 0), + py::arg("flags") = 0); + imgui_.def("dockspace_over_viewport", [](int flags) { return ImGui::DockSpaceOverViewport(nullptr, flags); }, py::arg("flags") = 0); + imgui_.def("set_next_window_dock_id", &ImGui::SetNextWindowDockID, py::arg("dock_id"), py::arg("cond") = 0); + + // Dock builder + imgui_.def("dock_builder_dock_window", &ImGui::DockBuilderDockWindow, py::arg("window_name"), py::arg("node_id")); + imgui_.def("dock_builder_add_node", &ImGui::DockBuilderAddNode, py::arg("node_id") = 0, py::arg("flags") = 0); + imgui_.def("dock_builder_remove_node", &ImGui::DockBuilderRemoveNode, py::arg("node_id")); + imgui_.def( + "dock_builder_split_node", + [](unsigned int node_id, int split_dir, float size_ratio_for_node_at_dir) -> std::pair { + ImGuiID id_at_dir, id_at_opposite_dir; + ImGui::DockBuilderSplitNode(node_id, split_dir, size_ratio_for_node_at_dir, &id_at_dir, &id_at_opposite_dir); + return std::make_pair(id_at_dir, id_at_opposite_dir); + }, + py::arg("node_id"), + py::arg("split_dir"), + py::arg("size_ratio_for_node_at_dir")); + imgui_.def("dock_builder_finish", [](unsigned int node_id) { ImGui::DockBuilderFinish(node_id); }, py::arg("node_id")); + + // Focus, Activation + imgui_.def("set_item_default_focus", &ImGui::SetItemDefaultFocus); + imgui_.def("set_keyboard_focus_here", &ImGui::SetKeyboardFocusHere, py::arg("offset") = 0); + + // Item/Widgets Utilities and Query Functions + imgui_.def("is_item_hovered", &ImGui::IsItemHovered, py::arg("flags") = 0); + imgui_.def("is_item_active", &ImGui::IsItemActive); + imgui_.def("is_item_focused", &ImGui::IsItemFocused); + imgui_.def("is_item_clicked", &ImGui::IsItemClicked, py::arg("mouse_button") = 0); + imgui_.def("is_item_visible", &ImGui::IsItemVisible); + imgui_.def("is_item_edited", &ImGui::IsItemEdited); + imgui_.def("is_item_activated", &ImGui::IsItemActivated); + imgui_.def("is_item_deactivated", &ImGui::IsItemDeactivated); + imgui_.def("is_item_deactivated_after_edit", &ImGui::IsItemDeactivatedAfterEdit); + imgui_.def("is_item_toggled_open", &ImGui::IsItemToggledOpen); + imgui_.def("is_any_item_hovered", &ImGui::IsAnyItemHovered); + imgui_.def("is_any_item_active", &ImGui::IsAnyItemActive); + imgui_.def("is_any_item_focused", &ImGui::IsAnyItemFocused); + imgui_.def("get_item_id", &ImGui::GetItemID); + imgui_.def("get_item_rect_min", [] { + auto pos = ImGui::GetItemRectMin(); return Eigen::Vector2f(pos[0], pos[1]); }); - - imgui_.def("get_window_pos", [] { - auto pos = ImGui::GetWindowPos(); + imgui_.def("get_item_rect_max", [] { + auto pos = ImGui::GetItemRectMax(); return Eigen::Vector2f(pos[0], pos[1]); }); + imgui_.def("get_item_rect_size", [] { + auto size = ImGui::GetItemRectSize(); + return Eigen::Vector2f(size[0], size[1]); + }); + imgui_.def("set_item_allow_overlap", &ImGui::SetItemAllowOverlap); - imgui_.def("get_cursor_screen_pos", [] { - auto pos = ImGui::GetCursorScreenPos(); + // Background/Foreground Draw Lists (return raw pointers) + imgui_.def("get_background_draw_list", [] { return ImGui::GetBackgroundDrawList(); }, py::return_value_policy::reference); + imgui_.def("get_foreground_draw_list", [] { return ImGui::GetForegroundDrawList(); }, py::return_value_policy::reference); + + // Miscellaneous Utilities + imgui_.def("is_rect_visible", [](const Eigen::Vector2f& size) { + ImVec2 sz(size[0], size[1]); + return ImGui::IsRectVisible(sz); + }); + imgui_.def("is_rect_visible_pos_size", [](const Eigen::Vector2f& pos, const Eigen::Vector2f& size) { + ImVec2 p(pos[0], pos[1]); + ImVec2 sz(size[0], size[1]); + return ImGui::IsRectVisible(p, sz); + }); + imgui_.def("get_time", &ImGui::GetTime); + imgui_.def("get_frame_count", &ImGui::GetFrameCount); + + // Text Utilities + imgui_.def( + "calc_text_size", + [](const std::string& text, float wrap_width, bool hide_text_after_double_hash) { + auto size = ImGui::CalcTextSize(text.c_str(), nullptr, hide_text_after_double_hash, wrap_width); + return Eigen::Vector2f(size[0], size[1]); + }, + py::arg("text"), + py::arg("wrap_width") = -1.0f, + py::arg("hide_text_after_double_hash") = false); + + // Inputs Utilities: Keyboard/Mouse/Gamepad + imgui_.def("is_key_down", [](int key) { return ImGui::IsKeyDown(static_cast(key)); }, py::arg("key")); + imgui_.def("is_key_pressed", [](int key, bool repeat) { return ImGui::IsKeyPressed(static_cast(key), repeat); }, py::arg("key"), py::arg("repeat") = false); + imgui_.def("is_key_released", [](int key) { return ImGui::IsKeyReleased(static_cast(key)); }, py::arg("key")); + imgui_.def("get_key_pressed_amount", &ImGui::GetKeyPressedAmount, py::arg("key"), py::arg("repeat_delay") = 0.0f, py::arg("repeat_rate") = 0.0f); + imgui_.def("get_key_name", [](int key_index) { return std::string(ImGui::GetKeyName(static_cast(key_index))); }, py::arg("key_index")); + + // Inputs Utilities: Mouse specific + imgui_.def("is_mouse_down", [](int button) { return ImGui::IsMouseDown(static_cast(button)); }, py::arg("button")); + imgui_.def( + "is_mouse_clicked", + [](int button, bool repeat) { return ImGui::IsMouseClicked(static_cast(button), repeat); }, + py::arg("button"), + py::arg("repeat") = false); + imgui_.def("is_mouse_released", [](int button) { return ImGui::IsMouseReleased(static_cast(button)); }, py::arg("button")); + imgui_.def("is_mouse_double_clicked", [](int button) { return ImGui::IsMouseDoubleClicked(static_cast(button)); }, py::arg("button")); + imgui_.def("get_mouse_clicked_count", [](int button) { return ImGui::GetMouseClickedCount(static_cast(button)); }, py::arg("button")); + imgui_.def( + "is_mouse_hovering_rect", + [](const Eigen::Vector2f& r_min, const Eigen::Vector2f& r_max, bool clip) { + ImVec2 min(r_min[0], r_min[1]); + ImVec2 max(r_max[0], r_max[1]); + return ImGui::IsMouseHoveringRect(min, max, clip); + }, + py::arg("r_min"), + py::arg("r_max"), + py::arg("clip") = true); + imgui_.def( + "is_mouse_pos_valid", + [](const Eigen::Vector2f& mouse_pos) { + ImVec2 pos(mouse_pos[0], mouse_pos[1]); + return ImGui::IsMousePosValid(&pos); + }, + py::arg("mouse_pos") = Eigen::Vector2f(-FLT_MAX, -FLT_MAX)); + imgui_.def("is_any_mouse_down", &ImGui::IsAnyMouseDown); + imgui_.def("get_mouse_pos", [] { + auto pos = ImGui::GetMousePos(); return Eigen::Vector2f(pos[0], pos[1]); }); - imgui_.def("get_content_region_avail", [] { - auto pos = ImGui::GetContentRegionAvail(); + imgui_.def("get_mouse_pos_on_opening_current_popup", [] { + auto pos = ImGui::GetMousePosOnOpeningCurrentPopup(); return Eigen::Vector2f(pos[0], pos[1]); }); + imgui_.def( + "is_mouse_dragging", + [](int button, float lock_threshold) { return ImGui::IsMouseDragging(static_cast(button), lock_threshold); }, + py::arg("button"), + py::arg("lock_threshold") = -1.0f); + imgui_.def( + "get_mouse_drag_delta", + [](int button, float lock_threshold) { + auto pos = ImGui::GetMouseDragDelta(static_cast(button), lock_threshold); + return Eigen::Vector2f(pos[0], pos[1]); + }, + py::arg("button") = 0, + py::arg("lock_threshold") = -1.0f); + imgui_.def("reset_mouse_drag_delta", [](int button) { ImGui::ResetMouseDragDelta(static_cast(button)); }, py::arg("button") = 0); - imgui_.def("is_item_hovered", &ImGui::IsItemHovered, py::arg("flags") = 0); - imgui_.def("is_item_active", &ImGui::IsItemActive); - imgui_.def("is_item_focused", &ImGui::IsItemFocused); + // Clipboard Utilities + imgui_.def("get_clipboard_text", [] { return std::string(ImGui::GetClipboardText()); }); + imgui_.def("set_clipboard_text", [](const std::string& text) { ImGui::SetClipboardText(text.c_str()); }, py::arg("text")); + + // + imgui_.def("get_window_draw_list", [] { + auto draw_list = ImGui::GetWindowDrawList(); + return std::shared_ptr(draw_list, [](ImDrawList* ptr) {}); + }); } \ No newline at end of file diff --git a/src/test/ui_test.py b/src/test/ui_test.py new file mode 100644 index 00000000..dac77d83 --- /dev/null +++ b/src/test/ui_test.py @@ -0,0 +1,575 @@ +#!/bin/env python +import numpy +from pyridescence import * + +class TestUI: + def __init__(self): + self.viewer = guik.viewer() + self.viewer.register_ui_callback('test_ui', self.ui_callback) + + def spin(self): + self.viewer.spin() + + def io_test(self): + io = imgui.get_io() + imgui.text(f'wants_capture_mouse: {io.want_capture_mouse}') + imgui.text(f'wants_capture_keyboard: {io.want_capture_keyboard}') + imgui.text(f'framerate: {io.framerate}') + imgui.text(f'delta_time: {io.delta_time}') + imgui.text(f'mouse_pos: {io.mouse_pos[0]}, {io.mouse_pos[1]}') + imgui.text(f'mouse_down: {io.mouse_down[0]}, {io.mouse_down[1]}, {io.mouse_down[2]}') + imgui.text(f'mouse_clicked: {io.mouse_clicked[0]}, {io.mouse_clicked[1]}, {io.mouse_clicked[2]}') + imgui.text(f'mouse_wheel: {io.mouse_wheel}') + imgui.text(f'mouse_wheel_h: {io.mouse_wheel_h}') + imgui.text(f'key_ctrl: {str(io.key_ctrl)}') + imgui.text(f'key_shift: {str(io.key_shift)}') + imgui.text(f'key_alt: {str(io.key_alt)}') + imgui.text(f'key_super: {str(io.key_super)}') + + pressed_keys = [imgui.get_key_name(i) for i in range(len(io.keys_down)) if io.keys_down[i]] + imgui.text(f'pressed_keys: {", ".join(pressed_keys)}') + imgui.text(f'nav_inputs:{", ".join([f"{i}:{io.nav_inputs[i]:.2f}" for i in range(len(io.nav_inputs))])}') + + def style_test(self): + style = imgui.get_style() + + imgui.text(f'alpha: {style.alpha:.2f}') + imgui.text(f'disabled_alpha: {style.disabled_alpha:.2f}') + imgui.text(f'window_padding: ({style.window_padding.x:.2f}, {style.window_padding.y:.2f})') + imgui.text(f'window_rounding: {style.window_rounding:.2f}') + imgui.text(f'window_border_size: {style.window_border_size:.2f}') + imgui.text(f'window_min_size: ({style.window_min_size.x:.2f}, {style.window_min_size.y:.2f})') + imgui.text(f'window_title_align: ({style.window_title_align.x:.2f}, {style.window_title_align.y:.2f})') + imgui.text(f'window_menu_button_position: {style.window_menu_button_position}') + imgui.text(f'child_rounding: {style.child_rounding:.2f}') + imgui.text(f'child_border_size: {style.child_border_size:.2f}') + imgui.text(f'popup_rounding: {style.popup_rounding:.2f}') + imgui.text(f'popup_border_size: {style.popup_border_size:.2f}') + imgui.text(f'frame_padding: ({style.frame_padding.x:.2f}, {style.frame_padding.y:.2f})') + imgui.text(f'frame_rounding: {style.frame_rounding:.2f}') + imgui.text(f'frame_border_size: {style.frame_border_size:.2f}') + imgui.text(f'item_spacing: ({style.item_spacing.x:.2f}, {style.item_spacing.y:.2f})') + imgui.text(f'item_inner_spacing: ({style.item_inner_spacing.x:.2f}, {style.item_inner_spacing.y:.2f})') + imgui.text(f'cell_padding: ({style.cell_padding.x:.2f}, {style.cell_padding.y:.2f})') + imgui.text(f'touch_extra_padding: ({style.touch_extra_padding.x:.2f}, {style.touch_extra_padding.y:.2f})') + imgui.text(f'indent_spacing: {style.indent_spacing:.2f}') + imgui.text(f'columns_min_spacing: {style.columns_min_spacing:.2f}') + imgui.text(f'scrollbar_size: {style.scrollbar_size:.2f}') + imgui.text(f'scrollbar_rounding: {style.scrollbar_rounding:.2f}') + imgui.text(f'grab_min_size: {style.grab_min_size:.2f}') + imgui.text(f'grab_rounding: {style.grab_rounding:.2f}') + imgui.text(f'tab_rounding: {style.tab_rounding:.2f}') + imgui.text(f'tab_border_size: {style.tab_border_size:.2f}') + imgui.text(f'tab_min_width_for_close_button: {style.tab_min_width_for_close_button:.2f}') + imgui.text(f'color_button_position: {style.color_button_position}') + imgui.text(f'button_text_align: ({style.button_text_align.x:.2f}, {style.button_text_align.y:.2f})') + imgui.text(f'selectable_text_align: ({style.selectable_text_align.x:.2f}, {style.selectable_text_align.y:.2f})') + imgui.text(f'display_window_padding: ({style.display_window_padding.x:.2f}, {style.display_window_padding.y:.2f})') + imgui.text(f'display_safe_area_padding: ({style.display_safe_area_padding.x:.2f}, {style.display_safe_area_padding.y:.2f})') + imgui.text(f'mouse_cursor_scale: {style.mouse_cursor_scale:.2f}') + imgui.text(f'anti_aliased_lines: {style.anti_aliased_lines}') + imgui.text(f'anti_aliased_lines_use_tex: {style.anti_aliased_lines_use_tex}') + imgui.text(f'anti_aliased_fill: {style.anti_aliased_fill}') + imgui.text(f'curve_tessellation_tol: {style.curve_tessellation_tol:.2f}') + imgui.text(f'circle_tessellation_max_error: {style.circle_tessellation_max_error:.2f}') + + imgui.separator() + imgui.text('=== Colors (first 10) ===') + colors = style.colors + for i in range(min(10, len(colors))): + color = colors[i] + imgui.text(f'Color[{i}]: ({color[0]:.2f}, {color[1]:.2f}, {color[2]:.2f}, {color[3]:.2f})') + + def drawlist_test(self): + imgui.text('DrawList Test:') + if not hasattr(self, 'dl_mode'): + self.dl_mode = 0 + + if imgui.radio_button('fg', self.dl_mode == 0): + self.dl_mode = 0 + imgui.same_line() + if imgui.radio_button('bg', self.dl_mode == 1): + self.dl_mode = 1 + imgui.same_line() + if imgui.radio_button('window', self.dl_mode == 2): + self.dl_mode = 2 + + if self.dl_mode == 0: + dl = imgui.get_foreground_draw_list() + elif self.dl_mode == 1: + dl = imgui.get_background_draw_list() + else: + dl = imgui.get_window_draw_list() + + dl.add_line((100, 100), (200, 100), imgui.IM_COL32(255, 0, 0, 255), 3.0) + dl.add_line((300, 100), (400, 100), imgui.IM_COL32(0, 255, 0, 128), 2.0) + dl.add_line((500, 100), (600, 100), imgui.IM_COL32(0, 0, 255, 64), 1.0) + + dl.add_rect_filled((100, 200), (200, 250), imgui.IM_COL32(255, 0, 0, 255), rounding=0.0) + dl.add_rect_filled((300, 200), (400, 250), imgui.IM_COL32(0, 255, 0, 128), rounding=10.0) + dl.add_rect_filled((500, 200), (600, 250), imgui.IM_COL32(0, 0, 255, 64), rounding=20.0) + + dl.add_rect((100, 300), (200, 350), imgui.IM_COL32(255, 0, 0, 255), thickness=3.0, rounding=0.0) + dl.add_rect((300, 300), (400, 350), imgui.IM_COL32(0, 255, 0, 128), thickness=2.0, rounding=10.0) + dl.add_rect((500, 300), (600, 350), imgui.IM_COL32(0, 0, 255, 64), thickness=1.0, rounding=20.0) + + dl.add_circle_filled((150, 450), 25.0, imgui.IM_COL32(255, 0, 0, 255), num_segments=0) + dl.add_circle_filled((350, 450), 25.0, imgui.IM_COL32(0, 255, 0, 128), num_segments=0) + dl.add_circle_filled((550, 450), 25.0, imgui.IM_COL32(0, 0, 255, 64), num_segments=0) + + dl.add_circle((150, 550), 25.0, imgui.IM_COL32(255, 0, 0, 255), num_segments=0, thickness=3.0) + dl.add_circle((350, 550), 25.0, imgui.IM_COL32(0, 255, 0, 128), num_segments=0, thickness=2.0) + dl.add_circle((550, 550), 25.0, imgui.IM_COL32(0, 0, 255, 64), num_segments=0, thickness=1.0) + + dl.add_text((100, 650), imgui.IM_COL32(255, 255, 255, 255), 'This is a test text drawn by ImDrawList.') + + def demo_test(self): + if not hasattr(self, 'show_demo'): + self.show_demo = False + self.show_metrics = False + self.show_debug_log = False + self.show_style_editor = False + + imgui.text(f'version: {imgui.get_version()}') + + imgui.text('style colors:') + if imgui.button('dark'): + imgui.style_colors_dark() + imgui.same_line() + if imgui.button('light'): + imgui.style_colors_light() + imgui.same_line() + if imgui.button('classic'): + imgui.style_colors_classic() + + imgui.show_style_selector('styles') + imgui.show_font_selector('fonts') + + _, self.show_demo = imgui.checkbox('Show ImGui Demo Window', self.show_demo) + if self.show_demo: + imgui.show_demo_window() + + _, self.show_metrics = imgui.checkbox('Show ImGui Metrics Window', self.show_metrics) + if self.show_metrics: + imgui.show_metrics_window() + + _, self.show_debug_log = imgui.checkbox('Show ImGui Debug Log Window', self.show_debug_log) + if self.show_debug_log: + imgui.show_debug_log_window() + + _, self.show_style_editor = imgui.checkbox('Show ImGui Style Editor', self.show_style_editor) + if self.show_style_editor: + imgui.show_style_editor() + + def win_test(self): + if imgui.begin_child('child', (300, 200), border=True): + imgui.text('in child window') + imgui.end_child() + + imgui.text(f'is_window_appearing: {imgui.is_window_appearing()}') + imgui.text(f'is_window_collapsed: {imgui.is_window_collapsed()}') + imgui.text(f'is_window_focused: {imgui.is_window_focused()}') + imgui.text(f'is_window_hovered: {imgui.is_window_hovered()}') + imgui.text(f'get_window_pos: ({imgui.get_window_pos()[0]}, {imgui.get_window_pos()[1]})') + imgui.text(f'get_window_size: ({imgui.get_window_size()[0]}, {imgui.get_window_size()[1]})') + imgui.text(f'get_window_width: {imgui.get_window_width()}') + imgui.text(f'get_window_height: {imgui.get_window_height()}') + + imgui.text(f'get_content_region_avail: ({imgui.get_content_region_avail()[0]}, {imgui.get_content_region_avail()[1]})') + imgui.text(f'get_content_region_max: ({imgui.get_content_region_max()[0]}, {imgui.get_content_region_max()[1]})') + imgui.text(f'get_window_content_region_min: ({imgui.get_window_content_region_min()[0]}, {imgui.get_window_content_region_min()[1]})') + imgui.text(f'get_window_content_region_max: ({imgui.get_window_content_region_max()[0]}, {imgui.get_window_content_region_max()[1]})') + + def param_stacks_test(self): + if not hasattr(self, 'repeat_value'): + self.repeat_value = 0 + + imgui.push_button_repeat(True) + if imgui.button('Repeat Button'): + self.repeat_value += 1 + imgui.same_line() + imgui.text(f'value: {self.repeat_value}') + imgui.pop_button_repeat() + + imgui.push_item_width(150) + imgui.drag_float('fl (w=150)', 0.5) + imgui.pop_item_width() + imgui.text(f'calc_item_width: {imgui.calc_item_width()}') + + imgui.set_next_item_width(250) + imgui.drag_float('fl (w=250)', 0.5) + imgui.text(f'calc_item_width: {imgui.calc_item_width()}') + + imgui.push_text_wrap_pos(200) + imgui.text('This is a long text that is wrapped at 200 pixels width. ' * 3) + imgui.pop_text_wrap_pos() + + def cursor_test(self): + imgui.separator() + + imgui.text('Text') + imgui.same_line() + imgui.text('Text after same_line') + + imgui.newline() + imgui.text('Text after newline') + + imgui.spacing() + imgui.text('Text after spacing') + + imgui.dummy((0, 20)) + imgui.text('Text after dummy(0,20)') + + imgui.indent(20) + imgui.text('Text after indent(20)') + imgui.text('More text after indent(20)') + + imgui.unindent(20) + imgui.text('Text after unindent(20)') + + imgui.text(f'get_cursor_pos: ({imgui.get_cursor_pos()[0]}, {imgui.get_cursor_pos()[1]})') + imgui.text(f'get_cursor_pos_x: {imgui.get_cursor_pos_x()}') + imgui.text(f'get_cursor_pos_y: {imgui.get_cursor_pos_y()}') + imgui.text(f'get_cursor_screen_pos: ({imgui.get_cursor_screen_pos()[0]}, {imgui.get_cursor_screen_pos()[1]})') + imgui.text(f'get_text_line_height: {imgui.get_text_line_height()}') + imgui.text(f'get_text_line_height_with_spacing: {imgui.get_text_line_height_with_spacing()}') + + def text_test(self): + imgui.text_unformatted('text_unformatted') + imgui.text('text') + imgui.text_colored((1.0, 0.0, 0.0, 1.0), 'text_colored (red)') + imgui.text_disabled('text_disabled') + imgui.label_text('label1', 'label_text1') + imgui.label_text('label2', 'label_text2') + imgui.bullet_text('bullet_text 1') + imgui.bullet_text('bullet_text 2') + + def main_widget_test(self): + if not hasattr(self, 'main_checked'): + self.main_checked = False + self.main_flags = 0 + self.main_radio = 0 + self.main_radio2 = 0 + + if imgui.button('press me'): + imgui.same_line() + imgui.text('pressed!!') + + imgui.text('invisible button test:') + if imgui.invisible_button('invisible_btn', (100, 50)): + imgui.same_line() + imgui.text('invisible button pressed!!') + + if imgui.arrow_button('arrow_btn', imgui.Dir_Left): + imgui.same_line() + imgui.text('arrow button pressed!!') + + _, self.main_checked = imgui.checkbox('checkbox', self.main_checked) + _, self.main_flags = imgui.checkbox_flags('flag1', self.main_flags, 1) + imgui.same_line() + _, self.main_flags = imgui.checkbox_flags('flag2', self.main_flags, 2) + imgui.same_line() + _, self.main_flags = imgui.checkbox_flags('flag3', self.main_flags, 4) + + if imgui.radio_button('radio1', self.main_radio == 0): + self.main_radio = 0 + if imgui.radio_button('radio2', self.main_radio == 1): + self.main_radio = 1 + if imgui.radio_button('radio3', self.main_radio == 2): + self.main_radio = 2 + + _, self.main_radio2 = imgui.radio_button_int('radio_int1', self.main_radio2, 0) + _, self.main_radio2 = imgui.radio_button_int('radio_int2', self.main_radio2, 1) + _, self.main_radio2 = imgui.radio_button_int('radio_int3', self.main_radio2, 2) + + imgui.progress_bar((imgui.get_time() * 0.5) % 1.0, (200, 20), 'progress_bar') + imgui.bullet() + imgui.same_line() + imgui.text('bullet text in main widget') + + def image_test(self): + if not hasattr(self, 'image_texture'): + colors = numpy.array([glk.colormapf(glk.COLORMAP.TURBO, x / 128.0) for x in range(128)]).reshape(1, 128, 4) + img = colors.repeat(128, axis=0).astype(numpy.float32) + self.image_texture = glk.create_texture_f(img) + + imgui.image(self.image_texture, (256, 256)) + + if imgui.image_button('image_button', self.image_texture, (64, 64)): + imgui.same_line() + imgui.text('image button pressed!!') + + def combo_test(self): + if not hasattr(self, 'combo_selected'): + self.combo_selected = 'option 0' + self.combo_selected2 = 0 + + if imgui.begin_combo('combo', 'select an option'): + for i in range(5): + if imgui.selectable(f'option {i}'): + imgui.same_line() + self.combo_selected = f'option {i}' + imgui.end_combo() + + imgui.text(f'selected: {self.combo_selected}') + + _, self.combo_selected2 = imgui.combo('combo_int', self.combo_selected2, [f'item {i}' for i in range(5)]) + + def drag_test(self): + if not hasattr(self, 'drag_float'): + self.drag_float = 0.0 + self.drag_float2 = [0.0, 1.0] + self.drag_float3 = [0.0, 1.0, 2.0] + self.drag_float4 = [0.0, 1.0, 2.0, 3.0] + + self.drag_int = 0 + self.drag_int2 = [0, 1] + self.drag_int3 = [0, 1, 2] + self.drag_int4 = [0, 1, 2, 3] + + _, self.drag_float = imgui.drag_float('drag_float1', self.drag_float, 0.1, 0.0, 10.0) + _, self.drag_float2 = imgui.drag_float2('drag_float2', self.drag_float2, 0.1, 0.0, 10.0) + _, self.drag_float3 = imgui.drag_float3('drag_float3', self.drag_float3, 0.1, 0.0, 10.0) + _, self.drag_float4 = imgui.drag_float4('drag_float4', self.drag_float4, 0.1, 0.0, 10.0) + _, self.drag_float2 = imgui.drag_float_range2('drag_float_range2', self.drag_float2, 0.1, 0.0, 10.0) + + _, self.drag_int = imgui.drag_int('drag_int1', self.drag_int, 1, 0, 100) + _, self.drag_int2 = imgui.drag_int2('drag_int2', self.drag_int2, 1, 0, 100) + _, self.drag_int3 = imgui.drag_int3('drag_int3', self.drag_int3, 1, 0, 100) + _, self.drag_int4 = imgui.drag_int4('drag_int4', self.drag_int4, 1, 0, 100) + _, self.drag_int2 = imgui.drag_int_range2('drag_int_range2', self.drag_int2, 1, 0, 100) + + _, self.drag_float = imgui.slider_float('slider_float', self.drag_float, 0.0, 10.0) + _, self.drag_float2 = imgui.slider_float2('slider_float2', self.drag_float2, 0.0, 10.0) + _, self.drag_float3 = imgui.slider_float3('slider_float3', self.drag_float3, 0.0, 10.0) + _, self.drag_float4 = imgui.slider_float4('slider_float4', self.drag_float4, 0.0, 10.0) + _, self.drag_float = imgui.slider_angle('slider_angle', self.drag_float) + + _, self.drag_int = imgui.slider_int('slider_int', self.drag_int, 0, 100) + _, self.drag_int2 = imgui.slider_int2('slider_int2', self.drag_int2, 0, 100) + _, self.drag_int3 = imgui.slider_int3('slider_int3', self.drag_int3, 0, 100) + _, self.drag_int4 = imgui.slider_int4('slider_int4', self.drag_int4, 0, 100) + + def input_text_test(self): + if not hasattr(self, 'input_text'): + self.input_text = 'input text' + self.input_text_multiline = 'This is a multiline\ninput text box.\nYou can write multiple lines here.' + self.input_text_with_hint = '' + self.input_float = 0.0 + self.input_float2 = [0.0, 1.0] + self.input_float3 = [0.0, 1.0, 2.0] + self.input_float4 = [0.0, 1.0, 2.0, 3.0] + self.input_int = 0 + self.input_int2 = [0, 1] + self.input_int3 = [0, 1, 2] + self.input_int4 = [0, 1, 2, 3] + + _, self.input_text = imgui.input_text('input_text', self.input_text) + _, self.input_text_multiline = imgui.input_text_multiline('input_text_multiline', self.input_text_multiline, (300, 100)) + _, self.input_text_with_hint = imgui.input_text_with_hint('input_text_with_hint', 'enter text here...', self.input_text_with_hint) + _, self.input_float = imgui.input_float('input_float', self.input_float, 0.1, 1.0) + _, self.input_float2 = imgui.input_float2('input_float2', self.input_float2) + _, self.input_float3 = imgui.input_float3('input_float3', self.input_float3) + _, self.input_float4 = imgui.input_float4('input_float4', self.input_float4) + _, self.input_int = imgui.input_int('input_int', self.input_int) + _, self.input_int2 = imgui.input_int2('input_int2', self.input_int2) + _, self.input_int3 = imgui.input_int3('input_int3', self.input_int3) + _, self.input_int4 = imgui.input_int4('input_int4', self.input_int4) + + def color_test(self): + if not hasattr(self, 'color3'): + self.color3 = [1.0, 0.0, 0.0] + self.color4 = [0.0, 1.0, 0.0, 1.0] + + _, self.color3 = imgui.color_edit3('color3', self.color3) + _, self.color4 = imgui.color_edit4('color4', self.color4) + _, self.color3 = imgui.color_picker3('color_picker3', self.color3) + _, self.color4 = imgui.color_picker4('color_picker4', self.color4) + + if imgui.color_button('color_button', self.color4): + imgui.same_line() + imgui.text('color button pressed!!') + + def trees_test(self): + if imgui.tree_node('tree node 1'): + imgui.text('inside tree node 1') + if imgui.tree_node('tree node 2'): + imgui.text('inside tree node 2') + imgui.tree_pop() + imgui.tree_pop() + + def menu_test(self): + if imgui.begin_main_menu_bar(): + if imgui.begin_menu('menu'): + if imgui.menu_item('menu_item 1'): + pass + if imgui.menu_item('menu_item 2'): + pass + if imgui.begin_menu('menux'): + imgui.menu_item('menu_item x1') + + imgui.end_menu() + + imgui.end_menu() + + if imgui.begin_menu('menu2'): + if imgui.menu_item('menu_item A'): + pass + if imgui.menu_item('menu_item B'): + pass + imgui.end_menu() + + imgui.end_main_menu_bar() + + def popup_test(self): + if not hasattr(self, 'modal_opened'): + self.modal_opened = False + + imgui.text('tooltip') + if imgui.is_item_hovered(): + imgui.begin_tooltip() + imgui.text('this is a tooltip') + imgui.end_tooltip() + + if imgui.button('open popup'): + imgui.open_popup('popup1') + + if imgui.begin_popup('popup1', imgui.WindowFlags_AlwaysAutoResize): + imgui.text('this is a popup') + if imgui.button('close'): + imgui.close_current_popup() + imgui.end_popup() + imgui.text(f'popup open: {imgui.is_popup_open("popup1")}') + + if imgui.button('open modal'): + imgui.open_popup('modal1') + + if imgui.begin_popup_modal('modal1', imgui.WindowFlags_AlwaysAutoResize): + imgui.text('this is a modal popup') + if imgui.button('close'): + imgui.close_current_popup() + imgui.end_popup() + + def table_test(self): + imgui.begin_table('table1', 3, imgui.TableFlags_Borders | imgui.TableFlags_RowBg) + for row in range(3): + imgui.table_next_row() + for column in range(3): + imgui.table_set_column_index(column) + imgui.text(f'Row {row}, Column {column}') + imgui.end_table() + + def query_test(self): + if not hasattr(self, 'query_text'): + self.query_text = 'text' + + _, self.query_text = imgui.input_text('query', self.query_text) + + imgui.text(f'is_item_hovered: {imgui.is_item_hovered()}') + imgui.text(f'is_item_active: {imgui.is_item_active()}') + imgui.text(f'is_item_focused: {imgui.is_item_focused()}') + imgui.text(f'is_item_clicked: {imgui.is_item_clicked()}') + imgui.text(f'is_item_visible: {imgui.is_item_visible()}') + imgui.text(f'is_item_edited: {imgui.is_item_edited()}') + imgui.text(f'is_item_deactivated: {imgui.is_item_deactivated()}') + imgui.text(f'is_item_deactivated_after_edit: {imgui.is_item_deactivated_after_edit()}') + imgui.text(f'is_item_toggled_open: {imgui.is_item_toggled_open()}') + imgui.text(f'is_any_item_hovered: {imgui.is_any_item_hovered()}') + imgui.text(f'is_any_item_active: {imgui.is_any_item_active()}') + imgui.text(f'is_any_item_focused: {imgui.is_any_item_focused()}') + imgui.text(f'get_item_id: {imgui.get_item_id()}') + imgui.text(f'get_item_rect_min: ({imgui.get_item_rect_min()[0]}, {imgui.get_item_rect_min()[1]})') + imgui.text(f'get_item_rect_max: ({imgui.get_item_rect_max()[0]}, {imgui.get_item_rect_max()[1]})') + imgui.text(f'get_item_rect_size: ({imgui.get_item_rect_size()[0]}, {imgui.get_item_rect_size()[1]})') + + text = 'test' + text_size = imgui.calc_text_size(text) + imgui.text(f'calc_text_size("{text}"): ({text_size[0]}, {text_size[1]})') + + def ui_callback(self): + imgui.begin('ui', flags=imgui.WindowFlags_AlwaysAutoResize) + + if imgui.begin_tab_bar('tab_bar'): + if imgui.begin_tab_item('io'): + self.io_test() + imgui.end_tab_item() + + if imgui.begin_tab_item('style'): + self.style_test() + imgui.end_tab_item() + + if imgui.begin_tab_item('drawlist'): + self.drawlist_test() + imgui.end_tab_item() + + if imgui.begin_tab_item('demo'): + self.demo_test() + imgui.end_tab_item() + + if imgui.begin_tab_item('win'): + self.win_test() + imgui.end_tab_item() + + if imgui.begin_tab_item('param_stacks'): + self.param_stacks_test() + imgui.end_tab_item() + + if imgui.begin_tab_item('cursor'): + self.cursor_test() + imgui.end_tab_item() + + if imgui.begin_tab_item('text'): + self.text_test() + imgui.end_tab_item() + + if imgui.begin_tab_item('main_widget'): + self.main_widget_test() + imgui.end_tab_item() + + if imgui.begin_tab_item('image'): + self.image_test() + imgui.end_tab_item() + + if imgui.begin_tab_item('combo'): + self.combo_test() + imgui.end_tab_item() + + if imgui.begin_tab_item('drag'): + self.drag_test() + imgui.end_tab_item() + + if imgui.begin_tab_item('input_test'): + self.input_text_test() + imgui.end_tab_item() + + if imgui.begin_tab_item('color'): + self.color_test() + imgui.end_tab_item() + + if imgui.begin_tab_item('trees'): + self.trees_test() + imgui.end_tab_item() + + if imgui.begin_tab_item('menu'): + self.menu_test() + imgui.end_tab_item() + + if imgui.begin_tab_item('popup'): + self.popup_test() + imgui.end_tab_item() + + if imgui.begin_tab_item('table'): + self.table_test() + imgui.end_tab_item() + + if imgui.begin_tab_item('query'): + self.query_test() + imgui.end_tab_item() + + imgui.end_tab_bar() + + imgui.end() + + +test_ui = TestUI() +test_ui.spin() From 5cbaadaa1fd7fbedb156ff978f192ab0941841be Mon Sep 17 00:00:00 2001 From: "k.koide" Date: Mon, 29 Dec 2025 21:49:04 +0900 Subject: [PATCH 03/40] return viewer shader setting reference --- src/python/guik.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python/guik.cpp b/src/python/guik.cpp index 88d0fdbf..57f4dc2f 100644 --- a/src/python/guik.cpp +++ b/src/python/guik.cpp @@ -322,7 +322,7 @@ void define_guik(py::module_& m) { .def( "shader_setting", - [](guik::LightViewerContext& context) { return context.shader_setting(); }, + [](guik::LightViewerContext& context) { return &context.shader_setting(); }, py::return_value_policy::reference) .def("disable_xy_grid", &guik::LightViewerContext::disable_xy_grid) From 56f1a132f07d8e11196b13759a86884bc32e1054 Mon Sep 17 00:00:00 2001 From: "k.koide" Date: Mon, 29 Dec 2025 22:56:35 +0900 Subject: [PATCH 04/40] refactor shader setting --- CMakeLists.txt | 1 + include/guik/viewer/shader_setting.hpp | 304 +++++++++--------- .../ext_light_viewer_partial_rendering.cpp | 2 +- src/guik/gl_canvas.cpp | 18 +- src/guik/viewer/light_viewer.cpp | 4 +- src/guik/viewer/light_viewer_context.cpp | 13 +- src/guik/viewer/shader_setting.cpp | 210 ++++++++++++ src/guik/viewer/viewer_ui.cpp | 6 +- 8 files changed, 372 insertions(+), 186 deletions(-) create mode 100644 src/guik/viewer/shader_setting.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index afb0b026..27dd16ef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -186,6 +186,7 @@ add_library(iridescence src/guik/camera/projection_control.cpp src/guik/camera/basic_projection_control.cpp src/guik/viewer/plot_data.cpp + src/guik/viewer/shader_setting.cpp src/guik/viewer/light_viewer.cpp src/guik/viewer/light_viewer_context.cpp src/guik/viewer/light_viewer_context_util.cpp diff --git a/include/guik/viewer/shader_setting.hpp b/include/guik/viewer/shader_setting.hpp index b58ed00c..3a36c8f5 100644 --- a/include/guik/viewer/shader_setting.hpp +++ b/include/guik/viewer/shader_setting.hpp @@ -12,18 +12,30 @@ namespace guik { +/// @brief Fragment color mode. +/// RAINBOW : Color mapped by 3D coordinates of pixels (by default, Z-axis is used for color mapping) +/// FLAT_COLOR : Single flat color +/// VERTEX_COLOR : Color from vertex color attribute +/// TEXTURE_COLOR : Color from texture map struct ColorMode { enum MODE { RAINBOW = 0, FLAT_COLOR = 1, VERTEX_COLOR = 2, TEXTURE_COLOR = 3 }; }; +/// @brief Point size scale mode. +/// SCREENSPACE : Screen space size +/// METRIC : Metric size (in meters) struct PointScaleMode { enum MODE { SCREENSPACE = 0, METRIC = 1 }; }; +/// @brief Point shape mode. +/// RECTANGLE : Square/rectangle shape +/// CIRCLE : Circle shape struct PointShapeMode { enum MODE { RECTANGLE = 0, CIRCLE = 1 }; }; +/// @brief Generic shader parameter interface. struct ShaderParameterInterface { public: using Ptr = std::shared_ptr; @@ -37,6 +49,7 @@ struct ShaderParameterInterface { std::string name; }; +/// @brief Type-specific shader parameter. template struct ShaderParameter : public ShaderParameterInterface { public: @@ -52,27 +65,26 @@ struct ShaderParameter : public ShaderParameterInterface { T value; }; -/// @brief Shader setting class holds rendering settings for the object. +/// @brief Shader setting class that holds rendering settings. struct ShaderSetting { public: using Ptr = std::shared_ptr; - - ShaderSetting() - : transparent(false), - params( - {glk::make_shared>("color_mode", ColorMode::FLAT_COLOR), - glk::make_shared>("point_scale", 1.0f), - glk::make_shared>("model_matrix", Eigen::Matrix4f::Identity())}) // - {} - - ShaderSetting(int color_mode) - : transparent(false), - params( - {glk::make_shared>("color_mode", color_mode), - glk::make_shared>("point_scale", 1.0f), - glk::make_shared>("model_matrix", Eigen::Matrix4f::Identity())}) // - {} - + using ConstPtr = std::shared_ptr; + + /// @brief Default constructor + /// @note Default parameters are: + /// color_mode : FLAT_COLOR + /// point_scale : 1.0 + /// model_matrix : Identity matrix + ShaderSetting(); + + /// @brief Constructor + /// @param color_mode Color mode (ColorMode) + ShaderSetting(int color_mode); + + /// @brief Constructor + /// @param color_mode Color mode (ColorMode) + /// @param transform Transform matrix (e.g., Eigen::Matrix4(f|d) or Eigen::Isometry3(f|d)) template ShaderSetting(int color_mode, const Transform& transform) : transparent(false), @@ -82,15 +94,11 @@ struct ShaderSetting { glk::make_shared>("model_matrix", (transform.template cast() * Eigen::Isometry3f::Identity()).matrix())}) // {} + /// @brief Destructor virtual ~ShaderSetting() {} - ShaderSetting clone() const { - ShaderSetting cloned; - cloned.transparent = transparent; - cloned.params.resize(params.size()); - std::transform(params.begin(), params.end(), cloned.params.begin(), [](const auto& p) { return p->clone(); }); - return cloned; - } + /// @brief Clone the shader setting. + ShaderSetting clone() const; /// @brief Add a new parameter to the shader setting. /// @param name Parameter name @@ -110,7 +118,7 @@ struct ShaderSetting { } } - params.push_back(glk::make_shared>(name, value)); + params.emplace_back(glk::make_shared>(name, value)); return *this; } @@ -135,6 +143,27 @@ struct ShaderSetting { return std::nullopt; } + /// @brief Get a parameter value from the shader setting. + /// @param name Parameter name + /// @return Parameter value if found, otherwise std::nullopt + template + std::optional get(const std::string& name) const { + for (const auto& param : params) { + if (param->name != name) { + continue; + } + + auto p = dynamic_cast*>(param.get()); + if (p == nullptr) { + continue; + } + + return p->value; + } + + return std::nullopt; + } + /// @brief Get a parameter value from the shader setting. This method avoid type checking. Fast but unsafe. /// @param name Parameter name /// @return Parameter value @@ -155,35 +184,22 @@ struct ShaderSetting { /// @brief Set shader parameters to the shader program. /// @param shader Shader program - void set(glk::GLSLShader& shader) const { - for (const auto& param : params) { - if (!param) { - continue; - } - param->set(shader); - } - } - - // Object type - ShaderSetting& static_object() { return add("dynamic_object", 0); } - - ShaderSetting& dynamic_object() { return add("dynamic_object", 1); } + void set(glk::GLSLShader& shader) const; - ShaderSetting& dymamic_object() { - std::cerr << "warning : dymamic_object() is deprecated. Use dynamic_object() instead. Sorry for the silly typo!!" << std::endl; - return add("dynamic_object", 1); - } + // Object type (static/dynamic) + /// @brief Set static object flag. + ShaderSetting& static_object(); + /// @brief Set dynamic object flag. + ShaderSetting& dynamic_object(); // Color - Eigen::Vector4f material_color() const { return cast("material_color"); } - - ShaderSetting& set_color(float r, float g, float b, float a) { - if (a < 0.999f) { - transparent = true; - } - return add("material_color", Eigen::Vector4f(r, g, b, a)); - } + /// @brief Get material color (FLAT_COLOR). + Eigen::Vector4f material_color() const; + /// @brief Set material color (FLAT_COLOR). + ShaderSetting& set_color(float r, float g, float b, float a); + /// @brief Set material color (for FLAT_COLOR). + /// @tparam Color Eigen 4d vector type (e.g., Eigen::Vector4f, Eigen::Vector4d) template ShaderSetting& set_color(const Color& color_) { const Eigen::Vector4f color = color_.template cast(); @@ -193,81 +209,66 @@ struct ShaderSetting { return add("material_color", color); } - ShaderSetting& set_alpha(float alpha) { - Eigen::Vector4f color(1.0f, 1.0f, 1.0f, 1.0f); - auto found = this->get("material_color"); - if (found) { - color = found.value(); - } - - color.w() = alpha; - this->add("material_color", color); - transparent = alpha < 0.999f; - return *this; - } - - ShaderSetting& make_transparent() { - transparent = true; - return *this; - } + /// @brief Set alpha value of the material color. + ShaderSetting& set_alpha(float alpha); + /// @brief Make the object transparent (alpha blending). + ShaderSetting& make_transparent(); // Point size and scale - float point_scale() const { - auto p = static_cast*>(params[1].get()); - return p->value; - } - - ShaderSetting& set_point_scale(float scaling) { - auto p = static_cast*>(params[1].get()); - p->value = scaling; - return *this; - } - - ShaderSetting& set_point_size(float size) { return add("point_size", size); } - ShaderSetting& set_point_size_offset(float offset) { return add("point_size_offset", offset); } + /// @brief Get point size scale factor. + float point_scale() const; + /// @brief Set point size scale factor. + ShaderSetting& set_point_scale(float scaling); + + /// @brief Get point size. + float point_size() const; + /// @brief Set point size. + ShaderSetting& set_point_size(float size); + /// @brief Set point size offset. + ShaderSetting& set_point_size_offset(float offset); // Point shape mode - ShaderSetting& set_point_shape_mode(guik::PointShapeMode::MODE mode) { return add("point_shape_mode", mode); } - ShaderSetting& set_point_shape_circle() { return set_point_shape_mode(guik::PointShapeMode::CIRCLE); } - ShaderSetting& set_point_shape_rectangle() { return set_point_shape_mode(guik::PointShapeMode::RECTANGLE); } + /// @brief Set point shape mode. + ShaderSetting& set_point_shape_mode(guik::PointShapeMode::MODE mode); + /// @brief Set point shape to circle. + ShaderSetting& set_point_shape_circle(); + /// @brief Set point shape to rectangle. + ShaderSetting& set_point_shape_rectangle(); // Point scale mode - ShaderSetting& set_point_scale_mode(guik::PointScaleMode::MODE mode) { return add("point_scale_mode", mode); } - ShaderSetting& set_point_scale_screenspace() { return set_point_scale_mode(guik::PointScaleMode::SCREENSPACE); } - ShaderSetting& set_point_scale_metric() { return set_point_scale_mode(guik::PointScaleMode::METRIC); } + /// @brief Set point size scale mode. + ShaderSetting& set_point_scale_mode(guik::PointScaleMode::MODE mode); + /// @brief Set point size scale to screen space. + ShaderSetting& set_point_scale_screenspace(); + /// @brief Set point size scale to metric. + ShaderSetting& set_point_scale_metric(); + + /// @brief Set point shape with common settings. + /// @param point_size Point size in meters (if metric) or in pseudo pixels (if screenspace) + /// @param metric If true, point size is in meters. If false, point size is in pixels. + /// @param circle If true, point shape is circle. If false, point shape is rectangle. + ShaderSetting& set_point_shape(float point_size, bool metric, bool circle); + + /// @brief Set old (v0.1.9) default point shape (rectangle + screenspace) + ShaderSetting& set_old_default_point_shape(); // Calling `remove_model_matrix` invalidates model matrix operations (translate, rotate, and scale) - ShaderSetting& remove_model_matrix() { - params[2] = nullptr; - return *this; - } - - int color_mode() const { - auto p = static_cast*>(params[0].get()); - return p->value; - } - - ShaderSetting& set_color_mode(int color_mode) { - auto p = static_cast*>(params[0].get()); - p->value = color_mode; - return *this; - } - - Eigen::Matrix4f model_matrix() const { - auto p = static_cast*>(params[2].get()); - return p->value; - } - - Eigen::Vector3f translation() const { - auto p = static_cast*>(params[2].get()); - return p->value.block<3, 1>(0, 3); - } - - Eigen::Matrix3f rotation() const { - auto p = static_cast*>(params[2].get()); - return p->value.block<3, 3>(0, 0); - } - + ShaderSetting& remove_model_matrix(); + + /// @brief Get color mode. + int color_mode() const; + /// @brief Set color mode. + ShaderSetting& set_color_mode(int color_mode); + + /// @brief Get model matrix. + Eigen::Matrix4f model_matrix() const; + /// @brief Get translation vector from the model matrix. + Eigen::Vector3f translation() const; + /// @brief Get rotation matrix from the model matrix. + Eigen::Matrix3f rotation() const; + + /// @brief Set model matrix. + /// @tparam Transform Transform matrix type (e.g., Eigen::Matrix4(f|d) or Eigen::Isometry3(f|d)) template ShaderSetting& set_model_matrix(const Transform& transform) { auto p = static_cast*>(params[2].get()); @@ -275,6 +276,9 @@ struct ShaderSetting { return *this; } + /// @brief Apply transformation to the model matrix. + /// @tparam Transform Transform matrix type (e.g., Eigen::Matrix4(f|d) or Eigen::Isometry3(f|d)) + /// @note The transformation is applied after the existing transformation. (T_new = T_old * transform) template ShaderSetting& transform(const Transform& transform) { auto p = static_cast*>(params[2].get()); @@ -282,14 +286,12 @@ struct ShaderSetting { return *this; } - ShaderSetting& translate(float tx, float ty, float tz) { return translate(Eigen::Vector3f(tx, ty, tz)); } - - ShaderSetting& translate(const Eigen::Vector3f& translation) { - auto p = static_cast*>(params[2].get()); - p->value.block<3, 1>(0, 3) += translation; - return *this; - } - + /// @brief Apply translation to the model matrix. + ShaderSetting& translate(float tx, float ty, float tz); + /// @brief Apply translation to the model matrix. + ShaderSetting& translate(const Eigen::Vector3f& translation); + /// @brief Apply translation to the model matrix. + /// @tparam Vector Eigen vector type (e.g., Eigen::Vector3f, Eigen::Vector3d) template ShaderSetting& translate(const Vector& translation) { auto p = static_cast*>(params[2].get()); @@ -298,13 +300,9 @@ struct ShaderSetting { return *this; } - ShaderSetting& rotate(const float angle, const Eigen::Vector3f& axis) { - const Eigen::Vector3f ax = axis.eval().template cast(); - auto p = static_cast*>(params[2].get()); - p->value = p->value * (Eigen::Isometry3f::Identity() * Eigen::AngleAxisf(angle, axis)).matrix(); - return *this; - } - + /// @brief Apply rotation to the model matrix. + ShaderSetting& rotate(const float angle, const Eigen::Vector3f& axis); + /// @brief Apply rotation to the model matrix. template ShaderSetting& rotate(const float angle, const Vector& axis) { const Eigen::Vector3f ax = axis.eval().template cast(); @@ -312,14 +310,16 @@ struct ShaderSetting { p->value = p->value * (Eigen::Isometry3f::Identity() * Eigen::AngleAxisf(angle, ax)).matrix(); return *this; } - + /// @brief Apply rotation to the model matrix. + /// @param quat Rotation quaternion (Eigen::Quaternion(f|d)) template ShaderSetting& rotate(const Eigen::Quaternion& quat) { auto p = static_cast*>(params[2].get()); p->value = p->value * (Eigen::Isometry3f::Identity() * quat.template cast()).matrix(); return *this; } - + /// @brief Apply rotation to the model matrix. + /// @param rot Rotation matrix (Eigen::Matrix3(f|d)) template ShaderSetting& rotate(const Eigen::Matrix& rot) { Eigen::Isometry3f R = Eigen::Isometry3f::Identity(); @@ -330,28 +330,14 @@ struct ShaderSetting { return *this; } - ShaderSetting& scale(float scaling) { - auto p = static_cast*>(params[2].get()); - p->value.block<4, 3>(0, 0) *= scaling; - return *this; - } - - ShaderSetting& scale(float sx, float sy, float sz) { - auto p = static_cast*>(params[2].get()); - p->value.col(0) *= sx; - p->value.col(1) *= sy; - p->value.col(2) *= sz; - return *this; - } - - ShaderSetting& scale(const Eigen::Vector3f& scaling) { - auto p = static_cast*>(params[2].get()); - p->value.col(0) *= scaling[0]; - p->value.col(1) *= scaling[1]; - p->value.col(2) *= scaling[2]; - return *this; - } - + /// @brief Apply uniform scaling to the model matrix. + ShaderSetting& scale(float scaling); + /// @brief Apply scaling to the model matrix (non-uniform). + ShaderSetting& scale(float sx, float sy, float sz); + /// @brief Apply scaling to the model matrix (non-uniform). + ShaderSetting& scale(const Eigen::Vector3f& scaling); + /// @brief Apply scaling to the model matrix (non-uniform). + /// @tparam Vector Eigen vector type (e.g., Eigen::Vector3f, Eigen::Vector3d) template std::enable_if_t, ShaderSetting&> scale(const Vector& scaling) { auto p = static_cast*>(params[2].get()); @@ -363,8 +349,8 @@ struct ShaderSetting { } public: - bool transparent; - std::vector params; + bool transparent; ///< If true, the object is rendered as transparent. + std::vector params; ///< Shader parameters }; template <> diff --git a/src/example/ext_light_viewer_partial_rendering.cpp b/src/example/ext_light_viewer_partial_rendering.cpp index c8d36c58..23ce8228 100644 --- a/src/example/ext_light_viewer_partial_rendering.cpp +++ b/src/example/ext_light_viewer_partial_rendering.cpp @@ -56,7 +56,7 @@ int main(int argc, char** argv) { .translate(std::cos(t) * 10.0f, std::sin(t) * 10.0f, 0.0f) .scale(1.0f, 1.0f, 20.0f) // Mark as dynamic object - .dymamic_object(); + .dynamic_object(); viewer->update_cube("cube", setting); } diff --git a/src/guik/gl_canvas.cpp b/src/guik/gl_canvas.cpp index 17af155f..a70d4497 100644 --- a/src/guik/gl_canvas.cpp +++ b/src/guik/gl_canvas.cpp @@ -42,9 +42,9 @@ GLCanvas::GLCanvas(const Eigen::Vector2i& size, const std::string& shader_name, shader->use(); - shader->set_uniform("point_scale_mode", 0); - shader->set_uniform("point_shape_mode", 0); - shader->set_uniform("point_size", 10.0f); + shader->set_uniform("point_scale_mode", 1); + shader->set_uniform("point_shape_mode", 1); + shader->set_uniform("point_size", 0.025f); shader->set_uniform("point_scale", 1.0f); shader->set_uniform("point_size_offset", 0.0f); @@ -109,9 +109,9 @@ bool GLCanvas::load_shader(const std::string& shader_name) { shader->use(); - shader->set_uniform("point_scale_mode", 0); - shader->set_uniform("point_shape_mode", 0); - shader->set_uniform("point_size", 10.0f); + shader->set_uniform("point_scale_mode", 1); + shader->set_uniform("point_shape_mode", 1); + shader->set_uniform("point_size", 0.025f); shader->set_uniform("point_scale", 1.0f); shader->set_uniform("point_size_offset", 0.0f); @@ -277,9 +277,9 @@ void GLCanvas::bind() { } shader->use(); - shader->set_uniform("point_scale_mode", 0); - shader->set_uniform("point_shape_mode", 0); - shader->set_uniform("point_size", 10.0f); + shader->set_uniform("point_scale_mode", 1); + shader->set_uniform("point_shape_mode", 1); + shader->set_uniform("point_size", 0.025f); shader->set_uniform("point_scale", 1.0f); shader->set_uniform("point_size_offset", 0.0f); diff --git a/src/guik/viewer/light_viewer.cpp b/src/guik/viewer/light_viewer.cpp index 99f06ded..5a6f334c 100644 --- a/src/guik/viewer/light_viewer.cpp +++ b/src/guik/viewer/light_viewer.cpp @@ -112,11 +112,11 @@ void LightViewer::draw_ui() { if (decrease_point_size || increase_point_size) { auto point_size = global_shader_setting.get("point_size"); if (!point_size) { - point_size = 10.0f; + point_size = 0.025f; } const auto point_scale_mode = global_shader_setting.get("point_scale_mode"); - const float scaling_factor = (point_scale_mode && *point_scale_mode == guik::PointScaleMode::METRIC) ? 0.1f : 10.0f; + const float scaling_factor = (point_scale_mode && *point_scale_mode == guik::PointScaleMode::SCREENSPACE) ? 10.0f : 0.1f; if (decrease_point_size) { *point_size = point_size.value() - ImGui::GetIO().DeltaTime * scaling_factor; diff --git a/src/guik/viewer/light_viewer_context.cpp b/src/guik/viewer/light_viewer_context.cpp index 24446456..b81d0ca3 100644 --- a/src/guik/viewer/light_viewer_context.cpp +++ b/src/guik/viewer/light_viewer_context.cpp @@ -519,18 +519,7 @@ std::shared_ptr LightViewerContext::use_fps_camera_control(dou } void LightViewerContext::set_point_shape(float point_size, bool metric, bool circle) { - shader_setting().set_point_size(point_size); - if (metric) { - shader_setting().set_point_scale_metric(); - } else { - shader_setting().set_point_scale_screenspace(); - } - - if (circle) { - shader_setting().set_point_shape_circle(); - } else { - shader_setting().set_point_shape_rectangle(); - } + shader_setting().set_point_shape(point_size, metric, circle); } Eigen::Vector4i LightViewerContext::pick_info(const Eigen::Vector2i& p, int window) const { diff --git a/src/guik/viewer/shader_setting.cpp b/src/guik/viewer/shader_setting.cpp new file mode 100644 index 00000000..18e3929c --- /dev/null +++ b/src/guik/viewer/shader_setting.cpp @@ -0,0 +1,210 @@ +#include + +namespace guik { + +ShaderSetting::ShaderSetting() +: transparent(false), + params( + {glk::make_shared>("color_mode", ColorMode::FLAT_COLOR), + glk::make_shared>("point_scale", 1.0f), + glk::make_shared>("model_matrix", Eigen::Matrix4f::Identity())}) // +{} + +ShaderSetting::ShaderSetting(int color_mode) +: transparent(false), + params( + {glk::make_shared>("color_mode", color_mode), + glk::make_shared>("point_scale", 1.0f), + glk::make_shared>("model_matrix", Eigen::Matrix4f::Identity())}) // +{} + +ShaderSetting ShaderSetting::clone() const { + ShaderSetting cloned; + cloned.transparent = transparent; + cloned.params.resize(params.size()); + std::transform(params.begin(), params.end(), cloned.params.begin(), [](const auto& p) { return p->clone(); }); + return cloned; +} + +void ShaderSetting::set(glk::GLSLShader& shader) const { + for (const auto& param : params) { + if (!param) { + continue; + } + param->set(shader); + } +} + +ShaderSetting& ShaderSetting::static_object() { + return add("dynamic_object", 0); +} + +ShaderSetting& ShaderSetting::dynamic_object() { + return add("dynamic_object", 1); +} + +Eigen::Vector4f ShaderSetting::material_color() const { + return cast("material_color"); +} + +ShaderSetting& ShaderSetting::set_color(float r, float g, float b, float a) { + if (a < 0.999f) { + transparent = true; + } + return add("material_color", Eigen::Vector4f(r, g, b, a)); +} + +ShaderSetting& ShaderSetting::set_alpha(float alpha) { + Eigen::Vector4f color(1.0f, 1.0f, 1.0f, 1.0f); + auto found = this->get("material_color"); + if (found) { + color = found.value(); + } + + color.w() = alpha; + this->add("material_color", color); + transparent = alpha < 0.999f; + return *this; +} + +ShaderSetting& ShaderSetting::make_transparent() { + transparent = true; + return *this; +} + +float ShaderSetting::point_scale() const { + auto p = static_cast*>(params[1].get()); + return p->value; +} + +ShaderSetting& ShaderSetting::set_point_scale(float scaling) { + auto p = static_cast*>(params[1].get()); + p->value = scaling; + return *this; +} + +float ShaderSetting::point_size() const { + return get("point_size").value_or(1.0f); +} +ShaderSetting& ShaderSetting::set_point_size(float size) { + return add("point_size", size); +} +ShaderSetting& ShaderSetting::set_point_size_offset(float offset) { + return add("point_size_offset", offset); +} + +// Point shape mode +ShaderSetting& ShaderSetting::set_point_shape_mode(guik::PointShapeMode::MODE mode) { + return add("point_shape_mode", mode); +} +ShaderSetting& ShaderSetting::set_point_shape_circle() { + return set_point_shape_mode(guik::PointShapeMode::CIRCLE); +} +ShaderSetting& ShaderSetting::set_point_shape_rectangle() { + return set_point_shape_mode(guik::PointShapeMode::RECTANGLE); +} + +// Point scale mode +ShaderSetting& ShaderSetting::set_point_scale_mode(guik::PointScaleMode::MODE mode) { + return add("point_scale_mode", mode); +} +ShaderSetting& ShaderSetting::set_point_scale_screenspace() { + return set_point_scale_mode(guik::PointScaleMode::SCREENSPACE); +} +ShaderSetting& ShaderSetting::set_point_scale_metric() { + return set_point_scale_mode(guik::PointScaleMode::METRIC); +} + +ShaderSetting& ShaderSetting::set_point_shape(float point_size, bool metric, bool circle) { + set_point_size(point_size); + if (metric) { + set_point_scale_metric(); + } else { + set_point_scale_screenspace(); + } + if (circle) { + set_point_shape_circle(); + } else { + set_point_shape_rectangle(); + } + return *this; +} + +ShaderSetting& ShaderSetting::set_old_default_point_shape() { + set_point_scale_screenspace(); + set_point_shape_rectangle(); + set_point_size(10.0f); + return *this; +} + +ShaderSetting& ShaderSetting::remove_model_matrix() { + params[2] = nullptr; + return *this; +} + +int ShaderSetting::color_mode() const { + auto p = static_cast*>(params[0].get()); + return p->value; +} + +ShaderSetting& ShaderSetting::set_color_mode(int color_mode) { + auto p = static_cast*>(params[0].get()); + p->value = color_mode; + return *this; +} + +Eigen::Matrix4f ShaderSetting::model_matrix() const { + auto p = static_cast*>(params[2].get()); + return p->value; +} + +Eigen::Vector3f ShaderSetting::translation() const { + auto p = static_cast*>(params[2].get()); + return p->value.block<3, 1>(0, 3); +} + +Eigen::Matrix3f ShaderSetting::rotation() const { + auto p = static_cast*>(params[2].get()); + return p->value.block<3, 3>(0, 0); +} + +ShaderSetting& ShaderSetting::translate(float tx, float ty, float tz) { + return translate(Eigen::Vector3f(tx, ty, tz)); +} + +ShaderSetting& ShaderSetting::translate(const Eigen::Vector3f& translation) { + auto p = static_cast*>(params[2].get()); + p->value.block<3, 1>(0, 3) += translation; + return *this; +} + +ShaderSetting& ShaderSetting::rotate(const float angle, const Eigen::Vector3f& axis) { + const Eigen::Vector3f ax = axis.eval().template cast(); + auto p = static_cast*>(params[2].get()); + p->value = p->value * (Eigen::Isometry3f::Identity() * Eigen::AngleAxisf(angle, axis)).matrix(); + return *this; +} + +ShaderSetting& ShaderSetting::scale(float scaling) { + auto p = static_cast*>(params[2].get()); + p->value.block<4, 3>(0, 0) *= scaling; + return *this; +} + +ShaderSetting& ShaderSetting::scale(float sx, float sy, float sz) { + auto p = static_cast*>(params[2].get()); + p->value.col(0) *= sx; + p->value.col(1) *= sy; + p->value.col(2) *= sz; + return *this; +} + +ShaderSetting& ShaderSetting::scale(const Eigen::Vector3f& scaling) { + auto p = static_cast*>(params[2].get()); + p->value.col(0) *= scaling[0]; + p->value.col(1) *= scaling[1]; + p->value.col(2) *= scaling[2]; + return *this; +} + +} // namespace guik diff --git a/src/guik/viewer/viewer_ui.cpp b/src/guik/viewer/viewer_ui.cpp index db17cec8..d01b0468 100644 --- a/src/guik/viewer/viewer_ui.cpp +++ b/src/guik/viewer/viewer_ui.cpp @@ -66,7 +66,7 @@ class LightViewer::ViewerUI::DisplaySettingWindow { auto point_scale_mode = viewer->shader_setting().get("point_scale_mode"); if (!point_scale_mode) { - point_scale_mode = 0; + point_scale_mode = 1; } if (ImGui::Combo("Point scale mode", &point_scale_mode.value(), "SCREENSPACE\0METRIC\0")) { viewer->shader_setting().add("point_scale_mode", *point_scale_mode); @@ -77,7 +77,7 @@ class LightViewer::ViewerUI::DisplaySettingWindow { auto point_shape_mode = viewer->shader_setting().get("point_shape_mode"); if (!point_shape_mode) { - point_shape_mode = 0; + point_shape_mode = 1; } if (ImGui::Combo("Point shape mode", &point_shape_mode.value(), "RECTANGLE\0CIRCLE\0")) { viewer->shader_setting().add("point_shape_mode", *point_shape_mode); @@ -85,7 +85,7 @@ class LightViewer::ViewerUI::DisplaySettingWindow { auto point_size = viewer->shader_setting().get("point_size"); if (!point_size) { - point_size = 10.0f; + point_size = 0.025f; } if (ImGui::DragFloat("Point size", &point_size.value(), 0.001f, 0.0f, 1000.0f)) { viewer->shader_setting().add("point_size", *point_size); From c3071e9259a657e1befb1cf88c6a2da80053b0b0 Mon Sep 17 00:00:00 2001 From: "k.koide" Date: Tue, 30 Dec 2025 01:15:21 +0900 Subject: [PATCH 05/40] vertex colormap --- data/shader/rainbow.vert | 14 ++++-- include/glk/pointcloud_buffer.hpp | 23 ++++++++++ include/glk/thin_lines.hpp | 54 ++++++++++++++++++++++ include/glk/type_conversion.hpp | 7 +++ include/guik/viewer/shader_setting.hpp | 22 +++++++-- src/glk/pointcloud_buffer.cpp | 63 ++++++++++++++++++++++++++ src/glk/splatting.cpp | 1 + src/glk/thin_lines.cpp | 41 ++++++++++++++++- src/guik/gl_canvas.cpp | 2 + src/guik/viewer/viewer_ui.cpp | 9 ++++ 10 files changed, 226 insertions(+), 10 deletions(-) diff --git a/data/shader/rainbow.vert b/data/shader/rainbow.vert index f1bf3805..213ed9ba 100644 --- a/data/shader/rainbow.vert +++ b/data/shader/rainbow.vert @@ -20,25 +20,28 @@ uniform mat4 projection_matrix; // colormode = 1 : material_color // colormode = 2 : vert_color // colormode = 3 : texture_color +// colormode = 4 : vert_cmap (color map) uniform int color_mode; uniform vec4 material_color; uniform sampler2D colormap_sampler; uniform sampler2D texture_sampler; uniform vec2 z_range; +uniform vec2 cmap_range; uniform vec3 colormap_axis; in vec3 vert_position; in vec4 vert_color; in vec2 vert_texcoord; in vec3 vert_normal; +in float vert_cmap; out vec4 frag_color; out vec2 frag_texcoord; out vec3 frag_normal; -vec4 rainbow(vec3 position) { - float p = (dot(position, colormap_axis) - z_range[0]) / (z_range[1] - z_range[0]); +vec4 rainbow(float val, vec2 range) { + float p = (val - range[0]) / (range[1] - range[0]); return texture(colormap_sampler, vec2(p, 0.0)); } @@ -49,7 +52,7 @@ void main() { switch(color_mode) { case 0: - frag_color = rainbow(frag_world_position); + frag_color = rainbow(dot(frag_world_position, colormap_axis), z_range); frag_color.a = material_color.a; break; @@ -64,6 +67,11 @@ void main() { case 3: frag_texcoord = vert_texcoord; break; + + case 4: + frag_color = rainbow(vert_cmap, cmap_range); + frag_color.a = material_color.a; + break; } if(normal_enabled) { diff --git a/include/glk/pointcloud_buffer.hpp b/include/glk/pointcloud_buffer.hpp index df41d463..dd79c20d 100644 --- a/include/glk/pointcloud_buffer.hpp +++ b/include/glk/pointcloud_buffer.hpp @@ -63,6 +63,16 @@ class PointCloudBuffer : public glk::Drawable { void add_normals(const float* data, int stride, int num_points); void add_color(const float* data, int stride, int num_points); void add_intensity(glk::COLORMAP colormap, const float* data, int stride, int num_points, float scale = 1.0f); + + void set_colormap_buffer(const std::string& attribute_name); + void add_colormap(std::vector& cmap, float scale = 1.0f); + void add_colormap(std::vector& cmap, float scale = 1.0); + void add_colormap(const float* data, int stride, int num_points, float scale = 1.0f); + + void add_buffer(const std::string& attribute_name, const std::vector& data); + void add_buffer(const std::string& attribute_name, const std::vector& data); + template + void add_buffer(const std::string& attribute_name, const std::vector, Allocator>& data); void add_buffer(const std::string& attribute_name, int dim, const float* data, int stride, int num_points); // Partial attribute update methods (User must ensure that stride and dim are matched with existing attribute) @@ -111,6 +121,8 @@ class PointCloudBuffer : public glk::Drawable { int stride; int num_points; + GLuint cmap_bo; // buffer object for colormap attribute + std::vector aux_buffers; }; @@ -147,6 +159,17 @@ void PointCloudBuffer::add_color(const std::vector, add_color(colors.data(), colors.size()); } +template +void PointCloudBuffer::add_buffer(const std::string& attribute_name, const std::vector, Allocator>& data) { + if constexpr (std::is_same::value) { + add_buffer(attribute_name, D, data[0].data(), sizeof(float) * D, data.size()); + } else { + std::vector, Eigen::aligned_allocator>> data_f(data.size()); + std::transform(data.begin(), data.end(), data_f.begin(), [](const Eigen::Matrix& p) { return p.template cast(); }); + add_buffer(attribute_name, D, data_f.data(), sizeof(float) * D, data_f.size()); + } +} + template void PointCloudBuffer::update_points_with_indices(const std::vector, Allocator>& points, const std::vector& indices) { if (points.size() != indices.size()) { diff --git a/include/glk/thin_lines.hpp b/include/glk/thin_lines.hpp index c0174c89..bf3aef84 100644 --- a/include/glk/thin_lines.hpp +++ b/include/glk/thin_lines.hpp @@ -21,10 +21,15 @@ class ThinLines : public Drawable { ThinLines(const float* vertices, int num_vertices, bool line_strip = false); ThinLines(const float* vertices, const float* colors, int num_vertices, bool line_strip = false); ThinLines(const float* vertices, const float* colors, int num_vertices, const unsigned int* indices, int num_indices, bool line_strip = false); + ThinLines(const float* vertices, const float* colors, const float* cmap, int num_vertices, const unsigned int* indices, int num_indices, bool line_strip = false); ThinLines(const Eigen::Vector3f* vertices, int num_vertices, bool line_strip = false); ThinLines(const Eigen::Vector3f* vertices, const Eigen::Vector4f* colors, int num_vertices, bool line_strip = false); ThinLines(const Eigen::Vector3f* vertices, const Eigen::Vector4f* colors, int num_vertices, const unsigned int* indices, int num_indices, bool line_strip = false); + ThinLines(const Eigen::Vector3f* vertices, const float* cmap, int num_vertices, bool line_strip = false); + ThinLines(const Eigen::Vector3f* vertices, const double* cmap, int num_vertices, bool line_strip = false); + ThinLines(const Eigen::Vector3f* vertices, const float* cmap, int num_vertices, const unsigned int* indices, int num_indices, bool line_strip = false); + ThinLines(const Eigen::Vector3f* vertices, const double* cmap, int num_vertices, const unsigned int* indices, int num_indices, bool line_strip = false); template ThinLines(const Eigen::Matrix* vertices, int num_vertices, bool line_strip = false); @@ -40,6 +45,14 @@ class ThinLines : public Drawable { const unsigned int* indices, int num_indices, bool line_strip = false); + template + ThinLines(const Eigen::Matrix* vertices, const float* cmap, int num_vertices, bool line_strip = false); + template + ThinLines(const Eigen::Matrix* vertices, const double* cmap, int num_vertices, bool line_strip = false); + template + ThinLines(const Eigen::Matrix* vertices, const float* cmap, int num_vertices, const unsigned int* indices, int num_indices, bool line_strip = false); + template + ThinLines(const Eigen::Matrix* vertices, const double* cmap, int num_vertices, const unsigned int* indices, int num_indices, bool line_strip = false); template ThinLines(const std::vector, Allocator>& vertices, bool line_strip = false); @@ -53,6 +66,14 @@ class ThinLines : public Drawable { const std::vector, Allocator2>& colors, const std::vector& indices, bool line_strip = false); + template + ThinLines(const std::vector, Allocator>& vertices, const std::vector& cmap, bool line_strip = false); + template + ThinLines(const std::vector, Allocator>& vertices, const std::vector& cmap, bool line_strip = false); + template + ThinLines(const std::vector, Allocator>& vertices, const std::vector& cmap, const std::vector& indices, bool line_strip = false); + template + ThinLines(const std::vector, Allocator>& vertices, const std::vector& cmap, const std::vector& indices, bool line_strip = false); virtual ~ThinLines() override; @@ -73,6 +94,7 @@ class ThinLines : public Drawable { GLuint vao; // vertex array object GLuint vbo; // vertices GLuint cbo; // colors + GLuint cmbo; // colormap GLuint ebo; // indices }; @@ -110,6 +132,22 @@ ThinLines::ThinLines( num_indices, line_strip) {} +template +ThinLines::ThinLines(const Eigen::Matrix* vertices, const float* cmap, int num_vertices, bool line_strip) +: ThinLines(convert_to_vector(vertices, num_vertices).data(), cmap, num_vertices, nullptr, 0, line_strip) {} + +template +ThinLines::ThinLines(const Eigen::Matrix* vertices, const float* cmap, int num_vertices, const unsigned int* indices, int num_indices, bool line_strip) +: ThinLines(convert_to_vector(vertices, num_vertices).data(), cmap, num_vertices, indices, num_indices, line_strip) {} + +template +ThinLines::ThinLines(const Eigen::Matrix* vertices, const double* cmap, int num_vertices, bool line_strip) +: ThinLines(convert_to_vector(vertices, num_vertices).data(), cmap, num_vertices, nullptr, 0, line_strip) {} + +template +ThinLines::ThinLines(const Eigen::Matrix* vertices, const double* cmap, int num_vertices, const unsigned int* indices, int num_indices, bool line_strip) +: ThinLines(convert_to_vector(vertices, num_vertices).data(), cmap, num_vertices, indices, num_indices, line_strip) {} + template ThinLines::ThinLines(const std::vector, Allocator>& vertices, bool line_strip) : ThinLines(vertices.data(), vertices.size(), line_strip) {} @@ -129,6 +167,22 @@ ThinLines::ThinLines( bool line_strip) : ThinLines(vertices.data(), colors.data(), vertices.size(), indices.data(), indices.size(), line_strip) {} +template +ThinLines::ThinLines(const std::vector, Allocator>& vertices, const std::vector& cmap, bool line_strip) +: ThinLines(vertices.data(), cmap.data(), vertices.size(), line_strip) {} + +template +ThinLines::ThinLines(const std::vector, Allocator>& vertices, const std::vector& cmap, const std::vector& indices, bool line_strip) +: ThinLines(vertices.data(), cmap.data(), vertices.size(), indices.data(), indices.size(), line_strip) {} + +template +ThinLines::ThinLines(const std::vector, Allocator>& vertices, const std::vector& cmap, bool line_strip) +: ThinLines(vertices.data(), cmap.data(), vertices.size(), line_strip) {} + +template +ThinLines::ThinLines(const std::vector, Allocator>& vertices, const std::vector& cmap, const std::vector& indices, bool line_strip) +: ThinLines(vertices.data(), cmap.data(), vertices.size(), indices.data(), indices.size(), line_strip) {} + } // namespace glk #endif \ No newline at end of file diff --git a/include/glk/type_conversion.hpp b/include/glk/type_conversion.hpp index ef2902f3..4f761015 100644 --- a/include/glk/type_conversion.hpp +++ b/include/glk/type_conversion.hpp @@ -7,6 +7,13 @@ namespace glk { +template +std::vector convert_scalars(const Src* data, int num_data) { + std::vector converted(num_data); + std::copy(data, data + num_data, converted.begin()); + return converted; +} + template class Allocator> std::enable_if_t< std::is_same::value && Dst_Dim == Src_Dim, diff --git a/include/guik/viewer/shader_setting.hpp b/include/guik/viewer/shader_setting.hpp index 3a36c8f5..4bbd8d10 100644 --- a/include/guik/viewer/shader_setting.hpp +++ b/include/guik/viewer/shader_setting.hpp @@ -13,12 +13,13 @@ namespace guik { /// @brief Fragment color mode. -/// RAINBOW : Color mapped by 3D coordinates of pixels (by default, Z-axis is used for color mapping) -/// FLAT_COLOR : Single flat color -/// VERTEX_COLOR : Color from vertex color attribute -/// TEXTURE_COLOR : Color from texture map +/// RAINBOW : Color mapped by 3D coordinates of pixels (by default, Z-axis is used for color mapping) +/// FLAT_COLOR : Single flat color +/// VERTEX_COLOR : Color from vertex color attribute +/// TEXTURE_COLOR : Color from texture map +/// VERTEX_COLORMAP : Color from vertex colormap attribute struct ColorMode { - enum MODE { RAINBOW = 0, FLAT_COLOR = 1, VERTEX_COLOR = 2, TEXTURE_COLOR = 3 }; + enum MODE { RAINBOW = 0, FLAT_COLOR = 1, VERTEX_COLOR = 2, TEXTURE_COLOR = 3, VERTEX_COLORMAP = 4 }; }; /// @brief Point size scale mode. @@ -526,6 +527,17 @@ struct TextureColor : public ShaderSetting { virtual ~TextureColor() override {} }; +/// @brief Vertex colormap scheme that assigns colors based on vertex colormap attributes. +struct VertexColorMap : public ShaderSetting { +public: + VertexColorMap() : ShaderSetting(ColorMode::VERTEX_COLORMAP) {} + + template + VertexColorMap(const Transform& transform) : ShaderSetting(ColorMode::VERTEX_COLORMAP, (transform.template cast() * Eigen::Isometry3f::Identity()).matrix()) {} + + virtual ~VertexColorMap() override {} +}; + } // namespace guik #endif \ No newline at end of file diff --git a/src/glk/pointcloud_buffer.cpp b/src/glk/pointcloud_buffer.cpp index 03efea39..8c7432bf 100644 --- a/src/glk/pointcloud_buffer.cpp +++ b/src/glk/pointcloud_buffer.cpp @@ -25,6 +25,7 @@ PointCloudBuffer::PointCloudBuffer(int stride, int num_points) { rendering_count = 0; points_rendering_budget = 8192; ebo = 0; + cmap_bo = 0; } PointCloudBuffer::PointCloudBuffer(const float* data, int stride, int num_points) { @@ -45,6 +46,7 @@ PointCloudBuffer::PointCloudBuffer(const float* data, int stride, int num_points rendering_count = 0; points_rendering_budget = 8192; ebo = 0; + cmap_bo = 0; } PointCloudBuffer::PointCloudBuffer(const Eigen::Matrix& points) : PointCloudBuffer(points.data(), sizeof(Eigen::Vector3f), points.cols()) {} @@ -117,6 +119,50 @@ void PointCloudBuffer::add_intensity(glk::COLORMAP colormap, const float* data, add_color(colors[0].data(), sizeof(Eigen::Vector4f), num_points); } +void PointCloudBuffer::set_colormap_buffer(const std::string& attribute_name) { + auto found = std::find_if(aux_buffers.begin(), aux_buffers.end(), [&](const AuxBufferData& aux) { return aux.attribute_name == attribute_name; }); + if (found == aux_buffers.end()) { + std::cerr << console::bold_yellow << "warning : attribute_name=" << attribute_name << " does not exist!!" << console::reset << std::endl; + } else { + cmap_bo = found->buffer; + } +} + +void PointCloudBuffer::add_colormap(std::vector& cmap, float scale) { + add_colormap(cmap.data(), sizeof(float), cmap.size(), scale); +} + +void PointCloudBuffer::add_colormap(std::vector& cmap, float scale) { + std::vector cmap_f(cmap.size()); + std::copy(cmap.begin(), cmap.end(), cmap_f.begin()); + add_colormap(cmap_f, scale); +} + +void PointCloudBuffer::add_colormap(const float* data, int stride, int num_points, float scale) { + if (std::abs(scale - 1.0f) > 1e-6f) { + const int step = stride / sizeof(float); + std::vector scaled(num_points); + for (int i = 0; i < num_points; i++) { + scaled[i] = scale * data[step * i]; + } + add_buffer("cmap", 1, scaled.data(), sizeof(float), num_points); + } else { + add_buffer("cmap", 1, data, stride, num_points); + } + + set_colormap_buffer("cmap"); +} + +void PointCloudBuffer::add_buffer(const std::string& attribute_name, const std::vector& data) { + add_buffer(attribute_name, 1, data.data(), sizeof(float), data.size()); +} + +void PointCloudBuffer::add_buffer(const std::string& attribute_name, const std::vector& data) { + std::vector data_f(data.size()); + std::copy(data.begin(), data.end(), data_f.begin()); + add_buffer(attribute_name, 1, data_f.data(), sizeof(float), data_f.size()); +} + void PointCloudBuffer::add_buffer(const std::string& attribute_name, int dim, const float* data, int stride, int num_points) { assert(this->num_points == num_points); @@ -286,7 +332,18 @@ void PointCloudBuffer::bind(glk::GLSLShader& shader) const { glBindBuffer(GL_ARRAY_BUFFER, vbo); glVertexAttribPointer(position_loc, 3, GL_FLOAT, GL_FALSE, stride, 0); + if (cmap_bo) { + GLint cmap_loc = shader.attrib("vert_cmap"); + glEnableVertexAttribArray(cmap_loc); + glBindBuffer(GL_ARRAY_BUFFER, cmap_bo); + glVertexAttribPointer(cmap_loc, 1, GL_FLOAT, GL_FALSE, sizeof(float), 0); + } + for (const auto& aux : aux_buffers) { + if (aux.buffer == cmap_bo) { + continue; + } + GLint attrib_loc = shader.attrib(aux.attribute_name); glEnableVertexAttribArray(attrib_loc); glBindBuffer(GL_ARRAY_BUFFER, aux.buffer); @@ -303,8 +360,14 @@ void PointCloudBuffer::unbind(glk::GLSLShader& shader) const { glBindBuffer(GL_ARRAY_BUFFER, 0); glDisableVertexAttribArray(position_loc); for (const auto& aux : aux_buffers) { + if (aux.buffer == cmap_bo) { + continue; + } glDisableVertexAttribArray(shader.attrib(aux.attribute_name)); } + if (cmap_bo) { + glDisableVertexAttribArray(shader.attrib("vert_cmap")); + } } void PointCloudBuffer::draw(glk::GLSLShader& shader) const { diff --git a/src/glk/splatting.cpp b/src/glk/splatting.cpp index b87a93b4..e21c04c8 100644 --- a/src/glk/splatting.cpp +++ b/src/glk/splatting.cpp @@ -83,6 +83,7 @@ void Splatting::draw(glk::GLSLShader& shader_) const { shader->set_uniform("color_mode", shader_.get_uniform_cache("color_mode")); shader->set_uniform("z_range", shader_.get_uniform_cache("z_range")); + shader->set_uniform("cmap_range", shader_.get_uniform_cache("cmap_range")); shader->set_uniform("colormap_axis", shader_.get_uniform_cache("colormap_axis")); shader->set_uniform("model_matrix", shader_.get_uniform_cache("model_matrix")); diff --git a/src/glk/thin_lines.cpp b/src/glk/thin_lines.cpp index ee1f091b..ba280eaf 100644 --- a/src/glk/thin_lines.cpp +++ b/src/glk/thin_lines.cpp @@ -11,12 +11,16 @@ ThinLines::ThinLines(const float* vertices, int num_vertices, bool line_strip) : ThinLines::ThinLines(const float* vertices, const float* colors, int num_vertices, bool line_strip) : ThinLines(vertices, colors, num_vertices, nullptr, 0, line_strip) {} -ThinLines::ThinLines(const float* vertices, const float* colors, int num_vertices, const unsigned int* indices, int num_indices, bool line_strip) : line_width(1.0f) { +ThinLines::ThinLines(const float* vertices, const float* colors, int num_vertices, const unsigned int* indices, int num_indices, bool line_strip) +: ThinLines(vertices, nullptr, colors, num_vertices, indices, num_indices, line_strip) {} + +ThinLines::ThinLines(const float* vertices, const float* colors, const float* cmap, int num_vertices, const unsigned int* indices, int num_indices, bool line_strip) +: line_width(1.0f) { this->num_vertices = num_vertices; this->num_indices = num_indices; this->mode = line_strip ? GL_LINE_STRIP : GL_LINES; - vao = vbo = cbo = ebo = 0; + vao = vbo = cbo = cmbo = ebo = 0; glGenVertexArrays(1, &vao); glBindVertexArray(vao); @@ -33,6 +37,13 @@ ThinLines::ThinLines(const float* vertices, const float* colors, int num_vertice write_buffer_async(GL_ARRAY_BUFFER, sizeof(float) * 4 * num_vertices, colors); } + if (cmap) { + glGenBuffers(1, &cmbo); + glBindBuffer(GL_ARRAY_BUFFER, cmbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(float) * num_vertices, nullptr, GL_STATIC_DRAW); + write_buffer_async(GL_ARRAY_BUFFER, sizeof(float) * num_vertices, cmap); + } + if (indices) { glGenBuffers(1, &ebo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); @@ -53,10 +64,25 @@ ThinLines::ThinLines(const Eigen::Vector3f* vertices, const Eigen::Vector4f* col ThinLines::ThinLines(const Eigen::Vector3f* vertices, const Eigen::Vector4f* colors, int num_vertices, const unsigned int* indices, int num_indices, bool line_strip) : ThinLines(vertices->data(), colors ? colors->data() : nullptr, num_vertices, indices, num_indices, line_strip) {} +ThinLines::ThinLines(const Eigen::Vector3f* vertices, const float* cmap, int num_vertices, bool line_strip) +: ThinLines(vertices->data(), nullptr, cmap, num_vertices, nullptr, 0, line_strip) {} + +ThinLines::ThinLines(const Eigen::Vector3f* vertices, const float* cmap, int num_vertices, const unsigned int* indices, int num_indices, bool line_strip) +: ThinLines(vertices->data(), nullptr, cmap, num_vertices, indices, num_indices, line_strip) {} + +ThinLines::ThinLines(const Eigen::Vector3f* vertices, const double* cmap, int num_vertices, bool line_strip) +: ThinLines(vertices->data(), nullptr, convert_scalars(cmap, num_vertices).data(), num_vertices, nullptr, 0, line_strip) {} + +ThinLines::ThinLines(const Eigen::Vector3f* vertices, const double* cmap, int num_vertices, const unsigned int* indices, int num_indices, bool line_strip) +: ThinLines(vertices->data(), nullptr, convert_scalars(cmap, num_vertices).data(), num_vertices, indices, num_indices, line_strip) {} + ThinLines::~ThinLines() { if (cbo) { glDeleteBuffers(1, &cbo); } + if (cmbo) { + glDeleteBuffers(1, &cmbo); + } if (ebo) { glDeleteBuffers(1, &ebo); } @@ -68,6 +94,7 @@ ThinLines::~ThinLines() { void ThinLines::draw(glk::GLSLShader& shader) const { GLint position_loc = shader.attrib("vert_position"); GLint color_loc = shader.attrib("vert_color"); + GLint cmap_loc = shader.attrib("vert_cmap"); glLineWidth(line_width); @@ -83,6 +110,12 @@ void ThinLines::draw(glk::GLSLShader& shader) const { glVertexAttribPointer(color_loc, 4, GL_FLOAT, GL_FALSE, 0, 0); } + if (cmbo) { + glEnableVertexAttribArray(cmap_loc); + glBindBuffer(GL_ARRAY_BUFFER, cmbo); + glVertexAttribPointer(cmap_loc, 1, GL_FLOAT, GL_FALSE, 0, 0); + } + if (!ebo) { glDrawArrays(mode, 0, num_vertices); } else { @@ -97,6 +130,10 @@ void ThinLines::draw(glk::GLSLShader& shader) const { glDisableVertexAttribArray(color_loc); } + if (cmbo) { + glDisableVertexAttribArray(cmap_loc); + } + glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); diff --git a/src/guik/gl_canvas.cpp b/src/guik/gl_canvas.cpp index a70d4497..5c115fe1 100644 --- a/src/guik/gl_canvas.cpp +++ b/src/guik/gl_canvas.cpp @@ -54,6 +54,7 @@ GLCanvas::GLCanvas(const Eigen::Vector2i& size, const std::string& shader_name, shader->set_uniform("color_mode", 0); shader->set_uniform("material_color", Eigen::Vector4f(1.0f, 1.0f, 1.0f, 1.0f)); shader->set_uniform("z_range", Eigen::Vector2f(-3.0f, 5.0f)); + shader->set_uniform("cmap_range", Eigen::Vector2f(0.0f, 1.0f)); shader->set_uniform("colormap_axis", Eigen::Vector3f(0.0f, 0.0f, 1.0f)); shader->set_uniform("colormap_sampler", 0); @@ -121,6 +122,7 @@ bool GLCanvas::load_shader(const std::string& shader_name) { shader->set_uniform("color_mode", 0); shader->set_uniform("material_color", Eigen::Vector4f(1.0f, 1.0f, 1.0f, 1.0f)); shader->set_uniform("z_range", Eigen::Vector2f(-3.0f, 5.0f)); + shader->set_uniform("cmap_range", Eigen::Vector2f(0.0f, 1.0f)); shader->set_uniform("colormap_axis", Eigen::Vector3f(0.0f, 0.0f, 1.0f)); shader->set_uniform("colormap_sampler", 0); diff --git a/src/guik/viewer/viewer_ui.cpp b/src/guik/viewer/viewer_ui.cpp index d01b0468..1e95c06e 100644 --- a/src/guik/viewer/viewer_ui.cpp +++ b/src/guik/viewer/viewer_ui.cpp @@ -103,6 +103,15 @@ class LightViewer::ViewerUI::DisplaySettingWindow { ImGui::SameLine(); ImGui::Checkbox("Auto", &auto_range); + auto cmap_range = viewer->shader_setting().get("cmap_range"); + if (!cmap_range) { + cmap_range = Eigen::Vector2f(0.0f, 1.0f); + } + + if (ImGui::DragFloatRange2("cmap_range", cmap_range->data(), cmap_range->data() + 1, 0.01f)) { + viewer->shader_setting().add("cmap_range", *cmap_range); + } + if (auto_range) { Eigen::Vector3f axis = Eigen::Vector3f::Zero(); axis[static_cast(colormap_axis)] = 1.0f; From d227bf9e969dfb925db9f8733814fc0546a9ff53 Mon Sep 17 00:00:00 2001 From: "k.koide" Date: Tue, 30 Dec 2025 01:30:31 +0900 Subject: [PATCH 06/40] move camera along z --- .../guik/camera/orbit_camera_control_xy.hpp | 6 +++++ src/guik/camera/orbit_camera_control_xy.cpp | 24 +++++++++++-------- src/guik/camera/orbit_camera_control_xz.cpp | 9 ++++--- 3 files changed, 24 insertions(+), 15 deletions(-) diff --git a/include/guik/camera/orbit_camera_control_xy.hpp b/include/guik/camera/orbit_camera_control_xy.hpp index 91a02732..df9d5dc7 100644 --- a/include/guik/camera/orbit_camera_control_xy.hpp +++ b/include/guik/camera/orbit_camera_control_xy.hpp @@ -5,6 +5,11 @@ namespace guik { +/// @brief Orbit camera control (Up vector is locked to Z axis) +/// Left button: rotate (pan/tilt) +/// Middle or Right button: XY translate +/// Middle & Right button: Z translate +/// Scroll wheel: zoom in/out class OrbitCameraControlXY : public CameraControl { public: EIGEN_MAKE_ALIGNED_OPERATOR_NEW @@ -40,6 +45,7 @@ class OrbitCameraControlXY : public CameraControl { Eigen::Vector2f drag_last_pos; bool left_button_down; + bool right_button_down; double theta; double phi; diff --git a/src/guik/camera/orbit_camera_control_xy.cpp b/src/guik/camera/orbit_camera_control_xy.cpp index 116a0c62..ac8efcea 100644 --- a/src/guik/camera/orbit_camera_control_xy.cpp +++ b/src/guik/camera/orbit_camera_control_xy.cpp @@ -20,6 +20,7 @@ OrbitCameraControlXY::OrbitCameraControlXY(double distance, double theta, double this->phi = phi; left_button_down = false; + right_button_down = false; middle_button_down = false; } @@ -34,10 +35,13 @@ void OrbitCameraControlXY::lookat(const Eigen::Vector3f& pt) { } void OrbitCameraControlXY::mouse(const Eigen::Vector2f& p, int button, bool down) { - if(button == 0) { + if (button == 0) { left_button_down = down; } - if(button == 2) { + if (button == 1) { + right_button_down = down; + } + if (button == 2) { middle_button_down = down; } drag_last_pos = p; @@ -46,14 +50,14 @@ void OrbitCameraControlXY::mouse(const Eigen::Vector2f& p, int button, bool down void OrbitCameraControlXY::drag(const Eigen::Vector2f& p, int button) { Eigen::Vector2f rel = p - drag_last_pos; - if(left_button_down) { + if (left_button_down && right_button_down) { + center.z() += rel[1] * distance * 0.001f; + } else if (left_button_down) { theta -= rel[0] * 0.01f; phi -= rel[1] * 0.01f; phi = std::min(M_PI_2 - 0.01, std::max(-M_PI_2 + 0.01, phi)); - } - - if(middle_button_down) { + } else if (middle_button_down || right_button_down) { center += Eigen::AngleAxisf(theta + M_PI_2, Eigen::Vector3f::UnitZ()) * Eigen::Vector3f(-rel[0], rel[1], 0.0f) * distance * 0.001f; } @@ -61,9 +65,9 @@ void OrbitCameraControlXY::drag(const Eigen::Vector2f& p, int button) { } void OrbitCameraControlXY::scroll(const Eigen::Vector2f& rel) { - if(rel[0] > 0) { + if (rel[0] > 0) { distance = distance * 0.8f; - } else if(rel[0] < 0) { + } else if (rel[0] < 0) { distance = distance * 1.2f; } @@ -71,9 +75,9 @@ void OrbitCameraControlXY::scroll(const Eigen::Vector2f& rel) { } void OrbitCameraControlXY::updown(double p) { - if(p > 0) { + if (p > 0) { distance = distance * 0.998f; - } else if(p < 0) { + } else if (p < 0) { distance = distance * 1.002f; } diff --git a/src/guik/camera/orbit_camera_control_xz.cpp b/src/guik/camera/orbit_camera_control_xz.cpp index 29fc6000..1fc7a11c 100644 --- a/src/guik/camera/orbit_camera_control_xz.cpp +++ b/src/guik/camera/orbit_camera_control_xz.cpp @@ -26,14 +26,14 @@ OrbitCameraControlXZ::~OrbitCameraControlXZ() {} void OrbitCameraControlXZ::drag(const Eigen::Vector2f& p, int button) { Eigen::Vector2f rel = p - drag_last_pos; - if(left_button_down) { + if (left_button_down && right_button_down) { + center.y() -= rel[1] * distance * 0.001f; + } else if (left_button_down) { theta -= rel[0] * 0.01f; phi -= rel[1] * 0.01f; phi = std::min(M_PI_2 - 0.01, std::max(-M_PI_2 + 0.01, phi)); - } - - if(middle_button_down) { + } else if (middle_button_down || right_button_down) { center += Eigen::AngleAxisf(theta + M_PI_2, -Eigen::Vector3f::UnitY()) * Eigen::Vector3f(rel[1], 0.0f, rel[0]) * distance * 0.001f; } @@ -54,7 +54,6 @@ Eigen::Matrix4f OrbitCameraControlXZ::view_matrix() const { return Eigen::Map(glm::value_ptr(mat)).eval(); } - void OrbitCameraControlXZ::load(std::istream& ist) { OrbitCameraControlXY::load(ist); } From 4a7497247f8f83dd4d4ede8eb5fb026f8d22505a Mon Sep 17 00:00:00 2001 From: "k.koide" Date: Tue, 30 Dec 2025 02:39:51 +0900 Subject: [PATCH 07/40] fix vertex color --- src/glk/thin_lines.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/glk/thin_lines.cpp b/src/glk/thin_lines.cpp index ba280eaf..483f88ae 100644 --- a/src/glk/thin_lines.cpp +++ b/src/glk/thin_lines.cpp @@ -12,7 +12,7 @@ ThinLines::ThinLines(const float* vertices, int num_vertices, bool line_strip) : ThinLines::ThinLines(const float* vertices, const float* colors, int num_vertices, bool line_strip) : ThinLines(vertices, colors, num_vertices, nullptr, 0, line_strip) {} ThinLines::ThinLines(const float* vertices, const float* colors, int num_vertices, const unsigned int* indices, int num_indices, bool line_strip) -: ThinLines(vertices, nullptr, colors, num_vertices, indices, num_indices, line_strip) {} +: ThinLines(vertices, colors, nullptr, num_vertices, indices, num_indices, line_strip) {} ThinLines::ThinLines(const float* vertices, const float* colors, const float* cmap, int num_vertices, const unsigned int* indices, int num_indices, bool line_strip) : line_width(1.0f) { From 5c479ed3125138e0ac2a5c5935930c6ee17a5d2c Mon Sep 17 00:00:00 2001 From: "k.koide" Date: Tue, 30 Dec 2025 02:40:38 +0900 Subject: [PATCH 08/40] replace shared_ptr with unique_ptr --- include/glk/make_shared.hpp | 5 ++ include/guik/viewer/shader_setting.hpp | 64 ++++++++++++++++++-------- src/guik/viewer/shader_setting.cpp | 39 +++++++++------- 3 files changed, 73 insertions(+), 35 deletions(-) diff --git a/include/glk/make_shared.hpp b/include/glk/make_shared.hpp index 7707fd58..645899b8 100644 --- a/include/glk/make_shared.hpp +++ b/include/glk/make_shared.hpp @@ -26,6 +26,11 @@ std::enable_if_t::value, std::shared_ptr> make_sh return std::make_shared(std::forward(args)...); } +template +std::unique_ptr make_unique(Args&&... args) { + return std::make_unique(std::forward(args)...); +} + } // namespace glk #endif \ No newline at end of file diff --git a/include/guik/viewer/shader_setting.hpp b/include/guik/viewer/shader_setting.hpp index 4bbd8d10..a42e69c9 100644 --- a/include/guik/viewer/shader_setting.hpp +++ b/include/guik/viewer/shader_setting.hpp @@ -39,7 +39,7 @@ struct PointShapeMode { /// @brief Generic shader parameter interface. struct ShaderParameterInterface { public: - using Ptr = std::shared_ptr; + using Ptr = std::unique_ptr; ShaderParameterInterface(const std::string& name) : name(name) {} virtual ~ShaderParameterInterface() {} @@ -60,7 +60,7 @@ struct ShaderParameter : public ShaderParameterInterface { virtual void set(glk::GLSLShader& shader) const override { shader.set_uniform(name, value); } - virtual Ptr clone() const override { return glk::make_shared>(name, value); } + virtual Ptr clone() const override { return glk::make_unique>(name, value); } public: T value; @@ -83,17 +83,22 @@ struct ShaderSetting { /// @param color_mode Color mode (ColorMode) ShaderSetting(int color_mode); + /// @brief Constructor + /// @param color_mode Color mode (ColorMode) + /// @param transform Transform matrix (Eigen::Matrix4f) + ShaderSetting(int color_mode, const Eigen::Matrix4f& transform); + /// @brief Constructor /// @param color_mode Color mode (ColorMode) /// @param transform Transform matrix (e.g., Eigen::Matrix4(f|d) or Eigen::Isometry3(f|d)) template - ShaderSetting(int color_mode, const Transform& transform) - : transparent(false), - params( - {glk::make_shared>("color_mode", color_mode), - glk::make_shared>("point_scale", 1.0f), - glk::make_shared>("model_matrix", (transform.template cast() * Eigen::Isometry3f::Identity()).matrix())}) // - {} + ShaderSetting(int color_mode, const Transform& transform) : ShaderSetting(color_mode, (transform.template cast() * Eigen::Isometry3f::Identity()).matrix()) {} + + /// @brief Copy constructor + ShaderSetting(const ShaderSetting& other); + + /// @brief Copy assignment operator + ShaderSetting& operator=(const ShaderSetting& other); /// @brief Destructor virtual ~ShaderSetting() {} @@ -107,7 +112,8 @@ struct ShaderSetting { /// @return This object template ShaderSetting& add(const std::string& name, const T& value) { - for (int i = 0; i < params.size(); i++) { + int i = 0; + for (i = 0; i < params.size() && params[i] != nullptr; i++) { if (params[i]->name == name) { auto p = dynamic_cast*>(params[i].get()); if (p) { @@ -119,7 +125,15 @@ struct ShaderSetting { } } - params.emplace_back(glk::make_shared>(name, value)); + if (i == params.size()) { + std::vector old_params = std::move(params); + params.resize(old_params.size() * 2); + for (int j = 0; j < old_params.size(); j++) { + params[j] = std::move(old_params[j]); + } + } + + params[i] = glk::make_unique>(name, value); return *this; } @@ -129,6 +143,10 @@ struct ShaderSetting { template std::optional get(const std::string& name) { for (const auto& param : params) { + if (!param) { + break; + } + if (param->name != name) { continue; } @@ -150,6 +168,10 @@ struct ShaderSetting { template std::optional get(const std::string& name) const { for (const auto& param : params) { + if (!param) { + break; + } + if (param->name != name) { continue; } @@ -171,6 +193,10 @@ struct ShaderSetting { template const T& cast(const std::string& name) const { for (const auto& param : params) { + if (!param) { + break; + } + if (param->name != name) { continue; } @@ -382,33 +408,33 @@ struct Rainbow : public ShaderSetting { struct FlatColor : public ShaderSetting { public: explicit FlatColor(float r, float g, float b, float a = 1.0f) : ShaderSetting(ColorMode::FLAT_COLOR) { - params.push_back(glk::make_shared>("material_color", Eigen::Vector4f(r, g, b, a))); + add("material_color", Eigen::Vector4f(r, g, b, a)); transparent = a < 0.999f; } explicit FlatColor(const Eigen::Vector4f& color) : ShaderSetting(ColorMode::FLAT_COLOR) { - params.push_back(glk::make_shared>("material_color", color)); + add("material_color", color); transparent = color.w() < 0.999f; } template explicit FlatColor(const Eigen::Vector4f& color, const Transform& transform) : ShaderSetting(ColorMode::FLAT_COLOR, (transform.template cast() * Eigen::Isometry3f::Identity()).matrix()) { - params.push_back(glk::make_shared>("material_color", color)); + add("material_color", color); transparent = color.w() < 0.999f; } template explicit FlatColor(const Color& color) : ShaderSetting(ColorMode::FLAT_COLOR) { const Eigen::Vector4f c = color.eval().template cast(); - params.push_back(glk::make_shared>("material_color", c)); + add("material_color", c); transparent = color.w() < 0.999f; } template explicit FlatColor(float r, float g, float b, float a, const Transform& transform) : ShaderSetting(ColorMode::FLAT_COLOR, (transform.template cast() * Eigen::Isometry3f::Identity()).matrix()) { - params.push_back(glk::make_shared>("material_color", Eigen::Vector4f(r, g, b, a))); + add("material_color", Eigen::Vector4f(r, g, b, a)); transparent = a < 0.999f; } @@ -416,7 +442,7 @@ struct FlatColor : public ShaderSetting { explicit FlatColor(const Color& color, const Transform& transform) : ShaderSetting(ColorMode::FLAT_COLOR, (transform.template cast() * Eigen::Isometry3f::Identity()).matrix()) { const Eigen::Vector4f c = color.eval().template cast(); - params.push_back(glk::make_shared>("material_color", c)); + add("material_color", c); transparent = color.w() < 0.999f; } @@ -424,7 +450,7 @@ struct FlatColor : public ShaderSetting { explicit FlatColor(std::initializer_list i) : ShaderSetting(ColorMode::FLAT_COLOR) { Eigen::Vector4f color = Eigen::Vector4f::Zero(); std::copy(i.begin(), i.end(), color.data()); - params.push_back(glk::make_shared>("material_color", color)); + add("material_color", color); transparent = color.w() < 0.999f; } @@ -433,7 +459,7 @@ struct FlatColor : public ShaderSetting { : ShaderSetting(ColorMode::FLAT_COLOR, (transform.template cast() * Eigen::Isometry3f::Identity()).matrix()) { Eigen::Vector4f color = Eigen::Vector4f::Zero(); std::copy(i.begin(), i.end(), color.data()); - params.push_back(glk::make_shared>("material_color", color)); + add("material_color", color); transparent = color.w() < 0.999f; } diff --git a/src/guik/viewer/shader_setting.cpp b/src/guik/viewer/shader_setting.cpp index 18e3929c..d334ab39 100644 --- a/src/guik/viewer/shader_setting.cpp +++ b/src/guik/viewer/shader_setting.cpp @@ -2,27 +2,34 @@ namespace guik { -ShaderSetting::ShaderSetting() -: transparent(false), - params( - {glk::make_shared>("color_mode", ColorMode::FLAT_COLOR), - glk::make_shared>("point_scale", 1.0f), - glk::make_shared>("model_matrix", Eigen::Matrix4f::Identity())}) // -{} - -ShaderSetting::ShaderSetting(int color_mode) -: transparent(false), - params( - {glk::make_shared>("color_mode", color_mode), - glk::make_shared>("point_scale", 1.0f), - glk::make_shared>("model_matrix", Eigen::Matrix4f::Identity())}) // -{} +ShaderSetting::ShaderSetting() : ShaderSetting::ShaderSetting(ColorMode::FLAT_COLOR, Eigen::Matrix4f::Identity().eval()) {} + +ShaderSetting::ShaderSetting(int color_mode) : ShaderSetting::ShaderSetting(color_mode, Eigen::Matrix4f::Identity().eval()) {} + +ShaderSetting::ShaderSetting(int color_mode, const Eigen::Matrix4f& transform) : transparent(false), params(6) { + params[0] = glk::make_unique>("color_mode", color_mode); + params[1] = glk::make_unique>("point_scale", 1.0f); + params[2] = glk::make_unique>("model_matrix", transform); +} + +ShaderSetting::ShaderSetting(const ShaderSetting& other) : transparent(other.transparent), params(other.params.size()) { + std::transform(other.params.begin(), other.params.end(), params.begin(), [](const auto& p) { return p ? p->clone() : nullptr; }); +} + +ShaderSetting& ShaderSetting::operator=(const ShaderSetting& other) { + if (this != &other) { + transparent = other.transparent; + params.resize(other.params.size()); + std::transform(other.params.begin(), other.params.end(), params.begin(), [](const auto& p) { return p ? p->clone() : nullptr; }); + } + return *this; +} ShaderSetting ShaderSetting::clone() const { ShaderSetting cloned; cloned.transparent = transparent; cloned.params.resize(params.size()); - std::transform(params.begin(), params.end(), cloned.params.begin(), [](const auto& p) { return p->clone(); }); + std::transform(params.begin(), params.end(), cloned.params.begin(), [](const auto& p) { return p ? p->clone() : nullptr; }); return cloned; } From 2683effc4dc41fd9212194a733c46e3655c5b972 Mon Sep 17 00:00:00 2001 From: "k.koide" Date: Tue, 30 Dec 2025 07:53:08 +0900 Subject: [PATCH 09/40] rapidhash --- CMakeLists.txt | 2 + include/glk/hash.hpp | 42 + src/glk/hash.cpp | 24 + thirdparty/rapidhash/LICENSE | 19 + thirdparty/rapidhash/README.md | 2011 ++++++++++++++++++++++++++++++ thirdparty/rapidhash/rapidhash.h | 568 +++++++++ 6 files changed, 2666 insertions(+) create mode 100644 include/glk/hash.hpp create mode 100644 src/glk/hash.cpp create mode 100644 thirdparty/rapidhash/LICENSE create mode 100644 thirdparty/rapidhash/README.md create mode 100644 thirdparty/rapidhash/rapidhash.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 27dd16ef..33c2c32e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -133,6 +133,7 @@ add_library(iridescence thirdparty/imgui/backends/imgui_impl_opengl3.cpp # glk src/glk/path_std.cpp + src/glk/hash.cpp src/glk/mesh.cpp src/glk/mesh_model.cpp src/glk/lines.cpp @@ -206,6 +207,7 @@ target_include_directories(iridescence PUBLIC $ $ $ + $ $ ) target_link_libraries(iridescence PUBLIC diff --git a/include/glk/hash.hpp b/include/glk/hash.hpp new file mode 100644 index 00000000..365082bf --- /dev/null +++ b/include/glk/hash.hpp @@ -0,0 +1,42 @@ +#ifndef GLK_HASH_HPP +#define GLK_HASH_HPP + +#include +#include + +namespace glk { + +/// @brief RapidHash (https://github.com/Nicoshev/rapidhash) +/// @param data Pointer to the data to be hashed +/// @param size Size of the data in bytes +/// @param seed Seed value for the hash function +/// @return 64-bit hash value +std::uint64_t hash(const void* data, std::size_t size, std::uint64_t seed = 0); + +/// @brief RapidHash for std::string +inline std::uint64_t hash(const std::string& str, std::uint64_t seed = 0) { + return hash(str.data(), str.size(), seed); +} + +/// @brief RapidHash (same as hash()) +inline std::uint64_t rapidhash(const void* data, std::size_t size, std::uint64_t seed = 0) { + return hash(data, size, seed); +} + +/// @brief RapidHash for std::string +inline std::uint64_t rapidhash(const std::string& str, std::uint64_t seed = 0) { + return hash(str.data(), str.size(), seed); +} + +/// @brief FNV1hash (https://gist.github.com/ruby0x1/81308642d0325fd386237cfa3b44785c) +/// @note This is slower and worse than RapidHash. Do not use this unless you have a specific reason. +std::uint64_t fnv1hash(const void* data, std::size_t size, std::uint64_t seed = 0); + +/// @brief FNV1hash for std::string +inline std::uint64_t fnv1hash(const std::string& str, std::uint64_t seed = 0) { + return fnv1hash(str.data(), str.size(), seed); +} + +} // namespace glk + +#endif \ No newline at end of file diff --git a/src/glk/hash.cpp b/src/glk/hash.cpp new file mode 100644 index 00000000..d26f52f7 --- /dev/null +++ b/src/glk/hash.cpp @@ -0,0 +1,24 @@ +#include + +#include + +namespace glk { + +std::uint64_t hash(const void* data, std::size_t size, std::uint64_t seed) { + return rapidhash_withSeed(data, size, seed); +} + +// https://gist.github.com/ruby0x1/81308642d0325fd386237cfa3b44785c +std::uint64_t fnv1hash(const void* data, std::size_t size, std::uint64_t seed) { + constexpr uint64_t prime = 0x100000001b3; + uint64_t hash = 0xcbf29ce484222325 ^ seed; + + for (int i = 0; i < size; ++i) { + const uint8_t value = static_cast(data)[i]; + hash = (hash ^ value) * prime; + } + + return hash; +} + +} // namespace glk diff --git a/thirdparty/rapidhash/LICENSE b/thirdparty/rapidhash/LICENSE new file mode 100644 index 00000000..67fe15ff --- /dev/null +++ b/thirdparty/rapidhash/LICENSE @@ -0,0 +1,19 @@ +Copyright 2025 Nicolas De Carli + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/thirdparty/rapidhash/README.md b/thirdparty/rapidhash/README.md new file mode 100644 index 00000000..164a2a8c --- /dev/null +++ b/thirdparty/rapidhash/README.md @@ -0,0 +1,2011 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + rapidhash/README.md at master · Nicoshev/rapidhash + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ Skip to content + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + + + + + + + + +
+ + + + + + + + + + + +
+
+
+ + + + + + + + + + + + + + +
+ Open in github.dev + Open in a new github.dev tab + Open in codespace + + + + + + + + + + + + + + + + + + +

Files

Latest commit

 

History

History
108 lines (86 loc) · 6.02 KB

README.md

File metadata and controls

108 lines (86 loc) · 6.02 KB

rapidhash - Very fast, high quality, platform-independent

+

Family of three hash functions: rapidhash, rapidhashMicro and rapidhashNano

+

Used by Chromium, Folly's F14, Ninja, JuliaLang, ziglang, fb303, among others

+

Rapidhash
+General purpose hash function, amazing performance across all sizes.
+Surpasses 70GB/s on Apple's M4 cpus.
+Clang-18+ compiles it to ~185 instructions, both on x86-64 and aarch64.
+The fastest recommended hash function by SMHasher and SMHasher3.

+

RapidhashMicro
+Designed for HPC and server applications, where cache misses make a noticeable performance detriment.
+Clang-18+ compiles it to ~140 instructions without stack usage, both on x86-64 and aarch64.
+Faster for sizes up to 512 bytes, just 15%-20% slower for inputs above 1kb.
+Produces same output as Rapidhash for inputs up to 80 bytes.

+

RapidhashNano
+Designed for Mobile and embedded applications, where keeping a small code size is a top priority.
+Clang-18+ compiles it to less than 100 instructions without stack usage, both on x86-64 and aarch64.
+The fastest for sizes up to 48 bytes, but may be considerably slower for larger inputs.
+Produces same output as Rapidhash for inputs up to 48 bytes.

+

Streamable
+The three functions can be computed without knowing the input length upfront.

+

Universal
+All functions have been optimized for both AMD64 and AArch64 systems.
+Compatible with gcc, clang, icx and MSVC.
+They do not use machine-specific vectorized or cryptographic instruction sets.

+

Excellent
+All functions pass all tests in both SMHasher and SMHasher3.
+Collision-based study showed a collision probability close to ideal.
+Outstanding collision ratio when tested with datasets of 16B and 67B keys:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Input LenNb HashesExpectedNb Collisions
1215 Gi7.06
1615 Gi7.07
2415 Gi7.07
3215 Gi7.010
4015 Gi7.04
4815 Gi7.07
6415 Gi7.06
8015 Gi7.011
9615 Gi7.06
12015 Gi7.08
12815 Gi7.06
1262 Gi120.1122
1662 Gi120.197
2462 Gi120.1125
3262 Gi120.1131
4062 Gi120.1117
4862 Gi120.1146
6462 Gi120.1162
8062 Gi120.1165
9662 Gi120.1180
12062 Gi120.1168
+

More results can be found in the collisions folder

+

Outstanding performance

+

Average latency when hashing keys of 4, 8 and 16 bytes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
HashM1 ProM3 ProNeoverse V2AMD TurinRyzen 9700X
rapidhash1.79ns1.38ns2.05ns2.31ns1.46ns
xxh31.92ns1.50ns2.15ns2.35ns1.45ns
+

Peak throughput when hashing files of 16Kb-2Mb

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
HashM1 ProM3 ProM3 UltraM4Neoverse V2Ryzen 9700X
rapidhash47GB/s57GB/s61GB/s71GB/s38GB/s68GB/s
xxh337GB/s43GB/s47GB/s49GB/s34GB/s78GB/s
+

Long-input measurements were taken compiling with the RAPIDHASH_UNROLLED macro.

+

The benchmarking program can be found in the bench folder

+

Collision-based hash quality study

+

A perfect hash function distributes its domain uniformly onto the image.
+When the domain's cardinality is a multiple of the image's cardinality, each potential output has the same probability of being produced.
+A function producing 64-bit hashes should have a $p=1/2^{64}$ of generating each output.

+

If we compute $n$ hashes, the expected amount of collisions should be the number of unique input pairs times the probability of producing a given hash.
+This should be $(n*(n-1))/2 * 1/2^{64}$, or simplified: $(n*(n-1))/2^{65}$.
+In the case of hashing $15*2^{30}$ (~16.1B) different keys, we should expect to see $7.03$ collisions.

+

We present an experiment in which we use rapidhash to hash $68$ datasets of $15*2^{30}$ (15Gi) keys each.
+For each dataset, the amount of collisions produced is recorded as measurement.
+Ideally, the average among measurements should be $7.03$ and the results collection should be a binomial distribution.
+We obtained a mean value of $7.60$, just $8.11$% over $7.03$.
+Each dataset individual result and the collisions test program can be found in the collisions folder.
+The default seed $0$ was used in all experiments.

+

Ports

+

Java by hash4j
+Rust by hoxxep
+JavaScript by komiya-atsushi

+

Symbols

Find definitions and references for functions and other symbols in this file by clicking a symbol below or in the code.
  • h1
    rapidhash - Very fast, high quality, platform-independent
  • h2
    Outstanding performance
  • h2
    Collision-based hash quality study
  • h2
    Ports
+
+ + + + +
+ +
+ +
+
+ +
+ +
+

Footer

+ + + + +
+
+ + + + + © 2025 GitHub, Inc. + +
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + diff --git a/thirdparty/rapidhash/rapidhash.h b/thirdparty/rapidhash/rapidhash.h new file mode 100644 index 00000000..338d2269 --- /dev/null +++ b/thirdparty/rapidhash/rapidhash.h @@ -0,0 +1,568 @@ +/* + * rapidhash V3 - Very fast, high quality, platform-independent hashing algorithm. + * + * Based on 'wyhash', by Wang Yi + * + * Copyright (C) 2025 Nicolas De Carli + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * You can contact the author at: + * - rapidhash source repository: https://github.com/Nicoshev/rapidhash + */ + + #pragma once + +/* + * Includes. + */ + #include + #include + #if defined(_MSC_VER) + # include + # if defined(_M_X64) && !defined(_M_ARM64EC) + # pragma intrinsic(_umul128) + # endif + #endif + + /* + * C/C++ macros. + */ + + #ifdef _MSC_VER + # define RAPIDHASH_ALWAYS_INLINE __forceinline + #elif defined(__GNUC__) + # define RAPIDHASH_ALWAYS_INLINE inline __attribute__((__always_inline__)) + #else + # define RAPIDHASH_ALWAYS_INLINE inline + #endif + + #ifdef __cplusplus + # define RAPIDHASH_NOEXCEPT noexcept + # define RAPIDHASH_CONSTEXPR constexpr + # ifndef RAPIDHASH_INLINE + # define RAPIDHASH_INLINE RAPIDHASH_ALWAYS_INLINE + # endif + # if __cplusplus >= 201402L && !defined(_MSC_VER) + # define RAPIDHASH_INLINE_CONSTEXPR RAPIDHASH_ALWAYS_INLINE constexpr + # else + # define RAPIDHASH_INLINE_CONSTEXPR RAPIDHASH_ALWAYS_INLINE + # endif + #else + # define RAPIDHASH_NOEXCEPT + # define RAPIDHASH_CONSTEXPR static const + # ifndef RAPIDHASH_INLINE + # define RAPIDHASH_INLINE static RAPIDHASH_ALWAYS_INLINE + # endif + # define RAPIDHASH_INLINE_CONSTEXPR RAPIDHASH_INLINE + #endif + + /* + * Unrolled macro. + * Improves large input speed, but increases code size and worsens small input speed. + * + * RAPIDHASH_COMPACT: Normal behavior. + * RAPIDHASH_UNROLLED: + * + */ + #ifndef RAPIDHASH_UNROLLED + # define RAPIDHASH_COMPACT + #elif defined(RAPIDHASH_COMPACT) + # error "cannot define RAPIDHASH_COMPACT and RAPIDHASH_UNROLLED simultaneously." + #endif + + /* + * Protection macro, alters behaviour of rapid_mum multiplication function. + * + * RAPIDHASH_FAST: Normal behavior, max speed. + * RAPIDHASH_PROTECTED: Extra protection against entropy loss. + */ + #ifndef RAPIDHASH_PROTECTED + # define RAPIDHASH_FAST + #elif defined(RAPIDHASH_FAST) + # error "cannot define RAPIDHASH_PROTECTED and RAPIDHASH_FAST simultaneously." + #endif + + /* + * Likely and unlikely macros. + */ + #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__) + # define _likely_(x) __builtin_expect(x,1) + # define _unlikely_(x) __builtin_expect(x,0) + #else + # define _likely_(x) (x) + # define _unlikely_(x) (x) + #endif + + /* + * Endianness macros. + */ + #ifndef RAPIDHASH_LITTLE_ENDIAN + # if defined(_WIN32) || defined(__LITTLE_ENDIAN__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) + # define RAPIDHASH_LITTLE_ENDIAN + # elif defined(__BIG_ENDIAN__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) + # define RAPIDHASH_BIG_ENDIAN + # else + # warning "could not determine endianness! Falling back to little endian." + # define RAPIDHASH_LITTLE_ENDIAN + # endif + #endif + + /* + * Default secret parameters. + */ + RAPIDHASH_CONSTEXPR uint64_t rapid_secret[8] = { + 0x2d358dccaa6c78a5ull, + 0x8bb84b93962eacc9ull, + 0x4b33a62ed433d4a3ull, + 0x4d5a2da51de1aa47ull, + 0xa0761d6478bd642full, + 0xe7037ed1a0b428dbull, + 0x90ed1765281c388cull, + 0xaaaaaaaaaaaaaaaaull}; + + /* + * 64*64 -> 128bit multiply function. + * + * @param A Address of 64-bit number. + * @param B Address of 64-bit number. + * + * Calculates 128-bit C = *A * *B. + * + * When RAPIDHASH_FAST is defined: + * Overwrites A contents with C's low 64 bits. + * Overwrites B contents with C's high 64 bits. + * + * When RAPIDHASH_PROTECTED is defined: + * Xors and overwrites A contents with C's low 64 bits. + * Xors and overwrites B contents with C's high 64 bits. + */ + RAPIDHASH_INLINE_CONSTEXPR void rapid_mum(uint64_t *A, uint64_t *B) RAPIDHASH_NOEXCEPT { + #if defined(__SIZEOF_INT128__) + __uint128_t r=*A; r*=*B; + #ifdef RAPIDHASH_PROTECTED + *A^=(uint64_t)r; *B^=(uint64_t)(r>>64); + #else + *A=(uint64_t)r; *B=(uint64_t)(r>>64); + #endif + #elif defined(_MSC_VER) && (defined(_WIN64) || defined(_M_HYBRID_CHPE_ARM64)) + #if defined(_M_X64) + #ifdef RAPIDHASH_PROTECTED + uint64_t a, b; + a=_umul128(*A,*B,&b); + *A^=a; *B^=b; + #else + *A=_umul128(*A,*B,B); + #endif + #else + #ifdef RAPIDHASH_PROTECTED + uint64_t a, b; + b = __umulh(*A, *B); + a = *A * *B; + *A^=a; *B^=b; + #else + uint64_t c = __umulh(*A, *B); + *A = *A * *B; + *B = c; + #endif + #endif + #else + uint64_t ha=*A>>32, hb=*B>>32, la=(uint32_t)*A, lb=(uint32_t)*B; + uint64_t rh=ha*hb, rm0=ha*lb, rm1=hb*la, rl=la*lb, t=rl+(rm0<<32), c=t>32)+(rm1>>32)+c; + #ifdef RAPIDHASH_PROTECTED + *A^=lo; *B^=hi; + #else + *A=lo; *B=hi; + #endif + #endif + } + + /* + * Multiply and xor mix function. + * + * @param A 64-bit number. + * @param B 64-bit number. + * + * Calculates 128-bit C = A * B. + * Returns 64-bit xor between high and low 64 bits of C. + */ + RAPIDHASH_INLINE_CONSTEXPR uint64_t rapid_mix(uint64_t A, uint64_t B) RAPIDHASH_NOEXCEPT { rapid_mum(&A,&B); return A^B; } + + /* + * Read functions. + */ + #ifdef RAPIDHASH_LITTLE_ENDIAN + RAPIDHASH_INLINE uint64_t rapid_read64(const uint8_t *p) RAPIDHASH_NOEXCEPT { uint64_t v; memcpy(&v, p, sizeof(uint64_t)); return v;} + RAPIDHASH_INLINE uint64_t rapid_read32(const uint8_t *p) RAPIDHASH_NOEXCEPT { uint32_t v; memcpy(&v, p, sizeof(uint32_t)); return v;} + #elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__) + RAPIDHASH_INLINE uint64_t rapid_read64(const uint8_t *p) RAPIDHASH_NOEXCEPT { uint64_t v; memcpy(&v, p, sizeof(uint64_t)); return __builtin_bswap64(v);} + RAPIDHASH_INLINE uint64_t rapid_read32(const uint8_t *p) RAPIDHASH_NOEXCEPT { uint32_t v; memcpy(&v, p, sizeof(uint32_t)); return __builtin_bswap32(v);} + #elif defined(_MSC_VER) + RAPIDHASH_INLINE uint64_t rapid_read64(const uint8_t *p) RAPIDHASH_NOEXCEPT { uint64_t v; memcpy(&v, p, sizeof(uint64_t)); return _byteswap_uint64(v);} + RAPIDHASH_INLINE uint64_t rapid_read32(const uint8_t *p) RAPIDHASH_NOEXCEPT { uint32_t v; memcpy(&v, p, sizeof(uint32_t)); return _byteswap_ulong(v);} + #else + RAPIDHASH_INLINE uint64_t rapid_read64(const uint8_t *p) RAPIDHASH_NOEXCEPT { + uint64_t v; memcpy(&v, p, 8); + return (((v >> 56) & 0xff)| ((v >> 40) & 0xff00)| ((v >> 24) & 0xff0000)| ((v >> 8) & 0xff000000)| ((v << 8) & 0xff00000000)| ((v << 24) & 0xff0000000000)| ((v << 40) & 0xff000000000000)| ((v << 56) & 0xff00000000000000)); + } + RAPIDHASH_INLINE uint64_t rapid_read32(const uint8_t *p) RAPIDHASH_NOEXCEPT { + uint32_t v; memcpy(&v, p, 4); + return (((v >> 24) & 0xff)| ((v >> 8) & 0xff00)| ((v << 8) & 0xff0000)| ((v << 24) & 0xff000000)); + } + #endif + + /* + * rapidhash main function. + * + * @param key Buffer to be hashed. + * @param len @key length, in bytes. + * @param seed 64-bit seed used to alter the hash result predictably. + * @param secret Triplet of 64-bit secrets used to alter hash result predictably. + * + * Returns a 64-bit hash. + */ +RAPIDHASH_INLINE_CONSTEXPR uint64_t rapidhash_internal(const void *key, size_t len, uint64_t seed, const uint64_t* secret) RAPIDHASH_NOEXCEPT { + const uint8_t *p=(const uint8_t *)key; + seed ^= rapid_mix(seed ^ secret[2], secret[1]); + uint64_t a=0, b=0; + size_t i = len; + if (_likely_(len <= 16)) { + if (len >= 4) { + seed ^= len; + if (len >= 8) { + const uint8_t* plast = p + len - 8; + a = rapid_read64(p); + b = rapid_read64(plast); + } else { + const uint8_t* plast = p + len - 4; + a = rapid_read32(p); + b = rapid_read32(plast); + } + } else if (len > 0) { + a = (((uint64_t)p[0])<<45)|p[len-1]; + b = p[len>>1]; + } else + a = b = 0; + } else { + if (len > 112) { + uint64_t see1 = seed, see2 = seed; + uint64_t see3 = seed, see4 = seed; + uint64_t see5 = seed, see6 = seed; +#ifdef RAPIDHASH_COMPACT + do { + seed = rapid_mix(rapid_read64(p) ^ secret[0], rapid_read64(p + 8) ^ seed); + see1 = rapid_mix(rapid_read64(p + 16) ^ secret[1], rapid_read64(p + 24) ^ see1); + see2 = rapid_mix(rapid_read64(p + 32) ^ secret[2], rapid_read64(p + 40) ^ see2); + see3 = rapid_mix(rapid_read64(p + 48) ^ secret[3], rapid_read64(p + 56) ^ see3); + see4 = rapid_mix(rapid_read64(p + 64) ^ secret[4], rapid_read64(p + 72) ^ see4); + see5 = rapid_mix(rapid_read64(p + 80) ^ secret[5], rapid_read64(p + 88) ^ see5); + see6 = rapid_mix(rapid_read64(p + 96) ^ secret[6], rapid_read64(p + 104) ^ see6); + p += 112; + i -= 112; + } while(i > 112); +#else + while (i > 224) { + seed = rapid_mix(rapid_read64(p) ^ secret[0], rapid_read64(p + 8) ^ seed); + see1 = rapid_mix(rapid_read64(p + 16) ^ secret[1], rapid_read64(p + 24) ^ see1); + see2 = rapid_mix(rapid_read64(p + 32) ^ secret[2], rapid_read64(p + 40) ^ see2); + see3 = rapid_mix(rapid_read64(p + 48) ^ secret[3], rapid_read64(p + 56) ^ see3); + see4 = rapid_mix(rapid_read64(p + 64) ^ secret[4], rapid_read64(p + 72) ^ see4); + see5 = rapid_mix(rapid_read64(p + 80) ^ secret[5], rapid_read64(p + 88) ^ see5); + see6 = rapid_mix(rapid_read64(p + 96) ^ secret[6], rapid_read64(p + 104) ^ see6); + seed = rapid_mix(rapid_read64(p + 112) ^ secret[0], rapid_read64(p + 120) ^ seed); + see1 = rapid_mix(rapid_read64(p + 128) ^ secret[1], rapid_read64(p + 136) ^ see1); + see2 = rapid_mix(rapid_read64(p + 144) ^ secret[2], rapid_read64(p + 152) ^ see2); + see3 = rapid_mix(rapid_read64(p + 160) ^ secret[3], rapid_read64(p + 168) ^ see3); + see4 = rapid_mix(rapid_read64(p + 176) ^ secret[4], rapid_read64(p + 184) ^ see4); + see5 = rapid_mix(rapid_read64(p + 192) ^ secret[5], rapid_read64(p + 200) ^ see5); + see6 = rapid_mix(rapid_read64(p + 208) ^ secret[6], rapid_read64(p + 216) ^ see6); + p += 224; + i -= 224; + } + if (i > 112) { + seed = rapid_mix(rapid_read64(p) ^ secret[0], rapid_read64(p + 8) ^ seed); + see1 = rapid_mix(rapid_read64(p + 16) ^ secret[1], rapid_read64(p + 24) ^ see1); + see2 = rapid_mix(rapid_read64(p + 32) ^ secret[2], rapid_read64(p + 40) ^ see2); + see3 = rapid_mix(rapid_read64(p + 48) ^ secret[3], rapid_read64(p + 56) ^ see3); + see4 = rapid_mix(rapid_read64(p + 64) ^ secret[4], rapid_read64(p + 72) ^ see4); + see5 = rapid_mix(rapid_read64(p + 80) ^ secret[5], rapid_read64(p + 88) ^ see5); + see6 = rapid_mix(rapid_read64(p + 96) ^ secret[6], rapid_read64(p + 104) ^ see6); + p += 112; + i -= 112; + } +#endif + seed ^= see1; + see2 ^= see3; + see4 ^= see5; + seed ^= see6; + see2 ^= see4; + seed ^= see2; + } + if (i > 16) { + seed = rapid_mix(rapid_read64(p) ^ secret[2], rapid_read64(p + 8) ^ seed); + if (i > 32) { + seed = rapid_mix(rapid_read64(p + 16) ^ secret[2], rapid_read64(p + 24) ^ seed); + if (i > 48) { + seed = rapid_mix(rapid_read64(p + 32) ^ secret[1], rapid_read64(p + 40) ^ seed); + if (i > 64) { + seed = rapid_mix(rapid_read64(p + 48) ^ secret[1], rapid_read64(p + 56) ^ seed); + if (i > 80) { + seed = rapid_mix(rapid_read64(p + 64) ^ secret[2], rapid_read64(p + 72) ^ seed); + if (i > 96) { + seed = rapid_mix(rapid_read64(p + 80) ^ secret[1], rapid_read64(p + 88) ^ seed); + } + } + } + } + } + } + a=rapid_read64(p+i-16) ^ i; b=rapid_read64(p+i-8); + } + a ^= secret[1]; + b ^= seed; + rapid_mum(&a, &b); + return rapid_mix(a ^ secret[7], b ^ secret[1] ^ i); +} + + /* + * rapidhashMicro main function. + * + * @param key Buffer to be hashed. + * @param len @key length, in bytes. + * @param seed 64-bit seed used to alter the hash result predictably. + * @param secret Triplet of 64-bit secrets used to alter hash result predictably. + * + * Returns a 64-bit hash. + */ + RAPIDHASH_INLINE_CONSTEXPR uint64_t rapidhashMicro_internal(const void *key, size_t len, uint64_t seed, const uint64_t* secret) RAPIDHASH_NOEXCEPT { + const uint8_t *p=(const uint8_t *)key; + seed ^= rapid_mix(seed ^ secret[2], secret[1]); + uint64_t a=0, b=0; + size_t i = len; + if (_likely_(len <= 16)) { + if (len >= 4) { + seed ^= len; + if (len >= 8) { + const uint8_t* plast = p + len - 8; + a = rapid_read64(p); + b = rapid_read64(plast); + } else { + const uint8_t* plast = p + len - 4; + a = rapid_read32(p); + b = rapid_read32(plast); + } + } else if (len > 0) { + a = (((uint64_t)p[0])<<45)|p[len-1]; + b = p[len>>1]; + } else + a = b = 0; + } else { + if (i > 80) { + uint64_t see1 = seed, see2 = seed; + uint64_t see3 = seed, see4 = seed; + do { + seed = rapid_mix(rapid_read64(p) ^ secret[0], rapid_read64(p + 8) ^ seed); + see1 = rapid_mix(rapid_read64(p + 16) ^ secret[1], rapid_read64(p + 24) ^ see1); + see2 = rapid_mix(rapid_read64(p + 32) ^ secret[2], rapid_read64(p + 40) ^ see2); + see3 = rapid_mix(rapid_read64(p + 48) ^ secret[3], rapid_read64(p + 56) ^ see3); + see4 = rapid_mix(rapid_read64(p + 64) ^ secret[4], rapid_read64(p + 72) ^ see4); + p += 80; + i -= 80; + } while(i > 80); + seed ^= see1; + see2 ^= see3; + seed ^= see4; + seed ^= see2; + } + if (i > 16) { + seed = rapid_mix(rapid_read64(p) ^ secret[2], rapid_read64(p + 8) ^ seed); + if (i > 32) { + seed = rapid_mix(rapid_read64(p + 16) ^ secret[2], rapid_read64(p + 24) ^ seed); + if (i > 48) { + seed = rapid_mix(rapid_read64(p + 32) ^ secret[1], rapid_read64(p + 40) ^ seed); + if (i > 64) { + seed = rapid_mix(rapid_read64(p + 48) ^ secret[1], rapid_read64(p + 56) ^ seed); + } + } + } + } + a=rapid_read64(p+i-16) ^ i; b=rapid_read64(p+i-8); + } + a ^= secret[1]; + b ^= seed; + rapid_mum(&a, &b); + return rapid_mix(a ^ secret[7], b ^ secret[1] ^ i); + } + + /* + * rapidhashNano main function. + * + * @param key Buffer to be hashed. + * @param len @key length, in bytes. + * @param seed 64-bit seed used to alter the hash result predictably. + * @param secret Triplet of 64-bit secrets used to alter hash result predictably. + * + * Returns a 64-bit hash. + */ + RAPIDHASH_INLINE_CONSTEXPR uint64_t rapidhashNano_internal(const void *key, size_t len, uint64_t seed, const uint64_t* secret) RAPIDHASH_NOEXCEPT { + const uint8_t *p=(const uint8_t *)key; + seed ^= rapid_mix(seed ^ secret[2], secret[1]); + uint64_t a=0, b=0; + size_t i = len; + if (_likely_(len <= 16)) { + if (len >= 4) { + seed ^= len; + if (len >= 8) { + const uint8_t* plast = p + len - 8; + a = rapid_read64(p); + b = rapid_read64(plast); + } else { + const uint8_t* plast = p + len - 4; + a = rapid_read32(p); + b = rapid_read32(plast); + } + } else if (len > 0) { + a = (((uint64_t)p[0])<<45)|p[len-1]; + b = p[len>>1]; + } else + a = b = 0; + } else { + if (i > 48) { + uint64_t see1 = seed, see2 = seed; + do { + seed = rapid_mix(rapid_read64(p) ^ secret[0], rapid_read64(p + 8) ^ seed); + see1 = rapid_mix(rapid_read64(p + 16) ^ secret[1], rapid_read64(p + 24) ^ see1); + see2 = rapid_mix(rapid_read64(p + 32) ^ secret[2], rapid_read64(p + 40) ^ see2); + p += 48; + i -= 48; + } while(i > 48); + seed ^= see1; + seed ^= see2; + } + if (i > 16) { + seed = rapid_mix(rapid_read64(p) ^ secret[2], rapid_read64(p + 8) ^ seed); + if (i > 32) { + seed = rapid_mix(rapid_read64(p + 16) ^ secret[2], rapid_read64(p + 24) ^ seed); + } + } + a=rapid_read64(p+i-16) ^ i; b=rapid_read64(p+i-8); + } + a ^= secret[1]; + b ^= seed; + rapid_mum(&a, &b); + return rapid_mix(a ^ secret[7], b ^ secret[1] ^ i); + } + +/* + * rapidhash seeded hash function. + * + * @param key Buffer to be hashed. + * @param len @key length, in bytes. + * @param seed 64-bit seed used to alter the hash result predictably. + * + * Calls rapidhash_internal using provided parameters and default secrets. + * + * Returns a 64-bit hash. + */ +RAPIDHASH_INLINE_CONSTEXPR uint64_t rapidhash_withSeed(const void *key, size_t len, uint64_t seed) RAPIDHASH_NOEXCEPT { + return rapidhash_internal(key, len, seed, rapid_secret); +} + +/* + * rapidhash general purpose hash function. + * + * @param key Buffer to be hashed. + * @param len @key length, in bytes. + * + * Calls rapidhash_withSeed using provided parameters and the default seed. + * + * Returns a 64-bit hash. + */ +RAPIDHASH_INLINE_CONSTEXPR uint64_t rapidhash(const void *key, size_t len) RAPIDHASH_NOEXCEPT { + return rapidhash_withSeed(key, len, 0); +} + +/* + * rapidhashMicro seeded hash function. + * + * Designed for HPC and server applications, where cache misses make a noticeable performance detriment. + * Clang-18+ compiles it to ~140 instructions without stack usage, both on x86-64 and aarch64. + * Faster for sizes up to 512 bytes, just 15%-20% slower for inputs above 1kb. + * + * @param key Buffer to be hashed. + * @param len @key length, in bytes. + * @param seed 64-bit seed used to alter the hash result predictably. + * + * Calls rapidhash_internal using provided parameters and default secrets. + * + * Returns a 64-bit hash. + */ + RAPIDHASH_INLINE_CONSTEXPR uint64_t rapidhashMicro_withSeed(const void *key, size_t len, uint64_t seed) RAPIDHASH_NOEXCEPT { + return rapidhashMicro_internal(key, len, seed, rapid_secret); +} + +/* + * rapidhashMicro hash function. + * + * @param key Buffer to be hashed. + * @param len @key length, in bytes. + * + * Calls rapidhash_withSeed using provided parameters and the default seed. + * + * Returns a 64-bit hash. + */ +RAPIDHASH_INLINE_CONSTEXPR uint64_t rapidhashMicro(const void *key, size_t len) RAPIDHASH_NOEXCEPT { + return rapidhashMicro_withSeed(key, len, 0); +} + +/* + * rapidhashNano seeded hash function. + * + * @param key Buffer to be hashed. + * @param len @key length, in bytes. + * @param seed 64-bit seed used to alter the hash result predictably. + * + * Calls rapidhash_internal using provided parameters and default secrets. + * + * Returns a 64-bit hash. + */ + RAPIDHASH_INLINE_CONSTEXPR uint64_t rapidhashNano_withSeed(const void *key, size_t len, uint64_t seed) RAPIDHASH_NOEXCEPT { + return rapidhashNano_internal(key, len, seed, rapid_secret); +} + +/* + * rapidhashNano hash function. + * + * Designed for Mobile and embedded applications, where keeping a small code size is a top priority. + * Clang-18+ compiles it to less than 100 instructions without stack usage, both on x86-64 and aarch64. + * The fastest for sizes up to 48 bytes, but may be considerably slower for larger inputs. + * + * @param key Buffer to be hashed. + * @param len @key length, in bytes. + * + * Calls rapidhash_withSeed using provided parameters and the default seed. + * + * Returns a 64-bit hash. + */ +RAPIDHASH_INLINE_CONSTEXPR uint64_t rapidhashNano(const void *key, size_t len) RAPIDHASH_NOEXCEPT { + return rapidhashNano_withSeed(key, len, 0); +} From 292eaee6bf2a52c377cb3d3bbcca14785855da62 Mon Sep 17 00:00:00 2001 From: "k.koide" Date: Tue, 30 Dec 2025 09:36:48 +0900 Subject: [PATCH 10/40] replace string name with hash name in glsl_shader --- include/glk/glsl_shader.hpp | 182 +++++------ .../naive_screen_space_ambient_occlusion.cpp | 19 +- .../screen_space_attribute_estimation.cpp | 40 +-- src/glk/effects/screen_space_lighting.cpp | 53 ++-- src/glk/glsl_shader.cpp | 292 ++++++++++++++++-- src/glk/splatting.cpp | 26 +- 6 files changed, 424 insertions(+), 188 deletions(-) diff --git a/include/glk/glsl_shader.hpp b/include/glk/glsl_shader.hpp index f0cb2824..44922f28 100644 --- a/include/glk/glsl_shader.hpp +++ b/include/glk/glsl_shader.hpp @@ -12,6 +12,7 @@ #include #include +#include #include namespace glk { @@ -39,38 +40,30 @@ class GLSLShader { void use() const { glUseProgram(shader_program); } void unuse() const { glUseProgram(0); } - GLint attrib(const std::string& name); - GLint uniform(const std::string& name); + GLint attrib(std::uint64_t name) const; + GLint attrib(const std::string& name) const; + GLint uniform(std::uint64_t name) const; + GLint uniform(const std::string& name) const; + GLint subroutine(GLenum shader_type, std::uint64_t name) const; GLint subroutine(GLenum shader_type, const std::string& name); + GLint subroutine_uniform(GLenum shader_type, std::uint64_t name) const; GLint subroutine_uniform(GLenum shader_type, const std::string& name); - int get_uniformi(const std::string& name) { - int value; - glGetUniformiv(shader_program, uniform(name), &value); - return value; - } + int get_uniformi(std::uint64_t name); + int get_uniformi(const std::string& name); - float get_uniformf(const std::string& name) { - float value; - glGetUniformfv(shader_program, uniform(name), &value); - return value; - } + float get_uniformf(std::uint64_t name); + float get_uniformf(const std::string& name); - Eigen::Vector4f get_uniform4f(const std::string& name) { - Eigen::Vector4f vec; - glGetUniformfv(shader_program, uniform(name), vec.data()); - return vec; - } + Eigen::Vector4f get_uniform4f(std::uint64_t name); + Eigen::Vector4f get_uniform4f(const std::string& name); - Eigen::Matrix4f get_uniform_matrix4f(const std::string& name) { - Eigen::Matrix4f mat; - glGetUniformfv(shader_program, uniform(name), mat.data()); - return mat; - } + Eigen::Matrix4f get_uniform_matrix4f(std::uint64_t name); + Eigen::Matrix4f get_uniform_matrix4f(const std::string& name); template - T get_uniform_cache(const std::string& name) const { - const auto found = uniform_variable_cache.find(name); + T get_uniform_cache(std::uint64_t name) const { + const auto found = std::find_if(uniform_variable_cache.begin(), uniform_variable_cache.end(), [=](const auto& pair) { return pair.first == name; }); if (found == uniform_variable_cache.end()) { std::cerr << "warning: failed to find uniform variable cache " << name << std::endl; return T(); @@ -79,78 +72,73 @@ class GLSLShader { } template - std::optional get_uniform_cache_safe(const std::string& name) const { - const auto found = uniform_variable_cache.find(name); + std::optional get_uniform_cache_safe(std::uint64_t name) const { + const auto found = std::find_if(uniform_variable_cache.begin(), uniform_variable_cache.end(), [=](const auto& pair) { return pair.first == name; }); if (found == uniform_variable_cache.end()) { return std::nullopt; } - return *std::reinterpret_pointer_cast(found->second); } - void set_uniform(const std::string& name, int value) { - glUniform1i(uniform(name), value); - set_uniform_cache(name, value); - } - void set_uniform(const std::string& name, float value) { - glUniform1f(uniform(name), value); - set_uniform_cache(name, value); - } - void set_uniform(const std::string& name, const Eigen::Vector2f& vector) { - glUniform2fv(uniform(name), 1, vector.data()); - set_uniform_cache(name, vector); - } - void set_uniform(const std::string& name, const Eigen::Vector3f& vector) { - glUniform3fv(uniform(name), 1, vector.data()); - set_uniform_cache(name, vector); - } - void set_uniform(const std::string& name, const Eigen::Vector4f& vector) { - glUniform4fv(uniform(name), 1, vector.data()); - set_uniform_cache(name, vector); - } - void set_uniform(const std::string& name, const Eigen::Vector2i& vector) { - glUniform4iv(uniform(name), 1, vector.data()); - set_uniform_cache(name, vector); - } - void set_uniform(const std::string& name, const Eigen::Vector3i& vector) { - glUniform3iv(uniform(name), 1, vector.data()); - set_uniform_cache(name, vector); - } - void set_uniform(const std::string& name, const Eigen::Vector4i& vector) { - glUniform4iv(uniform(name), 1, vector.data()); - set_uniform_cache(name, vector); - } - void set_uniform(const std::string& name, const Eigen::Matrix4f& matrix) { - glUniformMatrix4fv(uniform(name), 1, GL_FALSE, matrix.data()); - set_uniform_cache(name, matrix); - } - void set_uniform(const std::string& name, const std::vector& vectors) { - glUniform1iv(uniform(name), vectors.size(), vectors.data()); - set_uniform_cache(name, vectors); - } - void set_uniform(const std::string& name, const std::vector& vectors) { - glUniform1fv(uniform(name), vectors.size(), vectors.data()); - set_uniform_cache(name, vectors); - } - template - void set_uniform(const std::string& name, const std::vector& vectors) { - glUniform2fv(uniform(name), vectors.size(), vectors[0].data()); - set_uniform_cache(name, vectors); - } - template - void set_uniform(const std::string& name, const std::vector& vectors) { - glUniform3fv(uniform(name), vectors.size(), vectors[0].data()); - set_uniform_cache(name, vectors); - } - template - void set_uniform(const std::string& name, const std::vector& vectors) { - glUniform4fv(uniform(name), vectors.size(), vectors[0].data()); - set_uniform_cache(name, vectors); - } - void set_uniform(const std::string& name, const Eigen::Matrix4d& matrix_) { - Eigen::Matrix4f matrix = matrix_.cast(); - glUniformMatrix4fv(uniform(name), 1, GL_FALSE, matrix.data()); - } + // int + void set_uniform(std::uint64_t name, int value); + void set_uniform(const std::string& name, int value); + + // float + void set_uniform(std::uint64_t name, float value); + void set_uniform(const std::string& name, float value); + + // vec2f + void set_uniform(std::uint64_t name, const Eigen::Vector2f& vector); + void set_uniform(const std::string& name, const Eigen::Vector2f& vector); + + // vec3f + void set_uniform(std::uint64_t name, const Eigen::Vector3f& vector); + void set_uniform(const std::string& name, const Eigen::Vector3f& vector); + + // vec4f + void set_uniform(std::uint64_t name, const Eigen::Vector4f& vector); + void set_uniform(const std::string& name, const Eigen::Vector4f& vector); + + // vec2i + void set_uniform(std::uint64_t name, const Eigen::Vector2i& vector); + void set_uniform(const std::string& name, const Eigen::Vector2i& vector); + + // vec3i + void set_uniform(std::uint64_t name, const Eigen::Vector3i& vector); + void set_uniform(const std::string& name, const Eigen::Vector3i& vector); + + // vec4i + void set_uniform(std::uint64_t name, const Eigen::Vector4i& vector); + void set_uniform(const std::string& name, const Eigen::Vector4i& vector); + + // matrix4f + void set_uniform(std::uint64_t name, const Eigen::Matrix4f& matrix); + void set_uniform(const std::string& name, const Eigen::Matrix4f& matrix); + + // array of int + void set_uniform(std::uint64_t name, const std::vector& vectors); + void set_uniform(const std::string& name, const std::vector& vectors); + + // array of float + void set_uniform(std::uint64_t name, const std::vector& vectors); + void set_uniform(const std::string& name, const std::vector& vectors); + + // array of vec2f + void set_uniform(std::uint64_t name, const Eigen::Vector2f* vectors, size_t count); + void set_uniform(const std::string& name, const Eigen::Vector2f* vectors, size_t count); + + // array of vec3f + void set_uniform(std::uint64_t name, const Eigen::Vector3f* vectors, size_t count); + void set_uniform(const std::string& name, const Eigen::Vector3f* vectors, size_t count); + + // array of vec4f + void set_uniform(std::uint64_t name, const Eigen::Vector4f* vectors, size_t count); + void set_uniform(const std::string& name, const Eigen::Vector4f* vectors, size_t count); + + // matrix4d + void set_uniform(std::uint64_t name, const Eigen::Matrix4d& matrix_); + void set_uniform(const std::string& name, const Eigen::Matrix4d& matrix_); void set_subroutine(GLenum shader_type, const std::string& loc, const std::string& func); @@ -158,12 +146,12 @@ class GLSLShader { GLuint read_shader_from_file(const std::string& filename, const std::unordered_map& include_map, const std::string& defines, GLuint shader_type); template - void set_uniform_cache(const std::string& name, const T& value) { - const auto found = uniform_variable_cache.find(name); + void set_uniform_cache(std::uint64_t h, const T& value) { + const auto found = std::find_if(uniform_variable_cache.begin(), uniform_variable_cache.end(), [&h](const auto& pair) { return pair.first == h; }); if (found != uniform_variable_cache.end()) { *reinterpret_cast(found->second.get()) = value; } else { - uniform_variable_cache.emplace_hint(found, name, glk::make_shared(value)); + uniform_variable_cache.emplace_back(h, glk::make_shared(value)); } } @@ -172,11 +160,11 @@ class GLSLShader { std::vector feedback_varyings; GLuint shader_program; - std::unordered_map attrib_cache; - std::unordered_map uniform_cache; - std::unordered_map subroutine_cache; + std::vector> attrib_cache; + std::vector> uniform_cache; - std::unordered_map> uniform_variable_cache; + std::vector> subroutine_cache; + std::vector>> uniform_variable_cache; }; } // namespace glk diff --git a/src/glk/effects/naive_screen_space_ambient_occlusion.cpp b/src/glk/effects/naive_screen_space_ambient_occlusion.cpp index badae093..8e4eb116 100644 --- a/src/glk/effects/naive_screen_space_ambient_occlusion.cpp +++ b/src/glk/effects/naive_screen_space_ambient_occlusion.cpp @@ -8,12 +8,12 @@ namespace glk { NaiveScreenSpaceAmbientOcclusion::NaiveScreenSpaceAmbientOcclusion() { - if(!ssao_shader.init(get_data_path() + "/shader/texture.vert", get_data_path() + "/shader/naive_ssao.frag")) { + if (!ssao_shader.init(get_data_path() + "/shader/texture.vert", get_data_path() + "/shader/naive_ssao.frag")) { return; } std::mt19937 mt; std::vector> random_vectors(32); - for(auto& vec : random_vectors) { + for (auto& vec : random_vectors) { double u = std::uniform_real_distribution<>(0.0, 1.0)(mt); double v = std::uniform_real_distribution<>(-1.0, 1.0)(mt); double w = std::uniform_real_distribution<>(0.0, 1.0)(mt); @@ -27,13 +27,18 @@ NaiveScreenSpaceAmbientOcclusion::NaiveScreenSpaceAmbientOcclusion() { ssao_shader.use(); ssao_shader.set_uniform("ao_radius", 0.1f); - ssao_shader.set_uniform("random_vectors", random_vectors); + ssao_shader.set_uniform("random_vectors", random_vectors.data(), random_vectors.size()); } NaiveScreenSpaceAmbientOcclusion::~NaiveScreenSpaceAmbientOcclusion() {} -void NaiveScreenSpaceAmbientOcclusion::draw(const TextureRenderer& renderer, const glk::Texture& color_texture, const glk::Texture& depth_texture, const TextureRendererInput::Ptr& input, glk::FrameBuffer* frame_buffer) { - if(frame_buffer) { +void NaiveScreenSpaceAmbientOcclusion::draw( + const TextureRenderer& renderer, + const glk::Texture& color_texture, + const glk::Texture& depth_texture, + const TextureRendererInput::Ptr& input, + glk::FrameBuffer* frame_buffer) { + if (frame_buffer) { frame_buffer->bind(); } @@ -43,7 +48,7 @@ void NaiveScreenSpaceAmbientOcclusion::draw(const TextureRenderer& renderer, con auto view_matrix = input->get("view_matrix"); auto projection_matrix = input->get("projection_matrix"); - if(!view_matrix || !projection_matrix) { + if (!view_matrix || !projection_matrix) { using namespace glk::console; std::cerr << bold_red << "error: view and projection matrices must be set" << reset << std::endl; return; @@ -60,7 +65,7 @@ void NaiveScreenSpaceAmbientOcclusion::draw(const TextureRenderer& renderer, con renderer.draw_plain(ssao_shader); - if(frame_buffer) { + if (frame_buffer) { frame_buffer->unbind(); } } diff --git a/src/glk/effects/screen_space_attribute_estimation.cpp b/src/glk/effects/screen_space_attribute_estimation.cpp index 6727d175..57021448 100644 --- a/src/glk/effects/screen_space_attribute_estimation.cpp +++ b/src/glk/effects/screen_space_attribute_estimation.cpp @@ -10,23 +10,23 @@ namespace glk { ScreenSpaceAttributeEstimation::ScreenSpaceAttributeEstimation(const Eigen::Vector2i& size, BufferType rendering_type) { - if(!texture_shader.init(get_data_path() + "/shader/texture.vert", get_data_path() + "/shader/texture.frag")) { + if (!texture_shader.init(get_data_path() + "/shader/texture.vert", get_data_path() + "/shader/texture.frag")) { return; } - if(!pos_shader.init(get_data_path() + "/shader/texture.vert", get_data_path() + "/shader/ssae_pos.frag")) { + if (!pos_shader.init(get_data_path() + "/shader/texture.vert", get_data_path() + "/shader/ssae_pos.frag")) { return; } - if(!normal_shader.init(get_data_path() + "/shader/texture.vert", get_data_path() + "/shader/ssae_normal.frag")) { + if (!normal_shader.init(get_data_path() + "/shader/texture.vert", get_data_path() + "/shader/ssae_normal.frag")) { return; } - if(!occlusion_shader.init(get_data_path() + "/shader/texture.vert", get_data_path() + "/shader/ssae_ao.frag")) { + if (!occlusion_shader.init(get_data_path() + "/shader/texture.vert", get_data_path() + "/shader/ssae_ao.frag")) { return; } - if(!bilateral_shader.init(get_data_path() + "/shader/texture.vert", get_data_path() + "/shader/bilateral.frag")) { + if (!bilateral_shader.init(get_data_path() + "/shader/texture.vert", get_data_path() + "/shader/bilateral.frag")) { return; } @@ -51,12 +51,12 @@ ScreenSpaceAttributeEstimation::ScreenSpaceAttributeEstimation(const Eigen::Vect }; std::vector> random_vectors(16); - for(auto& vec : random_vectors) { + for (auto& vec : random_vectors) { vec = sample_random_vector(); } std::vector> randomization(128 * 128); - for(auto& vec : randomization) { + for (auto& vec : randomization) { vec = sample_random_vector().normalized(); } randomization_texture.reset(new glk::Texture(Eigen::Vector2i(128, 128), GL_RGB32F, GL_RGB, GL_FLOAT, randomization.data())); @@ -81,7 +81,7 @@ ScreenSpaceAttributeEstimation::ScreenSpaceAttributeEstimation(const Eigen::Vect occlusion_shader.set_uniform("normal_sampler", 2); occlusion_shader.set_uniform("randomization_sampler", 3); occlusion_shader.set_uniform("ao_radius", 0.05f); - occlusion_shader.set_uniform("random_vectors", random_vectors); + occlusion_shader.set_uniform("random_vectors", random_vectors.data(), random_vectors.size()); bilateral_shader.use(); bilateral_shader.set_uniform("color_sampler", 0); @@ -136,7 +136,12 @@ const glk::Texture& ScreenSpaceAttributeEstimation::occlusion() const { return bilateral_y_buffer->color(0); } -void ScreenSpaceAttributeEstimation::draw(const TextureRenderer& renderer, const glk::Texture& color_texture, const glk::Texture& depth_texture, const TextureRendererInput::Ptr& input, glk::FrameBuffer* frame_buffer) { +void ScreenSpaceAttributeEstimation::draw( + const TextureRenderer& renderer, + const glk::Texture& color_texture, + const glk::Texture& depth_texture, + const TextureRendererInput::Ptr& input, + glk::FrameBuffer* frame_buffer) { using namespace glk::console; glDisable(GL_DEPTH_TEST); @@ -144,7 +149,7 @@ void ScreenSpaceAttributeEstimation::draw(const TextureRenderer& renderer, const // position auto view_matrix = input->get("view_matrix"); auto projection_matrix = input->get("projection_matrix"); - if(!view_matrix || !projection_matrix) { + if (!view_matrix || !projection_matrix) { std::cerr << bold_red << "error: view and projection matrices must be set" << reset << std::endl; return; } @@ -160,7 +165,7 @@ void ScreenSpaceAttributeEstimation::draw(const TextureRenderer& renderer, const renderer.draw_plain(pos_shader); position_buffer->unbind(); - if(smooth_normal) { + if (smooth_normal) { // apply bilateral filter to position buffer bilateral_shader.use(); bilateral_shader.set_uniform("inv_frame_size", inv_frame_size); @@ -194,7 +199,7 @@ void ScreenSpaceAttributeEstimation::draw(const TextureRenderer& renderer, const normal_buffer->bind(); depth_texture.bind(GL_TEXTURE0); - if(smooth_normal) { + if (smooth_normal) { position_smoothing_y_buffer->color().bind(GL_TEXTURE1); } else { position_buffer->color().bind(GL_TEXTURE1); @@ -202,7 +207,7 @@ void ScreenSpaceAttributeEstimation::draw(const TextureRenderer& renderer, const glActiveTexture(GL_TEXTURE2); auto normal_texture = input->get("normal_texture"); - if(normal_texture) { + if (normal_texture) { glBindTexture(GL_TEXTURE_2D, *normal_texture); } else { glBindTexture(GL_TEXTURE_2D, 0); @@ -255,8 +260,8 @@ void ScreenSpaceAttributeEstimation::draw(const TextureRenderer& renderer, const renderer.draw_plain(bilateral_shader); bilateral_y_buffer->unbind(); - if(rendering_type != BufferType::NONE) { - if(frame_buffer) { + if (rendering_type != BufferType::NONE) { + if (frame_buffer) { frame_buffer->bind(); } @@ -268,15 +273,14 @@ void ScreenSpaceAttributeEstimation::draw(const TextureRenderer& renderer, const &normal_buffer->color(), &occlusion_buffer->color(), &bilateral_x_buffer->color(), - &bilateral_y_buffer->color() - }; + &bilateral_y_buffer->color()}; const auto texture = textures[static_cast(rendering_type) - 1]; texture->bind(); texture_shader.use(); renderer.draw_plain(texture_shader); - if(frame_buffer) { + if (frame_buffer) { frame_buffer->unbind(); } } diff --git a/src/glk/effects/screen_space_lighting.cpp b/src/glk/effects/screen_space_lighting.cpp index 5de240e0..92634886 100644 --- a/src/glk/effects/screen_space_lighting.cpp +++ b/src/glk/effects/screen_space_lighting.cpp @@ -15,7 +15,7 @@ namespace glk { ScreenSpaceLighting::ScreenSpaceLighting(const Eigen::Vector2i& size, bool use_splatting) { - if(use_splatting) { + if (use_splatting) { splatting.reset(new ScreenSpaceSplatting(size)); } else { ssae.reset(new ScreenSpaceAttributeEstimation(size)); @@ -24,7 +24,7 @@ ScreenSpaceLighting::ScreenSpaceLighting(const Eigen::Vector2i& size, bool use_s int width, height; std::vector bytes; - if(!load_png(get_data_path() + "/texture/iridescence1.png", width, height, bytes)) { + if (!load_png(get_data_path() + "/texture/iridescence1.png", width, height, bytes)) { return; } iridescence_texture.reset(new glk::Texture(Eigen::Vector2i(width, height), GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, bytes.data())); @@ -34,7 +34,7 @@ ScreenSpaceLighting::ScreenSpaceLighting(const Eigen::Vector2i& size, bool use_s occlusion_model = OCCLUSION_MODEL::AMBIENT_OCCLUSION; iridescence_model = IRIDESCENCE_MODEL::IRIDESCENCE1; - if(!load_shader()) { + if (!load_shader()) { return; } @@ -88,7 +88,7 @@ bool ScreenSpaceLighting::load_shader() { std::vector vertex_shaders = {get_data_path() + "/shader/texture.vert"}; std::vector fragment_shaders = {get_data_path() + "/shader/ssli.frag", get_data_path() + "/shader/brdf/schlick_fresnel.frag"}; - switch(diffuse_model) { + switch (diffuse_model) { default: case DIFFUSE_MODEL::ZERO: fragment_shaders.push_back(get_data_path() + "/shader/brdf/diffuse_zero.frag"); @@ -110,7 +110,7 @@ bool ScreenSpaceLighting::load_shader() { break; } - switch(specular_model) { + switch (specular_model) { default: case SPECULAR_MODEL::ZERO: fragment_shaders.push_back(get_data_path() + "/shader/brdf/specular_zero.frag"); @@ -126,7 +126,7 @@ bool ScreenSpaceLighting::load_shader() { break; } - switch(occlusion_model) { + switch (occlusion_model) { default: case OCCLUSION_MODEL::ZERO: fragment_shaders.push_back(get_data_path() + "/shader/brdf/occlusion_zero.frag"); @@ -137,7 +137,7 @@ bool ScreenSpaceLighting::load_shader() { } std::string iridescence_texture_path; - switch(iridescence_model) { + switch (iridescence_model) { case IRIDESCENCE_MODEL::ZERO: break; case IRIDESCENCE_MODEL::IRIDESCENCE1: @@ -151,13 +151,13 @@ bool ScreenSpaceLighting::load_shader() { break; } - if(iridescence_model == IRIDESCENCE_MODEL::ZERO) { + if (iridescence_model == IRIDESCENCE_MODEL::ZERO) { fragment_shaders.push_back(get_data_path() + "/shader/brdf/iridescence_zero.frag"); } else { int width, height; std::vector bytes; - if(!load_png(iridescence_texture_path, width, height, bytes)) { + if (!load_png(iridescence_texture_path, width, height, bytes)) { return false; } fragment_shaders.push_back(get_data_path() + "/shader/brdf/iridescence.frag"); @@ -248,7 +248,7 @@ void ScreenSpaceLighting::set_light(int i, const Eigen::Vector3f& pos, const Eig void ScreenSpaceLighting::set_light(int i, const Eigen::Vector3f& pos, const Eigen::Vector4f& color, const Eigen::Vector2f& attenuation, float max_range) { light_updated = true; - while(i >= light_pos.size()) { + while (i >= light_pos.size()) { light_directional.push_back(false); light_range.push_back(1000.0f); light_attenuation.push_back(Eigen::Vector2f(0.0f, 0.0f)); @@ -266,7 +266,7 @@ void ScreenSpaceLighting::set_light(int i, const Eigen::Vector3f& pos, const Eig void ScreenSpaceLighting::set_directional_light(int i, const Eigen::Vector3f& direction, const Eigen::Vector4f& color) { light_updated = true; - while(i >= light_pos.size()) { + while (i >= light_pos.size()) { light_directional.push_back(false); light_range.push_back(1000.0f); light_attenuation.push_back(Eigen::Vector2f(0.0f, 0.0f)); @@ -281,31 +281,36 @@ void ScreenSpaceLighting::set_directional_light(int i, const Eigen::Vector3f& di } void ScreenSpaceLighting::set_size(const Eigen::Vector2i& size) { - if(splatting) { + if (splatting) { splatting->set_size(size); } - if(ssae) { + if (ssae) { ssae->set_size(size); } } -void ScreenSpaceLighting::draw(const TextureRenderer& renderer, const glk::Texture& color_texture, const glk::Texture& depth_texture, const TextureRendererInput::Ptr& input, glk::FrameBuffer* frame_buffer) { +void ScreenSpaceLighting::draw( + const TextureRenderer& renderer, + const glk::Texture& color_texture, + const glk::Texture& depth_texture, + const TextureRendererInput::Ptr& input, + glk::FrameBuffer* frame_buffer) { using namespace glk::console; - if(splatting) { + if (splatting) { splatting->draw(renderer, color_texture, depth_texture, input); } - if(ssae) { + if (ssae) { ssae->draw(renderer, color_texture, depth_texture, input); } - if(frame_buffer) { + if (frame_buffer) { frame_buffer->bind(); } auto view_matrix = input->get("view_matrix"); - if(!view_matrix) { + if (!view_matrix) { std::cerr << bold_red << "error: view and projection matrices must be set" << reset << std::endl; return; } @@ -326,16 +331,16 @@ void ScreenSpaceLighting::draw(const TextureRenderer& renderer, const glk::Textu lighting_shader.set_uniform("albedo", albedo); lighting_shader.set_uniform("roughness", roughness); - if(light_updated) { + if (light_updated) { lighting_shader.set_uniform("num_lights", static_cast(light_pos.size())); lighting_shader.set_uniform("light_directional", light_directional); lighting_shader.set_uniform("light_range", light_range); - lighting_shader.set_uniform("light_attenuation", light_attenuation); - lighting_shader.set_uniform("light_pos", light_pos); - lighting_shader.set_uniform("light_color", light_color); + lighting_shader.set_uniform("light_attenuation", light_attenuation.data(), light_attenuation.size()); + lighting_shader.set_uniform("light_pos", light_pos.data(), light_pos.size()); + lighting_shader.set_uniform("light_color", light_color.data(), light_color.size()); } - if(splatting) { + if (splatting) { splatting->color().bind(GL_TEXTURE0); splatting->position().bind(GL_TEXTURE1); splatting->normal().bind(GL_TEXTURE2); @@ -366,7 +371,7 @@ void ScreenSpaceLighting::draw(const TextureRenderer& renderer, const glk::Textu }); */ - if(frame_buffer) { + if (frame_buffer) { frame_buffer->unbind(); } } diff --git a/src/glk/glsl_shader.cpp b/src/glk/glsl_shader.cpp index 09984fa5..5b1554ff 100644 --- a/src/glk/glsl_shader.cpp +++ b/src/glk/glsl_shader.cpp @@ -13,6 +13,7 @@ #include #include +#include #include namespace glk { @@ -116,6 +117,39 @@ bool GLSLShader::link_program() { return false; } + // Find attribs + glUseProgram(shader_program); + GLint num_attribs = 0; + glGetProgramiv(shader_program, GL_ACTIVE_ATTRIBUTES, &num_attribs); + for (GLint i = 0; i < num_attribs; i++) { + char name[256]; + GLsizei len = 0; + GLint size = 0; + GLenum type = 0; + glGetActiveAttrib(shader_program, i, sizeof(name), &len, &size, &type, name); + std::string name_str(name, len); + GLint location = glGetAttribLocation(shader_program, name_str.c_str()); + + attrib_cache.emplace_back(glk::hash(name_str), location); + } + + // Find uniforms + GLint num_uniforms = 0; + glGetProgramiv(shader_program, GL_ACTIVE_UNIFORMS, &num_uniforms); + for (GLint i = 0; i < num_uniforms; i++) { + char name[256]; + GLsizei len = 0; + GLint size = 0; + GLenum type = 0; + glGetActiveUniform(shader_program, i, sizeof(name), &len, &size, &type, name); + std::string name_str(name, len); + GLint location = glGetUniformLocation(shader_program, name_str.c_str()); + + uniform_cache.emplace_back(glk::hash(name_str), location); + } + + glUseProgram(0); + return true; } @@ -135,63 +169,79 @@ bool GLSLShader::init(const std::vector& vertex_shader_paths, const return link_program(); } -GLint GLSLShader::attrib(const std::string& name) { - auto found = attrib_cache.find(name); +GLint GLSLShader::attrib(std::uint64_t name) const { + auto found = std::find_if(attrib_cache.begin(), attrib_cache.end(), [&name](const auto& pair) { return pair.first == name; }); if (found != attrib_cache.end()) { return found->second; + } else { + return -1; } +} - GLint id = glGetAttribLocation(shader_program, name.c_str()); - if (id == -1) { - std::cerr << bold_yellow << "warning : attrib " << name << " not found" << reset << std::endl; - } - - attrib_cache[name] = id; - return id; +GLint GLSLShader::attrib(const std::string& name) const { + return attrib(glk::hash(name)); } -GLint GLSLShader::uniform(const std::string& name) { - auto found = uniform_cache.find(name); +GLint GLSLShader::uniform(std::uint64_t name) const { + auto found = std::find_if(uniform_cache.begin(), uniform_cache.end(), [&name](const auto& pair) { return pair.first == name; }); if (found != uniform_cache.end()) { return found->second; + } else { + return -1; } +} - GLint id = glGetUniformLocation(shader_program, name.c_str()); - if (id == -1) { - // std::cerr << bold_yellow << "warning : uniform " << name << " not found" << reset << std::endl; - } - - uniform_cache[name] = id; - return id; +GLint GLSLShader::uniform(const std::string& name) const { + return uniform(glk::hash(name)); } -GLint GLSLShader::subroutine(GLenum shader_type, const std::string& name) { - auto found = subroutine_cache.find(name); +GLint GLSLShader::subroutine(GLenum shader_type, std::uint64_t name) const { + auto found = std::find_if(subroutine_cache.begin(), subroutine_cache.end(), [&name](const auto& pair) { return pair.first == name; }); if (found != subroutine_cache.end()) { return found->second; + } else { + return -1; + } +} + +GLint GLSLShader::subroutine(GLenum shader_type, const std::string& name) { + const std::uint64_t h = glk::hash(name); + GLint id = subroutine(shader_type, h); + if (id >= -1) { + return id; } - GLint id = glGetSubroutineIndex(shader_program, shader_type, name.c_str()); + id = glGetSubroutineIndex(shader_program, shader_type, name.c_str()); if (id == -1) { std::cerr << bold_yellow << "warning : subroutine " << name << " not found" << reset << std::endl; } - subroutine_cache[name] = id; + subroutine_cache.emplace_back(h, id); return id; } -GLint GLSLShader::subroutine_uniform(GLenum shader_type, const std::string& name) { - auto found = uniform_cache.find(name); +GLint GLSLShader::subroutine_uniform(GLenum shader_type, std::uint64_t name) const { + auto found = std::find_if(uniform_cache.begin(), uniform_cache.end(), [&name](const auto& pair) { return pair.first == name; }); if (found != uniform_cache.end()) { return found->second; + } else { + return -1; + } +} + +GLint GLSLShader::subroutine_uniform(GLenum shader_type, const std::string& name) { + const std::uint64_t h = glk::hash(name); + GLint id = subroutine_uniform(shader_type, h); + if (id >= -1) { + return id; } - GLint id = glGetSubroutineUniformLocation(shader_program, shader_type, name.c_str()); + id = glGetSubroutineUniformLocation(shader_program, shader_type, name.c_str()); if (id == -1) { std::cerr << bold_yellow << "warning : subroutine uniform " << name << " not found" << reset << std::endl; } - uniform_cache[name] = id; + uniform_cache.emplace_back(h, id); return id; } @@ -215,7 +265,8 @@ void GLSLShader::set_subroutine(GLenum shader_type, const std::string& loc, cons glUniformSubroutinesuiv(shader_type, num_subroutines, indices.data()); } -GLuint GLSLShader::read_shader_from_file(const std::string& filename, const std::unordered_map& include_map, const std::string& defines, GLuint shader_type) { +GLuint +GLSLShader::read_shader_from_file(const std::string& filename, const std::unordered_map& include_map, const std::string& defines, GLuint shader_type) { GLuint shader_id = glCreateShader(shader_type); const auto read_source = [](const std::string& filename) -> std::string { @@ -242,7 +293,7 @@ GLuint GLSLShader::read_shader_from_file(const std::string& filename, const std: const std::string include_filename = match.str(2); std::string include_source; - if(include_filename == "define") { + if (include_filename == "define") { include_source = defines; } else { const auto found = include_map.find(include_filename); @@ -306,7 +357,7 @@ GLuint GLSLShader::read_shader_from_file(const std::string& filename, const std: if (std::regex_search(error_line, matched, std::regex("[0-9]+\\(([0-9]+)\\) : (error|warning)"))) { const int line = std::stoi(matched.str(1)) - 1; - if(line < source_lines.size()) { + if (line < source_lines.size()) { std::cout << console::cyan << " : : L" << line << "= " << source_lines[line] << console::reset << std::endl; } else { std::cout << console::cyan << " : : L" << line << "= out of source" << console::reset << std::endl; @@ -318,4 +369,187 @@ GLuint GLSLShader::read_shader_from_file(const std::string& filename, const std: return shader_id; } +int GLSLShader::get_uniformi(std::uint64_t name) { + int value; + glGetUniformiv(shader_program, uniform(name), &value); + return value; +} + +int GLSLShader::get_uniformi(const std::string& name) { + int value; + glGetUniformiv(shader_program, uniform(name), &value); + return value; +} + +float GLSLShader::get_uniformf(std::uint64_t name) { + float value; + glGetUniformfv(shader_program, uniform(name), &value); + return value; +} + +float GLSLShader::get_uniformf(const std::string& name) { + float value; + glGetUniformfv(shader_program, uniform(name), &value); + return value; +} + +Eigen::Vector4f GLSLShader::get_uniform4f(std::uint64_t name) { + Eigen::Vector4f vec; + glGetUniformfv(shader_program, uniform(name), vec.data()); + return vec; +} + +Eigen::Vector4f GLSLShader::get_uniform4f(const std::string& name) { + Eigen::Vector4f vec; + glGetUniformfv(shader_program, uniform(name), vec.data()); + return vec; +} + +Eigen::Matrix4f GLSLShader::get_uniform_matrix4f(std::uint64_t name) { + Eigen::Matrix4f mat; + glGetUniformfv(shader_program, uniform(name), mat.data()); + return mat; +} + +Eigen::Matrix4f GLSLShader::get_uniform_matrix4f(const std::string& name) { + Eigen::Matrix4f mat; + glGetUniformfv(shader_program, uniform(name), mat.data()); + return mat; +} + +void GLSLShader::set_uniform(std::uint64_t name, int value) { + glUniform1i(uniform(name), value); + set_uniform_cache(name, value); +} + +void GLSLShader::set_uniform(const std::string& name, int value) { + return set_uniform(glk::hash(name), value); +} + +void GLSLShader::set_uniform(std::uint64_t name, float value) { + glUniform1f(uniform(name), value); + set_uniform_cache(name, value); +} + +void GLSLShader::set_uniform(const std::string& name, float value) { + return set_uniform(glk::hash(name), value); +} + +void GLSLShader::set_uniform(std::uint64_t name, const Eigen::Vector2f& vector) { + glUniform2fv(uniform(name), 1, vector.data()); + set_uniform_cache(name, vector); +} + +void GLSLShader::set_uniform(const std::string& name, const Eigen::Vector2f& vector) { + return set_uniform(glk::hash(name), vector); +} + +void GLSLShader::set_uniform(std::uint64_t name, const Eigen::Vector3f& vector) { + glUniform3fv(uniform(name), 1, vector.data()); + set_uniform_cache(name, vector); +} + +void GLSLShader::set_uniform(const std::string& name, const Eigen::Vector3f& vector) { + return set_uniform(glk::hash(name), vector); +} + +void GLSLShader::set_uniform(std::uint64_t name, const Eigen::Vector4f& vector) { + glUniform4fv(uniform(name), 1, vector.data()); + set_uniform_cache(name, vector); +} + +void GLSLShader::set_uniform(const std::string& name, const Eigen::Vector4f& vector) { + return set_uniform(glk::hash(name), vector); +} + +void GLSLShader::set_uniform(std::uint64_t name, const Eigen::Vector2i& vector) { + glUniform2iv(uniform(name), 1, vector.data()); + set_uniform_cache(name, vector); +} + +void GLSLShader::set_uniform(const std::string& name, const Eigen::Vector2i& vector) { + return set_uniform(glk::hash(name), vector); +} + +void GLSLShader::set_uniform(std::uint64_t name, const Eigen::Vector3i& vector) { + glUniform3iv(uniform(name), 1, vector.data()); + set_uniform_cache(name, vector); +} + +void GLSLShader::set_uniform(const std::string& name, const Eigen::Vector3i& vector) { + return set_uniform(glk::hash(name), vector); +} + +void GLSLShader::set_uniform(std::uint64_t name, const Eigen::Vector4i& vector) { + glUniform4iv(uniform(name), 1, vector.data()); + set_uniform_cache(name, vector); +} + +void GLSLShader::set_uniform(const std::string& name, const Eigen::Vector4i& vector) { + return set_uniform(glk::hash(name), vector); +} + +void GLSLShader::set_uniform(std::uint64_t name, const Eigen::Matrix4f& matrix) { + glUniformMatrix4fv(uniform(name), 1, GL_FALSE, matrix.data()); + set_uniform_cache(name, matrix); +} + +void GLSLShader::set_uniform(const std::string& name, const Eigen::Matrix4f& matrix) { + return set_uniform(glk::hash(name), matrix); +} + +void GLSLShader::set_uniform(std::uint64_t name, const std::vector& vectors) { + glUniform1iv(uniform(name), vectors.size(), vectors.data()); + set_uniform_cache(name, vectors); +} + +void GLSLShader::set_uniform(const std::string& name, const std::vector& vectors) { + return set_uniform(glk::hash(name), vectors); +} + +void GLSLShader::set_uniform(std::uint64_t name, const std::vector& vectors) { + glUniform1fv(uniform(name), vectors.size(), vectors.data()); + set_uniform_cache(name, vectors); +} + +void GLSLShader::set_uniform(const std::string& name, const std::vector& vectors) { + return set_uniform(glk::hash(name), vectors); +} + +void GLSLShader::set_uniform(std::uint64_t name, const Eigen::Vector2f* vectors, size_t count) { + glUniform2fv(uniform(name), count, vectors[0].data()); + set_uniform_cache(name, vectors); +} + +void GLSLShader::set_uniform(const std::string& name, const Eigen::Vector2f* vectors, size_t count) { + return set_uniform(glk::hash(name), vectors, count); +} + +void GLSLShader::set_uniform(std::uint64_t name, const Eigen::Vector3f* vectors, size_t count) { + glUniform3fv(uniform(name), count, vectors[0].data()); + set_uniform_cache(name, vectors); +} + +void GLSLShader::set_uniform(const std::string& name, const Eigen::Vector3f* vectors, size_t count) { + return set_uniform(glk::hash(name), vectors, count); +} + +void GLSLShader::set_uniform(std::uint64_t name, const Eigen::Vector4f* vectors, size_t count) { + glUniform4fv(uniform(name), count, vectors[0].data()); + set_uniform_cache(name, vectors); +} + +void GLSLShader::set_uniform(const std::string& name, const Eigen::Vector4f* vectors, size_t count) { + return set_uniform(glk::hash(name), vectors, count); +} + +void GLSLShader::set_uniform(std::uint64_t name, const Eigen::Matrix4d& matrix_) { + Eigen::Matrix4f matrix = matrix_.cast(); + glUniformMatrix4fv(uniform(name), 1, GL_FALSE, matrix.data()); +} + +void GLSLShader::set_uniform(const std::string& name, const Eigen::Matrix4d& matrix_) { + set_uniform(glk::hash(name), matrix_); +} + } // namespace glk diff --git a/src/glk/splatting.cpp b/src/glk/splatting.cpp index e21c04c8..b3ebe09a 100644 --- a/src/glk/splatting.cpp +++ b/src/glk/splatting.cpp @@ -61,35 +61,35 @@ void Splatting::draw(glk::GLSLShader& shader_) const { } shader->use(); - if (shader_.get_uniform_cache("info_enabled")) { + if (shader_.get_uniform_cache(glk::hash("info_enabled"))) { shader->set_uniform("info_enabled", 1); - shader->set_uniform("info_values", shader_.get_uniform_cache("info_values")); + shader->set_uniform("info_values", shader_.get_uniform_cache(glk::hash("info_values"))); } else { shader->set_uniform("info_enabled", 0); } - if (shader_.get_uniform_cache("partial_rendering_enabled")) { + if (shader_.get_uniform_cache(glk::hash("partial_rendering_enabled"))) { shader->set_uniform("partial_rendering_enabled", 1); - shader->set_uniform("dynamic_object", shader_.get_uniform_cache("dynamic_object")); + shader->set_uniform("dynamic_object", shader_.get_uniform_cache(glk::hash("dynamic_object"))); } else { shader->set_uniform("partial_rendering_enabled", 0); } - shader->set_uniform("normal_enabled", shader_.get_uniform_cache("normal_enabled")); + shader->set_uniform("normal_enabled", shader_.get_uniform_cache(glk::hash("normal_enabled"))); shader->set_uniform("texture_enabled", texture ? 1 : 0); shader->set_uniform("vert_radius_enabled", vert_radius_enabled); shader->set_uniform("point_radius", point_radius); - shader->set_uniform("color_mode", shader_.get_uniform_cache("color_mode")); - shader->set_uniform("z_range", shader_.get_uniform_cache("z_range")); - shader->set_uniform("cmap_range", shader_.get_uniform_cache("cmap_range")); - shader->set_uniform("colormap_axis", shader_.get_uniform_cache("colormap_axis")); + shader->set_uniform("color_mode", shader_.get_uniform_cache(glk::hash("color_mode"))); + shader->set_uniform("z_range", shader_.get_uniform_cache(glk::hash("z_range"))); + shader->set_uniform("cmap_range", shader_.get_uniform_cache(glk::hash("cmap_range"))); + shader->set_uniform("colormap_axis", shader_.get_uniform_cache(glk::hash("colormap_axis"))); - shader->set_uniform("model_matrix", shader_.get_uniform_cache("model_matrix")); - shader->set_uniform("view_matrix", shader_.get_uniform_cache("view_matrix")); - shader->set_uniform("projection_matrix", shader_.get_uniform_cache("projection_matrix")); - shader->set_uniform("material_color", shader_.get_uniform_cache("material_color")); + shader->set_uniform("model_matrix", shader_.get_uniform_cache(glk::hash("model_matrix"))); + shader->set_uniform("view_matrix", shader_.get_uniform_cache(glk::hash("view_matrix"))); + shader->set_uniform("projection_matrix", shader_.get_uniform_cache(glk::hash("projection_matrix"))); + shader->set_uniform("material_color", shader_.get_uniform_cache(glk::hash("material_color"))); const bool cull_was_enabled = glIsEnabled(GL_CULL_FACE); glDisable(GL_CULL_FACE); From b1532bf65efd80c404c5c06f4cb1a6c4a2d818e8 Mon Sep 17 00:00:00 2001 From: "k.koide" Date: Tue, 30 Dec 2025 11:00:51 +0900 Subject: [PATCH 11/40] flat shader parameters --- include/guik/viewer/shader_setting.hpp | 242 +++++++++++++++++-------- src/glk/drawable_container.cpp | 2 +- src/glk/mesh_model.cpp | 2 +- src/guik/viewer/shader_setting.cpp | 82 ++++----- 4 files changed, 206 insertions(+), 122 deletions(-) diff --git a/include/guik/viewer/shader_setting.hpp b/include/guik/viewer/shader_setting.hpp index a42e69c9..86cf1a12 100644 --- a/include/guik/viewer/shader_setting.hpp +++ b/include/guik/viewer/shader_setting.hpp @@ -36,34 +36,118 @@ struct PointShapeMode { enum MODE { RECTANGLE = 0, CIRCLE = 1 }; }; -/// @brief Generic shader parameter interface. -struct ShaderParameterInterface { -public: - using Ptr = std::unique_ptr; - ShaderParameterInterface(const std::string& name) : name(name) {} - virtual ~ShaderParameterInterface() {} +/// @brief Data type of shader parameter. +enum class ShaderDataType { INT = 0, INT2, INT3, INT4, FLOAT, FLOAT2, FLOAT3, FLOAT4, MATRIX4, INVALID }; - virtual void set(glk::GLSLShader& shader) const = 0; - virtual Ptr clone() const = 0; +/// @brief Deduce shader data type from C++ type. +template +ShaderDataType deduce_data_type() { + if constexpr (std::is_same::value) { + return ShaderDataType::INT; + } else if constexpr (std::is_same::value) { + return ShaderDataType::INT2; + } else if constexpr (std::is_same::value) { + return ShaderDataType::INT3; + } else if constexpr (std::is_same::value) { + return ShaderDataType::INT4; + } else if constexpr (std::is_same::value) { + return ShaderDataType::FLOAT; + } else if constexpr (std::is_same::value) { + return ShaderDataType::FLOAT2; + } else if constexpr (std::is_same::value) { + return ShaderDataType::FLOAT3; + } else if constexpr (std::is_same::value) { + return ShaderDataType::FLOAT4; + } else if constexpr (std::is_same::value) { + return ShaderDataType::MATRIX4; + } else { + return ShaderDataType::INVALID; + } +} +/// @brief Shader parameter class that holds a single parameter for shader setting. +/// @note The maximum size of the parameter value is 4x4 float matrix. +struct ShaderParameter { public: - std::string name; -}; + /// @brief Default constructor + ShaderParameter() : type(ShaderDataType::INVALID), name(0), mat4f(Eigen::Matrix4f::Zero()) {} -/// @brief Type-specific shader parameter. -template -struct ShaderParameter : public ShaderParameterInterface { -public: - EIGEN_MAKE_ALIGNED_OPERATOR_NEW - ShaderParameter(const std::string& name, const T& value) : ShaderParameterInterface(name), value(value) {} - virtual ~ShaderParameter() override {} + /// @brief Constructor + template + ShaderParameter(std::uint64_t name, const T& v) : type(deduce_data_type()), + name(name) { + value() = v; + } - virtual void set(glk::GLSLShader& shader) const override { shader.set_uniform(name, value); } + /// @brief Check if the parameter is valid. + bool valid() const { return type != ShaderDataType::INVALID && name != 0; } - virtual Ptr clone() const override { return glk::make_unique>(name, value); } + /// @brief Invalidate the parameter. + void invalidate() { + type = ShaderDataType::INVALID; + name = 0; + mat4f.setZero(); + } + + /// @brief Get the parameter value. + template + T& value() { + if (type != deduce_data_type()) { + std::cerr << "error: type mismatch when getting shader parameter " << name << std::endl; + abort(); + } + return *reinterpret_cast(&mat4f); + } + + /// @brief Get the parameter value. + template + const T& value() const { + if (type != deduce_data_type()) { + std::cerr << "error: type mismatch when getting shader parameter " << name << std::endl; + abort(); + } + return *reinterpret_cast(&mat4f); + } + + /// @brief Set the parameter to the shader. + void set(glk::GLSLShader& shader) const { + switch (type) { + case ShaderDataType::INT: + shader.set_uniform(name, value()); + break; + case ShaderDataType::INT2: + shader.set_uniform(name, value()); + break; + case ShaderDataType::INT3: + shader.set_uniform(name, value()); + break; + case ShaderDataType::INT4: + shader.set_uniform(name, value()); + break; + case ShaderDataType::FLOAT: + shader.set_uniform(name, value()); + break; + case ShaderDataType::FLOAT2: + shader.set_uniform(name, value()); + break; + case ShaderDataType::FLOAT3: + shader.set_uniform(name, value()); + break; + case ShaderDataType::FLOAT4: + shader.set_uniform(name, value()); + break; + case ShaderDataType::MATRIX4: + shader.set_uniform(name, value()); + break; + default: + break; + } + } public: - T value; + ShaderDataType type; ///< Data type of the parameter + std::uint64_t name; ///< Name of the parameter (hashed) + Eigen::Matrix4f mat4f; ///< Value of the parameter (stored as 4x4 float matrix) }; /// @brief Shader setting class that holds rendering settings. @@ -111,29 +195,18 @@ struct ShaderSetting { /// @param value Parameter value /// @return This object template - ShaderSetting& add(const std::string& name, const T& value) { + ShaderSetting& add(const std::string& name_, const T& value) { + const std::uint64_t name = glk::hash(name_); + int i = 0; - for (i = 0; i < params.size() && params[i] != nullptr; i++) { - if (params[i]->name == name) { - auto p = dynamic_cast*>(params[i].get()); - if (p) { - p->value = value; - } else { - params[i].reset(new ShaderParameter(name, value)); - } + for (i = 0; i < params.size() && params[i].valid(); i++) { + if (params[i].name == name) { + params[i] = ShaderParameter(name, value); return *this; } } - if (i == params.size()) { - std::vector old_params = std::move(params); - params.resize(old_params.size() * 2); - for (int j = 0; j < old_params.size(); j++) { - params[j] = std::move(old_params[j]); - } - } - - params[i] = glk::make_unique>(name, value); + params.emplace_back(ShaderParameter(name, value)); return *this; } @@ -141,22 +214,24 @@ struct ShaderSetting { /// @param name Parameter name /// @return Parameter value if found, otherwise std::nullopt template - std::optional get(const std::string& name) { + std::optional get(const std::string& name_) { + const std::uint64_t name = glk::hash(name_); + for (const auto& param : params) { - if (!param) { - break; + if (!param.valid()) { + continue; } - if (param->name != name) { + if (param.name != name) { continue; } - auto p = dynamic_cast*>(param.get()); - if (p == nullptr) { - continue; + if (param.type != deduce_data_type()) { + std::cerr << "warning: type mismatch for shader parameter " << name_ << std::endl; + return std::nullopt; } - return p->value; + return param.value(); } return std::nullopt; @@ -166,22 +241,24 @@ struct ShaderSetting { /// @param name Parameter name /// @return Parameter value if found, otherwise std::nullopt template - std::optional get(const std::string& name) const { + std::optional get(const std::string& name_) const { + const std::uint64_t name = glk::hash(name_); + for (const auto& param : params) { - if (!param) { - break; + if (!param.valid()) { + continue; } - if (param->name != name) { + if (param.name != name) { continue; } - auto p = dynamic_cast*>(param.get()); - if (p == nullptr) { - continue; + if (param.type != deduce_data_type()) { + std::cerr << "warning: type mismatch for shader parameter " << name_ << std::endl; + return std::nullopt; } - return p->value; + return param.value(); } return std::nullopt; @@ -191,18 +268,24 @@ struct ShaderSetting { /// @param name Parameter name /// @return Parameter value template - const T& cast(const std::string& name) const { + const T& cast(const std::string& name_) const { + const std::uint64_t name = glk::hash(name_); + for (const auto& param : params) { - if (!param) { - break; + if (!param.valid()) { + continue; } - if (param->name != name) { + if (param.name != name) { continue; } - auto p = static_cast*>(param.get()); - return p->value; + if (param.type != deduce_data_type()) { + std::cerr << "error: type mismatch for shader parameter " << name << std::endl; + abort(); + } + + return param.value(); } std::cerr << "error: " << name << " not found in the param list" << std::endl; @@ -298,8 +381,10 @@ struct ShaderSetting { /// @tparam Transform Transform matrix type (e.g., Eigen::Matrix4(f|d) or Eigen::Isometry3(f|d)) template ShaderSetting& set_model_matrix(const Transform& transform) { - auto p = static_cast*>(params[2].get()); - p->value = (transform.template cast() * Eigen::Isometry3f::Identity()).matrix(); + Eigen::Matrix4f mat = (transform.template cast() * Eigen::Isometry3f::Identity()).matrix(); + + auto& p = params[2]; + p.value() = mat; return *this; } @@ -308,8 +393,9 @@ struct ShaderSetting { /// @note The transformation is applied after the existing transformation. (T_new = T_old * transform) template ShaderSetting& transform(const Transform& transform) { - auto p = static_cast*>(params[2].get()); - p->value = p->value * (Eigen::Isometry3f::Identity() * transform.template cast()).matrix(); + auto& p = params[2]; + const Eigen::Matrix4f mat = (p.value() * transform.template cast()).matrix(); + p.value() = mat; return *this; } @@ -321,9 +407,9 @@ struct ShaderSetting { /// @tparam Vector Eigen vector type (e.g., Eigen::Vector3f, Eigen::Vector3d) template ShaderSetting& translate(const Vector& translation) { - auto p = static_cast*>(params[2].get()); + auto& p = params[2]; const auto trans = translation.eval(); - p->value.block<3, 1>(0, 3) += trans.template cast().template head<3>(); + p.mat4f.block<3, 1>(0, 3) += trans.template cast().template head<3>(); return *this; } @@ -333,16 +419,16 @@ struct ShaderSetting { template ShaderSetting& rotate(const float angle, const Vector& axis) { const Eigen::Vector3f ax = axis.eval().template cast(); - auto p = static_cast*>(params[2].get()); - p->value = p->value * (Eigen::Isometry3f::Identity() * Eigen::AngleAxisf(angle, ax)).matrix(); + auto& p = params[2]; + p.mat4f = p.mat4f * (Eigen::Isometry3f::Identity() * Eigen::AngleAxisf(angle, ax)).matrix(); return *this; } /// @brief Apply rotation to the model matrix. /// @param quat Rotation quaternion (Eigen::Quaternion(f|d)) template ShaderSetting& rotate(const Eigen::Quaternion& quat) { - auto p = static_cast*>(params[2].get()); - p->value = p->value * (Eigen::Isometry3f::Identity() * quat.template cast()).matrix(); + auto& p = params[2]; + p.mat4f = p.mat4f * (Eigen::Isometry3f::Identity() * quat.template cast()).matrix(); return *this; } /// @brief Apply rotation to the model matrix. @@ -352,8 +438,8 @@ struct ShaderSetting { Eigen::Isometry3f R = Eigen::Isometry3f::Identity(); R.linear() = rot.template cast().template block<3, 3>(0, 0); - auto p = static_cast*>(params[2].get()); - p->value = p->value * R.matrix(); + auto& p = params[2]; + p.mat4f = p.mat4f * R.matrix(); return *this; } @@ -367,17 +453,17 @@ struct ShaderSetting { /// @tparam Vector Eigen vector type (e.g., Eigen::Vector3f, Eigen::Vector3d) template std::enable_if_t, ShaderSetting&> scale(const Vector& scaling) { - auto p = static_cast*>(params[2].get()); + auto& p = params[2]; const auto s = scaling.eval(); - p->value.col(0) *= s[0]; - p->value.col(1) *= s[1]; - p->value.col(2) *= s[2]; + p.mat4f.col(0) *= s[0]; + p.mat4f.col(1) *= s[1]; + p.mat4f.col(2) *= s[2]; return *this; } public: - bool transparent; ///< If true, the object is rendered as transparent. - std::vector params; ///< Shader parameters + bool transparent; ///< If true, the object is rendered as transparent. + std::vector params; ///< Shader parameters }; template <> diff --git a/src/glk/drawable_container.cpp b/src/glk/drawable_container.cpp index d1da239d..9b4b31a1 100644 --- a/src/glk/drawable_container.cpp +++ b/src/glk/drawable_container.cpp @@ -38,7 +38,7 @@ void DrawableContainer::draw(glk::GLSLShader& shader) const { continue; } - params[i]->set(shader); + params[i].set(shader); } } diff --git a/src/glk/mesh_model.cpp b/src/glk/mesh_model.cpp index 47719579..ec96f179 100644 --- a/src/glk/mesh_model.cpp +++ b/src/glk/mesh_model.cpp @@ -38,7 +38,7 @@ void MeshModel::draw(glk::GLSLShader& shader) const { continue; } - settings[material_id].params[i]->set(shader); + settings[material_id].params[i].set(shader); } } diff --git a/src/guik/viewer/shader_setting.cpp b/src/guik/viewer/shader_setting.cpp index d334ab39..cc9d75f9 100644 --- a/src/guik/viewer/shader_setting.cpp +++ b/src/guik/viewer/shader_setting.cpp @@ -6,21 +6,19 @@ ShaderSetting::ShaderSetting() : ShaderSetting::ShaderSetting(ColorMode::FLAT_CO ShaderSetting::ShaderSetting(int color_mode) : ShaderSetting::ShaderSetting(color_mode, Eigen::Matrix4f::Identity().eval()) {} -ShaderSetting::ShaderSetting(int color_mode, const Eigen::Matrix4f& transform) : transparent(false), params(6) { - params[0] = glk::make_unique>("color_mode", color_mode); - params[1] = glk::make_unique>("point_scale", 1.0f); - params[2] = glk::make_unique>("model_matrix", transform); +ShaderSetting::ShaderSetting(int color_mode, const Eigen::Matrix4f& transform) : transparent(false) { + params.reserve(6); + params.emplace_back(ShaderParameter(glk::hash("color_mode"), color_mode)); + params.emplace_back(ShaderParameter(glk::hash("point_scale"), 1.0f)); + params.emplace_back(ShaderParameter(glk::hash("model_matrix"), transform)); } -ShaderSetting::ShaderSetting(const ShaderSetting& other) : transparent(other.transparent), params(other.params.size()) { - std::transform(other.params.begin(), other.params.end(), params.begin(), [](const auto& p) { return p ? p->clone() : nullptr; }); -} +ShaderSetting::ShaderSetting(const ShaderSetting& other) : transparent(other.transparent), params(other.params) {} ShaderSetting& ShaderSetting::operator=(const ShaderSetting& other) { if (this != &other) { transparent = other.transparent; - params.resize(other.params.size()); - std::transform(other.params.begin(), other.params.end(), params.begin(), [](const auto& p) { return p ? p->clone() : nullptr; }); + params = other.params; } return *this; } @@ -28,17 +26,16 @@ ShaderSetting& ShaderSetting::operator=(const ShaderSetting& other) { ShaderSetting ShaderSetting::clone() const { ShaderSetting cloned; cloned.transparent = transparent; - cloned.params.resize(params.size()); - std::transform(params.begin(), params.end(), cloned.params.begin(), [](const auto& p) { return p ? p->clone() : nullptr; }); + cloned.params = params; return cloned; } void ShaderSetting::set(glk::GLSLShader& shader) const { for (const auto& param : params) { - if (!param) { + if (!param.valid()) { continue; } - param->set(shader); + param.set(shader); } } @@ -80,13 +77,13 @@ ShaderSetting& ShaderSetting::make_transparent() { } float ShaderSetting::point_scale() const { - auto p = static_cast*>(params[1].get()); - return p->value; + auto& p = params[1]; + return p.value(); } ShaderSetting& ShaderSetting::set_point_scale(float scaling) { - auto p = static_cast*>(params[1].get()); - p->value = scaling; + auto& p = params[1]; + p.value() = scaling; return *this; } @@ -145,34 +142,34 @@ ShaderSetting& ShaderSetting::set_old_default_point_shape() { } ShaderSetting& ShaderSetting::remove_model_matrix() { - params[2] = nullptr; + params[2].invalidate(); return *this; } int ShaderSetting::color_mode() const { - auto p = static_cast*>(params[0].get()); - return p->value; + const auto& p = params[0]; + return p.value(); } ShaderSetting& ShaderSetting::set_color_mode(int color_mode) { - auto p = static_cast*>(params[0].get()); - p->value = color_mode; + auto& p = params[0]; + p.value() = color_mode; return *this; } Eigen::Matrix4f ShaderSetting::model_matrix() const { - auto p = static_cast*>(params[2].get()); - return p->value; + const auto& p = params[2]; + return p.value(); } Eigen::Vector3f ShaderSetting::translation() const { - auto p = static_cast*>(params[2].get()); - return p->value.block<3, 1>(0, 3); + const auto& p = params[2]; + return p.value().block<3, 1>(0, 3); } Eigen::Matrix3f ShaderSetting::rotation() const { - auto p = static_cast*>(params[2].get()); - return p->value.block<3, 3>(0, 0); + const auto& p = params[2]; + return p.value().block<3, 3>(0, 0); } ShaderSetting& ShaderSetting::translate(float tx, float ty, float tz) { @@ -180,37 +177,38 @@ ShaderSetting& ShaderSetting::translate(float tx, float ty, float tz) { } ShaderSetting& ShaderSetting::translate(const Eigen::Vector3f& translation) { - auto p = static_cast*>(params[2].get()); - p->value.block<3, 1>(0, 3) += translation; + auto& p = params[2]; + p.mat4f.block<3, 1>(0, 3) += translation; return *this; } ShaderSetting& ShaderSetting::rotate(const float angle, const Eigen::Vector3f& axis) { const Eigen::Vector3f ax = axis.eval().template cast(); - auto p = static_cast*>(params[2].get()); - p->value = p->value * (Eigen::Isometry3f::Identity() * Eigen::AngleAxisf(angle, axis)).matrix(); + + auto& p = params[2]; + p.mat4f = p.mat4f * (Eigen::Isometry3f::Identity() * Eigen::AngleAxisf(angle, ax.normalized())).matrix(); return *this; } ShaderSetting& ShaderSetting::scale(float scaling) { - auto p = static_cast*>(params[2].get()); - p->value.block<4, 3>(0, 0) *= scaling; + auto& p = params[2]; + p.mat4f.block<4, 3>(0, 0) *= scaling; return *this; } ShaderSetting& ShaderSetting::scale(float sx, float sy, float sz) { - auto p = static_cast*>(params[2].get()); - p->value.col(0) *= sx; - p->value.col(1) *= sy; - p->value.col(2) *= sz; + auto& p = params[2]; + p.mat4f.col(0) *= sx; + p.mat4f.col(1) *= sy; + p.mat4f.col(2) *= sz; return *this; } ShaderSetting& ShaderSetting::scale(const Eigen::Vector3f& scaling) { - auto p = static_cast*>(params[2].get()); - p->value.col(0) *= scaling[0]; - p->value.col(1) *= scaling[1]; - p->value.col(2) *= scaling[2]; + auto& p = params[2]; + p.mat4f.col(0) *= scaling[0]; + p.mat4f.col(1) *= scaling[1]; + p.mat4f.col(2) *= scaling[2]; return *this; } From 8b091a99b39cfa493a3fead46617046084a8cefe Mon Sep 17 00:00:00 2001 From: "k.koide" Date: Tue, 30 Dec 2025 11:08:12 +0900 Subject: [PATCH 12/40] refactor and warn --- include/guik/viewer/shader_setting.hpp | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/include/guik/viewer/shader_setting.hpp b/include/guik/viewer/shader_setting.hpp index 86cf1a12..89bd88c7 100644 --- a/include/guik/viewer/shader_setting.hpp +++ b/include/guik/viewer/shader_setting.hpp @@ -140,6 +140,7 @@ struct ShaderParameter { shader.set_uniform(name, value()); break; default: + std::cerr << "error: invalid shader parameter type for " << name << std::endl; break; } } @@ -198,8 +199,7 @@ struct ShaderSetting { ShaderSetting& add(const std::string& name_, const T& value) { const std::uint64_t name = glk::hash(name_); - int i = 0; - for (i = 0; i < params.size() && params[i].valid(); i++) { + for (int i = 0; i < params.size() && params[i].valid(); i++) { if (params[i].name == name) { params[i] = ShaderParameter(name, value); return *this; @@ -218,11 +218,7 @@ struct ShaderSetting { const std::uint64_t name = glk::hash(name_); for (const auto& param : params) { - if (!param.valid()) { - continue; - } - - if (param.name != name) { + if (!param.valid() || param.name != name) { continue; } @@ -245,11 +241,7 @@ struct ShaderSetting { const std::uint64_t name = glk::hash(name_); for (const auto& param : params) { - if (!param.valid()) { - continue; - } - - if (param.name != name) { + if (!param.valid() || param.name != name) { continue; } @@ -272,11 +264,7 @@ struct ShaderSetting { const std::uint64_t name = glk::hash(name_); for (const auto& param : params) { - if (!param.valid()) { - continue; - } - - if (param.name != name) { + if (!param.valid() || param.name != name) { continue; } From 47750811f207aa15711d297c508b751d1255153c Mon Sep 17 00:00:00 2001 From: "k.koide" Date: Tue, 30 Dec 2025 12:19:12 +0900 Subject: [PATCH 13/40] tune ssao intensity --- data/shader/ssao.frag | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/shader/ssao.frag b/data/shader/ssao.frag index 2599c985..b5b44cb5 100644 --- a/data/shader/ssao.frag +++ b/data/shader/ssao.frag @@ -19,5 +19,5 @@ void main() { return; } - final_color = frag_color * (1 - frag_occlusion); + final_color = frag_color * (1 - clamp(frag_occlusion - 0.2, 0.0, 1.0)); } \ No newline at end of file From 5d669b83217809bfdcdefee2b22d3b8fee5fbafd Mon Sep 17 00:00:00 2001 From: "k.koide" Date: Tue, 30 Dec 2025 12:20:46 +0900 Subject: [PATCH 14/40] remove Eigen::aligned_allocator and fix array uniform bug --- include/glk/effects/screen_space_lighting.hpp | 13 +- include/glk/glsl_shader.hpp | 49 +++--- include/glk/io/ply_io.hpp | 8 +- include/glk/mesh_utils.hpp | 10 +- include/glk/pointcloud_buffer.hpp | 6 +- include/glk/pointcloud_buffer_pcl.hpp | 24 +-- include/glk/primitives/cone.hpp | 6 +- include/glk/primitives/coordinate_system.hpp | 4 +- include/glk/primitives/cube.hpp | 24 +-- include/glk/primitives/frustum.hpp | 28 ++-- include/glk/primitives/grid.hpp | 6 +- include/glk/primitives/icosahedron.hpp | 42 +++-- include/glk/trajectory.hpp | 7 +- src/example/ext_light_viewer_brdf.cpp | 2 +- src/example/ext_light_viewer_pointcloud.cpp | 10 +- .../naive_screen_space_ambient_occlusion.cpp | 4 +- .../screen_space_attribute_estimation.cpp | 6 +- src/glk/effects/screen_space_lighting.cpp | 6 +- src/glk/effects/screen_space_splatting.cpp | 81 +++++----- src/glk/glsl_shader.cpp | 153 ++++++++++-------- src/glk/gridmap.cpp | 4 +- src/glk/lines.cpp | 19 +-- src/glk/point_correspondences.cpp | 4 +- src/glk/pointcloud_buffer.cpp | 10 +- src/glk/pointnormals_buffer.cpp | 12 +- src/glk/texture_renderer.cpp | 2 +- src/glk/trajectory.cpp | 12 +- src/guik/gl_canvas.cpp | 4 +- src/guik/hovered_drawings.cpp | 4 +- src/python/glk.cpp | 37 ++--- 30 files changed, 312 insertions(+), 285 deletions(-) diff --git a/include/glk/effects/screen_space_lighting.hpp b/include/glk/effects/screen_space_lighting.hpp index 957331de..cb6e423d 100644 --- a/include/glk/effects/screen_space_lighting.hpp +++ b/include/glk/effects/screen_space_lighting.hpp @@ -53,7 +53,12 @@ class ScreenSpaceLighting : public ScreenEffect { void set_light_color(int i, const Eigen::Vector4f& color); virtual void set_size(const Eigen::Vector2i& size) override; - virtual void draw(const TextureRenderer& renderer, const glk::Texture& color_texture, const glk::Texture& depth_texture, const TextureRendererInput::Ptr& input, glk::FrameBuffer* frame_buffer = nullptr) override; + virtual void draw( + const TextureRenderer& renderer, + const glk::Texture& color_texture, + const glk::Texture& depth_texture, + const TextureRendererInput::Ptr& input, + glk::FrameBuffer* frame_buffer = nullptr) override; private: bool load_shader(); @@ -76,9 +81,9 @@ class ScreenSpaceLighting : public ScreenEffect { bool light_updated; std::vector light_directional; std::vector light_range; - std::vector> light_attenuation; - std::vector> light_pos; - std::vector> light_color; + std::vector light_attenuation; + std::vector light_pos; + std::vector light_color; }; } // namespace glk diff --git a/include/glk/glsl_shader.hpp b/include/glk/glsl_shader.hpp index 44922f28..12c0045a 100644 --- a/include/glk/glsl_shader.hpp +++ b/include/glk/glsl_shader.hpp @@ -40,13 +40,13 @@ class GLSLShader { void use() const { glUseProgram(shader_program); } void unuse() const { glUseProgram(0); } - GLint attrib(std::uint64_t name) const; - GLint attrib(const std::string& name) const; - GLint uniform(std::uint64_t name) const; - GLint uniform(const std::string& name) const; - GLint subroutine(GLenum shader_type, std::uint64_t name) const; + GLint attrib(std::uint64_t name, const char* debug_msg = nullptr); + GLint attrib(const std::string& name); + GLint uniform(std::uint64_t name, const char* debug_msg = nullptr); + GLint uniform(const std::string& name); + GLint subroutine(GLenum shader_type, std::uint64_t name, const char* debug_msg = nullptr); GLint subroutine(GLenum shader_type, const std::string& name); - GLint subroutine_uniform(GLenum shader_type, std::uint64_t name) const; + GLint subroutine_uniform(GLenum shader_type, std::uint64_t name, const char* debug_msg = nullptr); GLint subroutine_uniform(GLenum shader_type, const std::string& name); int get_uniformi(std::uint64_t name); @@ -81,63 +81,62 @@ class GLSLShader { } // int - void set_uniform(std::uint64_t name, int value); + void set_uniform(std::uint64_t name, int value, const char* debug_msg = nullptr); void set_uniform(const std::string& name, int value); // float - void set_uniform(std::uint64_t name, float value); + void set_uniform(std::uint64_t name, float value, const char* debug_msg = nullptr); void set_uniform(const std::string& name, float value); // vec2f - void set_uniform(std::uint64_t name, const Eigen::Vector2f& vector); + void set_uniform(std::uint64_t name, const Eigen::Vector2f& vector, const char* debug_msg = nullptr); void set_uniform(const std::string& name, const Eigen::Vector2f& vector); // vec3f - void set_uniform(std::uint64_t name, const Eigen::Vector3f& vector); + void set_uniform(std::uint64_t name, const Eigen::Vector3f& vector, const char* debug_msg = nullptr); void set_uniform(const std::string& name, const Eigen::Vector3f& vector); // vec4f - void set_uniform(std::uint64_t name, const Eigen::Vector4f& vector); + void set_uniform(std::uint64_t name, const Eigen::Vector4f& vector, const char* debug_msg = nullptr); void set_uniform(const std::string& name, const Eigen::Vector4f& vector); // vec2i - void set_uniform(std::uint64_t name, const Eigen::Vector2i& vector); + void set_uniform(std::uint64_t name, const Eigen::Vector2i& vector, const char* debug_msg = nullptr); void set_uniform(const std::string& name, const Eigen::Vector2i& vector); // vec3i - void set_uniform(std::uint64_t name, const Eigen::Vector3i& vector); + void set_uniform(std::uint64_t name, const Eigen::Vector3i& vector, const char* debug_msg = nullptr); void set_uniform(const std::string& name, const Eigen::Vector3i& vector); // vec4i - void set_uniform(std::uint64_t name, const Eigen::Vector4i& vector); + void set_uniform(std::uint64_t name, const Eigen::Vector4i& vector, const char* debug_msg = nullptr); void set_uniform(const std::string& name, const Eigen::Vector4i& vector); // matrix4f - void set_uniform(std::uint64_t name, const Eigen::Matrix4f& matrix); + void set_uniform(std::uint64_t name, const Eigen::Matrix4f& matrix, const char* debug_msg = nullptr); void set_uniform(const std::string& name, const Eigen::Matrix4f& matrix); // array of int - void set_uniform(std::uint64_t name, const std::vector& vectors); + void set_uniform(std::uint64_t name, const std::vector& vectors, const char* debug_msg = nullptr); void set_uniform(const std::string& name, const std::vector& vectors); // array of float - void set_uniform(std::uint64_t name, const std::vector& vectors); + void set_uniform(std::uint64_t name, const std::vector& vectors, const char* debug_msg = nullptr); void set_uniform(const std::string& name, const std::vector& vectors); // array of vec2f - void set_uniform(std::uint64_t name, const Eigen::Vector2f* vectors, size_t count); - void set_uniform(const std::string& name, const Eigen::Vector2f* vectors, size_t count); + void set_uniform(std::uint64_t name, const std::vector& vectors, const char* debug_msg = nullptr); + void set_uniform(const std::string& name, const std::vector& vectors); // array of vec3f - void set_uniform(std::uint64_t name, const Eigen::Vector3f* vectors, size_t count); - void set_uniform(const std::string& name, const Eigen::Vector3f* vectors, size_t count); + void set_uniform(std::uint64_t name, const std::vector& vectors, const char* debug_msg = nullptr); + void set_uniform(const std::string& name, const std::vector& vectors); // array of vec4f - void set_uniform(std::uint64_t name, const Eigen::Vector4f* vectors, size_t count); - void set_uniform(const std::string& name, const Eigen::Vector4f* vectors, size_t count); - + void set_uniform(std::uint64_t name, const std::vector& vectors, const char* debug_msg = nullptr); + void set_uniform(const std::string& name, const std::vector& vectors); // matrix4d - void set_uniform(std::uint64_t name, const Eigen::Matrix4d& matrix_); + void set_uniform(std::uint64_t name, const Eigen::Matrix4d& matrix_, const char* debug_msg = nullptr); void set_uniform(const std::string& name, const Eigen::Matrix4d& matrix_); void set_subroutine(GLenum shader_type, const std::string& loc, const std::string& func); diff --git a/include/glk/io/ply_io.hpp b/include/glk/io/ply_io.hpp index 91601088..2ee8420b 100644 --- a/include/glk/io/ply_io.hpp +++ b/include/glk/io/ply_io.hpp @@ -119,10 +119,10 @@ struct PLYData { } public: - std::vector> vertices; // Vertex positions (saved as "x", "y", "z" properties). - std::vector> normals; // Vertex normals (saved as "nx", "ny", "nz" properties). - std::vector intensities; // Intensity values (saved as "intensity" property). - std::vector> colors; // RGBA colors (saved as "r", "g", "b", "a" properties). + std::vector vertices; // Vertex positions (saved as "x", "y", "z" properties). + std::vector normals; // Vertex normals (saved as "nx", "ny", "nz" properties). + std::vector intensities; // Intensity values (saved as "intensity" property). + std::vector colors; // RGBA colors (saved as "r", "g", "b", "a" properties). std::vector indices; std::vector comments; diff --git a/include/glk/mesh_utils.hpp b/include/glk/mesh_utils.hpp index f2f99762..8966a59a 100644 --- a/include/glk/mesh_utils.hpp +++ b/include/glk/mesh_utils.hpp @@ -9,7 +9,7 @@ namespace glk { class Flatize { public: - Flatize(const std::vector>& vertices_, const std::vector& indices_) { + Flatize(const std::vector& vertices_, const std::vector& indices_) { vertices.resize(indices_.size()); normals.resize(indices_.size()); indices.resize(indices_.size()); @@ -29,14 +29,14 @@ class Flatize { } public: - std::vector> vertices; - std::vector> normals; + std::vector vertices; + std::vector normals; std::vector indices; }; class NormalEstimater { public: - NormalEstimater(const std::vector>& vertices, const std::vector& indices) { + NormalEstimater(const std::vector& vertices, const std::vector& indices) { normals.resize(vertices.size(), Eigen::Vector3f::Zero()); for (int i = 0; i < indices.size(); i += 3) { Eigen::Vector3f v1 = vertices[indices[i]]; @@ -56,7 +56,7 @@ class NormalEstimater { } public: - std::vector> normals; + std::vector normals; }; } // namespace glk diff --git a/include/glk/pointcloud_buffer.hpp b/include/glk/pointcloud_buffer.hpp index dd79c20d..46ba06c1 100644 --- a/include/glk/pointcloud_buffer.hpp +++ b/include/glk/pointcloud_buffer.hpp @@ -137,7 +137,7 @@ void PointCloudBuffer::add_normals(const std::vector, template void PointCloudBuffer::add_normals(const std::vector, Allocator>& normals) { - std::vector> normals_f(normals.size()); + std::vector normals_f(normals.size()); std::transform(normals.begin(), normals.end(), normals_f.begin(), [](const Eigen::Matrix& n) { return n.template head<3>().template cast(); }); add_normals(normals_f[0].data(), sizeof(Eigen::Vector3f), normals_f.size()); } @@ -149,7 +149,7 @@ void PointCloudBuffer::add_normals(const Eigen::Matrix* normals, in template void PointCloudBuffer::add_normals(const Eigen::Matrix* normals, int num_points) { - std::vector, Eigen::aligned_allocator>> normals_f(num_points); + std::vector> normals_f(num_points); std::transform(normals, normals + num_points, normals_f.begin(), [](const Eigen::Matrix& p) { return p.template cast(); }); add_normals(normals_f); } @@ -164,7 +164,7 @@ void PointCloudBuffer::add_buffer(const std::string& attribute_name, const std:: if constexpr (std::is_same::value) { add_buffer(attribute_name, D, data[0].data(), sizeof(float) * D, data.size()); } else { - std::vector, Eigen::aligned_allocator>> data_f(data.size()); + std::vector> data_f(data.size()); std::transform(data.begin(), data.end(), data_f.begin(), [](const Eigen::Matrix& p) { return p.template cast(); }); add_buffer(attribute_name, D, data_f.data(), sizeof(float) * D, data_f.size()); } diff --git a/include/glk/pointcloud_buffer_pcl.hpp b/include/glk/pointcloud_buffer_pcl.hpp index 12f4c9bf..07173d3d 100644 --- a/include/glk/pointcloud_buffer_pcl.hpp +++ b/include/glk/pointcloud_buffer_pcl.hpp @@ -8,25 +8,25 @@ namespace glk { -template +template std::shared_ptr create_point_cloud_buffer(const pcl::PointCloud& cloud) { - std::vector> points(cloud.size()); - for(int i = 0; i < cloud.size(); i++) { + std::vector points(cloud.size()); + for (int i = 0; i < cloud.size(); i++) { points[i] = cloud[i].getVector3fMap(); } return std::make_shared(points[0].data(), sizeof(Eigen::Vector3f), cloud.size()); } -template<> +template <> inline std::shared_ptr create_point_cloud_buffer(const pcl::PointCloud& cloud) { return std::make_shared(&cloud.at(0).x, sizeof(pcl::PointXYZ), cloud.size()); } -template<> +template <> inline std::shared_ptr create_point_cloud_buffer(const pcl::PointCloud& cloud) { - std::vector> points(cloud.size()); - std::vector> normals(cloud.size()); - for(int i = 0; i < cloud.size(); i++) { + std::vector points(cloud.size()); + std::vector normals(cloud.size()); + for (int i = 0; i < cloud.size(); i++) { points[i] = cloud[i].getVector3fMap(); normals[i] = cloud[i].getNormalVector3fMap(); } @@ -37,12 +37,12 @@ inline std::shared_ptr create_point_cloud_buffer(const pcl::Po return cloud_buffer; } -template +template std::shared_ptr create_colored_point_cloud_buffer(const pcl::PointCloud& cloud) { - std::vector> points(cloud.size()); - std::vector> colors(cloud.size()); + std::vector points(cloud.size()); + std::vector colors(cloud.size()); - for(int i = 0; i < cloud.size(); i++) { + for (int i = 0; i < cloud.size(); i++) { points[i] = cloud[i].getVector3fMap(); colors[i] = Eigen::Vector4f(cloud[i].r, cloud[i].g, cloud[i].b, cloud[i].a) / 255.0f; } diff --git a/include/glk/primitives/cone.hpp b/include/glk/primitives/cone.hpp index c6f0ebe4..8212a8b9 100644 --- a/include/glk/primitives/cone.hpp +++ b/include/glk/primitives/cone.hpp @@ -9,12 +9,12 @@ namespace glk { class Cone { public: - Cone(int div=10) { + Cone(int div = 10) { vertices.push_back(Eigen::Vector3f::Zero()); vertices.push_back(Eigen::Vector3f::UnitZ()); double step = 2.0 * M_PI / div; - for(int i = 0; i < div; i++) { + for (int i = 0; i < div; i++) { double rad = step * i; vertices.push_back(Eigen::Vector3f(std::cos(rad), std::sin(rad), 0.0f)); @@ -32,7 +32,7 @@ class Cone { } public: - std::vector> vertices; + std::vector vertices; std::vector indices; }; diff --git a/include/glk/primitives/coordinate_system.hpp b/include/glk/primitives/coordinate_system.hpp index 2ea15df7..c84fd6f1 100644 --- a/include/glk/primitives/coordinate_system.hpp +++ b/include/glk/primitives/coordinate_system.hpp @@ -29,8 +29,8 @@ class CoordinateSystem { } public: - std::vector> vertices; - std::vector> colors; + std::vector vertices; + std::vector colors; }; } // namespace glk diff --git a/include/glk/primitives/cube.hpp b/include/glk/primitives/cube.hpp index 8bdbc31e..5831d6a0 100644 --- a/include/glk/primitives/cube.hpp +++ b/include/glk/primitives/cube.hpp @@ -17,18 +17,18 @@ class Cube { // | 2 -----| 3 Y // |/ |/ // 0 ------ 1 - std::vector> vertices = { - Eigen::Vector3f(-0.5f, -0.5f, -0.5f), // 0 - Eigen::Vector3f(-0.5f, -0.5f, 0.5f), // 1 - Eigen::Vector3f(-0.5f, 0.5f, -0.5f), // 2 - Eigen::Vector3f(-0.5f, 0.5f, 0.5f), // 3 - Eigen::Vector3f(0.5f, -0.5f, -0.5f), // 4 - Eigen::Vector3f(0.5f, -0.5f, 0.5f), // 5 - Eigen::Vector3f(0.5f, 0.5f, -0.5f), // 6 - Eigen::Vector3f(0.5f, 0.5f, 0.5f), // 7 + std::vector vertices = { + Eigen::Vector3f(-0.5f, -0.5f, -0.5f), // 0 + Eigen::Vector3f(-0.5f, -0.5f, 0.5f), // 1 + Eigen::Vector3f(-0.5f, 0.5f, -0.5f), // 2 + Eigen::Vector3f(-0.5f, 0.5f, 0.5f), // 3 + Eigen::Vector3f(0.5f, -0.5f, -0.5f), // 4 + Eigen::Vector3f(0.5f, -0.5f, 0.5f), // 5 + Eigen::Vector3f(0.5f, 0.5f, -0.5f), // 6 + Eigen::Vector3f(0.5f, 0.5f, 0.5f), // 7 }; - std::vector> normals(vertices.size()); + std::vector normals(vertices.size()); for (int i = 0; i < vertices.size(); i++) { normals[i] = vertices[i].normalized(); } @@ -40,8 +40,8 @@ class Cube { } public: - std::vector> vertices; - std::vector> normals; + std::vector vertices; + std::vector normals; std::vector indices; }; diff --git a/include/glk/primitives/frustum.hpp b/include/glk/primitives/frustum.hpp index 8abe657d..0b250460 100644 --- a/include/glk/primitives/frustum.hpp +++ b/include/glk/primitives/frustum.hpp @@ -9,28 +9,28 @@ namespace glk { class Frustum { public: Frustum(float w, float h, float z, bool close_front) { - vertices.push_back(Eigen::Vector3f(w / 2, h / 2, z)); // v0 - vertices.push_back(Eigen::Vector3f(-w / 2, h / 2, z)); // v1 - vertices.push_back(Eigen::Vector3f(-w / 2, -h / 2, z)); // v2 - vertices.push_back(Eigen::Vector3f(w / 2, -h / 2, z)); // v3 - vertices.push_back(Eigen::Vector3f(0, 0, 0)); // v4 - - normals.push_back(vertices[0].normalized()); // n1 - normals.push_back(vertices[1].normalized()); // n2 - normals.push_back(vertices[2].normalized()); // n3 - normals.push_back(vertices[3].normalized()); // n4 - normals.push_back(Eigen::Vector3f(0, 0, 0)); // n5 + vertices.push_back(Eigen::Vector3f(w / 2, h / 2, z)); // v0 + vertices.push_back(Eigen::Vector3f(-w / 2, h / 2, z)); // v1 + vertices.push_back(Eigen::Vector3f(-w / 2, -h / 2, z)); // v2 + vertices.push_back(Eigen::Vector3f(w / 2, -h / 2, z)); // v3 + vertices.push_back(Eigen::Vector3f(0, 0, 0)); // v4 + + normals.push_back(vertices[0].normalized()); // n1 + normals.push_back(vertices[1].normalized()); // n2 + normals.push_back(vertices[2].normalized()); // n3 + normals.push_back(vertices[3].normalized()); // n4 + normals.push_back(Eigen::Vector3f(0, 0, 0)); // n5 indices = {0, 4, 1, 1, 4, 2, 2, 4, 3, 3, 4, 0}; if (close_front) { - std::array front_indices = { 0, 1, 2, 0, 2, 3}; + std::array front_indices = {0, 1, 2, 0, 2, 3}; indices.insert(indices.end(), front_indices.begin(), front_indices.end()); } } - std::vector> vertices; - std::vector> normals; + std::vector vertices; + std::vector normals; std::vector indices; }; } // namespace glk diff --git a/include/glk/primitives/grid.hpp b/include/glk/primitives/grid.hpp index 3efd35bf..c22bcc15 100644 --- a/include/glk/primitives/grid.hpp +++ b/include/glk/primitives/grid.hpp @@ -9,7 +9,7 @@ namespace glk { class Grid { public: Grid(double half_extent = 5.0, double step = 1.0) { - for(double x = -half_extent; x <= half_extent + 1e-9; x+=step) { + for (double x = -half_extent; x <= half_extent + 1e-9; x += step) { vertices.push_back(Eigen::Vector3f(x, -half_extent, 0.0f)); vertices.push_back(Eigen::Vector3f(x, half_extent, 0.0f)); vertices.push_back(Eigen::Vector3f(-half_extent, x, 0.0f)); @@ -18,8 +18,8 @@ class Grid { } public: - std::vector> vertices; + std::vector vertices; }; -} +} // namespace glk #endif \ No newline at end of file diff --git a/include/glk/primitives/icosahedron.hpp b/include/glk/primitives/icosahedron.hpp index 5758a7b1..ca21e1b2 100644 --- a/include/glk/primitives/icosahedron.hpp +++ b/include/glk/primitives/icosahedron.hpp @@ -12,19 +12,27 @@ class Icosahedron { Icosahedron() { double t = (1.0 + std::sqrt(5.0)) / 2.0; - std::vector> vertices = { - Eigen::Vector3f(-1, t, 0), Eigen::Vector3f(1, t, 0), Eigen::Vector3f(-1, -t, 0), Eigen::Vector3f(1, -t, 0), - Eigen::Vector3f(0, -1, t), Eigen::Vector3f(0, 1, t), Eigen::Vector3f(0, -1, -t), Eigen::Vector3f(0, 1, -t), - Eigen::Vector3f(t, 0, -1), Eigen::Vector3f(t, 0, 1), Eigen::Vector3f(-t, 0, -1), Eigen::Vector3f(-t, 0, 1)}; - - std::vector> normals(vertices.size()); - for(int i = 0; i < vertices.size(); i++) { + std::vector vertices = { + Eigen::Vector3f(-1, t, 0), + Eigen::Vector3f(1, t, 0), + Eigen::Vector3f(-1, -t, 0), + Eigen::Vector3f(1, -t, 0), + Eigen::Vector3f(0, -1, t), + Eigen::Vector3f(0, 1, t), + Eigen::Vector3f(0, -1, -t), + Eigen::Vector3f(0, 1, -t), + Eigen::Vector3f(t, 0, -1), + Eigen::Vector3f(t, 0, 1), + Eigen::Vector3f(-t, 0, -1), + Eigen::Vector3f(-t, 0, 1)}; + + std::vector normals(vertices.size()); + for (int i = 0; i < vertices.size(); i++) { normals[i] = vertices[i].normalized(); } - std::vector indices = {0, 11, 5, 0, 5, 1, 0, 1, 7, 0, 7, 10, 0, 10, 11, 1, 5, 9, 5, 11, - 4, 11, 10, 2, 10, 7, 6, 7, 1, 8, 3, 9, 4, 3, 4, 2, 3, 2, 6, 3, - 6, 8, 3, 8, 9, 4, 9, 5, 2, 4, 11, 6, 2, 10, 8, 6, 7, 9, 8, 1}; + std::vector indices = {0, 11, 5, 0, 5, 1, 0, 1, 7, 0, 7, 10, 0, 10, 11, 1, 5, 9, 5, 11, 4, 11, 10, 2, 10, 7, 6, 7, 1, 8, + 3, 9, 4, 3, 4, 2, 3, 2, 6, 3, 6, 8, 3, 8, 9, 4, 9, 5, 2, 4, 11, 6, 2, 10, 8, 6, 7, 9, 8, 1}; this->vertices.swap(vertices); this->normals.swap(normals); @@ -33,7 +41,7 @@ class Icosahedron { void subdivide() { std::vector new_indices; - for(int i = 0; i < indices.size(); i += 3) { + for (int i = 0; i < indices.size(); i += 3) { int a = insert_middle_point(indices[i], indices[i + 1]); int b = insert_middle_point(indices[i + 1], indices[i + 2]); int c = insert_middle_point(indices[i + 2], indices[i]); @@ -46,18 +54,18 @@ class Icosahedron { indices.swap(new_indices); normals.resize(vertices.size()); - for(int i = 0; i < vertices.size(); i++) { + for (int i = 0; i < vertices.size(); i++) { normals[i] = vertices[i].normalized(); } } void spherize() { - for(auto& vertex : vertices) { + for (auto& vertex : vertices) { vertex.normalize(); } normals.resize(vertices.size()); - for(int i = 0; i < vertices.size(); i++) { + for (int i = 0; i < vertices.size(); i++) { normals[i] = vertices[i].normalized(); } } @@ -69,7 +77,7 @@ class Icosahedron { int key = (smaller << 16) + greater; auto found = middle_points_cache.find(key); - if(found != middle_points_cache.end()) { + if (found != middle_points_cache.end()) { return found->second; } @@ -81,8 +89,8 @@ class Icosahedron { } public: - std::vector> vertices; - std::vector> normals; + std::vector vertices; + std::vector normals; std::vector indices; std::map middle_points_cache; diff --git a/include/glk/trajectory.hpp b/include/glk/trajectory.hpp index 628c0809..766b30e7 100644 --- a/include/glk/trajectory.hpp +++ b/include/glk/trajectory.hpp @@ -13,7 +13,7 @@ class ThinLines; class Trajectory : public glk::Drawable { public: - Trajectory(const std::vector>& trajectory); + Trajectory(const std::vector& trajectory); Trajectory(int num_frames, const std::function& adapter); virtual ~Trajectory(); @@ -22,9 +22,8 @@ class Trajectory : public glk::Drawable { private: std::unique_ptr lines; - std::vector> trajectory; + std::vector trajectory; }; -} - +} // namespace glk #endif \ No newline at end of file diff --git a/src/example/ext_light_viewer_brdf.cpp b/src/example/ext_light_viewer_brdf.cpp index c68db37d..7301e550 100644 --- a/src/example/ext_light_viewer_brdf.cpp +++ b/src/example/ext_light_viewer_brdf.cpp @@ -34,7 +34,7 @@ int main(int argc, char** argv) { bool rotate_lights = true; const int num_lights = 8; - std::vector> light_colors(num_lights); + std::vector light_colors(num_lights); for (int i = 0; i < num_lights; i++) { light_colors[i] = glk::colormap_categoricalf(glk::COLORMAP::TURBO, i, num_lights); } diff --git a/src/example/ext_light_viewer_pointcloud.cpp b/src/example/ext_light_viewer_pointcloud.cpp index d47128e4..fdf6c6ed 100644 --- a/src/example/ext_light_viewer_pointcloud.cpp +++ b/src/example/ext_light_viewer_pointcloud.cpp @@ -18,9 +18,9 @@ int main(int argc, char** argv) { std::vector filenames; viewer->register_ui_callback("cloud_loader", [&]() { - if(ImGui::Button("load")) { + if (ImGui::Button("load")) { std::vector results = pfd::open_file("choose PCD file").result(); - if(!results.empty()) { + if (!results.empty()) { filenames.push_back(results[0]); pcl::PointCloud::Ptr cloud(new pcl::PointCloud); @@ -40,7 +40,7 @@ int main(int argc, char** argv) { // viewer->update_drawable(results[0], cloud_buffer, guik::FlatColor(Eigen::Vector4f::Random(), Eigen::Translation3f(1.0f, 1.0f, 1.0f)).add("point_scale", 5.0f)); // with point color - // std::vector> colors(cloud->size()); + // std::vector colors(cloud->size()); // for(int i = 0; i < cloud->size(); i++) { // colors[i] = cloud->at(i).getVector4fMap() * 0.1f; // } @@ -55,10 +55,10 @@ int main(int argc, char** argv) { } } - for(int i = 0; i < filenames.size(); i++) { + for (int i = 0; i < filenames.size(); i++) { std::string button_name = "remove##" + std::to_string(i); std::string filename = filenames[i]; - if(ImGui::Button(button_name.c_str())) { + if (ImGui::Button(button_name.c_str())) { viewer->remove_drawable(filenames[i]); filenames.erase(filenames.begin() + i); } diff --git a/src/glk/effects/naive_screen_space_ambient_occlusion.cpp b/src/glk/effects/naive_screen_space_ambient_occlusion.cpp index 8e4eb116..162aa6c4 100644 --- a/src/glk/effects/naive_screen_space_ambient_occlusion.cpp +++ b/src/glk/effects/naive_screen_space_ambient_occlusion.cpp @@ -12,7 +12,7 @@ NaiveScreenSpaceAmbientOcclusion::NaiveScreenSpaceAmbientOcclusion() { return; } std::mt19937 mt; - std::vector> random_vectors(32); + std::vector random_vectors(32); for (auto& vec : random_vectors) { double u = std::uniform_real_distribution<>(0.0, 1.0)(mt); double v = std::uniform_real_distribution<>(-1.0, 1.0)(mt); @@ -27,7 +27,7 @@ NaiveScreenSpaceAmbientOcclusion::NaiveScreenSpaceAmbientOcclusion() { ssao_shader.use(); ssao_shader.set_uniform("ao_radius", 0.1f); - ssao_shader.set_uniform("random_vectors", random_vectors.data(), random_vectors.size()); + ssao_shader.set_uniform("random_vectors", random_vectors); } NaiveScreenSpaceAmbientOcclusion::~NaiveScreenSpaceAmbientOcclusion() {} diff --git a/src/glk/effects/screen_space_attribute_estimation.cpp b/src/glk/effects/screen_space_attribute_estimation.cpp index 57021448..9f01e3b7 100644 --- a/src/glk/effects/screen_space_attribute_estimation.cpp +++ b/src/glk/effects/screen_space_attribute_estimation.cpp @@ -50,12 +50,12 @@ ScreenSpaceAttributeEstimation::ScreenSpaceAttributeEstimation(const Eigen::Vect return vec; }; - std::vector> random_vectors(16); + std::vector random_vectors(16); for (auto& vec : random_vectors) { vec = sample_random_vector(); } - std::vector> randomization(128 * 128); + std::vector randomization(128 * 128); for (auto& vec : randomization) { vec = sample_random_vector().normalized(); } @@ -81,7 +81,7 @@ ScreenSpaceAttributeEstimation::ScreenSpaceAttributeEstimation(const Eigen::Vect occlusion_shader.set_uniform("normal_sampler", 2); occlusion_shader.set_uniform("randomization_sampler", 3); occlusion_shader.set_uniform("ao_radius", 0.05f); - occlusion_shader.set_uniform("random_vectors", random_vectors.data(), random_vectors.size()); + occlusion_shader.set_uniform("random_vectors", random_vectors); bilateral_shader.use(); bilateral_shader.set_uniform("color_sampler", 0); diff --git a/src/glk/effects/screen_space_lighting.cpp b/src/glk/effects/screen_space_lighting.cpp index 92634886..a3c85064 100644 --- a/src/glk/effects/screen_space_lighting.cpp +++ b/src/glk/effects/screen_space_lighting.cpp @@ -335,9 +335,9 @@ void ScreenSpaceLighting::draw( lighting_shader.set_uniform("num_lights", static_cast(light_pos.size())); lighting_shader.set_uniform("light_directional", light_directional); lighting_shader.set_uniform("light_range", light_range); - lighting_shader.set_uniform("light_attenuation", light_attenuation.data(), light_attenuation.size()); - lighting_shader.set_uniform("light_pos", light_pos.data(), light_pos.size()); - lighting_shader.set_uniform("light_color", light_color.data(), light_color.size()); + lighting_shader.set_uniform("light_attenuation", light_attenuation); + lighting_shader.set_uniform("light_pos", light_pos); + lighting_shader.set_uniform("light_color", light_color); } if (splatting) { diff --git a/src/glk/effects/screen_space_splatting.cpp b/src/glk/effects/screen_space_splatting.cpp index 22f9f434..c63e1887 100644 --- a/src/glk/effects/screen_space_splatting.cpp +++ b/src/glk/effects/screen_space_splatting.cpp @@ -24,84 +24,86 @@ ScreenSpaceSplatting::ScreenSpaceSplatting(const Eigen::Vector2i& size) { query.reset(new glk::Query()); - if(!texture_shader.init(get_data_path() + "/shader/texture.vert", get_data_path() + "/shader/texture.frag")) { + if (!texture_shader.init(get_data_path() + "/shader/texture.vert", get_data_path() + "/shader/texture.frag")) { abort(); } - if(!position_shader.init(get_data_path() + "/shader/texture.vert", get_data_path() + "/shader/splat/calc_pos.frag")) { + if (!position_shader.init(get_data_path() + "/shader/texture.vert", get_data_path() + "/shader/splat/calc_pos.frag")) { abort(); } - if(!white_shader.init(get_data_path() + "/shader/splat/tex2screen.vert", get_data_path() + "/shader/splat/one_float.frag")) { + if (!white_shader.init(get_data_path() + "/shader/splat/tex2screen.vert", get_data_path() + "/shader/splat/one_float.frag")) { abort(); } - if(!increment_shader.init(get_data_path() + "/shader/splat/tex2screen.vert", get_data_path() + "/shader/splat/one_float.frag")) { + if (!increment_shader.init(get_data_path() + "/shader/splat/tex2screen.vert", get_data_path() + "/shader/splat/one_float.frag")) { abort(); } - if(!point_extraction_shader.attach_source(get_data_path() + "/shader/splat/extract_points.vert", GL_VERTEX_SHADER) || - !point_extraction_shader.attach_source(get_data_path() + "/shader/splat/extract_points.geom", GL_GEOMETRY_SHADER) || - !point_extraction_shader.attach_source(get_data_path() + "/shader/splat/extract_points.frag", GL_FRAGMENT_SHADER) || - !point_extraction_shader.add_feedback_varying("vert_out") || !point_extraction_shader.link_program()) { + if ( + !point_extraction_shader.attach_source(get_data_path() + "/shader/splat/extract_points.vert", GL_VERTEX_SHADER) || + !point_extraction_shader.attach_source(get_data_path() + "/shader/splat/extract_points.geom", GL_GEOMETRY_SHADER) || + !point_extraction_shader.attach_source(get_data_path() + "/shader/splat/extract_points.frag", GL_FRAGMENT_SHADER) || + !point_extraction_shader.add_feedback_varying("vert_out") || !point_extraction_shader.link_program()) { abort(); } - if(!initial_radius_shader.init(get_data_path() + "/shader/splat/tex2screen.vert", get_data_path() + "/shader/splat/initial_radius.frag")) { + if (!initial_radius_shader.init(get_data_path() + "/shader/splat/tex2screen.vert", get_data_path() + "/shader/splat/initial_radius.frag")) { abort(); } - if(!distribution_shader.init(get_data_path() + "/shader/splat/distribution")) { + if (!distribution_shader.init(get_data_path() + "/shader/splat/distribution")) { abort(); } - if(!gathering_shader.init(get_data_path() + "/shader/splat/gathering")) { + if (!gathering_shader.init(get_data_path() + "/shader/splat/gathering")) { abort(); } - if(!bounds_update_shader.init(get_data_path() + "/shader/splat/tex2screen_test_finalized.vert", get_data_path() + "/shader/splat/update_bounds.frag")) { + if (!bounds_update_shader.init(get_data_path() + "/shader/splat/tex2screen_test_finalized.vert", get_data_path() + "/shader/splat/update_bounds.frag")) { abort(); } - if(!farthest_point_shader.init(get_data_path() + "/shader/splat/tex2screen.vert", get_data_path() + "/shader/splat/farthest_point.frag")) { + if (!farthest_point_shader.init(get_data_path() + "/shader/splat/tex2screen.vert", get_data_path() + "/shader/splat/farthest_point.frag")) { abort(); } - if(!radius_finalization_shader.init(get_data_path() + "/shader/splat/tex2screen.vert", get_data_path() + "/shader/splat/finalize_radius.frag")) { + if (!radius_finalization_shader.init(get_data_path() + "/shader/splat/tex2screen.vert", get_data_path() + "/shader/splat/finalize_radius.frag")) { abort(); } - if(!gaussian_gathering_shader.init(get_data_path() + "/shader/splat/gathering.vert", get_data_path() + "/shader/splat/gaussian_gathering.frag")) { + if (!gaussian_gathering_shader.init(get_data_path() + "/shader/splat/gathering.vert", get_data_path() + "/shader/splat/gaussian_gathering.frag")) { abort(); } - if(!gaussian_finalization_shader.attach_source(get_data_path() + "/shader/splat/tex2screen.vert", GL_VERTEX_SHADER) || - !gaussian_finalization_shader.attach_source(get_data_path() + "/shader/splat/gaussian_finalization.frag", GL_FRAGMENT_SHADER) || - !gaussian_finalization_shader.attach_source(get_data_path() + "/shader/splat/eigen.frag", GL_FRAGMENT_SHADER) || - !gaussian_finalization_shader.link_program()) { + if ( + !gaussian_finalization_shader.attach_source(get_data_path() + "/shader/splat/tex2screen.vert", GL_VERTEX_SHADER) || + !gaussian_finalization_shader.attach_source(get_data_path() + "/shader/splat/gaussian_finalization.frag", GL_FRAGMENT_SHADER) || + !gaussian_finalization_shader.attach_source(get_data_path() + "/shader/splat/eigen.frag", GL_FRAGMENT_SHADER) || !gaussian_finalization_shader.link_program()) { abort(); } - if(!splatting_first_shader.attach_source(get_data_path() + "/shader/splat/splat.vert", GL_VERTEX_SHADER) || - !splatting_first_shader.attach_source(get_data_path() + "/shader/splat/splat.geom", GL_GEOMETRY_SHADER) || - !splatting_first_shader.attach_source(get_data_path() + "/shader/splat/splat_first.frag", GL_FRAGMENT_SHADER) || - !splatting_first_shader.link_program()) { + if ( + !splatting_first_shader.attach_source(get_data_path() + "/shader/splat/splat.vert", GL_VERTEX_SHADER) || + !splatting_first_shader.attach_source(get_data_path() + "/shader/splat/splat.geom", GL_GEOMETRY_SHADER) || + !splatting_first_shader.attach_source(get_data_path() + "/shader/splat/splat_first.frag", GL_FRAGMENT_SHADER) || !splatting_first_shader.link_program()) { abort(); } - if(!splatting_second_shader.attach_source(get_data_path() + "/shader/splat/splat.vert", GL_VERTEX_SHADER) || - !splatting_second_shader.attach_source(get_data_path() + "/shader/splat/splat.geom", GL_GEOMETRY_SHADER) || - !splatting_second_shader.attach_source(get_data_path() + "/shader/splat/splat_second.frag", GL_FRAGMENT_SHADER) || - !splatting_second_shader.link_program()) { + if ( + !splatting_second_shader.attach_source(get_data_path() + "/shader/splat/splat.vert", GL_VERTEX_SHADER) || + !splatting_second_shader.attach_source(get_data_path() + "/shader/splat/splat.geom", GL_GEOMETRY_SHADER) || + !splatting_second_shader.attach_source(get_data_path() + "/shader/splat/splat_second.frag", GL_FRAGMENT_SHADER) || !splatting_second_shader.link_program()) { abort(); } - if(!splatting_finalization_shader.init(get_data_path() + "/shader/texture.vert", get_data_path() + "/shader/splat/finalize_splat.frag")) { + if (!splatting_finalization_shader.init(get_data_path() + "/shader/texture.vert", get_data_path() + "/shader/splat/finalize_splat.frag")) { abort(); } - if(!debug_shader.attach_source(get_data_path() + "/shader/texture.vert", GL_VERTEX_SHADER) || !debug_shader.attach_source(get_data_path() + "/shader/splat/debug.frag", GL_FRAGMENT_SHADER) || - !debug_shader.link_program()) { + if ( + !debug_shader.attach_source(get_data_path() + "/shader/texture.vert", GL_VERTEX_SHADER) || + !debug_shader.attach_source(get_data_path() + "/shader/splat/debug.frag", GL_FRAGMENT_SHADER) || !debug_shader.link_program()) { abort(); } @@ -197,9 +199,9 @@ void ScreenSpaceSplatting::set_size(const Eigen::Vector2i& size) { position_buffer.reset(new glk::FrameBuffer(size, 0, true)); position_buffer->add_color_buffer(0, GL_RGBA32F, GL_RGB, GL_FLOAT).set_filer_mode(GL_NEAREST); - std::vector> sampling_points; - for(int y = 0; y < size[1]; y += steps * subsample_steps) { - for(int x = 0; x < size[0]; x += steps * subsample_steps) { + std::vector sampling_points; + for (int y = 0; y < size[1]; y += steps * subsample_steps) { + for (int x = 0; x < size[0]; x += steps * subsample_steps) { Eigen::Array3d pt = step_size * Eigen::Array3d(x, y, 0) + step_size * 0.5; sampling_points.push_back(pt.cast()); } @@ -398,7 +400,7 @@ void ScreenSpaceSplatting::estimate_knn_radius() { glDepthMask(GL_FALSE); // ping pong - for(int i = 0; i < num_iterations; i++) { + for (int i = 0; i < num_iterations; i++) { auto& radius_buffer_front = i % 2 == 0 ? radius_buffer_ping : radius_buffer_pong; auto& radius_buffer_back = i % 2 == 0 ? radius_buffer_pong : radius_buffer_ping; @@ -629,7 +631,12 @@ void ScreenSpaceSplatting::render_splatting(GLProfiler& prof, const glk::Texture glDisable(GL_BLEND); } -void ScreenSpaceSplatting::draw(const TextureRenderer& renderer, const glk::Texture& color_texture, const glk::Texture& depth_texture, const TextureRendererInput::Ptr& input, glk::FrameBuffer* frame_buffer) { +void ScreenSpaceSplatting::draw( + const TextureRenderer& renderer, + const glk::Texture& color_texture, + const glk::Texture& depth_texture, + const TextureRendererInput::Ptr& input, + glk::FrameBuffer* frame_buffer) { glDisable(GL_DEPTH_TEST); color_texture.set_filer_mode(GL_NEAREST); @@ -638,7 +645,7 @@ void ScreenSpaceSplatting::draw(const TextureRenderer& renderer, const glk::Text // uniform variables const auto view_matrix = input->get("view_matrix"); const auto projection_matrix = input->get("projection_matrix"); - if(!view_matrix || !projection_matrix) { + if (!view_matrix || !projection_matrix) { std::cerr << bold_red << "error: view and projection matrices must be set" << reset << std::endl; return; } @@ -762,7 +769,5 @@ void ScreenSpaceSplatting::draw(const TextureRenderer& renderer, const glk::Text frame_buffer->unbind(); } */ - - } } // namespace glk \ No newline at end of file diff --git a/src/glk/glsl_shader.cpp b/src/glk/glsl_shader.cpp index 5b1554ff..37093429 100644 --- a/src/glk/glsl_shader.cpp +++ b/src/glk/glsl_shader.cpp @@ -128,8 +128,15 @@ bool GLSLShader::link_program() { GLenum type = 0; glGetActiveAttrib(shader_program, i, sizeof(name), &len, &size, &type, name); std::string name_str(name, len); + + // if variable is an array and name_str ends with "[0]", remove it + if (name_str.length() > 3 && name_str.substr(name_str.length() - 3) == "[0]") { + name_str = name_str.substr(0, name_str.length() - 3); + } + GLint location = glGetAttribLocation(shader_program, name_str.c_str()); + // std::cerr << bold_green << "info : found attrib " << name_str << " at location " << location << reset << std::endl; attrib_cache.emplace_back(glk::hash(name_str), location); } @@ -143,8 +150,15 @@ bool GLSLShader::link_program() { GLenum type = 0; glGetActiveUniform(shader_program, i, sizeof(name), &len, &size, &type, name); std::string name_str(name, len); + + // if variable is an array and name_str ends with "[0]", remove it + if (name_str.length() > 3 && name_str.substr(name_str.length() - 3) == "[0]") { + name_str = name_str.substr(0, name_str.length() - 3); + } + GLint location = glGetUniformLocation(shader_program, name_str.c_str()); + // std::cerr << bold_green << "info : found uniform " << name_str << " at location " << location << reset << std::endl; uniform_cache.emplace_back(glk::hash(name_str), location); } @@ -169,76 +183,86 @@ bool GLSLShader::init(const std::vector& vertex_shader_paths, const return link_program(); } -GLint GLSLShader::attrib(std::uint64_t name) const { +GLint GLSLShader::attrib(std::uint64_t name, const char* debug_msg) { auto found = std::find_if(attrib_cache.begin(), attrib_cache.end(), [&name](const auto& pair) { return pair.first == name; }); if (found != attrib_cache.end()) { return found->second; } else { - return -1; + // std::cerr << bold_yellow << "warning : attrib " << (debug_msg ? debug_msg : "N/A") << " (" << name << ")" << " not found" << reset << std::endl; } + + attrib_cache.emplace_back(name, -1); + return -1; } -GLint GLSLShader::attrib(const std::string& name) const { - return attrib(glk::hash(name)); +GLint GLSLShader::attrib(const std::string& name) { + return attrib(glk::hash(name), name.c_str()); } -GLint GLSLShader::uniform(std::uint64_t name) const { +GLint GLSLShader::uniform(std::uint64_t name, const char* debug_msg) { auto found = std::find_if(uniform_cache.begin(), uniform_cache.end(), [&name](const auto& pair) { return pair.first == name; }); if (found != uniform_cache.end()) { return found->second; } else { - return -1; + // std::cerr << bold_yellow << "warning : uniform " << (debug_msg ? debug_msg : "N/A") << " (" << name << ")" << " not found" << reset << std::endl; } + + uniform_cache.emplace_back(name, -1); + return -1; } -GLint GLSLShader::uniform(const std::string& name) const { - return uniform(glk::hash(name)); +GLint GLSLShader::uniform(const std::string& name) { + return uniform(glk::hash(name), name.c_str()); } -GLint GLSLShader::subroutine(GLenum shader_type, std::uint64_t name) const { +GLint GLSLShader::subroutine(GLenum shader_type, std::uint64_t name, const char* debug_msg) { auto found = std::find_if(subroutine_cache.begin(), subroutine_cache.end(), [&name](const auto& pair) { return pair.first == name; }); if (found != subroutine_cache.end()) { return found->second; } else { - return -1; + // std::cerr << bold_yellow << "warning : subroutine " << (debug_msg ? debug_msg : "N/A") << " (" << name << ")" << " not found" << reset << std::endl; } + + subroutine_cache.emplace_back(name, -1); + return -1; } GLint GLSLShader::subroutine(GLenum shader_type, const std::string& name) { const std::uint64_t h = glk::hash(name); - GLint id = subroutine(shader_type, h); + GLint id = subroutine(shader_type, h, name.c_str()); if (id >= -1) { return id; } id = glGetSubroutineIndex(shader_program, shader_type, name.c_str()); if (id == -1) { - std::cerr << bold_yellow << "warning : subroutine " << name << " not found" << reset << std::endl; + // std::cerr << bold_yellow << "warning : subroutine " << name << " not found" << reset << std::endl; } subroutine_cache.emplace_back(h, id); return id; } -GLint GLSLShader::subroutine_uniform(GLenum shader_type, std::uint64_t name) const { +GLint GLSLShader::subroutine_uniform(GLenum shader_type, std::uint64_t name, const char* debug_msg) { auto found = std::find_if(uniform_cache.begin(), uniform_cache.end(), [&name](const auto& pair) { return pair.first == name; }); if (found != uniform_cache.end()) { return found->second; } else { + // std::cerr << bold_yellow << "warning : subroutine uniform " << (debug_msg ? debug_msg : "N/A") << " (" << name << ")" << " not found" << reset << std::endl; return -1; } } GLint GLSLShader::subroutine_uniform(GLenum shader_type, const std::string& name) { const std::uint64_t h = glk::hash(name); - GLint id = subroutine_uniform(shader_type, h); + GLint id = subroutine_uniform(shader_type, h, name.c_str()); if (id >= -1) { return id; } id = glGetSubroutineUniformLocation(shader_program, shader_type, name.c_str()); if (id == -1) { - std::cerr << bold_yellow << "warning : subroutine uniform " << name << " not found" << reset << std::endl; + // std::cerr << bold_yellow << "warning : subroutine uniform " << name << " not found" << reset << std::endl; } uniform_cache.emplace_back(h, id); @@ -417,139 +441,142 @@ Eigen::Matrix4f GLSLShader::get_uniform_matrix4f(const std::string& name) { return mat; } -void GLSLShader::set_uniform(std::uint64_t name, int value) { - glUniform1i(uniform(name), value); +void GLSLShader::set_uniform(std::uint64_t name, int value, const char* debug_msg) { + glUniform1i(uniform(name, debug_msg), value); set_uniform_cache(name, value); } void GLSLShader::set_uniform(const std::string& name, int value) { - return set_uniform(glk::hash(name), value); + return set_uniform(glk::hash(name), value, name.c_str()); } -void GLSLShader::set_uniform(std::uint64_t name, float value) { - glUniform1f(uniform(name), value); +void GLSLShader::set_uniform(std::uint64_t name, float value, const char* debug_msg) { + glUniform1f(uniform(name, debug_msg), value); set_uniform_cache(name, value); } void GLSLShader::set_uniform(const std::string& name, float value) { - return set_uniform(glk::hash(name), value); + return set_uniform(glk::hash(name), value, name.c_str()); } -void GLSLShader::set_uniform(std::uint64_t name, const Eigen::Vector2f& vector) { - glUniform2fv(uniform(name), 1, vector.data()); +void GLSLShader::set_uniform(std::uint64_t name, const Eigen::Vector2f& vector, const char* debug_msg) { + glUniform2fv(uniform(name, debug_msg), 1, vector.data()); set_uniform_cache(name, vector); } void GLSLShader::set_uniform(const std::string& name, const Eigen::Vector2f& vector) { - return set_uniform(glk::hash(name), vector); + return set_uniform(glk::hash(name), vector, name.c_str()); } -void GLSLShader::set_uniform(std::uint64_t name, const Eigen::Vector3f& vector) { - glUniform3fv(uniform(name), 1, vector.data()); +void GLSLShader::set_uniform(std::uint64_t name, const Eigen::Vector3f& vector, const char* debug_msg) { + glUniform3fv(uniform(name, debug_msg), 1, vector.data()); set_uniform_cache(name, vector); } void GLSLShader::set_uniform(const std::string& name, const Eigen::Vector3f& vector) { - return set_uniform(glk::hash(name), vector); + return set_uniform(glk::hash(name), vector, name.c_str()); } -void GLSLShader::set_uniform(std::uint64_t name, const Eigen::Vector4f& vector) { - glUniform4fv(uniform(name), 1, vector.data()); +void GLSLShader::set_uniform(std::uint64_t name, const Eigen::Vector4f& vector, const char* debug_msg) { + glUniform4fv(uniform(name, debug_msg), 1, vector.data()); set_uniform_cache(name, vector); } void GLSLShader::set_uniform(const std::string& name, const Eigen::Vector4f& vector) { - return set_uniform(glk::hash(name), vector); + return set_uniform(glk::hash(name), vector, name.c_str()); } -void GLSLShader::set_uniform(std::uint64_t name, const Eigen::Vector2i& vector) { - glUniform2iv(uniform(name), 1, vector.data()); +void GLSLShader::set_uniform(std::uint64_t name, const Eigen::Vector2i& vector, const char* debug_msg) { + glUniform2iv(uniform(name, debug_msg), 1, vector.data()); set_uniform_cache(name, vector); } void GLSLShader::set_uniform(const std::string& name, const Eigen::Vector2i& vector) { - return set_uniform(glk::hash(name), vector); + return set_uniform(glk::hash(name), vector, name.c_str()); } -void GLSLShader::set_uniform(std::uint64_t name, const Eigen::Vector3i& vector) { - glUniform3iv(uniform(name), 1, vector.data()); +void GLSLShader::set_uniform(std::uint64_t name, const Eigen::Vector3i& vector, const char* debug_msg) { + glUniform3iv(uniform(name, debug_msg), 1, vector.data()); set_uniform_cache(name, vector); } void GLSLShader::set_uniform(const std::string& name, const Eigen::Vector3i& vector) { - return set_uniform(glk::hash(name), vector); + return set_uniform(glk::hash(name), vector, name.c_str()); } -void GLSLShader::set_uniform(std::uint64_t name, const Eigen::Vector4i& vector) { - glUniform4iv(uniform(name), 1, vector.data()); +void GLSLShader::set_uniform(std::uint64_t name, const Eigen::Vector4i& vector, const char* debug_msg) { + glUniform4iv(uniform(name, debug_msg), 1, vector.data()); set_uniform_cache(name, vector); } void GLSLShader::set_uniform(const std::string& name, const Eigen::Vector4i& vector) { - return set_uniform(glk::hash(name), vector); + return set_uniform(glk::hash(name), vector, name.c_str()); } -void GLSLShader::set_uniform(std::uint64_t name, const Eigen::Matrix4f& matrix) { - glUniformMatrix4fv(uniform(name), 1, GL_FALSE, matrix.data()); +void GLSLShader::set_uniform(std::uint64_t name, const Eigen::Matrix4f& matrix, const char* debug_msg) { + GLint loc = uniform(name, debug_msg); + if (loc >= 0) { + glUniformMatrix4fv(loc, 1, GL_FALSE, matrix.data()); + } set_uniform_cache(name, matrix); } void GLSLShader::set_uniform(const std::string& name, const Eigen::Matrix4f& matrix) { - return set_uniform(glk::hash(name), matrix); + return set_uniform(glk::hash(name), matrix, name.c_str()); } -void GLSLShader::set_uniform(std::uint64_t name, const std::vector& vectors) { - glUniform1iv(uniform(name), vectors.size(), vectors.data()); +void GLSLShader::set_uniform(std::uint64_t name, const std::vector& vectors, const char* debug_msg) { + glUniform1iv(uniform(name, debug_msg), vectors.size(), vectors.data()); set_uniform_cache(name, vectors); } void GLSLShader::set_uniform(const std::string& name, const std::vector& vectors) { - return set_uniform(glk::hash(name), vectors); + return set_uniform(glk::hash(name), vectors, name.c_str()); } -void GLSLShader::set_uniform(std::uint64_t name, const std::vector& vectors) { - glUniform1fv(uniform(name), vectors.size(), vectors.data()); +void GLSLShader::set_uniform(std::uint64_t name, const std::vector& vectors, const char* debug_msg) { + glUniform1fv(uniform(name, debug_msg), vectors.size(), vectors.data()); set_uniform_cache(name, vectors); } void GLSLShader::set_uniform(const std::string& name, const std::vector& vectors) { - return set_uniform(glk::hash(name), vectors); + return set_uniform(glk::hash(name), vectors, name.c_str()); } -void GLSLShader::set_uniform(std::uint64_t name, const Eigen::Vector2f* vectors, size_t count) { - glUniform2fv(uniform(name), count, vectors[0].data()); +void GLSLShader::set_uniform(std::uint64_t name, const std::vector& vectors, const char* debug_msg) { + glUniform2fv(uniform(name, debug_msg), vectors.size(), vectors[0].data()); set_uniform_cache(name, vectors); } -void GLSLShader::set_uniform(const std::string& name, const Eigen::Vector2f* vectors, size_t count) { - return set_uniform(glk::hash(name), vectors, count); +void GLSLShader::set_uniform(const std::string& name, const std::vector& vectors) { + return set_uniform(glk::hash(name), vectors, name.c_str()); } -void GLSLShader::set_uniform(std::uint64_t name, const Eigen::Vector3f* vectors, size_t count) { - glUniform3fv(uniform(name), count, vectors[0].data()); +void GLSLShader::set_uniform(std::uint64_t name, const std::vector& vectors, const char* debug_msg) { + glUniform3fv(uniform(name, debug_msg), vectors.size(), vectors[0].data()); set_uniform_cache(name, vectors); } -void GLSLShader::set_uniform(const std::string& name, const Eigen::Vector3f* vectors, size_t count) { - return set_uniform(glk::hash(name), vectors, count); +void GLSLShader::set_uniform(const std::string& name, const std::vector& vectors) { + return set_uniform(glk::hash(name), vectors, name.c_str()); } -void GLSLShader::set_uniform(std::uint64_t name, const Eigen::Vector4f* vectors, size_t count) { - glUniform4fv(uniform(name), count, vectors[0].data()); +void GLSLShader::set_uniform(std::uint64_t name, const std::vector& vectors, const char* debug_msg) { + glUniform4fv(uniform(name, debug_msg), vectors.size(), vectors[0].data()); set_uniform_cache(name, vectors); } -void GLSLShader::set_uniform(const std::string& name, const Eigen::Vector4f* vectors, size_t count) { - return set_uniform(glk::hash(name), vectors, count); +void GLSLShader::set_uniform(const std::string& name, const std::vector& vectors) { + return set_uniform(glk::hash(name), vectors, name.c_str()); } -void GLSLShader::set_uniform(std::uint64_t name, const Eigen::Matrix4d& matrix_) { +void GLSLShader::set_uniform(std::uint64_t name, const Eigen::Matrix4d& matrix_, const char* debug_msg) { Eigen::Matrix4f matrix = matrix_.cast(); - glUniformMatrix4fv(uniform(name), 1, GL_FALSE, matrix.data()); + glUniformMatrix4fv(uniform(name, debug_msg), 1, GL_FALSE, matrix.data()); } void GLSLShader::set_uniform(const std::string& name, const Eigen::Matrix4d& matrix_) { - set_uniform(glk::hash(name), matrix_); + set_uniform(glk::hash(name), matrix_, name.c_str()); } } // namespace glk diff --git a/src/glk/gridmap.cpp b/src/glk/gridmap.cpp index 8de216f8..186c8d8c 100644 --- a/src/glk/gridmap.cpp +++ b/src/glk/gridmap.cpp @@ -101,8 +101,8 @@ GridMap::~GridMap() { } void GridMap::init_vao(double resolution, int width, int height) { - std::vector> vertices; - std::vector> texcoords; + std::vector vertices; + std::vector texcoords; vertices.push_back(Eigen::Vector3f(-resolution * width / 2, -resolution * height / 2, 0.0f)); vertices.push_back(Eigen::Vector3f(resolution * width / 2, -resolution * height / 2, 0.0f)); diff --git a/src/glk/lines.cpp b/src/glk/lines.cpp index ef749216..1ac1144a 100644 --- a/src/glk/lines.cpp +++ b/src/glk/lines.cpp @@ -11,15 +11,15 @@ Lines::Lines(float line_width, const Eigen::Vector3f* vertices_, const Eigen::Ve glGenVertexArrays(1, &vao); glBindVertexArray(vao); - std::vector> vertices; - std::vector> colors; - std::vector> infos; + std::vector vertices; + std::vector colors; + std::vector infos; if (!line_strip) { vertices.assign(vertices_, vertices_ + num_points); - if(colors_) { + if (colors_) { colors.assign(colors_, colors_ + num_points); } - if(infos_) { + if (infos_) { infos.assign(infos_, infos_ + num_points); } } else { @@ -41,7 +41,7 @@ Lines::Lines(float line_width, const Eigen::Vector3f* vertices_, const Eigen::Ve num_vertices = vertices.size(); - std::vector> vertices_ext(vertices.size() * 4); + std::vector vertices_ext(vertices.size() * 4); for (int i = 0; i < vertices.size(); i += 2) { Eigen::Vector3f direction = vertices[i + 1] - vertices[i]; Eigen::Vector3f axis = std::abs(direction.normalized().dot(Eigen::Vector3f::UnitZ())) < 0.9f ? Eigen::Vector3f::UnitZ() : Eigen::Vector3f::UnitX(); @@ -65,7 +65,7 @@ Lines::Lines(float line_width, const Eigen::Vector3f* vertices_, const Eigen::Ve glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertices_ext.size() * 3, vertices_ext.data(), GL_STATIC_DRAW); if (!colors.empty()) { - std::vector> colors_ext(colors.size() * 4); + std::vector colors_ext(colors.size() * 4); for (int i = 0; i < colors.size(); i += 2) { for (int j = 0; j < 4; j++) { colors_ext[i * 4 + j * 2] = colors[i]; @@ -78,7 +78,7 @@ Lines::Lines(float line_width, const Eigen::Vector3f* vertices_, const Eigen::Ve } if (!infos.empty()) { - std::vector> infos_ext(infos.size() * 4); + std::vector infos_ext(infos.size() * 4); for (int i = 0; i < infos.size(); i += 2) { for (int j = 0; j < 4; j++) { infos_ext[i * 4 + j * 2] = infos[i]; @@ -122,7 +122,8 @@ Lines::Lines(float line_width, const Eigen::Vector3f* vertices_, const Eigen::Ve Lines::Lines(float line_width, const Eigen::Vector3f* vertices, int num_points, bool line_strip) : Lines(line_width, vertices, nullptr, nullptr, num_points, line_strip) {} -Lines::Lines(float line_width, const Eigen::Vector3f* vertices, const Eigen::Vector4f* colors, int num_points, bool line_strip) : Lines(line_width, vertices, colors, nullptr, num_points, line_strip) {} +Lines::Lines(float line_width, const Eigen::Vector3f* vertices, const Eigen::Vector4f* colors, int num_points, bool line_strip) +: Lines(line_width, vertices, colors, nullptr, num_points, line_strip) {} Lines::~Lines() { glDeleteBuffers(1, &vbo); diff --git a/src/glk/point_correspondences.cpp b/src/glk/point_correspondences.cpp index b0f3e3f3..92b341cf 100644 --- a/src/glk/point_correspondences.cpp +++ b/src/glk/point_correspondences.cpp @@ -9,8 +9,8 @@ PointCorrespondences::PointCorrespondences( const pcl::shared_ptr>& source_cloud, const pcl::shared_ptr>& target_cloud, const pcl::CorrespondencesConstPtr& correspondences) { - std::vector> vertices(correspondences->size() * 2); - for(const auto& c: *correspondences) { + std::vector vertices(correspondences->size() * 2); + for (const auto& c : *correspondences) { vertices.push_back(source_cloud->at(c.index_query).getVector3fMap()); vertices.push_back(target_cloud->at(c.index_match).getVector3fMap()); } diff --git a/src/glk/pointcloud_buffer.cpp b/src/glk/pointcloud_buffer.cpp index 8c7432bf..14f09dab 100644 --- a/src/glk/pointcloud_buffer.cpp +++ b/src/glk/pointcloud_buffer.cpp @@ -97,7 +97,7 @@ void PointCloudBuffer::add_color(const Eigen::Vector4f* colors, int num_points) } void PointCloudBuffer::add_color(const Eigen::Vector4d* colors, int num_points) { - std::vector> colors_f(num_points); + std::vector colors_f(num_points); std::transform(colors, colors + num_points, colors_f.begin(), [](const Eigen::Vector4d& c) { return c.cast(); }); add_color(colors_f); } @@ -111,7 +111,7 @@ void PointCloudBuffer::add_color(const float* data, int stride, int num_points) } void PointCloudBuffer::add_intensity(glk::COLORMAP colormap, const float* data, int stride, int num_points, float scale) { - std::vector> colors(num_points); + std::vector colors(num_points); for (int i = 0; i < num_points; i++) { colors[i] = glk::colormapf(colormap, scale * data[(stride / sizeof(float)) * i]); } @@ -253,13 +253,13 @@ void PointCloudBuffer::update_points_with_indices(const Eigen::Vector4f* points, } void PointCloudBuffer::update_points_with_indices(const Eigen::Vector3d* points, const unsigned int* indices, int num_indices) { - std::vector> points_f(num_indices); + std::vector points_f(num_indices); std::transform(points, points + num_indices, points_f.begin(), [](const auto& p) { return p.template cast(); }); update_points_with_indices(points_f.data(), indices, num_indices); } void PointCloudBuffer::update_points_with_indices(const Eigen::Vector4d* points, const unsigned int* indices, int num_indices) { - std::vector> points_f(num_indices); + std::vector points_f(num_indices); std::transform(points, points + num_indices, points_f.begin(), [](const auto& p) { return p.template cast(); }); update_points_with_indices(points_f.data(), indices, num_indices); } @@ -279,7 +279,7 @@ void PointCloudBuffer::update_color_with_indices(const Eigen::Vector4f* colors, } void PointCloudBuffer::update_color_with_indices(const Eigen::Vector4d* colors, const unsigned int* indices, int num_indices) { - std::vector> colors_f(num_indices); + std::vector colors_f(num_indices); std::transform(colors, colors + num_indices, colors_f.begin(), [](const Eigen::Vector4d& c) { return c.cast(); }); update_color_with_indices(colors_f.data(), indices, num_indices); } diff --git a/src/glk/pointnormals_buffer.cpp b/src/glk/pointnormals_buffer.cpp index c7bbd786..b2836279 100644 --- a/src/glk/pointnormals_buffer.cpp +++ b/src/glk/pointnormals_buffer.cpp @@ -5,7 +5,7 @@ namespace glk { PointNormalsBuffer::PointNormalsBuffer(const float* vertices, size_t vertex_stride, const float* normals, size_t normal_stride, int num_points, double normal_length) { - std::vector> lines(num_points * 2); + std::vector lines(num_points * 2); for (int i = 0; i < num_points; i++) { lines[i * 2] = Eigen::Map(vertices + i * vertex_stride / sizeof(float)); @@ -22,15 +22,7 @@ PointNormalsBuffer::PointNormalsBuffer( double normal_length) : PointNormalsBuffer(vertices[0].data(), sizeof(Eigen::Vector3f), normals[0].data(), sizeof(Eigen::Vector3f), vertices.size(), normal_length) {} -template PointNormalsBuffer::PointNormalsBuffer( - const std::vector>& vertices, - const std::vector>& normals, - double normal_length); - -template PointNormalsBuffer::PointNormalsBuffer( - const std::vector>& vertices, - const std::vector>& normals, - double normal_length); +template PointNormalsBuffer::PointNormalsBuffer(const std::vector& vertices, const std::vector& normals, double normal_length); PointNormalsBuffer::~PointNormalsBuffer() {} diff --git a/src/glk/texture_renderer.cpp b/src/glk/texture_renderer.cpp index a23a5763..c7aeb644 100644 --- a/src/glk/texture_renderer.cpp +++ b/src/glk/texture_renderer.cpp @@ -8,7 +8,7 @@ namespace glk { TextureRenderer::TextureRenderer() { plain_effect = std::make_shared(); - std::vector> vertices = { + std::vector vertices = { Eigen::Vector3f(-1.0f, -1.0f, 0.0f), Eigen::Vector3f(1.0f, -1.0f, 0.0f), Eigen::Vector3f(-1.0f, 1.0f, 0.0f), diff --git a/src/glk/trajectory.cpp b/src/glk/trajectory.cpp index 1f5eaee6..fa7d7fe7 100644 --- a/src/glk/trajectory.cpp +++ b/src/glk/trajectory.cpp @@ -7,9 +7,9 @@ namespace glk { -Trajectory::Trajectory(const std::vector>& trajectory) : trajectory(trajectory) { - std::vector> line_vertices; - for(int i = 1; i < trajectory.size(); i++) { +Trajectory::Trajectory(const std::vector& trajectory) : trajectory(trajectory) { + std::vector line_vertices; + for (int i = 1; i < trajectory.size(); i++) { line_vertices.push_back(trajectory[i - 1].translation()); line_vertices.push_back(trajectory[i].translation()); } @@ -22,8 +22,8 @@ Trajectory::Trajectory(int num_frames, const std::function> line_vertices; - for(int i = 1; i < trajectory.size(); i++) { + std::vector line_vertices; + for (int i = 1; i < trajectory.size(); i++) { line_vertices.push_back(trajectory[i - 1].translation()); line_vertices.push_back(trajectory[i].translation()); } @@ -34,7 +34,7 @@ Trajectory::~Trajectory() {} void Trajectory::draw(glk::GLSLShader& shader) const { shader.set_uniform("color_mode", 2); - for(int i = 0; i < trajectory.size(); i++) { + for (int i = 0; i < trajectory.size(); i++) { shader.set_uniform("model_matrix", trajectory[i].matrix()); glk::Primitives::coordinate_system()->draw(shader); } diff --git a/src/guik/gl_canvas.cpp b/src/guik/gl_canvas.cpp index 5c115fe1..6de5f3ea 100644 --- a/src/guik/gl_canvas.cpp +++ b/src/guik/gl_canvas.cpp @@ -538,7 +538,7 @@ Eigen::Vector4i GLCanvas::pick_info(const Eigen::Vector2i& p, int window) const std::vector pixels = frame_buffer->color(info_buffer_id).read_pixels(GL_RGBA_INTEGER, GL_INT, 4); - std::vector> ps; + std::vector ps; for (int i = -window; i <= window; i++) { for (int j = -window; j <= window; j++) { @@ -574,7 +574,7 @@ float GLCanvas::pick_depth(const Eigen::Vector2i& p, int window) const { std::vector pixels = frame_buffer->depth().read_pixels(GL_DEPTH_COMPONENT, GL_FLOAT, 1); - std::vector> ps; + std::vector ps; for (int i = -window; i <= window; i++) { for (int j = -window; j <= window; j++) { diff --git a/src/guik/hovered_drawings.cpp b/src/guik/hovered_drawings.cpp index 5993fa36..7d75dfce 100644 --- a/src/guik/hovered_drawings.cpp +++ b/src/guik/hovered_drawings.cpp @@ -27,7 +27,7 @@ struct HoveredDrawingsData { std::vector> drawable_drawings; std::vector removed_drawing_ids; - std::vector> pts; + std::vector pts; std::vector> drawings; }; @@ -185,7 +185,7 @@ void HoveredDrawings::clear() { std::function HoveredDrawings::create_callback() { return [data = data] { - std::vector> all_pts; + std::vector all_pts; std::vector> all_drawings; all_pts.reserve(data->pts.size() + data->drawable_names.size()); diff --git a/src/python/glk.cpp b/src/python/glk.cpp index ee541ebc..b0e96c0d 100644 --- a/src/python/glk.cpp +++ b/src/python/glk.cpp @@ -160,7 +160,7 @@ void define_glk(py::module_& m) { } if (c.size()) { - std::vector> colors(size, Eigen::Vector4f::Zero()); + std::vector colors(size, Eigen::Vector4f::Zero()); for (int i = 0; i < size && i < c.size(); i++) { colors[i] = glk::colormapf(glk::COLORMAP::TURBO, c[i]); } @@ -180,14 +180,7 @@ void define_glk(py::module_& m) { // glk::Lines py::class_>(glk_, "Lines") - .def( - py::init< - float, - const std::vector>&, - const std::vector>&>(), - py::arg("thickness"), - py::arg("vertices"), - py::arg("colors")) + .def(py::init&, const std::vector&>(), py::arg("thickness"), py::arg("vertices"), py::arg("colors")) .def( py::init([]( float thickness, @@ -203,8 +196,8 @@ void define_glk(py::module_& m) { throw std::runtime_error("vertices and colors must have the same number of rows"); } - std::vector> vertices_vec(vertices.shape(0)); - std::vector> colors_vec(colors.shape(0)); + std::vector vertices_vec(vertices.shape(0)); + std::vector colors_vec(colors.shape(0)); for (int i = 0; i < vertices.shape(0); i++) { vertices_vec[i] = Eigen::Vector3f(vertices.at(i, 0), vertices.at(i, 1), vertices.at(i, 2)); @@ -230,7 +223,7 @@ void define_glk(py::module_& m) { size = std::min(size, z.size()); } - std::vector> vertices((size - 1) * 2, Eigen::Vector3f::Zero()); + std::vector vertices((size - 1) * 2, Eigen::Vector3f::Zero()); for (int i = 1; i < size && i < x.size(); i++) { vertices[(i - 1) * 2].x() = x[i - 1]; vertices[(i - 1) * 2 + 1].x() = x[i]; @@ -246,7 +239,7 @@ void define_glk(py::module_& m) { vertices[(i - 1) * 2 + 1].z() = z[i]; } - std::vector> colors; + std::vector colors; if (c.size()) { colors.reserve((size - 1) * 2); for (int i = 1; i < size && i < c.size(); i++) { @@ -276,13 +269,11 @@ void define_glk(py::module_& m) { return std::make_shared(points.data(), sizeof(float) * points.shape(1), points.shape(0)); }), py::arg("points")) - .def(py::init>&>()) - .def( - py::init([](const std::vector>& points) { return std::make_shared(points); }), - py::arg("points")) + .def(py::init&>()) + .def(py::init([](const std::vector& points) { return std::make_shared(points); }), py::arg("points")) .def( "add_normals", - [](glk::PointCloudBuffer& buffer, const std::vector>& normals) { buffer.add_normals(normals); }, + [](glk::PointCloudBuffer& buffer, const std::vector& normals) { buffer.add_normals(normals); }, py::arg("normals")) .def( "add_normals", @@ -291,7 +282,7 @@ void define_glk(py::module_& m) { throw std::runtime_error("invalid normals array"); } - std::vector> normals_vec(normals.shape(0)); + std::vector normals_vec(normals.shape(0)); for (int i = 0; i < normals.shape(0); i++) { normals_vec[i] = Eigen::Vector3f(normals.at(i, 0), normals.at(i, 1), normals.at(i, 2)); } @@ -300,15 +291,15 @@ void define_glk(py::module_& m) { py::arg("normals")) .def( "add_color", - [](glk::PointCloudBuffer& buffer, const std::vector>& colors) { - std::vector> colors_(colors.size()); + [](glk::PointCloudBuffer& buffer, const std::vector& colors) { + std::vector colors_(colors.size()); std::transform(colors.begin(), colors.end(), colors_.begin(), [](const Eigen::Vector3f& c) { return Eigen::Vector4f(c.x(), c.y(), c.z(), 1.0f); }); buffer.add_color(colors_); }, py::arg("colors")) .def( "add_color", - [](glk::PointCloudBuffer& buffer, const std::vector>& colors) { buffer.add_color(colors); }, + [](glk::PointCloudBuffer& buffer, const std::vector& colors) { buffer.add_color(colors); }, py::arg("colors")) .def( "add_color", @@ -317,7 +308,7 @@ void define_glk(py::module_& m) { throw std::runtime_error("invalid colors array"); } - std::vector> colors_vec(colors.shape(0)); + std::vector colors_vec(colors.shape(0)); for (int i = 0; i < colors.shape(0); i++) { colors_vec[i] = Eigen::Vector4f(colors.at(i, 0), colors.at(i, 1), colors.at(i, 2), colors.at(i, 3)); } From 5213f74a7462e14bafb5bdc1d3f423b0b9373e35 Mon Sep 17 00:00:00 2001 From: "k.koide" Date: Tue, 30 Dec 2025 12:41:02 +0900 Subject: [PATCH 15/40] support int and float arrays --- include/guik/viewer/shader_setting.hpp | 76 ++++++++++++++++++-------- src/guik/viewer/shader_setting.cpp | 14 ++--- 2 files changed, 61 insertions(+), 29 deletions(-) diff --git a/include/guik/viewer/shader_setting.hpp b/include/guik/viewer/shader_setting.hpp index 89bd88c7..cb350858 100644 --- a/include/guik/viewer/shader_setting.hpp +++ b/include/guik/viewer/shader_setting.hpp @@ -37,7 +37,7 @@ struct PointShapeMode { }; /// @brief Data type of shader parameter. -enum class ShaderDataType { INT = 0, INT2, INT3, INT4, FLOAT, FLOAT2, FLOAT3, FLOAT4, MATRIX4, INVALID }; +enum class ShaderDataType { INT = 0, INT2, INT3, INT4, FLOAT, FLOAT2, FLOAT3, FLOAT4, MATRIX4, INT_ARRAY, FLOAT_ARRAY, INVALID }; /// @brief Deduce shader data type from C++ type. template @@ -60,6 +60,10 @@ ShaderDataType deduce_data_type() { return ShaderDataType::FLOAT4; } else if constexpr (std::is_same::value) { return ShaderDataType::MATRIX4; + } else if constexpr (std::is_same>::value) { + return ShaderDataType::INT_ARRAY; + } else if constexpr (std::is_same>::value) { + return ShaderDataType::FLOAT_ARRAY; } else { return ShaderDataType::INVALID; } @@ -76,7 +80,7 @@ struct ShaderParameter { template ShaderParameter(std::uint64_t name, const T& v) : type(deduce_data_type()), name(name) { - value() = v; + set_value(v); } /// @brief Check if the parameter is valid. @@ -91,53 +95,81 @@ struct ShaderParameter { /// @brief Get the parameter value. template - T& value() { + T get_value() const { if (type != deduce_data_type()) { std::cerr << "error: type mismatch when getting shader parameter " << name << std::endl; abort(); } - return *reinterpret_cast(&mat4f); + + if constexpr (std::is_same>::value || std::is_same>::value) { + const int* ptr = reinterpret_cast(&mat4f); + int num_data = ptr[0]; + + T v(num_data); + memcpy(v.data(), &ptr[1], sizeof(typename T::value_type) * num_data); + return v; + } else { + return *reinterpret_cast(&mat4f); + } } /// @brief Get the parameter value. template - const T& value() const { + void set_value(const T& value) { if (type != deduce_data_type()) { std::cerr << "error: type mismatch when getting shader parameter " << name << std::endl; abort(); } - return *reinterpret_cast(&mat4f); + + if constexpr (std::is_same>::value || std::is_same>::value) { + if (value.size() > 15) { + std::cerr << "error: array size exceeds the maximum limit of 15 for shader parameter " << name << std::endl; + abort(); + } + + int* ptr = reinterpret_cast(&mat4f); + ptr[0] = static_cast(value.size()); + memcpy(&ptr[1], value.data(), sizeof(typename T::value_type) * value.size()); + } else { + *reinterpret_cast(&mat4f) = value; + } } /// @brief Set the parameter to the shader. void set(glk::GLSLShader& shader) const { switch (type) { case ShaderDataType::INT: - shader.set_uniform(name, value()); + shader.set_uniform(name, get_value()); break; case ShaderDataType::INT2: - shader.set_uniform(name, value()); + shader.set_uniform(name, get_value()); break; case ShaderDataType::INT3: - shader.set_uniform(name, value()); + shader.set_uniform(name, get_value()); break; case ShaderDataType::INT4: - shader.set_uniform(name, value()); + shader.set_uniform(name, get_value()); break; case ShaderDataType::FLOAT: - shader.set_uniform(name, value()); + shader.set_uniform(name, get_value()); break; case ShaderDataType::FLOAT2: - shader.set_uniform(name, value()); + shader.set_uniform(name, get_value()); break; case ShaderDataType::FLOAT3: - shader.set_uniform(name, value()); + shader.set_uniform(name, get_value()); break; case ShaderDataType::FLOAT4: - shader.set_uniform(name, value()); + shader.set_uniform(name, get_value()); break; case ShaderDataType::MATRIX4: - shader.set_uniform(name, value()); + shader.set_uniform(name, get_value()); + break; + case ShaderDataType::INT_ARRAY: + shader.set_uniform(name, get_value>()); + break; + case ShaderDataType::FLOAT_ARRAY: + shader.set_uniform(name, get_value>()); break; default: std::cerr << "error: invalid shader parameter type for " << name << std::endl; @@ -227,7 +259,7 @@ struct ShaderSetting { return std::nullopt; } - return param.value(); + return param.get_value(); } return std::nullopt; @@ -250,7 +282,7 @@ struct ShaderSetting { return std::nullopt; } - return param.value(); + return param.get_value(); } return std::nullopt; @@ -260,7 +292,7 @@ struct ShaderSetting { /// @param name Parameter name /// @return Parameter value template - const T& cast(const std::string& name_) const { + T cast(const std::string& name_) const { const std::uint64_t name = glk::hash(name_); for (const auto& param : params) { @@ -273,7 +305,7 @@ struct ShaderSetting { abort(); } - return param.value(); + return param.get_value(); } std::cerr << "error: " << name << " not found in the param list" << std::endl; @@ -372,7 +404,7 @@ struct ShaderSetting { Eigen::Matrix4f mat = (transform.template cast() * Eigen::Isometry3f::Identity()).matrix(); auto& p = params[2]; - p.value() = mat; + p.set_value(mat); return *this; } @@ -382,8 +414,8 @@ struct ShaderSetting { template ShaderSetting& transform(const Transform& transform) { auto& p = params[2]; - const Eigen::Matrix4f mat = (p.value() * transform.template cast()).matrix(); - p.value() = mat; + const Eigen::Matrix4f mat = (p.get_value() * transform.template cast()).matrix(); + p.set_value(mat); return *this; } diff --git a/src/guik/viewer/shader_setting.cpp b/src/guik/viewer/shader_setting.cpp index cc9d75f9..c4d26830 100644 --- a/src/guik/viewer/shader_setting.cpp +++ b/src/guik/viewer/shader_setting.cpp @@ -78,12 +78,12 @@ ShaderSetting& ShaderSetting::make_transparent() { float ShaderSetting::point_scale() const { auto& p = params[1]; - return p.value(); + return p.get_value(); } ShaderSetting& ShaderSetting::set_point_scale(float scaling) { auto& p = params[1]; - p.value() = scaling; + p.set_value(scaling); return *this; } @@ -148,28 +148,28 @@ ShaderSetting& ShaderSetting::remove_model_matrix() { int ShaderSetting::color_mode() const { const auto& p = params[0]; - return p.value(); + return p.get_value(); } ShaderSetting& ShaderSetting::set_color_mode(int color_mode) { auto& p = params[0]; - p.value() = color_mode; + p.set_value(color_mode); return *this; } Eigen::Matrix4f ShaderSetting::model_matrix() const { const auto& p = params[2]; - return p.value(); + return p.get_value(); } Eigen::Vector3f ShaderSetting::translation() const { const auto& p = params[2]; - return p.value().block<3, 1>(0, 3); + return p.get_value().block<3, 1>(0, 3); } Eigen::Matrix3f ShaderSetting::rotation() const { const auto& p = params[2]; - return p.value().block<3, 3>(0, 0); + return p.get_value().block<3, 3>(0, 0); } ShaderSetting& ShaderSetting::translate(float tx, float ty, float tz) { From 2e1e4068ae821adfeb91bb97b7f01cb1c335130f Mon Sep 17 00:00:00 2001 From: "k.koide" Date: Tue, 30 Dec 2025 13:34:02 +0900 Subject: [PATCH 16/40] add fullscreen --- include/guik/imgui_application.hpp | 1 + src/guik/imgui_application.cpp | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/include/guik/imgui_application.hpp b/include/guik/imgui_application.hpp index 24201b5b..91ce7a76 100644 --- a/include/guik/imgui_application.hpp +++ b/include/guik/imgui_application.hpp @@ -28,6 +28,7 @@ class Application { virtual void show_window(); virtual void hide_window(); virtual void maximize_window(); + virtual void fullscreen_window(); virtual void resize(const Eigen::Vector2i& size); void set_title(const std::string& title); diff --git a/src/guik/imgui_application.cpp b/src/guik/imgui_application.cpp index 2992e61d..2dac2b58 100644 --- a/src/guik/imgui_application.cpp +++ b/src/guik/imgui_application.cpp @@ -131,6 +131,12 @@ void Application::maximize_window() { glfwMaximizeWindow(window); } +void Application::fullscreen_window() { + GLFWmonitor* monitor = glfwGetPrimaryMonitor(); + const GLFWvidmode* mode = glfwGetVideoMode(monitor); + glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate); +} + void Application::resize(const Eigen::Vector2i& size) { glfwSetWindowSize(window, size[0], size[1]); } From bdabbec09c0e02cfe5309737a6068833e37c099a Mon Sep 17 00:00:00 2001 From: "k.koide" Date: Tue, 30 Dec 2025 13:34:25 +0900 Subject: [PATCH 17/40] hovered and cmap --- src/python/glk.cpp | 6 ++ src/python/guik.cpp | 139 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 143 insertions(+), 2 deletions(-) diff --git a/src/python/glk.cpp b/src/python/glk.cpp index b0e96c0d..94b9f7a7 100644 --- a/src/python/glk.cpp +++ b/src/python/glk.cpp @@ -321,6 +321,12 @@ void define_glk(py::module_& m) { py::arg("colormap"), py::arg("intensities"), py::arg("scale") = 1.0f) + .def("set_colormap_buffer", &glk::PointCloudBuffer::set_colormap_buffer, py::arg("colormap_buffer")) + .def( + "add_colormap", + [](glk::PointCloudBuffer& buffer, std::vector& cmap, float scale) { buffer.add_colormap(cmap, scale); }, + py::arg("cmap"), + py::arg("scale") = 1.0f) .def( "add_buffer", [](glk::PointCloudBuffer& buffer, const std::string& attribute_name, const Eigen::MatrixXf& data) { diff --git a/src/python/guik.cpp b/src/python/guik.cpp index 94baf490..e89baef5 100644 --- a/src/python/guik.cpp +++ b/src/python/guik.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -74,6 +75,8 @@ void define_guik(py::module_& m) { .def("add", &guik::ShaderSetting::add) .def("add", &guik::ShaderSetting::add) .def("addi", &guik::ShaderSetting::add) + .def("static_object", &guik::ShaderSetting::static_object, py::return_value_policy::reference_internal) + .def("dynamic_object", &guik::ShaderSetting::dynamic_object, py::return_value_policy::reference_internal) .def("material_color", &guik::ShaderSetting::material_color) .def( "set_color", @@ -100,6 +103,7 @@ void define_guik(py::module_& m) { .def("set_point_scale_mode", &guik::ShaderSetting::set_point_scale_mode, py::arg("mode"), py::return_value_policy::reference_internal) .def("set_point_scale_screenspace", &guik::ShaderSetting::set_point_scale_screenspace, py::return_value_policy::reference_internal) .def("set_point_scale_metric", &guik::ShaderSetting::set_point_scale_metric, py::return_value_policy::reference_internal) + .def("set_point_shape", &guik::ShaderSetting::set_point_shape, py::arg("point_size"), py::arg("metric"), py::arg("circle"), py::return_value_policy::reference_internal) .def("remove_model_matrix", &guik::ShaderSetting::remove_model_matrix, py::return_value_policy::reference_internal) .def("color_mode", &guik::ShaderSetting::color_mode) .def("set_color_mode", &guik::ShaderSetting::set_color_mode, py::arg("color_mode"), py::return_value_policy::reference_internal) @@ -283,6 +287,136 @@ void define_guik(py::module_& m) { .def("set_mouse_senstivity", &guik::FPSCameraControl::set_mouse_senstivity) .def("set_translation_speed", &guik::FPSCameraControl::set_translation_speed); + // guik::HoveredDrawings + py::class_>(guik_, "HoveredDrawings") // + .def( + py::init([](guik::LightViewerContext* context) { + if (context == nullptr) { + context = guik::LightViewer::instance(); + } + return std::make_shared(context); + }), + py::arg("context") = nullptr) + .def( + "add_text", + &guik::HoveredDrawings::add_text, + py::arg("pt"), + py::arg("text"), + py::arg("fg_color") = 0xFFFFFFFF, + py::arg("bg_color") = 0x80000000, + py::arg("offset") = Eigen::Vector2f(0.0f, 0.0f)) + .def( + "add_text_on", + &guik::HoveredDrawings::add_text_on, + py::arg("drawable_name"), + py::arg("text"), + py::arg("fg_color") = 0xFFFFFFFF, + py::arg("bg_color") = 0x80000000, + py::arg("offset") = Eigen::Vector2f(0.0f, 0.0f)) + .def("add_cross", &guik::HoveredDrawings::add_cross, py::arg("pt"), py::arg("color") = 0xFFFFFFFF, py::arg("size") = 7.07f, py::arg("thickness") = 1.0f) + .def("add_cross_on", &guik::HoveredDrawings::add_cross_on, py::arg("drawable_name"), py::arg("color") = 0xFFFFFFFF, py::arg("size") = 7.07f, py::arg("thickness") = 1.0f) + .def( + "add_circle", + &guik::HoveredDrawings::add_circle, + py::arg("pt"), + py::arg("color") = 0xFFFFFFFF, + py::arg("radius") = 10.0f, + py::arg("num_segments") = 32, + py::arg("thickness") = 1.0f) + .def( + "add_circle_on", + &guik::HoveredDrawings::add_circle_on, + py::arg("drawable_name"), + py::arg("color") = 0xFFFFFFFF, + py::arg("radius") = 10.0f, + py::arg("num_segments") = 32, + py::arg("thickness") = 1.0f) + .def( + "add_triangle", + &guik::HoveredDrawings::add_triangle, + py::arg("pt"), + py::arg("color") = 0xFFFFFFFF, + py::arg("height") = 20.0f, + py::arg("thickness") = 1.0f, + py::arg("upsidedown") = true, + py::arg("centering") = false) + .def( + "add_triangle_on", + &guik::HoveredDrawings::add_triangle_on, + py::arg("drawable"), + py::arg("color") = 0xFFFFFFFF, + py::arg("height") = 20.0f, + py::arg("thickness") = 1.0f, + py::arg("upsidedown") = true, + py::arg("centering") = false) + .def( + "add_filled_triangle", + &guik::HoveredDrawings::add_filled_triangle, + py::arg("pt"), + py::arg("color") = 0xFFFFFFFF, + py::arg("height") = 20.0f, + py::arg("upsidedown") = true, + py::arg("centering") = false) + .def( + "add_filled_triangle_on", + &guik::HoveredDrawings::add_filled_triangle_on, + py::arg("drawable_name"), + py::arg("color") = 0xFFFFFFFF, + py::arg("height") = 20.0f, + py::arg("upsidedown") = true, + py::arg("centering") = false) + .def( + "add_rect", + &guik::HoveredDrawings::add_rect, + py::arg("pt"), + py::arg("color") = 0xFFFFFFFF, + py::arg("size") = Eigen::Vector2f(15.0f, 15.0f), + py::arg("offset") = Eigen::Vector2f(0.0f, 0.0f)) + .def( + "add_rect_on", + &guik::HoveredDrawings::add_rect_on, + py::arg("drawable"), + py::arg("color") = 0xFFFFFFFF, + py::arg("size") = Eigen::Vector2f(15.0f, 15.0f), + py::arg("offset") = Eigen::Vector2f(0.0f, 0.0f)) + .def( + "add_filled_rect", + &guik::HoveredDrawings::add_filled_rect, + py::arg("pt"), + py::arg("color") = 0xFFFFFFFF, + py::arg("size") = Eigen::Vector2f(15.0f, 15.0f), + py::arg("offset") = Eigen::Vector2f(0.0f, 0.0f)) + .def( + "add_filled_rect_on", + &guik::HoveredDrawings::add_filled_rect_on, + py::arg("drawable_name"), + py::arg("color") = 0xFFFFFFFF, + py::arg("size") = Eigen::Vector2f(15.0f, 15.0f), + py::arg("offset") = Eigen::Vector2f(0.0f, 0.0f)) + .def( + "add_image", + &guik::HoveredDrawings::add_image, + py::arg("pt"), + py::arg("texture"), + py::arg("size") = Eigen::Vector2f(0.0f, 0.0f), + py::arg("offset") = Eigen::Vector2f(0.0f, 0.0f), + py::arg("bg_color") = 0, + py::arg("border_color") = 0, + py::arg("border_thickness") = 1.0f) + .def( + "add_image_on", + &guik::HoveredDrawings::add_image_on, + py::arg("drawable_name"), + py::arg("texture"), + py::arg("size") = Eigen::Vector2f(0.0f, 0.0f), + py::arg("offset") = Eigen::Vector2f(0.0f, 0.0f), + py::arg("bg_color") = 0, + py::arg("border_color") = 0, + py::arg("border_thickness") = 1.0f) + .def("remove_drawing", &guik::HoveredDrawings::remove_drawing, py::arg("drawing_id")) + .def("clear", &guik::HoveredDrawings::clear) + .def("create_callback", &guik::HoveredDrawings::create_callback); + // guik::ProjectionControl py::class_>(guik_, "ProjectionControl"); @@ -297,6 +431,7 @@ void define_guik(py::module_& m) { .def("show_window", &guik::Application::show_window) .def("hide_window", &guik::Application::hide_window) .def("maximize_window", &guik::Application::maximize_window) + .def("fullscreen_window", &guik::Application::fullscreen_window) .def("resize", &guik::Application::resize) .def("set_title", &guik::Application::set_title) .def("framebuffer_size", &guik::Application::framebuffer_size) @@ -333,8 +468,6 @@ void define_guik(py::module_& m) { .def("get_screen_effect", &guik::LightViewerContext::get_screen_effect) .def("set_bg_texture", &guik::LightViewerContext::set_bg_texture) - .def("set_point_shape", &guik::LightViewerContext::set_point_shape, py::arg("point_size") = 1.0f, py::arg("metric") = true, py::arg("circle") = true) - .def("enable_normal_buffer", &guik::LightViewerContext::enable_normal_buffer) .def("enable_info_buffer", &guik::LightViewerContext::enable_info_buffer) .def("enable_partial_rendering", &guik::LightViewerContext::enable_partial_rendering, py::arg("clear_thresh") = 1e-6) @@ -403,6 +536,8 @@ void define_guik(py::module_& m) { py::arg("phi") = -60.0 * M_PI / 180.0) .def("use_fps_camera_control", &guik::LightViewerContext::use_fps_camera_control, py::arg("fovy_deg") = 60.0) + .def("set_point_shape", &guik::LightViewerContext::set_point_shape, py::arg("point_size") = 1.0f, py::arg("metric") = true, py::arg("circle") = true) + .def("pick_info", &guik::LightViewerContext::pick_info, py::arg("p"), py::arg("window") = 2) .def("pick_depth", &guik::LightViewerContext::pick_depth, py::arg("p"), py::arg("window") = 2) .def("unproject", &guik::LightViewerContext::unproject, py::arg("p"), py::arg("depth")) From 562b2008dcf92c7d40533b6277e580ecd8c4ae84 Mon Sep 17 00:00:00 2001 From: "k.koide" Date: Tue, 30 Dec 2025 13:43:49 +0900 Subject: [PATCH 18/40] fix bugs --- include/glk/glsl_shader.hpp | 2 +- include/guik/viewer/shader_setting.hpp | 5 +++-- src/glk/glsl_shader.cpp | 6 +++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/include/glk/glsl_shader.hpp b/include/glk/glsl_shader.hpp index 12c0045a..2288e65c 100644 --- a/include/glk/glsl_shader.hpp +++ b/include/glk/glsl_shader.hpp @@ -77,7 +77,7 @@ class GLSLShader { if (found == uniform_variable_cache.end()) { return std::nullopt; } - return *std::reinterpret_pointer_cast(found->second); + return *reinterpret_cast(found->second.get()); } // int diff --git a/include/guik/viewer/shader_setting.hpp b/include/guik/viewer/shader_setting.hpp index cb350858..ad2f505a 100644 --- a/include/guik/viewer/shader_setting.hpp +++ b/include/guik/viewer/shader_setting.hpp @@ -414,8 +414,9 @@ struct ShaderSetting { template ShaderSetting& transform(const Transform& transform) { auto& p = params[2]; - const Eigen::Matrix4f mat = (p.get_value() * transform.template cast()).matrix(); - p.set_value(mat); + Eigen::Matrix4f current = p.get_value(); + Eigen::Matrix4f trans_mat = (transform.template cast() * Eigen::Isometry3f::Identity()).matrix(); + p.set_value(current * trans_mat); return *this; } diff --git a/src/glk/glsl_shader.cpp b/src/glk/glsl_shader.cpp index 37093429..306cf021 100644 --- a/src/glk/glsl_shader.cpp +++ b/src/glk/glsl_shader.cpp @@ -80,7 +80,7 @@ bool GLSLShader::add_feedback_varying(const std::string& name) { bool GLSLShader::link_program() { if (shader_program) { glUseProgram(0); - glDeleteShader(shader_program); + glDeleteProgram(shader_program); attrib_cache.clear(); uniform_cache.clear(); } @@ -230,7 +230,7 @@ GLint GLSLShader::subroutine(GLenum shader_type, std::uint64_t name, const char* GLint GLSLShader::subroutine(GLenum shader_type, const std::string& name) { const std::uint64_t h = glk::hash(name); GLint id = subroutine(shader_type, h, name.c_str()); - if (id >= -1) { + if (id != -1) { return id; } @@ -256,7 +256,7 @@ GLint GLSLShader::subroutine_uniform(GLenum shader_type, std::uint64_t name, con GLint GLSLShader::subroutine_uniform(GLenum shader_type, const std::string& name) { const std::uint64_t h = glk::hash(name); GLint id = subroutine_uniform(shader_type, h, name.c_str()); - if (id >= -1) { + if (id != -1) { return id; } From 9794b883aceedbeaca7fbbf8354a58c0815d9cc3 Mon Sep 17 00:00:00 2001 From: "k.koide" Date: Tue, 30 Dec 2025 14:48:08 +0900 Subject: [PATCH 19/40] install stubs --- CMakeLists.txt | 3 + scripts/gen_python_stubs.sh | 11 + src/python/stubs/pyridescence/__init__.pyi | 8 + src/python/stubs/pyridescence/gl.pyi | 18 + .../stubs/pyridescence/glk/__init__.pyi | 419 ++++++++++ .../stubs/pyridescence/glk/primitives.pyi | 31 + src/python/stubs/pyridescence/guik.pyi | 689 +++++++++++++++++ src/python/stubs/pyridescence/imgui.pyi | 713 ++++++++++++++++++ src/python/stubs/pyridescence/pfd.pyi | 12 + 9 files changed, 1904 insertions(+) create mode 100755 scripts/gen_python_stubs.sh create mode 100644 src/python/stubs/pyridescence/__init__.pyi create mode 100644 src/python/stubs/pyridescence/gl.pyi create mode 100644 src/python/stubs/pyridescence/glk/__init__.pyi create mode 100644 src/python/stubs/pyridescence/glk/primitives.pyi create mode 100644 src/python/stubs/pyridescence/guik.pyi create mode 100644 src/python/stubs/pyridescence/imgui.pyi create mode 100644 src/python/stubs/pyridescence/pfd.pyi diff --git a/CMakeLists.txt b/CMakeLists.txt index 33c2c32e..27aeb800 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -354,6 +354,9 @@ if(BUILD_PYTHON_BINDINGS) LIBRARY DESTINATION ${PYTHON_INSTALL_DIR} COMPONENT python ) + + # install stubs in src/python/stubs + install(DIRECTORY src/python/stubs/ DESTINATION ${PYTHON_INSTALL_DIR}) endif() ############# diff --git a/scripts/gen_python_stubs.sh b/scripts/gen_python_stubs.sh new file mode 100755 index 00000000..72359198 --- /dev/null +++ b/scripts/gen_python_stubs.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +pushd . + +dst_path=$(realpath src/python/stubs) + +cd build +python -m pybind11_stubgen -o $dst_path pyridescence + +popd + diff --git a/src/python/stubs/pyridescence/__init__.pyi b/src/python/stubs/pyridescence/__init__.pyi new file mode 100644 index 00000000..6b2658fc --- /dev/null +++ b/src/python/stubs/pyridescence/__init__.pyi @@ -0,0 +1,8 @@ +from __future__ import annotations +from . import gl +from . import glk +from . import guik +from . import imgui +from . import pfd +__all__: list[str] = ['gl', 'glk', 'guik', 'imgui', 'pfd'] +__version__: str = 'dev' diff --git a/src/python/stubs/pyridescence/gl.pyi b/src/python/stubs/pyridescence/gl.pyi new file mode 100644 index 00000000..c96ee27b --- /dev/null +++ b/src/python/stubs/pyridescence/gl.pyi @@ -0,0 +1,18 @@ +""" +""" +from __future__ import annotations +__all__: list[str] = ['BGR', 'BGRA', 'BYTE', 'FLOAT', 'HALF_FLOAT', 'INT', 'RED', 'RG', 'RGB', 'RGBA', 'SHORT', 'UNSIGNED_BYTE', 'UNSIGNED_INT', 'UNSIGNED_SHORT'] +BGR: int = 32992 +BGRA: int = 32993 +BYTE: int = 5120 +FLOAT: int = 5126 +HALF_FLOAT: int = 5131 +INT: int = 5124 +RED: int = 6403 +RG: int = 33319 +RGB: int = 6407 +RGBA: int = 6408 +SHORT: int = 5122 +UNSIGNED_BYTE: int = 5121 +UNSIGNED_INT: int = 5125 +UNSIGNED_SHORT: int = 5123 diff --git a/src/python/stubs/pyridescence/glk/__init__.pyi b/src/python/stubs/pyridescence/glk/__init__.pyi new file mode 100644 index 00000000..ac850b42 --- /dev/null +++ b/src/python/stubs/pyridescence/glk/__init__.pyi @@ -0,0 +1,419 @@ +""" +""" +from __future__ import annotations +import numpy +import typing +from . import primitives +__all__: list[str] = ['AUTUMN', 'BLUE_RED', 'CIVIDIS', 'COLORMAP', 'COOL_WARM', 'CURL', 'Drawable', 'GREAN_YELLOW', 'HELIX', 'JET', 'Lines', 'NaiveScreenSpaceAmbientOcclusion', 'OCEAN', 'PASTEL', 'PHASE', 'PLYData', 'PUBUGN', 'PointCloudBuffer', 'SPRING', 'SUMMER', 'ScreenEffect', 'ScreenSpaceAmbientOcclusion', 'ScreenSpaceLighting', 'TURBID', 'TURBO', 'Texture', 'ThinLines', 'VEGETATION', 'WINTER', 'colormap', 'colormap_categorical', 'colormap_categoricalf', 'colormapf', 'create_pointcloud_buffer', 'create_texture', 'create_texture_f', 'get_data_path', 'load_ply', 'primitives', 'save_ply', 'set_data_path'] +class COLORMAP: + """ + Members: + + TURBO + + JET + + CIVIDIS + + OCEAN + + SPRING + + SUMMER + + AUTUMN + + WINTER + + GREAN_YELLOW + + BLUE_RED + + PUBUGN + + TURBID + + PASTEL + + HELIX + + PHASE + + VEGETATION + + CURL + + COOL_WARM + """ + AUTUMN: typing.ClassVar[COLORMAP] # value = + BLUE_RED: typing.ClassVar[COLORMAP] # value = + CIVIDIS: typing.ClassVar[COLORMAP] # value = + COOL_WARM: typing.ClassVar[COLORMAP] # value = + CURL: typing.ClassVar[COLORMAP] # value = + GREAN_YELLOW: typing.ClassVar[COLORMAP] # value = + HELIX: typing.ClassVar[COLORMAP] # value = + JET: typing.ClassVar[COLORMAP] # value = + OCEAN: typing.ClassVar[COLORMAP] # value = + PASTEL: typing.ClassVar[COLORMAP] # value = + PHASE: typing.ClassVar[COLORMAP] # value = + PUBUGN: typing.ClassVar[COLORMAP] # value = + SPRING: typing.ClassVar[COLORMAP] # value = + SUMMER: typing.ClassVar[COLORMAP] # value = + TURBID: typing.ClassVar[COLORMAP] # value = + TURBO: typing.ClassVar[COLORMAP] # value = + VEGETATION: typing.ClassVar[COLORMAP] # value = + WINTER: typing.ClassVar[COLORMAP] # value = + __members__: typing.ClassVar[dict[str, COLORMAP]] # value = {'TURBO': , 'JET': , 'CIVIDIS': , 'OCEAN': , 'SPRING': , 'SUMMER': , 'AUTUMN': , 'WINTER': , 'GREAN_YELLOW': , 'BLUE_RED': , 'PUBUGN': , 'TURBID': , 'PASTEL': , 'HELIX': , 'PHASE': , 'VEGETATION': , 'CURL': , 'COOL_WARM': } + def __eq__(self, other: typing.Any) -> bool: + ... + def __getstate__(self) -> int: + ... + def __hash__(self) -> int: + ... + def __index__(self) -> int: + ... + def __init__(self, value: int) -> None: + ... + def __int__(self) -> int: + ... + def __ne__(self, other: typing.Any) -> bool: + ... + def __repr__(self) -> str: + ... + def __setstate__(self, state: int) -> None: + ... + def __str__(self) -> str: + ... + @property + def name(self) -> str: + ... + @property + def value(self) -> int: + ... +class Drawable: + pass +class Lines(Drawable): + @typing.overload + def __init__(self, thickness: float, vertices: list[numpy.ndarray[numpy.float32[3, 1]]], colors: list[numpy.ndarray[numpy.float32[4, 1]]]) -> None: + ... + @typing.overload + def __init__(self, thickness: float, vertices: numpy.ndarray[numpy.float32], colors: numpy.ndarray[numpy.float32]) -> None: + ... + @typing.overload + def __init__(self, x: numpy.ndarray[numpy.float32[m, 1]] = ..., y: numpy.ndarray[numpy.float32[m, 1]] = ..., z: numpy.ndarray[numpy.float32[m, 1]] = ..., c: numpy.ndarray[numpy.float32[m, 1]] = ..., width: float = 0.10000000149011612, line_strip: bool = True) -> None: + ... +class NaiveScreenSpaceAmbientOcclusion(ScreenEffect): + def __init__(self) -> None: + ... +class PLYData: + colors: numpy.ndarray[numpy.float32[m, n]] + comments: list[str] + indices: numpy.ndarray[numpy.int32[m, 1]] + intensities: numpy.ndarray[numpy.float32[m, 1]] + normals: numpy.ndarray[numpy.float32[m, n]] + vertices: numpy.ndarray[numpy.float32[m, n]] + def __init__(self) -> None: + ... +class PointCloudBuffer(Drawable): + @typing.overload + def __init__(self, points: numpy.ndarray[numpy.float32]) -> None: + ... + @typing.overload + def __init__(self, arg0: list[numpy.ndarray[numpy.float32[3, 1]]]) -> None: + ... + @typing.overload + def __init__(self, points: list[numpy.ndarray[numpy.float32[3, 1]]]) -> None: + ... + def add_buffer(self, attribute_name: str, data: numpy.ndarray[numpy.float32[m, n]]) -> None: + ... + @typing.overload + def add_color(self, colors: list[numpy.ndarray[numpy.float32[3, 1]]]) -> None: + ... + @typing.overload + def add_color(self, colors: list[numpy.ndarray[numpy.float32[4, 1]]]) -> None: + ... + @typing.overload + def add_color(self, colors: numpy.ndarray[numpy.float32]) -> None: + ... + def add_colormap(self, cmap: list[float], scale: float = 1.0) -> None: + ... + def add_intensity(self, colormap: COLORMAP, intensities: list[float], scale: float = 1.0) -> None: + ... + @typing.overload + def add_normals(self, normals: list[numpy.ndarray[numpy.float32[3, 1]]]) -> None: + ... + @typing.overload + def add_normals(self, normals: numpy.ndarray[numpy.float32]) -> None: + ... + def set_colormap_buffer(self, colormap_buffer: str) -> None: + ... +class ScreenEffect: + pass +class ScreenSpaceAmbientOcclusion(ScreenEffect): + def __init__(self) -> None: + ... +class ScreenSpaceLighting(ScreenEffect): + class DIFFUSE_MODEL: + """ + Members: + + ZERO + + LAMBERT + + DISNEY + + NORMALIZED_DISNEY + + OREN_NAYAR + """ + DISNEY: typing.ClassVar[ScreenSpaceLighting.DIFFUSE_MODEL] # value = + LAMBERT: typing.ClassVar[ScreenSpaceLighting.DIFFUSE_MODEL] # value = + NORMALIZED_DISNEY: typing.ClassVar[ScreenSpaceLighting.DIFFUSE_MODEL] # value = + OREN_NAYAR: typing.ClassVar[ScreenSpaceLighting.DIFFUSE_MODEL] # value = + ZERO: typing.ClassVar[ScreenSpaceLighting.DIFFUSE_MODEL] # value = + __members__: typing.ClassVar[dict[str, ScreenSpaceLighting.DIFFUSE_MODEL]] # value = {'ZERO': , 'LAMBERT': , 'DISNEY': , 'NORMALIZED_DISNEY': , 'OREN_NAYAR': } + def __eq__(self, other: typing.Any) -> bool: + ... + def __getstate__(self) -> int: + ... + def __hash__(self) -> int: + ... + def __index__(self) -> int: + ... + def __init__(self, value: int) -> None: + ... + def __int__(self) -> int: + ... + def __ne__(self, other: typing.Any) -> bool: + ... + def __repr__(self) -> str: + ... + def __setstate__(self, state: int) -> None: + ... + def __str__(self) -> str: + ... + @property + def name(self) -> str: + ... + @property + def value(self) -> int: + ... + class IRIDESCENCE_MODEL: + """ + Members: + + ZERO + + IRIDESCENCE1 + + IRIDESCENCE2 + + IRIDESCENCE3 + """ + IRIDESCENCE1: typing.ClassVar[ScreenSpaceLighting.IRIDESCENCE_MODEL] # value = + IRIDESCENCE2: typing.ClassVar[ScreenSpaceLighting.IRIDESCENCE_MODEL] # value = + IRIDESCENCE3: typing.ClassVar[ScreenSpaceLighting.IRIDESCENCE_MODEL] # value = + ZERO: typing.ClassVar[ScreenSpaceLighting.IRIDESCENCE_MODEL] # value = + __members__: typing.ClassVar[dict[str, ScreenSpaceLighting.IRIDESCENCE_MODEL]] # value = {'ZERO': , 'IRIDESCENCE1': , 'IRIDESCENCE2': , 'IRIDESCENCE3': } + def __eq__(self, other: typing.Any) -> bool: + ... + def __getstate__(self) -> int: + ... + def __hash__(self) -> int: + ... + def __index__(self) -> int: + ... + def __init__(self, value: int) -> None: + ... + def __int__(self) -> int: + ... + def __ne__(self, other: typing.Any) -> bool: + ... + def __repr__(self) -> str: + ... + def __setstate__(self, state: int) -> None: + ... + def __str__(self) -> str: + ... + @property + def name(self) -> str: + ... + @property + def value(self) -> int: + ... + class OCCLUSION_MODEL: + """ + Members: + + ZERO + + AMBIENT_OCCLUSION + """ + AMBIENT_OCCLUSION: typing.ClassVar[ScreenSpaceLighting.OCCLUSION_MODEL] # value = + ZERO: typing.ClassVar[ScreenSpaceLighting.OCCLUSION_MODEL] # value = + __members__: typing.ClassVar[dict[str, ScreenSpaceLighting.OCCLUSION_MODEL]] # value = {'ZERO': , 'AMBIENT_OCCLUSION': } + def __eq__(self, other: typing.Any) -> bool: + ... + def __getstate__(self) -> int: + ... + def __hash__(self) -> int: + ... + def __index__(self) -> int: + ... + def __init__(self, value: int) -> None: + ... + def __int__(self) -> int: + ... + def __ne__(self, other: typing.Any) -> bool: + ... + def __repr__(self) -> str: + ... + def __setstate__(self, state: int) -> None: + ... + def __str__(self) -> str: + ... + @property + def name(self) -> str: + ... + @property + def value(self) -> int: + ... + class SPECULAR_MODEL: + """ + Members: + + ZERO + + PHONG + + BLINN_PHONG + + COOK_TORRANCE + """ + BLINN_PHONG: typing.ClassVar[ScreenSpaceLighting.SPECULAR_MODEL] # value = + COOK_TORRANCE: typing.ClassVar[ScreenSpaceLighting.SPECULAR_MODEL] # value = + PHONG: typing.ClassVar[ScreenSpaceLighting.SPECULAR_MODEL] # value = + ZERO: typing.ClassVar[ScreenSpaceLighting.SPECULAR_MODEL] # value = + __members__: typing.ClassVar[dict[str, ScreenSpaceLighting.SPECULAR_MODEL]] # value = {'ZERO': , 'PHONG': , 'BLINN_PHONG': , 'COOK_TORRANCE': } + def __eq__(self, other: typing.Any) -> bool: + ... + def __getstate__(self) -> int: + ... + def __hash__(self) -> int: + ... + def __index__(self) -> int: + ... + def __init__(self, value: int) -> None: + ... + def __int__(self) -> int: + ... + def __ne__(self, other: typing.Any) -> bool: + ... + def __repr__(self) -> str: + ... + def __setstate__(self, state: int) -> None: + ... + def __str__(self) -> str: + ... + @property + def name(self) -> str: + ... + @property + def value(self) -> int: + ... + AMBIENT_OCCLUSION: typing.ClassVar[ScreenSpaceLighting.OCCLUSION_MODEL] # value = + BLINN_PHONG: typing.ClassVar[ScreenSpaceLighting.SPECULAR_MODEL] # value = + COOK_TORRANCE: typing.ClassVar[ScreenSpaceLighting.SPECULAR_MODEL] # value = + DISNEY: typing.ClassVar[ScreenSpaceLighting.DIFFUSE_MODEL] # value = + IRIDESCENCE1: typing.ClassVar[ScreenSpaceLighting.IRIDESCENCE_MODEL] # value = + IRIDESCENCE2: typing.ClassVar[ScreenSpaceLighting.IRIDESCENCE_MODEL] # value = + IRIDESCENCE3: typing.ClassVar[ScreenSpaceLighting.IRIDESCENCE_MODEL] # value = + LAMBERT: typing.ClassVar[ScreenSpaceLighting.DIFFUSE_MODEL] # value = + NORMALIZED_DISNEY: typing.ClassVar[ScreenSpaceLighting.DIFFUSE_MODEL] # value = + OREN_NAYAR: typing.ClassVar[ScreenSpaceLighting.DIFFUSE_MODEL] # value = + PHONG: typing.ClassVar[ScreenSpaceLighting.SPECULAR_MODEL] # value = + ZERO: typing.ClassVar[ScreenSpaceLighting.IRIDESCENCE_MODEL] # value = + def __init__(self) -> None: + ... + def num_lights(self) -> int: + ... + def set_albedo(self, arg0: float) -> None: + ... + def set_diffuse_model(self, arg0: ScreenSpaceLighting.DIFFUSE_MODEL) -> None: + ... + def set_iridescence_model(self, arg0: ScreenSpaceLighting.IRIDESCENCE_MODEL) -> None: + ... + def set_light(self, arg0: int, arg1: numpy.ndarray[numpy.float32[3, 1]], arg2: numpy.ndarray[numpy.float32[4, 1]]) -> None: + ... + def set_occlusion_model(self, arg0: ScreenSpaceLighting.OCCLUSION_MODEL) -> None: + ... + def set_roughness(self, arg0: float) -> None: + ... + def set_specular_model(self, arg0: ScreenSpaceLighting.SPECULAR_MODEL) -> None: + ... +class Texture: + def __init__(self, size: numpy.ndarray[numpy.int32[2, 1]], internal_format: int, format: int, type: int, bytes: list[int]) -> None: + ... +class ThinLines(Drawable): + @typing.overload + def __init__(self, points: numpy.ndarray[numpy.float32], line_strip: bool = False) -> None: + ... + @typing.overload + def __init__(self, points: numpy.ndarray[numpy.float32], colors: numpy.ndarray[numpy.float32], line_strip: bool = False) -> None: + ... + @typing.overload + def __init__(self, points: list[numpy.ndarray[numpy.float32[3, 1]]], line_strip: bool = False) -> None: + ... + @typing.overload + def __init__(self, points: list[numpy.ndarray[numpy.float32[3, 1]]], colors: list[numpy.ndarray[numpy.float32[4, 1]]], line_strip: bool = False) -> None: + ... + @typing.overload + def __init__(self, x: numpy.ndarray[numpy.float32[m, 1]] = ..., y: numpy.ndarray[numpy.float32[m, 1]] = ..., z: numpy.ndarray[numpy.float32[m, 1]] = ..., c: numpy.ndarray[numpy.float32[m, 1]] = ..., line_strip: bool = True) -> None: + ... + def set_line_width(self, width: float) -> None: + ... +def colormap(colormap_type: COLORMAP, x: int) -> numpy.ndarray[numpy.int32[4, 1]]: + ... +def colormap_categorical(colormap_type: COLORMAP, x: int, num_categories: int) -> numpy.ndarray[numpy.int32[4, 1]]: + ... +def colormap_categoricalf(colormap_type: COLORMAP, x: int, num_categories: int) -> numpy.ndarray[numpy.float32[4, 1]]: + ... +def colormapf(colormap_type: COLORMAP, x: float) -> numpy.ndarray[numpy.float32[4, 1]]: + ... +def create_pointcloud_buffer(points: numpy.ndarray[numpy.float32[m, 3]], colors: numpy.ndarray[numpy.float32[m, 4]] = ...) -> PointCloudBuffer: + ... +def create_texture(image_uint8: numpy.ndarray[numpy.uint8]) -> Texture: + ... +def create_texture_f(image_float: numpy.ndarray[numpy.float32]) -> Texture: + ... +def get_data_path() -> str: + ... +def load_ply(filename: str) -> PLYData: + ... +@typing.overload +def save_ply(filename: str, ply: PLYData, binary: bool = True) -> bool: + ... +@typing.overload +def save_ply(arg0: str, arg1: numpy.ndarray[numpy.float32[m, n]]) -> bool: + ... +def set_data_path(arg0: str) -> None: + ... +AUTUMN: COLORMAP # value = +BLUE_RED: COLORMAP # value = +CIVIDIS: COLORMAP # value = +COOL_WARM: COLORMAP # value = +CURL: COLORMAP # value = +GREAN_YELLOW: COLORMAP # value = +HELIX: COLORMAP # value = +JET: COLORMAP # value = +OCEAN: COLORMAP # value = +PASTEL: COLORMAP # value = +PHASE: COLORMAP # value = +PUBUGN: COLORMAP # value = +SPRING: COLORMAP # value = +SUMMER: COLORMAP # value = +TURBID: COLORMAP # value = +TURBO: COLORMAP # value = +VEGETATION: COLORMAP # value = +WINTER: COLORMAP # value = diff --git a/src/python/stubs/pyridescence/glk/primitives.pyi b/src/python/stubs/pyridescence/glk/primitives.pyi new file mode 100644 index 00000000..7812f7b8 --- /dev/null +++ b/src/python/stubs/pyridescence/glk/primitives.pyi @@ -0,0 +1,31 @@ +""" +""" +from __future__ import annotations +import pyridescence.glk +__all__: list[str] = ['bunny', 'cone', 'coordinate_system', 'cube', 'frustum', 'icosahedron', 'sphere', 'wire_bunny', 'wire_cone', 'wire_cube', 'wire_frustum', 'wire_icosahedron', 'wire_sphere'] +def bunny() -> pyridescence.glk.Drawable: + ... +def cone() -> pyridescence.glk.Drawable: + ... +def coordinate_system() -> pyridescence.glk.Drawable: + ... +def cube() -> pyridescence.glk.Drawable: + ... +def frustum() -> pyridescence.glk.Drawable: + ... +def icosahedron() -> pyridescence.glk.Drawable: + ... +def sphere() -> pyridescence.glk.Drawable: + ... +def wire_bunny() -> pyridescence.glk.Drawable: + ... +def wire_cone() -> pyridescence.glk.Drawable: + ... +def wire_cube() -> pyridescence.glk.Drawable: + ... +def wire_frustum() -> pyridescence.glk.Drawable: + ... +def wire_icosahedron() -> pyridescence.glk.Drawable: + ... +def wire_sphere() -> pyridescence.glk.Drawable: + ... diff --git a/src/python/stubs/pyridescence/guik.pyi b/src/python/stubs/pyridescence/guik.pyi new file mode 100644 index 00000000..c44ef68e --- /dev/null +++ b/src/python/stubs/pyridescence/guik.pyi @@ -0,0 +1,689 @@ +""" +""" +from __future__ import annotations +import numpy +import pyridescence.glk +import typing +__all__: list[str] = ['Application', 'ArcBallCameraControl', 'AsyncLightViewer', 'AsyncLightViewerContext', 'CIRCLE', 'CameraControl', 'FPSCameraControl', 'FlatBlue', 'FlatColor', 'FlatGreen', 'FlatOrange', 'FlatRed', 'HoveredDrawings', 'LightViewer', 'LightViewerContext', 'METRIC', 'ModelControl', 'OrbitCameraControlXY', 'OrbitCameraControlXZ', 'PointScaleMode', 'PointShapeMode', 'ProjectionControl', 'RECTANGLE', 'Rainbow', 'RecentFiles', 'SCREENSPACE', 'ShaderSetting', 'TopDownCameraControl', 'VertexColor', 'anon', 'async_destroy', 'async_viewer', 'async_wait', 'destroy', 'viewer'] +class Application: + def close(self) -> None: + ... + def closed(self) -> bool: + ... + def disable_docking(self) -> None: + ... + def disable_vsync(self) -> None: + ... + def enable_docking(self) -> None: + ... + def enable_vsync(self) -> None: + ... + def framebuffer_size(self) -> numpy.ndarray[numpy.int32[2, 1]]: + ... + def fullscreen_window(self) -> None: + ... + def hide_window(self) -> None: + ... + def maximize_window(self) -> None: + ... + def ok(self) -> bool: + ... + def resize(self, arg0: numpy.ndarray[numpy.int32[2, 1]]) -> None: + ... + def set_title(self, arg0: str) -> None: + ... + def show_window(self) -> None: + ... + def spin(self) -> None: + ... + def spin_once(self) -> bool: + ... + def window_size(self) -> numpy.ndarray[numpy.int32[2, 1]]: + ... +class ArcBallCameraControl(CameraControl): + pass +class AsyncLightViewer(AsyncLightViewerContext): + @staticmethod + def destroy() -> None: + ... + @staticmethod + def instance(size: numpy.ndarray[numpy.int32[2, 1]] = ..., background: bool = False, title: str = 'screen') -> LightViewer: + ... + @staticmethod + def toggle_wait() -> None: + ... + @staticmethod + def wait() -> None: + ... + @staticmethod + def wait_until_click() -> None: + ... + def async_sub_viewer(self, arg0: str, arg1: tuple[int, int]) -> AsyncLightViewerContext: + ... + def clear_images(self) -> None: + ... + def fit_all_plots(self) -> None: + ... + def fit_plot(self, plot_name: str) -> None: + ... + def remove_image(self, arg0: str) -> None: + ... + def update_image(self, name: str, width: int, height: int, rgba_bytes: list[int], scale: float = -1.0, order: int = -1) -> None: + ... + def update_plot_histogram(self, plot_name: str, label: str, xs: list[float], ys: list[float] = [], x_bins: int = -2, y_bins: int = -2, x_range: numpy.ndarray[numpy.float64[2, 1]] = ..., y_range: numpy.ndarray[numpy.float64[2, 1]] = ..., histogram_flags: int = 0) -> None: + ... + def update_plot_line(self, plot_name: str, label: str, xs: list[float], ys: list[float] = [], line_flags: int = 0, max_num_data: int = 1048576) -> None: + ... + def update_plot_scatter(self, plot_name: str, label: str, xs: list[float], ys: list[float] = [], scatter_flats: int = 0) -> None: + ... +class AsyncLightViewerContext: + def append_text(self, arg0: str) -> None: + ... + def clear(self) -> None: + ... + def clear_drawables(self) -> None: + ... + def clear_text(self) -> None: + ... + def disable_xy_grid(self) -> None: + ... + def enable_xy_grid(self) -> None: + ... + def load_camera_settings(self, path: str) -> None: + ... + def lookat(self, pt: numpy.ndarray[numpy.float32[3, 1]]) -> None: + ... + def register_ui_callback(self, callback_name: str, callback: typing.Callable[[], None]) -> None: + ... + def remove_drawable(self, pattern: str, regex: bool = False) -> None: + ... + def remove_ui_callback(self, callback_name: str) -> None: + ... + def reset_center(self) -> None: + ... + def save_camera_settings(self, path: str) -> None: + ... + def save_color_buffer(self, path: str) -> None: + ... + def save_depth_buffer(self, path: str, real_scale: bool = True) -> None: + ... + def set_colormap(self, arg0: pyridescence.glk.COLORMAP) -> None: + ... + def set_draw_xy_grid(self, arg0: bool) -> None: + ... + def set_point_shape(self, point_size: float = 1.0, metric: bool = True, circle: bool = True) -> None: + ... + def update_cone(self, arg0: str, arg1: ShaderSetting) -> None: + ... + def update_coord(self, arg0: str, arg1: ShaderSetting) -> None: + ... + def update_cube(self, arg0: str, arg1: ShaderSetting) -> None: + ... + def update_drawable_setting(self, name: str, setting: ShaderSetting) -> None: + ... + def update_frustum(self, arg0: str, arg1: ShaderSetting) -> None: + ... + def update_icosahedron(self, arg0: str, arg1: ShaderSetting) -> None: + ... + @typing.overload + def update_normal_dists(self, arg0: str, arg1: list[numpy.ndarray[numpy.float32[3, 1]]], arg2: list[numpy.ndarray[numpy.float32[3, 3]]], arg3: float, arg4: ShaderSetting) -> None: + ... + @typing.overload + def update_normal_dists(self, arg0: str, arg1: list[numpy.ndarray[numpy.float32[4, 1]]], arg2: list[numpy.ndarray[numpy.float32[4, 4]]], arg3: float, arg4: ShaderSetting) -> None: + ... + @typing.overload + def update_points(self, arg0: str, arg1: numpy.ndarray[numpy.float32[m, n]], arg2: ShaderSetting) -> None: + ... + @typing.overload + def update_points(self, arg0: str, arg1: numpy.ndarray[numpy.float32[m, n]], arg2: numpy.ndarray[numpy.float32[m, n]], arg3: ShaderSetting) -> None: + ... + def update_sphere(self, arg0: str, arg1: ShaderSetting) -> None: + ... + def update_thin_lines(self, name: str, vertices: numpy.ndarray[numpy.float32[m, n]], colors: numpy.ndarray[numpy.float32[m, n]] = ..., indices: list[int] = [], line_strip: bool = False, shader_setting: ShaderSetting = ...) -> None: + ... + def update_wire_cone(self, arg0: str, arg1: ShaderSetting) -> None: + ... + def update_wire_cube(self, arg0: str, arg1: ShaderSetting) -> None: + ... + def update_wire_frustum(self, arg0: str, arg1: ShaderSetting) -> None: + ... + def update_wire_icosahedron(self, arg0: str, arg1: ShaderSetting) -> None: + ... + def update_wire_sphere(self, arg0: str, arg1: ShaderSetting) -> None: + ... + def use_arcball_camera_control(self, distance: float = 80.0, theta: float = 0.0, phi: float = -1.0471975511965976) -> None: + ... + def use_fps_camera_control(self, fovy_deg: float = 60.0) -> None: + ... + def use_orbit_camera_control(self, distance: float = 80.0, theta: float = 0.0, phi: float = -1.0471975511965976) -> None: + ... + def use_orbit_camera_control_xz(self, distance: float = 80.0, theta: float = 0.0, phi: float = 0.0) -> None: + ... + def use_topdown_camera_control(self, distance: float = 80.0, theta: float = 0.0) -> None: + ... +class CameraControl: + def lookat(self, arg0: numpy.ndarray[numpy.float32[3, 1]]) -> None: + ... + def reset_center(self) -> None: + ... + def view_matrix(self) -> numpy.ndarray[numpy.float32[4, 4]]: + ... +class FPSCameraControl(CameraControl): + def set_depth_range(self, arg0: numpy.ndarray[numpy.float32[2, 1]]) -> None: + ... + def set_fovy(self, arg0: float) -> None: + ... + def set_mouse_senstivity(self, arg0: float, arg1: float) -> None: + ... + def set_pose(self, arg0: numpy.ndarray[numpy.float32[3, 1]], arg1: float, arg2: float) -> None: + ... + def set_translation_speed(self, arg0: float) -> None: + ... +class FlatBlue(FlatColor): + @typing.overload + def __init__(self) -> None: + ... + @typing.overload + def __init__(self, arg0: numpy.ndarray[numpy.float32[4, 4]]) -> None: + ... + @typing.overload + def __init__(self, scale: float = 1.0, trans: numpy.ndarray[numpy.float32[3, 1]] = ..., rot: numpy.ndarray[numpy.float32[3, 3]] = ...) -> None: + ... +class FlatColor(ShaderSetting): + @typing.overload + def __init__(self, r: float, g: float, b: float, a: float) -> None: + ... + @typing.overload + def __init__(self, r: float, g: float, b: float, a: float, model_matrix: numpy.ndarray[numpy.float32[4, 4]]) -> None: + ... + @typing.overload + def __init__(self, r: float, g: float, b: float, a: float, scale: float = 1.0, trans: numpy.ndarray[numpy.float32[3, 1]] = ..., rot: numpy.ndarray[numpy.float32[3, 3]] = ...) -> None: + ... +class FlatGreen(FlatColor): + @typing.overload + def __init__(self) -> None: + ... + @typing.overload + def __init__(self, arg0: numpy.ndarray[numpy.float32[4, 4]]) -> None: + ... + @typing.overload + def __init__(self, scale: float = 1.0, trans: numpy.ndarray[numpy.float32[3, 1]] = ..., rot: numpy.ndarray[numpy.float32[3, 3]] = ...) -> None: + ... +class FlatOrange(FlatColor): + @typing.overload + def __init__(self) -> None: + ... + @typing.overload + def __init__(self, arg0: numpy.ndarray[numpy.float32[4, 4]]) -> None: + ... + @typing.overload + def __init__(self, scale: float = 1.0, trans: numpy.ndarray[numpy.float32[3, 1]] = ..., rot: numpy.ndarray[numpy.float32[3, 3]] = ...) -> None: + ... +class FlatRed(FlatColor): + @typing.overload + def __init__(self) -> None: + ... + @typing.overload + def __init__(self, arg0: numpy.ndarray[numpy.float32[4, 4]]) -> None: + ... + @typing.overload + def __init__(self, scale: float = 1.0, trans: numpy.ndarray[numpy.float32[3, 1]] = ..., rot: numpy.ndarray[numpy.float32[3, 3]] = ...) -> None: + ... +class HoveredDrawings: + def __init__(self, context: ... = None) -> None: + ... + def add_circle(self, pt: numpy.ndarray[numpy.float32[3, 1]], color: int = 4294967295, radius: float = 10.0, num_segments: int = 32, thickness: float = 1.0) -> int: + ... + def add_circle_on(self, drawable_name: str, color: int = 4294967295, radius: float = 10.0, num_segments: int = 32, thickness: float = 1.0) -> int: + ... + def add_cross(self, pt: numpy.ndarray[numpy.float32[3, 1]], color: int = 4294967295, size: float = 7.070000171661377, thickness: float = 1.0) -> int: + ... + def add_cross_on(self, drawable_name: str, color: int = 4294967295, size: float = 7.070000171661377, thickness: float = 1.0) -> int: + ... + def add_filled_rect(self, pt: numpy.ndarray[numpy.float32[3, 1]], color: int = 4294967295, size: numpy.ndarray[numpy.float32[2, 1]] = ..., offset: numpy.ndarray[numpy.float32[2, 1]] = ...) -> int: + ... + def add_filled_rect_on(self, drawable_name: str, color: int = 4294967295, size: numpy.ndarray[numpy.float32[2, 1]] = ..., offset: numpy.ndarray[numpy.float32[2, 1]] = ...) -> int: + ... + def add_filled_triangle(self, pt: numpy.ndarray[numpy.float32[3, 1]], color: int = 4294967295, height: float = 20.0, upsidedown: bool = True, centering: bool = False) -> int: + ... + def add_filled_triangle_on(self, drawable_name: str, color: int = 4294967295, height: float = 20.0, upsidedown: bool = True, centering: bool = False) -> int: + ... + def add_image(self, pt: numpy.ndarray[numpy.float32[3, 1]], texture: pyridescence.glk.Texture, size: numpy.ndarray[numpy.float32[2, 1]] = ..., offset: numpy.ndarray[numpy.float32[2, 1]] = ..., bg_color: int = 0, border_color: int = 0, border_thickness: float = 1.0) -> int: + ... + def add_image_on(self, drawable_name: str, texture: pyridescence.glk.Texture, size: numpy.ndarray[numpy.float32[2, 1]] = ..., offset: numpy.ndarray[numpy.float32[2, 1]] = ..., bg_color: int = 0, border_color: int = 0, border_thickness: float = 1.0) -> int: + ... + def add_rect(self, pt: numpy.ndarray[numpy.float32[3, 1]], color: int = 4294967295, size: numpy.ndarray[numpy.float32[2, 1]] = ..., offset: numpy.ndarray[numpy.float32[2, 1]] = ...) -> int: + ... + def add_rect_on(self, drawable: str, color: int = 4294967295, size: numpy.ndarray[numpy.float32[2, 1]] = ..., offset: numpy.ndarray[numpy.float32[2, 1]] = ...) -> int: + ... + def add_text(self, pt: numpy.ndarray[numpy.float32[3, 1]], text: str, fg_color: int = 4294967295, bg_color: int = 2147483648, offset: numpy.ndarray[numpy.float32[2, 1]] = ...) -> int: + ... + def add_text_on(self, drawable_name: str, text: str, fg_color: int = 4294967295, bg_color: int = 2147483648, offset: numpy.ndarray[numpy.float32[2, 1]] = ...) -> int: + ... + def add_triangle(self, pt: numpy.ndarray[numpy.float32[3, 1]], color: int = 4294967295, height: float = 20.0, thickness: float = 1.0, upsidedown: bool = True, centering: bool = False) -> int: + ... + def add_triangle_on(self, drawable: str, color: int = 4294967295, height: float = 20.0, thickness: float = 1.0, upsidedown: bool = True, centering: bool = False) -> int: + ... + def clear(self) -> None: + ... + def create_callback(self) -> typing.Callable[[], None]: + ... + def remove_drawing(self, drawing_id: int) -> None: + ... +class LightViewer(Application, LightViewerContext): + @staticmethod + def instance(size: numpy.ndarray[numpy.int32[2, 1]] = ..., background: bool = False, title: str = 'screen') -> LightViewer: + ... + def clear_images(self) -> None: + ... + def fit_all_plots(self) -> None: + ... + def fit_plot(self, plot_name: str) -> None: + ... + def remove_image(self, arg0: str) -> None: + ... + def spin_until_click(self) -> bool: + ... + def sub_viewer(self, name: str, size: tuple[int, int] = (-1, -1)) -> LightViewerContext: + ... + def toggle_spin_once(self) -> bool: + ... + def update_image(self, name: str, image: pyridescence.glk.Texture, scale: float = -1.0, order: int = -1) -> None: + ... + def update_plot_histogram(self, plot_name: str, label: str, xs: list[float], ys: list[float] = [], x_bins: int = -2, y_bins: int = -2, x_range: numpy.ndarray[numpy.float64[2, 1]] = ..., y_range: numpy.ndarray[numpy.float64[2, 1]] = ..., histogram_flags: int = 0) -> None: + ... + def update_plot_line(self, plot_name: str, label: str, xs: list[float], ys: list[float] = [], line_flags: int = 0, max_num_data: int = 1048576) -> None: + ... + def update_plot_scatter(self, plot_name: str, label: str, xs: list[float], ys: list[float] = [], scatter_flats: int = 0) -> None: + ... +class LightViewerContext: + def append_text(self, arg0: str) -> None: + ... + def clear(self) -> None: + ... + def clear_drawable_filters(self) -> None: + ... + def clear_drawables(self) -> None: + ... + def clear_partial_rendering(self) -> None: + ... + def clear_text(self) -> None: + ... + def color_buffer(self) -> pyridescence.glk.Texture: + ... + def depth_buffer(self) -> pyridescence.glk.Texture: + ... + def disable_partial_rendering(self) -> None: + ... + def disable_xy_grid(self) -> None: + ... + def enable_info_buffer(self) -> None: + ... + def enable_normal_buffer(self) -> None: + ... + def enable_partial_rendering(self, clear_thresh: float = 1e-06) -> None: + ... + def enable_xy_grid(self) -> None: + ... + def find_drawable(self, arg0: str) -> tuple[ShaderSetting, pyridescence.glk.Drawable]: + ... + def get_camera_control(self) -> CameraControl: + ... + def get_drawables(self) -> dict[str, tuple[ShaderSetting, pyridescence.glk.Drawable]]: + ... + def get_projection_control(self) -> ProjectionControl: + ... + def get_screen_effect(self) -> pyridescence.glk.ScreenEffect: + ... + def hide(self) -> None: + ... + def info_buffer(self) -> pyridescence.glk.Texture: + ... + def load_camera_settings(self, path: str) -> bool: + ... + def lookat(self, pt: numpy.ndarray[numpy.float32[3, 1]]) -> None: + ... + def normal_buffer(self) -> pyridescence.glk.Texture: + ... + def pick_depth(self, p: numpy.ndarray[numpy.int32[2, 1]], window: int = 2) -> float: + ... + def pick_info(self, p: numpy.ndarray[numpy.int32[2, 1]], window: int = 2) -> numpy.ndarray[numpy.int32[4, 1]]: + ... + def register_drawable_filter(self, arg0: str, arg1: typing.Callable[[str], bool]) -> None: + ... + def register_ui_callback(self, callback_name: str, callback: typing.Callable[[], None]) -> None: + ... + def remove_drawable(self, pattern: str, regex: bool = False) -> None: + ... + def remove_drawable_filter(self, arg0: str) -> None: + ... + def remove_ui_callback(self, callback_name: str) -> None: + ... + def reset_center(self) -> None: + ... + def save_camera_settings(self, path: str) -> bool: + ... + def save_color_buffer(self, path: str) -> bool: + ... + def save_depth_buffer(self, path: str, real_scale: bool = True) -> bool: + ... + def set_bg_texture(self, arg0: pyridescence.glk.Texture) -> None: + ... + def set_camera_control(self, arg0: CameraControl) -> None: + ... + def set_clear_color(self, arg0: numpy.ndarray[numpy.float32[4, 1]]) -> None: + ... + def set_colormap(self, arg0: pyridescence.glk.COLORMAP) -> None: + ... + def set_draw_xy_grid(self, arg0: bool) -> None: + ... + def set_point_shape(self, point_size: float = 1.0, metric: bool = True, circle: bool = True) -> None: + ... + def set_pos(self, pos: numpy.ndarray[numpy.int32[2, 1]], cond: int = 4, flags: int = 0) -> None: + ... + def set_projection_control(self, arg0: ProjectionControl) -> None: + ... + def set_screen_effect(self, arg0: pyridescence.glk.ScreenEffect) -> None: + ... + def set_size(self, arg0: numpy.ndarray[numpy.int32[2, 1]]) -> None: + ... + def shader_setting(self) -> ShaderSetting: + ... + def show(self) -> None: + ... + def unproject(self, p: numpy.ndarray[numpy.int32[2, 1]], depth: float) -> numpy.ndarray[numpy.float32[3, 1]]: + ... + def update_cone(self, arg0: str, arg1: ShaderSetting) -> None: + ... + def update_coord(self, arg0: str, arg1: ShaderSetting) -> None: + ... + def update_cube(self, arg0: str, arg1: ShaderSetting) -> None: + ... + def update_drawable(self, arg0: str, arg1: pyridescence.glk.Drawable, arg2: ShaderSetting) -> None: + ... + def update_frustum(self, arg0: str, arg1: ShaderSetting) -> None: + ... + def update_icosahedron(self, arg0: str, arg1: ShaderSetting) -> None: + ... + @typing.overload + def update_normal_dists(self, arg0: str, arg1: list[numpy.ndarray[numpy.float32[3, 1]]], arg2: list[numpy.ndarray[numpy.float32[3, 3]]], arg3: float, arg4: ShaderSetting) -> None: + ... + @typing.overload + def update_normal_dists(self, arg0: str, arg1: list[numpy.ndarray[numpy.float32[4, 1]]], arg2: list[numpy.ndarray[numpy.float32[4, 4]]], arg3: float, arg4: ShaderSetting) -> None: + ... + def update_points(self, arg0: str, arg1: numpy.ndarray[numpy.float32[m, n]], arg2: ShaderSetting) -> pyridescence.glk.PointCloudBuffer: + ... + def update_sphere(self, arg0: str, arg1: ShaderSetting) -> None: + ... + def update_thin_lines(self, name: str, vertices: numpy.ndarray[numpy.float32[m, n]], colors: numpy.ndarray[numpy.float32[m, n]] = ..., indices: list[int] = [], line_strip: bool = False, shader_setting: ShaderSetting = ...) -> pyridescence.glk.ThinLines: + ... + def update_wire_cone(self, arg0: str, arg1: ShaderSetting) -> None: + ... + def update_wire_cube(self, arg0: str, arg1: ShaderSetting) -> None: + ... + def update_wire_frustum(self, arg0: str, arg1: ShaderSetting) -> None: + ... + def update_wire_icosahedron(self, arg0: str, arg1: ShaderSetting) -> None: + ... + def update_wire_sphere(self, arg0: str, arg1: ShaderSetting) -> None: + ... + def use_arcball_camera_control(self, distance: float = 80.0, theta: float = 0.0, phi: float = -1.0471975511965976) -> ArcBallCameraControl: + ... + @typing.overload + def use_fps_camera_control(self, fovy_deg: float = 60.0) -> FPSCameraControl: + ... + @typing.overload + def use_fps_camera_control(self, fovy_deg: float = 60.0) -> FPSCameraControl: + ... + def use_orbit_camera_control(self, distance: float = 80.0, theta: float = 0.0, phi: float = -1.0471975511965976) -> OrbitCameraControlXY: + ... + def use_orbit_camera_control_xz(self, distance: float = 80.0, theta: float = 0.0, phi: float = 0.0) -> OrbitCameraControlXZ: + ... + def use_topdown_camera_control(self, distance: float = 80.0, theta: float = 0.0) -> TopDownCameraControl: + ... +class ModelControl: + def __init__(self, label: str = 'model_control', model_matrix: numpy.ndarray[numpy.float32[4, 4]] = ...) -> None: + ... + def disable_gizmo(self) -> None: + ... + def draw_gizmo(self) -> None: + ... + def draw_gizmo_ui(self) -> None: + ... + def draw_ui(self) -> None: + ... + def enable_gizmo(self) -> None: + ... + def model_matrix(self) -> numpy.ndarray[numpy.float32[4, 4]]: + ... + def set_gizmo_clip_scale(self, arg0: float) -> None: + ... + def set_gizmo_enabled(self, arg0: bool) -> None: + ... + def set_gizmo_mode(self, arg0: int) -> None: + ... + def set_gizmo_operation(self, arg0: str) -> None: + ... + def set_model_matrix(self, model_matrix: numpy.ndarray[numpy.float32[4, 4]]) -> None: + ... +class OrbitCameraControlXY(CameraControl): + pass +class OrbitCameraControlXZ(CameraControl): + pass +class PointScaleMode: + """ + Members: + + SCREENSPACE + + METRIC + """ + METRIC: typing.ClassVar[PointScaleMode] # value = + SCREENSPACE: typing.ClassVar[PointScaleMode] # value = + __members__: typing.ClassVar[dict[str, PointScaleMode]] # value = {'SCREENSPACE': , 'METRIC': } + def __eq__(self, other: typing.Any) -> bool: + ... + def __getstate__(self) -> int: + ... + def __hash__(self) -> int: + ... + def __index__(self) -> int: + ... + def __init__(self, value: int) -> None: + ... + def __int__(self) -> int: + ... + def __ne__(self, other: typing.Any) -> bool: + ... + def __repr__(self) -> str: + ... + def __setstate__(self, state: int) -> None: + ... + def __str__(self) -> str: + ... + @property + def name(self) -> str: + ... + @property + def value(self) -> int: + ... +class PointShapeMode: + """ + Members: + + RECTANGLE + + CIRCLE + """ + CIRCLE: typing.ClassVar[PointShapeMode] # value = + RECTANGLE: typing.ClassVar[PointShapeMode] # value = + __members__: typing.ClassVar[dict[str, PointShapeMode]] # value = {'RECTANGLE': , 'CIRCLE': } + def __eq__(self, other: typing.Any) -> bool: + ... + def __getstate__(self) -> int: + ... + def __hash__(self) -> int: + ... + def __index__(self) -> int: + ... + def __init__(self, value: int) -> None: + ... + def __int__(self) -> int: + ... + def __ne__(self, other: typing.Any) -> bool: + ... + def __repr__(self) -> str: + ... + def __setstate__(self, state: int) -> None: + ... + def __str__(self) -> str: + ... + @property + def name(self) -> str: + ... + @property + def value(self) -> int: + ... +class ProjectionControl: + pass +class Rainbow(ShaderSetting): + @typing.overload + def __init__(self) -> None: + ... + @typing.overload + def __init__(self, arg0: numpy.ndarray[numpy.float32[4, 4]]) -> None: + ... + @typing.overload + def __init__(self, scale: float = 1.0, trans: numpy.ndarray[numpy.float32[3, 1]] = ..., rot: numpy.ndarray[numpy.float32[3, 3]] = ...) -> None: + ... +class RecentFiles: + def __init__(self, arg0: str) -> None: + ... + def clear(self) -> None: + ... + def empty(self) -> bool: + ... + def filename(self, arg0: int) -> str: + ... + def fullpath(self, arg0: int) -> str: + ... + def most_recent(self) -> str: + ... + def push(self, arg0: str) -> None: + ... + def push_all(self, arg0: list[str]) -> None: + ... + def size(self) -> int: + ... +class ShaderSetting: + @typing.overload + def add(self, arg0: str, arg1: float) -> ShaderSetting: + ... + @typing.overload + def add(self, arg0: str, arg1: numpy.ndarray[numpy.float32[2, 1]]) -> ShaderSetting: + ... + @typing.overload + def add(self, arg0: str, arg1: numpy.ndarray[numpy.float32[4, 4]]) -> ShaderSetting: + ... + def addi(self, arg0: str, arg1: numpy.ndarray[numpy.int32[4, 1]]) -> ShaderSetting: + ... + def color_mode(self) -> int: + ... + def dynamic_object(self) -> ShaderSetting: + ... + def make_transparent(self) -> ShaderSetting: + ... + def material_color(self) -> numpy.ndarray[numpy.float32[4, 1]]: + ... + def model_matrix(self) -> numpy.ndarray[numpy.float32[4, 4]]: + ... + def point_scale(self) -> float: + ... + def remove_model_matrix(self) -> ShaderSetting: + ... + @typing.overload + def rotate(self, angle: float, axis: numpy.ndarray[numpy.float32[3, 1]]) -> ShaderSetting: + ... + @typing.overload + def rotate(self, rotation: numpy.ndarray[numpy.float32[3, 3]]) -> ShaderSetting: + ... + def rotation(self) -> numpy.ndarray[numpy.float32[3, 3]]: + ... + @typing.overload + def scale(self, scale: float) -> ShaderSetting: + ... + @typing.overload + def scale(self, scale: numpy.ndarray[numpy.float32[3, 1]]) -> ShaderSetting: + ... + def set_alpha(self, arg0: float) -> ShaderSetting: + ... + @typing.overload + def set_color(self, r: float, g: float, b: float, a: float = 1.0) -> ShaderSetting: + ... + @typing.overload + def set_color(self, color: numpy.ndarray[numpy.float32[4, 1]]) -> ShaderSetting: + ... + def set_color_mode(self, color_mode: int) -> ShaderSetting: + ... + def set_model_matrix(self, model_matrix: numpy.ndarray[numpy.float32[4, 4]]) -> ShaderSetting: + ... + def set_point_scale(self, scale: float) -> ShaderSetting: + ... + def set_point_scale_metric(self) -> ShaderSetting: + ... + def set_point_scale_mode(self, mode: PointScaleMode) -> ShaderSetting: + ... + def set_point_scale_screenspace(self) -> ShaderSetting: + ... + def set_point_shape(self, point_size: float, metric: bool, circle: bool) -> ShaderSetting: + ... + def set_point_shape_circle(self) -> ShaderSetting: + ... + def set_point_shape_mode(self, mode: PointShapeMode) -> ShaderSetting: + ... + def set_point_shape_rectangle(self) -> ShaderSetting: + ... + def set_point_size(self, size: float) -> ShaderSetting: + ... + def set_point_size_offset(self, offset: float) -> ShaderSetting: + ... + def static_object(self) -> ShaderSetting: + ... + def transform(self, arg0: numpy.ndarray[numpy.float32[4, 4]]) -> ShaderSetting: + ... + @typing.overload + def translate(self, x: float, y: float, z: float) -> ShaderSetting: + ... + @typing.overload + def translate(self, translation: numpy.ndarray[numpy.float32[3, 1]]) -> ShaderSetting: + ... + def translation(self) -> numpy.ndarray[numpy.float32[3, 1]]: + ... +class TopDownCameraControl(CameraControl): + pass +class VertexColor(ShaderSetting): + @typing.overload + def __init__(self) -> None: + ... + @typing.overload + def __init__(self, arg0: numpy.ndarray[numpy.float32[4, 4]]) -> None: + ... + @typing.overload + def __init__(self, scale: float = 1.0, trans: numpy.ndarray[numpy.float32[3, 1]] = ..., rot: numpy.ndarray[numpy.float32[3, 3]] = ...) -> None: + ... +def anon() -> str: + ... +def async_destroy() -> None: + ... +def async_viewer(size: numpy.ndarray[numpy.int32[2, 1]] = ..., background: bool = False, title: str = 'screen') -> AsyncLightViewer: + ... +def async_wait() -> None: + ... +def destroy() -> None: + ... +def viewer(size: numpy.ndarray[numpy.int32[2, 1]] = ..., background: bool = False, title: str = 'screen') -> LightViewer: + ... +CIRCLE: PointShapeMode # value = +METRIC: PointScaleMode # value = +RECTANGLE: PointShapeMode # value = +SCREENSPACE: PointScaleMode # value = diff --git a/src/python/stubs/pyridescence/imgui.pyi b/src/python/stubs/pyridescence/imgui.pyi new file mode 100644 index 00000000..7aa1dcd4 --- /dev/null +++ b/src/python/stubs/pyridescence/imgui.pyi @@ -0,0 +1,713 @@ +""" +""" +from __future__ import annotations +import numpy +import pyridescence.glk +import typing +__all__: list[str] = ['ButtonFlags_MouseButtonLeft', 'ButtonFlags_MouseButtonMiddle', 'ButtonFlags_MouseButtonRight', 'ButtonFlags_None', 'ColorEditFlags_AlphaBar', 'ColorEditFlags_AlphaPreview', 'ColorEditFlags_AlphaPreviewHalf', 'ColorEditFlags_DisplayHSV', 'ColorEditFlags_DisplayHex', 'ColorEditFlags_DisplayRGB', 'ColorEditFlags_Float', 'ColorEditFlags_HDR', 'ColorEditFlags_InputHSV', 'ColorEditFlags_InputRGB', 'ColorEditFlags_NoAlpha', 'ColorEditFlags_NoBorder', 'ColorEditFlags_NoDragDrop', 'ColorEditFlags_NoInputs', 'ColorEditFlags_NoLabel', 'ColorEditFlags_NoOptions', 'ColorEditFlags_NoPicker', 'ColorEditFlags_NoSidePreview', 'ColorEditFlags_NoSmallPreview', 'ColorEditFlags_NoTooltip', 'ColorEditFlags_None', 'ColorEditFlags_PickerHueBar', 'ColorEditFlags_PickerHueWheel', 'ColorEditFlags_Uint8', 'Cond_Always', 'Cond_Appearing', 'Cond_FirstUseEver', 'Cond_Once', 'Dir_Down', 'Dir_Left', 'Dir_None', 'Dir_Right', 'Dir_Up', 'DockNodeFlags_AutoHideTabBar', 'DockNodeFlags_KeepAliveOnly', 'DockNodeFlags_NoDockingInCentralNode', 'DockNodeFlags_NoResize', 'DockNodeFlags_NoSplit', 'DockNodeFlags_None', 'DockNodeFlags_PassthruCentralNode', 'IM_COL32', 'IO', 'ImDrawList', 'ImVec2', 'ImVec4', 'MouseButton_Left', 'MouseButton_Middle', 'MouseButton_Right', 'Style', 'TableFlags_Borders', 'TableFlags_BordersH', 'TableFlags_BordersInner', 'TableFlags_BordersInnerH', 'TableFlags_BordersInnerV', 'TableFlags_BordersOuter', 'TableFlags_BordersOuterH', 'TableFlags_BordersOuterV', 'TableFlags_BordersV', 'TableFlags_ContextMenuInBody', 'TableFlags_Hideable', 'TableFlags_NoBordersInBody', 'TableFlags_NoBordersInBodyUntilResize', 'TableFlags_NoClip', 'TableFlags_NoHostExtendX', 'TableFlags_NoHostExtendY', 'TableFlags_NoKeepColumnsVisible', 'TableFlags_NoPadInnerX', 'TableFlags_NoPadOuterX', 'TableFlags_NoSavedSettings', 'TableFlags_None', 'TableFlags_PadOuterX', 'TableFlags_PreciseWidths', 'TableFlags_Reorderable', 'TableFlags_Resizable', 'TableFlags_RowBg', 'TableFlags_ScrollX', 'TableFlags_ScrollY', 'TableFlags_SizingFixedFit', 'TableFlags_SizingFixedSame', 'TableFlags_SizingMask_', 'TableFlags_SizingStretchProp', 'TableFlags_SizingStretchSame', 'TableFlags_SortMulti', 'TableFlags_SortTristate', 'TableFlags_Sortable', 'WindowFlags_AlwaysAutoResize', 'WindowFlags_NoBackground', 'WindowFlags_NoMove', 'WindowFlags_NoResize', 'WindowFlags_NoScrollbar', 'WindowFlags_NoTitleBar', 'WindowFlags_None', 'align_text_to_frame_padding', 'arrow_button', 'begin', 'begin_child', 'begin_combo', 'begin_group', 'begin_main_menu_bar', 'begin_menu', 'begin_menu_bar', 'begin_popup', 'begin_popup_modal', 'begin_tab_bar', 'begin_tab_item', 'begin_table', 'begin_tooltip', 'bullet', 'bullet_text', 'button', 'calc_item_width', 'calc_text_size', 'checkbox', 'checkbox_flags', 'close_current_popup', 'collapsing_header', 'collapsing_header_bool', 'color_button', 'color_edit3', 'color_edit4', 'color_picker3', 'color_picker4', 'combo', 'dock_builder_add_node', 'dock_builder_dock_window', 'dock_builder_finish', 'dock_builder_remove_node', 'dock_builder_split_node', 'dockspace', 'dockspace_over_viewport', 'drag_float', 'drag_float2', 'drag_float3', 'drag_float4', 'drag_float_range2', 'drag_int', 'drag_int2', 'drag_int3', 'drag_int4', 'drag_int_range2', 'dummy', 'end', 'end_child', 'end_combo', 'end_group', 'end_main_menu_bar', 'end_menu', 'end_menu_bar', 'end_popup', 'end_tab_bar', 'end_tab_item', 'end_table', 'end_tooltip', 'get_background_draw_list', 'get_clipboard_text', 'get_content_region_avail', 'get_content_region_max', 'get_cursor_pos', 'get_cursor_pos_x', 'get_cursor_pos_y', 'get_cursor_screen_pos', 'get_foreground_draw_list', 'get_frame_count', 'get_frame_height', 'get_frame_height_with_spacing', 'get_id', 'get_io', 'get_item_id', 'get_item_rect_max', 'get_item_rect_min', 'get_item_rect_size', 'get_key_name', 'get_key_pressed_amount', 'get_mouse_clicked_count', 'get_mouse_drag_delta', 'get_mouse_pos', 'get_mouse_pos_on_opening_current_popup', 'get_style', 'get_text_line_height', 'get_text_line_height_with_spacing', 'get_time', 'get_tree_node_to_label_spacing', 'get_version', 'get_window_content_region_max', 'get_window_content_region_min', 'get_window_draw_list', 'get_window_height', 'get_window_pos', 'get_window_size', 'get_window_width', 'image', 'image_button', 'indent', 'input_double', 'input_float', 'input_float2', 'input_float3', 'input_float4', 'input_int', 'input_int2', 'input_int3', 'input_int4', 'input_text', 'input_text_multiline', 'input_text_with_hint', 'invisible_button', 'is_any_item_active', 'is_any_item_focused', 'is_any_item_hovered', 'is_any_mouse_down', 'is_item_activated', 'is_item_active', 'is_item_clicked', 'is_item_deactivated', 'is_item_deactivated_after_edit', 'is_item_edited', 'is_item_focused', 'is_item_hovered', 'is_item_toggled_open', 'is_item_visible', 'is_key_down', 'is_key_pressed', 'is_key_released', 'is_mouse_clicked', 'is_mouse_double_clicked', 'is_mouse_down', 'is_mouse_dragging', 'is_mouse_hovering_rect', 'is_mouse_pos_valid', 'is_mouse_released', 'is_popup_open', 'is_rect_visible', 'is_rect_visible_pos_size', 'is_window_appearing', 'is_window_collapsed', 'is_window_focused', 'is_window_hovered', 'label_text', 'menu_item', 'newline', 'open_popup', 'open_popup_on_item_click', 'pop_button_repeat', 'pop_id', 'pop_item_width', 'pop_text_wrap_pos', 'progress_bar', 'push_button_repeat', 'push_id', 'push_item_width', 'push_text_wrap_pos', 'radio_button', 'radio_button_int', 'reset_mouse_drag_delta', 'same_line', 'selectable', 'separator', 'set_clipboard_text', 'set_cursor_pos', 'set_cursor_pos_x', 'set_cursor_pos_y', 'set_cursor_screen_pos', 'set_item_allow_overlap', 'set_item_default_focus', 'set_keyboard_focus_here', 'set_next_item_open', 'set_next_item_width', 'set_next_window_bg_alpha', 'set_next_window_collapsed', 'set_next_window_content_size', 'set_next_window_dock_id', 'set_next_window_focus', 'set_next_window_pos', 'set_next_window_scroll', 'set_next_window_size', 'set_next_window_size_constraints', 'set_tab_item_closed', 'set_tooltip', 'set_window_collapsed', 'set_window_focus', 'set_window_font_scale', 'set_window_pos', 'set_window_size', 'show_debug_log_window', 'show_demo_window', 'show_font_selector', 'show_metrics_window', 'show_style_editor', 'show_style_selector', 'slider_angle', 'slider_float', 'slider_float2', 'slider_float3', 'slider_float4', 'slider_int', 'slider_int2', 'slider_int3', 'slider_int4', 'small_button', 'spacing', 'style_colors_classic', 'style_colors_dark', 'style_colors_light', 'tab_item_button', 'table_header', 'table_headers_row', 'table_next_column', 'table_next_row', 'table_set_column_index', 'table_setup_column', 'table_setup_scroll_freeze', 'text', 'text_colored', 'text_disabled', 'text_unformatted', 'text_wrapped', 'tree_node', 'tree_pop', 'tree_push_str', 'unindent'] +class IO: + @property + def delta_time(self) -> float: + ... + @property + def framerate(self) -> float: + ... + @property + def key_alt(self) -> bool: + ... + @property + def key_ctrl(self) -> bool: + ... + @property + def key_shift(self) -> bool: + ... + @property + def key_super(self) -> bool: + ... + @property + def keys_down(self) -> numpy.ndarray: + ... + @property + def mouse_clicked(self) -> numpy.ndarray: + ... + @property + def mouse_down(self) -> numpy.ndarray: + ... + @property + def mouse_pos(self) -> numpy.ndarray: + ... + @property + def mouse_wheel(self) -> float: + ... + @property + def mouse_wheel_h(self) -> float: + ... + @property + def nav_inputs(self) -> numpy.ndarray: + ... + @property + def want_capture_keyboard(self) -> bool: + ... + @property + def want_capture_mouse(self) -> bool: + ... +class ImDrawList: + def add_circle(self, center: numpy.ndarray[numpy.int32[2, 1]], radius: float, color: int, num_segments: int = 0, thickness: float = 1.0) -> None: + ... + def add_circle_filled(self, center: numpy.ndarray[numpy.int32[2, 1]], radius: float, color: int, num_segments: int = 0) -> None: + ... + def add_line(self, p0: numpy.ndarray[numpy.int32[2, 1]], p1: numpy.ndarray[numpy.int32[2, 1]], col: int, thickness: float = 1.0) -> None: + ... + def add_rect(self, p0: numpy.ndarray[numpy.int32[2, 1]], p1: numpy.ndarray[numpy.int32[2, 1]], color: int, rounding: float = 0.0, flags: int = 0, thickness: float = 1.0) -> None: + ... + def add_rect_filled(self, p0: numpy.ndarray[numpy.int32[2, 1]], p1: numpy.ndarray[numpy.int32[2, 1]], color: int, rounding: float = 0.0, flags: int = 0) -> None: + ... + def add_text(self, pos: numpy.ndarray[numpy.int32[2, 1]], color: int, text: str) -> None: + ... +class ImVec2: + x: float + y: float + def __buffer__(self, flags): + """ + Return a buffer object that exposes the underlying memory of the object. + """ + @typing.overload + def __init__(self, arg0: float, arg1: float) -> None: + ... + @typing.overload + def __init__(self, arg0: numpy.ndarray[numpy.float32]) -> None: + ... + def __release_buffer__(self, buffer): + """ + Release the buffer object that exposes the underlying memory of the object. + """ +class ImVec4: + w: float + x: float + y: float + z: float + def __buffer__(self, flags): + """ + Return a buffer object that exposes the underlying memory of the object. + """ + @typing.overload + def __init__(self, arg0: float, arg1: float, arg2: float, arg3: float) -> None: + ... + @typing.overload + def __init__(self, arg0: numpy.ndarray[numpy.float32]) -> None: + ... + def __release_buffer__(self, buffer): + """ + Release the buffer object that exposes the underlying memory of the object. + """ +class Style: + alpha: float + anti_aliased_fill: bool + anti_aliased_lines: bool + anti_aliased_lines_use_tex: bool + button_text_align: ImVec2 + cell_padding: ImVec2 + child_border_size: float + child_rounding: float + circle_tessellation_max_error: float + color_button_position: int + columns_min_spacing: float + curve_tessellation_tol: float + disabled_alpha: float + display_safe_area_padding: ImVec2 + display_window_padding: ImVec2 + frame_border_size: float + frame_padding: ImVec2 + frame_rounding: float + grab_min_size: float + grab_rounding: float + indent_spacing: float + item_inner_spacing: ImVec2 + item_spacing: ImVec2 + mouse_cursor_scale: float + popup_border_size: float + popup_rounding: float + scrollbar_rounding: float + scrollbar_size: float + selectable_text_align: ImVec2 + tab_border_size: float + tab_min_width_for_close_button: float + tab_rounding: float + touch_extra_padding: ImVec2 + window_border_size: float + window_menu_button_position: int + window_min_size: ImVec2 + window_padding: ImVec2 + window_rounding: float + window_title_align: ImVec2 + @property + def colors(self) -> list: + ... +def IM_COL32(r: int, g: int, b: int, a: int) -> int: + ... +def align_text_to_frame_padding() -> None: + ... +def arrow_button(id: str, dir: int) -> bool: + ... +def begin(name: str, open: bool = True, flags: int = 0) -> tuple[bool, bool]: + ... +def begin_child(str_id: str, size: numpy.ndarray[numpy.int32[2, 1]] = ..., border: bool = False, flags: int = 0) -> bool: + ... +def begin_combo(label: str, preview_value: str, flags: int = 0) -> bool: + ... +def begin_group() -> None: + ... +def begin_main_menu_bar() -> bool: + ... +def begin_menu(label: str, enabled: bool = True) -> bool: + ... +def begin_menu_bar() -> bool: + ... +def begin_popup(id: str, flags: int) -> bool: + ... +def begin_popup_modal(name: str, flags: int = 0) -> bool: + ... +def begin_tab_bar(id: str, flags: int = 0) -> bool: + ... +def begin_tab_item(label: str) -> bool: + ... +def begin_table(str_id: str, column_n: int, flags: int = 0, outer_size: ImVec2 = ..., inner_width: float = 0.0) -> bool: + ... +def begin_tooltip() -> None: + ... +def bullet() -> None: + ... +def bullet_text(text: str) -> None: + ... +def button(label: str, size: numpy.ndarray[numpy.int32[2, 1]] = ...) -> bool: + ... +def calc_item_width() -> float: + ... +def calc_text_size(text: str, wrap_width: float = -1.0, hide_text_after_double_hash: bool = False) -> numpy.ndarray[numpy.float32[2, 1]]: + ... +def checkbox(label: str, v: bool) -> tuple[bool, bool]: + ... +def checkbox_flags(label: str, flags: int, flags_value: int) -> tuple[bool, int]: + ... +def close_current_popup() -> None: + ... +def collapsing_header(label: str, flags: int = 0) -> bool: + ... +def collapsing_header_bool(label: str, open: bool, flags: int = 0) -> tuple[bool, bool]: + ... +def color_button(desc_id: str, color: numpy.ndarray[numpy.float32[4, 1]], flags: int = 0, size: numpy.ndarray[numpy.int32[2, 1]] = ...) -> bool: + ... +def color_edit3(label: str, color: numpy.ndarray[numpy.float32[3, 1]], flags: int = 0) -> tuple[bool, numpy.ndarray[numpy.float32[3, 1]]]: + ... +def color_edit4(label: str, color: numpy.ndarray[numpy.float32[4, 1]], flags: int = 0) -> tuple[bool, numpy.ndarray[numpy.float32[4, 1]]]: + ... +def color_picker3(label: str, color: numpy.ndarray[numpy.float32[3, 1]], flags: int = 0) -> tuple[bool, numpy.ndarray[numpy.float32[3, 1]]]: + ... +def color_picker4(label: str, color: numpy.ndarray[numpy.float32[4, 1]], flags: int = 0) -> tuple[bool, numpy.ndarray[numpy.float32[4, 1]]]: + ... +def combo(label: str, current_item: int, items: list[str], popup_max_height_in_items: int = -1) -> tuple[bool, int]: + ... +def dock_builder_add_node(node_id: int = 0, flags: int = 0) -> int: + ... +def dock_builder_dock_window(window_name: str, node_id: int) -> None: + ... +def dock_builder_finish(node_id: int) -> None: + ... +def dock_builder_remove_node(node_id: int) -> None: + ... +def dock_builder_split_node(node_id: int, split_dir: int, size_ratio_for_node_at_dir: float) -> tuple[int, int]: + ... +def dockspace(id: int, size: numpy.ndarray[numpy.int32[2, 1]] = ..., flags: int = 0) -> int: + ... +def dockspace_over_viewport(flags: int = 0) -> int: + ... +def drag_float(label: str, v: float, v_speed: float = 1.0, v_min: float = 0.0, v_max: float = 0.0, format: str = '%.3f', power: float = 1.0) -> tuple[bool, float]: + ... +def drag_float2(label: str, v: numpy.ndarray[numpy.float32[2, 1]], v_speed: float = 1.0, v_min: float = 0.0, v_max: float = 0.0, format: str = '%.3f', power: float = 1.0) -> tuple[bool, numpy.ndarray[numpy.float32[2, 1]]]: + ... +def drag_float3(label: str, v: numpy.ndarray[numpy.float32[3, 1]], v_speed: float = 1.0, v_min: float = 0.0, v_max: float = 0.0, format: str = '%.3f', power: float = 1.0) -> tuple[bool, numpy.ndarray[numpy.float32[3, 1]]]: + ... +def drag_float4(label: str, v: numpy.ndarray[numpy.float32[4, 1]], v_speed: float = 1.0, v_min: float = 0.0, v_max: float = 0.0, format: str = '%.3f', power: float = 1.0) -> tuple[bool, numpy.ndarray[numpy.float32[4, 1]]]: + ... +def drag_float_range2(label: str, v: numpy.ndarray[numpy.float32[2, 1]], v_speed: float = 1.0, v_min: float = 0.0, v_max: float = 0.0, format: str = '%.3f', format_max: str = '%.3f', power: float = 1.0) -> tuple[bool, numpy.ndarray[numpy.float32[2, 1]]]: + ... +def drag_int(label: str, v: int, v_speed: int = 1, v_min: int = 0, v_max: int = 0, format: str = '%d') -> tuple[bool, int]: + ... +def drag_int2(label: str, v: numpy.ndarray[numpy.int32[2, 1]], v_speed: int = 1, v_min: int = 0, v_max: int = 0, format: str = '%d') -> tuple[bool, numpy.ndarray[numpy.int32[2, 1]]]: + ... +def drag_int3(label: str, v: numpy.ndarray[numpy.int32[3, 1]], v_speed: int = 1, v_min: int = 0, v_max: int = 0, format: str = '%d') -> tuple[bool, numpy.ndarray[numpy.int32[3, 1]]]: + ... +def drag_int4(label: str, v: numpy.ndarray[numpy.int32[4, 1]], v_speed: int = 1, v_min: int = 0, v_max: int = 0, format: str = '%d') -> tuple[bool, numpy.ndarray[numpy.int32[4, 1]]]: + ... +def drag_int_range2(label: str, v: numpy.ndarray[numpy.int32[2, 1]], v_speed: int = 1, v_min: int = 0, v_max: int = 0, format: str = '%d', format_max: str = '%d') -> tuple[bool, numpy.ndarray[numpy.int32[2, 1]]]: + ... +def dummy(size: numpy.ndarray[numpy.int32[2, 1]]) -> None: + ... +def end() -> None: + ... +def end_child() -> None: + ... +def end_combo() -> None: + ... +def end_group() -> None: + ... +def end_main_menu_bar() -> None: + ... +def end_menu() -> None: + ... +def end_menu_bar() -> None: + ... +def end_popup() -> None: + ... +def end_tab_bar() -> None: + ... +def end_tab_item() -> None: + ... +def end_table() -> None: + ... +def end_tooltip() -> None: + ... +def get_background_draw_list() -> ImDrawList: + ... +def get_clipboard_text() -> str: + ... +def get_content_region_avail() -> numpy.ndarray[numpy.float32[2, 1]]: + ... +def get_content_region_max() -> numpy.ndarray[numpy.float32[2, 1]]: + ... +def get_cursor_pos() -> numpy.ndarray[numpy.float32[2, 1]]: + ... +def get_cursor_pos_x() -> float: + ... +def get_cursor_pos_y() -> float: + ... +def get_cursor_screen_pos() -> numpy.ndarray[numpy.float32[2, 1]]: + ... +def get_foreground_draw_list() -> ImDrawList: + ... +def get_frame_count() -> int: + ... +def get_frame_height() -> float: + ... +def get_frame_height_with_spacing() -> float: + ... +def get_id(name: str) -> int: + ... +def get_io() -> IO: + ... +def get_item_id() -> int: + ... +def get_item_rect_max() -> numpy.ndarray[numpy.float32[2, 1]]: + ... +def get_item_rect_min() -> numpy.ndarray[numpy.float32[2, 1]]: + ... +def get_item_rect_size() -> numpy.ndarray[numpy.float32[2, 1]]: + ... +def get_key_name(key_index: int) -> str: + ... +def get_key_pressed_amount(key: ImGuiKey, repeat_delay: float = 0.0, repeat_rate: float = 0.0) -> int: + ... +def get_mouse_clicked_count(button: int) -> int: + ... +def get_mouse_drag_delta(button: int = 0, lock_threshold: float = -1.0) -> numpy.ndarray[numpy.float32[2, 1]]: + ... +def get_mouse_pos() -> numpy.ndarray[numpy.float32[2, 1]]: + ... +def get_mouse_pos_on_opening_current_popup() -> numpy.ndarray[numpy.float32[2, 1]]: + ... +def get_style() -> Style: + ... +def get_text_line_height() -> float: + ... +def get_text_line_height_with_spacing() -> float: + ... +def get_time() -> float: + ... +def get_tree_node_to_label_spacing() -> float: + ... +def get_version() -> str: + ... +def get_window_content_region_max() -> numpy.ndarray[numpy.float32[2, 1]]: + ... +def get_window_content_region_min() -> numpy.ndarray[numpy.float32[2, 1]]: + ... +@typing.overload +def get_window_draw_list() -> ImDrawList: + ... +@typing.overload +def get_window_draw_list() -> ImDrawList: + ... +def get_window_height() -> float: + ... +def get_window_pos() -> numpy.ndarray[numpy.int32[2, 1]]: + ... +def get_window_size() -> numpy.ndarray[numpy.int32[2, 1]]: + ... +def get_window_width() -> float: + ... +def image(texture: pyridescence.glk.Texture, size: numpy.ndarray[numpy.int32[2, 1]], uv0: numpy.ndarray[numpy.float32[2, 1]] = ..., uv1: numpy.ndarray[numpy.float32[2, 1]] = ..., tint_col: numpy.ndarray[numpy.float32[4, 1]] = ..., border_col: numpy.ndarray[numpy.float32[4, 1]] = ...) -> None: + ... +def image_button(str_id: str, texture: pyridescence.glk.Texture, size: numpy.ndarray[numpy.int32[2, 1]], uv0: numpy.ndarray[numpy.float32[2, 1]] = ..., uv1: numpy.ndarray[numpy.float32[2, 1]] = ..., bg_col: numpy.ndarray[numpy.float32[4, 1]] = ..., tint_col: numpy.ndarray[numpy.float32[4, 1]] = ...) -> bool: + ... +def indent(indent_w: float = 0.0) -> None: + ... +def input_double(label: str, v: float, step: float = 0.0, step_fast: float = 0.0, format: str = '%.6f', flags: int = 0) -> tuple[bool, float]: + ... +def input_float(label: str, v: float, step: float = 0.0, step_fast: float = 0.0, format: str = '%.3f', flags: int = 0) -> tuple[bool, float]: + ... +def input_float2(label: str, v: numpy.ndarray[numpy.float32[2, 1]], format: str = '%.3f', flags: int = 0) -> tuple[bool, numpy.ndarray[numpy.float32[2, 1]]]: + ... +def input_float3(label: str, v: numpy.ndarray[numpy.float32[3, 1]], format: str = '%.3f', flags: int = 0) -> tuple[bool, numpy.ndarray[numpy.float32[3, 1]]]: + ... +def input_float4(label: str, v: numpy.ndarray[numpy.float32[4, 1]], format: str = '%.3f', flags: int = 0) -> tuple[bool, numpy.ndarray[numpy.float32[4, 1]]]: + ... +def input_int(label: str, v: int, step: int = 1, step_fast: int = 100, flags: int = 0) -> tuple[bool, int]: + ... +def input_int2(label: str, v: numpy.ndarray[numpy.int32[2, 1]], flags: int = 0) -> tuple[bool, numpy.ndarray[numpy.int32[2, 1]]]: + ... +def input_int3(label: str, v: numpy.ndarray[numpy.int32[3, 1]], flags: int = 0) -> tuple[bool, numpy.ndarray[numpy.int32[3, 1]]]: + ... +def input_int4(label: str, v: numpy.ndarray[numpy.int32[4, 1]], flags: int = 0) -> tuple[bool, numpy.ndarray[numpy.int32[4, 1]]]: + ... +def input_text(label: str, text: str, flags: int = 0, buffer_size: int = 256) -> tuple[bool, str]: + ... +def input_text_multiline(label: str, text: str, size: numpy.ndarray[numpy.int32[2, 1]] = ..., flags: int = 0, buffer_size: int = 256) -> tuple[bool, str]: + ... +def input_text_with_hint(label: str, hint: str, text: str, flags: int = 0, buffer_size: int = 256) -> tuple[bool, str]: + ... +def invisible_button(id: str, size: numpy.ndarray[numpy.int32[2, 1]], flags: int = 0) -> bool: + ... +def is_any_item_active() -> bool: + ... +def is_any_item_focused() -> bool: + ... +def is_any_item_hovered() -> bool: + ... +def is_any_mouse_down() -> bool: + ... +def is_item_activated() -> bool: + ... +def is_item_active() -> bool: + ... +def is_item_clicked(mouse_button: int = 0) -> bool: + ... +def is_item_deactivated() -> bool: + ... +def is_item_deactivated_after_edit() -> bool: + ... +def is_item_edited() -> bool: + ... +def is_item_focused() -> bool: + ... +def is_item_hovered(flags: int = 0) -> bool: + ... +def is_item_toggled_open() -> bool: + ... +def is_item_visible() -> bool: + ... +def is_key_down(key: int) -> bool: + ... +def is_key_pressed(key: int, repeat: bool = False) -> bool: + ... +def is_key_released(key: int) -> bool: + ... +def is_mouse_clicked(button: int, repeat: bool = False) -> bool: + ... +def is_mouse_double_clicked(button: int) -> bool: + ... +def is_mouse_down(button: int) -> bool: + ... +def is_mouse_dragging(button: int, lock_threshold: float = -1.0) -> bool: + ... +def is_mouse_hovering_rect(r_min: numpy.ndarray[numpy.float32[2, 1]], r_max: numpy.ndarray[numpy.float32[2, 1]], clip: bool = True) -> bool: + ... +def is_mouse_pos_valid(mouse_pos: numpy.ndarray[numpy.float32[2, 1]] = ...) -> bool: + ... +def is_mouse_released(button: int) -> bool: + ... +def is_popup_open(name: str, flags: int = 0) -> bool: + ... +def is_rect_visible(arg0: numpy.ndarray[numpy.float32[2, 1]]) -> bool: + ... +def is_rect_visible_pos_size(arg0: numpy.ndarray[numpy.float32[2, 1]], arg1: numpy.ndarray[numpy.float32[2, 1]]) -> bool: + ... +def is_window_appearing() -> bool: + ... +def is_window_collapsed() -> bool: + ... +def is_window_focused(flags: int = 0) -> bool: + ... +def is_window_hovered(flags: int = 0) -> bool: + ... +def label_text(label: str, text: str) -> None: + ... +def menu_item(label: str, shortcut: str = '', selected: bool = False, enabled: bool = True) -> bool: + ... +def newline() -> None: + ... +def open_popup(name: str) -> None: + ... +def open_popup_on_item_click(str_id: str, mouse_button: int = 0) -> None: + ... +def pop_button_repeat() -> None: + ... +def pop_id() -> None: + ... +def pop_item_width() -> None: + ... +def pop_text_wrap_pos() -> None: + ... +def progress_bar(fraction: float, size: numpy.ndarray[numpy.int32[2, 1]] = ..., overlay: str = '') -> None: + ... +def push_button_repeat(repeat: bool) -> None: + ... +def push_id(str_id: str) -> None: + ... +def push_item_width(item_width: float) -> None: + ... +def push_text_wrap_pos(wrap_local_pos_x: float = 0.0) -> None: + ... +def radio_button(label: str, active: bool) -> bool: + ... +def radio_button_int(label: str, v: int, v_button: int) -> tuple[bool, int]: + ... +def reset_mouse_drag_delta(button: int = 0) -> None: + ... +def same_line(offset_from_start_x: float = 0.0, spacing: float = -1.0) -> None: + ... +def selectable(label: str, selected: bool = False, flags: int = 0, size: numpy.ndarray[numpy.int32[2, 1]] = ...) -> bool: + ... +def separator() -> None: + ... +def set_clipboard_text(text: str) -> None: + ... +def set_cursor_pos(pos: numpy.ndarray[numpy.float32[2, 1]]) -> None: + ... +def set_cursor_pos_x(x: float) -> None: + ... +def set_cursor_pos_y(y: float) -> None: + ... +def set_cursor_screen_pos(pos: numpy.ndarray[numpy.float32[2, 1]]) -> None: + ... +def set_item_allow_overlap() -> None: + ... +def set_item_default_focus() -> None: + ... +def set_keyboard_focus_here(offset: int = 0) -> None: + ... +def set_next_item_open(is_open: bool, cond: int = 0) -> None: + ... +def set_next_item_width(item_width: float) -> None: + ... +def set_next_window_bg_alpha(alpha: float) -> None: + ... +def set_next_window_collapsed(collapsed: bool, cond: int = 0) -> None: + ... +def set_next_window_content_size(size: numpy.ndarray[numpy.int32[2, 1]]) -> None: + ... +def set_next_window_dock_id(dock_id: int, cond: int = 0) -> None: + ... +def set_next_window_focus() -> None: + ... +def set_next_window_pos(pos: numpy.ndarray[numpy.int32[2, 1]], cond: int = 0, pivot: numpy.ndarray[numpy.int32[2, 1]] = ...) -> None: + ... +def set_next_window_scroll(scroll: numpy.ndarray[numpy.int32[2, 1]]) -> None: + ... +def set_next_window_size(size: numpy.ndarray[numpy.int32[2, 1]], cond: int = 0) -> None: + ... +def set_next_window_size_constraints(size_min: numpy.ndarray[numpy.int32[2, 1]], size_max: numpy.ndarray[numpy.int32[2, 1]]) -> None: + ... +def set_tab_item_closed(tab_or_dockspace_id: str) -> None: + ... +def set_tooltip(fmt: str) -> None: + ... +@typing.overload +def set_window_collapsed(collapsed: bool, cond: int = 0) -> None: + ... +@typing.overload +def set_window_collapsed(name: str, collapsed: bool, cond: int = 0) -> None: + ... +@typing.overload +def set_window_focus() -> None: + ... +@typing.overload +def set_window_focus(name: str) -> None: + ... +def set_window_font_scale(scale: float) -> None: + ... +@typing.overload +def set_window_pos(pos: numpy.ndarray[numpy.int32[2, 1]], cond: int = 0) -> None: + ... +@typing.overload +def set_window_pos(name: str, pos: numpy.ndarray[numpy.int32[2, 1]], cond: int = 0) -> None: + ... +@typing.overload +def set_window_size(size: numpy.ndarray[numpy.int32[2, 1]], cond: int = 0) -> None: + ... +@typing.overload +def set_window_size(name: str, size: numpy.ndarray[numpy.int32[2, 1]], cond: int = 0) -> None: + ... +def show_debug_log_window() -> None: + ... +def show_demo_window() -> None: + ... +def show_font_selector(label: str) -> None: + ... +def show_metrics_window() -> None: + ... +def show_style_editor() -> None: + ... +def show_style_selector(label: str) -> None: + ... +def slider_angle(label: str, v_rad: float, v_degrees_min: float = -360.0, v_degrees_max: float = 360.0, format: str = '%.0f deg', flags: int = 0) -> tuple[bool, float]: + ... +def slider_float(label: str, v: float, v_min: float, v_max: float, format: str = '%.3f', power: float = 1.0) -> tuple[bool, float]: + ... +def slider_float2(label: str, v: numpy.ndarray[numpy.float32[2, 1]], v_min: float, v_max: float, format: str = '%.3f', power: float = 1.0) -> tuple[bool, numpy.ndarray[numpy.float32[2, 1]]]: + ... +def slider_float3(label: str, v: numpy.ndarray[numpy.float32[3, 1]], v_min: float, v_max: float, format: str = '%.3f', flags: int = 0) -> tuple[bool, numpy.ndarray[numpy.float32[3, 1]]]: + ... +def slider_float4(label: str, v: numpy.ndarray[numpy.float32[4, 1]], v_min: float, v_max: float, format: str = '%.3f', flags: int = 0) -> tuple[bool, numpy.ndarray[numpy.float32[4, 1]]]: + ... +def slider_int(label: str, v: int, v_min: int, v_max: int, format: str = '%d', flags: int = 0) -> tuple[bool, int]: + ... +def slider_int2(label: str, v: numpy.ndarray[numpy.int32[2, 1]], v_min: int, v_max: int, format: str = '%d', flags: int = 0) -> tuple[bool, numpy.ndarray[numpy.int32[2, 1]]]: + ... +def slider_int3(label: str, v: numpy.ndarray[numpy.int32[3, 1]], v_min: int, v_max: int, format: str = '%d', flags: int = 0) -> tuple[bool, numpy.ndarray[numpy.int32[3, 1]]]: + ... +def slider_int4(label: str, v: numpy.ndarray[numpy.int32[4, 1]], v_min: int, v_max: int, format: str = '%d', flags: int = 0) -> tuple[bool, numpy.ndarray[numpy.int32[4, 1]]]: + ... +def small_button(label: str) -> bool: + ... +def spacing() -> None: + ... +def style_colors_classic(dst: Style = None) -> None: + ... +def style_colors_dark(dst: Style = None) -> None: + ... +def style_colors_light(dst: Style = None) -> None: + ... +def tab_item_button(label: str, flags: int = 0) -> bool: + ... +def table_header(label: str) -> None: + ... +def table_headers_row() -> None: + ... +def table_next_column() -> bool: + ... +def table_next_row(row_flags: int = 0, min_row_height: float = 0.0) -> None: + ... +def table_set_column_index(column_index: int) -> bool: + ... +def table_setup_column(label: str, flags: int = 0, init_width_or_weight: float = 0.0, user_id: int = 0) -> None: + ... +def table_setup_scroll_freeze(cols: int, rows: int) -> None: + ... +def text(text: str) -> None: + ... +def text_colored(col: numpy.ndarray[numpy.float32[4, 1]], text: str) -> None: + ... +def text_disabled(text: str) -> None: + ... +def text_unformatted(text: str) -> None: + ... +def text_wrapped(text: str) -> None: + ... +def tree_node(label: str) -> bool: + ... +def tree_pop() -> None: + ... +def tree_push_str(str_id: str) -> None: + ... +def unindent(indent_w: float = 0.0) -> None: + ... +ButtonFlags_MouseButtonLeft: int = 1 +ButtonFlags_MouseButtonMiddle: int = 4 +ButtonFlags_MouseButtonRight: int = 2 +ButtonFlags_None: int = 0 +ColorEditFlags_AlphaBar: int = 2 +ColorEditFlags_AlphaPreview: int = 2 +ColorEditFlags_AlphaPreviewHalf: int = 2 +ColorEditFlags_DisplayHSV: int = 2 +ColorEditFlags_DisplayHex: int = 2 +ColorEditFlags_DisplayRGB: int = 2 +ColorEditFlags_Float: int = 2 +ColorEditFlags_HDR: int = 2 +ColorEditFlags_InputHSV: int = 2 +ColorEditFlags_InputRGB: int = 2 +ColorEditFlags_NoAlpha: int = 2 +ColorEditFlags_NoBorder: int = 2 +ColorEditFlags_NoDragDrop: int = 2 +ColorEditFlags_NoInputs: int = 2 +ColorEditFlags_NoLabel: int = 2 +ColorEditFlags_NoOptions: int = 2 +ColorEditFlags_NoPicker: int = 2 +ColorEditFlags_NoSidePreview: int = 2 +ColorEditFlags_NoSmallPreview: int = 2 +ColorEditFlags_NoTooltip: int = 2 +ColorEditFlags_None: int = 0 +ColorEditFlags_PickerHueBar: int = 2 +ColorEditFlags_PickerHueWheel: int = 2 +ColorEditFlags_Uint8: int = 2 +Cond_Always: int = 1 +Cond_Appearing: int = 8 +Cond_FirstUseEver: int = 4 +Cond_Once: int = 2 +Dir_Down: int = 3 +Dir_Left: int = 0 +Dir_None: int = -1 +Dir_Right: int = 1 +Dir_Up: int = 2 +DockNodeFlags_AutoHideTabBar: int = 64 +DockNodeFlags_KeepAliveOnly: int = 1 +DockNodeFlags_NoDockingInCentralNode: int = 4 +DockNodeFlags_NoResize: int = 32 +DockNodeFlags_NoSplit: int = 16 +DockNodeFlags_None: int = 0 +DockNodeFlags_PassthruCentralNode: int = 8 +MouseButton_Left: int = 0 +MouseButton_Middle: int = 2 +MouseButton_Right: int = 1 +TableFlags_Borders: int = 1920 +TableFlags_BordersH: int = 384 +TableFlags_BordersInner: int = 640 +TableFlags_BordersInnerH: int = 128 +TableFlags_BordersInnerV: int = 512 +TableFlags_BordersOuter: int = 1280 +TableFlags_BordersOuterH: int = 256 +TableFlags_BordersOuterV: int = 1024 +TableFlags_BordersV: int = 1536 +TableFlags_ContextMenuInBody: int = 32 +TableFlags_Hideable: int = 4 +TableFlags_NoBordersInBody: int = 2048 +TableFlags_NoBordersInBodyUntilResize: int = 4096 +TableFlags_NoClip: int = 1048576 +TableFlags_NoHostExtendX: int = 65536 +TableFlags_NoHostExtendY: int = 131072 +TableFlags_NoKeepColumnsVisible: int = 262144 +TableFlags_NoPadInnerX: int = 8388608 +TableFlags_NoPadOuterX: int = 4194304 +TableFlags_NoSavedSettings: int = 16 +TableFlags_None: int = 0 +TableFlags_PadOuterX: int = 2097152 +TableFlags_PreciseWidths: int = 524288 +TableFlags_Reorderable: int = 2 +TableFlags_Resizable: int = 1 +TableFlags_RowBg: int = 64 +TableFlags_ScrollX: int = 16777216 +TableFlags_ScrollY: int = 33554432 +TableFlags_SizingFixedFit: int = 8192 +TableFlags_SizingFixedSame: int = 16384 +TableFlags_SizingMask_: int = 57344 +TableFlags_SizingStretchProp: int = 24576 +TableFlags_SizingStretchSame: int = 32768 +TableFlags_SortMulti: int = 67108864 +TableFlags_SortTristate: int = 134217728 +TableFlags_Sortable: int = 8 +WindowFlags_AlwaysAutoResize: int = 64 +WindowFlags_NoBackground: int = 128 +WindowFlags_NoMove: int = 4 +WindowFlags_NoResize: int = 2 +WindowFlags_NoScrollbar: int = 8 +WindowFlags_NoTitleBar: int = 1 +WindowFlags_None: int = 0 diff --git a/src/python/stubs/pyridescence/pfd.pyi b/src/python/stubs/pyridescence/pfd.pyi new file mode 100644 index 00000000..29cbb574 --- /dev/null +++ b/src/python/stubs/pyridescence/pfd.pyi @@ -0,0 +1,12 @@ +""" +""" +from __future__ import annotations +__all__: list[str] = ['notify', 'open_file', 'save_file', 'select_folder'] +def notify(arg0: str, arg1: str) -> None: + ... +def open_file(title: str, default_path: str = '') -> str: + ... +def save_file(title: str, default_path: str = '') -> str: + ... +def select_folder(title: str, default_path: str = '') -> str: + ... From 135e633ac13a3f344a1776fb7e0eba106f7573af Mon Sep 17 00:00:00 2001 From: "k.koide" Date: Tue, 30 Dec 2025 16:35:44 +0900 Subject: [PATCH 20/40] update README --- README.md | 94 ++++++++++++++++++++++++++----------------------------- 1 file changed, 44 insertions(+), 50 deletions(-) diff --git a/README.md b/README.md index 0924233c..0a6358ee 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ ![Iridescence](docs/assets/logo.png) -**Iridescence** is a light-weight visualization library for rapid prototyping of 3D algorithms. This library is designed for accelerating personal research and development projects (mainly focusing on point-cloud-related algorithms) and is NOT intended to be a general-purpose visualization library with rich rendering capabilities. +**Iridescence** is a light-weight visualization library for rapid prototyping of 3D algorithms. This library is designed for accelerating personal research and development projects (mainly focuing on point-cloud-related algorithms) and is NOT intended to be a general-purpose visualization library with rich rendering capabilities. + +[![ppa](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapi.launchpad.net%2F1.0%2F~koide3%2F%2Barchive%2Fubuntu%2Firidescence%3Fws.op%3DgetPublishedSources%26status%3DPublished&query=entries.0.source_package_version&label=ppa)](https://launchpad.net/~koide3/+archive/ubuntu/iridescence) [![PyPI - Version](https://img.shields.io/pypi/v/pyridescence)](https://pypi.org/project/pyridescence/) [![Build](https://github.com/koide3/iridescence/actions/workflows/build.yml/badge.svg)](https://github.com/koide3/iridescence/actions/workflows/build.yml) on Ubuntu 22.04 / 24.04 and Windows + -[![Build](https://github.com/koide3/iridescence/actions/workflows/build.yml/badge.svg)](https://github.com/koide3/iridescence/actions/workflows/build.yml) on Ubuntu 20.04 / 22.04 / 24.04 ## Features @@ -24,68 +26,59 @@ See **[documentation](https://koide3.github.io/iridescence/)** for details. - [ImGuizmo](https://github.com/CedricGuillemet/ImGuizmo) ([MIT license](https://github.com/CedricGuillemet/ImGuizmo/blob/master/LICENSE)) - [implot](https://github.com/epezent/implot) ([MIT license](https://github.com/epezent/implot/blob/master/LICENSE)) - [Eigen](https://eigen.tuxfamily.org/index.php) ([MPL2 license](https://www.mozilla.org/en-US/MPL/2.0/)) +- [rapidhash](https://github.com/Nicoshev/rapidhash) ([MIT license](https://github.com/Nicoshev/rapidhash/blob/master/LICENSE)) - [portable-file-dialogs](https://github.com/samhocevar/portable-file-dialogs) ([WTFPL license](https://github.com/samhocevar/portable-file-dialogs/blob/main/COPYING)) ## Installation -### Install from source +### C++ : Install from [PPA](https://launchpad.net/~koide3/+archive/ubuntu/iridescence) (Ubuntu) ```bash -# Install dependencies -sudo apt-get install -y libglm-dev libglfw3-dev libpng-dev libjpeg-dev libeigen3-dev - -# Build and install Iridescence -git clone https://github.com/koide3/iridescence --recursive -mkdir iridescence/build && cd iridescence/build -cmake .. -make -j -sudo make install - -# [Optional] Build and install python bindings -cd .. -pip install . - -# [Optional2] Install stubs for autocomplete -pip install pybind11-stubgen - -cd ~/.local/lib/python3.12/site-packages -# If you are using a virtual environment, you can find the path with: -# cd $(dirname $(which python))/../lib/python3.12/site-packages - -pybind11-stubgen -o . pyridescence +# Install from PPA +sudo add-apt-repository koide3/iridescence +sudo apt install libiridescence-dev ``` -### Install from [PPA](https://github.com/koide3/ppa) [AMD64, ARM64] +### Python : Install from [PyPI](https://pypi.org/project/pyridescence/) (Ubuntu and Windows) -#### Ubuntu 24.04 +Note : Source installation is required for Python 3.14. ```bash -curl -s --compressed "https://koide3.github.io/ppa/ubuntu2404/KEY.gpg" | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/koide3_ppa.gpg >/dev/null -echo "deb [signed-by=/etc/apt/trusted.gpg.d/koide3_ppa.gpg] https://koide3.github.io/ppa/ubuntu2404 ./" | sudo tee /etc/apt/sources.list.d/koide3_ppa.list - -sudo apt update && sudo apt install -y libiridescence-dev +# Install from PyPI +pip install pyridescence ``` -#### Ubuntu 22.04 +
+ Install from source + + +### C++ : Install from source (Ubuntu) ```bash -curl -s --compressed "https://koide3.github.io/ppa/ubuntu2204/KEY.gpg" | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/koide3_ppa.gpg >/dev/null -echo "deb [signed-by=/etc/apt/trusted.gpg.d/koide3_ppa.gpg] https://koide3.github.io/ppa/ubuntu2204 ./" | sudo tee /etc/apt/sources.list.d/koide3_ppa.list +# Install dependencies +sudo apt-get install -y libglm-dev libglfw3-dev libpng-dev libjpeg-dev libeigen3-dev -sudo apt update && sudo apt install -y libiridescence-dev +# Build and install Iridescence +git clone https://github.com/koide3/iridescence --recursive +mkdir iridescence/build && cd iridescence/build +cmake .. +make -j +sudo make install ``` -#### Ubuntu 20.04 +### Python : Install from source ```bash -curl -s --compressed "https://koide3.github.io/ppa/ubuntu2004/KEY.gpg" | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/koide3_ppa.gpg >/dev/null -echo "deb [signed-by=/etc/apt/trusted.gpg.d/koide3_ppa.gpg] https://koide3.github.io/ppa/ubuntu2004 ./" | sudo tee /etc/apt/sources.list.d/koide3_ppa.list - -sudo apt update && sudo apt install -y libiridescence-dev +git clone https://github.com/koide3/iridescence --recursive +cd iridescence +pip install . ``` +
-## Use Iridescence in your cmake project +## Usage + +### C++ : Use Iridescence in your cmake project ```cmake # Find package @@ -101,7 +94,7 @@ target_link_libraries(your_program ``` -## Minimum example +### C++ : Minimum example C++: ```cpp @@ -128,8 +121,10 @@ int main(int argc, char** argv) { // Spin the viewer until it gets closed while (viewer->spin_once()) { // Objects to be rendered are called "drawables" and managed with unique names. - // Here, solid and wire spheres are registered to the viewer respectively with the "Rainbow" and "FlatColor" coloring schemes. - // The "Rainbow" coloring scheme encodes the height of each fragment using the turbo colormap by default. + // Here, solid and wire spheres are registered to the viewer respectively with + // the "Rainbow" and "FlatColor" coloring schemes. + // The "Rainbow" coloring scheme encodes the height of each fragment using the + // turbo colormap by default. Eigen::AngleAxisf transform(angle, Eigen::Vector3f::UnitZ()); viewer->update_drawable("sphere", glk::Primitives::sphere(), guik::Rainbow(transform)); viewer->update_drawable("wire_sphere", glk::Primitives::wire_sphere(), guik::FlatColor({0.1f, 0.7f, 1.0f, 1.0f}, transform)); @@ -139,8 +134,7 @@ int main(int argc, char** argv) { } ``` -
- Python version +### Python : Minimum example ```py #!/usr/bin/python3 @@ -171,16 +165,16 @@ viewer.register_ui_callback('ui', ui_callback) # Spin the viewer until it gets closed while viewer.spin_once(): # Objects to be rendered are called "drawables" and managed with unique names. - # Here, solid and wire spheres are registered to the viewer respectively with the "Rainbow" and "FlatColor" coloring schemes. - # The "Rainbow" coloring scheme encodes the height of each fragment using the turbo colormap by default. + # Here, solid and wire spheres are registered to the viewer respectively with + # the "Rainbow" and "FlatColor" coloring schemes. + # The "Rainbow" coloring scheme encodes the height of each fragment using the + # turbo colormap by default. transform = numpy.identity(4) transform[:3, :3] = Rotation.from_rotvec([0.0, 0.0, angle]).as_matrix() viewer.update_drawable('sphere', glk.primitives.sphere(), guik.Rainbow(transform)) viewer.update_drawable('wire_sphere', glk.primitives.wire_sphere(), guik.FlatColor(0.1, 0.7, 1.0, 1.0, transform)) ``` -
- ![example_01](https://user-images.githubusercontent.com/31344317/210127177-31630466-f8a1-45b6-8bc7-2fdd2e4c9548.gif) From 508cd1dd1f8c0b667a1ddc692adc2688f601b925 Mon Sep 17 00:00:00 2001 From: "k.koide" Date: Tue, 30 Dec 2025 16:48:58 +0900 Subject: [PATCH 21/40] update docs --- README.md | 1 - docs/index.md | 96 ++++++++++++++++++++++++-------------------------- docs/shader.md | 4 +++ 3 files changed, 51 insertions(+), 50 deletions(-) diff --git a/README.md b/README.md index 0a6358ee..ecc564c0 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,6 @@ [![ppa](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapi.launchpad.net%2F1.0%2F~koide3%2F%2Barchive%2Fubuntu%2Firidescence%3Fws.op%3DgetPublishedSources%26status%3DPublished&query=entries.0.source_package_version&label=ppa)](https://launchpad.net/~koide3/+archive/ubuntu/iridescence) [![PyPI - Version](https://img.shields.io/pypi/v/pyridescence)](https://pypi.org/project/pyridescence/) [![Build](https://github.com/koide3/iridescence/actions/workflows/build.yml/badge.svg)](https://github.com/koide3/iridescence/actions/workflows/build.yml) on Ubuntu 22.04 / 24.04 and Windows - ## Features What this library provides: diff --git a/docs/index.md b/docs/index.md index 7d88e8c3..81953783 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,21 +1,22 @@ ![Iridescence](assets/logo.png) -**Iridescence** a light-weight visualization library for rapid prototyping of 3D algorithms. This library is designed for accelerating personal research and development projects (mainly focusing on point-cloud-related algorithms) and is NOT intended to be a general-purpose visualization library with rich rendering capabilities. +**Iridescence** is a light-weight visualization library for rapid prototyping of 3D algorithms. This library is designed for accelerating personal research and development projects (mainly focuing on point-cloud-related algorithms) and is NOT intended to be a general-purpose visualization library with rich rendering capabilities. + +[![ppa](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapi.launchpad.net%2F1.0%2F~koide3%2F%2Barchive%2Fubuntu%2Firidescence%3Fws.op%3DgetPublishedSources%26status%3DPublished&query=entries.0.source_package_version&label=ppa)](https://launchpad.net/~koide3/+archive/ubuntu/iridescence) [![PyPI - Version](https://img.shields.io/pypi/v/pyridescence)](https://pypi.org/project/pyridescence/) [![Build](https://github.com/koide3/iridescence/actions/workflows/build.yml/badge.svg)](https://github.com/koide3/iridescence/actions/workflows/build.yml) on Ubuntu 22.04 / 24.04 and Windows -[![Build](https://github.com/koide3/iridescence/actions/workflows/build.yml/badge.svg)](https://github.com/koide3/iridescence/actions/workflows/build.yml) on Ubuntu 18.04 / 20.04 / 22.04 ## Features What this library provides: - - An easy-to-use 3D visualization framework (inpaticular suitable for rendering point clouds) - Tightly integrated Dear ImGui interfaces for rapid UI design What this library does NOT provide: - - Realistic rendering and shading - Rich textured 3D mesh rendering +See **[documentation](https://koide3.github.io/iridescence/)** for details. + ## Dependencies - [GLFW](https://www.glfw.org/) ([zlib/libpng license](https://www.glfw.org/license.html)) @@ -24,69 +25,64 @@ What this library does NOT provide: - [ImGuizmo](https://github.com/CedricGuillemet/ImGuizmo) ([MIT license](https://github.com/CedricGuillemet/ImGuizmo/blob/master/LICENSE)) - [implot](https://github.com/epezent/implot) ([MIT license](https://github.com/epezent/implot/blob/master/LICENSE)) - [Eigen](https://eigen.tuxfamily.org/index.php) ([MPL2 license](https://www.mozilla.org/en-US/MPL/2.0/)) +- [rapidhash](https://github.com/Nicoshev/rapidhash) ([MIT license](https://github.com/Nicoshev/rapidhash/blob/master/LICENSE)) - [portable-file-dialogs](https://github.com/samhocevar/portable-file-dialogs) ([WTFPL license](https://github.com/samhocevar/portable-file-dialogs/blob/main/COPYING)) ## Installation -### Install from source +### C++ : Install from [PPA](https://launchpad.net/~koide3/+archive/ubuntu/iridescence) (Ubuntu) ```bash -# Install dependencies -sudo apt-get install -y libglm-dev libglfw3-dev libpng-dev libjpeg-dev libeigen3-dev +# Install from PPA +sudo add-apt-repository koide3/iridescence +sudo apt install libiridescence-dev +``` -# Build and install Iridescence -git clone https://github.com/koide3/iridescence --recursive -mkdir iridescence/build && cd iridescence/build -cmake .. -DCMAKE_BUILD_TYPE=Release -make -j$(nproc) -sudo make install +### Python : Install from [PyPI](https://pypi.org/project/pyridescence/) (Ubuntu and Windows) -# [Optional] Build and install python bindings -cd .. -pip install . +Note : Source installation is required for Python 3.14. -# [Optional2] Install stubs for autocomplete -pip install pybind11-stubgen -cd ~/.local/lib/python3.10/site-packages -pybind11-stubgen -o . --ignore-invalid=all pyridescence +```bash +# Install from PyPI +pip install pyridescence ``` -### Install from [PPA](https://github.com/koide3/ppa) [AMD64, ARM64] +
+ Install from source + -#### Ubuntu 24.04 +### C++ : Install from source (Ubuntu) ```bash -curl -s --compressed "https://koide3.github.io/ppa/ubuntu2404/KEY.gpg" | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/koide3_ppa.gpg >/dev/null -echo "deb [signed-by=/etc/apt/trusted.gpg.d/koide3_ppa.gpg] https://koide3.github.io/ppa/ubuntu2404 ./" | sudo tee /etc/apt/sources.list.d/koide3_ppa.list +# Install dependencies +sudo apt-get install -y libglm-dev libglfw3-dev libpng-dev libjpeg-dev libeigen3-dev -sudo apt update && sudo apt install -y libiridescence-dev +# Build and install Iridescence +git clone https://github.com/koide3/iridescence --recursive +mkdir iridescence/build && cd iridescence/build +cmake .. +make -j +sudo make install ``` -#### Ubuntu 22.04 +### Python : Install from source ```bash -curl -s --compressed "https://koide3.github.io/ppa/ubuntu2204/KEY.gpg" | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/koide3_ppa.gpg >/dev/null -echo "deb [signed-by=/etc/apt/trusted.gpg.d/koide3_ppa.gpg] https://koide3.github.io/ppa/ubuntu2204 ./" | sudo tee /etc/apt/sources.list.d/koide3_ppa.list - -sudo apt update && sudo apt install -y libiridescence-dev +git clone https://github.com/koide3/iridescence --recursive +cd iridescence +pip install . ``` -#### Ubuntu 20.04 - -```bash -curl -s --compressed "https://koide3.github.io/ppa/ubuntu2004/KEY.gpg" | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/koide3_ppa.gpg >/dev/null -echo "deb [signed-by=/etc/apt/trusted.gpg.d/koide3_ppa.gpg] https://koide3.github.io/ppa/ubuntu2004 ./" | sudo tee /etc/apt/sources.list.d/koide3_ppa.list +
-sudo apt update && sudo apt install -y libiridescence-dev -``` +## Usage -## Use Iridescence in your cmake project +### C++ : Use Iridescence in your cmake project ```cmake # Find package find_package(Iridescence REQUIRED) - # Add include dirs and link libraries add_executable(your_program src/your_program.cpp @@ -97,7 +93,7 @@ target_link_libraries(your_program ``` -## Minimum example +### C++ : Minimum example C++: ```cpp @@ -124,8 +120,10 @@ int main(int argc, char** argv) { // Spin the viewer until it gets closed while (viewer->spin_once()) { // Objects to be rendered are called "drawables" and managed with unique names. - // Here, solid and wire spheres are registered to the viewer respectively with the "Rainbow" and "FlatColor" coloring schemes. - // The "Rainbow" coloring scheme encodes the height of each fragment using the turbo colormap by default. + // Here, solid and wire spheres are registered to the viewer respectively with + // the "Rainbow" and "FlatColor" coloring schemes. + // The "Rainbow" coloring scheme encodes the height of each fragment using the + // turbo colormap by default. Eigen::AngleAxisf transform(angle, Eigen::Vector3f::UnitZ()); viewer->update_drawable("sphere", glk::Primitives::sphere(), guik::Rainbow(transform)); viewer->update_drawable("wire_sphere", glk::Primitives::wire_sphere(), guik::FlatColor({0.1f, 0.7f, 1.0f, 1.0f}, transform)); @@ -135,13 +133,13 @@ int main(int argc, char** argv) { } ``` -
- Python version +### Python : Minimum example ```py #!/usr/bin/python3 import numpy from scipy.spatial.transform import Rotation + from pyridescence import * # Create a viewer instance (global singleton) @@ -166,26 +164,26 @@ viewer.register_ui_callback('ui', ui_callback) # Spin the viewer until it gets closed while viewer.spin_once(): # Objects to be rendered are called "drawables" and managed with unique names. - # Here, solid and wire spheres are registered to the viewer respectively with the "Rainbow" and "FlatColor" coloring schemes. - # The "Rainbow" coloring scheme encodes the height of each fragment using the turbo colormap by default. + # Here, solid and wire spheres are registered to the viewer respectively with + # the "Rainbow" and "FlatColor" coloring schemes. + # The "Rainbow" coloring scheme encodes the height of each fragment using the + # turbo colormap by default. transform = numpy.identity(4) transform[:3, :3] = Rotation.from_rotvec([0.0, 0.0, angle]).as_matrix() viewer.update_drawable('sphere', glk.primitives.sphere(), guik.Rainbow(transform)) viewer.update_drawable('wire_sphere', glk.primitives.wire_sphere(), guik.FlatColor(0.1, 0.7, 1.0, 1.0, transform)) ``` -
- ![example_01](https://user-images.githubusercontent.com/31344317/210127177-31630466-f8a1-45b6-8bc7-2fdd2e4c9548.gif) +See **[documentation](https://koide3.github.io/iridescence/)** for details. ## Some use examples in my academic works ![ral2021](https://user-images.githubusercontent.com/31344317/210128637-80f79abf-69c3-479c-91e9-0807e5b8b3ae.jpg) ![iros2022](https://user-images.githubusercontent.com/31344317/210128635-2ef02dff-3d74-499e-bde8-2c9c0dc047ff.jpg) - ## License This package is released under the MIT license. diff --git a/docs/shader.md b/docs/shader.md index 53eeae2a..c925fc4c 100644 --- a/docs/shader.md +++ b/docs/shader.md @@ -37,6 +37,7 @@ There are four coloring schemes in Iridescence, and they have corresponding util - **FLAT_COLOR (guik::FlatColor)** scheme draws pixels with a flat color. - **VERTEX_COLOR (guik::VertexColor)** scheme draws pixels with interpolated colors of corresponding vertices. - **TEXTURE_COLOR (guik::TextureColor)** scheme samples pixel colors from a texture. +- **VERTEX_COLORMAP (guik::VertexColorMap)** scheme draws pixels with colors that encode vertex colormap attribute (Similar to RAINBOW, but uses an arbitrary vertex scalar attribute like vertex intensity). ![Screenshot_20230101_004203](https://user-images.githubusercontent.com/31344317/210148371-c12e7126-2dc2-48e5-b43b-b57a7be9d92e.png) Left to right: Rainbow, FlatColor, VertexColor, TextureColor (transparent) @@ -63,6 +64,9 @@ auto shader_setting = guik::VertexColor(transformation); // TEXTURE_COLOR with transparency auto shader_setting = guik::TextureColor(transformation).make_transparent(); + +// VERTEX_COLORMAP +auto shader_setting = guik::VertexColorMap(transformation); ``` ![Screenshot_20230101_005425](https://user-images.githubusercontent.com/31344317/210149282-38377bad-dfb8-4f86-a907-60cdcef10b92.png) From 3c0050a427120dfaae44c16bf26d6fbdbeeee8ca Mon Sep 17 00:00:00 2001 From: "k.koide" Date: Tue, 30 Dec 2025 16:50:23 +0900 Subject: [PATCH 22/40] remove link to doc --- docs/index.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/index.md b/docs/index.md index 81953783..0c1ad071 100644 --- a/docs/index.md +++ b/docs/index.md @@ -15,8 +15,6 @@ What this library does NOT provide: - Realistic rendering and shading - Rich textured 3D mesh rendering -See **[documentation](https://koide3.github.io/iridescence/)** for details. - ## Dependencies - [GLFW](https://www.glfw.org/) ([zlib/libpng license](https://www.glfw.org/license.html)) From f47856367d0cea40ac5023e4a39868cd565202af Mon Sep 17 00:00:00 2001 From: "k.koide" Date: Tue, 30 Dec 2025 17:17:39 +0900 Subject: [PATCH 23/40] doc --- docs/Doxyfile | 2579 +++++++++++++++++++++++++++++++++++ docs/Makefile | 18 + docs/conf.py | 42 + docs/index.rst | 26 + docs/pyridescence.glk.rst | 8 + docs/pyridescence.guik.rst | 8 + docs/pyridescence.imgui.rst | 8 + docs/pyridescence.pfd.rst | 8 + docs/pyridescence.rst | 7 + 9 files changed, 2704 insertions(+) create mode 100644 docs/Doxyfile create mode 100644 docs/Makefile create mode 100644 docs/conf.py create mode 100644 docs/index.rst create mode 100644 docs/pyridescence.glk.rst create mode 100644 docs/pyridescence.guik.rst create mode 100644 docs/pyridescence.imgui.rst create mode 100644 docs/pyridescence.pfd.rst create mode 100644 docs/pyridescence.rst diff --git a/docs/Doxyfile b/docs/Doxyfile new file mode 100644 index 00000000..bc987c20 --- /dev/null +++ b/docs/Doxyfile @@ -0,0 +1,2579 @@ +# Doxyfile 1.8.17 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the configuration +# file that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# https://www.gnu.org/software/libiconv/ for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = "gtsam_points" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all generated output in the proper direction. +# Possible values are: None, LTR, RTL and Context. +# The default value is: None. + +OUTPUT_TEXT_DIRECTION = None + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line +# such as +# /*************** +# as being the beginning of a Javadoc-style comment "banner". If set to NO, the +# Javadoc-style will behave just like regular comments and it will not be +# interpreted by doxygen. +# The default value is: NO. + +JAVADOC_BANNER = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines (in the resulting output). You can put ^^ in the value part of an +# alias to insert a newline as if a physical newline was in the original file. +# When you need a literal { or } or , in the value part of an alias you have to +# escape them by means of a backslash (\), this can lead to conflicts with the +# commands \{ and \} for these it is advised to use the version @{ and @} or use +# a double escape (\\{ and \\}) + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice +# sources only. Doxygen will then generate output that is more tailored for that +# language. For instance, namespaces will be presented as modules, types will be +# separated into more groups, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_SLICE = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, JavaScript, +# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, +# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser +# tries to guess whether the code is fixed or free formatted code, this is the +# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat +# .inc files as Fortran files (default is PHP), and .f files as C (default is +# Fortran), use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See https://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 5. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 5 + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual +# methods of a class will be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIV_VIRTUAL = NO + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# declarations. If set to NO, these declarations will be included in the +# documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES, upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# (including Cygwin) ands Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. If +# EXTRACT_ALL is set to YES then this flag will automatically be disabled. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. +# The default value is: NO. + +WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. + +INPUT = ../README.md ../include + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: https://www.gnu.org/software/libiconv/) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment), +# *.doc (to be provided as doxygen C comment), *.txt (to be provided as doxygen +# C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f, *.for, *.tcl, *.vhd, +# *.vhdl, *.ucf, *.qsf and *.ice. + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.idl \ + *.ddl \ + *.odl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.cs \ + *.d \ + *.php \ + *.php4 \ + *.php5 \ + *.phtml \ + *.inc \ + *.m \ + *.markdown \ + *.md \ + *.mm \ + *.dox \ + *.doc \ + *.txt \ + *.py \ + *.pyw \ + *.f90 \ + *.f95 \ + *.f03 \ + *.f08 \ + *.f \ + *.for \ + *.tcl \ + *.vhd \ + *.vhdl \ + *.ucf \ + *.qsf \ + *.ice + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = ../include/gtsam_points/factors/experimental ../include/gtsam_points/optimizers + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = README.md + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# entity all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see https://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the +# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the +# cost of reduced performance. This can be particularly helpful with template +# rich C++ code for which doxygen's built-in parser lacks the necessary type +# information. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = NO + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + +# If clang assisted parsing is enabled you can provide the clang parser with the +# path to the compilation database (see: +# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) used when the files +# were built. This is equivalent to specifying the "-p" option to a clang tool, +# such as clang-check. These options will then be passed to the parser. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. + +CLANG_DATABASE_PATH = + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = doc_cpp + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# https://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = NO + +# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML +# documentation will contain a main index with vertical navigation menus that +# are dynamically created via JavaScript. If disabled, the navigation index will +# consists of multiple levels of tabs that are statically embedded in every HTML +# page. Disable this option to support browsers that do not have JavaScript, +# like the Qt help browser. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_MENUS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: https://developer.apple.com/xcode/), introduced with OSX +# 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy +# genXcode/_index.html for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the master .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANSPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands +# to create new LaTeX commands to be used in formulas as building blocks. See +# the section "Including formulas" for details. + +FORMULA_MACROFILE = + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# https://www.mathjax.org) which uses client side JavaScript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from https://www.mathjax.org before deployment. +# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/ + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /