proj_plot

view 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 source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdarg.h>
4 #include <assert.h>
5 #include <GL/glut.h>
6 #include <vmath/vmath.h>
7 #include <drawtext.h>
9 bool init();
10 void display();
11 void draw_grid();
12 void draw_label(const Vector2 &pos, const char *fmt, ...);
13 void reshape(int x, int y);
14 void keyb(unsigned char key, int x, int y);
15 void keyb_up(unsigned char key, int x, int y);
16 void mouse(int bn, int st, int x, int y);
17 void motion(int x, int y);
18 Vector2 screen_to_world(int x, int y);
20 int win_xsz, win_ysz;
21 float aspect;
23 Matrix4x4 proj;
24 Vector2 cur_point;
25 bool cur_point_valid;
27 bool keystate[256];
28 dtx_font *font;
29 float pan[2], zoom = 1.0;
31 int main(int argc, char **argv)
32 {
33 glutInit(&argc, argv);
34 glutInitWindowSize(1024, 768);
35 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_MULTISAMPLE);
36 glutCreateWindow("Interactive projection diagram");
38 glutDisplayFunc(display);
39 glutReshapeFunc(reshape);
40 glutKeyboardFunc(keyb);
41 glutKeyboardUpFunc(keyb_up);
42 glutMouseFunc(mouse);
43 glutMotionFunc(motion);
45 if(!init()) {
46 return 1;
47 }
49 glutMainLoop();
50 return 0;
51 }
53 bool init()
54 {
55 if(!(font = dtx_open_font("data/font.ttf", 16))) {
56 fprintf(stderr, "failed to open font\n");
57 return false;
58 }
60 glEnable(GL_MULTISAMPLE);
61 proj.set_perspective(DEG_TO_RAD(60), 1, 0.5, 500.0);
62 return true;
63 }
65 void display()
66 {
67 glClear(GL_COLOR_BUFFER_BIT);
69 glMatrixMode(GL_MODELVIEW);
70 glLoadIdentity();
71 glTranslatef(-pan[0], -pan[1], 0);
72 glScalef(zoom, zoom, zoom);
74 draw_grid();
76 if(cur_point_valid) {
77 glPointSize(7.0);
78 glBegin(GL_POINTS);
79 glColor3f(0.2, 1, 0.2);
80 glVertex2f(cur_point.x, cur_point.y);
81 glEnd();
83 glColor3f(0.15, 0.5, 0.15);
84 draw_label(cur_point, "(%.2f, %.2f)", cur_point.x, cur_point.y);
85 }
87 glutSwapBuffers();
88 assert(glGetError() == GL_NO_ERROR);
89 }
91 #define LINE(x0, y0, x1, y1) (glVertex2f(x0, y0), glVertex2f(x1, y1))
93 void draw_grid()
94 {
95 float ymin = -1;
96 float ymax = 1;
97 float xmin = -1;
98 float xmax = 1;
99 float ticksz = 0.015;
101 glBegin(GL_LINES);
102 glColor3f(1, 1, 1);
103 LINE(0, -1, 0, 1);
104 LINE(-1, 0, 1, 0);
106 for(int i=1; i<11; i++) {
107 for(int j=0; j<2; j++) {
108 float x = (float)i / 10.0 * (j ? -1.0 : 1.0);
110 glColor3f(0.15, 0.15, 0.15);
111 LINE(x, ymin, x, ymax);
112 LINE(xmin, x, xmax, x);
114 glColor3f(0.4, 0.4, 0.4);
115 LINE(x, -ticksz, x, ticksz);
116 LINE(-ticksz, x, ticksz, x);
117 }
118 }
119 glEnd();
120 }
122 void draw_label(const Vector2 &pos, const char *fmt, ...)
123 {
124 static char buf[512];
125 va_list ap;
127 va_start(ap, fmt);
128 vsnprintf(buf, sizeof buf - 1, fmt, ap);
129 va_end(ap);
131 glPushMatrix();
132 glTranslatef(pos.x + 0.01, pos.y + 0.01, 0);
133 float s = 2.0 / (win_ysz * zoom);
134 glScalef(s, s, s);
136 dtx_string(buf);
138 glPopMatrix();
139 }
141 void reshape(int x, int y)
142 {
143 win_xsz = x;
144 win_ysz = y;
145 aspect = (float)x / (float)y;
147 glViewport(0, 0, x, y);
149 glMatrixMode(GL_PROJECTION);
150 glLoadIdentity();
151 glScalef(1.0 / aspect, 1.0, 1.0);
152 }
154 void keyb(unsigned char key, int x, int y)
155 {
156 keystate[key] = 1;
158 switch(key) {
159 case 27:
160 exit(0);
161 }
162 }
164 void keyb_up(unsigned char key, int x, int y)
165 {
166 keystate[key] = 0;
167 }
169 bool bnstate[16];
170 int prev_x, prev_y;
172 void mouse(int bn, int st, int x, int y)
173 {
174 bnstate[bn - GLUT_LEFT_BUTTON] = st == GLUT_DOWN;
175 prev_x = x;
176 prev_y = y;
178 if(bn == GLUT_LEFT_BUTTON && st == GLUT_DOWN) {
179 cur_point = screen_to_world(x, y);
180 cur_point_valid = true;
181 glutPostRedisplay();
182 }
183 }
185 void motion(int x, int y)
186 {
187 float dx = 2.0 * aspect * (x - prev_x) / (float)win_xsz;
188 float dy = 2.0 * (y - prev_y) / (float)win_ysz;
189 prev_x = x;
190 prev_y = y;
192 if(bnstate[0]) {
193 cur_point = screen_to_world(x, y);
194 glutPostRedisplay();
195 }
196 if(bnstate[1]) {
197 pan[0] -= dx;
198 pan[1] += dy;
200 glutPostRedisplay();
201 }
202 if(bnstate[2]) {
203 zoom += dy;
205 if(zoom < 1e-4) zoom = 1e-4;
206 glutPostRedisplay();
207 }
208 }
210 Vector2 screen_to_world(int px, int py)
211 {
212 float sx = 2.0 * aspect * (1.0 / zoom) / (float)win_xsz;
213 float sy = 2.0 * (1.0 / zoom) / (float)win_ysz;
215 float x = (float)px * sx - (aspect + pan[0]) / zoom;
216 float y = (float)(win_ysz - py) * sy - (1.0 + pan[1]) / zoom;
218 return Vector2(x, y);
219 }