gl_view.cc (7764B)
1 /* 2 * Copyright 2012 Google, Inc. All Rights Reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * Google Author(s): Behdad Esfahbod, Maysum Panju, Wojciech Baranowski 17 */ 18 #include <assert.h> 19 20 #include "gl_view.h" 21 22 extern "C" { 23 #include "matrix4x4.h" 24 } 25 26 27 View::View(citrun::gl_state &st) : 28 refcount(1), 29 st(st), 30 fullscreen(false) 31 { 32 TRACE(); 33 34 reset(); 35 } 36 37 View::~View() 38 { 39 assert (refcount == 1); 40 } 41 42 43 #define ANIMATION_SPEED 1. /* Default speed, in radians second. */ 44 void 45 View::reset() 46 { 47 perspective = 4; 48 scale_ = 1; 49 translate_.x = translate_.y = 0; 50 // trackball (quat , 0.0, 0.0, 0.0, 0.0); 51 // vset (rot_axis, 0., 0., 1.); 52 rot_speed = ANIMATION_SPEED / 1000.; 53 } 54 55 void 56 View::scale_gamma_adjust(double factor) 57 { 58 st.scale_gamma_adjust(factor); 59 } 60 61 void 62 View::scale_contrast(double factor) 63 { 64 st.scale_contrast(factor); 65 } 66 67 void 68 View::scale_perspective(double factor) 69 { 70 perspective = clamp(perspective * factor, .01, 100.); 71 } 72 73 void 74 View::toggle_outline() 75 { 76 st.toggle_outline(); 77 } 78 79 void 80 View::scale_outline_thickness(double factor) 81 { 82 st.scale_outline_thickness(factor); 83 } 84 85 void 86 View::adjust_boldness(double factor) 87 { 88 st.adjust_boldness(factor); 89 } 90 91 void 92 View::scale(double factor) 93 { 94 scale_ *= factor; 95 } 96 97 void 98 View::translate(double dx, double dy) 99 { 100 translate_.x += dx / scale_; 101 translate_.y += dy / scale_; 102 } 103 104 void 105 View::apply_transform(float *mat) 106 { 107 int viewport[4]; 108 glGetIntegerv (GL_VIEWPORT, viewport); 109 GLint width = viewport[2]; 110 GLint height = viewport[3]; 111 112 // View transform 113 m4Scale (mat, scale_, scale_, 1); 114 m4Translate (mat, translate_.x, translate_.y, 0); 115 116 // Perspective 117 { 118 double d = std::max (width, height); 119 double near = d / perspective; 120 double far = near + d; 121 double factor = near / (2 * near + d); 122 m4Frustum (mat, -width * factor, width * factor, -height * factor, height * factor, near, far); 123 m4Translate (mat, 0, 0, -(near + d * .5)); 124 } 125 126 // Rotate 127 //float m[4][4]; 128 //build_rotmatrix (m, quat); 129 //m4MultMatrix(mat, &m[0][0]); 130 131 // Fix 'up' 132 m4Scale (mat, 1, -1, 1); 133 } 134 135 136 /* return current time in milli-seconds */ 137 static long 138 current_time (void) 139 { 140 return glfwGetTime(); 141 } 142 143 void 144 View::toggle_fullscreen() 145 { 146 #if 0 147 fullscreen = !fullscreen; 148 if (fullscreen) { 149 x = glutGet(GLUT_WINDOW_X); 150 y = glutGet(GLUT_WINDOW_Y); 151 width = glutGet(GLUT_WINDOW_WIDTH); 152 height = glutGet(GLUT_WINDOW_HEIGHT); 153 glutFullScreen(); 154 } else { 155 glutReshapeWindow(width, height); 156 glutPositionWindow(x, y); 157 } 158 #endif 159 } 160 161 void 162 View::toggle_debug() 163 { 164 st.toggle_debug(); 165 } 166 167 168 void 169 View::reshape_func(int width, int height) 170 { 171 glViewport (0, 0, width, height); 172 // glutPostRedisplay (); 173 } 174 175 #define STEP 1.05 176 void 177 View::keyboard_func(GLFWwindow *window, int key, int scancode, int action, int mods) 178 { 179 switch (key) 180 { 181 case '\033': 182 case GLFW_KEY_Q: 183 glfwSetWindowShouldClose(window, 1); 184 break; 185 186 case 'f': 187 toggle_fullscreen(); 188 break; 189 190 case 'd': 191 toggle_debug(); 192 break; 193 194 case 'o': 195 toggle_outline(); 196 break; 197 case 'p': 198 scale_outline_thickness(STEP); 199 break; 200 case 'i': 201 scale_outline_thickness(1. / STEP); 202 break; 203 204 case '0': 205 adjust_boldness(+.01); 206 break; 207 case '9': 208 adjust_boldness(-.01); 209 break; 210 211 212 case 'a': 213 scale_contrast(STEP); 214 break; 215 case 'z': 216 scale_contrast(1. / STEP); 217 break; 218 case 'g': 219 scale_gamma_adjust(STEP); 220 break; 221 case 'b': 222 scale_gamma_adjust(1. / STEP); 223 break; 224 225 case GLFW_KEY_EQUAL: 226 scale(STEP); 227 break; 228 case '-': 229 scale(1. / STEP); 230 break; 231 232 case GLFW_KEY_K: 233 translate(0, -.1); 234 break; 235 case GLFW_KEY_J: 236 translate(0, +.1); 237 break; 238 case GLFW_KEY_H: 239 translate(+.1, 0); 240 break; 241 case GLFW_KEY_L: 242 translate(-.1, 0); 243 break; 244 245 case 'r': 246 reset(); 247 break; 248 249 default: 250 return; 251 } 252 } 253 254 void 255 View::special_func(int key, int x, int y) 256 { 257 #if 0 258 switch (key) 259 { 260 case GLUT_KEY_UP: 261 translate(0, -.1); 262 break; 263 case GLUT_KEY_DOWN: 264 translate(0, +.1); 265 break; 266 case GLUT_KEY_LEFT: 267 translate(+.1, 0); 268 break; 269 case GLUT_KEY_RIGHT: 270 translate(-.1, 0); 271 break; 272 273 default: 274 return; 275 } 276 #endif 277 // glutPostRedisplay (); 278 } 279 280 void 281 View::mouse_func(int button, int state, int x, int y) 282 { 283 #if 0 284 if (state == GLUT_DOWN) { 285 buttons |= (1 << button); 286 click_handled = false; 287 } else 288 buttons &= !(1 << button); 289 // modifiers = glutGetModifiers (); 290 291 switch (button) { 292 case GLUT_RIGHT_BUTTON: 293 switch (state) { 294 case GLUT_DOWN: 295 if (animate) { 296 toggle_animation(); 297 click_handled = true; 298 } 299 break; 300 case GLUT_UP: 301 if (!animate) 302 { 303 if (!dragged && !click_handled) 304 toggle_animation(); 305 else if (dt) { 306 double speed = hypot (dx, dy) / dt; 307 if (speed > 0.1) 308 toggle_animation(); 309 } 310 dx = dy = dt = 0; 311 } 312 break; 313 } 314 break; 315 316 #if !defined(GLUT_WHEEL_UP) 317 #define GLUT_WHEEL_UP 3 318 #define GLUT_WHEEL_DOWN 4 319 #endif 320 case GLUT_WHEEL_UP: 321 scale(STEP); 322 break; 323 324 case GLUT_WHEEL_DOWN: 325 scale(1. / STEP); 326 break; 327 } 328 #endif 329 330 beginx = lastx = x; 331 beginy = lasty = y; 332 dragged = false; 333 334 // glutPostRedisplay (); 335 } 336 337 void 338 View::motion_func(int x, int y) 339 { 340 dragged = true; 341 342 int viewport[4]; 343 glGetIntegerv (GL_VIEWPORT, viewport); 344 #if 0 345 GLuint width = viewport[2]; 346 GLuint height = viewport[3]; 347 348 if (buttons & (1 << GLUT_LEFT_BUTTON)) 349 { 350 if (modifiers & GLUT_ACTIVE_SHIFT) { 351 /* adjust contrast/gamma */ 352 scale_gamma_adjust(1 - ((y - lasty) / height)); 353 scale_contrast(1 + ((x - lastx) / width)); 354 } else { 355 /* translate */ 356 translate( 357 +2 * (x - lastx) / width, 358 -2 * (y - lasty) / height); 359 } 360 } 361 362 if (buttons & (1 << GLUT_RIGHT_BUTTON)) 363 { 364 if (modifiers & GLUT_ACTIVE_SHIFT) { 365 /* adjust perspective */ 366 scale_perspective(1 - ((y - lasty) / height) * 5); 367 } else { 368 /* rotate */ 369 float dquat[4]; 370 trackball (dquat, 371 (2.0*lastx - width) / width, 372 ( height - 2.0*lasty) / height, 373 ( 2.0*x - width) / width, 374 ( height - 2.0*y) / height ); 375 376 dx = x - lastx; 377 dy = y - lasty; 378 dt = current_time () - lastt; 379 380 add_quats (dquat, quat, quat); 381 382 if (dt) { 383 vcopy (dquat, rot_axis); 384 vnormal (rot_axis); 385 rot_speed = 2 * acos (dquat[3]) / dt; 386 } 387 } 388 } 389 390 if (buttons & (1 << GLUT_MIDDLE_BUTTON)) 391 { 392 /* scale */ 393 double factor = 1 - ((y - lasty) / height) * 5; 394 scale(factor); 395 /* adjust translate so we scale centered at the drag-begin mouse position */ 396 translate( 397 +(2. * beginx / width - 1) * (1 - factor), 398 -(2. * beginy / height - 1) * (1 - factor)); 399 } 400 #endif 401 402 lastx = x; 403 lasty = y; 404 lastt = current_time (); 405 406 // glutPostRedisplay (); 407 } 408 409 void 410 View::display(glyphy_extents_t const &extents) 411 { 412 int viewport[4]; 413 glGetIntegerv (GL_VIEWPORT, viewport); 414 GLint width = viewport[2]; 415 GLint height = viewport[3]; 416 417 418 float mat[16]; 419 420 m4LoadIdentity (mat); 421 422 apply_transform(mat); 423 424 // Buffer best-fit 425 double content_scale = .9 * std::min (width / (extents.max_x - extents.min_x), 426 height / (extents.max_y - extents.min_y)); 427 m4Scale (mat, content_scale, content_scale, 1); 428 // Center buffer 429 m4Translate (mat, 430 -(extents.max_x + extents.min_x) / 2., 431 -(extents.max_y + extents.min_y) / 2., 0); 432 433 st.set_matrix(mat); 434 435 glClearColor (1, 1, 1, 1); 436 glClear (GL_COLOR_BUFFER_BIT); 437 } 438 439 void 440 View::setup() 441 { 442 st.setup(); 443 }