eqemu
diff src/main.cc @ 4:3d3656360a82
rendering properly, added picking, almost done...
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 17 Jul 2014 08:51:17 +0300 |
parents | 48dce4ee4850 |
children | 977bc1cb055b |
line diff
1.1 --- a/src/main.cc Thu Jul 17 02:35:19 2014 +0300 1.2 +++ b/src/main.cc Thu Jul 17 08:51:17 2014 +0300 1.3 @@ -1,5 +1,6 @@ 1.4 #include <stdio.h> 1.5 #include <stdlib.h> 1.6 +#include <float.h> 1.7 #include <assert.h> 1.8 #include <errno.h> 1.9 #include <unistd.h> 1.10 @@ -8,6 +9,7 @@ 1.11 #include <X11/Xlib.h> 1.12 #include <GL/glx.h> 1.13 #include "dev.h" 1.14 +#include "scene.h" 1.15 1.16 static bool init(); 1.17 static void cleanup(); 1.18 @@ -15,6 +17,7 @@ 1.19 static void keyb(int key, bool pressed); 1.20 static void mouse(int bn, bool pressed, int x, int y); 1.21 static void motion(int x, int y); 1.22 +static Ray calc_pick_ray(int x, int y); 1.23 1.24 static Window create_window(const char *title, int xsz, int ysz); 1.25 static void process_events(); 1.26 @@ -29,12 +32,19 @@ 1.27 1.28 static int win_width, win_height; 1.29 1.30 -static bool redisplay_pending; 1.31 +static bool draw_pending; 1.32 static bool win_mapped; 1.33 1.34 static int fakefd = -1; 1.35 static char *fake_devpath; 1.36 1.37 +static float cam_theta, cam_phi, cam_dist = 140; 1.38 +static Scene *scn; 1.39 + 1.40 +enum { BN_TICKET, BN_NEXT, NUM_BUTTONS }; 1.41 +const char *button_names[] = { "button1", "button2" }; 1.42 +static Object *button_obj[NUM_BUTTONS]; 1.43 + 1.44 int main(int argc, char **argv) 1.45 { 1.46 if(proc_args(argc, argv) == -1) { 1.47 @@ -47,6 +57,9 @@ 1.48 1.49 int xfd = ConnectionNumber(dpy); 1.50 1.51 + // run once through pending events before going into the select loop 1.52 + process_events(); 1.53 + 1.54 for(;;) { 1.55 fd_set rd; 1.56 FD_ZERO(&rd); 1.57 @@ -54,9 +67,9 @@ 1.58 FD_SET(xfd, &rd); 1.59 FD_SET(fakefd, &rd); 1.60 1.61 + struct timeval noblock = {0, 0}; 1.62 int maxfd = xfd > fakefd ? xfd : fakefd; 1.63 - 1.64 - while(select(maxfd + 1, &rd, 0, 0, 0) == -1 && errno == EINTR); 1.65 + while(select(maxfd + 1, &rd, 0, 0, draw_pending ? &noblock : 0) == -1 && errno == EINTR); 1.66 1.67 if(FD_ISSET(xfd, &rd)) { 1.68 process_events(); 1.69 @@ -65,9 +78,9 @@ 1.70 proc_dev_input(); 1.71 } 1.72 1.73 - if(redisplay_pending) { 1.74 + if(draw_pending) { 1.75 display(); 1.76 - redisplay_pending = false; 1.77 + draw_pending = false; 1.78 } 1.79 } 1.80 return 0; 1.81 @@ -86,15 +99,42 @@ 1.82 return false; 1.83 } 1.84 1.85 - if(!(win = create_window("dummy equeue device", 800, 600))) { 1.86 + if(!(win = create_window("equeue device emulator", 800, 600))) { 1.87 return false; 1.88 } 1.89 1.90 + glewInit(); 1.91 + 1.92 + scn = new Scene; 1.93 + if(!scn->load("data/device.obj")) { 1.94 + fprintf(stderr, "failed to load device 3D model\n"); 1.95 + return false; 1.96 + } 1.97 + 1.98 + for(int i=0; i<NUM_BUTTONS; i++) { 1.99 + button_obj[i] = scn->get_object(button_names[i]); 1.100 + if(!button_obj[i]) { 1.101 + fprintf(stderr, "invalid 3D model\n"); 1.102 + return false; 1.103 + } 1.104 + BSphere &bs = button_obj[i]->get_mesh()->get_bounds(); 1.105 + bs.set_radius(bs.get_radius() * 1.5); 1.106 + } 1.107 + 1.108 + glEnable(GL_DEPTH_TEST); 1.109 + glEnable(GL_CULL_FACE); 1.110 + glEnable(GL_LIGHTING); 1.111 + glEnable(GL_LIGHT0); 1.112 + 1.113 + glClearColor(0.1, 0.1, 0.1, 1); 1.114 + 1.115 return true; 1.116 } 1.117 1.118 static void cleanup() 1.119 { 1.120 + delete scn; 1.121 + 1.122 stop_dev(); 1.123 1.124 if(!dpy) return; 1.125 @@ -111,6 +151,14 @@ 1.126 1.127 glMatrixMode(GL_MODELVIEW); 1.128 glLoadIdentity(); 1.129 + glTranslatef(0, 0, -cam_dist); 1.130 + glRotatef(cam_phi, 1, 0, 0); 1.131 + glRotatef(cam_theta, 0, 1, 0); 1.132 + 1.133 + float lpos[] = {-7, 5, 10, 0}; 1.134 + glLightfv(GL_LIGHT0, GL_POSITION, lpos); 1.135 + 1.136 + scn->render(); 1.137 1.138 glXSwapBuffers(dpy, win); 1.139 assert(glGetError() == GL_NO_ERROR); 1.140 @@ -122,7 +170,10 @@ 1.141 1.142 glMatrixMode(GL_PROJECTION); 1.143 glLoadIdentity(); 1.144 - gluPerspective(50.0, (float)x / (float)y, 0.5, 500.0); 1.145 + gluPerspective(50.0, (float)x / (float)y, 1.0, 1000.0); 1.146 + 1.147 + win_width = x; 1.148 + win_height = y; 1.149 } 1.150 1.151 static void keyb(int key, bool pressed) 1.152 @@ -135,12 +186,87 @@ 1.153 } 1.154 } 1.155 1.156 +static bool bnstate[32]; 1.157 +static int prev_x, prev_y; 1.158 + 1.159 static void mouse(int bn, bool pressed, int x, int y) 1.160 { 1.161 + bnstate[bn] = pressed; 1.162 + prev_x = x; 1.163 + prev_y = y; 1.164 + 1.165 + if(bn == 0 && pressed) { 1.166 + // do picking 1.167 + Ray ray = calc_pick_ray(x, win_height - y); 1.168 + 1.169 + HitPoint minhit; 1.170 + minhit.t = FLT_MAX; 1.171 + int hit_found = -1; 1.172 + 1.173 + for(int i=0; i<NUM_BUTTONS; i++) { 1.174 + HitPoint hit; 1.175 + if(button_obj[i]->get_mesh()->get_bounds().intersect(ray, &hit) && hit.t < minhit.t) { 1.176 + minhit = hit; 1.177 + hit_found = i; 1.178 + } 1.179 + } 1.180 + 1.181 + if(hit_found != -1) { 1.182 + switch(hit_found) { 1.183 + case BN_TICKET: 1.184 + issue_ticket(); 1.185 + printf("issue ticket\n"); 1.186 + break; 1.187 + 1.188 + case BN_NEXT: 1.189 + next_customer(); 1.190 + printf("next customer\n"); 1.191 + break; 1.192 + } 1.193 + draw_pending = true; 1.194 + } 1.195 + } 1.196 } 1.197 1.198 static void motion(int x, int y) 1.199 { 1.200 + int dx = x - prev_x; 1.201 + int dy = y - prev_y; 1.202 + prev_x = x; 1.203 + prev_y = y; 1.204 + 1.205 + if(bnstate[0]) { 1.206 + cam_theta += dx * 0.5; 1.207 + cam_phi += dy * 0.5; 1.208 + if(cam_phi < -90) cam_phi = -90; 1.209 + if(cam_phi > 90) cam_phi = 90; 1.210 + draw_pending = true; 1.211 + } 1.212 + if(bnstate[2]) { 1.213 + cam_dist += dy * 0.5; 1.214 + if(cam_dist < 0.0) cam_dist = 0.0; 1.215 + draw_pending = true; 1.216 + } 1.217 +} 1.218 + 1.219 +static Ray calc_pick_ray(int x, int y) 1.220 +{ 1.221 + double mv[16], proj[16]; 1.222 + int vp[4]; 1.223 + double resx, resy, resz; 1.224 + Ray ray; 1.225 + 1.226 + glGetDoublev(GL_MODELVIEW_MATRIX, mv); 1.227 + glGetDoublev(GL_PROJECTION_MATRIX, proj); 1.228 + glGetIntegerv(GL_VIEWPORT, vp); 1.229 + 1.230 + gluUnProject(x, y, 0, mv, proj, vp, &resx, &resy, &resz); 1.231 + ray.origin = Vector3(resx, resy, resz); 1.232 + 1.233 + gluUnProject(x, y, 1, mv, proj, vp, &resx, &resy, &resz); 1.234 + ray.dir = normalize(Vector3(resx, resy, resz) - ray.origin); 1.235 + 1.236 + return ray; 1.237 } 1.238 1.239 static Window create_window(const char *title, int xsz, int ysz) 1.240 @@ -231,7 +357,7 @@ 1.241 1.242 case Expose: 1.243 if(win_mapped && ev.xexpose.count == 0) { 1.244 - redisplay_pending = 1; 1.245 + draw_pending = 1; 1.246 } 1.247 break; 1.248