# HG changeset patch # User John Tsiombikas # Date 1422114575 -7200 # Node ID 64483c640a3849c429248ecf845476007955faf3 # Parent e467998dcc64f0437a499bc8f77e10efbe3374b4 foo diff -r e467998dcc64 -r 64483c640a38 main.cc --- a/main.cc Sat Jan 24 16:36:34 2015 +0200 +++ b/main.cc Sat Jan 24 17:49:35 2015 +0200 @@ -9,6 +9,7 @@ bool init(); void display(); void draw_grid(); +void draw_frustum(); void draw_label(const Vector2 &pos, const char *fmt, ...); void reshape(int x, int y); void keyb(unsigned char key, int x, int y); @@ -16,6 +17,8 @@ void mouse(int bn, int st, int x, int y); void motion(int x, int y); Vector2 screen_to_world(int x, int y); +Vector2 project(const Vector2 &v); +Vector2 unproject(const Vector2 &v); int win_xsz, win_ysz; float aspect; @@ -24,9 +27,12 @@ Vector2 cur_point; bool cur_point_valid; +float proj_near = 0.5, proj_far = 50.0; +float proj_vfov = 50.0; + bool keystate[256]; dtx_font *font; -float pan[2], zoom = 1.0; +float pan[2] = {0, 0.85}, zoom = 0.4; int main(int argc, char **argv) { @@ -58,7 +64,7 @@ } glEnable(GL_MULTISAMPLE); - proj.set_perspective(DEG_TO_RAD(60), 1, 0.5, 500.0); + proj.set_perspective(DEG_TO_RAD(proj_vfov), 1, 1.0, 50.0); return true; } @@ -73,15 +79,34 @@ draw_grid(); + draw_frustum(); + if(cur_point_valid) { + Vector2 ppt = project(cur_point); + glPointSize(7.0); glBegin(GL_POINTS); glColor3f(0.2, 1, 0.2); glVertex2f(cur_point.x, cur_point.y); + glColor3f(0.7, 0.2, 0.2); + glVertex2f(ppt.x, ppt.y); glEnd(); + glEnable(GL_LINE_STIPPLE); + glLineStipple(4, 0xe0e0); + + glBegin(GL_LINES); + glColor3f(0.2, 0.5, 0.2); + glVertex2f(cur_point.x, cur_point.y); + glColor3f(0.5, 0.2, 0.2); + glVertex2f(ppt.x, ppt.y); + glEnd(); + glDisable(GL_LINE_STIPPLE); + glColor3f(0.15, 0.5, 0.15); draw_label(cur_point, "(%.2f, %.2f)", cur_point.x, cur_point.y); + glColor3f(0.4, 0.1, 0.1); + draw_label(ppt, "(%.2f, %.2f)", ppt.x, ppt.y); } glutSwapBuffers(); @@ -92,20 +117,20 @@ void draw_grid() { - float ymin = -1; - float ymax = 1; - float xmin = -1; - float xmax = 1; - float ticksz = 0.015; + float ymin = -10; + float ymax = 10; + float xmin = -10; + float xmax = 10; + float ticksz = 0.015 / zoom; glBegin(GL_LINES); glColor3f(1, 1, 1); - LINE(0, -1, 0, 1); - LINE(-1, 0, 1, 0); + LINE(0, -10, 0, 10); + LINE(-10, 0, 10, 0); for(int i=1; i<11; i++) { for(int j=0; j<2; j++) { - float x = (float)i / 10.0 * (j ? -1.0 : 1.0); + float x = 10.0 * (float)i / 10.0 * (j ? -1.0 : 1.0); glColor3f(0.15, 0.15, 0.15); LINE(x, ymin, x, ymax); @@ -119,6 +144,26 @@ glEnd(); } +void draw_frustum() +{ + Vector2 v0, v1; + + glBegin(GL_LINES); + glColor3f(0.2, 0.4, 0.8); + + v0 = unproject(Vector2(1, 0)); + v1 = unproject(Vector2(1, 1)); + LINE(v0.x, v0.y, v1.x, v1.y); + + v0 = unproject(Vector2(-1, 0)); + v1 = unproject(Vector2(-1, 1)); + LINE(v0.x, v0.y, v1.x, v1.y); + + LINE(-0.5, proj_near, 0.5, proj_near); + + glEnd(); +} + void draw_label(const Vector2 &pos, const char *fmt, ...) { static char buf[512]; @@ -209,11 +254,28 @@ Vector2 screen_to_world(int px, int py) { - float sx = 2.0 * aspect * (1.0 / zoom) / (float)win_xsz; - float sy = 2.0 * (1.0 / zoom) / (float)win_ysz; + /* canonical [-1, 1] system */ + float x = aspect * ((float)px * 2.0 / (float)win_xsz - 1.0); + float y = (float)(win_ysz - py) * 2.0 / (float)win_ysz - 1.0; - float x = (float)px * sx - (aspect + pan[0]) / zoom; - float y = (float)(win_ysz - py) * sy - (1.0 + pan[1]) / zoom; + /* account for pan & zoom */ + x = (x + pan[0]) / zoom; + y = (y + pan[1]) / zoom; return Vector2(x, y); } + +Vector2 project(const Vector2 &v) +{ + Vector4 ppt = Vector4(v.x, 0, -v.y, 1).transformed(proj); + return Vector2(ppt.x / ppt.w, ppt.z / ppt.w); +} + +Vector2 unproject(const Vector2 &v) +{ + Vector4 v4 = Vector4(v.x, 0.0, v.y, 1.0); + Matrix4x4 inv_proj = proj.inverse(); + + Vector4 res4 = v4.transformed(inv_proj); + return Vector2(res4.x / res4.w, -res4.z / res4.w); +}