Skip to content

Commit

Permalink
[Utils/Ray] Ray-triangle intersection gives the triangle's own normal
Browse files Browse the repository at this point in the history
- If the normal always remains in the ray's opposite direction, there is no way knowing if we hit the triangle from behind, which can be useful in some cases
  - Another solution, that might be used later, would be to give a negative distance in this case

- Added a Geogebra link for the ray-triangle intersection unit test
  • Loading branch information
Razakhel committed Jan 28, 2024
1 parent 3ce733d commit b9fe4b1
Show file tree
Hide file tree
Showing 3 changed files with 9 additions and 13 deletions.
8 changes: 1 addition & 7 deletions src/RaZ/Utils/Ray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,13 +139,7 @@ bool Ray::intersects(const Triangle& triangle, RayHit* hit) const {

if (hit) {
hit->position = m_origin + m_direction * hitDist;

const Vec3f normal = firstEdge.cross(secondEdge).normalize();

// We want the normal facing the ray, not the opposite direction (no culling)
// This may not be the ideal behavior; this may change when a real use case will be available
hit->normal = (normal.dot(m_direction) > 0.f ? -normal : normal);

hit->normal = firstEdge.cross(secondEdge).normalize(); // Directly computing the normal using the already calculated triangle's edges
hit->distance = hitDist;
}

Expand Down
4 changes: 2 additions & 2 deletions tests/src/RaZ/Data/BvhSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ TEST_CASE("BvhSystem query") {
CHECK(entity == &mesh1);
CHECK(hit.position == Raz::Vec3f(0.f, 0.f, 0.25f));
CHECK_THROWS(triangle1.contains(hit.position)); // TODO: wait for the triangle's point containment check to be available
CHECK(hit.normal == -triangle1.computeNormal());
CHECK(hit.normal == triangle1.computeNormal());
CHECK(hit.distance == 1.414213538f);

// Same as the above, but in the opposite direction
Expand All @@ -249,7 +249,7 @@ TEST_CASE("BvhSystem query") {
CHECK(entity == &mesh2);
CHECK(hit.position == Raz::Vec3f(0.f, 0.375f, 0.f));
CHECK_THROWS(triangle2.contains(hit.position)); // TODO: wait for the triangle's point containment check to be available
CHECK(hit.normal == -triangle2.computeNormal());
CHECK(hit.normal == triangle2.computeNormal());
CHECK(hit.distance == 1.414213538f);

// If the ray hits nothing, a null pointer is returned
Expand Down
10 changes: 6 additions & 4 deletions tests/src/RaZ/Utils/Ray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ TEST_CASE("Ray-sphere intersection") {
}

TEST_CASE("Ray-triangle intersection") {
// See: https://www.geogebra.org/m/e8uqvjwh

// These triangles are defined so that:
// - triangle1 is laying flat slightly above 0
// - triangle2 is standing, parallel to the Y/Z plane (facing the X direction)
Expand All @@ -168,12 +170,12 @@ TEST_CASE("Ray-triangle intersection") {

CHECK(ray1.intersects(triangle1, &hit));
CHECK(hit.position == Raz::Vec3f(0.f, 0.5f, 0.f));
CHECK(hit.normal == -Raz::Axis::Y);
CHECK(hit.normal == Raz::Axis::Y);
CHECK(hit.distance == 0.5f);

CHECK(ray2.intersects(triangle1, &hit));
CHECK(hit.position == Raz::Vec3f(0.5f, 0.5f, 0.f));
CHECK(hit.normal == -Raz::Axis::Y);
CHECK(hit.normal == Raz::Axis::Y);
CHECK_THAT(hit.distance, IsNearlyEqualTo(2.1213205f));

CHECK(ray3.intersects(triangle1, &hit));
Expand All @@ -185,7 +187,7 @@ TEST_CASE("Ray-triangle intersection") {

CHECK(ray2.intersects(triangle2, &hit));
CHECK(hit.position == Raz::Vec3f(0.5f, 0.5f, 0.f));
CHECK(hit.normal == -Raz::Axis::X);
CHECK(hit.normal == Raz::Axis::X);
CHECK_THAT(hit.distance, IsNearlyEqualTo(2.1213202f));

CHECK(ray3.intersects(triangle2, &hit));
Expand All @@ -200,7 +202,7 @@ TEST_CASE("Ray-triangle intersection") {
CHECK(ray3.intersects(triangle3, &hit));
// The second point is almost aligned with the ray; see https://www.geogebra.org/m/g4pumzwu
CHECK_THAT(hit.position, IsNearlyEqualToVector(Raz::Vec3f(-1.5000002f, -1.5000002f, 0.f)));
CHECK_THAT(hit.normal, IsNearlyEqualToVector(Raz::Vec3f(-0.077791f, 0.9334918f, -0.3500594f)));
CHECK_THAT(hit.normal, IsNearlyEqualToVector(Raz::Vec3f(0.077791f, -0.9334918f, 0.3500594f)));
CHECK_THAT(hit.distance, IsNearlyEqualTo(3.5355341f));
}

Expand Down

0 comments on commit b9fe4b1

Please sign in to comment.