dbf-halloween2015
diff src/main.cc @ 0:50683c78264e
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 01 Nov 2015 00:09:12 +0200 |
parents | |
children | 5ae5fd3626fa |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/main.cc Sun Nov 01 00:09:12 2015 +0200 1.3 @@ -0,0 +1,409 @@ 1.4 +#include <stdio.h> 1.5 +#include <stdlib.h> 1.6 +#include <assert.h> 1.7 +#include <vector> 1.8 +#include "opengl.h" 1.9 +#include <GL/glut.h> 1.10 +#include "scene.h" 1.11 +#include "meshgen.h" 1.12 +#include "pnoise.h" 1.13 +#include "image.h" 1.14 +#include "rng.h" 1.15 +#include "sdr.h" 1.16 +#include "audio/audio.h" 1.17 +#include "audio/ovstream.h" 1.18 +#include "dsys/dsys.h" 1.19 + 1.20 +bool init(); 1.21 +void cleanup(); 1.22 +void display(); 1.23 +void idle(); 1.24 +void reshape(int x, int y); 1.25 +void keyb(unsigned char key, int x, int y); 1.26 +void mouse(int bn, int st, int x, int y); 1.27 +void motion(int x, int y); 1.28 + 1.29 +float cam_theta, cam_phi = 25, cam_dist = 6; 1.30 +Scene *scn; 1.31 +bool wireframe; 1.32 +int num_shells = 64; 1.33 +float shell_scale = 1.015; 1.34 +bool anim = true; 1.35 +bool fullscr = true; 1.36 + 1.37 +static std::vector<Image*> images; 1.38 +static Object *pkin_obj; 1.39 +static Mesh *pkin_mesh; 1.40 +static unsigned int pkin_tex; 1.41 + 1.42 +static unsigned int sdr_spot; 1.43 + 1.44 +static float ramp[3]; 1.45 + 1.46 + 1.47 +static OggVorbisStream *music; 1.48 +static struct dsys_demo *demo; 1.49 + 1.50 + 1.51 +int main(int argc, char **argv) 1.52 +{ 1.53 + glutInit(&argc, argv); 1.54 + glutInitWindowSize(1280, 720); 1.55 + glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE); 1.56 + glutCreateWindow("DBF Halloween 2015 compo entry"); 1.57 + 1.58 + if(argv[1]) { 1.59 + if(strcmp(argv[1], "-w") == 0 || strcmp(argv[1], "-windowed") == 0) { 1.60 + fullscr = false; 1.61 + } else { 1.62 + fprintf(stderr, "unrecognized argument: %s\nUse -w or -windowed to run in a window\n", argv[1]); 1.63 + return 1; 1.64 + } 1.65 + } 1.66 + if(fullscr) { 1.67 + glutFullScreen(); 1.68 + } 1.69 + 1.70 + glutDisplayFunc(display); 1.71 + glutIdleFunc(idle); 1.72 + glutReshapeFunc(reshape); 1.73 + glutKeyboardFunc(keyb); 1.74 + glutMouseFunc(mouse); 1.75 + glutMotionFunc(motion); 1.76 + 1.77 + if(!init()) { 1.78 + return 1; 1.79 + } 1.80 + glutMainLoop(); 1.81 + return 0; 1.82 +} 1.83 + 1.84 +static float ground_func(float u, float v, void *cls) 1.85 +{ 1.86 + return fbm2(u * 3.0, v * 3.0, 2) * 0.8; 1.87 +} 1.88 + 1.89 +static Vector2 pumpkin_func(float u, float v, void *cls) 1.90 +{ 1.91 + float theta = v * M_PI; 1.92 + float r = sin(theta) * 0.5 + 0.5; 1.93 + 1.94 + // modulate a high-frequency short-amp wave along u to make the ribs(?) 1.95 + r += fabs(sin(u * M_PI * 12.0)) * 0.02;// + 1.0; 1.96 + 1.97 + // throw some noise in there for good measure 1.98 + r += pnoise2(u * 16.0, v * 8.0, 16) * 0.05;// + 1.0; 1.99 + 1.100 + float x = sin(theta) * r; 1.101 + float y = cos(theta) * r; 1.102 + return Vector2(x, y); 1.103 +} 1.104 + 1.105 +#define CLAMP(x, a, b) std::max<float>(std::min<float>(x, b), a) 1.106 + 1.107 +bool init() 1.108 +{ 1.109 + if(init_opengl() == -1) { 1.110 + return false; 1.111 + } 1.112 + Mesh::use_custom_sdr_attr = false; 1.113 + 1.114 + glEnable(GL_DEPTH_TEST); 1.115 + glEnable(GL_CULL_FACE); 1.116 + glEnable(GL_LIGHTING); 1.117 + glEnable(GL_NORMALIZE); 1.118 + 1.119 + if(!(demo = dsys_open("data/demo.script"))) { 1.120 + fprintf(stderr, "failed to load sequencing file\n"); 1.121 + return false; 1.122 + } 1.123 + for(int i=0; i<3; i++) { 1.124 + char name[16]; 1.125 + sprintf(name, "ramp%d", i); 1.126 + struct dsys_event *ev = dsys_event(demo, name); 1.127 + if(ev) { 1.128 + printf("found event: %s\n", name); 1.129 + dsys_event_link(ev, ramp + i); 1.130 + } 1.131 + } 1.132 + 1.133 + 1.134 + if(!(sdr_spot = create_program_load("sdr/default.v.glsl", "sdr/spot.p.glsl"))) { 1.135 + return false; 1.136 + } 1.137 + 1.138 + Matrix4x4 xform; 1.139 + 1.140 + scn = new Scene; 1.141 + 1.142 + Light *lt = new Light; 1.143 + lt->pos = Vector3(-10, 10, 10); 1.144 + scn->add_light(lt); 1.145 + 1.146 + // floor 1.147 + Mesh *mesh = new Mesh; 1.148 + gen_heightmap(mesh, 20, 20, 50, 50, ground_func); 1.149 + xform.set_rotation(Vector3(-M_PI / 2.0, 0, 0)); 1.150 + mesh->apply_xform(xform); 1.151 + 1.152 + Object *obj = new Object; 1.153 + obj->set_mesh(mesh); 1.154 + obj->xform().set_translation(Vector3(0, -0.9, 0)); 1.155 + obj->mtl.diffuse = Vector3(0.7, 0.7, 0.7); 1.156 + obj->set_shader(sdr_spot); 1.157 + scn->add_object(obj); 1.158 + 1.159 + Image *img = new Image; 1.160 + if(!img->load("data/grass02.jpg")) { 1.161 + return false; 1.162 + } 1.163 + images.push_back(img); 1.164 + obj->tex_xform().set_scaling(Vector3(5.0, 10.0, 1.0)); 1.165 + obj->set_texture(img->texture()); 1.166 + 1.167 + // pumpkin texture 1.168 + img = new Image; 1.169 + if(!img->create(1024, 512)) { 1.170 + return false; 1.171 + } 1.172 + images.push_back(img); 1.173 + 1.174 + static const Vector3 pkin_col = Vector3(0.824, 0.325, 0.063); 1.175 + unsigned char *pptr = img->pixels; 1.176 + for(int i=0; i<img->height; i++) { 1.177 + float v = (float)i / (float)img->height; 1.178 + for(int j=0; j<img->width; j++) { 1.179 + float u = (float)j / (float)img->width; 1.180 + 1.181 + float val = pfbm2(u * 64.0, v * 32.0, 3, 128) * 0.1 + 1.0; 1.182 + val *= fabs(sin(u * M_PI * 12.0)) * 0.2 + 0.8; 1.183 + Vector3 col = pkin_col * val; 1.184 + 1.185 + *pptr++ = (int)(CLAMP(col.x, 0.0, 1.0) * 255.0f); 1.186 + *pptr++ = (int)(CLAMP(col.y, 0.0, 1.0) * 255.0f); 1.187 + *pptr++ = (int)(CLAMP(col.z, 0.0, 1.0) * 255.0f); 1.188 + *pptr++ = 255; 1.189 + } 1.190 + } 1.191 + 1.192 + // pumpkin 1.193 + pkin_mesh = new Mesh; 1.194 + gen_revol(pkin_mesh, 64, 20, pumpkin_func); 1.195 + 1.196 + pkin_obj = new Object; 1.197 + pkin_obj->xform().set_rotation(Vector3(DEG_TO_RAD(-10), DEG_TO_RAD(90), 0)); 1.198 + pkin_obj->set_mesh(pkin_mesh); 1.199 + pkin_obj->set_texture(img->texture()); 1.200 + obj->set_shader(sdr_spot); 1.201 + scn->add_object(pkin_obj); 1.202 + 1.203 + int num_pumpkins = 20; 1.204 + float dtheta = 1.0 / (float)num_pumpkins; 1.205 + 1.206 + for(int i=0; i<num_pumpkins; i++) { 1.207 + float theta = (((float)i + rng_frand() * 0.5) * dtheta) * 2.0 * M_PI * 2.0; 1.208 + float r = 5.0 * (float)i / (float)num_pumpkins + 4.0; 1.209 + 1.210 + float x = cos(theta) * r; 1.211 + float y = sin(theta) * r; 1.212 + 1.213 + float tu = (x + 10.0) / 20.0; 1.214 + float tv = (10.0 - y) / 20.0; 1.215 + float h = ground_func(tu, tv, 0); 1.216 + 1.217 + obj = new Object; 1.218 + obj->xform().translate(Vector3(x, h - 0.5, y)); 1.219 + obj->xform().rotate(Vector3(DEG_TO_RAD(rng_frand() * 40.0 - 20.0), rng_frand() * M_PI * 2.0, 0)); 1.220 + obj->xform().scale(Vector3(0.7, 0.7, 0.7)); 1.221 + obj->set_mesh(pkin_mesh); 1.222 + obj->set_texture(img->texture()); 1.223 + obj->set_shader(sdr_spot); 1.224 + scn->add_object(obj); 1.225 + } 1.226 + 1.227 + // pumpkin glow mask 1.228 + img = new Image; 1.229 + if(!img->load("data/pumpkin_mask_blured.png")) { 1.230 + return false; 1.231 + } 1.232 + images.push_back(img); 1.233 + pkin_tex = img->texture(); 1.234 + 1.235 + if(!init_audio()) { 1.236 + fprintf(stderr, "failed to initialize audio\n"); 1.237 + return false; 1.238 + } 1.239 + music = new OggVorbisStream; 1.240 + if(!music->open("data/welcome_to_horrorland.ogg")) { 1.241 + fprintf(stderr, "failed to open music\n"); 1.242 + return false; 1.243 + } 1.244 + music->play(AUDIO_PLAYMODE_LOOP); 1.245 + 1.246 + return true; 1.247 +} 1.248 + 1.249 +void cleanup() 1.250 +{ 1.251 + music->stop(); 1.252 + delete music; 1.253 + destroy_audio(); 1.254 + 1.255 + delete scn; 1.256 + 1.257 + for(size_t i=0; i<images.size(); i++) { 1.258 + delete images[i]; 1.259 + } 1.260 + images.clear(); 1.261 +} 1.262 + 1.263 +void display() 1.264 +{ 1.265 + unsigned int msec = glutGet(GLUT_ELAPSED_TIME); 1.266 + float sec = (float)msec / 1000.0; 1.267 + 1.268 + dsys_update(demo, dsys_msec_to_dtime(msec)); 1.269 + if(!dsys_is_running(demo)) { 1.270 + exit(0); 1.271 + } 1.272 + 1.273 + float offs[3]; 1.274 + 1.275 + if(anim) { 1.276 + float t = sec * 0.5; 1.277 + cam_theta = cos(t) * 35.0;// + fbm1(t * 6.0, 1) * 2.0; 1.278 + cam_phi = sin(t * 2.0) * 10.0 + 25.0;// + fbm1(t * 8.0, 1) * 3.0; 1.279 + 1.280 + float mag = std::max(fmod(ramp[0], 1.0), std::max(fmod(ramp[1], 1.0), fmod(ramp[2], 1.0))) * 0.8 + 0.15; 1.281 + //printf("ramps: %g %g %g, mag: %g\n", ramp[0], ramp[1], ramp[2], mag); 1.282 + for(int i=0; i<3; i++) { 1.283 + offs[i] = turbulence1(sec * 4.0 + i, 2) * mag; 1.284 + } 1.285 + } 1.286 + 1.287 + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 1.288 + 1.289 + glMatrixMode(GL_MODELVIEW); 1.290 + glLoadIdentity(); 1.291 + glTranslatef(0, 0, -cam_dist); 1.292 + glRotatef(cam_phi, 1, 0, 0); 1.293 + glRotatef(cam_theta, 0, 1, 0); 1.294 + glTranslatef(offs[0], offs[1], offs[2]); 1.295 + 1.296 + scn->draw(); 1.297 + 1.298 + glPushAttrib(GL_ENABLE_BIT | GL_LIGHTING_BIT); 1.299 + glDisable(GL_CULL_FACE); 1.300 + 1.301 + glDepthMask(0); 1.302 + glEnable(GL_BLEND); 1.303 + glBlendFunc(GL_SRC_ALPHA, GL_ONE); 1.304 + 1.305 + glBindTexture(GL_TEXTURE_2D, pkin_tex); 1.306 + glEnable(GL_TEXTURE_2D); 1.307 + 1.308 + glMatrixMode(GL_MODELVIEW); 1.309 + glPushMatrix(); 1.310 + glMultTransposeMatrixf(pkin_obj->xform()[0]); 1.311 + 1.312 + num_shells = fbm1(sec * 2.0, 2) * 28.0 + 45; 1.313 + 1.314 + for(int i=0; i<num_shells; i++) { 1.315 + float x = (float)i / (float)num_shells; 1.316 + float alpha = 0.025 / (x * x); 1.317 + 1.318 + float black[] = {0, 0, 0, std::min(alpha, 1.0f) * 0.3f}; 1.319 + float glow_col[] = {0.7, 0.5, 0.25, 1.0}; 1.320 + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, black); 1.321 + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, black); 1.322 + glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, glow_col); 1.323 + 1.324 + glScalef(shell_scale, shell_scale, shell_scale); 1.325 + pkin_mesh->draw(); 1.326 + } 1.327 + glDepthMask(1); 1.328 + 1.329 + glPopMatrix(); 1.330 + glPopAttrib(); 1.331 + 1.332 + 1.333 + glutSwapBuffers(); 1.334 + assert(glGetError() == GL_NO_ERROR); 1.335 +} 1.336 + 1.337 +void idle() 1.338 +{ 1.339 + glutPostRedisplay(); 1.340 +} 1.341 + 1.342 +void reshape(int x, int y) 1.343 +{ 1.344 + glViewport(0, 0, x, y); 1.345 + 1.346 + glMatrixMode(GL_PROJECTION); 1.347 + glLoadIdentity(); 1.348 + gluPerspective(50.0, (float)x / (float)y, 0.5, 500.0); 1.349 +} 1.350 + 1.351 +void keyb(unsigned char key, int x, int y) 1.352 +{ 1.353 + switch(key) { 1.354 + case 27: 1.355 + exit(0); 1.356 + 1.357 + case 'w': 1.358 + wireframe = !wireframe; 1.359 + break; 1.360 + 1.361 + case 'f': 1.362 + case 'F': 1.363 + { 1.364 + static int prev_pos[2] = {50, 80}; 1.365 + 1.366 + fullscr = !fullscr; 1.367 + if(fullscr) { 1.368 + prev_pos[0] = glutGet(GLUT_WINDOW_X); 1.369 + prev_pos[1] = glutGet(GLUT_WINDOW_Y); 1.370 + glutFullScreen(); 1.371 + } else { 1.372 + glutPositionWindow(prev_pos[0], prev_pos[1]); 1.373 + } 1.374 + } 1.375 + break; 1.376 + } 1.377 +} 1.378 + 1.379 +static int prev_x, prev_y; 1.380 +static bool bnstate[16]; 1.381 + 1.382 +void mouse(int bn, int st, int x, int y) 1.383 +{ 1.384 + prev_x = x; 1.385 + prev_y = y; 1.386 + bnstate[bn - GLUT_LEFT_BUTTON] = st == GLUT_DOWN; 1.387 + 1.388 + anim = !(st == GLUT_DOWN); 1.389 +} 1.390 + 1.391 +void motion(int x, int y) 1.392 +{ 1.393 + int dx = x - prev_x; 1.394 + int dy = y - prev_y; 1.395 + prev_x = x; 1.396 + prev_y = y; 1.397 + 1.398 + if(!dx && !dy) return; 1.399 + 1.400 + if(bnstate[0]) { 1.401 + //anim = false; 1.402 + cam_theta += dx * 0.5; 1.403 + cam_phi += dy * 0.5; 1.404 + if(cam_phi < -90) cam_phi = -90; 1.405 + if(cam_phi > 90) cam_phi = 90; 1.406 + } 1.407 + if(bnstate[2]) { 1.408 + //anim = false; 1.409 + cam_dist += dy * 0.1; 1.410 + if(cam_dist < 0.0) cam_dist = 0.0; 1.411 + } 1.412 +}