proj_plot
diff main.cc @ 0:e467998dcc64
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 24 Jan 2015 16:36:34 +0200 |
parents | |
children | 64483c640a38 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/main.cc Sat Jan 24 16:36:34 2015 +0200 1.3 @@ -0,0 +1,219 @@ 1.4 +#include <stdio.h> 1.5 +#include <stdlib.h> 1.6 +#include <stdarg.h> 1.7 +#include <assert.h> 1.8 +#include <GL/glut.h> 1.9 +#include <vmath/vmath.h> 1.10 +#include <drawtext.h> 1.11 + 1.12 +bool init(); 1.13 +void display(); 1.14 +void draw_grid(); 1.15 +void draw_label(const Vector2 &pos, const char *fmt, ...); 1.16 +void reshape(int x, int y); 1.17 +void keyb(unsigned char key, int x, int y); 1.18 +void keyb_up(unsigned char key, int x, int y); 1.19 +void mouse(int bn, int st, int x, int y); 1.20 +void motion(int x, int y); 1.21 +Vector2 screen_to_world(int x, int y); 1.22 + 1.23 +int win_xsz, win_ysz; 1.24 +float aspect; 1.25 + 1.26 +Matrix4x4 proj; 1.27 +Vector2 cur_point; 1.28 +bool cur_point_valid; 1.29 + 1.30 +bool keystate[256]; 1.31 +dtx_font *font; 1.32 +float pan[2], zoom = 1.0; 1.33 + 1.34 +int main(int argc, char **argv) 1.35 +{ 1.36 + glutInit(&argc, argv); 1.37 + glutInitWindowSize(1024, 768); 1.38 + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_MULTISAMPLE); 1.39 + glutCreateWindow("Interactive projection diagram"); 1.40 + 1.41 + glutDisplayFunc(display); 1.42 + glutReshapeFunc(reshape); 1.43 + glutKeyboardFunc(keyb); 1.44 + glutKeyboardUpFunc(keyb_up); 1.45 + glutMouseFunc(mouse); 1.46 + glutMotionFunc(motion); 1.47 + 1.48 + if(!init()) { 1.49 + return 1; 1.50 + } 1.51 + 1.52 + glutMainLoop(); 1.53 + return 0; 1.54 +} 1.55 + 1.56 +bool init() 1.57 +{ 1.58 + if(!(font = dtx_open_font("data/font.ttf", 16))) { 1.59 + fprintf(stderr, "failed to open font\n"); 1.60 + return false; 1.61 + } 1.62 + 1.63 + glEnable(GL_MULTISAMPLE); 1.64 + proj.set_perspective(DEG_TO_RAD(60), 1, 0.5, 500.0); 1.65 + return true; 1.66 +} 1.67 + 1.68 +void display() 1.69 +{ 1.70 + glClear(GL_COLOR_BUFFER_BIT); 1.71 + 1.72 + glMatrixMode(GL_MODELVIEW); 1.73 + glLoadIdentity(); 1.74 + glTranslatef(-pan[0], -pan[1], 0); 1.75 + glScalef(zoom, zoom, zoom); 1.76 + 1.77 + draw_grid(); 1.78 + 1.79 + if(cur_point_valid) { 1.80 + glPointSize(7.0); 1.81 + glBegin(GL_POINTS); 1.82 + glColor3f(0.2, 1, 0.2); 1.83 + glVertex2f(cur_point.x, cur_point.y); 1.84 + glEnd(); 1.85 + 1.86 + glColor3f(0.15, 0.5, 0.15); 1.87 + draw_label(cur_point, "(%.2f, %.2f)", cur_point.x, cur_point.y); 1.88 + } 1.89 + 1.90 + glutSwapBuffers(); 1.91 + assert(glGetError() == GL_NO_ERROR); 1.92 +} 1.93 + 1.94 +#define LINE(x0, y0, x1, y1) (glVertex2f(x0, y0), glVertex2f(x1, y1)) 1.95 + 1.96 +void draw_grid() 1.97 +{ 1.98 + float ymin = -1; 1.99 + float ymax = 1; 1.100 + float xmin = -1; 1.101 + float xmax = 1; 1.102 + float ticksz = 0.015; 1.103 + 1.104 + glBegin(GL_LINES); 1.105 + glColor3f(1, 1, 1); 1.106 + LINE(0, -1, 0, 1); 1.107 + LINE(-1, 0, 1, 0); 1.108 + 1.109 + for(int i=1; i<11; i++) { 1.110 + for(int j=0; j<2; j++) { 1.111 + float x = (float)i / 10.0 * (j ? -1.0 : 1.0); 1.112 + 1.113 + glColor3f(0.15, 0.15, 0.15); 1.114 + LINE(x, ymin, x, ymax); 1.115 + LINE(xmin, x, xmax, x); 1.116 + 1.117 + glColor3f(0.4, 0.4, 0.4); 1.118 + LINE(x, -ticksz, x, ticksz); 1.119 + LINE(-ticksz, x, ticksz, x); 1.120 + } 1.121 + } 1.122 + glEnd(); 1.123 +} 1.124 + 1.125 +void draw_label(const Vector2 &pos, const char *fmt, ...) 1.126 +{ 1.127 + static char buf[512]; 1.128 + va_list ap; 1.129 + 1.130 + va_start(ap, fmt); 1.131 + vsnprintf(buf, sizeof buf - 1, fmt, ap); 1.132 + va_end(ap); 1.133 + 1.134 + glPushMatrix(); 1.135 + glTranslatef(pos.x + 0.01, pos.y + 0.01, 0); 1.136 + float s = 2.0 / (win_ysz * zoom); 1.137 + glScalef(s, s, s); 1.138 + 1.139 + dtx_string(buf); 1.140 + 1.141 + glPopMatrix(); 1.142 +} 1.143 + 1.144 +void reshape(int x, int y) 1.145 +{ 1.146 + win_xsz = x; 1.147 + win_ysz = y; 1.148 + aspect = (float)x / (float)y; 1.149 + 1.150 + glViewport(0, 0, x, y); 1.151 + 1.152 + glMatrixMode(GL_PROJECTION); 1.153 + glLoadIdentity(); 1.154 + glScalef(1.0 / aspect, 1.0, 1.0); 1.155 +} 1.156 + 1.157 +void keyb(unsigned char key, int x, int y) 1.158 +{ 1.159 + keystate[key] = 1; 1.160 + 1.161 + switch(key) { 1.162 + case 27: 1.163 + exit(0); 1.164 + } 1.165 +} 1.166 + 1.167 +void keyb_up(unsigned char key, int x, int y) 1.168 +{ 1.169 + keystate[key] = 0; 1.170 +} 1.171 + 1.172 +bool bnstate[16]; 1.173 +int prev_x, prev_y; 1.174 + 1.175 +void mouse(int bn, int st, int x, int y) 1.176 +{ 1.177 + bnstate[bn - GLUT_LEFT_BUTTON] = st == GLUT_DOWN; 1.178 + prev_x = x; 1.179 + prev_y = y; 1.180 + 1.181 + if(bn == GLUT_LEFT_BUTTON && st == GLUT_DOWN) { 1.182 + cur_point = screen_to_world(x, y); 1.183 + cur_point_valid = true; 1.184 + glutPostRedisplay(); 1.185 + } 1.186 +} 1.187 + 1.188 +void motion(int x, int y) 1.189 +{ 1.190 + float dx = 2.0 * aspect * (x - prev_x) / (float)win_xsz; 1.191 + float dy = 2.0 * (y - prev_y) / (float)win_ysz; 1.192 + prev_x = x; 1.193 + prev_y = y; 1.194 + 1.195 + if(bnstate[0]) { 1.196 + cur_point = screen_to_world(x, y); 1.197 + glutPostRedisplay(); 1.198 + } 1.199 + if(bnstate[1]) { 1.200 + pan[0] -= dx; 1.201 + pan[1] += dy; 1.202 + 1.203 + glutPostRedisplay(); 1.204 + } 1.205 + if(bnstate[2]) { 1.206 + zoom += dy; 1.207 + 1.208 + if(zoom < 1e-4) zoom = 1e-4; 1.209 + glutPostRedisplay(); 1.210 + } 1.211 +} 1.212 + 1.213 +Vector2 screen_to_world(int px, int py) 1.214 +{ 1.215 + float sx = 2.0 * aspect * (1.0 / zoom) / (float)win_xsz; 1.216 + float sy = 2.0 * (1.0 / zoom) / (float)win_ysz; 1.217 + 1.218 + float x = (float)px * sx - (aspect + pan[0]) / zoom; 1.219 + float y = (float)(win_ysz - py) * sy - (1.0 + pan[1]) / zoom; 1.220 + 1.221 + return Vector2(x, y); 1.222 +}