view3d
diff src/main.c @ 0:182bfd9f55c7
view3d
author | John Tsiombikas <nuclear@mutantstargoat.com> |
---|---|
date | Thu, 19 Jan 2012 00:17:31 +0200 |
parents | |
children | 7e982a61852a |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/main.c Thu Jan 19 00:17:31 2012 +0200 1.3 @@ -0,0 +1,354 @@ 1.4 +#include <stdio.h> 1.5 +#include <stdlib.h> 1.6 +#include <math.h> 1.7 + 1.8 +#include <GL/glew.h> 1.9 +#ifndef __APPLE__ 1.10 +#include <GL/glut.h> 1.11 +#else 1.12 +#include <GLUT/glut.h> 1.13 +#endif 1.14 + 1.15 +#include "scene.h" 1.16 + 1.17 +void disp(void); 1.18 +void render(unsigned int msec); 1.19 +void proj_matrix(float eye); 1.20 +void view_matrix(float eye); 1.21 + 1.22 +void reshape(int x, int y); 1.23 +void keyb(unsigned char key, int x, int y); 1.24 +void keyb_up(unsigned char key, int x, int y); 1.25 +void mouse(int bn, int state, int x, int y); 1.26 +void motion(int x, int y); 1.27 +void sball_motion(int x, int y, int z); 1.28 +void sball_rotate(int x, int y, int z); 1.29 +void sball_button(int bn, int state); 1.30 +int parse_args(int argc, char **argv); 1.31 + 1.32 +char *scene_fname; 1.33 +int win_width, win_height; 1.34 +int stereo; 1.35 +int flip_winding; 1.36 +int auto_rot = 1; 1.37 +float cam_theta, cam_phi, cam_dist = 10; 1.38 +float near_clip = 0.5; 1.39 +float far_clip = 1000.0; 1.40 +float fov = M_PI / 4.0; 1.41 +float stereo_focus_dist = 1.0; 1.42 +float stereo_eye_sep = 1.0 / 30.0; 1.43 + 1.44 +struct scene scn; 1.45 + 1.46 +int main(int argc, char **argv) 1.47 +{ 1.48 + float ldir[] = {1, -1, -1, 0}; 1.49 + float dx, dy, dz, diag; 1.50 + 1.51 + glutInitWindowSize(800, 600); 1.52 + glutInit(&argc, argv); 1.53 + 1.54 + if(parse_args(argc, argv) == -1) { 1.55 + return 1; 1.56 + } 1.57 + 1.58 + glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE | (stereo ? GLUT_STEREO : 0)); 1.59 + glutCreateWindow("OpenGL Logo"); 1.60 + 1.61 + glutDisplayFunc(disp); 1.62 + glutReshapeFunc(reshape); 1.63 + glutKeyboardFunc(keyb); 1.64 + glutKeyboardUpFunc(keyb_up); 1.65 + glutMouseFunc(mouse); 1.66 + glutMotionFunc(motion); 1.67 + glutSpaceballMotionFunc(sball_motion); 1.68 + glutSpaceballRotateFunc(sball_rotate); 1.69 + glutSpaceballButtonFunc(sball_button); 1.70 + glutIdleFunc(glutPostRedisplay); 1.71 + 1.72 + glewInit(); 1.73 + 1.74 + glEnable(GL_DEPTH_TEST); 1.75 + glEnable(GL_CULL_FACE); 1.76 + glEnable(GL_LIGHTING); 1.77 + glEnable(GL_LIGHT0); 1.78 + glLightfv(GL_LIGHT0, GL_POSITION, ldir); 1.79 + 1.80 + if((load_scene(&scn, scene_fname)) == -1) { 1.81 + fprintf(stderr, "failed to load: %s\n", scene_fname); 1.82 + return 1; 1.83 + } 1.84 + dx = scn.bbox.max[0] - scn.bbox.min[0]; 1.85 + dy = scn.bbox.max[1] - scn.bbox.min[1]; 1.86 + dz = scn.bbox.max[2] - scn.bbox.min[2]; 1.87 + diag = sqrt(dx * dx + dy * dy + dz * dz); 1.88 + cam_dist = diag / fov; 1.89 + printf("camera distance: %f\n", cam_dist); 1.90 + 1.91 + glutMainLoop(); 1.92 + return 0; 1.93 +} 1.94 + 1.95 + 1.96 +void disp(void) 1.97 +{ 1.98 + unsigned int tm = glutGet(GLUT_ELAPSED_TIME); 1.99 + 1.100 + if(stereo) { 1.101 + glDrawBuffer(GL_BACK_LEFT); 1.102 + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 1.103 + 1.104 + glMatrixMode(GL_PROJECTION); 1.105 + glLoadIdentity(); 1.106 + proj_matrix(-1); 1.107 + glMatrixMode(GL_MODELVIEW); 1.108 + glLoadIdentity(); 1.109 + view_matrix(-1); 1.110 + 1.111 + render(tm); 1.112 + 1.113 + glDrawBuffer(GL_BACK_RIGHT); 1.114 + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 1.115 + 1.116 + glMatrixMode(GL_PROJECTION); 1.117 + glLoadIdentity(); 1.118 + proj_matrix(1); 1.119 + glMatrixMode(GL_MODELVIEW); 1.120 + glLoadIdentity(); 1.121 + view_matrix(1); 1.122 + 1.123 + render(tm); 1.124 + } else { 1.125 + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 1.126 + 1.127 + glMatrixMode(GL_PROJECTION); 1.128 + glLoadIdentity(); 1.129 + proj_matrix(0); 1.130 + glMatrixMode(GL_MODELVIEW); 1.131 + glLoadIdentity(); 1.132 + view_matrix(0); 1.133 + 1.134 + render(tm); 1.135 + } 1.136 + 1.137 + glutSwapBuffers(); 1.138 +} 1.139 + 1.140 +void render(unsigned int msec) 1.141 +{ 1.142 + if(auto_rot) { 1.143 + glRotatef(msec / 10, 0, 1, 0); 1.144 + } 1.145 + render_scene(&scn); 1.146 +} 1.147 + 1.148 +void proj_matrix(float eye) 1.149 +{ 1.150 + float vfov_rad = fov; 1.151 + float top = near_clip * tan(vfov_rad * 0.5); 1.152 + float right = top * (float)win_width / (float)win_height; 1.153 + 1.154 + float frust_shift = eye * (stereo_eye_sep * 0.5 * near_clip / stereo_focus_dist); 1.155 + 1.156 + glFrustum(-right + frust_shift, right + frust_shift, -top, top, near_clip, far_clip); 1.157 +} 1.158 + 1.159 +void view_matrix(float eye) 1.160 +{ 1.161 + float offs = stereo_eye_sep * eye * 0.5; 1.162 + glTranslatef(offs, 0, 0); 1.163 + 1.164 + glTranslatef(0, 0, -cam_dist); 1.165 + glRotatef(cam_phi, 1, 0, 0); 1.166 + glRotatef(cam_theta, 0, 1, 0); 1.167 +} 1.168 + 1.169 +void reshape(int x, int y) 1.170 +{ 1.171 + glViewport(0, 0, x, y); 1.172 + win_width = x; 1.173 + win_height = y; 1.174 +} 1.175 + 1.176 +static int stereo_shift_key; 1.177 + 1.178 +void keyb(unsigned char key, int x, int y) 1.179 +{ 1.180 + switch(key) { 1.181 + case 'q': 1.182 + case 27: 1.183 + exit(0); 1.184 + 1.185 + case 's': 1.186 + stereo_shift_key = 1; 1.187 + break; 1.188 + 1.189 + case 'c': 1.190 + { 1.191 + static int flip; 1.192 + glFrontFace((++flip & 1) ? GL_CW : GL_CCW); 1.193 + glutPostRedisplay(); 1.194 + } 1.195 + break; 1.196 + 1.197 + case 'C': 1.198 + { 1.199 + static int cull = 1; 1.200 + if(++cull & 1) { 1.201 + glEnable(GL_CULL_FACE); 1.202 + } else { 1.203 + glDisable(GL_CULL_FACE); 1.204 + } 1.205 + glutPostRedisplay(); 1.206 + } 1.207 + break; 1.208 + 1.209 + case 'w': 1.210 + { 1.211 + static int wire; 1.212 + glPolygonMode(GL_FRONT_AND_BACK, (++wire & 1) ? GL_LINE : GL_FILL); 1.213 + glutPostRedisplay(); 1.214 + } 1.215 + break; 1.216 + 1.217 + case 'l': 1.218 + { 1.219 + static int lit = 1; 1.220 + if(++lit & 1) { 1.221 + glEnable(GL_LIGHTING); 1.222 + } else { 1.223 + glDisable(GL_LIGHTING); 1.224 + } 1.225 + glutPostRedisplay(); 1.226 + } 1.227 + break; 1.228 + 1.229 + case ' ': 1.230 + auto_rot = !auto_rot; 1.231 + if(auto_rot) { 1.232 + glutIdleFunc(glutPostRedisplay); 1.233 + } else { 1.234 + glutIdleFunc(0); 1.235 + } 1.236 + glutPostRedisplay(); 1.237 + break; 1.238 + 1.239 + default: 1.240 + break; 1.241 + } 1.242 +} 1.243 + 1.244 +void keyb_up(unsigned char key, int x, int y) 1.245 +{ 1.246 + switch(key) { 1.247 + case 's': 1.248 + stereo_shift_key = 0; 1.249 + break; 1.250 + 1.251 + default: 1.252 + break; 1.253 + } 1.254 +} 1.255 + 1.256 + 1.257 +static int bnstate[32]; 1.258 +static int prev_x, prev_y; 1.259 +void mouse(int bn, int state, int x, int y) 1.260 +{ 1.261 + prev_x = x; 1.262 + prev_y = y; 1.263 + bnstate[bn - GLUT_LEFT_BUTTON] = state == GLUT_DOWN ? 1 : 0; 1.264 +} 1.265 + 1.266 +void motion(int x, int y) 1.267 +{ 1.268 + int dx = x - prev_x; 1.269 + int dy = y - prev_y; 1.270 + prev_x = x; 1.271 + prev_y = y; 1.272 + 1.273 + if(stereo_shift_key && dy != 0) { 1.274 + stereo_focus_dist += dy * 0.1; 1.275 + stereo_eye_sep = stereo_focus_dist / 30.0; 1.276 + glutPostRedisplay(); 1.277 + return; 1.278 + } 1.279 + 1.280 + if(bnstate[0]) { 1.281 + cam_theta += dx * 0.5; 1.282 + cam_phi += dy * 0.5; 1.283 + 1.284 + if(cam_phi < -90) 1.285 + cam_phi = -90; 1.286 + if(cam_phi > 90) 1.287 + cam_phi = 90; 1.288 + 1.289 + glutPostRedisplay(); 1.290 + } 1.291 + if(bnstate[2]) { 1.292 + cam_dist += dy * 0.1; 1.293 + glutPostRedisplay(); 1.294 + } 1.295 +} 1.296 + 1.297 +void sball_motion(int x, int y, int z) 1.298 +{ 1.299 +} 1.300 + 1.301 +void sball_rotate(int x, int y, int z) 1.302 +{ 1.303 + cam_theta += y * 0.05; 1.304 + cam_phi += x * 0.05; 1.305 + 1.306 + if(cam_phi < -90) 1.307 + cam_phi = -90; 1.308 + if(cam_phi > 90) 1.309 + cam_phi = 90; 1.310 + 1.311 + glutPostRedisplay(); 1.312 +} 1.313 + 1.314 +void sball_button(int bn, int state) 1.315 +{ 1.316 +} 1.317 + 1.318 +int parse_args(int argc, char **argv) 1.319 +{ 1.320 + int i; 1.321 + 1.322 + for(i=1; i<argc; i++) { 1.323 + if(argv[i][0] == '-') { 1.324 + if(argv[i][2] != 0) 1.325 + goto inval; 1.326 + switch(argv[i][1]) { 1.327 + case 's': 1.328 + stereo = 1; 1.329 + break; 1.330 + 1.331 + case 'c': 1.332 + flip_winding = 1; 1.333 + break; 1.334 + 1.335 + default: 1.336 + goto inval; 1.337 + } 1.338 + } else { 1.339 + if(scene_fname) { 1.340 + fprintf(stderr, "unexpected argument: %s\n", argv[i]); 1.341 + return -1; 1.342 + } 1.343 + scene_fname = argv[i]; 1.344 + } 1.345 + } 1.346 + 1.347 + if(!scene_fname) { 1.348 + fprintf(stderr, "you must pass the filename of a scene to open\n"); 1.349 + return -1; 1.350 + } 1.351 + 1.352 + return 0; 1.353 + 1.354 +inval: 1.355 + fprintf(stderr, "invalid argument: %s\n", argv[i]); 1.356 + return -1; 1.357 +}