proj_plot

view main.cc @ 1:64483c640a38

foo
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 24 Jan 2015 17:49:35 +0200
parents e467998dcc64
children e6ed6acee42f
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_frustum();
13 void draw_label(const Vector2 &pos, const char *fmt, ...);
14 void reshape(int x, int y);
15 void keyb(unsigned char key, int x, int y);
16 void keyb_up(unsigned char key, int x, int y);
17 void mouse(int bn, int st, int x, int y);
18 void motion(int x, int y);
19 Vector2 screen_to_world(int x, int y);
20 Vector2 project(const Vector2 &v);
21 Vector2 unproject(const Vector2 &v);
23 int win_xsz, win_ysz;
24 float aspect;
26 Matrix4x4 proj;
27 Vector2 cur_point;
28 bool cur_point_valid;
30 float proj_near = 0.5, proj_far = 50.0;
31 float proj_vfov = 50.0;
33 bool keystate[256];
34 dtx_font *font;
35 float pan[2] = {0, 0.85}, zoom = 0.4;
37 int main(int argc, char **argv)
38 {
39 glutInit(&argc, argv);
40 glutInitWindowSize(1024, 768);
41 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_MULTISAMPLE);
42 glutCreateWindow("Interactive projection diagram");
44 glutDisplayFunc(display);
45 glutReshapeFunc(reshape);
46 glutKeyboardFunc(keyb);
47 glutKeyboardUpFunc(keyb_up);
48 glutMouseFunc(mouse);
49 glutMotionFunc(motion);
51 if(!init()) {
52 return 1;
53 }
55 glutMainLoop();
56 return 0;
57 }
59 bool init()
60 {
61 if(!(font = dtx_open_font("data/font.ttf", 16))) {
62 fprintf(stderr, "failed to open font\n");
63 return false;
64 }
66 glEnable(GL_MULTISAMPLE);
67 proj.set_perspective(DEG_TO_RAD(proj_vfov), 1, 1.0, 50.0);
68 return true;
69 }
71 void display()
72 {
73 glClear(GL_COLOR_BUFFER_BIT);
75 glMatrixMode(GL_MODELVIEW);
76 glLoadIdentity();
77 glTranslatef(-pan[0], -pan[1], 0);
78 glScalef(zoom, zoom, zoom);
80 draw_grid();
82 draw_frustum();
84 if(cur_point_valid) {
85 Vector2 ppt = project(cur_point);
87 glPointSize(7.0);
88 glBegin(GL_POINTS);
89 glColor3f(0.2, 1, 0.2);
90 glVertex2f(cur_point.x, cur_point.y);
91 glColor3f(0.7, 0.2, 0.2);
92 glVertex2f(ppt.x, ppt.y);
93 glEnd();
95 glEnable(GL_LINE_STIPPLE);
96 glLineStipple(4, 0xe0e0);
98 glBegin(GL_LINES);
99 glColor3f(0.2, 0.5, 0.2);
100 glVertex2f(cur_point.x, cur_point.y);
101 glColor3f(0.5, 0.2, 0.2);
102 glVertex2f(ppt.x, ppt.y);
103 glEnd();
104 glDisable(GL_LINE_STIPPLE);
106 glColor3f(0.15, 0.5, 0.15);
107 draw_label(cur_point, "(%.2f, %.2f)", cur_point.x, cur_point.y);
108 glColor3f(0.4, 0.1, 0.1);
109 draw_label(ppt, "(%.2f, %.2f)", ppt.x, ppt.y);
110 }
112 glutSwapBuffers();
113 assert(glGetError() == GL_NO_ERROR);
114 }
116 #define LINE(x0, y0, x1, y1) (glVertex2f(x0, y0), glVertex2f(x1, y1))
118 void draw_grid()
119 {
120 float ymin = -10;
121 float ymax = 10;
122 float xmin = -10;
123 float xmax = 10;
124 float ticksz = 0.015 / zoom;
126 glBegin(GL_LINES);
127 glColor3f(1, 1, 1);
128 LINE(0, -10, 0, 10);
129 LINE(-10, 0, 10, 0);
131 for(int i=1; i<11; i++) {
132 for(int j=0; j<2; j++) {
133 float x = 10.0 * (float)i / 10.0 * (j ? -1.0 : 1.0);
135 glColor3f(0.15, 0.15, 0.15);
136 LINE(x, ymin, x, ymax);
137 LINE(xmin, x, xmax, x);
139 glColor3f(0.4, 0.4, 0.4);
140 LINE(x, -ticksz, x, ticksz);
141 LINE(-ticksz, x, ticksz, x);
142 }
143 }
144 glEnd();
145 }
147 void draw_frustum()
148 {
149 Vector2 v0, v1;
151 glBegin(GL_LINES);
152 glColor3f(0.2, 0.4, 0.8);
154 v0 = unproject(Vector2(1, 0));
155 v1 = unproject(Vector2(1, 1));
156 LINE(v0.x, v0.y, v1.x, v1.y);
158 v0 = unproject(Vector2(-1, 0));
159 v1 = unproject(Vector2(-1, 1));
160 LINE(v0.x, v0.y, v1.x, v1.y);
162 LINE(-0.5, proj_near, 0.5, proj_near);
164 glEnd();
165 }
167 void draw_label(const Vector2 &pos, const char *fmt, ...)
168 {
169 static char buf[512];
170 va_list ap;
172 va_start(ap, fmt);
173 vsnprintf(buf, sizeof buf - 1, fmt, ap);
174 va_end(ap);
176 glPushMatrix();
177 glTranslatef(pos.x + 0.01, pos.y + 0.01, 0);
178 float s = 2.0 / (win_ysz * zoom);
179 glScalef(s, s, s);
181 dtx_string(buf);
183 glPopMatrix();
184 }
186 void reshape(int x, int y)
187 {
188 win_xsz = x;
189 win_ysz = y;
190 aspect = (float)x / (float)y;
192 glViewport(0, 0, x, y);
194 glMatrixMode(GL_PROJECTION);
195 glLoadIdentity();
196 glScalef(1.0 / aspect, 1.0, 1.0);
197 }
199 void keyb(unsigned char key, int x, int y)
200 {
201 keystate[key] = 1;
203 switch(key) {
204 case 27:
205 exit(0);
206 }
207 }
209 void keyb_up(unsigned char key, int x, int y)
210 {
211 keystate[key] = 0;
212 }
214 bool bnstate[16];
215 int prev_x, prev_y;
217 void mouse(int bn, int st, int x, int y)
218 {
219 bnstate[bn - GLUT_LEFT_BUTTON] = st == GLUT_DOWN;
220 prev_x = x;
221 prev_y = y;
223 if(bn == GLUT_LEFT_BUTTON && st == GLUT_DOWN) {
224 cur_point = screen_to_world(x, y);
225 cur_point_valid = true;
226 glutPostRedisplay();
227 }
228 }
230 void motion(int x, int y)
231 {
232 float dx = 2.0 * aspect * (x - prev_x) / (float)win_xsz;
233 float dy = 2.0 * (y - prev_y) / (float)win_ysz;
234 prev_x = x;
235 prev_y = y;
237 if(bnstate[0]) {
238 cur_point = screen_to_world(x, y);
239 glutPostRedisplay();
240 }
241 if(bnstate[1]) {
242 pan[0] -= dx;
243 pan[1] += dy;
245 glutPostRedisplay();
246 }
247 if(bnstate[2]) {
248 zoom += dy;
250 if(zoom < 1e-4) zoom = 1e-4;
251 glutPostRedisplay();
252 }
253 }
255 Vector2 screen_to_world(int px, int py)
256 {
257 /* canonical [-1, 1] system */
258 float x = aspect * ((float)px * 2.0 / (float)win_xsz - 1.0);
259 float y = (float)(win_ysz - py) * 2.0 / (float)win_ysz - 1.0;
261 /* account for pan & zoom */
262 x = (x + pan[0]) / zoom;
263 y = (y + pan[1]) / zoom;
265 return Vector2(x, y);
266 }
268 Vector2 project(const Vector2 &v)
269 {
270 Vector4 ppt = Vector4(v.x, 0, -v.y, 1).transformed(proj);
271 return Vector2(ppt.x / ppt.w, ppt.z / ppt.w);
272 }
274 Vector2 unproject(const Vector2 &v)
275 {
276 Vector4 v4 = Vector4(v.x, 0.0, v.y, 1.0);
277 Matrix4x4 inv_proj = proj.inverse();
279 Vector4 res4 = v4.transformed(inv_proj);
280 return Vector2(res4.x / res4.w, -res4.z / res4.w);
281 }