1#ifndef TATOOINE_RENDERING_INTERACTIVE_RECTILINEAR_GRID3_H
2#define TATOOINE_RENDERING_INTERACTIVE_RECTILINEAR_GRID3_H
14template <
typename Axis0,
typename Axis1>
16 static constexpr std::array<std::string_view, 5> vector_component_names = {
17 "magnitude",
"x",
"y",
"z",
"w"};
24 static auto get() ->
auto& {
25 static auto instance = geometry{};
29 vertexbuffer().resize(8);
31 auto vb_map = vertexbuffer().wmap();
41 indexbuffer().resize(36);
43 auto data = indexbuffer().wmap();
92 static constexpr std::string_view vertex_shader =
94 "layout (location = 0) in vec2 position;\n"
95 "uniform mat4 model_view_matrix;\n"
96 "uniform mat4 projection_matrix;\n"
97 "uniform vec2 extent;\n"
98 "uniform vec2 pixel_width;\n"
99 "out vec2 texcoord;\n"
101 " texcoord = (position * extent + pixel_width / 2) /\n"
102 " (extent+pixel_width);\n"
103 " gl_Position = projection_matrix *\n"
104 " model_view_matrix *\n"
105 " vec4(position, 0, 1);\n"
108 static constexpr std::string_view fragment_shader =
109 "#version 330 core\n"
110 "uniform sampler2D data;\n"
111 "uniform sampler1D color_scale;\n"
112 "uniform float min;\n"
113 "uniform float max;\n"
114 "uniform int invert_scale;\n"
115 "in vec2 texcoord;\n"
116 "out vec4 out_color;\n"
118 " float scalar = texture(data, texcoord).r;\n"
119 " if (isnan(scalar)) { discard; }\n"
120 " scalar = clamp((scalar - min) / (max - min), 0, 1);\n"
121 " if (invert_scale == 1) {\n"
122 " scalar = 1 - scalar;\n"
124 " vec3 col = texture(color_scale, scalar).rgb;\n"
125 " out_color = vec4(col, 1);\n"
128 static auto get() ->
auto& {
139 set_uniform(
"data", 0);
140 set_uniform(
"color_scale", 1);
151 set_uniform_mat4(
"projection_matrix", P.data());
155 set_uniform_mat4(
"model_view_matrix", MV.data());
159 set_uniform_vec2(
"extent", extent.data());
163 set_uniform_vec2(
"pixel_width", pixel_width.data());
170 set_uniform(
"invert_scale", invert ? 1 : 0);
177 struct property_settings {
179 GLfloat min_scalar = std::numeric_limits<GLfloat>::max();
180 GLfloat max_scalar = -std::numeric_limits<GLfloat>::max();
181 bool scale_inverted =
false;
183 bool show_grid =
true;
184 bool show_property =
false;
187 std::unordered_map<std::string, property_settings> settings;
188 std::unordered_map<std::string, std::string_view> selected_component;
189 std::string
const* selected_property_name =
nullptr;
208 init_grid_geometry(
grid);
209 init_properties(
grid);
213 auto const num_vertices =
214 grid.template size<0>() * 2 +
grid.template size<1>() * 2;
215 geometry.vertexbuffer().resize(num_vertices);
216 geometry.indexbuffer().resize(num_vertices);
218 auto data = geometry.vertexbuffer().wmap();
219 auto k = std::size_t{};
220 for (std::size_t i = 0; i <
grid.template size<0>(); ++i) {
222 grid.template dimension<1>().front()};
224 grid.template dimension<1>().back()};
226 for (std::size_t i = 0; i <
grid.template size<1>(); ++i) {
228 grid.template dimension<1>()[i]};
230 grid.template dimension<1>()[i]};
234 auto data = geometry.indexbuffer().wmap();
235 for (std::size_t i = 0; i < num_vertices; ++i) {
242 tex.resize(
grid.template size<0>(),
grid.template size<1>());
244 for (
auto const& [name, prop] :
grid.vertex_properties()) {
245 if (prop_holds_scalar(prop)) {
246 auto min_scalar = std::numeric_limits<GLfloat>::max();
247 auto max_scalar = -std::numeric_limits<GLfloat>::max();
248 retrieve_typed_prop(prop.get(), [&](
auto const& prop) {
249 using prop_type = std::decay_t<decltype(prop)>;
250 using value_type = typename prop_type::value_type;
251 if constexpr (is_arithmetic<value_type>) {
252 grid.vertices().iterate_indices([&](auto const... is) {
253 auto const p = prop.at(is...);
254 min_scalar = std::min<GLfloat>(min_scalar, p);
255 max_scalar = std::max<GLfloat>(max_scalar, p);
260 }
else if (prop_holds_vector(prop)) {
261 retrieve_typed_prop(prop.get(), [&](
auto const& prop) {
262 using prop_type = std::decay_t<decltype(prop)>;
263 using value_type = typename prop_type::value_type;
264 if constexpr (static_vec<value_type>) {
265 auto constexpr num_comps = value_type::num_components();
266 auto min_scalars = std::vector<GLfloat>(
267 num_comps + 1, std::numeric_limits<GLfloat>::max());
268 auto max_scalars = std::vector<GLfloat>(
269 num_comps + 1, -std::numeric_limits<GLfloat>::max());
270 grid.vertices().iterate_indices([&](auto const... is) {
271 auto const p = prop.at(is...);
272 auto mag = typename value_type::value_type{};
273 for (std::size_t j = 0; j < num_comps; ++j) {
276 std::min<GLfloat>(min_scalars[j + 1], p(j));
278 std::max<GLfloat>(max_scalars[j + 1], p(j));
280 mag = std::sqrt(mag);
281 min_scalars[0] = std::min<GLfloat>(min_scalars[0], mag);
282 max_scalars[0] = std::max<GLfloat>(max_scalars[0], mag);
285 for (std::size_t j = 0; j < num_comps + 1; ++j) {
286 settings[name +
'_' + std::string{vector_component_names[j]}] = {
287 &color_scale::viridis(), min_scalars[j], max_scalars[j]};
289 selected_component[name] = vector_component_names[0];
296 template <
typename T>
302 if (prop->type() ==
typeid(
float)) {
303 f(*cast_prop<float>(prop));
304 }
else if (prop->type() ==
typeid(
double)) {
305 f(*cast_prop<double>(prop));
306 }
else if (prop->type() ==
typeid(
vec2d)) {
307 f(*cast_prop<vec2d>(prop));
308 }
else if (prop->type() ==
typeid(
vec2f)) {
309 f(*cast_prop<vec2f>(prop));
310 }
else if (prop->type() ==
typeid(
vec3d)) {
311 f(*cast_prop<vec3d>(prop));
312 }
else if (prop->type() ==
typeid(
vec3f)) {
313 f(*cast_prop<vec3f>(prop));
314 }
else if (prop->type() ==
typeid(
vec4d)) {
315 f(*cast_prop<vec4d>(prop));
316 }
else if (prop->type() ==
typeid(
vec4f)) {
317 f(*cast_prop<vec4f>(prop));
322 return prop->type() ==
typeid(float) || prop->type() ==
typeid(
double);
326 return prop->type() ==
typeid(
vec2f) || prop->type() ==
typeid(
vec2d) ||
327 prop->type() ==
typeid(
vec3f) || prop->type() ==
typeid(
vec3d) ||
328 prop->type() ==
typeid(
vec4f) || prop->type() ==
typeid(
vec4d);
333 auto texdata = std::vector<GLfloat>{};
334 texdata.reserve(
grid.vertices().size());
336 grid.vertices().iterate_indices(
337 [&](
auto const... is) { texdata.push_back(get_data(prop, is...)); });
338 tex.upload_data(texdata,
grid.template size<0>(),
grid.template size<1>());
342 retrieve_typed_prop(prop, [&](
auto&& prop) {
343 using prop_type = std::decay_t<
decltype(prop)>;
344 using value_type =
typename prop_type::value_type;
345 if constexpr (is_arithmetic<value_type>) {
346 upload_data_to_texture(
348 [](
auto const& prop,
auto const... is) {
return prop(is...); },
355 retrieve_typed_prop(prop, [&](
auto&& prop) {
356 using prop_type = std::decay_t<
decltype(prop)>;
357 using value_type =
typename prop_type::value_type;
359 upload_data_to_texture(
361 [](
auto const& prop,
auto const... is) {
362 auto mag =
typename value_type::value_type{};
364 mag += prop(is...)(j) * prop(is...)(j);
374 retrieve_typed_prop(prop, [&](
auto&& prop) {
375 using prop_type = std::decay_t<
decltype(prop)>;
376 using value_type =
typename prop_type::value_type;
378 upload_data_to_texture(
380 [](
auto const& prop,
auto const... is) {
return prop(is...).x(); },
387 retrieve_typed_prop(prop, [&](
auto&& prop) {
388 using prop_type = std::decay_t<
decltype(prop)>;
389 using value_type =
typename prop_type::value_type;
391 upload_data_to_texture(
393 [](
auto const& prop,
auto const... is) {
return prop(is...).y(); },
400 retrieve_typed_prop(prop, [&](
auto&& prop) {
401 using prop_type = std::decay_t<
decltype(prop)>;
402 using value_type =
typename prop_type::value_type;
405 upload_data_to_texture(
407 [](
auto const& prop,
auto const... is) {
408 return prop(is...).z();
417 retrieve_typed_prop(prop, [&](
auto&& prop) {
418 using prop_type = std::decay_t<
decltype(prop)>;
419 using value_type =
typename prop_type::value_type;
422 upload_data_to_texture(
424 [](
auto const& prop,
auto const... is) {
425 return prop(is...).w();
434 auto name = std::string{};
435 if (selected_property_name !=
nullptr) {
436 name = *selected_property_name;
437 if (
auto c = selected_component.find(name);
438 c !=
end(selected_component)) {
447 if (ImGui::BeginCombo(
"##combo", selected_property_name !=
nullptr
448 ? selected_property_name->c_str()
450 for (
auto const& [name, prop] :
grid.vertex_properties()) {
451 if (prop->type() ==
typeid(
float) || prop->type() ==
typeid(
double) ||
452 prop->type() ==
typeid(
vec2f) || prop->type() ==
typeid(
vec2d) ||
453 prop->type() ==
typeid(
vec3f) || prop->type() ==
typeid(
vec3d) ||
454 prop->type() ==
typeid(
vec4f) || prop->type() ==
typeid(
vec4d)) {
455 auto is_selected = selected_property == prop.get();
456 if (ImGui::Selectable(name.c_str(), is_selected)) {
457 selected_property = prop.get();
458 selected_property_name = &name;
459 if (prop_holds_scalar(prop)) {
460 upload_scalar_to_texture(selected_property,
grid);
462 }
else if (prop_holds_vector(prop)) {
463 upload_magnitude_to_texture(selected_property,
grid);
468 ImGui::SetItemDefaultFocus();
477 if (ImGui::BeginCombo(
478 "##combo_vector_component",
479 std::string{selected_component.at(*selected_property_name)}
481 auto n = std::size_t{};
482 retrieve_typed_prop(selected_property, [&](
auto&& prop) {
483 using prop_type = std::decay_t<
decltype(prop)>;
484 using value_type =
typename prop_type::value_type;
489 for (std::size_t i = 0; i < n + 1; ++i) {
490 auto const is_selected =
491 selected_component.at(*selected_property_name) ==
492 vector_component_names[i];
493 if (ImGui::Selectable(std::string{vector_component_names[i]}.c_str(),
495 selected_component.at(*selected_property_name) =
496 vector_component_names[i];
498 upload_magnitude_to_texture(selected_property,
grid);
500 upload_x_to_texture(selected_property,
grid);
502 upload_y_to_texture(selected_property,
grid);
504 upload_z_to_texture(selected_property,
grid);
506 upload_w_to_texture(selected_property,
grid);
518 if (selected_property !=
nullptr) {
519 auto combo_pos = ImGui::GetCursorScreenPos();
520 auto& setting = settings.at(selected_settings_name());
521 if (ImGui::BeginCombo(
"##combocolor",
522 selected_property_name !=
nullptr
523 ? selected_property_name->c_str()
525 ImGui::PushID(
"##viridis");
526 auto viridis_selected =
532 if (viridis_selected) {
536 ImGui::PushID(
"##GYPi");
549 ImGui::Text(
"Invert Color");
553 auto const backup_pos = ImGui::GetCursorScreenPos();
554 ImGuiStyle& style = ImGui::GetStyle();
555 ImGui::SetCursorScreenPos(
556 ImVec2(combo_pos.x + style.FramePadding.x, combo_pos.y));
557 ImGui::Image((
void*)(std::intptr_t)setting.c->tex_2d.id(),
559 ImGui::SetCursorScreenPos(backup_pos);
561 if (ImGui::Button(
"Rescale")) {
562 rescale_current_property(
grid);
568 auto const name = selected_settings_name();
569 auto& setting = settings[name];
570 auto min_scalar = std::numeric_limits<GLfloat>::max();
571 auto max_scalar = -std::numeric_limits<GLfloat>::max();
572 if (prop_holds_scalar(selected_property)) {
573 retrieve_typed_prop(selected_property, [&](
auto const& prop) {
574 using prop_type = std::decay_t<
decltype(prop)>;
575 using value_type =
typename prop_type::value_type;
576 if constexpr (is_arithmetic<value_type>) {
577 grid.vertices().iterate_indices([&](
auto const... is) {
578 auto const p = prop.at(is...);
579 min_scalar = std::min<GLfloat>(min_scalar, p);
580 max_scalar = std::max<GLfloat>(max_scalar, p);
584 }
else if (prop_holds_vector(selected_property)) {
585 retrieve_typed_prop(selected_property, [&](
auto const& prop) {
586 using prop_type = std::decay_t<
decltype(prop)>;
587 using value_type =
typename prop_type::value_type;
590 grid.vertices().iterate_indices([&](
auto const... is) {
591 auto const p = prop.at(is...);
592 if (selected_component.at(*selected_property_name) ==
593 vector_component_names[0]) {
594 auto mag = typename value_type::value_type{};
595 for (std::size_t i = 0; i < num_comps; ++i) {
598 mag = std::sqrt(mag);
599 min_scalar = std::min<GLfloat>(min_scalar, mag);
600 max_scalar = std::max<GLfloat>(max_scalar, mag);
602 auto s =
typename value_type::value_type{};
603 if (selected_component.at(*selected_property_name) ==
604 vector_component_names[1]) {
606 }
else if (selected_component.at(*selected_property_name) ==
607 vector_component_names[2]) {
609 }
else if (selected_component.at(*selected_property_name) ==
610 vector_component_names[3]) {
614 }
else if (selected_component.at(*selected_property_name) ==
615 vector_component_names[4]) {
620 min_scalar = std::min<GLfloat>(min_scalar, s);
621 max_scalar = std::max<GLfloat>(max_scalar, s);
627 setting.min_scalar = min_scalar;
628 setting.max_scalar = max_scalar;
632 ImGui::Text(
"Rectilinear Grid");
633 ImGui::Checkbox(
"Show Grid", &show_grid);
634 ImGui::Checkbox(
"Show Property", &show_property);
635 ImGui::DragInt(
"Line width", &line_width, 1, 1, 20);
636 ImGui::ColorEdit4(
"Grid Color", grid_color.data());
637 grid_property_selection(
grid);
639 vector_component_selection(
grid);
641 if (selected_property !=
nullptr) {
642 auto& setting = settings[selected_settings_name()];
643 ImGui::DragFloat(
"Min", &setting.min_scalar, 0.01f, -FLT_MAX,
644 setting.max_scalar,
"%.06f");
645 ImGui::DragFloat(
"Max", &setting.max_scalar, 0.01f, setting.min_scalar,
649 color_scale_selection(
grid);
656 if (show_property && selected_property !=
nullptr) {
663 using CamReal =
typename std::decay_t<
decltype(cam)>
::real_type;
664 static auto constexpr cam_is_float = is_same<GLfloat, CamReal>;
666 if constexpr (cam_is_float) {
673 if constexpr (cam_is_float) {
681 if constexpr (cam_is_float) {
688 if constexpr (cam_is_float) {
691 translation_matrix<GLfloat>(
grid.template dimension<0>().front(),
692 grid.template dimension<1>().front(),
694 scale_matrix<GLfloat>(
grid.template extent<0>(),
695 grid.template extent<1>(), 1));
699 scale_matrix<GLfloat>(
grid.template extent<0>(),
700 grid.template extent<1>(), 1) *
701 translation_matrix<GLfloat>(
grid.template dimension<0>().front(),
702 grid.template dimension<1>().front(),
707 grid.template dimension<0>()[1] -
grid.template dimension<0>()[0],
708 grid.template dimension<1>()[1] -
grid.template dimension<1>()[0]});
718 gl::line_width(line_width);
719 geometry.draw_lines();
725 if (selected_property_name !=
nullptr) {
726 auto const name = selected_settings_name();
727 auto& setting = settings.at(name);
731 setting.c->tex.bind(1);
Definition: indexeddata.h:13
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
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
rectilinear_grid(Dimensions &&...) -> rectilinear_grid< std::decay_t< Dimensions >... >
constexpr auto min(A &&a, B &&b)
Definition: math.h:15
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_grid3.h:135
auto set_model_view_matrix(Mat4< GLfloat > const &MV) -> void
Definition: rectilinear_grid3.h:154
auto set_pixel_width(Vec2< GLfloat > const &pixel_width) -> void
Definition: rectilinear_grid3.h:162
auto set_min(GLfloat const min) -> void
Definition: rectilinear_grid3.h:166
static auto get() -> auto &
Definition: rectilinear_grid3.h:128
auto set_projection_matrix(Mat4< GLfloat > const &P) -> void
Definition: rectilinear_grid3.h:150
auto set_extent(Vec2< GLfloat > const &extent) -> void
Definition: rectilinear_grid3.h:158
auto set_max(GLfloat const max) -> void
Definition: rectilinear_grid3.h:167
auto invert_scale(bool const invert) -> void
Definition: rectilinear_grid3.h:169
geometry()
Definition: rectilinear_grid3.h:28
static auto get() -> auto &
Definition: rectilinear_grid3.h:24
auto vector_component_selection(renderable_type const &grid)
Definition: rectilinear_grid3.h:476
gl::indexeddata< vec3f > m_right_geometry
Definition: rectilinear_grid3.h:199
auto init_properties(renderable_type const &grid)
Definition: rectilinear_grid3.h:241
gl::indexeddata< vec3f > m_bottom_geometry
Definition: rectilinear_grid3.h:201
auto upload_x_to_texture(auto &&prop, renderable_type const &grid)
Definition: rectilinear_grid3.h:373
auto update(auto const dt, renderable_type const &grid, camera auto const &cam)
Definition: rectilinear_grid3.h:661
auto prop_holds_vector(auto const &prop)
Definition: rectilinear_grid3.h:325
auto grid_property_selection(renderable_type const &grid)
Definition: rectilinear_grid3.h:446
auto properties(renderable_type const &grid)
Definition: rectilinear_grid3.h:631
gl::indexeddata< vec3f > m_top_geometry
Definition: rectilinear_grid3.h:200
auto selected_settings_name() const
Definition: rectilinear_grid3.h:433
auto render_grid()
Definition: rectilinear_grid3.h:712
auto upload_scalar_to_texture(auto &&prop, renderable_type const &grid)
Definition: rectilinear_grid3.h:341
auto upload_z_to_texture(auto &&prop, renderable_type const &grid)
Definition: rectilinear_grid3.h:399
auto rescale_current_property(renderable_type const &grid)
Definition: rectilinear_grid3.h:567
auto upload_data_to_texture(auto &&prop, auto &&get_data, renderable_type const &grid)
Definition: rectilinear_grid3.h:331
auto prop_holds_scalar(auto const &prop)
Definition: rectilinear_grid3.h:321
auto retrieve_typed_prop(auto &&prop, auto &&f)
Definition: rectilinear_grid3.h:301
renderer(renderable_type const &grid)
Definition: rectilinear_grid3.h:207
auto upload_magnitude_to_texture(auto &&prop, renderable_type const &grid)
Definition: rectilinear_grid3.h:354
auto render_property()
Definition: rectilinear_grid3.h:722
auto upload_w_to_texture(auto &&prop, renderable_type const &grid)
Definition: rectilinear_grid3.h:416
auto render()
Definition: rectilinear_grid3.h:652
gl::indexeddata< vec3f > m_outer_geometry
Definition: rectilinear_grid3.h:197
auto color_scale_selection(renderable_type const &grid)
Definition: rectilinear_grid3.h:517
gl::indexeddata< vec3f > m_left_geometry
Definition: rectilinear_grid3.h:198
auto upload_y_to_texture(auto &&prop, renderable_type const &grid)
Definition: rectilinear_grid3.h:386
gl::indexeddata< vec3f > m_back_geometry
Definition: rectilinear_grid3.h:203
gl::indexeddata< vec3f > m_front_geometry
Definition: rectilinear_grid3.h:202
typename renderable_type::typed_vertex_property_interface_t< T > typed_vertex_property_interface_t
Definition: rectilinear_grid3.h:21
auto init_grid_geometry(renderable_type const &grid)
Definition: rectilinear_grid3.h:212
static auto cast_prop(auto &&prop)
Definition: rectilinear_grid3.h:297
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
typename parent_t::template vertex_property_t< T > vertex_property_t
Definition: unstructured_grid.h:21
Definition: property.h:16