Loading [MathJax]/extensions/tex2jax.js
Tatooine
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages Concepts
pointset.h
Go to the documentation of this file.
1#ifndef TATOOINE_RENDERING_INTERACTIVE_POINTSET_H
2#define TATOOINE_RENDERING_INTERACTIVE_POINTSET_H
3//==============================================================================
6#include <tatooine/linspace.h>
7#include <tatooine/pointset.h>
12//==============================================================================
14//==============================================================================
15template <floating_point Real>
16struct renderer<tatooine::pointset<Real, 2>> {
17 static constexpr std::array<std::string_view, 5> vector_component_names = {
18 "magnitude", "x", "y", "z", "w"};
20 template <typename T>
22 typename renderable_type::template typed_vertex_property_type<T>;
23 //==============================================================================
24 struct shader : gl::shader {
25 //------------------------------------------------------------------------------
26 static constexpr std::string_view vertex_shader =
27 "#version 330 core\n"
28 "layout (location = 0) in vec2 position;\n"
29 "layout (location = 1) in float prop;\n"
30 "out float prop_frag;\n"
31 "uniform mat4 projection_matrix;\n"
32 "uniform mat4 view_matrix;\n"
33 "void main() {\n"
34 " prop_frag = prop;\n"
35 " gl_Position = projection_matrix * view_matrix *\n"
36 " vec4(position, 0, 1);\n"
37 "}\n";
38 //------------------------------------------------------------------------------
39 static constexpr std::string_view fragment_shader =
40 "#version 330 core\n"
41 "uniform vec4 color;\n"
42 "in float prop_frag;\n"
43 "out vec4 out_color;\n"
44 "uniform int show_property;\n"
45 "uniform int invert_scale;\n"
46 "uniform float min;\n"
47 "uniform float max;\n"
48 "uniform sampler1D color_scale;\n"
49 "void main() {\n"
50 " if (show_property == 0) {\n"
51 " out_color = color;\n"
52 " } else {\n"
53 " float scalar = prop_frag;\n"
54 " if (isnan(scalar)) { discard; }\n"
55 " scalar = clamp((scalar - min) / (max - min), 0, 1);\n"
56 " if (invert_scale == 1) {\n"
57 " scalar = 1 - scalar;\n"
58 " }\n"
59 " vec3 col = texture(color_scale, scalar).rgb;\n"
60 " out_color = vec4(col, 1);\n"
61 " }\n"
62 "}\n";
63 //------------------------------------------------------------------------------
64 static auto get() -> auto& {
65 static auto s = shader{};
66 return s;
67 }
68 //------------------------------------------------------------------------------
69 private:
70 //------------------------------------------------------------------------------
72 add_stage<gl::vertexshader>(gl::shadersource{vertex_shader});
73 add_stage<gl::fragmentshader>(gl::shadersource{fragment_shader});
74 create();
75 set_color(0, 0, 0);
76 set_projection_matrix(Mat4<GLfloat>::eye());
77 set_view_matrix(Mat4<GLfloat>::eye());
78 set_uniform("color_scale", 0);
79 }
80 //------------------------------------------------------------------------------
81 public:
82 //------------------------------------------------------------------------------
83 auto set_color(GLfloat const r, GLfloat const g, GLfloat const b,
84 GLfloat const a = 1) -> void {
85 set_uniform("color", r, g, b, a);
86 }
87 //------------------------------------------------------------------------------
88 auto set_projection_matrix(Mat4<GLfloat> const& P) -> void {
89 set_uniform_mat4("projection_matrix", P.data());
90 }
91 //------------------------------------------------------------------------------
92 auto set_view_matrix(Mat4<GLfloat> const& V) -> void {
93 set_uniform_mat4("view_matrix", V.data());
94 }
95 //--------------------------------------------------------------------------
96 auto invert_scale(bool const invert) -> void {
97 set_uniform("invert_scale", invert ? 1 : 0);
98 }
99 //--------------------------------------------------------------------------
100 auto show_property(bool const show) -> void {
101 set_uniform("show_property", show ? 1 : 0);
102 }
103 //--------------------------------------------------------------------------
104 auto set_min(GLfloat const min) -> void {
105 set_uniform("min", min);
106 }
107 //--------------------------------------------------------------------------
108 auto set_max(GLfloat const max) -> void {
109 set_uniform("max", max);
110 }
111 };
112 static auto set_projection_matrix(Mat4<GLfloat> const& P) {
113 shader::get().set_projection_matrix(P);
114 }
115 static auto set_view_matrix(Mat4<GLfloat> const& V) {
116 shader::get().set_view_matrix(V);
117 }
118 //==============================================================================
119 struct property_settings {
120 color_scale* c = nullptr;
121 GLfloat min_scalar = std::numeric_limits<GLfloat>::max();
122 GLfloat max_scalar = -std::numeric_limits<GLfloat>::max();
123 bool scale_inverted = false;
124 };
125 //==============================================================================
126 GLfloat point_size = 1;
127 Vec4<GLfloat> color = {0, 0, 0, 1};
130 typename renderable_type::vertex_property_type const* selected_property =
131 nullptr;
132 std::string const* selected_property_name = nullptr;
133 std::unordered_map<std::string, property_settings> settings;
134 std::unordered_map<std::string, std::string_view> selected_component;
135 bool vector_property = false;
136 bool show_property = false;
137 //==============================================================================
139 {
140 geometry.vertexbuffer().resize(ps.vertices().size());
141 auto m = geometry.vertexbuffer().wmap();
142 for (auto v : ps.vertices()) {
143 m[v.index()] = {Vec2<GLfloat>{ps[v]}, GLfloat{}};
144 }
145 }
146 {
147 geometry.indexbuffer().resize(ps.vertices().size());
148 auto m = geometry.indexbuffer().wmap();
149 for (auto v : ps.vertices()) {
150 m[v.index()] = v.index();
151 }
152 }
153 init_properties(ps);
154 }
155 //----------------------------------------------------------------------------
156 template <typename T>
157 static auto cast_prop(auto&& prop) {
158 return static_cast<typed_vertex_property_type<T> const*>(prop);
159 }
160 //----------------------------------------------------------------------------
161 auto retrieve_typed_prop(auto&& prop, auto&& f) {
162 if (prop->type() == typeid(float)) {
163 f(*cast_prop<float>(prop));
164 } else if (prop->type() == typeid(double)) {
165 f(*cast_prop<double>(prop));
166 } else if (prop->type() == typeid(vec2d)) {
167 f(*cast_prop<vec2d>(prop));
168 } else if (prop->type() == typeid(vec2f)) {
169 f(*cast_prop<vec2f>(prop));
170 } else if (prop->type() == typeid(vec3d)) {
171 f(*cast_prop<vec3d>(prop));
172 } else if (prop->type() == typeid(vec3f)) {
173 f(*cast_prop<vec3f>(prop));
174 } else if (prop->type() == typeid(vec4d)) {
175 f(*cast_prop<vec4d>(prop));
176 } else if (prop->type() == typeid(vec4f)) {
177 f(*cast_prop<vec4f>(prop));
178 }
179 }
180 //----------------------------------------------------------------------------
181 auto prop_holds_scalar(auto const& prop) {
182 return prop->template holds_type<float>() ||
183 prop->template holds_type<double>();
184 }
185 //----------------------------------------------------------------------------
186 auto prop_holds_vector(auto const& prop) {
187 return prop->template holds_type<vec2f>() ||
188 prop->template holds_type<vec2d>() ||
189 prop->template holds_type<vec3f>() ||
190 prop->template holds_type<vec3d>() ||
191 prop->template holds_type<vec4f>() ||
192 prop->template holds_type<vec4d>();
193 }
194 //----------------------------------------------------------------------------
196 for (auto const& key_value : ps.vertex_properties()) {
197 auto const& [name, prop] = key_value;
198 if (prop_holds_scalar(prop)) {
199 auto min_scalar = std::numeric_limits<GLfloat>::max();
200 auto max_scalar = -std::numeric_limits<GLfloat>::max();
201 retrieve_typed_prop(prop.get(), [&](auto const& prop) {
202 using prop_type = std::decay_t<decltype(prop)>;
203 using value_type = typename prop_type::value_type;
204 if constexpr (is_arithmetic<value_type>) {
205 for (auto const v: ps.vertices()) {
206 auto const p = prop[v];
207 min_scalar = std::min<GLfloat>(min_scalar, p);
208 max_scalar = std::max<GLfloat>(max_scalar, p);
209 }
210 }
211 });
212 settings[name] = {&color_scale::viridis(), min_scalar, max_scalar};
213 } else if (prop_holds_vector(prop)) {
214 retrieve_typed_prop(prop.get(), [&](auto const& prop) {
215 using prop_type = std::decay_t<decltype(prop)>;
216 using value_type = typename prop_type::value_type;
217 if constexpr (static_vec<value_type>) {
218 auto constexpr num_comps = value_type::num_components();
219 auto min_scalars = std::vector<GLfloat>(
220 num_comps + 1, std::numeric_limits<GLfloat>::max());
221 auto max_scalars = std::vector<GLfloat>(
222 num_comps + 1, -std::numeric_limits<GLfloat>::max());
223 for (auto const v: ps.vertices()) {
224 auto const p = prop[v];
225 auto mag = typename value_type::value_type{};
226 for (std::size_t j = 0; j < num_comps; ++j) {
227 mag += p(j) * p(j);
228 min_scalars[j + 1] =
229 std::min<GLfloat>(min_scalars[j + 1], p(j));
230 max_scalars[j + 1] =
231 std::max<GLfloat>(max_scalars[j + 1], p(j));
232 }
233 mag = std::sqrt(mag);
234 min_scalars[0] = std::min<GLfloat>(min_scalars[0], mag);
235 max_scalars[0] = std::max<GLfloat>(max_scalars[0], mag);
236 }
237 auto const& [name, prop] = key_value;
238 for (std::size_t j = 0; j < num_comps + 1; ++j) {
239 settings[name + '_' + std::string{vector_component_names[j]}] = {
240 &color_scale::viridis(), min_scalars[j], max_scalars[j]};
241 }
242 selected_component[name] = vector_component_names[0];
243 }
244 });
245 }
246 }
247 }
248 //----------------------------------------------------------------------------
250 auto name = std::string{};
251 if (selected_property_name != nullptr) {
252 name = *selected_property_name;
253 if (auto c = selected_component.find(name);
254 c != end(selected_component)) {
255 name += "_";
256 name += c->second;
257 }
258 }
259 return name;
260 }
261 //----------------------------------------------------------------------------
262 auto upload_data(auto&& prop, auto&& get_data,
263 renderable_type const& ps) {
264 auto map = geometry.vertexbuffer().wmap();
265 for (auto const v : ps.vertices()) {
266 map[v.index()] = {Vec2<GLfloat>{ps[v]}, get_data(prop, v)};
267 }
268 };
269 //----------------------------------------------------------------------------
270 auto upload_scalar(auto&& prop, renderable_type const& grid) {
271 retrieve_typed_prop(prop, [&](auto&& prop) {
272 using prop_type = std::decay_t<decltype(prop)>;
273 using value_type = typename prop_type::value_type;
274 if constexpr (is_arithmetic<value_type>) {
275 upload_data(
276 prop, [](auto const& prop, auto const v) { return prop[v]; }, grid);
277 }
278 });
279 }
280 //----------------------------------------------------------------------------
281 auto upload_magnitude(auto&& prop, renderable_type const& grid) {
282 retrieve_typed_prop(prop, [&](auto&& prop) {
283 using prop_type = std::decay_t<decltype(prop)>;
284 using value_type = typename prop_type::value_type;
285 if constexpr (static_vec<value_type>) {
286 upload_data(
287 prop,
288 [](auto const& prop, auto const v) {
289 auto mag = typename value_type::value_type{};
290 for (std::size_t j = 0; j < value_type::num_components(); ++j) {
291 mag += prop[v](j) * prop[v](j);
292 }
293 return mag / value_type::num_components();
294 },
295 grid);
296 }
297 });
298 }
299 //----------------------------------------------------------------------------
300 auto upload_x(auto&& prop, renderable_type const& grid) {
301 retrieve_typed_prop(prop, [&](auto&& prop) {
302 using prop_type = std::decay_t<decltype(prop)>;
303 using value_type = typename prop_type::value_type;
304 if constexpr (static_vec<value_type>) {
305 upload_data(
306 prop, [](auto const& prop, auto const v) { return prop[v].x(); },
307 grid);
308 }
309 });
310 }
311 //----------------------------------------------------------------------------
312 auto upload_y(auto&& prop, renderable_type const& grid) {
313 retrieve_typed_prop(prop, [&](auto&& prop) {
314 using prop_type = std::decay_t<decltype(prop)>;
315 using value_type = typename prop_type::value_type;
316 if constexpr (static_vec<value_type>) {
317 upload_data(
318 prop, [](auto const& prop, auto const v) { return prop[v].y(); },
319 grid);
320 }
321 });
322 }
323 //----------------------------------------------------------------------------
324 auto upload_z(auto&& prop, renderable_type const& grid) {
325 retrieve_typed_prop(prop, [&](auto&& prop) {
326 using prop_type = std::decay_t<decltype(prop)>;
327 using value_type = typename prop_type::value_type;
328 if constexpr (static_vec<value_type>) {
329 if constexpr (value_type::num_components() > 2) {
330 upload_data(
331 prop, [](auto const& prop, auto const v) { return prop[v].z(); },
332 grid);
333 }
334 }
335 });
336 }
337 //----------------------------------------------------------------------------
338 auto upload_w(auto&& prop, renderable_type const& grid) {
339 retrieve_typed_prop(prop, [&](auto&& prop) {
340 using prop_type = std::decay_t<decltype(prop)>;
341 using value_type = typename prop_type::value_type;
342 if constexpr (static_vec<value_type>) {
343 if constexpr (value_type::num_components() > 3) {
344 upload_data(
345 prop, [](auto const& prop, auto const v) { return prop[v].w(); },
346 grid);
347 }
348 }
349 });
350 }
351 //----------------------------------------------------------------------------
353 if (ImGui::BeginCombo("##combo", selected_property_name != nullptr
354 ? selected_property_name->c_str()
355 : nullptr)) {
356 for (auto const& [name, prop] : ps.vertex_properties()) {
357 if (prop->type() == typeid(float) || prop->type() == typeid(double) ||
358 prop->type() == typeid(vec2f) || prop->type() == typeid(vec2d) ||
359 prop->type() == typeid(vec3f) || prop->type() == typeid(vec3d) ||
360 prop->type() == typeid(vec4f) || prop->type() == typeid(vec4d)) {
361 auto is_selected = selected_property == prop.get();
362 if (ImGui::Selectable(name.c_str(), is_selected)) {
363 selected_property = prop.get();
364 selected_property_name = &name;
365 if (prop_holds_scalar(prop)) {
366 upload_scalar(selected_property, ps);
367 vector_property = false;
368 } else if (prop_holds_vector(prop)) {
369 upload_magnitude(selected_property, ps);
370 vector_property = true;
371 }
372 }
373 if (is_selected) {
374 ImGui::SetItemDefaultFocus();
375 }
376 }
377 }
378 ImGui::EndCombo();
379 }
380 }
381 //==============================================================================
382 auto properties(renderable_type const& ps) {
383 ImGui::Text("Pointset");
384 ImGui::DragFloat("Point Size", &point_size, 1.0f, 1.0f, 2.0f, "%.01f");
385 ImGui::ColorEdit4("Color", color.data());
386 ImGui::Checkbox("Show Property", &show_property);
387 pointset_property_selection(ps);
388 if (selected_property != nullptr) {
389 auto& setting = settings[selected_settings_name()];
390 ImGui::DragFloat("Min", &setting.min_scalar, 0.01f, -FLT_MAX,
391 setting.max_scalar, "%.06f");
392 ImGui::DragFloat("Max", &setting.max_scalar, 0.01f, setting.min_scalar,
393 FLT_MAX, "%.06f");
394 }
395 }
396 //==============================================================================
397 auto render() {
398 shader::get().bind();
399 shader::get().set_color(color(0), color(1), color(2), color(3));
400 gl::point_size(point_size);
401 auto show = selected_property != nullptr && show_property;
402 shader::get().show_property(show);
403 if (show) {
404 auto& setting = settings[selected_settings_name()];
405 setting.c->tex.bind(0);
406 shader::get().set_min(setting.min_scalar);
407 shader::get().set_max(setting.max_scalar);
408 shader::get().invert_scale(setting.scale_inverted);
409 }
410 geometry.draw_points();
411 }
412
413 auto on_cursor_moved(double const x, double const y) { cursor_pos = {x, y}; }
416};
417static_assert(interactively_renderable<renderer<pointset2>>);
418//==============================================================================
419} // namespace tatooine::rendering::interactive
420//==============================================================================
421#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 set_uniform(const std::string &, GLfloat)
DLL_API void create()
DLL_API void set_uniform_mat4(const std::string &, GLfloat const *)
Definition: grid_edge.h:16
Definition: tensor_concepts.h:23
button
Definition: mouse.h:8
Definition: interactive.h:15
auto show(std::index_sequence< Is... >, Renderables &&... renderables)
Definition: interactive.h:60
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
auto constexpr map(F &&f, Ts &&... ts)
maps unary function f to all single parameters of parameter pack ts
Definition: map.h:10
constexpr auto max(A &&a, B &&b)
Definition: math.h:20
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: mat.h:14
Definition: pointset.h:69
auto vertices() const
Definition: pointset.h:226
auto vertex_properties() const -> auto const &
Definition: pointset.h:191
static auto viridis() -> auto &
Definition: color_scale.h:82
auto invert_scale(bool const invert) -> void
Definition: pointset.h:96
auto show_property(bool const show) -> void
Definition: pointset.h:100
auto set_projection_matrix(Mat4< GLfloat > const &P) -> void
Definition: pointset.h:88
auto set_max(GLfloat const max) -> void
Definition: pointset.h:108
auto set_min(GLfloat const min) -> void
Definition: pointset.h:104
auto set_color(GLfloat const r, GLfloat const g, GLfloat const b, GLfloat const a=1) -> void
Definition: pointset.h:83
auto set_view_matrix(Mat4< GLfloat > const &V) -> void
Definition: pointset.h:92
auto upload_data(auto &&prop, auto &&get_data, renderable_type const &ps)
Definition: pointset.h:262
auto upload_z(auto &&prop, renderable_type const &grid)
Definition: pointset.h:324
auto prop_holds_vector(auto const &prop)
Definition: pointset.h:186
gl::indexeddata< Vec2< GLfloat >, GLfloat > geometry
Definition: pointset.h:128
typename renderable_type::template typed_vertex_property_type< T > typed_vertex_property_type
Definition: pointset.h:22
auto on_cursor_moved(double const x, double const y)
Definition: pointset.h:413
auto upload_w(auto &&prop, renderable_type const &grid)
Definition: pointset.h:338
auto properties(renderable_type const &ps)
Definition: pointset.h:382
auto init_properties(renderable_type const &ps)
Definition: pointset.h:195
std::unordered_map< std::string, std::string_view > selected_component
Definition: pointset.h:134
auto retrieve_typed_prop(auto &&prop, auto &&f)
Definition: pointset.h:161
auto upload_scalar(auto &&prop, renderable_type const &grid)
Definition: pointset.h:270
auto pointset_property_selection(renderable_type const &ps)
Definition: pointset.h:352
auto upload_magnitude(auto &&prop, renderable_type const &grid)
Definition: pointset.h:281
std::unordered_map< std::string, property_settings > settings
Definition: pointset.h:133
auto upload_x(auto &&prop, renderable_type const &grid)
Definition: pointset.h:300
static auto set_view_matrix(Mat4< GLfloat > const &V)
Definition: pointset.h:115
auto upload_y(auto &&prop, renderable_type const &grid)
Definition: pointset.h:312
static auto set_projection_matrix(Mat4< GLfloat > const &P)
Definition: pointset.h:112
renderer(renderable_type const &ps)
Definition: pointset.h:138
auto prop_holds_scalar(auto const &prop)
Definition: pointset.h:181
static auto cast_prop(auto &&prop)
Definition: pointset.h:157
Definition: pointset.h:10
Definition: vec.h:12
Definition: property.h:16