diff --git a/extern/glow-extras b/extern/glow-extras index 6d4ea26072854d9ca74d9249b6654823c965e013..1978c6b5209d2de5fbfbb250f74385817149b193 160000 --- a/extern/glow-extras +++ b/extern/glow-extras @@ -1 +1 @@ -Subproject commit 6d4ea26072854d9ca74d9249b6654823c965e013 +Subproject commit 1978c6b5209d2de5fbfbb250f74385817149b193 diff --git a/samples/basic/viewer/main.cc b/samples/basic/viewer/main.cc index 4f419c5e97b41cf346b37851331d311bf2cc08f1..55e8944ee5d2df5c6cc8df571c945d7e2913d5ce 100644 --- a/samples/basic/viewer/main.cc +++ b/samples/basic/viewer/main.cc @@ -29,34 +29,122 @@ std::string const dataPath = glow::util::pathOf(__FILE__) + "/../../../data/"; void simple_picking(pm::Mesh& m, pm::vertex_attribute<tg::pos3>& pos, pm::face_attribute<tg::color3> const& col) { - { - // In this case a Picker is defined for the Renderable (Picking Texture filled) but no callback will be executed. - gv::view(pos, col, gv::pick(), "Picker defined without callback"); - } + // { + // // In this case a Picker is defined for the Renderable (Picking Texture filled) but no callback will be executed. + // gv::view(pos, col, gv::pick(), "Picker defined without callback"); + // } { + auto g = gv::grid(); + // Only on_left_click callback defined - gv::view(pos, col, gv::pick().onLeftClick([&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal) -> picking_result { - std::cout << "Something has been picked! ON_LEFT_CLICK" - << "ID: " << (int)face_id << std::endl; - std::cout << "World_Position " << world_pos << std::endl; - std::cout << "Normal " << normal << std::endl; - picking_result res; - res.mPickingColor = tg::color3::cyan; - return res; - }), - "simple picking: callback on left click"); - } + gv::view(pos, col, + gv::pick().onLeftClick( + [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal) -> gv::picking_result + { + std::cout << "Something has been picked! ON_LEFT_CLICK" + << "ID: " << (int)face_id << std::endl; + std::cout << "World_Position " << world_pos << std::endl; + std::cout << "Normal " << normal << std::endl; + gv::picking_result res; + res.mPickingColor = tg::color3::cyan; + return res; + }), + "picking MeshRenderable - callback on left click"); - { // Only on_left_click callback defined - LineRenderable - uncolored - gv::view(gv::lines(pos), gv::pick().onLeftClick([&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal) { - std::cout << "Something has been picked! ON_LEFT_CLICK" - << "ID: " << int(face_id) << std::endl; - std::cout << "World_Position" << world_pos << std::endl; - std::cout << "Normal" << normal << std::endl; - }), + gv::view(gv::lines(pos), + gv::pick().onLeftClick( + [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal) + { + std::cout << "Something has been picked! ON_LEFT_CLICK" + << "ID: " << int(face_id) << std::endl; + std::cout << "World_Position" << world_pos << std::endl; + std::cout << "Normal" << normal << std::endl; + }), "picking LineRenderable - callback on left click"); + + { + // Only on_left_click callback defined - PointRenderable - uncolored + gv::view(gv::points(pos), + gv::pick().onLeftClick( + [&](pm::vertex_index vertex_id, tg::pos3 world_pos, tg::vec3 normal) + { + std::cout << "Something has been picked! ON_LEFT_CLICK" + << "ID: " << int(vertex_id) << std::endl; + std::cout << "World_Position" << world_pos << std::endl; + std::cout << "Normal" << normal << std::endl; + return; + }), + "picking PointRenderable - callback on left click - spheres"); + } + + { + // Only on_left_click callback defined - PointRenderable - uncolored - square billboards - NOT WORKING APPROPRIATELY + gv::view(gv::points(pos).point_size_world(0.03f).camera_facing().square(), + gv::pick().onLeftClick( + [&](pm::vertex_index vertex_id, tg::pos3 world_pos, tg::vec3 normal) + { + std::cout << "Something has been picked! ON_LEFT_CLICK" + << "ID: " << int(vertex_id) << std::endl; + std::cout << "World_Position" << world_pos << std::endl; + std::cout << "Normal" << normal << std::endl; + return; + }), + "picking PointRenderables - callback on left click - billboards"); + } + } + { + auto r1 = gv::make_and_configure_renderable(pos, col, + gv::pick().onRightClick( + [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal) + { + std::cout << "Something has been picked! ON_RIGHT_CLICK" + << "ID: " << int(face_id) << std::endl; + return; + }), + "picking MeshRenderable - callback on right click"); + auto r2 = gv::make_and_configure_renderable(pos, col, + gv::pick().onHover( + [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal) + { + std::cout << "Something has been picked! ON_HOVER" + << "ID: " << (int)face_id << std::endl; + return; + }), + "picking MeshRenderable - callback on hover"); + gv::interactive( + [&](float) + { + auto g = gv::grid(); + gv::view(r1); + gv::view(r2); + }); + } + { + auto g = gv::grid(); + + // Only on_right_click callback defined + gv::view(pos, col, + gv::pick().onRightClick( + [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal) + { + std::cout << "Something has been picked! ON_RIGHT_CLICK" + << "ID: " << int(face_id) << std::endl; + return; + }), + "picking MeshRenderable - callback on right click"); + + // Only on_hover callback defined + gv::view(pos, col, + gv::pick().onHover( + [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal) + { + std::cout << "Something has been picked! ON_HOVER" + << "ID: " << (int)face_id << std::endl; + return; + }), + "picking MeshRenderable - callback on hover"); } { @@ -72,40 +160,45 @@ void simple_picking(pm::Mesh& m, pm::vertex_attribute<tg::pos3>& pos, pm::face_a pm::vertex_attribute<tg::pos3> pos2(m2); pos2.copy_from(pos); - gv::interactive([&](auto) { - gv::view(pos2, col, gv::pick().onLeftClick([&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal) { - std::cout << "Something has been picked! ON_LEFT_CLICK" - << "ID: " << int(face_id) << std::endl; - std::cout << "World_Position" << world_pos << std::endl; - std::cout << "Normal" << normal << std::endl; - - face_index_i = face_id; - world_pos_i = world_pos; - normal_i = normal; - }), - "picking interactive mode"); - - ImGui::Begin("Picking"); - - ImGui::Value("pm::face_index", face_index_i.value); - - ImGui::Value("WorldPos.x", world_pos_i.x); - ImGui::Value("WorldPos.y", world_pos_i.y); - ImGui::Value("WorldPos.z", world_pos_i.z); - - ImGui::Value("Normal.x", normal_i.x); - ImGui::Value("Normal.y", normal_i.y); - ImGui::Value("Normal.z", normal_i.z); - - if (ImGui::Button("Delete selected face")) + gv::interactive( + [&](auto) { - // delete selected face - after deleting one face another face has to be picked - std::cout << "DELETE FACE" << std::endl; - m2.faces().remove(m2.faces()[face_index_i]); - } - - ImGui::End(); - }); + gv::view(pos2, col, + gv::pick().onLeftClick( + [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal) + { + std::cout << "Something has been picked! ON_LEFT_CLICK" + << "ID: " << int(face_id) << std::endl; + std::cout << "World_Position" << world_pos << std::endl; + std::cout << "Normal" << normal << std::endl; + + face_index_i = face_id; + world_pos_i = world_pos; + normal_i = normal; + }), + "picking interactive mode"); + + ImGui::Begin("Picking"); + + ImGui::Value("pm::face_index", face_index_i.value); + + ImGui::Value("WorldPos.x", world_pos_i.x); + ImGui::Value("WorldPos.y", world_pos_i.y); + ImGui::Value("WorldPos.z", world_pos_i.z); + + ImGui::Value("Normal.x", normal_i.x); + ImGui::Value("Normal.y", normal_i.y); + ImGui::Value("Normal.z", normal_i.z); + + if (ImGui::Button("Delete selected face")) + { + // delete selected face - after deleting one face another face has to be picked + std::cout << "DELETE FACE" << std::endl; + m2.faces().remove(m2.faces()[face_index_i]); + } + + ImGui::End(); + }); } { @@ -125,109 +218,74 @@ void simple_picking(pm::Mesh& m, pm::vertex_attribute<tg::pos3>& pos, pm::face_a // auto m2 = copy._Myfirst._Val.get(); // auto pos2 = copy._Get_rest()._Myfirst._Val; - gv::interactive([&](auto) { - gv::view(gv::points(pos2), - gv::pick().onLeftClick([&vertex_index_i, &world_pos_i, &normal_i](pm::vertex_index vertex_id, tg::pos3 world_pos, tg::vec3 normal) { - std::cout << "Something has been picked! ON_LEFT_CLICK" - << "ID: " << int(vertex_id) << std::endl; - std::cout << "World_Position" << world_pos << std::endl; - std::cout << "Normal" << normal << std::endl; - - vertex_index_i = vertex_id; - world_pos_i = world_pos; - normal_i = normal; - - return; - }), - "picking interactive mode - PointRenderable"); - - ImGui::Begin("Picking"); - - ImGui::Value("pm::vertex_index", vertex_index_i.value); - - ImGui::Value("WorldPos.x", world_pos_i.x); - ImGui::Value("WorldPos.y", world_pos_i.y); - ImGui::Value("WorldPos.z", world_pos_i.z); - - ImGui::Value("Normal.x", normal_i.x); - ImGui::Value("Normal.y", normal_i.y); - ImGui::Value("Normal.z", normal_i.z); - - if (ImGui::Button("Delete selected vertex")) + gv::interactive( + [&](auto) { - // delete selected vertex - after deleting one vertex another vertex has to be picked - std::cout << "DELETE VERTEX" << std::endl; - m2.vertices().remove(m2.vertices()[vertex_index_i]); - } - - ImGui::End(); - }); - } - - { - // Only on_left_click callback defined - PointRenderable - uncolored - gv::view(gv::points(pos), gv::pick().onLeftClick([&](pm::vertex_index vertex_id, tg::pos3 world_pos, tg::vec3 normal) { - std::cout << "Something has been picked! ON_LEFT_CLICK" - << "ID: " << int(vertex_id) << std::endl; - std::cout << "World_Position" << world_pos << std::endl; - std::cout << "Normal" << normal << std::endl; - return; - }), - "picking PointRenderable - callback on left click - spheres"); - } - - { - // Only on_left_click callback defined - PointRenderable - uncolored - square billboards - NOT WORKING APPROPRIATELY - gv::view(gv::points(pos).point_size_world(0.03f).camera_facing().square(), - gv::pick().onLeftClick([&](pm::vertex_index vertex_id, tg::pos3 world_pos, tg::vec3 normal) { - std::cout << "Something has been picked! ON_LEFT_CLICK" - << "ID: " << int(vertex_id) << std::endl; - std::cout << "World_Position" << world_pos << std::endl; - std::cout << "Normal" << normal << std::endl; - return; - }), - "picking PointRenderables - callback on left click - billboards"); - } - - { - // Only on_right_click callback defined - gv::view(pos, col, gv::pick().onRightClick([&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal) { - std::cout << "Something has been picked! ON_RIGHT_CLICK" - << "ID: " << int(face_id) << std::endl; - return; - }), - "picking MeshRenderable - callback on right click"); - } - - { - // Only on_hover callback defined - gv::view(pos, col, gv::pick().onHover([&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal) { - std::cout << "Something has been picked! ON_HOVER" - << "ID: " << (int)face_id << std::endl; - return; - }), - "picking MeshRenderable - callback on hover"); + gv::view(gv::points(pos2), + gv::pick().onLeftClick( + [&vertex_index_i, &world_pos_i, &normal_i](pm::vertex_index vertex_id, tg::pos3 world_pos, tg::vec3 normal) + { + std::cout << "Something has been picked! ON_LEFT_CLICK" + << "ID: " << int(vertex_id) << std::endl; + std::cout << "World_Position" << world_pos << std::endl; + std::cout << "Normal" << normal << std::endl; + + vertex_index_i = vertex_id; + world_pos_i = world_pos; + normal_i = normal; + + return; + }), + "picking interactive mode - PointRenderable"); + + ImGui::Begin("Picking"); + + ImGui::Value("pm::vertex_index", vertex_index_i.value); + + ImGui::Value("WorldPos.x", world_pos_i.x); + ImGui::Value("WorldPos.y", world_pos_i.y); + ImGui::Value("WorldPos.z", world_pos_i.z); + + ImGui::Value("Normal.x", normal_i.x); + ImGui::Value("Normal.y", normal_i.y); + ImGui::Value("Normal.z", normal_i.z); + + if (ImGui::Button("Delete selected vertex")) + { + // delete selected vertex - after deleting one vertex another vertex has to be picked + std::cout << "DELETE VERTEX" << std::endl; + m2.vertices().remove(m2.vertices()[vertex_index_i]); + } + + ImGui::End(); + }); } { // On_hover, on_right_click, and on_left_click callbacks defined simultaneously gv::view(pos, col, gv::pick() - .onLeftClick([&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal) { - std::cout << "Something has been picked! ON_LEFT_CLICK" - << "ID: " << int(face_id) << std::endl; - return; - }) - .onRightClick([&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal) { - std::cout << "Something has been picked! ON_RIGHT_CLICK" - << "ID: " << int(face_id) << std::endl; - return; - }) - .onHover([&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal) { - std::cout << "Something has been picked! ON_HOVER" - << "ID: " << int(face_id) << std::endl; - return; - }), + .onLeftClick( + [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal) + { + std::cout << "Something has been picked! ON_LEFT_CLICK" + << "ID: " << int(face_id) << std::endl; + return; + }) + .onRightClick( + [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal) + { + std::cout << "Something has been picked! ON_RIGHT_CLICK" + << "ID: " << int(face_id) << std::endl; + return; + }) + .onHover( + [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal) + { + std::cout << "Something has been picked! ON_HOVER" + << "ID: " << int(face_id) << std::endl; + return; + }), "picking MeshRenderable - multiple callbacks: on left click, on right click, on hover" ); @@ -242,15 +300,18 @@ void simple_picking(pm::Mesh& m, pm::vertex_attribute<tg::pos3>& pos, pm::face_a fa[f] = 1000 + i; i++; } - gv::view(pos, col, gv::pick(fa).onLeftClick([&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal) -> picking_result { - std::cout << "Something has been picked! ON_LEFT_CLICK" - << "ID: " << (int)face_id << std::endl; - std::cout << "World_Position" << world_pos << std::endl; - std::cout << "Normal" << normal << std::endl; - picking_result res; - res.mPickingColor = tg::color3::cyan; - return res; - }), + gv::view(pos, col, + gv::pick(fa).onLeftClick( + [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal) -> gv::picking_result + { + std::cout << "Something has been picked! ON_LEFT_CLICK" + << "ID: " << (int)face_id << std::endl; + std::cout << "World_Position" << world_pos << std::endl; + std::cout << "Normal" << normal << std::endl; + gv::picking_result res; + res.mPickingColor = tg::color3::cyan; + return res; + }), "simple picking: callback on left click - user-defined IDs"); } @@ -258,15 +319,17 @@ void simple_picking(pm::Mesh& m, pm::vertex_attribute<tg::pos3>& pos, pm::face_a auto v = gv::view(pos, "Multiple renderables"); // Check multiple Renderables. - gv::view(pos, gv::pick().onLeftClick([&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal) -> picking_result { - std::cout << "Something has been picked! PICKER 1 " - << "ID: " << (int)face_id << std::endl; - std::cout << "World_Position" << world_pos << std::endl; - std::cout << "Normal" << normal << std::endl; - picking_result res; - res.mPickingColor = tg::color3::cyan; - return res; - })); + gv::view(pos, gv::pick().onLeftClick( + [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal) -> gv::picking_result + { + std::cout << "Something has been picked! PICKER 1 " + << "ID: " << (int)face_id << std::endl; + std::cout << "World_Position" << world_pos << std::endl; + std::cout << "Normal" << normal << std::endl; + gv::picking_result res; + res.mPickingColor = tg::color3::cyan; + return res; + })); pm::Mesh m2; m2.copy_from(m); @@ -279,15 +342,17 @@ void simple_picking(pm::Mesh& m, pm::vertex_attribute<tg::pos3>& pos, pm::face_a pos2[p] = pos2[p] + tg::vec3(2, 2, 2); } - gv::view(pos2, gv::pick().onLeftClick([&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal) -> picking_result { - std::cout << "Something has been picked! PICKER 2 " - << "ID: " << (int)face_id << std::endl; - std::cout << "World_Position" << world_pos << std::endl; - std::cout << "Normal" << normal << std::endl; - picking_result res; - res.mPickingColor = tg::color3::cyan; - return res; - })); + gv::view(pos2, gv::pick().onLeftClick( + [&](pm::face_index face_id, tg::pos3 world_pos, tg::vec3 normal) -> gv::picking_result + { + std::cout << "Something has been picked! PICKER 2 " + << "ID: " << (int)face_id << std::endl; + std::cout << "World_Position" << world_pos << std::endl; + std::cout << "Normal" << normal << std::endl; + gv::picking_result res; + res.mPickingColor = tg::color3::cyan; + return res; + })); } } @@ -684,10 +749,12 @@ void advanced_configs(pm::vertex_attribute<tg::pos3> const& pos) } // custom configure function - gv::view(pos, "config via lambda", [](gv::SceneConfig& cfg) { - cfg.enableShadows = false; - cfg.bgColorInner = {1, 0, 1}; - }); + gv::view(pos, "config via lambda", + [](gv::SceneConfig& cfg) + { + cfg.enableShadows = false; + cfg.bgColorInner = {1, 0, 1}; + }); } void advanced_layouting(pm::vertex_attribute<tg::pos3> const& pos) @@ -883,38 +950,45 @@ void interactive_viewer(pm::vertex_attribute<tg::pos3> const& pos) // the scene config and all renderables are hashed and the viewer accumulation is cleared when the hash changes // a simple interactive viewer with some interactive-related controls - gv::interactive([&](auto) { - if (ImGui::Button("make screenshot")) - gv::make_screenshot("screenshot.png", 1920, 1080); + gv::interactive( + [&](auto) + { + if (ImGui::Button("make screenshot")) + gv::make_screenshot("screenshot.png", 1920, 1080); - if (ImGui::Button("close viewer")) - gv::close_viewer(); + if (ImGui::Button("close viewer")) + gv::close_viewer(); - gv::view(pos, "interactive viewer with custom buttons. It is slow because nothing is cached."); - }); + gv::view(pos, "interactive viewer with custom buttons. It is slow because nothing is cached."); + }); // creating renderables is expensive, cache them whenever possible // NOTE: capture by value if the interactive viewer is not the top-most viewer { auto const r = gv::make_renderable(pos); - gv::interactive([r](auto dt) { - static auto time = 0.f; - time += dt; + gv::interactive( + [r](auto dt) + { + static auto time = 0.f; + time += dt; - gv::view(r, tg::translation(tg::vec3(tg::sin(tg::radians(time * .5f)) * .5f, 0.f, 0.f)), "Caching renderables in interactive views increases performance."); - }); + gv::view(r, tg::translation(tg::vec3(tg::sin(tg::radians(time * .5f)) * .5f, 0.f, 0.f)), + "Caching renderables in interactive views increases performance."); + }); } // using imgui in an interactive view { auto const r = gv::make_renderable(pos); - gv::interactive([r](auto) { - static float configurable = 0.f; + gv::interactive( + [r](auto) + { + static float configurable = 0.f; - ImGui::SliderFloat("Height", &configurable, -3.f, 3.f); + ImGui::SliderFloat("Height", &configurable, -3.f, 3.f); - gv::view(r, tg::translation(tg::vec3(0.f, configurable, 0.f)), "interactive translation of a model"); - }); + gv::view(r, tg::translation(tg::vec3(0.f, configurable, 0.f)), "interactive translation of a model"); + }); } // an interactive textured torus with animated texture coordinates @@ -927,7 +1001,8 @@ void interactive_viewer(pm::vertex_attribute<tg::pos3> const& pos) auto uv = m.vertices().make_attribute<tg::pos2>(); pm::objects::add_quad( m, - [&](pm::vertex_handle v, float x, float y) { + [&](pm::vertex_handle v, float x, float y) + { auto [cx, sx] = tg::sin_cos(tg::pi<float> * 2 * x); auto [cy, sy] = tg::sin_cos(tg::pi<float> * 2 * y); @@ -950,18 +1025,20 @@ void interactive_viewer(pm::vertex_attribute<tg::pos3> const& pos) auto a = 0.f; auto animate = false; - gv::interactive([&](auto dt) { - ImGui::Begin("Torus"); - ImGui::SliderFloat("angle", &a, 0.f, 360.f); - ImGui::Checkbox("Animate", &animate); - ImGui::End(); + gv::interactive( + [&](auto dt) + { + ImGui::Begin("Torus"); + ImGui::SliderFloat("angle", &a, 0.f, 360.f); + ImGui::Checkbox("Animate", &animate); + ImGui::End(); - if (animate) - a += 5 * dt; + if (animate) + a += 5 * dt; - // texture coordinates are rotated by "a" degrees - view(pos, gv::textured(uv, tex).transform(tg::rotation_around(tg::pos2::zero, tg::degree(a))), "animated texture coordinates"); - }); + // texture coordinates are rotated by "a" degrees + view(pos, gv::textured(uv, tex).transform(tg::rotation_around(tg::pos2::zero, tg::degree(a))), "animated texture coordinates"); + }); } } @@ -1171,23 +1248,27 @@ void special_use_cases(pm::vertex_attribute<tg::pos3> const& pos) { auto const r = gv::make_renderable(pos); - gv::interactive([r](auto dt) { - static auto time = 0.f; - time += dt; + gv::interactive( + [r](auto dt) + { + static auto time = 0.f; + time += dt; - // gv::view_cleared creates an always cleared view, resetting accumulation each frame - gv::view_cleared(r, tg::translation(tg::vec3(tg::sin(tg::radians(time * .5f)) * .5f, 0.f, 0.f))); - }); + // gv::view_cleared creates an always cleared view, resetting accumulation each frame + gv::view_cleared(r, tg::translation(tg::vec3(tg::sin(tg::radians(time * .5f)) * .5f, 0.f, 0.f))); + }); - gv::interactive([r](auto) { - static float configurable = 0.f; + gv::interactive( + [r](auto) + { + static float configurable = 0.f; - auto changed = false; - changed |= ImGui::SliderFloat("Height", &configurable, -3.f, 3.f); + auto changed = false; + changed |= ImGui::SliderFloat("Height", &configurable, -3.f, 3.f); - // gv::clear_accumulation conditionally clears the view accumulation - gv::view(r, tg::translation(tg::vec3(0.f, configurable, 0.f)), gv::clear_accumulation(changed)); - }); + // gv::clear_accumulation conditionally clears the view accumulation + gv::view(r, tg::translation(tg::vec3(0.f, configurable, 0.f)), gv::clear_accumulation(changed)); + }); } }