#include #include #include "player.h" Player::Player(glm::vec3 startpos, float startyaw) { position = startpos; yaw = startyaw; pitch = 0.0f; first_mouse = false; first_frame = false; light_xpersist = 0.0f; light_ypersist = 0.0f; armlength = 0.5f; camera_offset = glm::vec3(0.0f, 2.5f, 0.0f); camera_up = glm::vec3(0.0f, 1.0f, 0.0f); fov = 60.0f; velocity = glm::vec3(0.0f, 0.0f, 0.0f); } glm::vec3 Player::get_position() { return position; } glm::vec3 Player::get_camera_front() { return camera_front; } glm::vec3 Player::get_camera_up() { return camera_up; } glm::vec3 Player::get_camera_pos() { return position + camera_offset; } glm::vec3 Player::get_light_pos() { return get_camera_pos() + get_light_front() * armlength; } glm::vec3 Player::get_light_front() { float yawp = yaw + light_xpersist; float pitchp = pitch + light_ypersist; glm::vec3 front; front.x = cos(glm::radians(yawp)) * cos(glm::radians(pitchp)); front.y = sin(glm::radians(pitchp)); front.z = sin(glm::radians(yawp)) * cos(glm::radians(pitchp)); return normalize(front); } float Player::get_yaw() { return yaw; } float Player::get_pitch() { return pitch; } float Player::get_fov() { return fov; } void Player::mouse_callback(GLFWwindow* window, double xposI, double yposI) { float xpos = static_cast(xposI); float ypos = static_cast(yposI); if (first_mouse) { prevx = xpos; prevy = ypos; first_mouse = false; } float xoffset = xpos - prevx; float yoffset = prevy - ypos; prevx = xpos; prevy = ypos; float sensitivity = 0.1f; xoffset *= sensitivity; yoffset *= sensitivity; float prev_yaw = yaw; yaw += xoffset; pitch += yoffset; if (pitch > 89.0f) { pitch = 89.0f; } if (pitch < -89.0f) { pitch = -89.0f; } mouse_xoffset = xoffset; mouse_yoffset = yoffset; } void Player::process_input(GLFWwindow *window) { if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) { glfwSetWindowShouldClose(window, true); } bool W, A, S, D, space; if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) { W = true; } else { W = false; } if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) { S = true; } else { S = false; } if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) { A = true; } else { A = false; } if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) { D = true; } else { D = false; } if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS) { space = true; } else { space = false; } if (!is_in_air()) { glm::vec3 relvel; if (space) { velocity.y = jumpvelocity; return; } else { velocity.y = 0.0; } // intentionally don't update velocity if contradictory keys are pressed if (!W && !S) { relvel.z = 0.0; } else if (W) { relvel.z = 1.0; } else if (S) { relvel.z = -1.0; } if (!A && !D) { relvel.x = 0.0; } else if (A) { relvel.x = -1.0; } else if (D) { relvel.x = 1.0; } if (relvel.x == 0.0 && relvel.z == 0.0) { velocity.x = 0.0; velocity.z = 0.0; return; } relvel = glm::normalize(relvel); relvel *= hvelocity; float yawr = glm::radians(yaw); velocity.z = relvel.x * cos(yawr) + relvel.z * sin(yawr); velocity.x = -relvel.x * sin(yawr) + relvel.z * cos(yawr); } } bool Player::is_in_air() { return position.y > 0.0; } void Player::set_light_offset(float xoffset, float yoffset) { xoffset *= light_movement_multiplier; yoffset *= light_movement_multiplier; light_xpersist = light_xpersist * light_persist_factor + xoffset * light_offset_factor; if (light_xpersist > lightoffsetmax) { light_xpersist = lightoffsetmax; } else if (light_xpersist < -lightoffsetmax) { light_xpersist = -lightoffsetmax; } light_ypersist = light_ypersist * light_persist_factor + yoffset * light_offset_factor; if (light_ypersist > lightoffsetmax) { light_ypersist = lightoffsetmax; } else if (light_ypersist < -lightoffsetmax) { light_ypersist = -lightoffsetmax; } } void Player::apply_movement(float timed) { // mouse movement glm::vec3 front; front.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch)); front.y = sin(glm::radians(pitch)); front.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch)); camera_front = normalize(front); // light movement; set_light_offset(mouse_xoffset, mouse_yoffset); mouse_xoffset = 0.0; mouse_yoffset = 0.0; // positional movement glm::vec3 movement = velocity; movement *= timed; glm::vec3 intersected = check_intersection(movement); if (is_in_air()) { if (intersected.x == 0.0) { velocity.x = 0.0; } if (intersected.z == 0.0) { velocity.z = 0.0; } } else { // not in air if (intersected.x != movement.x) { intersected.x = -movement.x; } if (intersected.z != movement.z) { intersected.z = -movement.z; } } position.y += intersected.y; if (position.y <= 0.0f) { position.y = 0.0f; velocity.y = 0.0f; } else { velocity.y += timed * vacceleration; } position.x += intersected.x; position.z += intersected.z; } glm::vec3 Player::get_normal_from_index(int ix) { return glm::vec3( wall_vertices[ix * 6 * 6 + 3], wall_vertices[ix * 6 * 6 + 4], wall_vertices[ix * 6 * 6 + 5] ); } glm::vec3 Player::get_vec3_from_indices(int ix, int jx) { return glm::vec3( wall_vertices[ix * 6 * 6 + jx * 6], wall_vertices[ix * 6 * 6 + jx * 6 + 1], wall_vertices[ix * 6 * 6 + jx * 6 + 2] ); } glm::vec3 Player::check_intersection(glm::vec3 movement) { glm::vec3 vec_start, vec_stop, p1, p2, p3, res; bool gotX = false, gotZ = false; vec_start = get_camera_pos(); vec_stop = vec_start + movement * 20.0f; res.x = movement.x; res.y = movement.y; res.z = movement.z; for (int ix = 0; ix < num_walls; ix++) { if (gotX && gotZ) { break; } glm::vec3 norm = get_normal_from_index(ix); if (!gotX) { if ((movement.x > 0 && norm.x < 0) || (movement.x < 0 && norm.x > 0)) { p1 = get_vec3_from_indices(ix, 1); p2 = get_vec3_from_indices(ix, 0); p3 = get_vec3_from_indices(ix, 2); if (get_intersection(vec_start, vec_stop, p1, p2, p3)) { gotX = true; res.x = 0.0; } } } if (!gotZ) { if ((movement.z > 0 && norm.z < 0) || (movement.z < 0 && norm.z > 0)) { p1 = get_vec3_from_indices(ix, 1); p2 = get_vec3_from_indices(ix, 0); p3 = get_vec3_from_indices(ix, 2); if (get_intersection(vec_start, vec_stop, p1, p2, p3)) { gotZ = true; res.z = 0.0; } } } } return res; } void Player::scroll_callback(GLFWwindow* window, double xoffset, double yoffset) { fov -= (float)yoffset; if (fov < 1.0f) { fov = 1.0f; } if (fov > 90.0f) { fov = 90.0f; } }