dbf-halloween2015

annotate 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
rev   line source
nuclear@0 1 #include <stdio.h>
nuclear@0 2 #include <stdlib.h>
nuclear@0 3 #include <assert.h>
nuclear@0 4 #include <vector>
nuclear@0 5 #include "opengl.h"
nuclear@0 6 #include <GL/glut.h>
nuclear@0 7 #include "scene.h"
nuclear@0 8 #include "meshgen.h"
nuclear@0 9 #include "pnoise.h"
nuclear@0 10 #include "image.h"
nuclear@0 11 #include "rng.h"
nuclear@0 12 #include "sdr.h"
nuclear@0 13 #include "audio/audio.h"
nuclear@0 14 #include "audio/ovstream.h"
nuclear@0 15 #include "dsys/dsys.h"
nuclear@0 16
nuclear@0 17 bool init();
nuclear@0 18 void cleanup();
nuclear@0 19 void display();
nuclear@0 20 void idle();
nuclear@0 21 void reshape(int x, int y);
nuclear@0 22 void keyb(unsigned char key, int x, int y);
nuclear@0 23 void mouse(int bn, int st, int x, int y);
nuclear@0 24 void motion(int x, int y);
nuclear@0 25
nuclear@0 26 float cam_theta, cam_phi = 25, cam_dist = 6;
nuclear@0 27 Scene *scn;
nuclear@0 28 bool wireframe;
nuclear@0 29 int num_shells = 64;
nuclear@0 30 float shell_scale = 1.015;
nuclear@0 31 bool anim = true;
nuclear@0 32 bool fullscr = true;
nuclear@0 33
nuclear@0 34 static std::vector<Image*> images;
nuclear@0 35 static Object *pkin_obj;
nuclear@0 36 static Mesh *pkin_mesh;
nuclear@0 37 static unsigned int pkin_tex;
nuclear@0 38
nuclear@0 39 static unsigned int sdr_spot;
nuclear@0 40
nuclear@0 41 static float ramp[3];
nuclear@0 42
nuclear@0 43
nuclear@0 44 static OggVorbisStream *music;
nuclear@0 45 static struct dsys_demo *demo;
nuclear@0 46
nuclear@0 47
nuclear@0 48 int main(int argc, char **argv)
nuclear@0 49 {
nuclear@0 50 glutInit(&argc, argv);
nuclear@0 51 glutInitWindowSize(1280, 720);
nuclear@0 52 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
nuclear@0 53 glutCreateWindow("DBF Halloween 2015 compo entry");
nuclear@0 54
nuclear@0 55 if(argv[1]) {
nuclear@0 56 if(strcmp(argv[1], "-w") == 0 || strcmp(argv[1], "-windowed") == 0) {
nuclear@0 57 fullscr = false;
nuclear@0 58 } else {
nuclear@0 59 fprintf(stderr, "unrecognized argument: %s\nUse -w or -windowed to run in a window\n", argv[1]);
nuclear@0 60 return 1;
nuclear@0 61 }
nuclear@0 62 }
nuclear@0 63 if(fullscr) {
nuclear@0 64 glutFullScreen();
nuclear@0 65 }
nuclear@0 66
nuclear@0 67 glutDisplayFunc(display);
nuclear@0 68 glutIdleFunc(idle);
nuclear@0 69 glutReshapeFunc(reshape);
nuclear@0 70 glutKeyboardFunc(keyb);
nuclear@0 71 glutMouseFunc(mouse);
nuclear@0 72 glutMotionFunc(motion);
nuclear@0 73
nuclear@0 74 if(!init()) {
nuclear@0 75 return 1;
nuclear@0 76 }
nuclear@0 77 glutMainLoop();
nuclear@0 78 return 0;
nuclear@0 79 }
nuclear@0 80
nuclear@0 81 static float ground_func(float u, float v, void *cls)
nuclear@0 82 {
nuclear@0 83 return fbm2(u * 3.0, v * 3.0, 2) * 0.8;
nuclear@0 84 }
nuclear@0 85
nuclear@0 86 static Vector2 pumpkin_func(float u, float v, void *cls)
nuclear@0 87 {
nuclear@0 88 float theta = v * M_PI;
nuclear@0 89 float r = sin(theta) * 0.5 + 0.5;
nuclear@0 90
nuclear@0 91 // modulate a high-frequency short-amp wave along u to make the ribs(?)
nuclear@0 92 r += fabs(sin(u * M_PI * 12.0)) * 0.02;// + 1.0;
nuclear@0 93
nuclear@0 94 // throw some noise in there for good measure
nuclear@0 95 r += pnoise2(u * 16.0, v * 8.0, 16) * 0.05;// + 1.0;
nuclear@0 96
nuclear@0 97 float x = sin(theta) * r;
nuclear@0 98 float y = cos(theta) * r;
nuclear@0 99 return Vector2(x, y);
nuclear@0 100 }
nuclear@0 101
nuclear@0 102 #define CLAMP(x, a, b) std::max<float>(std::min<float>(x, b), a)
nuclear@0 103
nuclear@0 104 bool init()
nuclear@0 105 {
nuclear@0 106 if(init_opengl() == -1) {
nuclear@0 107 return false;
nuclear@0 108 }
nuclear@0 109 Mesh::use_custom_sdr_attr = false;
nuclear@0 110
nuclear@0 111 glEnable(GL_DEPTH_TEST);
nuclear@0 112 glEnable(GL_CULL_FACE);
nuclear@0 113 glEnable(GL_LIGHTING);
nuclear@0 114 glEnable(GL_NORMALIZE);
nuclear@0 115
nuclear@0 116 if(!(demo = dsys_open("data/demo.script"))) {
nuclear@0 117 fprintf(stderr, "failed to load sequencing file\n");
nuclear@0 118 return false;
nuclear@0 119 }
nuclear@0 120 for(int i=0; i<3; i++) {
nuclear@0 121 char name[16];
nuclear@0 122 sprintf(name, "ramp%d", i);
nuclear@0 123 struct dsys_event *ev = dsys_event(demo, name);
nuclear@0 124 if(ev) {
nuclear@0 125 printf("found event: %s\n", name);
nuclear@0 126 dsys_event_link(ev, ramp + i);
nuclear@0 127 }
nuclear@0 128 }
nuclear@0 129
nuclear@0 130
nuclear@0 131 if(!(sdr_spot = create_program_load("sdr/default.v.glsl", "sdr/spot.p.glsl"))) {
nuclear@0 132 return false;
nuclear@0 133 }
nuclear@0 134
nuclear@0 135 Matrix4x4 xform;
nuclear@0 136
nuclear@0 137 scn = new Scene;
nuclear@0 138
nuclear@0 139 Light *lt = new Light;
nuclear@0 140 lt->pos = Vector3(-10, 10, 10);
nuclear@0 141 scn->add_light(lt);
nuclear@0 142
nuclear@0 143 // floor
nuclear@0 144 Mesh *mesh = new Mesh;
nuclear@0 145 gen_heightmap(mesh, 20, 20, 50, 50, ground_func);
nuclear@0 146 xform.set_rotation(Vector3(-M_PI / 2.0, 0, 0));
nuclear@0 147 mesh->apply_xform(xform);
nuclear@0 148
nuclear@0 149 Object *obj = new Object;
nuclear@0 150 obj->set_mesh(mesh);
nuclear@0 151 obj->xform().set_translation(Vector3(0, -0.9, 0));
nuclear@0 152 obj->mtl.diffuse = Vector3(0.7, 0.7, 0.7);
nuclear@0 153 obj->set_shader(sdr_spot);
nuclear@0 154 scn->add_object(obj);
nuclear@0 155
nuclear@0 156 Image *img = new Image;
nuclear@0 157 if(!img->load("data/grass02.jpg")) {
nuclear@0 158 return false;
nuclear@0 159 }
nuclear@0 160 images.push_back(img);
nuclear@0 161 obj->tex_xform().set_scaling(Vector3(5.0, 10.0, 1.0));
nuclear@0 162 obj->set_texture(img->texture());
nuclear@0 163
nuclear@0 164 // pumpkin texture
nuclear@0 165 img = new Image;
nuclear@0 166 if(!img->create(1024, 512)) {
nuclear@0 167 return false;
nuclear@0 168 }
nuclear@0 169 images.push_back(img);
nuclear@0 170
nuclear@0 171 static const Vector3 pkin_col = Vector3(0.824, 0.325, 0.063);
nuclear@0 172 unsigned char *pptr = img->pixels;
nuclear@0 173 for(int i=0; i<img->height; i++) {
nuclear@0 174 float v = (float)i / (float)img->height;
nuclear@0 175 for(int j=0; j<img->width; j++) {
nuclear@0 176 float u = (float)j / (float)img->width;
nuclear@0 177
nuclear@0 178 float val = pfbm2(u * 64.0, v * 32.0, 3, 128) * 0.1 + 1.0;
nuclear@0 179 val *= fabs(sin(u * M_PI * 12.0)) * 0.2 + 0.8;
nuclear@0 180 Vector3 col = pkin_col * val;
nuclear@0 181
nuclear@0 182 *pptr++ = (int)(CLAMP(col.x, 0.0, 1.0) * 255.0f);
nuclear@0 183 *pptr++ = (int)(CLAMP(col.y, 0.0, 1.0) * 255.0f);
nuclear@0 184 *pptr++ = (int)(CLAMP(col.z, 0.0, 1.0) * 255.0f);
nuclear@0 185 *pptr++ = 255;
nuclear@0 186 }
nuclear@0 187 }
nuclear@0 188
nuclear@0 189 // pumpkin
nuclear@0 190 pkin_mesh = new Mesh;
nuclear@0 191 gen_revol(pkin_mesh, 64, 20, pumpkin_func);
nuclear@0 192
nuclear@0 193 pkin_obj = new Object;
nuclear@0 194 pkin_obj->xform().set_rotation(Vector3(DEG_TO_RAD(-10), DEG_TO_RAD(90), 0));
nuclear@0 195 pkin_obj->set_mesh(pkin_mesh);
nuclear@0 196 pkin_obj->set_texture(img->texture());
nuclear@0 197 obj->set_shader(sdr_spot);
nuclear@0 198 scn->add_object(pkin_obj);
nuclear@0 199
nuclear@0 200 int num_pumpkins = 20;
nuclear@0 201 float dtheta = 1.0 / (float)num_pumpkins;
nuclear@0 202
nuclear@0 203 for(int i=0; i<num_pumpkins; i++) {
nuclear@0 204 float theta = (((float)i + rng_frand() * 0.5) * dtheta) * 2.0 * M_PI * 2.0;
nuclear@0 205 float r = 5.0 * (float)i / (float)num_pumpkins + 4.0;
nuclear@0 206
nuclear@0 207 float x = cos(theta) * r;
nuclear@0 208 float y = sin(theta) * r;
nuclear@0 209
nuclear@0 210 float tu = (x + 10.0) / 20.0;
nuclear@0 211 float tv = (10.0 - y) / 20.0;
nuclear@0 212 float h = ground_func(tu, tv, 0);
nuclear@0 213
nuclear@0 214 obj = new Object;
nuclear@0 215 obj->xform().translate(Vector3(x, h - 0.5, y));
nuclear@0 216 obj->xform().rotate(Vector3(DEG_TO_RAD(rng_frand() * 40.0 - 20.0), rng_frand() * M_PI * 2.0, 0));
nuclear@0 217 obj->xform().scale(Vector3(0.7, 0.7, 0.7));
nuclear@0 218 obj->set_mesh(pkin_mesh);
nuclear@0 219 obj->set_texture(img->texture());
nuclear@0 220 obj->set_shader(sdr_spot);
nuclear@0 221 scn->add_object(obj);
nuclear@0 222 }
nuclear@0 223
nuclear@0 224 // pumpkin glow mask
nuclear@0 225 img = new Image;
nuclear@0 226 if(!img->load("data/pumpkin_mask_blured.png")) {
nuclear@0 227 return false;
nuclear@0 228 }
nuclear@0 229 images.push_back(img);
nuclear@0 230 pkin_tex = img->texture();
nuclear@0 231
nuclear@0 232 if(!init_audio()) {
nuclear@0 233 fprintf(stderr, "failed to initialize audio\n");
nuclear@0 234 return false;
nuclear@0 235 }
nuclear@0 236 music = new OggVorbisStream;
nuclear@0 237 if(!music->open("data/welcome_to_horrorland.ogg")) {
nuclear@0 238 fprintf(stderr, "failed to open music\n");
nuclear@0 239 return false;
nuclear@0 240 }
nuclear@0 241 music->play(AUDIO_PLAYMODE_LOOP);
nuclear@0 242
nuclear@0 243 return true;
nuclear@0 244 }
nuclear@0 245
nuclear@0 246 void cleanup()
nuclear@0 247 {
nuclear@0 248 music->stop();
nuclear@0 249 delete music;
nuclear@0 250 destroy_audio();
nuclear@0 251
nuclear@0 252 delete scn;
nuclear@0 253
nuclear@0 254 for(size_t i=0; i<images.size(); i++) {
nuclear@0 255 delete images[i];
nuclear@0 256 }
nuclear@0 257 images.clear();
nuclear@0 258 }
nuclear@0 259
nuclear@0 260 void display()
nuclear@0 261 {
nuclear@0 262 unsigned int msec = glutGet(GLUT_ELAPSED_TIME);
nuclear@0 263 float sec = (float)msec / 1000.0;
nuclear@0 264
nuclear@0 265 dsys_update(demo, dsys_msec_to_dtime(msec));
nuclear@0 266 if(!dsys_is_running(demo)) {
nuclear@0 267 exit(0);
nuclear@0 268 }
nuclear@0 269
nuclear@0 270 float offs[3];
nuclear@0 271
nuclear@0 272 if(anim) {
nuclear@0 273 float t = sec * 0.5;
nuclear@0 274 cam_theta = cos(t) * 35.0;// + fbm1(t * 6.0, 1) * 2.0;
nuclear@0 275 cam_phi = sin(t * 2.0) * 10.0 + 25.0;// + fbm1(t * 8.0, 1) * 3.0;
nuclear@0 276
nuclear@0 277 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;
nuclear@0 278 //printf("ramps: %g %g %g, mag: %g\n", ramp[0], ramp[1], ramp[2], mag);
nuclear@0 279 for(int i=0; i<3; i++) {
nuclear@0 280 offs[i] = turbulence1(sec * 4.0 + i, 2) * mag;
nuclear@0 281 }
nuclear@0 282 }
nuclear@0 283
nuclear@0 284 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
nuclear@0 285
nuclear@0 286 glMatrixMode(GL_MODELVIEW);
nuclear@0 287 glLoadIdentity();
nuclear@0 288 glTranslatef(0, 0, -cam_dist);
nuclear@0 289 glRotatef(cam_phi, 1, 0, 0);
nuclear@0 290 glRotatef(cam_theta, 0, 1, 0);
nuclear@0 291 glTranslatef(offs[0], offs[1], offs[2]);
nuclear@0 292
nuclear@0 293 scn->draw();
nuclear@0 294
nuclear@0 295 glPushAttrib(GL_ENABLE_BIT | GL_LIGHTING_BIT);
nuclear@0 296 glDisable(GL_CULL_FACE);
nuclear@0 297
nuclear@0 298 glDepthMask(0);
nuclear@0 299 glEnable(GL_BLEND);
nuclear@0 300 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
nuclear@0 301
nuclear@0 302 glBindTexture(GL_TEXTURE_2D, pkin_tex);
nuclear@0 303 glEnable(GL_TEXTURE_2D);
nuclear@0 304
nuclear@0 305 glMatrixMode(GL_MODELVIEW);
nuclear@0 306 glPushMatrix();
nuclear@0 307 glMultTransposeMatrixf(pkin_obj->xform()[0]);
nuclear@0 308
nuclear@0 309 num_shells = fbm1(sec * 2.0, 2) * 28.0 + 45;
nuclear@0 310
nuclear@0 311 for(int i=0; i<num_shells; i++) {
nuclear@0 312 float x = (float)i / (float)num_shells;
nuclear@0 313 float alpha = 0.025 / (x * x);
nuclear@0 314
nuclear@0 315 float black[] = {0, 0, 0, std::min(alpha, 1.0f) * 0.3f};
nuclear@0 316 float glow_col[] = {0.7, 0.5, 0.25, 1.0};
nuclear@0 317 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, black);
nuclear@0 318 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, black);
nuclear@0 319 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, glow_col);
nuclear@0 320
nuclear@0 321 glScalef(shell_scale, shell_scale, shell_scale);
nuclear@0 322 pkin_mesh->draw();
nuclear@0 323 }
nuclear@0 324 glDepthMask(1);
nuclear@0 325
nuclear@0 326 glPopMatrix();
nuclear@0 327 glPopAttrib();
nuclear@0 328
nuclear@0 329
nuclear@0 330 glutSwapBuffers();
nuclear@0 331 assert(glGetError() == GL_NO_ERROR);
nuclear@0 332 }
nuclear@0 333
nuclear@0 334 void idle()
nuclear@0 335 {
nuclear@0 336 glutPostRedisplay();
nuclear@0 337 }
nuclear@0 338
nuclear@0 339 void reshape(int x, int y)
nuclear@0 340 {
nuclear@0 341 glViewport(0, 0, x, y);
nuclear@0 342
nuclear@0 343 glMatrixMode(GL_PROJECTION);
nuclear@0 344 glLoadIdentity();
nuclear@0 345 gluPerspective(50.0, (float)x / (float)y, 0.5, 500.0);
nuclear@0 346 }
nuclear@0 347
nuclear@0 348 void keyb(unsigned char key, int x, int y)
nuclear@0 349 {
nuclear@0 350 switch(key) {
nuclear@0 351 case 27:
nuclear@0 352 exit(0);
nuclear@0 353
nuclear@0 354 case 'w':
nuclear@0 355 wireframe = !wireframe;
nuclear@0 356 break;
nuclear@0 357
nuclear@0 358 case 'f':
nuclear@0 359 case 'F':
nuclear@0 360 {
nuclear@0 361 static int prev_pos[2] = {50, 80};
nuclear@0 362
nuclear@0 363 fullscr = !fullscr;
nuclear@0 364 if(fullscr) {
nuclear@0 365 prev_pos[0] = glutGet(GLUT_WINDOW_X);
nuclear@0 366 prev_pos[1] = glutGet(GLUT_WINDOW_Y);
nuclear@0 367 glutFullScreen();
nuclear@0 368 } else {
nuclear@0 369 glutPositionWindow(prev_pos[0], prev_pos[1]);
nuclear@0 370 }
nuclear@0 371 }
nuclear@0 372 break;
nuclear@0 373 }
nuclear@0 374 }
nuclear@0 375
nuclear@0 376 static int prev_x, prev_y;
nuclear@0 377 static bool bnstate[16];
nuclear@0 378
nuclear@0 379 void mouse(int bn, int st, int x, int y)
nuclear@0 380 {
nuclear@0 381 prev_x = x;
nuclear@0 382 prev_y = y;
nuclear@0 383 bnstate[bn - GLUT_LEFT_BUTTON] = st == GLUT_DOWN;
nuclear@0 384
nuclear@0 385 anim = !(st == GLUT_DOWN);
nuclear@0 386 }
nuclear@0 387
nuclear@0 388 void motion(int x, int y)
nuclear@0 389 {
nuclear@0 390 int dx = x - prev_x;
nuclear@0 391 int dy = y - prev_y;
nuclear@0 392 prev_x = x;
nuclear@0 393 prev_y = y;
nuclear@0 394
nuclear@0 395 if(!dx && !dy) return;
nuclear@0 396
nuclear@0 397 if(bnstate[0]) {
nuclear@0 398 //anim = false;
nuclear@0 399 cam_theta += dx * 0.5;
nuclear@0 400 cam_phi += dy * 0.5;
nuclear@0 401 if(cam_phi < -90) cam_phi = -90;
nuclear@0 402 if(cam_phi > 90) cam_phi = 90;
nuclear@0 403 }
nuclear@0 404 if(bnstate[2]) {
nuclear@0 405 //anim = false;
nuclear@0 406 cam_dist += dy * 0.1;
nuclear@0 407 if(cam_dist < 0.0) cam_dist = 0.0;
nuclear@0 408 }
nuclear@0 409 }