#define FAR_CLIP 10000.0
static void draw_scene();
+static void toggle_flight();
long time_msec;
int win_width, win_height;
bool fb_srgb;
bool opt_gear_wireframe;
+TextureSet texman;
+SceneSet sceneman;
+
unsigned int sdr_ltmap, sdr_ltmap_notex;
static float cam_dist = 0.0;
-static float cam_theta, cam_phi = 20;
+static float cam_theta, cam_phi;
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 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 MetaScene *mscn;
static unsigned int sdr_post_gamma;
static long prev_msec;
glClearColor(0.2, 0.2, 0.2, 1.0);
- 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);
-
- floor_y = bcent.y;
- cam_pos = bcent + Vec3(0, user_eye_height, 0);
- }
+ cam_pos = mscn->start_pos;
+ Vec3 dir = rotate(Vec3(0, 0, 1), mscn->start_rot);
+ dir.y = 0;
+ cam_theta = rad_to_deg(acos(dot(dir, Vec3(0, 0, 1))));
if(!(sdr_ltmap_notex = create_program_load("sdr/lightmap.v.glsl", "sdr/lightmap-notex.p.glsl"))) {
return false;
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;
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;
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;
}
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;
}
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);
glDepthMask(0);
glColor3f(0.3, 0.08, 0.01);
- scn->walk_mesh->draw();
+ mscn->walk_mesh->draw();
glDepthMask(1);
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':
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;
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;
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");
+ }
+}