Tatooine
rectilinear_grid2.h
Go to the documentation of this file.
1#ifndef TATOOINE_RENDERING_INTERACTIVE_RECTILINEAR_GRID2_H
2#define TATOOINE_RENDERING_INTERACTIVE_RECTILINEAR_GRID2_H
3//==============================================================================
11//==============================================================================
13//==============================================================================
14template <typename Axis0, typename Axis1>
15struct renderer<tatooine::rectilinear_grid<Axis0, Axis1>> {
16 static constexpr std::array<std::string_view, 5> vector_component_names = {
17 "magnitude", "x", "y", "z", "w"};
19 template <typename T>
21 typename renderable_type::template typed_vertex_property_interface_type<
22 T>;
23 //============================================================================
24 struct geometry : gl::indexeddata<Vec2<GLfloat>> {
25 static auto get() -> auto& {
26 static auto instance = geometry{};
27 return instance;
28 }
29 explicit geometry() {
30 vertexbuffer().resize(4);
31 {
32 auto vb_map = vertexbuffer().wmap();
33 vb_map[0] = Vec2<GLfloat>{0, 0};
34 vb_map[1] = Vec2<GLfloat>{1, 0};
35 vb_map[2] = Vec2<GLfloat>{1, 1};
36 vb_map[3] = Vec2<GLfloat>{0, 1};
37 }
38 indexbuffer().resize(6);
39 {
40 auto data = indexbuffer().wmap();
41 data[0] = 0;
42 data[1] = 1;
43 data[2] = 3;
44 data[3] = 1;
45 data[4] = 2;
46 data[5] = 3;
47 }
48 }
49 };
50 //============================================================================
51 struct property_shader : gl::shader {
52 //--------------------------------------------------------------------------
53 static constexpr std::string_view vertex_shader =
54 "#version 330 core\n"
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"
61 "void main() {\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"
67 "}\n";
68 //--------------------------------------------------------------------------
69 static constexpr std::string_view fragment_shader =
70 "#version 330 core\n"
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"
76 "in vec2 texcoord;\n"
77 "out vec4 out_color;\n"
78 "void main() {\n"
79 " float scalar = texture(data, texcoord).r;\n"
80 " if (isnan(scalar)) {\n"
81 " out_color = vec4(1,0,0,1);\n"
82 " return;\n"
83 " }\n"
84 " scalar = clamp((scalar - min) / (max - min), 0, 1);\n"
85 " if (invert_scale == 1) {\n"
86 " scalar = 1 - scalar;\n"
87 " }\n"
88 " vec3 col = texture(color_scale, scalar).rgb;\n"
89 " out_color = vec4(col, 1);\n"
90 "}\n";
91 //--------------------------------------------------------------------------
92 static auto get() -> auto& {
93 static auto s = property_shader{};
94 return s;
95 }
96 //--------------------------------------------------------------------------
97 private:
98 //--------------------------------------------------------------------------
100 add_stage<gl::vertexshader>(gl::shadersource{vertex_shader});
101 add_stage<gl::fragmentshader>(gl::shadersource{fragment_shader});
102 create();
103 set_uniform("data", 0);
104 set_uniform("color_scale", 1);
105 set_projection_matrix(Mat4<GLfloat>::eye());
106 set_model_view_matrix(Mat4<GLfloat>::eye());
107 set_min(0);
108 set_max(1);
109 invert_scale(false);
110 }
111 //--------------------------------------------------------------------------
112 public:
113 //--------------------------------------------------------------------------
114 auto set_projection_matrix(Mat4<GLfloat> const& P) -> void {
115 set_uniform_mat4("projection_matrix", P.data());
116 }
117 //--------------------------------------------------------------------------
118 auto set_model_view_matrix(Mat4<GLfloat> const& MV) -> void {
119 set_uniform_mat4("model_view_matrix", MV.data());
120 }
121 //--------------------------------------------------------------------------
122 auto set_extent(Vec2<GLfloat> const& extent) -> void {
123 set_uniform_vec2("extent", extent.data());
124 }
125 //--------------------------------------------------------------------------
126 auto set_pixel_width(Vec2<GLfloat> const& pixel_width) -> void {
127 set_uniform_vec2("pixel_width", pixel_width.data());
128 }
129 //--------------------------------------------------------------------------
130 auto set_min(GLfloat const min) -> void { set_uniform("min", min); }
131 auto set_max(GLfloat const max) -> void { set_uniform("max", max); }
132 //--------------------------------------------------------------------------
133 auto invert_scale(bool const invert) -> void {
134 set_uniform("invert_scale", invert ? 1 : 0);
135 }
136 };
137 //============================================================================
139 //============================================================================
140 private:
141 struct property_settings {
142 color_scale* c = nullptr;
143 GLfloat min_scalar = std::numeric_limits<GLfloat>::max();
144 GLfloat max_scalar = -std::numeric_limits<GLfloat>::max();
145 bool scale_inverted = false;
146 };
147 bool show_grid = true;
148 bool show_property = false;
149 int line_width = 1;
150 Vec4<GLfloat> grid_color = {0, 0, 0, 1};
151 std::unordered_map<std::string, property_settings> settings;
152 std::unordered_map<std::string, std::string_view> selected_component;
153 std::string const* selected_property_name = nullptr;
154 typename renderable_type::vertex_property_type const* selected_property =
155 nullptr;
156
157 bool vector_property = false;
158
161
162 public:
163 //============================================================================
165 init_grid_geometry(grid);
166 init_properties(grid);
167 }
168 //----------------------------------------------------------------------------
170 auto const num_vertices =
171 grid.template size<0>() * 2 + grid.template size<1>() * 2;
172 geometry.vertexbuffer().resize(static_cast<GLsizei>(num_vertices));
173 geometry.indexbuffer().resize(static_cast<GLsizei>(num_vertices));
174 {
175 auto data = geometry.vertexbuffer().wmap();
176 auto k = std::size_t{};
177 for (std::size_t i = 0; i < grid.template size<0>(); ++i) {
178 data[k++] = Vec2<GLfloat>{grid.template dimension<0>()[i],
179 grid.template dimension<1>().front()};
180 data[k++] = Vec2<GLfloat>{grid.template dimension<0>()[i],
181 grid.template dimension<1>().back()};
182 }
183 for (std::size_t i = 0; i < grid.template size<1>(); ++i) {
184 data[k++] = Vec2<GLfloat>{grid.template dimension<0>().front(),
185 grid.template dimension<1>()[i]};
186 data[k++] = Vec2<GLfloat>{grid.template dimension<0>().back(),
187 grid.template dimension<1>()[i]};
188 }
189 }
190 {
191 auto data = geometry.indexbuffer().wmap();
192 for (std::size_t i = 0; i < num_vertices; ++i) {
193 data[i] = static_cast<value_type<decltype(data)>>(i);
194 }
195 }
196 }
197 //----------------------------------------------------------------------------
199 tex.resize(grid.template size<0>(), grid.template size<1>());
200
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));
214 });
215 }
216 });
217 settings[name] = {&color_scale::viridis(), min_scalar, max_scalar};
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) {
232 mag += p(j) * p(j);
233 min_scalars[j + 1] =
234 gcem::min(min_scalars[j + 1], static_cast<GLfloat>(p(j)));
235 max_scalars[j + 1] =
236 gcem::max(max_scalars[j + 1], static_cast<GLfloat>(p(j)));
237 }
238 mag = gcem::sqrt(mag);
239 min_scalars[0] =
240 gcem::min(min_scalars[0], static_cast<GLfloat>(mag));
241 max_scalars[0] =
242 gcem::max(max_scalars[0], static_cast<GLfloat>(mag));
243 });
244
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]};
248 }
249 selected_component[key_value.first] = vector_component_names[0];
250 }
251 });
252 }
253 }
254 }
255 //============================================================================
256 auto retrieve_typed_prop(auto&& prop, auto&& f) {
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>());
273 }
274 }
275 //----------------------------------------------------------------------------
276 auto prop_holds_scalar(auto const& prop) {
277 return prop->type() == typeid(float) || prop->type() == typeid(double);
278 }
279 //----------------------------------------------------------------------------
280 auto prop_holds_vector(auto const& prop) {
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);
284 }
285 //----------------------------------------------------------------------------
286 auto upload_data_to_texture(auto&& prop, auto&& get_data,
287 renderable_type const& grid) {
288 auto texdata = std::vector<GLfloat>{};
289 texdata.reserve(grid.vertices().size());
290
291 grid.vertices().iterate_indices([&](auto const... is) {
292 texdata.push_back(static_cast<GLfloat>(get_data(prop, is...)));
293 });
294 tex.upload_data(texdata, grid.template size<0>(), grid.template size<1>());
295 };
296 //----------------------------------------------------------------------------
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(
303 prop,
304 [](auto const& prop, auto const... is) { return prop(is...); },
305 grid);
306 }
307 });
308 }
309 //----------------------------------------------------------------------------
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;
314 if constexpr (static_vec<value_type>) {
315 upload_data_to_texture(
316 prop,
317 [](auto const& prop, auto const... is) {
318 auto mag = typename value_type::value_type{};
319 for (std::size_t j = 0; j < value_type::num_components(); ++j) {
320 mag += prop(is...)(j) * prop(is...)(j);
321 }
322 return mag / value_type::num_components();
323 },
324 grid);
325 }
326 });
327 }
328 //----------------------------------------------------------------------------
329 auto upload_x_to_texture(auto&& prop, renderable_type const& grid) {
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;
333 if constexpr (static_vec<value_type>) {
334 upload_data_to_texture(
335 prop,
336 [](auto const& prop, auto const... is) { return prop(is...).x(); },
337 grid);
338 }
339 });
340 }
341 //----------------------------------------------------------------------------
342 auto upload_y_to_texture(auto&& prop, renderable_type const& grid) {
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;
346 if constexpr (static_vec<value_type>) {
347 upload_data_to_texture(
348 prop,
349 [](auto const& prop, auto const... is) { return prop(is...).y(); },
350 grid);
351 }
352 });
353 }
354 //----------------------------------------------------------------------------
355 auto upload_z_to_texture(auto&& prop, renderable_type const& grid) {
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;
359 if constexpr (static_vec<value_type>) {
360 if constexpr (value_type::num_components() > 2) {
361 upload_data_to_texture(
362 prop,
363 [](auto const& prop, auto const... is) {
364 return prop(is...).z();
365 },
366 grid);
367 }
368 }
369 });
370 }
371 //----------------------------------------------------------------------------
372 auto upload_w_to_texture(auto&& prop, renderable_type const& grid) {
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;
376 if constexpr (static_vec<value_type>) {
377 if constexpr (value_type::num_components() > 3) {
378 upload_data_to_texture(
379 prop,
380 [](auto const& prop, auto const... is) {
381 return prop(is...).w();
382 },
383 grid);
384 }
385 }
386 });
387 }
388 //----------------------------------------------------------------------------
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)) {
395 name += "_";
396 name += c->second;
397 }
398 }
399 return name;
400 }
401 //----------------------------------------------------------------------------
403 if (ImGui::BeginCombo("##combo", selected_property_name != nullptr
404 ? selected_property_name->c_str()
405 : nullptr)) {
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);
418 vector_property = false;
419 } else if (prop_holds_vector(prop)) {
420 upload_magnitude_to_texture(selected_property, grid);
421
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);
436 }
437 }
438
439 vector_property = true;
440 }
441 }
442 if (is_selected) {
443 ImGui::SetItemDefaultFocus();
444 }
445 }
446 }
447 ImGui::EndCombo();
448 }
449 }
450 //----------------------------------------------------------------------------
452 if (ImGui::BeginCombo(
453 "##combo_vector_component",
454 std::string{selected_component.at(*selected_property_name)}
455 .c_str())) {
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;
460 if constexpr (static_vec<value_type>) {
462 }
463 });
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(),
469 is_selected)) {
470 selected_component.at(*selected_property_name) =
471 vector_component_names[i];
472 if (i == 0) {
473 upload_magnitude_to_texture(selected_property, grid);
474 } else if (i == 1) {
475 upload_x_to_texture(selected_property, grid);
476 } else if (i == 2) {
477 upload_y_to_texture(selected_property, grid);
478 } else if (i == 3) {
479 upload_z_to_texture(selected_property, grid);
480 } else if (i == 4) {
481 upload_w_to_texture(selected_property, grid);
482 }
483 }
484 }
485 ImGui::EndCombo();
486 }
487 // ImGui::DragFloat("Min", &min_scalar, 0.01f, -FLT_MAX, max_scalar,
488 // "%.06f"); ImGui::DragFloat("Max", &max_scalar, 0.01f, min_scalar,
489 // FLT_MAX, "%.06f");
490 }
491 //----------------------------------------------------------------------------
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()
499 : nullptr)) {
500 bool selected = false;
501 ImGui::PushID("##viridis");
502 selected = ImGui::Selectable("", setting.c == &color_scale::viridis());
503 ImGui::PopID();
504 ImGui::SameLine();
505 ImGui::Image((void*)(std::intptr_t)color_scale::viridis().tex_2d.id(),
506 ImVec2(256, 20));
507 if (selected) {
508 setting.c = &color_scale::viridis();
509 }
510
511 ImGui::PushID("##magma");
512 selected = ImGui::Selectable("", setting.c == &color_scale::magma());
513 ImGui::PopID();
514 ImGui::SameLine();
515 ImGui::Image((void*)(std::intptr_t)color_scale::magma().tex_2d.id(),
516 ImVec2(256, 20));
517 if (selected) {
518 setting.c = &color_scale::magma();
519 }
520
521 ImGui::PushID("##cool_to_warm");
522 selected =
523 ImGui::Selectable("", setting.c == &color_scale::cool_to_warm());
524 ImGui::PopID();
525 ImGui::SameLine();
526 ImGui::Image(
527 (void*)(std::intptr_t)color_scale::cool_to_warm().tex_2d.id(),
528 ImVec2(256, 20));
529 if (selected) {
530 setting.c = &color_scale::cool_to_warm();
531 }
532
533 ImGui::PushID("##jet");
534 selected = ImGui::Selectable("", setting.c == &color_scale::jet());
535 ImGui::PopID();
536 ImGui::SameLine();
537 ImGui::Image((void*)(std::intptr_t)color_scale::jet().tex_2d.id(),
538 ImVec2(256, 20));
539 if (selected) {
540 setting.c = &color_scale::jet();
541 }
542
543 ImGui::PushID("##GYPi");
544 selected = ImGui::Selectable("", setting.c == &color_scale::GYPi());
545 ImGui::PopID();
546 ImGui::SameLine();
547 ImGui::Image((void*)(std::intptr_t)color_scale::GYPi().tex_2d.id(),
548 ImVec2(256, 20));
549 if (selected) {
550 setting.c = &color_scale::GYPi();
551 }
552
553 ImGui::PushID("##PiYG");
554 selected = ImGui::Selectable("", setting.c == &color_scale::PiYG());
555 ImGui::PopID();
556 ImGui::SameLine();
557 ImGui::Image((void*)(std::intptr_t)color_scale::PiYG().tex_2d.id(),
558 ImVec2(256, 20));
559 if (selected) {
560 setting.c = &color_scale::PiYG();
561 }
562
563 ImGui::PushID("##BrBG");
564 selected = ImGui::Selectable("", setting.c == &color_scale::BrBG());
565 ImGui::PopID();
566 ImGui::SameLine();
567 ImGui::Image((void*)(std::intptr_t)color_scale::BrBG().tex_2d.id(),
568 ImVec2(256, 20));
569 if (selected) {
570 setting.c = &color_scale::BrBG();
571 }
572
573 ImGui::PushID("##GBBr");
574 selected = ImGui::Selectable("", setting.c == &color_scale::GBBr());
575 ImGui::PopID();
576 ImGui::SameLine();
577 ImGui::Image((void*)(std::intptr_t)color_scale::GBBr().tex_2d.id(),
578 ImVec2(256, 20));
579 if (selected) {
580 setting.c = &color_scale::GBBr();
581 }
582
583 ImGui::PushID("##BuRD");
584 selected = ImGui::Selectable("", setting.c == &color_scale::BuRD());
585 ImGui::PopID();
586 ImGui::SameLine();
587 ImGui::Image((void*)(std::intptr_t)color_scale::BuRD().tex_2d.id(),
588 ImVec2(256, 20));
589 if (selected) {
590 setting.c = &color_scale::BuRD();
591 }
592
593 ImGui::PushID("##GnRP");
594 selected = ImGui::Selectable("", setting.c == &color_scale::GnRP());
595 ImGui::PopID();
596 ImGui::SameLine();
597 ImGui::Image((void*)(std::intptr_t)color_scale::GnRP().tex_2d.id(),
598 ImVec2(256, 20));
599 if (selected) {
600 setting.c = &color_scale::GnRP();
601 }
602
603 ImGui::PushID("##PRGn");
604 selected = ImGui::Selectable("", setting.c == &color_scale::PRGn());
605 ImGui::PopID();
606 ImGui::SameLine();
607 ImGui::Image((void*)(std::intptr_t)color_scale::PRGn().tex_2d.id(),
608 ImVec2(256, 20));
609 if (selected) {
610 setting.c = &color_scale::PRGn();
611 }
612
613 ImGui::PushID("##OrPu");
614 selected = ImGui::Selectable("", setting.c == &color_scale::OrPu());
615 ImGui::PopID();
616 ImGui::SameLine();
617 ImGui::Image((void*)(std::intptr_t)color_scale::OrPu().tex_2d.id(),
618 ImVec2(256, 20));
619 if (selected) {
620 setting.c = &color_scale::OrPu();
621 }
622
623 ImGui::PushID("##PuOr");
624 selected = ImGui::Selectable("", setting.c == &color_scale::PuOr());
625 ImGui::PopID();
626 ImGui::SameLine();
627 ImGui::Image((void*)(std::intptr_t)color_scale::PuOr().tex_2d.id(),
628 ImVec2(256, 20));
629 if (selected) {
630 setting.c = &color_scale::PuOr();
631 }
632
633 ImGui::PushID("##GnYIRd");
634 selected = ImGui::Selectable("", setting.c == &color_scale::GnYIRd());
635 ImGui::PopID();
636 ImGui::SameLine();
637 ImGui::Image((void*)(std::intptr_t)color_scale::GnYIRd().tex_2d.id(),
638 ImVec2(256, 20));
639 if (selected) {
640 setting.c = &color_scale::GnYIRd();
641 }
642 ImGui::EndCombo();
643 }
644 ImGui::SameLine();
645 ImGui::Text("Invert Color");
646 ImGui::SameLine();
647 ImGui::ToggleButton("inverted", &setting.scale_inverted);
648
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(),
654 ImVec2(256, 20));
655 ImGui::SetCursorScreenPos(backup_pos);
656
657 if (ImGui::Button("Rescale")) {
658 rescale_current_property(grid);
659 }
660 }
661 }
662 //----------------------------------------------------------------------------
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));
677 });
678 }
679 });
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;
684 if constexpr (static_vec<value_type>) {
685 auto constexpr num_comps = value_type::num_components();
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) {
692 mag += p(i) * p(i);
693 }
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));
697 } else {
698 auto s = typename value_type::value_type{};
699 if (selected_component.at(*selected_property_name) ==
700 vector_component_names[1]) {
701 s = p.x();
702 } else if (selected_component.at(*selected_property_name) ==
703 vector_component_names[2]) {
704 s = p.y();
705 } else if (selected_component.at(*selected_property_name) ==
706 vector_component_names[3]) {
707 if constexpr (value_type::num_components() > 2) {
708 s = p.z();
709 }
710 } else if (selected_component.at(*selected_property_name) ==
711 vector_component_names[4]) {
712 if constexpr (value_type::num_components() > 3) {
713 s = p.w();
714 }
715 }
716 min_scalar = gcem::min(min_scalar, static_cast<GLfloat>(s));
717 max_scalar = gcem::max(max_scalar, static_cast<GLfloat>(s));
718 }
719 });
720 }
721 });
722 }
723 setting.min_scalar = min_scalar;
724 setting.max_scalar = max_scalar;
725 }
726 //----------------------------------------------------------------------------
728 ImGui::Text("Rectilinear Grid");
729 ImGui::Checkbox("Show Grid", &show_grid);
730 if (show_grid) {
731 ImGui::DragInt("Line width", &line_width, 1, 1, 20);
732 ImGui::ColorEdit4("Grid Color", grid_color.data());
733 }
734 if (!grid.vertex_properties().empty()) {
735 ImGui::Checkbox("Show Property", &show_property);
736 grid_property_selection(grid);
737 }
738 if (selected_property != nullptr && vector_property) {
739 vector_component_selection(grid);
740 }
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,
746 FLT_MAX, "%.06f");
747 }
748
749 color_scale_selection(grid);
750 }
751 //============================================================================
752 auto render() {
753 if (show_grid) {
754 render_grid();
755 }
756 if (show_property && selected_property != nullptr) {
757 render_property();
758 }
759 }
760 //----------------------------------------------------------------------------
761 auto update(auto const /*dt*/, renderable_type const& grid,
762 camera auto const& cam) {
763 using CamReal = typename std::decay_t<decltype(cam)>::real_type;
764 static auto constexpr cam_is_float = is_same<GLfloat, CamReal>;
765 if (show_grid) {
766 if constexpr (cam_is_float) {
767 line_shader::get().set_projection_matrix(cam.projection_matrix());
768 } else {
769 line_shader::get().set_projection_matrix(
770 Mat4<GLfloat>{cam.projection_matrix()});
771 }
772
773 if constexpr (cam_is_float) {
774 line_shader::get().set_model_view_matrix(cam.view_matrix());
775 } else {
776 line_shader::get().set_model_view_matrix(
777 Mat4<GLfloat>{cam.view_matrix()});
778 }
779 }
780 if (show_property) {
781 if constexpr (cam_is_float) {
782 property_shader::get().set_projection_matrix(cam.projection_matrix());
783 } else {
784 property_shader::get().set_projection_matrix(
785 Mat4<GLfloat>{cam.projection_matrix()});
786 }
787
788 if constexpr (cam_is_float) {
789 property_shader::get().set_model_view_matrix(
790 cam.view_matrix() *
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));
797 } else {
798 property_shader::get().set_model_view_matrix(
799 Mat4<GLfloat>{cam.view_matrix()} *
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));
806 }
807 property_shader::get().set_extent(Vec2<GLfloat>{grid.extent()});
808 property_shader::get().set_pixel_width(Vec2<GLfloat>{
809 grid.template dimension<0>()[1] - grid.template dimension<0>()[0],
810 grid.template dimension<1>()[1] - grid.template dimension<1>()[0]});
811 }
812 }
813 //----------------------------------------------------------------------------
814 auto render_grid() {
817
818 line_shader.set_color(grid_color(0), grid_color(1), grid_color(2),
819 grid_color(3));
820 gl::line_width(static_cast<GLfloat>(line_width));
821 geometry.draw_lines();
822 }
823 //----------------------------------------------------------------------------
825 property_shader::get().bind();
826 tex.bind(0);
827 if (selected_property_name != nullptr) {
828 auto const name = selected_settings_name();
829 auto& setting = settings.at(name);
830 property_shader::get().set_min(setting.min_scalar);
831 property_shader::get().set_max(setting.max_scalar);
832 property_shader::get().invert_scale(setting.scale_inverted);
833 setting.c->tex.bind(1);
834 geometry::get().draw_triangles();
835 }
836 }
837};
838//==============================================================================
839} // namespace tatooine::rendering::interactive
840//==============================================================================
841#endif
Definition: indexeddata.h:13
auto indexbuffer() -> auto &
Definition: indexeddata.h:145
auto vertexbuffer() -> auto &
Definition: indexeddata.h:148
Definition: shader.h:24
DLL_API void bind() const
Definition: grid_edge.h:16
Definition: rectilinear_grid.h:38
Definition: camera.h:312
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: BrBG.h:12
Definition: BuRD.h:12
Definition: GBBr.h:12
Definition: GYPi.h:12
Definition: GnRP.h:12
Definition: GnYIRd.h:12
Definition: OrPu.h:12
Definition: PRGn.h:12
Definition: PiYG.h:12
Definition: PuOr.h:12
Definition: cool_to_warm.h:12
Definition: jet.h:12
Definition: magma.h:13
Definition: viridis.h:12
static constexpr GLsizei num_components
Definition: texcomponents.h:10
Definition: shadersource.h:8
Definition: mat.h:14
static auto viridis() -> auto &
Definition: color_scale.h:82
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_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 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 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 upload_w_to_texture(auto &&prop, renderable_type const &grid)
Definition: rectilinear_grid2.h:372
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
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: vec.h:12
Definition: property.h:16