diff --git a/Makefile b/Makefile index ff9fea4..079ab69 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ -snowland: glad.o snowland.o stb_image.o - g++ -o snowland glad.o snowland.o stb_image.o -ldl -lglfw -std=c++17 +snowland: glad.o snowland.o stb_image.o collisions.o + g++ -o snowland glad.o snowland.o stb_image.o collisions.o -ldl -lglfw -std=c++17 glad.o: glad.c g++ -c -o glad.o glad.c @@ -10,5 +10,8 @@ snowland.o: snowland.cpp stb_image.o: stb_image.c g++ -c -o stb_image.o stb_image.c -std=c++17 +collisions.o: collisions.cpp + g++ -c -o collisions.o collisions.cpp -std=c++17 + clean: rm -f *.o snowland diff --git a/collisions.cpp b/collisions.cpp new file mode 100644 index 0000000..ce1c453 --- /dev/null +++ b/collisions.cpp @@ -0,0 +1,48 @@ +#include + +float abs(float x) { + if (x < 0) { + return -x; + } + return x; +} + +int signbit(float x) { + if (x < 0) { + return 1; + } + return 0; +} + +int getIntersection(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; + glm::vec3 v02 = P3 - P1; + glm::vec3 cross12 = glm::cross(v01, v02); + float det = glm::dot(lba, cross12); + if (abs(det) < 0.0000001) { + return 0; + } + + glm::vec3 diff_start = vec_start - P1; + float tn = glm::dot(cross12, diff_start); + if (signbit(tn) != signbit(det) || abs(det) < abs(tn)) { + return 0; + } + + glm::vec3 coefU = glm::cross(v02, lba); + float un = glm::dot(coefU, diff_start); + if (signbit(un) != signbit(det) || abs(det) < abs(un)) { + return 0; + } + + glm::vec3 coefV = glm::cross(lba, v01); + float vn = glm::dot(coefV, diff_start); + if (signbit(vn) != signbit(det) || abs(det) < abs(vn)) { + return 0; + } + + return 1; + +} diff --git a/collisions.h b/collisions.h new file mode 100644 index 0000000..e6e44d5 --- /dev/null +++ b/collisions.h @@ -0,0 +1,8 @@ +#ifndef COLLISIONS_H +#define COLLISIONS_H + +#include + +int getIntersection(glm::vec3 vec_start, glm::vec3 vec_stop, glm::vec3 P1, glm::vec3 P2, glm::vec3 P3); + +#endif diff --git a/maze.png b/maze.png new file mode 100644 index 0000000..a21986f Binary files /dev/null and b/maze.png differ diff --git a/snowland.cpp b/snowland.cpp index d9028d8..583515a 100644 --- a/snowland.cpp +++ b/snowland.cpp @@ -12,6 +12,9 @@ #include #include +#include + +#include "collisions.h" void framebuffer_size_callback(GLFWwindow* window, int width, int height); void mouse_callback(GLFWwindow* window, double xpos, double ypos); @@ -47,6 +50,68 @@ const char *viewposC = "viewPos"; const char *lightcolorC = "lightColor"; const char *objectcolorC = "objectColor"; +int num_walls; +float *wall_vertices; + +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] + ); +} + +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 * 10.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; + +} + int main() { glfwInit(); @@ -154,14 +219,13 @@ int main() fp = fopen("maze.txt", "r"); fscanf(fp, "%f %f %f %f\n", &player_pos.x, &player_pos.y, &player_pos.z, &yaw); - int num_surfaces; - fscanf(fp, "%d\n", &num_surfaces); + fscanf(fp, "%d\n", &num_walls); // num surfaces * 6 (vertices per point) * 6 (floats per point) // add 1 for floor - int num_walls = (num_surfaces) * 6 * 6; - float *wall_vertices = (float *)calloc(sizeof(float), num_surfaces * 6 * 6); + int num_walls = (num_walls) * 6 * 6; + wall_vertices = (float *)calloc(sizeof(float), num_walls * 6 * 6); // read walls - for (int i = 0; i < num_surfaces; i++) { + for (int i = 0; i < num_walls; i++) { for (int j = 0; j < 6; j++) { int vix = i*6*6 + j*6; fscanf( @@ -272,7 +336,7 @@ int main() glBindVertexArray(wallsVAO); glDrawArrays(GL_TRIANGLES, 0, num_walls); - glm::vec3 floor_color = glm::vec3(0.1f, 0.1f, 0.1f); + glm::vec3 floor_color = glm::vec3(0.0f, 0.0f, 0.0f); glUniform3fv(glGetUniformLocation(program, objectcolorC), 1, &floor_color[0]); glBindVertexArray(floorVAO); @@ -301,19 +365,20 @@ void processInput(GLFWwindow *window) glm::vec3 movement; if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) { movement = glm::vec3(camera_front.x, 0.0, camera_front.z); - player_pos += glm::normalize(movement) * camera_speed_adjusted; } else if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) { movement = glm::vec3(-camera_front.x, 0.0, -camera_front.z); - player_pos += glm::normalize(movement) * camera_speed_adjusted; } 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); - player_pos -= glm::normalize(movement) * camera_speed_adjusted; } 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); - player_pos += glm::normalize(movement) * camera_speed_adjusted; + } 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)