Add rudimentary collision detection

This commit is contained in:
2023-10-09 00:12:00 -04:00
parent 38dc495d36
commit ba05c09439
5 changed files with 136 additions and 12 deletions

View File

@@ -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

48
collisions.cpp Normal file
View File

@@ -0,0 +1,48 @@
#include <glm/glm.hpp>
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;
}

8
collisions.h Normal file
View File

@@ -0,0 +1,8 @@
#ifndef COLLISIONS_H
#define COLLISIONS_H
#include <glm/glm.hpp>
int getIntersection(glm::vec3 vec_start, glm::vec3 vec_stop, glm::vec3 P1, glm::vec3 P2, glm::vec3 P3);
#endif

BIN
maze.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

View File

@@ -12,6 +12,9 @@
#include <iostream>
#include <filesystem>
#include <vector>
#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)