diff --git a/FinalProject/mesh.cpp b/FinalProject/mesh.cpp index bcd149e..7edf097 100644 --- a/FinalProject/mesh.cpp +++ b/FinalProject/mesh.cpp @@ -53,3 +53,38 @@ void Mesh::setupMesh() { //_vao.setVertexAttributePointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)OFFSETOF(Vertex, _tangent)); //_vao.setVertexAttributePointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)OFFSETOF(Vertex, _bitangent)); } + +HitRecord Mesh::hit(const Ray& ray) const { + // Test whether the ray hits the mesh + + // Traverse the indices to test every triangle + for (int i = 0; i < _indices.size(); i += 3) { + // Get the three vertices of the triangle + Vertex v0 = _vertices[_indices[i]]; + Vertex v1 = _vertices[_indices[i + 1]]; + Vertex v2 = _vertices[_indices[i + 2]]; + + // Moller Trumbore algorithm + // https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm + glm::vec3 edge1 = v1._position - v0._position; + glm::vec3 edge2 = v2._position - v0._position; + glm::vec3 pvec = glm::cross(ray.direction(), edge2); + float det = glm::dot(edge1, pvec); + if (det < 0.0001f) continue; + float invDet = 1.0f / det; + glm::vec3 tvec = ray.origin() - v0._position; + float u = glm::dot(tvec, pvec) * invDet; + if (u < 0.0f || u > 1.0f) continue; + glm::vec3 qvec = glm::cross(tvec, edge1); + float v = glm::dot(ray.direction(), qvec) * invDet; + if (v < 0.0f || u + v > 1.0f) continue; + float t = glm::dot(edge2, qvec) * invDet; + if (t > 0.0001f) { + // Hit + glm::vec3 normal = glm::normalize(glm::cross(edge1, edge2)); + glm::vec3 hitPoint = ray.origin() + t * ray.direction(); + return HitRecord(hitPoint, normal); + } + } + return HitRecord(); +} diff --git a/FinalProject/mesh.h b/FinalProject/mesh.h index 86390ce..16c7bfd 100644 --- a/FinalProject/mesh.h +++ b/FinalProject/mesh.h @@ -6,6 +6,8 @@ #include "texture.h" #include "vao.h" #include "shader.h" +#include "ray.h" +#include "hitrecord.h" class Mesh { private: @@ -34,6 +36,7 @@ public: public: void render(const ShaderProgram& shader) const ; + HitRecord hit(const Ray& ray) const; private: void setupMesh();