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