X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=laserbrain_demo;a=blobdiff_plain;f=src%2Fapp.cc;h=7f6f077e294268b3281719c571114d08fcbea263;hp=59c8f077133c2d64aa24bd70af88244cfc5b82f7;hb=fb11663a3654acd0132e71e5652e35b0ea72d544;hpb=13c9481b0430d0bf6fc50b0952bcd81229022abc diff --git a/src/app.cc b/src/app.cc index 59c8f07..7f6f077 100644 --- a/src/app.cc +++ b/src/app.cc @@ -13,11 +13,18 @@ #include "ui.h" #include "opt.h" #include "post.h" +#include "renderer.h" +#include "avatar.h" +#include "vrinput.h" +#include "exman.h" +#include "blob_exhibit.h" #define NEAR_CLIP 5.0 #define FAR_CLIP 10000.0 static void draw_scene(); +static void toggle_flight(); +static void calc_framerate(); long time_msec; int win_width, win_height; @@ -25,33 +32,44 @@ float win_aspect; bool fb_srgb; bool opt_gear_wireframe; +TextureSet texman; +SceneSet sceneman; + unsigned int sdr_ltmap, sdr_ltmap_notex; +static Avatar avatar; + static float cam_dist = 0.0; -static float cam_theta, cam_phi = 20; -static Vec3 cam_pos; static float floor_y; // last floor height static float user_eye_height = 165; static float walk_speed = 300.0f; -static float mouse_speed = 1.0f; +static float mouse_speed = 0.5f; static bool show_walk_mesh, noclip = false; -static bool have_headtracking, should_swap; +static bool have_headtracking, have_handtracking, should_swap; static int prev_mx, prev_my; static bool bnstate[8]; static bool keystate[256]; +static bool gpad_bnstate[64]; static Vec2 joy_move, joy_look; -static float joy_deadzone = 0.1; +static float joy_deadzone = 0.01; + +static float framerate; static Mat4 view_matrix, mouse_view_matrix, proj_matrix; -static TextureSet texman; -static Scene *scn; +static MetaScene *mscn; static unsigned int sdr_post_gamma; static long prev_msec; +static ExhibitManager *exman; +static BlobExhibit *blobs; +static bool show_blobs; + +static Renderer *rend; + bool app_init(int argc, char **argv) { @@ -72,6 +90,7 @@ bool app_init(int argc, char **argv) should_swap = goatvr_should_swap() != 0; user_eye_height = goatvr_get_eye_height(); have_headtracking = goatvr_have_headtracking(); + have_handtracking = goatvr_have_handtracking(); goatvr_recenter(); } @@ -93,57 +112,93 @@ bool app_init(int argc, char **argv) float ambient[] = {0.0, 0.0, 0.0, 0.0}; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient); - glClearColor(0.2, 0.2, 0.2, 1.0); + glClearColor(1, 1, 1, 1); + + init_audio(); + + if(!init_vrhands()) { + return false; + } - scn = new Scene(&texman); - if(!load_scene(scn, "data/museum.scene")) { + mscn = new MetaScene; + if(!mscn->load(opt.scenefile ? opt.scenefile : "data/museum.scene")) { return false; } - // set initial cam_pos above the center of the walk mesh (if any) - if(scn->walk_mesh) { - Vec3 bcent; - float brad; - scn->walk_mesh->get_bsphere(&bcent, &brad); + avatar.pos = mscn->start_pos; + Vec3 dir = rotate(Vec3(0, 0, 1), mscn->start_rot); + dir.y = 0; + avatar.body_rot = rad_to_deg(acos(dot(dir, Vec3(0, 0, 1)))); - floor_y = bcent.y; - cam_pos = bcent + Vec3(0, user_eye_height, 0); + exman = new ExhibitManager; + if(!exman->load(mscn, "data/exhibits")) { + //return false; } + blobs = new BlobExhibit; + blobs->node = new SceneNode; + blobs->init(); + blobs->node->set_position(Vec3(-680, 160, -100)); + blobs->node->set_scaling(Vec3(28, 28, 28)); + blobs->node->update(0); + + exman->add(blobs); + if(!(sdr_ltmap_notex = create_program_load("sdr/lightmap.v.glsl", "sdr/lightmap-notex.p.glsl"))) { return false; } + set_uniform_int(sdr_ltmap_notex, "texmap", MTL_TEX_DIFFUSE); + set_uniform_int(sdr_ltmap_notex, "lightmap", MTL_TEX_LIGHTMAP); if(!(sdr_ltmap = create_program_load("sdr/lightmap.v.glsl", "sdr/lightmap-tex.p.glsl"))) { return false; } - set_uniform_int(sdr_ltmap, "texmap", 0); - set_uniform_int(sdr_ltmap, "lightmap", 1); + set_uniform_int(sdr_ltmap, "texmap", MTL_TEX_DIFFUSE); + set_uniform_int(sdr_ltmap, "lightmap", MTL_TEX_LIGHTMAP); if(!fb_srgb) { sdr_post_gamma = create_program_load("sdr/post_gamma.v.glsl", "sdr/post_gamma.p.glsl"); } + rend = new Renderer; + rend->set_scene(mscn); + glUseProgram(0); if(opt.vr || opt.fullscreen) { app_grab_mouse(true); } + + if(mscn->music) { + mscn->music->play(AUDIO_PLAYMODE_LOOP); + } return true; } void app_cleanup() { + if(mscn->music) { + mscn->music->stop(); + } + destroy_audio(); + app_grab_mouse(false); if(opt.vr) { goatvr_shutdown(); } + destroy_vrhands(); + + delete rend; + + delete exman; + texman.clear(); + sceneman.clear(); } static bool constrain_walk_mesh(const Vec3 &v, Vec3 *newv) { - Mesh *wm = scn->walk_mesh; + Mesh *wm = mscn->walk_mesh; if(!wm) { *newv = v; return true; @@ -151,7 +206,7 @@ static bool constrain_walk_mesh(const Vec3 &v, Vec3 *newv) Ray downray = Ray(v, Vec3(0, -1, 0)); HitPoint hit; - if(scn->walk_mesh->intersect(downray, &hit)) { + if(mscn->walk_mesh->intersect(downray, &hit)) { *newv = hit.pos; newv->y += user_eye_height; return true; @@ -162,8 +217,10 @@ static bool constrain_walk_mesh(const Vec3 &v, Vec3 *newv) static void update(float dt) { texman.update(); + sceneman.update(); - scn->update(dt); + mscn->update(dt); + exman->update(dt); float speed = walk_speed * dt; Vec3 dir; @@ -177,17 +234,19 @@ static void update(float dt) float len = sqrt(jmove_lensq); jmove_lensq -= jdeadsq; - dir.x += joy_move.x / len * speed; - dir.z += joy_move.y / len * speed; + float mag = len * len; + dir.x += mag * joy_move.x / len * 2.0 * speed; + dir.z += mag * joy_move.y / len * 2.0 * speed; } if(jlook_lensq > jdeadsq) { float len = sqrt(jlook_lensq); jlook_lensq -= jdeadsq; - cam_theta += joy_look.x / len * mouse_speed * 2.0; - cam_phi += joy_look.y / len * mouse_speed * 1.0; - if(cam_phi < -90.0f) cam_phi = -90.0f; - if(cam_phi > 90.0f) cam_phi = 90.0f; + float mag = len * len; + avatar.body_rot += mag * joy_look.x / len * 200.0 * dt; + avatar.head_alt += mag * joy_look.y / len * 100.0 * dt; + if(avatar.head_alt < -90.0f) avatar.head_alt = -90.0f; + if(avatar.head_alt > 90.0f) avatar.head_alt = 90.0f; } // keyboard move @@ -203,52 +262,58 @@ static void update(float dt) if(keystate[(int)'a']) { dir.x -= speed; } - if(keystate[(int)'q']) { - cam_pos.y += speed; + if(keystate[(int)'q'] || gpad_bnstate[GPAD_UP]) { + avatar.pos.y += speed; } - if(keystate[(int)'z']) { - cam_pos.y -= speed; + if(keystate[(int)'z'] || gpad_bnstate[GPAD_DOWN]) { + avatar.pos.y -= speed; } - float theta = M_PI * cam_theta / 180.0f; + float theta = M_PI * avatar.body_rot / 180.0f; Vec3 newpos; - newpos.x = cam_pos.x + cos(theta) * dir.x - sin(theta) * dir.z; - newpos.y = cam_pos.y; - newpos.z = cam_pos.z + sin(theta) * dir.x + cos(theta) * dir.z; + newpos.x = avatar.pos.x + cos(theta) * dir.x - sin(theta) * dir.z; + newpos.y = avatar.pos.y; + newpos.z = avatar.pos.z + sin(theta) * dir.x + cos(theta) * dir.z; if(noclip) { - cam_pos = newpos; + avatar.pos = newpos; } else { - if(!constrain_walk_mesh(newpos, &cam_pos)) { + if(!constrain_walk_mesh(newpos, &avatar.pos)) { float dtheta = M_PI / 32.0; float theta = dtheta; - Vec2 dir2d = newpos.xz() - cam_pos.xz(); + Vec2 dir2d = newpos.xz() - avatar.pos.xz(); for(int i=0; i<16; i++) { Vec2 dvec = rotate(dir2d, theta); - Vec3 pos = cam_pos + Vec3(dvec.x, 0, dvec.y); - if(constrain_walk_mesh(pos, &cam_pos)) { + Vec3 pos = avatar.pos + Vec3(dvec.x, 0, dvec.y); + if(constrain_walk_mesh(pos, &avatar.pos)) { break; } dvec = rotate(dir2d, -theta); - pos = cam_pos + Vec3(dvec.x, 0, dvec.y); - if(constrain_walk_mesh(pos, &cam_pos)) { + pos = avatar.pos + Vec3(dvec.x, 0, dvec.y); + if(constrain_walk_mesh(pos, &avatar.pos)) { break; } theta += dtheta; } } - floor_y = cam_pos.y - user_eye_height; + floor_y = avatar.pos.y - user_eye_height; } + // TODO move to avatar // calculate mouselook view matrix mouse_view_matrix = Mat4::identity; mouse_view_matrix.pre_translate(0, 0, -cam_dist); if(!have_headtracking) { - mouse_view_matrix.pre_rotate_x(deg_to_rad(cam_phi)); + mouse_view_matrix.pre_rotate_x(deg_to_rad(avatar.head_alt)); + } + mouse_view_matrix.pre_rotate_y(deg_to_rad(avatar.body_rot)); + mouse_view_matrix.pre_translate(-avatar.pos.x, -avatar.pos.y, -avatar.pos.z); + + // update hand-tracking + if(have_handtracking) { + update_vrhands(&avatar); } - mouse_view_matrix.pre_rotate_y(deg_to_rad(cam_theta)); - mouse_view_matrix.pre_translate(-cam_pos.x, -cam_pos.y, -cam_pos.z); } static void set_light(int idx, const Vec3 &pos, const Vec3 &color) @@ -268,13 +333,13 @@ void app_display() float dt = (float)(time_msec - prev_msec) / 1000.0f; prev_msec = time_msec; - update(dt); - if(opt.vr) { // VR mode goatvr_draw_start(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + update(dt); + for(int i=0; i<2; i++) { // for each eye goatvr_draw_eye(i); @@ -288,6 +353,9 @@ void app_display() glLoadMatrixf(view_matrix[0]); draw_scene(); + if(have_handtracking) { + draw_vrhands(); + } } goatvr_draw_done(); @@ -298,6 +366,8 @@ void app_display() } else { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + update(dt); + proj_matrix.perspective(deg_to_rad(50.0), win_aspect, NEAR_CLIP, FAR_CLIP); glMatrixMode(GL_PROJECTION); glLoadMatrixf(proj_matrix[0]); @@ -315,6 +385,8 @@ void app_display() app_swap_buffers(); } assert(glGetError() == GL_NO_ERROR); + + calc_framerate(); } @@ -325,9 +397,45 @@ static void draw_scene() set_light(1, lpos[1], Vec3(0.6, 0.7, 1.0) * 0.6); set_light(2, lpos[2], Vec3(0.8, 1.0, 0.8) * 0.3); - scn->draw(); + rend->draw(); + + if(show_blobs) { + blobs->draw(); + } + + /* + if(have_handtracking) { + Mat4 head_xform = inverse(mouse_view_matrix);//goatvr_head_matrix(); + Mat4 head_dir_xform = head_xform.upper3x3(); - if(show_walk_mesh && scn->walk_mesh) { + glUseProgram(0); + glPushAttrib(GL_ENABLE_BIT); + glDisable(GL_LIGHTING); + glBegin(GL_LINES); + for(int i=0; i<2; i++) { + if(hand[i].valid) { + glColor3f(i, 1 - i, i); + } else { + glColor3f(0.5, 0.5, 0.5); + } + Vec3 v = head_xform * hand[i].pos; + Vec3 dir = head_dir_xform * rotate(Vec3(0, 0, -1), hand[i].rot) * 20.0f; + Vec3 up = head_dir_xform * rotate(Vec3(0, 1, 0), hand[i].rot) * 10.0f; + Vec3 right = head_dir_xform * rotate(Vec3(1, 0, 0), hand[i].rot) * 10.0f; + + glVertex3f(v.x, v.y, v.z); + glVertex3f(v.x + dir.x, v.y + dir.y, v.z + dir.z); + glVertex3f(v.x - right.x, v.y - right.y, v.z - right.z); + glVertex3f(v.x + right.x, v.y + right.y, v.z + right.z); + glVertex3f(v.x - up.x, v.y - up.y, v.z - up.z); + glVertex3f(v.x + up.x, v.y + up.y, v.z + up.z); + } + glEnd(); + glPopAttrib(); + } + */ + + if(show_walk_mesh && mscn->walk_mesh) { glPushAttrib(GL_ENABLE_BIT); glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE); @@ -340,13 +448,14 @@ static void draw_scene() glDepthMask(0); glColor3f(0.3, 0.08, 0.01); - scn->walk_mesh->draw(); + mscn->walk_mesh->draw(); glDepthMask(1); glPopAttrib(); } + print_text(Vec2(9 * win_width / 10, 20), Vec3(1, 1, 0), "fps: %.1f", framerate); draw_ui(); } @@ -394,20 +503,7 @@ void app_keyboard(int key, bool pressed) break; case 'f': - { - static float prev_walk_speed = -1.0; - if(prev_walk_speed < 0.0) { - noclip = true; - prev_walk_speed = walk_speed; - walk_speed = 1000.0; - show_message("fly mode\n"); - } else { - noclip = false; - walk_speed = prev_walk_speed; - prev_walk_speed = -1.0; - show_message("walk mode\n"); - } - } + toggle_flight(); break; case 'p': @@ -436,6 +532,16 @@ void app_keyboard(int key, bool pressed) mouse_speed *= 0.8; show_message("mouse speed: %g", mouse_speed); break; + + case 'b': + show_blobs = !show_blobs; + show_message("blobs: %s\n", show_blobs ? "on" : "off"); + break; + + case ' ': + goatvr_recenter(); + show_message("VR recenter\n"); + break; } } @@ -451,17 +557,17 @@ void app_mouse_button(int bn, bool pressed, int x, int y) bnstate[bn] = pressed; } -static inline void mouse_look(int dx, int dy) +static inline void mouse_look(float dx, float dy) { float scrsz = (float)win_height; - cam_theta += dx * 512.0 / scrsz; - cam_phi += dy * 512.0 / scrsz; + avatar.body_rot += dx * 512.0 / scrsz; + avatar.head_alt += dy * 512.0 / scrsz; - if(cam_phi < -90) cam_phi = -90; - if(cam_phi > 90) cam_phi = 90; + if(avatar.head_alt < -90) avatar.head_alt = -90; + if(avatar.head_alt > 90) avatar.head_alt = 90; } -static void mouse_zoom(int dx, int dy) +static void mouse_zoom(float dx, float dy) { cam_dist += dy * 0.1; if(cam_dist < 0.0) cam_dist = 0.0; @@ -514,4 +620,63 @@ void app_gamepad_axis(int axis, float val) void app_gamepad_button(int bn, bool pressed) { + gpad_bnstate[bn] = pressed; + + if(pressed) { + switch(bn) { + case GPAD_LSTICK: + toggle_flight(); + break; + + case GPAD_X: + show_blobs = !show_blobs; + show_message("blobs: %s\n", show_blobs ? "on" : "off"); + break; + + case GPAD_START: + goatvr_recenter(); + show_message("VR recenter\n"); + break; + + default: + break; + } + } +} + +static void toggle_flight() +{ + static float prev_walk_speed = -1.0; + if(prev_walk_speed < 0.0) { + noclip = true; + prev_walk_speed = walk_speed; + walk_speed = 1000.0; + show_message("fly mode\n"); + } else { + noclip = false; + walk_speed = prev_walk_speed; + prev_walk_speed = -1.0; + show_message("walk mode\n"); + } +} + +static void calc_framerate() +{ + static int ncalc; + static int nframes; + static long prev_upd; + + long elapsed = time_msec - prev_upd; + if(elapsed >= 1000) { + framerate = (float)nframes / (float)(elapsed * 0.001); + nframes = 1; + prev_upd = time_msec; + + /*if(++ncalc >= 5) { + printf("fps: %f\n", framerate); + ncalc = 0; + }*/ + } else { + ++nframes; + } }