dbf-halloween2015

annotate src/main.cc @ 3:c37fe5d8a4ed

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