nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@3: #include nuclear@0: #include "opengl.h" nuclear@2: #ifdef __APPLE__ nuclear@2: #include nuclear@2: #else nuclear@0: #include nuclear@2: #endif nuclear@0: #include "scene.h" nuclear@0: #include "meshgen.h" nuclear@0: #include "pnoise.h" nuclear@0: #include "image.h" nuclear@0: #include "rng.h" nuclear@0: #include "sdr.h" nuclear@0: #include "audio/audio.h" nuclear@0: #include "audio/ovstream.h" nuclear@0: #include "dsys/dsys.h" nuclear@0: nuclear@0: bool init(); nuclear@0: void cleanup(); nuclear@0: void display(); nuclear@0: void idle(); nuclear@0: void reshape(int x, int y); nuclear@0: void keyb(unsigned char key, int x, int y); nuclear@0: void mouse(int bn, int st, int x, int y); nuclear@0: void motion(int x, int y); nuclear@0: nuclear@0: float cam_theta, cam_phi = 25, cam_dist = 6; nuclear@0: Scene *scn; nuclear@0: bool wireframe; nuclear@0: int num_shells = 64; nuclear@0: float shell_scale = 1.015; nuclear@0: bool anim = true; nuclear@0: bool fullscr = true; nuclear@0: nuclear@0: static std::vector images; nuclear@0: static Object *pkin_obj; nuclear@0: static Mesh *pkin_mesh; nuclear@0: static unsigned int pkin_tex; nuclear@0: nuclear@0: static unsigned int sdr_spot; nuclear@0: nuclear@0: static float ramp[3]; nuclear@0: nuclear@0: nuclear@0: static OggVorbisStream *music; nuclear@0: static struct dsys_demo *demo; nuclear@0: nuclear@0: nuclear@0: int main(int argc, char **argv) nuclear@0: { nuclear@0: glutInit(&argc, argv); nuclear@0: glutInitWindowSize(1280, 720); nuclear@0: glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE); nuclear@0: glutCreateWindow("DBF Halloween 2015 compo entry"); nuclear@0: nuclear@0: if(argv[1]) { nuclear@0: if(strcmp(argv[1], "-w") == 0 || strcmp(argv[1], "-windowed") == 0) { nuclear@0: fullscr = false; nuclear@0: } else { nuclear@0: fprintf(stderr, "unrecognized argument: %s\nUse -w or -windowed to run in a window\n", argv[1]); nuclear@0: return 1; nuclear@0: } nuclear@0: } nuclear@0: if(fullscr) { nuclear@0: glutFullScreen(); nuclear@0: } nuclear@0: nuclear@0: glutDisplayFunc(display); nuclear@0: glutIdleFunc(idle); nuclear@0: glutReshapeFunc(reshape); nuclear@0: glutKeyboardFunc(keyb); nuclear@0: glutMouseFunc(mouse); nuclear@0: glutMotionFunc(motion); nuclear@0: nuclear@0: if(!init()) { nuclear@0: return 1; nuclear@0: } nuclear@0: glutMainLoop(); nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: static float ground_func(float u, float v, void *cls) nuclear@0: { nuclear@0: return fbm2(u * 3.0, v * 3.0, 2) * 0.8; nuclear@0: } nuclear@0: nuclear@0: static Vector2 pumpkin_func(float u, float v, void *cls) nuclear@0: { nuclear@0: float theta = v * M_PI; nuclear@0: float r = sin(theta) * 0.5 + 0.5; nuclear@0: nuclear@0: // modulate a high-frequency short-amp wave along u to make the ribs(?) nuclear@0: r += fabs(sin(u * M_PI * 12.0)) * 0.02;// + 1.0; nuclear@0: nuclear@0: // throw some noise in there for good measure nuclear@0: r += pnoise2(u * 16.0, v * 8.0, 16) * 0.05;// + 1.0; nuclear@0: nuclear@0: float x = sin(theta) * r; nuclear@0: float y = cos(theta) * r; nuclear@0: return Vector2(x, y); nuclear@0: } nuclear@0: nuclear@0: #define CLAMP(x, a, b) std::max(std::min(x, b), a) nuclear@0: nuclear@0: bool init() nuclear@0: { nuclear@0: if(init_opengl() == -1) { nuclear@0: return false; nuclear@0: } nuclear@0: Mesh::use_custom_sdr_attr = false; nuclear@0: nuclear@0: glEnable(GL_DEPTH_TEST); nuclear@0: glEnable(GL_CULL_FACE); nuclear@0: glEnable(GL_LIGHTING); nuclear@0: glEnable(GL_NORMALIZE); nuclear@0: nuclear@0: if(!(demo = dsys_open("data/demo.script"))) { nuclear@0: fprintf(stderr, "failed to load sequencing file\n"); nuclear@0: return false; nuclear@0: } nuclear@0: for(int i=0; i<3; i++) { nuclear@0: char name[16]; nuclear@0: sprintf(name, "ramp%d", i); nuclear@0: struct dsys_event *ev = dsys_event(demo, name); nuclear@0: if(ev) { nuclear@0: printf("found event: %s\n", name); nuclear@0: dsys_event_link(ev, ramp + i); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: nuclear@0: if(!(sdr_spot = create_program_load("sdr/default.v.glsl", "sdr/spot.p.glsl"))) { nuclear@0: return false; nuclear@0: } nuclear@0: nuclear@0: Matrix4x4 xform; nuclear@0: nuclear@0: scn = new Scene; nuclear@0: nuclear@0: Light *lt = new Light; nuclear@0: lt->pos = Vector3(-10, 10, 10); nuclear@0: scn->add_light(lt); nuclear@0: nuclear@0: // floor nuclear@0: Mesh *mesh = new Mesh; nuclear@0: gen_heightmap(mesh, 20, 20, 50, 50, ground_func); nuclear@0: xform.set_rotation(Vector3(-M_PI / 2.0, 0, 0)); nuclear@0: mesh->apply_xform(xform); nuclear@0: nuclear@0: Object *obj = new Object; nuclear@0: obj->set_mesh(mesh); nuclear@0: obj->xform().set_translation(Vector3(0, -0.9, 0)); nuclear@0: obj->mtl.diffuse = Vector3(0.7, 0.7, 0.7); nuclear@0: obj->set_shader(sdr_spot); nuclear@0: scn->add_object(obj); nuclear@0: nuclear@0: Image *img = new Image; nuclear@0: if(!img->load("data/grass02.jpg")) { nuclear@0: return false; nuclear@0: } nuclear@0: images.push_back(img); nuclear@0: obj->tex_xform().set_scaling(Vector3(5.0, 10.0, 1.0)); nuclear@0: obj->set_texture(img->texture()); nuclear@0: nuclear@0: // pumpkin texture nuclear@0: img = new Image; nuclear@0: if(!img->create(1024, 512)) { nuclear@0: return false; nuclear@0: } nuclear@0: images.push_back(img); nuclear@0: nuclear@0: static const Vector3 pkin_col = Vector3(0.824, 0.325, 0.063); nuclear@0: unsigned char *pptr = img->pixels; nuclear@0: for(int i=0; iheight; i++) { nuclear@0: float v = (float)i / (float)img->height; nuclear@0: for(int j=0; jwidth; j++) { nuclear@0: float u = (float)j / (float)img->width; nuclear@0: nuclear@0: float val = pfbm2(u * 64.0, v * 32.0, 3, 128) * 0.1 + 1.0; nuclear@0: val *= fabs(sin(u * M_PI * 12.0)) * 0.2 + 0.8; nuclear@0: Vector3 col = pkin_col * val; nuclear@0: nuclear@0: *pptr++ = (int)(CLAMP(col.x, 0.0, 1.0) * 255.0f); nuclear@0: *pptr++ = (int)(CLAMP(col.y, 0.0, 1.0) * 255.0f); nuclear@0: *pptr++ = (int)(CLAMP(col.z, 0.0, 1.0) * 255.0f); nuclear@0: *pptr++ = 255; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: // pumpkin nuclear@0: pkin_mesh = new Mesh; nuclear@0: gen_revol(pkin_mesh, 64, 20, pumpkin_func); nuclear@0: nuclear@0: pkin_obj = new Object; nuclear@0: pkin_obj->xform().set_rotation(Vector3(DEG_TO_RAD(-10), DEG_TO_RAD(90), 0)); nuclear@0: pkin_obj->set_mesh(pkin_mesh); nuclear@0: pkin_obj->set_texture(img->texture()); nuclear@0: obj->set_shader(sdr_spot); nuclear@0: scn->add_object(pkin_obj); nuclear@0: nuclear@0: int num_pumpkins = 20; nuclear@0: float dtheta = 1.0 / (float)num_pumpkins; nuclear@0: nuclear@0: for(int i=0; ixform().translate(Vector3(x, h - 0.5, y)); nuclear@0: obj->xform().rotate(Vector3(DEG_TO_RAD(rng_frand() * 40.0 - 20.0), rng_frand() * M_PI * 2.0, 0)); nuclear@0: obj->xform().scale(Vector3(0.7, 0.7, 0.7)); nuclear@0: obj->set_mesh(pkin_mesh); nuclear@0: obj->set_texture(img->texture()); nuclear@0: obj->set_shader(sdr_spot); nuclear@0: scn->add_object(obj); nuclear@0: } nuclear@0: nuclear@0: // pumpkin glow mask nuclear@0: img = new Image; nuclear@0: if(!img->load("data/pumpkin_mask_blured.png")) { nuclear@0: return false; nuclear@0: } nuclear@0: images.push_back(img); nuclear@0: pkin_tex = img->texture(); nuclear@0: nuclear@0: if(!init_audio()) { nuclear@0: fprintf(stderr, "failed to initialize audio\n"); nuclear@0: return false; nuclear@0: } nuclear@0: music = new OggVorbisStream; nuclear@0: if(!music->open("data/welcome_to_horrorland.ogg")) { nuclear@0: fprintf(stderr, "failed to open music\n"); nuclear@0: return false; nuclear@0: } nuclear@0: music->play(AUDIO_PLAYMODE_LOOP); nuclear@0: nuclear@0: return true; nuclear@0: } nuclear@0: nuclear@0: void cleanup() nuclear@0: { nuclear@0: music->stop(); nuclear@0: delete music; nuclear@0: destroy_audio(); nuclear@0: nuclear@0: delete scn; nuclear@0: nuclear@0: for(size_t i=0; idraw(); nuclear@0: nuclear@0: glPushAttrib(GL_ENABLE_BIT | GL_LIGHTING_BIT); nuclear@0: glDisable(GL_CULL_FACE); nuclear@0: nuclear@0: glDepthMask(0); nuclear@0: glEnable(GL_BLEND); nuclear@0: glBlendFunc(GL_SRC_ALPHA, GL_ONE); nuclear@0: nuclear@0: glBindTexture(GL_TEXTURE_2D, pkin_tex); nuclear@0: glEnable(GL_TEXTURE_2D); nuclear@0: nuclear@0: glMatrixMode(GL_MODELVIEW); nuclear@0: glPushMatrix(); nuclear@0: glMultTransposeMatrixf(pkin_obj->xform()[0]); nuclear@0: nuclear@0: num_shells = fbm1(sec * 2.0, 2) * 28.0 + 45; nuclear@0: nuclear@0: for(int i=0; idraw(); nuclear@0: } nuclear@0: glDepthMask(1); nuclear@0: nuclear@0: glPopMatrix(); nuclear@0: glPopAttrib(); nuclear@0: nuclear@0: nuclear@0: glutSwapBuffers(); nuclear@0: assert(glGetError() == GL_NO_ERROR); nuclear@0: } nuclear@0: nuclear@0: void idle() nuclear@0: { nuclear@0: glutPostRedisplay(); nuclear@0: } nuclear@0: nuclear@0: void reshape(int x, int y) nuclear@0: { nuclear@0: glViewport(0, 0, x, y); nuclear@0: nuclear@0: glMatrixMode(GL_PROJECTION); nuclear@0: glLoadIdentity(); nuclear@0: gluPerspective(50.0, (float)x / (float)y, 0.5, 500.0); nuclear@0: } nuclear@0: nuclear@0: void keyb(unsigned char key, int x, int y) nuclear@0: { nuclear@0: switch(key) { nuclear@0: case 27: nuclear@0: exit(0); nuclear@0: nuclear@0: case 'w': nuclear@0: wireframe = !wireframe; nuclear@0: break; nuclear@0: nuclear@0: case 'f': nuclear@0: case 'F': nuclear@0: { nuclear@0: static int prev_pos[2] = {50, 80}; nuclear@0: nuclear@0: fullscr = !fullscr; nuclear@0: if(fullscr) { nuclear@0: prev_pos[0] = glutGet(GLUT_WINDOW_X); nuclear@0: prev_pos[1] = glutGet(GLUT_WINDOW_Y); nuclear@0: glutFullScreen(); nuclear@0: } else { nuclear@0: glutPositionWindow(prev_pos[0], prev_pos[1]); nuclear@0: } nuclear@0: } nuclear@0: break; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: static int prev_x, prev_y; nuclear@0: static bool bnstate[16]; nuclear@0: nuclear@0: void mouse(int bn, int st, int x, int y) nuclear@0: { nuclear@0: prev_x = x; nuclear@0: prev_y = y; nuclear@0: bnstate[bn - GLUT_LEFT_BUTTON] = st == GLUT_DOWN; nuclear@0: nuclear@0: anim = !(st == GLUT_DOWN); nuclear@0: } nuclear@0: nuclear@0: void motion(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@0: if(!dx && !dy) return; nuclear@0: nuclear@0: if(bnstate[0]) { nuclear@0: //anim = false; nuclear@0: cam_theta += dx * 0.5; nuclear@0: cam_phi += dy * 0.5; nuclear@0: if(cam_phi < -90) cam_phi = -90; nuclear@0: if(cam_phi > 90) cam_phi = 90; nuclear@0: } nuclear@0: if(bnstate[2]) { nuclear@0: //anim = false; nuclear@0: cam_dist += dy * 0.1; nuclear@0: if(cam_dist < 0.0) cam_dist = 0.0; nuclear@0: } nuclear@0: }