nuclear@0: #include nuclear@0: #include nuclear@0: #include "opengl.h" nuclear@0: #include "game.h" nuclear@0: #include "sdr.h" nuclear@0: #include "shader.h" nuclear@0: #include "shadow.h" nuclear@0: #include "opt.h" nuclear@3: #include "mesh.h" nuclear@0: nuclear@2: #include "room.h" nuclear@6: #include "dragon.h" nuclear@2: nuclear@0: static void draw_scene(); nuclear@0: nuclear@0: int win_width, win_height; nuclear@0: unsigned long cur_time; nuclear@0: bool dbg_wireframe; nuclear@0: int dbg_int; nuclear@0: nuclear@0: unsigned int sdr_shadow, sdr_shadow_notex; nuclear@0: nuclear@6: static float cam_theta, cam_phi = 23, cam_dist = 26; nuclear@6: static float cam_x, cam_y, cam_z = 9; nuclear@0: static bool bnstate[8]; nuclear@0: static int prev_x, prev_y; nuclear@6: static bool gamectl = false; nuclear@0: nuclear@0: static unsigned int modkeys; nuclear@0: nuclear@0: nuclear@7: static Dragon *dragon; nuclear@6: nuclear@6: nuclear@0: bool game_init() nuclear@0: { nuclear@0: if(init_opengl() == -1) { nuclear@0: return false; nuclear@0: } nuclear@0: nuclear@0: glEnable(GL_DEPTH_TEST); nuclear@0: glEnable(GL_CULL_FACE); nuclear@0: glEnable(GL_NORMALIZE); nuclear@0: glEnable(GL_LIGHTING); nuclear@0: glEnable(GL_LIGHT0); nuclear@0: nuclear@2: float amb[] = {0.1, 0.1, 0.1, 1.0}; nuclear@0: glLightModelfv(GL_LIGHT_MODEL_AMBIENT, amb); nuclear@0: nuclear@0: if(glcaps.sep_spec) { nuclear@0: glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); nuclear@0: } nuclear@0: glEnable(GL_MULTISAMPLE); nuclear@0: nuclear@0: if(!init_shadow(4096)) { nuclear@0: fprintf(stderr, "failed to initialize shadowmaps\n"); nuclear@0: return false; nuclear@0: } nuclear@0: if(!(sdr_shadow = create_program_load("sdr/shadow.v.glsl", "sdr/shadow.p.glsl"))) { nuclear@0: return false; nuclear@0: } nuclear@0: set_uniform_int(sdr_shadow, "tex", 0); nuclear@0: set_uniform_int(sdr_shadow, "shadowmap", 1); nuclear@0: nuclear@0: if(!(sdr_shadow_notex = create_program_load("sdr/shadow.v.glsl", "sdr/shadow-notex.p.glsl"))) { nuclear@0: return false; nuclear@0: } nuclear@0: set_uniform_int(sdr_shadow_notex, "shadowmap", 1); nuclear@0: nuclear@2: if(!init_room()) { nuclear@2: return false; nuclear@2: } nuclear@0: nuclear@7: dragon = new Dragon; nuclear@7: dragon->set_position(Vector3(0, 5, 20)); nuclear@7: dragon->set_direction(Vector3(0, 0, -1)); nuclear@7: dragon->set_target(Vector3(0, 3, 0)); nuclear@7: dragon->move_head(Vector3(0, 6, 10)); nuclear@7: dragon->set_head_limits(-ROOM_WIDTH * 0.2, ROOM_WIDTH * 0.2, 1, ROOM_HEIGHT - 3); nuclear@6: nuclear@3: Mesh::use_custom_sdr_attr = false; nuclear@3: nuclear@0: assert(glGetError() == GL_NO_ERROR); nuclear@0: return true; nuclear@0: } nuclear@0: nuclear@0: void game_cleanup() nuclear@0: { nuclear@7: delete dragon; nuclear@2: cleanup_room(); nuclear@0: } nuclear@0: nuclear@0: void game_update(unsigned long time_msec) nuclear@0: { nuclear@0: cur_time = time_msec; nuclear@6: nuclear@7: dragon->update(); nuclear@0: } nuclear@0: nuclear@0: void game_display() nuclear@0: { nuclear@0: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); nuclear@0: nuclear@0: glMatrixMode(GL_MODELVIEW); nuclear@0: glLoadIdentity(); nuclear@0: glTranslatef(0, 0.1, -cam_dist); nuclear@0: glRotatef(cam_phi, 1, 0, 0); nuclear@0: glRotatef(cam_theta, 0, 1, 0); nuclear@6: glTranslatef(-cam_x, -cam_y, -cam_z); nuclear@0: nuclear@6: float lpos[] = {0, 10, 24, 1}; nuclear@0: glLightfv(GL_LIGHT0, GL_POSITION, lpos); nuclear@0: nuclear@0: if(opt.shadows && sdr_shadow) { nuclear@6: begin_shadow_pass(Vector3(lpos[0], lpos[1], lpos[2]), Vector3(0, 0, 0), 45); nuclear@0: draw_scene(); nuclear@0: end_shadow_pass(); nuclear@0: nuclear@0: glActiveTexture(GL_TEXTURE1); nuclear@0: glBindTexture(GL_TEXTURE_2D, get_shadow_tex()); nuclear@0: nuclear@0: glMatrixMode(GL_TEXTURE); nuclear@0: Matrix4x4 shadow_matrix = get_shadow_matrix(); nuclear@0: glLoadTransposeMatrixf(shadow_matrix[0]); nuclear@0: nuclear@0: glActiveTexture(GL_TEXTURE0); nuclear@0: glMatrixMode(GL_MODELVIEW); nuclear@0: nuclear@2: override_shader(sdr_shadow_notex); nuclear@0: nuclear@0: draw_scene(); nuclear@0: nuclear@0: glActiveTexture(GL_TEXTURE1); nuclear@0: glBindTexture(GL_TEXTURE_2D, 0); nuclear@0: glActiveTexture(GL_TEXTURE0); nuclear@0: glBindTexture(GL_TEXTURE_2D, 0); nuclear@0: } else { nuclear@0: draw_scene(); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: static void glmaterial(float r, float g, float b, float spec, float shin) nuclear@0: { nuclear@0: float color[] = {r, g, b, 1}; nuclear@0: float scolor[] = {spec, spec, spec, 1}; nuclear@0: glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color); nuclear@0: glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, scolor); nuclear@0: glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shin); nuclear@0: } nuclear@0: nuclear@0: static void draw_scene() nuclear@0: { nuclear@2: draw_room(); nuclear@2: nuclear@0: glPushMatrix(); nuclear@2: glTranslatef(0, 0.75, 0); nuclear@0: nuclear@3: glmaterial(1.0, 0.4, 0.3, 0.8, 60.0); nuclear@0: draw_teapot(); nuclear@2: nuclear@2: glPopMatrix(); nuclear@6: nuclear@7: dragon->draw(); nuclear@0: } nuclear@0: nuclear@0: nuclear@0: void game_reshape(int x, int y) nuclear@0: { nuclear@0: glMatrixMode(GL_PROJECTION); nuclear@0: glLoadIdentity(); nuclear@0: gluPerspective(45, (float)x / (float)y, 0.2, 200.0); nuclear@0: nuclear@0: glViewport(0, 0, x, y); nuclear@0: } nuclear@0: nuclear@0: void game_keyboard(int bn, bool press) nuclear@0: { nuclear@0: if(press) { nuclear@0: switch(bn) { nuclear@0: case 27: nuclear@0: quit(); nuclear@0: nuclear@6: case ' ': nuclear@6: gamectl = !gamectl; nuclear@6: break; nuclear@6: nuclear@0: case 'w': nuclear@0: dbg_wireframe = !dbg_wireframe; nuclear@0: redisplay(); nuclear@0: break; nuclear@0: nuclear@0: case 's': nuclear@0: opt.shadows = !opt.shadows; nuclear@0: redisplay(); nuclear@0: break; nuclear@6: nuclear@6: case 'p': nuclear@6: printf("camera pos(%g %g %g) rot(%g %g) d(%g)\n", nuclear@6: cam_x, cam_y, cam_z, cam_theta, cam_phi, cam_dist); nuclear@6: break; nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: void game_modifier_key(int key, bool press) nuclear@0: { nuclear@0: if(press) { nuclear@0: modkeys |= (1 << key); nuclear@0: } else { nuclear@0: modkeys &= ~(1 << key); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: void game_mbutton(int bn, bool press, int x, int y) nuclear@0: { nuclear@0: bnstate[bn] = press; nuclear@0: prev_x = x; nuclear@0: prev_y = y; nuclear@0: nuclear@0: if(modkeys) { nuclear@0: return; nuclear@0: } nuclear@0: nuclear@0: if(bn == 0) { nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: void game_mmotion(int x, int y) nuclear@0: { nuclear@0: int dx = x - prev_x; nuclear@0: int dy = y - prev_y; nuclear@0: prev_x = x; nuclear@0: prev_y = y; nuclear@0: nuclear@6: if(gamectl) { nuclear@7: dragon->move_head(dx * 0.1, -dy * 0.1); nuclear@6: } nuclear@6: nuclear@0: if(modkeys) { nuclear@0: if(bnstate[0]) { nuclear@0: cam_theta += dx * 0.5; nuclear@0: cam_phi += dy * 0.5; nuclear@0: nuclear@0: if(cam_phi < -90) cam_phi = -90; nuclear@0: if(cam_phi > 90) cam_phi = 90; nuclear@0: } nuclear@6: if(bnstate[1]) { nuclear@6: float theta = DEG_TO_RAD(cam_theta); nuclear@6: nuclear@6: float dxp = dx * 0.1; nuclear@6: float dyp = dy * 0.1; nuclear@6: nuclear@6: cam_x += cos(theta) * dxp - sin(theta) * dyp; nuclear@6: if(modkeys & (1 << MOD_SHIFT)) { nuclear@6: cam_y -= sin(theta) * dxp + cos(theta) * dyp; nuclear@6: } else { nuclear@6: cam_z += sin(theta) * dxp + cos(theta) * dyp; nuclear@6: } nuclear@6: } nuclear@0: if(bnstate[2]) { nuclear@0: cam_dist += dy * 0.1; nuclear@0: if(cam_dist < 0.0) cam_dist = 0.0; nuclear@0: } nuclear@0: } nuclear@0: }