1#ifndef TATOOINE_RENDERING_INTERACTIVE_UNSTRUCTURED_TRIANGULAR_GRID3_H
2#define TATOOINE_RENDERING_INTERACTIVE_UNSTRUCTURED_TRIANGULAR_GRID3_H
15template <
floating_po
int Real>
17 static constexpr std::array<std::string_view, 5> vector_component_names = {
18 "magnitude",
"x",
"y",
"z",
"w"};
23 typename renderable_type::template typed_vertex_property_type<T>;
28 struct property_settings {
30 GLfloat min_scalar = std::numeric_limits<GLfloat>::max();
31 GLfloat max_scalar = -std::numeric_limits<GLfloat>::max();
32 bool scale_inverted =
false;
34 GLfloat reflectance = 0.8f;
35 GLfloat roughness = 0.5f;
36 GLfloat metallic = 0.0f;
37 GLfloat irradi_perp = 5.0f;
38 bool lighting_enabled =
true;
41 std::unordered_map<std::string, property_settings>
settings;
43 std::string
const* selected_property_name =
nullptr;
56 init_grid_geometry(
grid);
57 init_properties(
grid);
61 auto const n =
grid.vertices().size();
67 auto data = m_geometry.
wmap();
68 for (
auto const v :
grid.vertices()) {
72 for (
auto const t :
grid.simplices()) {
73 auto const [v0, v1, v2] =
grid[t];
75 data[v0.index()].template at<1>() += n;
76 data[v1.index()].template at<1>() += n;
77 data[v2.index()].template at<1>() += n;
79 for (
auto const v :
grid.vertices()) {
80 data[v.index()].template at<1>() =
81 normalize(data[v.index()].template at<1>());
85 auto data = m_triangles.
wmap();
86 auto k = std::size_t{};
87 for (
auto const s :
grid.simplices()) {
88 auto const [v0, v1, v2] =
grid[s];
96 if (!
grid.invalid_simplices().empty()) {
97 auto constexpr inc = [](
auto i) {
return ++i; };
99 std::vector<typename gl::indexbuffer::value_type>(
size(
grid.vertex_position_data()), 0);
100 for (
auto const v :
grid.invalid_vertices()) {
101 auto i =
begin(offsets) +
static_cast<std::ptrdiff_t
>(v.index());
102 std::ranges::transform(i,
end(offsets), i, inc);
104 for (
auto& i : data) {
110 auto data = m_wireframe.
wmap();
111 auto k = std::size_t{};
112 for (
auto const s :
grid.simplices()) {
113 auto const [v0, v1, v2] =
grid[s];
126 for (
auto const& key_value :
grid.vertex_properties()) {
127 auto const& [name, prop] = key_value;
128 if (prop_holds_scalar(prop)) {
129 auto min_scalar = std::numeric_limits<GLfloat>::max();
130 auto max_scalar = -std::numeric_limits<GLfloat>::max();
131 retrieve_typed_prop(prop.get(), [&](
auto const& prop) {
132 using prop_type = std::decay_t<decltype(prop)>;
133 using value_type = typename prop_type::value_type;
134 if constexpr (is_arithmetic<value_type>) {
135 for (auto const v : grid.vertices()) {
136 auto const p = prop[v.index()];
137 min_scalar = std::min(min_scalar, static_cast<GLfloat>(p));
138 max_scalar = std::max(max_scalar, static_cast<GLfloat>(p));
143 }
else if (prop_holds_vector(prop)) {
144 retrieve_typed_prop(prop.get(), [&](
auto const& prop) {
145 using prop_type = std::decay_t<decltype(prop)>;
146 using value_type = typename prop_type::value_type;
147 if constexpr (static_vec<value_type>) {
148 auto constexpr num_comps = value_type::num_components();
149 auto min_scalars = std::vector<GLfloat>(
150 num_comps + 1, std::numeric_limits<GLfloat>::max());
151 auto max_scalars = std::vector<GLfloat>(
152 num_comps + 1, -std::numeric_limits<GLfloat>::max());
153 for (auto const v : grid.vertices()) {
154 auto const p = prop[v.index()];
155 auto mag = typename value_type::value_type{};
156 for (std::size_t j = 0; j < num_comps; ++j) {
159 std::min(min_scalars[j + 1], static_cast<GLfloat>(p(j)));
161 std::max(max_scalars[j + 1], static_cast<GLfloat>(p(j)));
163 mag = std::sqrt(mag);
164 min_scalars[0] = std::min(min_scalars[0], static_cast<GLfloat>(mag));
165 max_scalars[0] = std::max(max_scalars[0], static_cast<GLfloat>(mag));
168 for (std::size_t j = 0; j < num_comps + 1; ++j) {
169 settings[key_value.first +
'_' + std::string{vector_component_names[j]}] = {
170 &color_scale::viridis(), min_scalars[j], max_scalars[j]};
172 selected_component[key_value.first] = vector_component_names[0];
180 if (prop->type() ==
typeid(
float)) {
181 f(prop->template cast_to_typed<float>());
182 }
else if (prop->type() ==
typeid(
double)) {
183 f(prop->template cast_to_typed<double>());
184 }
else if (prop->type() ==
typeid(
vec2d)) {
185 f(prop->template cast_to_typed<vec2d>());
186 }
else if (prop->type() ==
typeid(
vec2f)) {
187 f(prop->template cast_to_typed<vec2f>());
188 }
else if (prop->type() ==
typeid(
vec3d)) {
189 f(prop->template cast_to_typed<vec3d>());
190 }
else if (prop->type() ==
typeid(
vec3f)) {
191 f(prop->template cast_to_typed<vec3f>());
192 }
else if (prop->type() ==
typeid(
vec4d)) {
193 f(prop->template cast_to_typed<vec4d>());
194 }
else if (prop->type() ==
typeid(
vec4f)) {
195 f(prop->template cast_to_typed<vec4f>());
200 return prop->type() ==
typeid(float) || prop->type() ==
typeid(
double);
204 return prop->type() ==
typeid(
vec2f) || prop->type() ==
typeid(
vec2d) ||
205 prop->type() ==
typeid(
vec3f) || prop->type() ==
typeid(
vec3d) ||
206 prop->type() ==
typeid(
vec4f) || prop->type() ==
typeid(
vec4d);
210 auto data = m_geometry.rwmap();
211 for (std::size_t i = 0; i <
grid.vertices().
size(); ++i) {
212 get<2>(data[i]) =
static_cast<GLfloat
>(get_data(prop, i));
217 retrieve_typed_prop(prop, [&](
auto&& prop) {
218 using prop_type = std::decay_t<
decltype(prop)>;
219 using value_type =
typename prop_type::value_type;
220 if constexpr (is_arithmetic<value_type>) {
223 [](
auto const& prop,
auto const i) {
return prop[i]; },
230 retrieve_typed_prop(prop, [&](
auto&& prop) {
231 using prop_type = std::decay_t<
decltype(prop)>;
232 using value_type =
typename prop_type::value_type;
236 [](
auto const& prop,
auto const i) {
237 auto mag =
typename value_type::value_type{};
239 mag += prop[i](j) * prop[i](j);
249 retrieve_typed_prop(prop, [&](
auto&& prop) {
250 using prop_type = std::decay_t<
decltype(prop)>;
251 using value_type =
typename prop_type::value_type;
255 [](
auto const& prop,
auto const i) {
return prop[i].x(); },
262 retrieve_typed_prop(prop, [&](
auto&& prop) {
263 using prop_type = std::decay_t<
decltype(prop)>;
264 using value_type =
typename prop_type::value_type;
268 [](
auto const& prop,
auto const i) {
return prop[i].y(); },
275 retrieve_typed_prop(prop, [&](
auto&& prop) {
276 using prop_type = std::decay_t<
decltype(prop)>;
277 using value_type =
typename prop_type::value_type;
282 [](
auto const& prop,
auto const i) {
292 retrieve_typed_prop(prop, [&](
auto&& prop) {
293 using prop_type = std::decay_t<
decltype(prop)>;
294 using value_type =
typename prop_type::value_type;
299 [](
auto const& prop,
auto const i) {
309 auto name = std::string{};
310 if (selected_property_name !=
nullptr) {
311 name = *selected_property_name;
312 if (
auto c = selected_component.find(name);
313 c !=
end(selected_component)) {
322 if (ImGui::BeginCombo(
"##combo", selected_property_name !=
nullptr
323 ? selected_property_name->c_str()
325 if (ImGui::Selectable(
"Solid Color", selected_property ==
nullptr)) {
326 selected_property =
nullptr;
328 for (
auto const& [name, prop] :
grid.vertex_properties()) {
329 if (prop->type() ==
typeid(
float) || prop->type() ==
typeid(
double) ||
330 prop->type() ==
typeid(
vec2f) || prop->type() ==
typeid(
vec2d) ||
331 prop->type() ==
typeid(
vec3f) || prop->type() ==
typeid(
vec3d) ||
332 prop->type() ==
typeid(
vec4f) || prop->type() ==
typeid(
vec4d)) {
333 auto is_selected = selected_property == prop.get();
334 if (ImGui::Selectable(name.c_str(), is_selected)) {
335 selected_property = prop.get();
336 selected_property_name = &name;
337 if (prop_holds_scalar(prop)) {
338 upload_scalar_to_texture(selected_property,
grid);
340 }
else if (prop_holds_vector(prop)) {
341 upload_magnitude_to_texture(selected_property,
grid);
343 for (std::size_t i = 0; i < 5; ++i) {
344 auto const is_selected =
345 selected_component.at(*selected_property_name) ==
346 vector_component_names[i];
347 if (is_selected && i == 0) {
348 upload_magnitude_to_texture(selected_property,
grid);
349 }
else if (is_selected && i == 1) {
350 upload_x_to_texture(selected_property,
grid);
351 }
else if (is_selected && i == 2) {
352 upload_y_to_texture(selected_property,
grid);
353 }
else if (is_selected && i == 3) {
354 upload_z_to_texture(selected_property,
grid);
355 }
else if (is_selected && i == 4) {
356 upload_w_to_texture(selected_property,
grid);
364 ImGui::SetItemDefaultFocus();
373 if (ImGui::BeginCombo(
374 "##combo_vector_component",
375 std::string{selected_component.at(*selected_property_name)}
377 auto n = std::size_t{};
378 retrieve_typed_prop(selected_property, [&](
auto&& prop) {
379 using prop_type = std::decay_t<
decltype(prop)>;
380 using value_type =
typename prop_type::value_type;
385 for (std::size_t i = 0; i < n + 1; ++i) {
386 auto const is_selected =
387 selected_component.at(*selected_property_name) ==
388 vector_component_names[i];
389 if (ImGui::Selectable(std::string{vector_component_names[i]}.c_str(),
391 selected_component.at(*selected_property_name) =
392 vector_component_names[i];
394 upload_magnitude_to_texture(selected_property,
grid);
396 upload_x_to_texture(selected_property,
grid);
398 upload_y_to_texture(selected_property,
grid);
400 upload_z_to_texture(selected_property,
grid);
402 upload_w_to_texture(selected_property,
grid);
414 if (selected_property !=
nullptr) {
415 auto combo_pos = ImGui::GetCursorScreenPos();
416 auto& setting = settings.at(selected_settings_name());
417 if (ImGui::BeginCombo(
"##combocolor",
418 selected_property_name !=
nullptr
419 ? selected_property_name->c_str()
421 ImGui::PushID(
"##viridis");
422 auto viridis_selected =
428 if (viridis_selected) {
432 ImGui::PushID(
"##GYPi");
445 ImGui::Text(
"Invert Color");
449 auto const backup_pos = ImGui::GetCursorScreenPos();
450 ImGuiStyle& style = ImGui::GetStyle();
451 ImGui::SetCursorScreenPos(
452 ImVec2(combo_pos.x + style.FramePadding.x, combo_pos.y));
453 ImGui::Image((
void*)(std::intptr_t)setting.c->tex_2d.id(),
455 ImGui::SetCursorScreenPos(backup_pos);
457 if (ImGui::Button(
"Rescale")) {
458 rescale_current_property(
grid);
464 auto const name = selected_settings_name();
465 auto& setting = settings[name];
466 auto min_scalar = std::numeric_limits<GLfloat>::max();
467 auto max_scalar = -std::numeric_limits<GLfloat>::max();
468 if (prop_holds_scalar(selected_property)) {
469 retrieve_typed_prop(selected_property, [&](
auto const& prop) {
470 using prop_type = std::decay_t<
decltype(prop)>;
471 using value_type =
typename prop_type::value_type;
472 if constexpr (is_arithmetic<value_type>) {
473 for (
auto const v :
grid.vertices()) {
474 auto const p = prop[v.index()];
475 min_scalar = std::min(min_scalar,
static_cast<GLfloat
>(p));
476 max_scalar = std::max(max_scalar,
static_cast<GLfloat
>(p));
480 }
else if (prop_holds_vector(selected_property)) {
481 retrieve_typed_prop(selected_property, [&](
auto const& prop) {
482 using prop_type = std::decay_t<
decltype(prop)>;
483 using value_type =
typename prop_type::value_type;
486 for (
auto const v :
grid.vertices()) {
487 auto const p = prop[v.index()];
488 if (selected_component.at(*selected_property_name) ==
489 vector_component_names[0]) {
490 auto mag =
typename value_type::value_type{};
491 for (std::size_t i = 0; i < num_comps; ++i) {
494 mag = std::sqrt(mag);
495 min_scalar = std::min(min_scalar,
static_cast<GLfloat
>(mag));
496 max_scalar = std::max(max_scalar,
static_cast<GLfloat
>(mag));
498 auto s =
typename value_type::value_type{};
499 if (selected_component.at(*selected_property_name) ==
500 vector_component_names[1]) {
502 }
else if (selected_component.at(*selected_property_name) ==
503 vector_component_names[2]) {
505 }
else if (selected_component.at(*selected_property_name) ==
506 vector_component_names[3]) {
510 }
else if (selected_component.at(*selected_property_name) ==
511 vector_component_names[4]) {
516 min_scalar = std::min(min_scalar,
static_cast<GLfloat
>(s));
517 max_scalar = std::max(max_scalar,
static_cast<GLfloat
>(s));
523 setting.min_scalar = min_scalar;
524 setting.max_scalar = max_scalar;
529 ImGui::Checkbox(
"Enable Lighting", &lighting_enabled);
530 if (lighting_enabled) {
531 ImGui::DragFloat(
"Reflectance", &reflectance, 0.01f, 0.0f, 1.0f);
532 ImGui::DragFloat(
"Roughness", &roughness, 0.01f, 0.0f, 1.0f);
533 ImGui::DragFloat(
"Metallic", &metallic, 0.01f, 0.0f, 1.0f);
534 ImGui::DragFloat(
"Irradiance Perp", &irradi_perp, 0.1f, 0.0f, 100.0f);
536 grid_property_selection(
grid);
538 vector_component_selection(
grid);
540 if (selected_property !=
nullptr) {
541 auto& setting = settings[selected_settings_name()];
542 ImGui::DragFloat(
"Min", &setting.min_scalar, 0.01f, -FLT_MAX,
543 setting.max_scalar,
"%.06f");
544 ImGui::DragFloat(
"Max", &setting.max_scalar, 0.01f, setting.min_scalar,
547 if (selected_property ==
nullptr) {
548 ImGui::ColorEdit3(
"Solid Color", solid_base_color.data());
551 color_scale_selection(
grid);
556 if (selected_property !=
nullptr) {
557 auto const name = selected_settings_name();
558 auto& setting = settings.at(name);
559 setting.c->tex.bind(0);
586 m_geometry.activate_attributes();
588 vao.draw_triangles(m_triangles.size());
594 using CamReal =
typename std::decay_t<
decltype(cam)>
::real_type;
595 static auto constexpr cam_is_float = is_same<GLfloat, CamReal>;
597 if constexpr (cam_is_float) {
604 if constexpr (cam_is_float) {
auto resize(GLsizei size) -> void
Definition: buffer.h:640
auto wmap()
Definition: buffer.h:506
Definition: indexbuffer.h:13
Definition: vertexarray.h:15
DLL_API void bind() const
Definition: vertexbuffer.h:22
Definition: grid_edge.h:16
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
auto begin(Range &&range)
Definition: iterator_facade.h:318
typename value_type_impl< T >::type value_type
Definition: type_traits.h:280
auto end(Range &&range)
Definition: iterator_facade.h:322
constexpr auto normalize(base_tensor< Tensor, T, N > const &t_in) -> vec< T, N >
Definition: tensor_operations.h:100
auto size(vec< ValueType, N > const &v)
Definition: vec.h:148
constexpr auto cross(base_tensor< Tensor0, T0, 3 > const &lhs, base_tensor< Tensor1, T1, 3 > const &rhs)
Definition: cross.h:9
typename Line::vertex_property_type vertex_property_type
Definition: vtk_writer.h:20
static constexpr GLsizei num_components
Definition: texcomponents.h:10
Definition: color_scale.h:25
static auto viridis() -> auto &
Definition: color_scale.h:82
Definition: cook_torrance_brdf_shader.h:8
auto vector_component_selection(renderable_type const &grid)
Definition: unstructured_triangular_grid3.h:372
auto retrieve_typed_prop(auto &&prop, auto &&f)
Definition: unstructured_triangular_grid3.h:179
auto grid_property_selection(renderable_type const &grid)
Definition: unstructured_triangular_grid3.h:321
auto upload_w_to_texture(auto &&prop, renderable_type const &grid)
Definition: unstructured_triangular_grid3.h:291
gl::indexbuffer m_triangles
Definition: unstructured_triangular_grid3.h:50
auto upload_y_to_texture(auto &&prop, renderable_type const &grid)
Definition: unstructured_triangular_grid3.h:261
typename renderable_type::template typed_vertex_property_type< T > typed_vertex_property_interface_type
Definition: unstructured_triangular_grid3.h:23
auto prop_holds_scalar(auto const &prop)
Definition: unstructured_triangular_grid3.h:199
auto upload_z_to_texture(auto &&prop, renderable_type const &grid)
Definition: unstructured_triangular_grid3.h:274
renderer(renderable_type const &grid)
Definition: unstructured_triangular_grid3.h:55
auto render()
Definition: unstructured_triangular_grid3.h:554
auto upload_x_to_texture(auto &&prop, renderable_type const &grid)
Definition: unstructured_triangular_grid3.h:248
auto upload_data(auto &&prop, auto &&get_data, renderable_type const &grid)
Definition: unstructured_triangular_grid3.h:209
auto rescale_current_property(renderable_type const &grid)
Definition: unstructured_triangular_grid3.h:463
std::unordered_map< std::string, std::string_view > selected_component
Definition: unstructured_triangular_grid3.h:42
auto properties(renderable_type const &grid)
Definition: unstructured_triangular_grid3.h:527
auto selected_settings_name() const
Definition: unstructured_triangular_grid3.h:308
gl::indexbuffer m_wireframe
Definition: unstructured_triangular_grid3.h:51
std::unordered_map< std::string, property_settings > settings
Definition: unstructured_triangular_grid3.h:41
auto update(auto const, renderable_type const &, camera auto const &cam)
Definition: unstructured_triangular_grid3.h:592
auto init_grid_geometry(renderable_type const &grid)
Definition: unstructured_triangular_grid3.h:60
auto init_properties(renderable_type const &grid)
Definition: unstructured_triangular_grid3.h:125
auto upload_magnitude_to_texture(auto &&prop, renderable_type const &grid)
Definition: unstructured_triangular_grid3.h:229
gl::vertexbuffer< Vec3< GLfloat >, Vec3< GLfloat >, GLfloat > m_geometry
Definition: unstructured_triangular_grid3.h:49
auto prop_holds_vector(auto const &prop)
Definition: unstructured_triangular_grid3.h:203
auto color_scale_selection(renderable_type const &grid)
Definition: unstructured_triangular_grid3.h:413
auto upload_scalar_to_texture(auto &&prop, renderable_type const &grid)
Definition: unstructured_triangular_grid3.h:216
Definition: unstructured_simplicial_grid.h:52
Definition: unstructured_triangular_grid.h:10
static auto constexpr zeros()
Definition: vec.h:26
Definition: property.h:16