MetaScene class
[laserbrain_demo] / src / app.cc
index 4fd3690..f92899d 100644 (file)
@@ -18,6 +18,7 @@
 #define FAR_CLIP       10000.0
 
 static void draw_scene();
+static void toggle_flight();
 
 long time_msec;
 int win_width, win_height;
@@ -34,7 +35,7 @@ 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;
@@ -42,10 +43,14 @@ static bool have_headtracking, 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.01;
 
 static Mat4 view_matrix, mouse_view_matrix, proj_matrix;
 static TextureSet texman;
-static Scene *scn;
+static SceneSet sceneman;
+static MetaScene *mscn;
 static unsigned int sdr_post_gamma;
 
 static long prev_msec;
@@ -93,20 +98,13 @@ bool app_init(int argc, char **argv)
 
        glClearColor(0.2, 0.2, 0.2, 1.0);
 
-       scn = new Scene(&texman);
-       if(!load_scene(scn, "data/museum.scene")) {
+       mscn = new MetaScene(&sceneman, &texman);
+       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);
-
-               floor_y = bcent.y;
-               cam_pos = bcent + Vec3(0, user_eye_height, 0);
-       }
+       cam_pos = mscn->start_pos;
+       // TODO use start_rot
 
        if(!(sdr_ltmap_notex = create_program_load("sdr/lightmap.v.glsl", "sdr/lightmap-notex.p.glsl"))) {
                return false;
@@ -136,12 +134,14 @@ void app_cleanup()
        if(opt.vr) {
                goatvr_shutdown();
        }
+
        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;
@@ -149,7 +149,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;
@@ -160,12 +160,38 @@ 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);
 
        float speed = walk_speed * dt;
        Vec3 dir;
 
+       // joystick
+       float jdeadsq = joy_deadzone * joy_deadzone;
+       float jmove_lensq = length_sq(joy_move);
+       float jlook_lensq = length_sq(joy_look);
+
+       if(jmove_lensq > jdeadsq) {
+               float len = sqrt(jmove_lensq);
+               jmove_lensq -= jdeadsq;
+
+               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;
+
+               float mag = len * len;
+               cam_theta += mag * joy_look.x / len * 200.0 * dt;
+               cam_phi += mag * joy_look.y / len * 100.0 * dt;
+               if(cam_phi < -90.0f) cam_phi = -90.0f;
+               if(cam_phi > 90.0f) cam_phi = 90.0f;
+       }
+
+       // keyboard move
        if(keystate[(int)'w']) {
                dir.z -= speed;
        }
@@ -178,10 +204,10 @@ static void update(float dt)
        if(keystate[(int)'a']) {
                dir.x -= speed;
        }
-       if(keystate[(int)'q']) {
+       if(keystate[(int)'q'] || gpad_bnstate[GPAD_UP]) {
                cam_pos.y += speed;
        }
-       if(keystate[(int)'z']) {
+       if(keystate[(int)'z'] || gpad_bnstate[GPAD_DOWN]) {
                cam_pos.y -= speed;
        }
 
@@ -300,9 +326,9 @@ 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();
+       mscn->draw();
 
-       if(show_walk_mesh && scn->walk_mesh) {
+       if(show_walk_mesh && mscn->walk_mesh) {
                glPushAttrib(GL_ENABLE_BIT);
                glEnable(GL_BLEND);
                glBlendFunc(GL_ONE, GL_ONE);
@@ -315,7 +341,7 @@ static void draw_scene()
                glDepthMask(0);
 
                glColor3f(0.3, 0.08, 0.01);
-               scn->walk_mesh->draw();
+               mscn->walk_mesh->draw();
 
                glDepthMask(1);
 
@@ -369,20 +395,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':
@@ -426,7 +439,7 @@ 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;
@@ -436,7 +449,7 @@ static inline void mouse_look(int dx, int dy)
        if(cam_phi > 90) cam_phi = 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;
@@ -467,3 +480,54 @@ void app_mouse_delta(int dx, int dy)
                mouse_look(dx * mouse_speed, dy * mouse_speed);
        }
 }
+
+void app_gamepad_axis(int axis, float val)
+{
+       switch(axis) {
+       case 0:
+               joy_move.x = val;
+               break;
+       case 1:
+               joy_move.y = val;
+               break;
+
+       case 2:
+               joy_look.x = val;
+               break;
+       case 3:
+               joy_look.y = val;
+               break;
+       }
+}
+
+void app_gamepad_button(int bn, bool pressed)
+{
+       gpad_bnstate[bn] = pressed;
+
+       if(pressed) {
+               switch(bn) {
+               case GPAD_LSTICK:
+                       toggle_flight();
+                       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");
+       }
+}