1#ifndef TATOOINE_RENDERING_INTERACTIVE_RECTILINEAR_GRID2_H
2#define TATOOINE_RENDERING_INTERACTIVE_RECTILINEAR_GRID2_H
14template <
typename Axis0,
typename Axis1>
16 static constexpr std::array<std::string_view, 5> vector_component_names = {
17 "magnitude",
"x",
"y",
"z",
"w"};
25 static auto get() ->
auto& {
26 static auto instance = geometry{};
30 vertexbuffer().resize(4);
32 auto vb_map = vertexbuffer().wmap();
38 indexbuffer().resize(6);
40 auto data = indexbuffer().wmap();
53 static constexpr std::string_view vertex_shader =
55 "layout (location = 0) in vec2 position;\n"
56 "uniform mat4 model_view_matrix;\n"
57 "uniform mat4 projection_matrix;\n"
58 "uniform vec2 extent;\n"
59 "uniform vec2 pixel_width;\n"
60 "out vec2 texcoord;\n"
62 " texcoord = (position * extent + pixel_width / 2) /\n"
63 " (extent+pixel_width);\n"
64 " gl_Position = projection_matrix *\n"
65 " model_view_matrix *\n"
66 " vec4(position, 0, 1);\n"
69 static constexpr std::string_view fragment_shader =
71 "uniform sampler2D data;\n"
72 "uniform sampler1D color_scale;\n"
73 "uniform float min;\n"
74 "uniform float max;\n"
75 "uniform int invert_scale;\n"
77 "out vec4 out_color;\n"
79 " float scalar = texture(data, texcoord).r;\n"
80 " if (isnan(scalar)) {\n"
81 " out_color = vec4(1,0,0,1);\n"
84 " scalar = clamp((scalar - min) / (max - min), 0, 1);\n"
85 " if (invert_scale == 1) {\n"
86 " scalar = 1 - scalar;\n"
88 " vec3 col = texture(color_scale, scalar).rgb;\n"
89 " out_color = vec4(col, 1);\n"
92 static auto get() ->
auto& {
103 set_uniform(
"data", 0);
104 set_uniform(
"color_scale", 1);
115 set_uniform_mat4(
"projection_matrix", P.data());
119 set_uniform_mat4(
"model_view_matrix", MV.data());
123 set_uniform_vec2(
"extent", extent.data());
127 set_uniform_vec2(
"pixel_width", pixel_width.data());
134 set_uniform(
"invert_scale", invert ? 1 : 0);
141 struct property_settings {
143 GLfloat min_scalar = std::numeric_limits<GLfloat>::max();
144 GLfloat max_scalar = -std::numeric_limits<GLfloat>::max();
145 bool scale_inverted =
false;
147 bool show_grid =
true;
148 bool show_property =
false;
151 std::unordered_map<std::string, property_settings>
settings;
153 std::string
const* selected_property_name =
nullptr;
165 init_grid_geometry(
grid);
166 init_properties(
grid);
170 auto const num_vertices =
171 grid.template size<0>() * 2 +
grid.template size<1>() * 2;
176 auto k = std::size_t{};
177 for (std::size_t i = 0; i <
grid.template size<0>(); ++i) {
179 grid.template dimension<1>().front()};
181 grid.template dimension<1>().back()};
183 for (std::size_t i = 0; i <
grid.template size<1>(); ++i) {
185 grid.template dimension<1>()[i]};
187 grid.template dimension<1>()[i]};
192 for (std::size_t i = 0; i < num_vertices; ++i) {
193 data[i] =
static_cast<value_type<decltype(data)
>>(i);
199 tex.resize(
grid.template size<0>(),
grid.template size<1>());
201 for (
auto const& key_value :
grid.vertex_properties()) {
202 auto const& [name, prop] = key_value;
203 if (prop_holds_scalar(prop)) {
204 auto min_scalar = std::numeric_limits<GLfloat>::max();
205 auto max_scalar = -std::numeric_limits<GLfloat>::max();
206 retrieve_typed_prop(prop.get(), [&](
auto const& prop) {
207 using prop_type = std::decay_t<decltype(prop)>;
208 using value_type = typename prop_type::value_type;
209 if constexpr (is_arithmetic<value_type>) {
210 grid.vertices().iterate_indices([&](auto const... is) {
211 auto const p = prop.at(is...);
212 min_scalar = gcem::min(min_scalar, static_cast<GLfloat>(p));
213 max_scalar = gcem::max(max_scalar, static_cast<GLfloat>(p));
218 }
else if (prop_holds_vector(prop)) {
219 retrieve_typed_prop(prop.get(), [&](
auto const& prop) {
220 using prop_type = std::decay_t<decltype(prop)>;
221 using value_type = typename prop_type::value_type;
222 if constexpr (static_vec<value_type>) {
223 auto constexpr num_comps = value_type::num_components();
224 auto min_scalars = std::vector<GLfloat>(
225 num_comps + 1, std::numeric_limits<GLfloat>::max());
226 auto max_scalars = std::vector<GLfloat>(
227 num_comps + 1, -std::numeric_limits<GLfloat>::max());
228 grid.vertices().iterate_indices([&](auto const... is) {
229 auto const p = prop.at(is...);
230 auto mag = typename value_type::value_type{};
231 for (std::size_t j = 0; j < num_comps; ++j) {
234 gcem::min(min_scalars[j + 1], static_cast<GLfloat>(p(j)));
236 gcem::max(max_scalars[j + 1], static_cast<GLfloat>(p(j)));
238 mag = gcem::sqrt(mag);
240 gcem::min(min_scalars[0], static_cast<GLfloat>(mag));
242 gcem::max(max_scalars[0], static_cast<GLfloat>(mag));
245 for (std::size_t j = 0; j < num_comps + 1; ++j) {
246 settings[key_value.first+
'_' + std::string{vector_component_names[j]}] = {
247 &color_scale::viridis(), min_scalars[j], max_scalars[j]};
249 selected_component[key_value.first] = vector_component_names[0];
257 if (prop->type() ==
typeid(
float)) {
258 f(prop->template cast_to_typed<float>());
259 }
else if (prop->type() ==
typeid(
double)) {
260 f(prop->template cast_to_typed<double>());
261 }
else if (prop->type() ==
typeid(
vec2d)) {
262 f(prop->template cast_to_typed<vec2d>());
263 }
else if (prop->type() ==
typeid(
vec2f)) {
264 f(prop->template cast_to_typed<vec2f>());
265 }
else if (prop->type() ==
typeid(
vec3d)) {
266 f(prop->template cast_to_typed<vec3d>());
267 }
else if (prop->type() ==
typeid(
vec3f)) {
268 f(prop->template cast_to_typed<vec3f>());
269 }
else if (prop->type() ==
typeid(
vec4d)) {
270 f(prop->template cast_to_typed<vec4d>());
271 }
else if (prop->type() ==
typeid(
vec4f)) {
272 f(prop->template cast_to_typed<vec4f>());
277 return prop->type() ==
typeid(float) || prop->type() ==
typeid(
double);
281 return prop->type() ==
typeid(
vec2f) || prop->type() ==
typeid(
vec2d) ||
282 prop->type() ==
typeid(
vec3f) || prop->type() ==
typeid(
vec3d) ||
283 prop->type() ==
typeid(
vec4f) || prop->type() ==
typeid(
vec4d);
288 auto texdata = std::vector<GLfloat>{};
289 texdata.reserve(
grid.vertices().size());
291 grid.vertices().iterate_indices([&](
auto const... is) {
292 texdata.push_back(
static_cast<GLfloat
>(get_data(prop, is...)));
294 tex.upload_data(texdata,
grid.template size<0>(),
grid.template size<1>());
298 retrieve_typed_prop(prop, [&](
auto&& prop) {
299 using prop_type = std::decay_t<
decltype(prop)>;
300 using value_type =
typename prop_type::value_type;
301 if constexpr (is_arithmetic<value_type>) {
302 upload_data_to_texture(
304 [](
auto const& prop,
auto const... is) {
return prop(is...); },
311 retrieve_typed_prop(prop, [&](
auto&& prop) {
312 using prop_type = std::decay_t<
decltype(prop)>;
313 using value_type =
typename prop_type::value_type;
315 upload_data_to_texture(
317 [](
auto const& prop,
auto const... is) {
318 auto mag =
typename value_type::value_type{};
320 mag += prop(is...)(j) * prop(is...)(j);
330 retrieve_typed_prop(prop, [&](
auto&& prop) {
331 using prop_type = std::decay_t<
decltype(prop)>;
332 using value_type =
typename prop_type::value_type;
334 upload_data_to_texture(
336 [](
auto const& prop,
auto const... is) {
return prop(is...).x(); },
343 retrieve_typed_prop(prop, [&](
auto&& prop) {
344 using prop_type = std::decay_t<
decltype(prop)>;
345 using value_type =
typename prop_type::value_type;
347 upload_data_to_texture(
349 [](
auto const& prop,
auto const... is) {
return prop(is...).y(); },
356 retrieve_typed_prop(prop, [&](
auto&& prop) {
357 using prop_type = std::decay_t<
decltype(prop)>;
358 using value_type =
typename prop_type::value_type;
361 upload_data_to_texture(
363 [](
auto const& prop,
auto const... is) {
364 return prop(is...).z();
373 retrieve_typed_prop(prop, [&](
auto&& prop) {
374 using prop_type = std::decay_t<
decltype(prop)>;
375 using value_type =
typename prop_type::value_type;
378 upload_data_to_texture(
380 [](
auto const& prop,
auto const... is) {
381 return prop(is...).w();
390 auto name = std::string{};
391 if (selected_property_name !=
nullptr) {
392 name = *selected_property_name;
393 if (
auto c = selected_component.find(name);
394 c !=
end(selected_component)) {
403 if (ImGui::BeginCombo(
"##combo", selected_property_name !=
nullptr
404 ? selected_property_name->c_str()
406 for (
auto const& [name, prop] :
grid.vertex_properties()) {
407 if (prop->type() ==
typeid(
float) || prop->type() ==
typeid(
double) ||
408 prop->type() ==
typeid(
vec2f) || prop->type() ==
typeid(
vec2d) ||
409 prop->type() ==
typeid(
vec3f) || prop->type() ==
typeid(
vec3d) ||
410 prop->type() ==
typeid(
vec4f) || prop->type() ==
typeid(
vec4d)) {
411 auto is_selected = selected_property == prop.get();
412 if (ImGui::Selectable(name.c_str(), is_selected)) {
413 show_property =
true;
414 selected_property = prop.get();
415 selected_property_name = &name;
416 if (prop_holds_scalar(prop)) {
417 upload_scalar_to_texture(selected_property,
grid);
419 }
else if (prop_holds_vector(prop)) {
420 upload_magnitude_to_texture(selected_property,
grid);
422 for (std::size_t i = 0; i < 5; ++i) {
423 auto const is_selected =
424 selected_component.at(*selected_property_name) ==
425 vector_component_names[i];
426 if (is_selected && i == 0) {
427 upload_magnitude_to_texture(selected_property,
grid);
428 }
else if (is_selected && i == 1) {
429 upload_x_to_texture(selected_property,
grid);
430 }
else if (is_selected && i == 2) {
431 upload_y_to_texture(selected_property,
grid);
432 }
else if (is_selected && i == 3) {
433 upload_z_to_texture(selected_property,
grid);
434 }
else if (is_selected && i == 4) {
435 upload_w_to_texture(selected_property,
grid);
443 ImGui::SetItemDefaultFocus();
452 if (ImGui::BeginCombo(
453 "##combo_vector_component",
454 std::string{selected_component.at(*selected_property_name)}
456 auto n = std::size_t{};
457 retrieve_typed_prop(selected_property, [&](
auto&& prop) {
458 using prop_type = std::decay_t<
decltype(prop)>;
459 using value_type =
typename prop_type::value_type;
464 for (std::size_t i = 0; i < n + 1; ++i) {
465 auto const is_selected =
466 selected_component.at(*selected_property_name) ==
467 vector_component_names[i];
468 if (ImGui::Selectable(std::string{vector_component_names[i]}.c_str(),
470 selected_component.at(*selected_property_name) =
471 vector_component_names[i];
473 upload_magnitude_to_texture(selected_property,
grid);
475 upload_x_to_texture(selected_property,
grid);
477 upload_y_to_texture(selected_property,
grid);
479 upload_z_to_texture(selected_property,
grid);
481 upload_w_to_texture(selected_property,
grid);
493 if (selected_property !=
nullptr) {
494 auto combo_pos = ImGui::GetCursorScreenPos();
495 auto& setting = settings.at(selected_settings_name());
496 if (ImGui::BeginCombo(
"##combocolor",
497 selected_property_name !=
nullptr
498 ? selected_property_name->c_str()
500 bool selected =
false;
501 ImGui::PushID(
"##viridis");
511 ImGui::PushID(
"##magma");
521 ImGui::PushID(
"##cool_to_warm");
533 ImGui::PushID(
"##jet");
543 ImGui::PushID(
"##GYPi");
553 ImGui::PushID(
"##PiYG");
563 ImGui::PushID(
"##BrBG");
573 ImGui::PushID(
"##GBBr");
583 ImGui::PushID(
"##BuRD");
593 ImGui::PushID(
"##GnRP");
603 ImGui::PushID(
"##PRGn");
613 ImGui::PushID(
"##OrPu");
623 ImGui::PushID(
"##PuOr");
633 ImGui::PushID(
"##GnYIRd");
645 ImGui::Text(
"Invert Color");
649 auto const backup_pos = ImGui::GetCursorScreenPos();
650 ImGuiStyle& style = ImGui::GetStyle();
651 ImGui::SetCursorScreenPos(
652 ImVec2(combo_pos.x + style.FramePadding.x, combo_pos.y));
653 ImGui::Image((
void*)(std::intptr_t)setting.c->tex_2d.id(),
655 ImGui::SetCursorScreenPos(backup_pos);
657 if (ImGui::Button(
"Rescale")) {
658 rescale_current_property(
grid);
664 auto const name = selected_settings_name();
665 auto& setting = settings[name];
666 auto min_scalar = std::numeric_limits<GLfloat>::max();
667 auto max_scalar = -std::numeric_limits<GLfloat>::max();
668 if (prop_holds_scalar(selected_property)) {
669 retrieve_typed_prop(selected_property, [&](
auto const& prop) {
670 using prop_type = std::decay_t<
decltype(prop)>;
671 using value_type =
typename prop_type::value_type;
672 if constexpr (is_arithmetic<value_type>) {
673 grid.vertices().iterate_indices([&](
auto const... is) {
674 auto const p = prop.at(is...);
675 min_scalar = gcem::min(min_scalar,
static_cast<GLfloat
>(p));
676 max_scalar = gcem::max(max_scalar,
static_cast<GLfloat
>(p));
680 }
else if (prop_holds_vector(selected_property)) {
681 retrieve_typed_prop(selected_property, [&](
auto const& prop) {
682 using prop_type = std::decay_t<
decltype(prop)>;
683 using value_type =
typename prop_type::value_type;
686 grid.vertices().iterate_indices([&](
auto const... is) {
687 auto const p = prop.at(is...);
688 if (selected_component.at(*selected_property_name) ==
689 vector_component_names[0]) {
690 auto mag = typename value_type::value_type{};
691 for (std::size_t i = 0; i < num_comps; ++i) {
694 mag = gcem::sqrt(mag);
695 min_scalar = gcem::min(min_scalar,
static_cast<GLfloat
>(mag));
696 max_scalar = gcem::max(max_scalar,
static_cast<GLfloat
>(mag));
698 auto s =
typename value_type::value_type{};
699 if (selected_component.at(*selected_property_name) ==
700 vector_component_names[1]) {
702 }
else if (selected_component.at(*selected_property_name) ==
703 vector_component_names[2]) {
705 }
else if (selected_component.at(*selected_property_name) ==
706 vector_component_names[3]) {
710 }
else if (selected_component.at(*selected_property_name) ==
711 vector_component_names[4]) {
716 min_scalar = gcem::min(min_scalar,
static_cast<GLfloat
>(s));
717 max_scalar = gcem::max(max_scalar,
static_cast<GLfloat
>(s));
723 setting.min_scalar = min_scalar;
724 setting.max_scalar = max_scalar;
728 ImGui::Text(
"Rectilinear Grid");
729 ImGui::Checkbox(
"Show Grid", &show_grid);
731 ImGui::DragInt(
"Line width", &line_width, 1, 1, 20);
732 ImGui::ColorEdit4(
"Grid Color", grid_color.data());
734 if (!
grid.vertex_properties().empty()) {
735 ImGui::Checkbox(
"Show Property", &show_property);
736 grid_property_selection(
grid);
739 vector_component_selection(
grid);
741 if (selected_property !=
nullptr) {
742 auto& setting = settings[selected_settings_name()];
743 ImGui::DragFloat(
"Min", &setting.min_scalar, 0.01f, -FLT_MAX,
744 setting.max_scalar,
"%.06f");
745 ImGui::DragFloat(
"Max", &setting.max_scalar, 0.01f, setting.min_scalar,
749 color_scale_selection(
grid);
756 if (show_property && selected_property !=
nullptr) {
763 using CamReal =
typename std::decay_t<
decltype(cam)>
::real_type;
764 static auto constexpr cam_is_float = is_same<GLfloat, CamReal>;
766 if constexpr (cam_is_float) {
773 if constexpr (cam_is_float) {
781 if constexpr (cam_is_float) {
788 if constexpr (cam_is_float) {
791 translation_matrix<GLfloat>(
792 static_cast<GLfloat
>(
grid.template dimension<0>().front()),
793 static_cast<GLfloat
>(
grid.template dimension<1>().front()), 0) *
794 scale_matrix<GLfloat>(
795 static_cast<GLfloat
>(
grid.template extent<0>()),
796 static_cast<GLfloat
>(
grid.template extent<1>()), 1));
800 scale_matrix<GLfloat>(
801 static_cast<GLfloat
>(
grid.template extent<0>()),
802 static_cast<GLfloat
>(
grid.template extent<1>()), 1) *
803 translation_matrix<GLfloat>(
804 static_cast<GLfloat
>(
grid.template dimension<0>().front()),
805 static_cast<GLfloat
>(
grid.template dimension<1>().front()), 0));
809 grid.template dimension<0>()[1] -
grid.template dimension<0>()[0],
810 grid.template dimension<1>()[1] -
grid.template dimension<1>()[0]});
820 gl::line_width(
static_cast<GLfloat
>(line_width));
821 geometry.draw_lines();
827 if (selected_property_name !=
nullptr) {
828 auto const name = selected_settings_name();
829 auto& setting = settings.at(name);
833 setting.c->tex.bind(1);
Definition: indexeddata.h:13
auto indexbuffer() -> auto &
Definition: indexeddata.h:145
auto vertexbuffer() -> auto &
Definition: indexeddata.h:148
DLL_API void bind() const
Definition: grid_edge.h:16
Definition: rectilinear_grid.h:38
Definition: tensor_concepts.h:23
auto ToggleButton(const char *str_id, bool *v) -> bool
tex2r< GLfloat > tex2r32f
Definition: texture.h:930
Definition: interactive.h:15
Definition: algorithm.h:6
typename get_impl< Container, I >::type get
Definition: get.h:11
typename value_type_impl< T >::type value_type
Definition: type_traits.h:280
auto end(Range &&range)
Definition: iterator_facade.h:322
constexpr auto max(A &&a, B &&b)
Definition: math.h:20
constexpr auto min(A &&a, B &&b)
Definition: math.h:15
Definition: cool_to_warm.h:12
Definition: vertex_property.h:45
static constexpr GLsizei num_components
Definition: texcomponents.h:10
Definition: shadersource.h:8
Definition: color_scale.h:25
static auto viridis() -> auto &
Definition: color_scale.h:82
property_shader()
Definition: rectilinear_grid2.h:99
auto set_model_view_matrix(Mat4< GLfloat > const &MV) -> void
Definition: rectilinear_grid2.h:118
auto set_pixel_width(Vec2< GLfloat > const &pixel_width) -> void
Definition: rectilinear_grid2.h:126
auto set_min(GLfloat const min) -> void
Definition: rectilinear_grid2.h:130
static auto get() -> auto &
Definition: rectilinear_grid2.h:92
auto set_projection_matrix(Mat4< GLfloat > const &P) -> void
Definition: rectilinear_grid2.h:114
auto set_extent(Vec2< GLfloat > const &extent) -> void
Definition: rectilinear_grid2.h:122
auto set_max(GLfloat const max) -> void
Definition: rectilinear_grid2.h:131
auto invert_scale(bool const invert) -> void
Definition: rectilinear_grid2.h:133
geometry()
Definition: rectilinear_grid2.h:29
static auto get() -> auto &
Definition: rectilinear_grid2.h:25
auto vector_component_selection(renderable_type const &grid)
Definition: rectilinear_grid2.h:451
auto init_properties(renderable_type const &grid)
Definition: rectilinear_grid2.h:198
auto upload_x_to_texture(auto &&prop, renderable_type const &grid)
Definition: rectilinear_grid2.h:329
auto prop_holds_vector(auto const &prop)
Definition: rectilinear_grid2.h:280
auto grid_property_selection(renderable_type const &grid)
Definition: rectilinear_grid2.h:402
auto update(auto const, renderable_type const &grid, camera auto const &cam)
Definition: rectilinear_grid2.h:761
auto properties(renderable_type const &grid)
Definition: rectilinear_grid2.h:727
auto selected_settings_name() const
Definition: rectilinear_grid2.h:389
auto render_grid()
Definition: rectilinear_grid2.h:814
auto upload_scalar_to_texture(auto &&prop, renderable_type const &grid)
Definition: rectilinear_grid2.h:297
auto upload_z_to_texture(auto &&prop, renderable_type const &grid)
Definition: rectilinear_grid2.h:355
auto rescale_current_property(renderable_type const &grid)
Definition: rectilinear_grid2.h:663
auto upload_data_to_texture(auto &&prop, auto &&get_data, renderable_type const &grid)
Definition: rectilinear_grid2.h:286
auto prop_holds_scalar(auto const &prop)
Definition: rectilinear_grid2.h:276
gl::indexeddata< Vec2< GLfloat > > geometry
Definition: rectilinear_grid2.h:159
auto retrieve_typed_prop(auto &&prop, auto &&f)
Definition: rectilinear_grid2.h:256
renderer(renderable_type const &grid)
Definition: rectilinear_grid2.h:164
auto upload_magnitude_to_texture(auto &&prop, renderable_type const &grid)
Definition: rectilinear_grid2.h:310
std::unordered_map< std::string, std::string_view > selected_component
Definition: rectilinear_grid2.h:152
auto render_property()
Definition: rectilinear_grid2.h:824
auto upload_w_to_texture(auto &&prop, renderable_type const &grid)
Definition: rectilinear_grid2.h:372
auto render()
Definition: rectilinear_grid2.h:752
auto color_scale_selection(renderable_type const &grid)
Definition: rectilinear_grid2.h:492
auto upload_y_to_texture(auto &&prop, renderable_type const &grid)
Definition: rectilinear_grid2.h:342
gl::tex2r32f tex
Definition: rectilinear_grid2.h:160
auto init_grid_geometry(renderable_type const &grid)
Definition: rectilinear_grid2.h:169
typename renderable_type::template typed_vertex_property_interface_type< T > typed_vertex_property_interface_type
Definition: rectilinear_grid2.h:22
std::unordered_map< std::string, property_settings > settings
Definition: rectilinear_grid2.h:151
cook_torrance_brdf_shader property_shader
Definition: unstructured_triangular_grid3.h:25
auto set_color(GLfloat r, GLfloat g, GLfloat b, GLfloat a=1) -> void
Definition: shaders.h:85
Definition: property.h:16