BlosSOM
Interactive dimensionality reduction on large datasets (EmbedSOM and FLOWER combined)
view.h
Go to the documentation of this file.
1/* This file is part of BlosSOM.
2 *
3 * Copyright (C) 2021 Mirek Kratochvil
4 * Sona Molnarova
5 *
6 * BlosSOM is free software: you can redistribute it and/or modify it under
7 * the terms of the GNU General Public License as published by the Free
8 * Software Foundation, either version 3 of the License, or (at your option)
9 * any later version.
10 *
11 * BlosSOM is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14 * details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * BlosSOM. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20#ifndef VIEW_H
21#define VIEW_H
22
23#include <glm/glm.hpp>
24#include <glm/gtc/matrix_transform.hpp>
25
26#include <cmath>
27#include <iostream>
28#include <vector>
29
30#include "input_data.h"
31
32/**
33 * @brief A small utility class that manages the viewport coordinates, together
34 * with the virtual "camera" position and zoom.
35 */
36class View
37{
38public:
39 // Default View values
40 const float movement_speed = 0.2f;
41 const float smooth_speed = 0.005f;
42 const float zoom_depth = 0.009f;
43
44 // View vectors
45 glm::vec3 target_pos;
46 glm::vec3 current_pos;
47 glm::vec3 front;
48 glm::vec3 up;
49 glm::vec3 right;
50 glm::vec3 world_up;
51
54
55 // Framebuffer size
56 int width;
57 int height;
58
59 View(int width = 800,
60 int height = 600,
61 glm::vec3 position = glm::vec3(0.0f, 0.0f, 1.0f),
62 glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f))
63 : front(glm::vec3(0.0f, 0.0f, -1.0f))
66 {
67 target_pos = position;
68 current_pos = position;
69 world_up = up;
71 }
72
73 /**
74 * @brief Move the current position and zoom a bit closer to the target
75 * position and zoom.
76 *
77 * @param dt Time difference.
78 * @param input Values collected by event callbacks.
79 */
80 void update(float dt, int w, int h)
81 {
82 width = w;
83 height = h;
84
85 float power = pow(smooth_speed, dt);
86 float r = 1 - power;
87 current_pos = power * current_pos + r * target_pos;
89
91 }
92
93 /**
94 * @brief Compute view matrix for drawing into the "view" space.
95 *
96 * @return glm::mat4 View matrix
97 */
98 glm::mat4 get_view_matrix() const
99 {
100 return glm::lookAt(current_pos, current_pos + front, up);
101 }
102
103 /**
104 * @brief Compute projection matrix for orthographic projection.
105 *
106 * @return glm::mat4 Projection matrix
107 */
108 glm::mat4 get_proj_matrix() const
109 {
110 float half_w = width / 2.0f;
111 float half_h = height / 2.0f;
112 return glm::ortho(-half_w * current_zoom,
113 half_w * current_zoom,
114 -half_h * current_zoom,
115 half_h * current_zoom,
116 0.1f,
117 100.0f);
118 }
119
120 /**
121 * @brief Convert mouse coordinates ([0,0] in the upper left corner),
122 * to screen coordinates ([0,0] in the middle of the screen).
123 *
124 * @param mouse Mouse coordinates ([0,0] in the upper left corner)
125 * @return glm::vec2 Screen coordinates ([0,0] in the middle of the screen)
126 */
127 glm::vec2 screen_mouse_coords(glm::vec2 mouse) const
128 {
129 return glm::vec2(mouse.x - width / 2.0f, height / 2.0f - mouse.y);
130 }
131
132 /**
133 * @brief Convert mouse coordinates ([0,0] in the upper left corner),
134 * to model coordinates ([0,0] in the middle of the screen).
135 *
136 * @param mouse Mouse coordinates ([0,0] in the upper left corner)
137 * @return glm::vec2 Model coordinates ([0,0] in the middle of the screen)
138 */
139 glm::vec2 model_mouse_coords(glm::vec2 mouse) const
140 {
141 glm::vec3 res =
142 glm::unProject(glm::vec3(mouse.x, height - mouse.y, 0.1f),
145 glm::vec4(0.0f, 0.0f, width, height));
146
147 return glm::vec2(res.x, res.y);
148 }
149
150 /**
151 * @brief Converts point to screen coordinates([0,0] in the middle of the
152 * screen).
153 *
154 * @param point Input point in original not projected coordinates.
155 * @return glm::vec2 Point in screen coordinates.
156 */
157 glm::vec2 screen_coords(glm::vec2 point) const
158 {
159 glm::vec3 res = glm::project(glm::vec3(point, 0.1f),
162 glm::vec4(0.0f, 0.0f, width, height));
163 return screen_point_coords(glm::vec2(res.x, res.y));
164 }
165
166 /**
167 * @brief Move view along Y-axis.
168 *
169 * @param dir Direction of the movement. (-1 - down, 1 - up)
170 */
171 void move_y(int dir)
172 {
173 float half_h = height / 2.0f;
174 float velocity = half_h * target_zoom * movement_speed;
175 target_pos.y += (dir * velocity);
176 }
177
178 /**
179 * @brief Move view along X-axis.
180 *
181 * @param dir Direction of the movement. (-1 - left, 1 - right)
182 */
183 void move_x(int dir)
184 {
185 float half_h = height / 2.0f;
186 float velocity = half_h * target_zoom * movement_speed;
187 target_pos.x += (dir * velocity);
188 }
189
190 /**
191 * @brief Adjust zoom accordingly.
192 *
193 * @param yoffset Direction of the scroll (-1, 0, 1).
194 * @param mouse Mouse coordinates ([0,0] in the upper left corner).
195 */
196 void zoom(float yoffset, glm::vec2 mouse)
197 {
198 if (yoffset > -0.0001 && yoffset < 0.0001)
199 return;
200
201 float velocity = -1 * yoffset / 1500.0f * (target_zoom * 100);
202 auto zoom_around = model_mouse_coords(mouse);
203
204 target_zoom += velocity;
205 target_pos =
206 glm::vec3(zoom_around + powf(2.0f, target_zoom * 400) *
207 (glm::vec2(current_pos) - zoom_around) /
208 powf(2.0f, current_zoom * 400),
209 target_pos.z);
210 }
211
212 /**
213 * @brief Cause the camera to look at the specified point.
214 *
215 * @param tgt This point will eventually get to the middle of the screen.
216 * It needs to be converted from mouse to model coordinates.
217 */
218 void look_at(glm::vec2 tgt)
219 {
220 tgt = model_mouse_coords(tgt);
221 target_pos.x = tgt.x;
222 target_pos.y = tgt.y;
223 }
224
225private:
226 /**
227 * @brief Re-calculates the right and up vector from the View's updated
228 * vectors.
229 *
230 */
232 {
233 right = glm::normalize(glm::cross(
234 front, world_up)); // normalize the vectors, because their length gets
235 // closer to 0 the more you look up or down which
236 // results in slower movement.
237 up = glm::normalize(glm::cross(right, front));
238 }
239
240 /**
241 * @brief Convert point coordinates ([0,0] in the upper left corner),
242 * to screen coordinates ([0,0] in the middle of the screen).
243 *
244 * @param point Point coordinates ([0,0] in the upper left corner)
245 * @return glm::vec2 Screen coordinates ([0,0] in the middle of the screen)
246 */
247 glm::vec2 screen_point_coords(glm::vec2 point) const
248 {
249 return glm::vec2(point.x - width / 2.0f, point.y - height / 2.0f);
250 }
251};
252
253#endif
A small utility class that manages the viewport coordinates, together with the virtual "camera" posit...
Definition: view.h:37
glm::vec3 front
Definition: view.h:47
glm::vec3 up
Definition: view.h:48
glm::vec2 screen_mouse_coords(glm::vec2 mouse) const
Convert mouse coordinates ([0,0] in the upper left corner), to screen coordinates ([0,...
Definition: view.h:127
glm::vec3 current_pos
Definition: view.h:46
glm::vec3 right
Definition: view.h:49
void move_y(int dir)
Move view along Y-axis.
Definition: view.h:171
void look_at(glm::vec2 tgt)
Cause the camera to look at the specified point.
Definition: view.h:218
const float movement_speed
Definition: view.h:40
int height
Definition: view.h:57
const float smooth_speed
Definition: view.h:41
glm::vec2 screen_point_coords(glm::vec2 point) const
Convert point coordinates ([0,0] in the upper left corner), to screen coordinates ([0,...
Definition: view.h:247
void zoom(float yoffset, glm::vec2 mouse)
Adjust zoom accordingly.
Definition: view.h:196
void update(float dt, int w, int h)
Move the current position and zoom a bit closer to the target position and zoom.
Definition: view.h:80
glm::mat4 get_proj_matrix() const
Compute projection matrix for orthographic projection.
Definition: view.h:108
glm::vec3 world_up
Definition: view.h:50
float target_zoom
Definition: view.h:52
void move_x(int dir)
Move view along X-axis.
Definition: view.h:183
float current_zoom
Definition: view.h:53
int width
Definition: view.h:56
glm::mat4 get_view_matrix() const
Compute view matrix for drawing into the "view" space.
Definition: view.h:98
glm::vec2 screen_coords(glm::vec2 point) const
Converts point to screen coordinates([0,0] in the middle of the screen).
Definition: view.h:157
glm::vec2 model_mouse_coords(glm::vec2 mouse) const
Convert mouse coordinates ([0,0] in the upper left corner), to model coordinates ([0,...
Definition: view.h:139
void update_view_vectors()
Re-calculates the right and up vector from the View's updated vectors.
Definition: view.h:231
glm::vec3 target_pos
Definition: view.h:45
const float zoom_depth
Definition: view.h:42
View(int width=800, int height=600, glm::vec3 position=glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3 up=glm::vec3(0.0f, 1.0f, 0.0f))
Definition: view.h:59