diff --git a/src/dawn/physics/3d/Ray3D.cpp b/src/dawn/physics/3d/Ray3D.cpp index ed8eb541..f83336ec 100644 --- a/src/dawn/physics/3d/Ray3D.cpp +++ b/src/dawn/physics/3d/Ray3D.cpp @@ -23,6 +23,9 @@ bool_t Dawn::raytestSphere( glm::vec3 *hit, glm::vec3 *normal ) { + assertNotNull(hit); + assertNotNull(normal); + glm::vec3 h, n; auto result = glm::intersectRaySphere( ray.origin, ray.direction, @@ -30,8 +33,8 @@ bool_t Dawn::raytestSphere( h, n ); - if(hit != nullptr) *hit = h; - if(normal != nullptr) *normal = n; + *hit = h; + *normal = n; return result; } @@ -39,19 +42,54 @@ bool_t Dawn::raytestSphere( bool_t Dawn::raytestTriangle( struct Ray3D ray, struct PhysicsTriangle triangle, - glm::vec2 *hit, - float_t *distance + glm::vec3 *hitPoint, + glm::vec3 *hitNormal, + float_t *hitDistance ) { - glm::vec2 h; - float_t d; - auto result = glm::intersectRayTriangle( - ray.origin, ray.direction, - triangle.v0, triangle.v1, triangle.v2, - h, d - ); - if(hit != nullptr) *hit = h; - if(distance != nullptr) *distance = d; - return result; + assertNotNull(hitPoint); + assertNotNull(hitNormal); + assertNotNull(hitDistance); + + // Calculate the normal of the triangle + glm::vec3 e0 = triangle.v1 - triangle.v0; + glm::vec3 e1 = triangle.v2 - triangle.v0; + glm::vec3 normal = glm::normalize(glm::cross(e0, e1)); + + // Calculate the denominator of the ray-triangle intersection formula + float_t denominator = glm::dot(normal, ray.direction); + + // If the denominator is zero, the ray and triangle are parallel and there is no intersection + if(denominator == 0) return -1; + + // Calculate the distance from the ray origin to the plane of the triangle + float_t d = glm::dot(triangle.v0 - ray.origin, normal) / denominator; + + // If the distance is negative, the intersection point is behind the ray origin and there is no intersection + if(d < 0) return -1; + + // Calculate the intersection point + glm::vec3 intersectionPoint = ray.origin + d * ray.direction; + + // Check if the intersection point is inside the triangle + glm::vec3 edge0 = triangle.v1 - triangle.v0; + glm::vec3 edge1 = triangle.v2 - triangle.v1; + glm::vec3 edge2 = triangle.v0 - triangle.v2; + glm::vec3 c0 = intersectionPoint - triangle.v0; + glm::vec3 c1 = intersectionPoint - triangle.v1; + glm::vec3 c2 = intersectionPoint - triangle.v2; + glm::vec3 n0 = glm::cross(edge0, c0); + glm::vec3 n1 = glm::cross(edge1, c1); + glm::vec3 n2 = glm::cross(edge2, c2); + if (glm::dot(n0, normal) >= 0 && glm::dot(n1, normal) >= 0 && glm::dot(n2, normal) >= 0) { + // If the intersection point is inside the triangle, set the hit point, normal and distance + *hitPoint = intersectionPoint; + *hitNormal = normal; + *hitDistance = d; + return true; + } + + // If the intersection point is outside the triangle, there is no intersection + return false; } bool_t Dawn::raytestAABB( diff --git a/src/dawn/physics/3d/Ray3D.hpp b/src/dawn/physics/3d/Ray3D.hpp index ea71dd95..022b9b6c 100644 --- a/src/dawn/physics/3d/Ray3D.hpp +++ b/src/dawn/physics/3d/Ray3D.hpp @@ -26,8 +26,9 @@ namespace Dawn { bool_t raytestTriangle( struct Ray3D ray, struct PhysicsTriangle triangle, - glm::vec2 *hit, - float_t *distance + glm::vec3 *hitPoint, + glm::vec3 *hitNormal, + float_t *hitDistance ); bool_t raytestAABB( diff --git a/src/dawn/scene/components/physics/3d/RayTester3D.cpp b/src/dawn/scene/components/physics/3d/RayTester3D.cpp index 6166811a..5dd08c09 100644 --- a/src/dawn/scene/components/physics/3d/RayTester3D.cpp +++ b/src/dawn/scene/components/physics/3d/RayTester3D.cpp @@ -18,8 +18,10 @@ void RayTester3D::onStart() { void RayTester3D::onUpdate() { prefab->transform.setLocalPosition(glm::vec3(0, 0, 0)); - box.max = glm::vec3( 0.5f, 0.5f, 0.5f); - box.min = glm::vec3(-0.5f, -0.5f, -0.5f); + + triangle.v0 = glm::vec3(-0.5f, -0.5f, 0); + triangle.v1 = glm::vec3(0.5f, -0.5f, 0); + triangle.v2 = glm::vec3(0, 0.5f, 0); auto mouse = this->getGame()->inputManager.getAxis2D(INPUT_BIND_MOUSE_X, INPUT_BIND_MOUSE_Y); mouse *= 2.0f; @@ -32,7 +34,7 @@ void RayTester3D::onUpdate() { // prefab->transform.setLocalPosition(pos); // ray.origin = glm::vec3(0, 0, 5); - bool_t x = raytestAABB(ray, box, &hit, &normal, &distance); + bool_t x = raytestTriangle(ray, triangle, &hit, &normal, &distance); if(x) { prefab->material->color = COLOR_RED; diff --git a/src/dawn/scene/components/physics/3d/RayTester3D.hpp b/src/dawn/scene/components/physics/3d/RayTester3D.hpp index 390a1746..099043f1 100644 --- a/src/dawn/scene/components/physics/3d/RayTester3D.hpp +++ b/src/dawn/scene/components/physics/3d/RayTester3D.hpp @@ -14,7 +14,7 @@ namespace Dawn { public: SimpleSpinningCubePrefab *prefab; Camera *camera; - struct AABB3D box; + struct PhysicsTriangle triangle; struct Ray3D ray; glm::vec3 hit; glm::vec3 normal; diff --git a/src/dawn/scene/components/physics/3d/collider/CubeCollider.cpp b/src/dawn/scene/components/physics/3d/collider/CubeCollider.cpp index 05a399cb..63a30344 100644 --- a/src/dawn/scene/components/physics/3d/collider/CubeCollider.cpp +++ b/src/dawn/scene/components/physics/3d/collider/CubeCollider.cpp @@ -9,8 +9,4 @@ using namespace Dawn; CubeCollider::CubeCollider(SceneItem *item) : Collider3D(item) { -} - -bool_t CubeCollider::raycast(struct Ray3D ray, struct Collider3DRayResult *out){ - return false; } \ No newline at end of file diff --git a/src/dawn/scene/components/physics/3d/collider/CubeCollider.hpp b/src/dawn/scene/components/physics/3d/collider/CubeCollider.hpp index 5971d941..5c9702aa 100644 --- a/src/dawn/scene/components/physics/3d/collider/CubeCollider.hpp +++ b/src/dawn/scene/components/physics/3d/collider/CubeCollider.hpp @@ -5,6 +5,7 @@ #pragma once #include "Collider3D.hpp" +#include "physics/3d/Ray3D.hpp" namespace Dawn { class CubeCollider : public Collider3D { @@ -13,7 +14,5 @@ namespace Dawn { glm::vec3 size = glm::vec3(1, 1, 1); CubeCollider(SceneItem *item); - - bool_t raycast(struct Ray3D ray, struct Collider3DRayResult *out)override; }; } \ No newline at end of file diff --git a/src/dawntictactoe/scenes/TicTacToeScene.hpp b/src/dawntictactoe/scenes/TicTacToeScene.hpp index 444ff876..4cae598f 100644 --- a/src/dawntictactoe/scenes/TicTacToeScene.hpp +++ b/src/dawntictactoe/scenes/TicTacToeScene.hpp @@ -7,7 +7,7 @@ #include "scene/Scene.hpp" #include "prefabs/SimpleSpinningCubePrefab.hpp" #include "prefabs/TicTacToeTilePrefab.hpp" -#include "display/mesh/SphereMesh.hpp" +#include "display/mesh/TriangleMesh.hpp" #include "scene/components/physics/3d/RayTester3D.hpp" @@ -31,6 +31,7 @@ namespace Dawn { camera->orthoRight = s * ratio; auto cube = SimpleSpinningCubePrefab::create(this); + TriangleMesh::createTriangleMesh(&cube->meshHost->mesh); // SphereMesh::createSphere(&cube->meshHost->mesh, 1.0f, 16, 16); auto tester = cube->addComponent(); tester->prefab = cube;