citrun

watch C/C++ source code execute
Log | Files | Refs | LICENSE

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 }