diff --git a/Makefile b/Makefile index 32fb71d..628ccdd 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ -ghostland: glad.o ghostland.o stb_image.o collisions.o - g++ -o ghostland glad.o ghostland.o stb_image.o collisions.o -ldl -lglfw -std=c++17 -O3 +ghostland: glad.o ghostland.o stb_image.o collisions.o player.o + g++ -o ghostland glad.o ghostland.o stb_image.o collisions.o player.o -ldl -lglfw -std=c++17 -O3 glad.o: glad.c g++ -c -o glad.o glad.c -O3 @@ -13,5 +13,8 @@ stb_image.o: stb_image.c collisions.o: collisions.cpp g++ -c -o collisions.o collisions.cpp -std=c++17 -O3 +player.o: player.cpp + g++ -c -o player.o player.cpp -std=c++17 -O3 + clean: rm -f *.o ghostland diff --git a/collisions.cpp b/collisions.cpp index ce1c453..819c2e4 100644 --- a/collisions.cpp +++ b/collisions.cpp @@ -14,7 +14,7 @@ int signbit(float x) { return 0; } -int getIntersection(glm::vec3 vec_start, glm::vec3 vec_stop, glm::vec3 P1, glm::vec3 P2, glm::vec3 P3) { +int get_intersection(glm::vec3 vec_start, glm::vec3 vec_stop, glm::vec3 P1, glm::vec3 P2, glm::vec3 P3) { glm::vec3 lba = vec_start - vec_stop; glm::vec3 v01 = P2 - P1; diff --git a/collisions.h b/collisions.h index e6e44d5..e78e65e 100644 --- a/collisions.h +++ b/collisions.h @@ -3,6 +3,6 @@ #include -int getIntersection(glm::vec3 vec_start, glm::vec3 vec_stop, glm::vec3 P1, glm::vec3 P2, glm::vec3 P3); +int get_intersection(glm::vec3 vec_start, glm::vec3 vec_stop, glm::vec3 P1, glm::vec3 P2, glm::vec3 P3); #endif diff --git a/ghostland.cpp b/ghostland.cpp index 8e4f3d9..c7b867b 100644 --- a/ghostland.cpp +++ b/ghostland.cpp @@ -14,41 +14,31 @@ #include #include "collisions.h" +#include "player.h" -glm::vec3 getNormalFromIndex(int ix); -glm::vec3 getVec3FromIndices(int ix, int jx); -glm::vec3 checkIntersection(glm::vec3 movement); void framebuffer_size_callback(GLFWwindow* window, int width, int height); void mouse_callback(GLFWwindow* window, double xpos, double ypos); void scroll_callback(GLFWwindow* window, double xoffset, double yoffset); -void processInput(GLFWwindow *window); int createShader(const char *filename, int shadertype); void set_light_front(int xoffset, int yoffset); +// player +Player *player; + // settings const unsigned int WINDOWWIDTH = 1600; const unsigned int WINDOWHEIGHT = 900; // camera -glm::vec3 player_pos = glm::vec3(0.0f, 0.0f, 3.0f); -glm::vec3 camera_front = glm::vec3(0.0f, 0.0f, -1.0f); -glm::vec3 camera_up = glm::vec3(0.0f, 1.0f, 0.0f); -glm::vec3 light_pos = glm::vec3(0.0f, 0.0f, 0.0f); -glm::vec3 light_front = glm::vec3(0.0f, 0.0f, -1.0f); - bool mousemove = false; -const float lightoffsetmax = 15.0f; float xpersist = 0.0f; float ypersist = 0.0f; -float persist_factor = 0.99f; -float offset_factor = 0.01f; bool first_mouse = true; float yaw = 0.0f; float pitch = 0.0f; float lastX = WINDOWWIDTH / 2.0; float lastY = WINDOWHEIGHT / 2.0; -float fov = 60.0f; float timed = 0.0f; float last_frame = 0.0f; @@ -71,7 +61,6 @@ const char *ambientC = "light.ambient"; const char *diffuseC = "light.diffuse"; const char *specularC = "light.specular"; - int num_walls; float *wall_vertices; @@ -81,17 +70,20 @@ int main(int argc, char *argv[]) { int success; + glm::vec3 position; FILE *fp = fopen("maze.txt", "r"); - float fakeyaw; - if (fscanf(fp, "%f %f %f %f\n", &player_pos.x, &player_pos.y, &player_pos.z, &fakeyaw) == EOF) { + float yaw; + if (fscanf(fp, "%f %f %f %f\n", &position.x, &position.y, &position.z, &yaw) == EOF) { printf("1st fscanf failed.\n"); return -1; } + player = new Player(position, yaw); if (fscanf(fp, "%d\n", &num_walls) == EOF) { printf("2nd fscanf failed.\n"); return -1; } + player->num_walls = num_walls; // num surfaces * 6 (vertices per point) * 6 (floats per point) int num_wall_vertices = num_walls * 6 * 6; wall_vertices = (float *)calloc(sizeof(float), num_wall_vertices); @@ -118,6 +110,27 @@ int main(int argc, char *argv[]) return -1; } } + player->wall_vertices = wall_vertices; + + // read floor + float *floor_vertices = (float *)calloc(sizeof(float), 6*6); + for (int j = 0; j < 6; j++) { + int vix = j*6; + if (fscanf( + fp, + "%f %f %f %f %f %f\n", + &floor_vertices[vix], + &floor_vertices[vix+1], + &floor_vertices[vix+2], + &floor_vertices[vix+3], + &floor_vertices[vix+4], + &floor_vertices[vix+5] + ) == EOF) { + printf("floor fscanf failed.\n"); + return -1; + } + } + fclose(fp); glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); @@ -184,26 +197,6 @@ int main(int argc, char *argv[]) glDeleteShader(vertex_shader); glDeleteShader(fragment_shader); - // read floor - float *floor_vertices = (float *)calloc(sizeof(float), 6*6); - for (int j = 0; j < 6; j++) { - int vix = j*6; - if (fscanf( - fp, - "%f %f %f %f %f %f\n", - &floor_vertices[vix], - &floor_vertices[vix+1], - &floor_vertices[vix+2], - &floor_vertices[vix+3], - &floor_vertices[vix+4], - &floor_vertices[vix+5] - ) == EOF) { - printf("floor fscanf failed.\n"); - return -1; - } - } - fclose(fp); - // do stuff for walls unsigned int wallsVBO, wallsVAO; glGenVertexArrays(1, &wallsVAO); @@ -294,7 +287,8 @@ int main(int argc, char *argv[]) int trail_ix = 0; int trail_sz = 0; - int time_sec = 0, num_frames = 0; + int time_secI = 0, num_frames = 1; + float time_sec; glm::vec3 wall_color = glm::vec3(0.61f, 0.6f, 0.59f); float wall_shininess = 6.5; glm::vec3 floor_color = glm::vec3(0.11f, 0.1f, 0.09f); @@ -310,15 +304,21 @@ int main(int argc, char *argv[]) { float current_frame = static_cast(glfwGetTime()); int current_frameI = (int)current_frame; - if (current_frameI != time_sec) { + if (current_frameI != time_secI) { + glm::vec3 player_pos = player->get_position(); + float yaw, pitch; + yaw = player->get_yaw(); + pitch = player->get_pitch(); printf("FPS: %d\n", num_frames); - time_sec = current_frameI; - num_frames = 0; + printf("Player is at: (%f, %f, %f) facing (%f, %f)\n", player_pos.x, player_pos.y, player_pos.z, yaw, pitch); + time_sec = current_frame; + time_secI = current_frameI; + num_frames = 1; trail_positions[trail_ix].x = player_pos.x; trail_positions[trail_ix].y = 6.5; trail_positions[trail_ix].z = player_pos.z; trail_angles[trail_ix] = yaw; - printf("Recorded trail %d: (%f, %f, %f) %f\n", trail_ix, trail_positions[trail_ix].x, trail_positions[trail_ix].y, trail_positions[trail_ix].z, yaw); + //printf("Recorded trail %d: (%f, %f, %f) %f\n", trail_ix, trail_positions[trail_ix].x, trail_positions[trail_ix].y, trail_positions[trail_ix].z, yaw); trail_ix = (trail_ix + 1) % trailmax; if (trail_sz < trailmax) { trail_sz++; @@ -331,32 +331,36 @@ int main(int argc, char *argv[]) mousemove = false; - processInput(window); + player->process_input(window); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glUseProgram(wall_program); + float fov = player->get_fov(); glm::mat4 projection = glm::perspective(glm::radians(fov), (float)WINDOWWIDTH / (float)WINDOWHEIGHT, 0.1f, 256.0f); glUniformMatrix4fv(glGetUniformLocation(wall_program, projectionC), 1, GL_FALSE, &projection[0][0]); - glm::mat4 view = glm::lookAt(player_pos, player_pos + camera_front, camera_up); + glm::vec3 camera_pos, camera_front, camera_up; + camera_pos = player->get_camera_pos(); + camera_front = player->get_camera_front(); + camera_up = player->get_camera_up(); + + glm::mat4 view = glm::lookAt(camera_pos, camera_pos + camera_front, camera_up); glUniformMatrix4fv(glGetUniformLocation(wall_program, viewC), 1, GL_FALSE, &view[0][0]); glm::mat4 model = glm::mat4(1.0f); glUniformMatrix4fv(glGetUniformLocation(wall_program, modelC), 1, GL_FALSE, &model[0][0]); // light position - float armlength = 0.50f; - float yawoffset = 90.0f; - float pitchoffset = -30.0f; - light_pos.x = player_pos.x + armlength * cos(glm::radians(yaw + yawoffset)) * cos(glm::radians(pitch + pitchoffset)); - light_pos.y = player_pos.y + armlength * sin(glm::radians(pitch + pitchoffset)); - light_pos.z = player_pos.z + armlength * sin(glm::radians(yaw + yawoffset)) * cos(glm::radians(pitch + pitchoffset)); + glm::vec3 light_pos = player->get_light_pos(); + //printf("light_pos: (%f, %f, %f)\n", light_pos.x, light_pos.y, light_pos.z); + glm::vec3 light_front = player->get_light_front(); + //printf("light_pos: (%f, %f, %f)\n", light_front.x, light_front.y, light_front.z); // fragment requirements - glUniform3fv(glGetUniformLocation(wall_program, viewposC), 1, &player_pos[0]); + glUniform3fv(glGetUniformLocation(wall_program, viewposC), 1, &camera_pos[0]); glUniform1f(glGetUniformLocation(wall_program, shininessC), wall_shininess); glUniform3fv(glGetUniformLocation(wall_program, colorC), 1, &wall_color[0]); glUniform3fv(glGetUniformLocation(wall_program, lightposC), 1, &light_pos[0]); @@ -375,10 +379,10 @@ int main(int argc, char *argv[]) glUniformMatrix4fv(glGetUniformLocation(floor_program, projectionC), 1, GL_FALSE, &projection[0][0]); glUniformMatrix4fv(glGetUniformLocation(floor_program, viewC), 1, GL_FALSE, &view[0][0]); glUniformMatrix4fv(glGetUniformLocation(floor_program, modelC), 1, GL_FALSE, &model[0][0]); - glUniform3fv(glGetUniformLocation(floor_program, viewposC), 1, &player_pos[0]); + glUniform3fv(glGetUniformLocation(floor_program, viewposC), 1, &camera_pos[0]); // fragment requirements - glUniform3fv(glGetUniformLocation(floor_program, viewposC), 1, &player_pos[0]); + glUniform3fv(glGetUniformLocation(floor_program, viewposC), 1, &camera_pos[0]); glUniform1f(glGetUniformLocation(floor_program, shininessC), floor_shininess); glUniform3fv(glGetUniformLocation(floor_program, colorC), 1, &floor_color[0]); glUniform3fv(glGetUniformLocation(floor_program, lightposC), 1, &light_pos[0]); @@ -409,13 +413,11 @@ int main(int argc, char *argv[]) glDrawArrays(GL_TRIANGLES, 0, 3 * 3 * 3); } + player->apply_movement(); + glfwSwapBuffers(window); glfwPollEvents(); - if (!mousemove) { - set_light_front(0.0f, 0.0f); - } - } glDeleteVertexArrays(1, &wallsVAO); @@ -428,88 +430,11 @@ int main(int argc, char *argv[]) return 0; } -void processInput(GLFWwindow *window) -{ - if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) - glfwSetWindowShouldClose(window, true); - - float camera_speed_adjusted = static_cast(camera_speed * timed); - glm::vec3 movement; - if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) { - movement = glm::vec3(camera_front.x, 0.0, camera_front.z); - } else if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) { - movement = glm::vec3(-camera_front.x, 0.0, -camera_front.z); - } else if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) { - glm::vec3 right = glm::cross(camera_front, camera_up); - movement = glm::vec3(-right.x, 0.0, -right.z); - } else if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) { - glm::vec3 right = glm::cross(camera_front, camera_up); - movement = glm::vec3(right.x, 0.0, right.z); - } else { - return; - } - movement = glm::normalize(movement) * camera_speed_adjusted; - movement = checkIntersection(movement); - player_pos += movement; -} - void framebuffer_size_callback(GLFWwindow* window, int width, int height) { glViewport(0, 0, width, height); } -void mouse_callback(GLFWwindow* window, double xpos_in, double ypos_in) -{ - - mousemove = true; - - float xpos = static_cast(xpos_in); - float ypos = static_cast(ypos_in); - - if (first_mouse) - { - lastX = xpos; - lastY = ypos; - first_mouse = false; - } - - float xoffset = xpos - lastX; - float yoffset = lastY - ypos; - lastX = xpos; - lastY = 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; - - 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); - - set_light_front(xoffset, yoffset); - -} - -void 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; -} - int createShader(const char *filename, int shadertype) { FILE* fp = fopen(filename, "r"); if (!fp) { @@ -543,87 +468,10 @@ int createShader(const char *filename, int shadertype) { return shader; } -glm::vec3 getNormalFromIndex(int ix) { - return glm::vec3( - wall_vertices[ix * 6 * 6 + 3], - wall_vertices[ix * 6 * 6 + 4], - wall_vertices[ix * 6 * 6 + 5] - ); +void mouse_callback(GLFWwindow* window, double xpos, double ypos) { + player->mouse_callback(window, xpos, ypos); } -glm::vec3 getVec3FromIndices(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 checkIntersection(glm::vec3 movement) { - - glm::vec3 vec_start, vec_stop, p1, p2, p3, res; - int gotX = 0, gotZ = 0; - vec_start = player_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++) { - glm::vec3 norm = getNormalFromIndex(ix); - if (gotX && gotZ) { - break; - } - if (!gotX) { - if ((movement.x > 0 && norm.x < 0) || (movement.x < 0 && norm.x > 0)) { - p1 = getVec3FromIndices(ix, 1); - p2 = getVec3FromIndices(ix, 0); - p3 = getVec3FromIndices(ix, 2); - if (getIntersection(vec_start, vec_stop, p1, p2, p3)) { - gotX = 1; - res.x = -movement.x; - } - } - } - if (!gotZ) { - if ((movement.z > 0 && norm.z < 0) || (movement.z < 0 && norm.z > 0)) { - p1 = getVec3FromIndices(ix, 1); - p2 = getVec3FromIndices(ix, 0); - p3 = getVec3FromIndices(ix, 2); - if (getIntersection(vec_start, vec_stop, p1, p2, p3)) { - gotZ = 1; - res.z = -movement.z; - } - } - } - } - - return res; - -} - -void set_light_front(int xoffset, int yoffset) { - - xoffset *= 128.0f; - yoffset *= 128.0f; - - xpersist = xpersist * persist_factor + xoffset * offset_factor; - if (xpersist > lightoffsetmax) { - xpersist = lightoffsetmax; - } else if (xpersist < -lightoffsetmax) { - xpersist = -lightoffsetmax; - } - ypersist = ypersist * persist_factor + yoffset * offset_factor; - if (ypersist > lightoffsetmax) { - ypersist = lightoffsetmax; - } else if (ypersist < -lightoffsetmax) { - ypersist = -lightoffsetmax; - } - float yawp = yaw + xpersist; - float pitchp = pitch + 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)); - light_front = normalize(front); +void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) { + player->scroll_callback(window, xoffset, yoffset); } diff --git a/player.cpp b/player.cpp new file mode 100644 index 0000000..6fcfa6f --- /dev/null +++ b/player.cpp @@ -0,0 +1,331 @@ +#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 curr_time = static_cast(glfwGetTime()); + + if (!first_frame) { + prev_move_time = curr_time; + first_frame = true; + return; + } + + float diff_time = curr_time - prev_move_time; + prev_move_time = curr_time; + + // 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 *= diff_time; + 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 += diff_time * 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; + } +} diff --git a/player.h b/player.h new file mode 100644 index 0000000..e5d0753 --- /dev/null +++ b/player.h @@ -0,0 +1,75 @@ +#ifndef PLAYER_H +#define PLAYER_H + +#include +#include +#include + +#include "collisions.h" + +const float lightoffsetmax = 15.0; +const float light_persist_factor = 0.99; +const float light_offset_factor = 0.01; +const float light_movement_multiplier = 128.0; +const float jumpvelocity = 8.104849; +const float vacceleration = -13.4058; +const float hvelocity = 10.0; + +class Player { + + + public: + + Player(glm::vec3 startpos, float startyaw); + + int num_walls; + float *wall_vertices; + + glm::vec3 get_position(); + glm::vec3 get_camera_front(); + glm::vec3 get_camera_up(); + glm::vec3 get_camera_pos(); + glm::vec3 get_light_pos(); + glm::vec3 get_light_front(); + float get_yaw(); + float get_pitch(); + float get_fov(); + + void mouse_callback(GLFWwindow *window, double xposI, double yposI); + void process_input(GLFWwindow *window); + void scroll_callback(GLFWwindow* window, double xoffset, double yoffset); + bool is_in_air(); + void apply_movement(); + + private: + float yaw; + float pitch; + float fov; + float prevx; + float prevy; + bool first_mouse; + bool first_frame; + float light_xpersist; + float light_ypersist; + float armlength; + float prev_move_time; + float mouse_xoffset; + float mouse_yoffset; + + glm::vec3 position; + glm::vec3 camera_front; + glm::vec3 camera_up; + glm::vec3 light_pos; + glm::vec3 light_front; + glm::vec3 velocity; + glm::vec3 camera_offset; + + void set_light_offset(float xoffset, float yoffset); + + glm::vec3 get_normal_from_index(int ix); + glm::vec3 get_vec3_from_indices(int ix, int jx); + glm::vec3 check_intersection(glm::vec3 movement); + +}; + +#endif