#include #include #include "GLTB/geom/intersection.h" TEST(Intersection, raySphere) { gltb::Ray ray(glm::vec3(0.5f, 0.5f, -3), glm::vec3(0, 0, 1)); gltb::Sphere sphere(glm::vec3(0, 0, 0), 1); glm::vec3 position; float lambda; // expect a hit bool result = gltb::intersects(sphere, ray, position, lambda); ASSERT_TRUE(result); // expect a miss ray.start.x = 10; result = gltb::intersects(sphere, ray, position, lambda); ASSERT_FALSE(result); } TEST(Intersection, rayAABB) { gltb::AABB aabb(glm::vec3(-10, -10, -10), glm::vec3(5, 5, 5)); gltb::Ray ray(glm::vec3(-20, 0, 0), glm::vec3(1, 0, 0)); float tMin, tMax; bool result; float tMinInvDir, tMaxInvDir; bool resultInvDir; glm::vec3 invDir; // expect a hit result = gltb::intersects(aabb, ray, tMin, tMax); ASSERT_TRUE(result); invDir = 1.0f / ray.direction; resultInvDir = gltb::intersects(aabb, ray, tMinInvDir, tMaxInvDir); ASSERT_EQ(result, resultInvDir); ASSERT_FLOAT_EQ(tMinInvDir, tMin); ASSERT_FLOAT_EQ(tMaxInvDir, tMax); // expect a miss ray.start.y = - 20; result = gltb::intersects(aabb, ray, tMin, tMax); ASSERT_FALSE(result); invDir = 1.0f / ray.direction; resultInvDir = gltb::intersects(aabb, ray, tMinInvDir, tMaxInvDir); ASSERT_EQ(result, resultInvDir); ASSERT_FLOAT_EQ(tMinInvDir, tMin); ASSERT_FLOAT_EQ(tMaxInvDir, tMax); } TEST(Intersection, _intersectsEdgeIsVisible_VisibleEdge) { glm::vec2 projectedSphereCenter(1, 1); glm::vec2 corner(2, 2); glm::vec2 normal(-1, 0); ASSERT_TRUE(gltb::_intersectsEdgeIsVisible(projectedSphereCenter, corner, normal)); } TEST(Intersection, _intersectsEdgeIsVisible_InvisibleEdge) { glm::vec2 projectedSphereCenter(1, 1); glm::vec2 corner(2, 2); glm::vec2 normal(1, 0); ASSERT_FALSE(gltb::_intersectsEdgeIsVisible(projectedSphereCenter, corner, normal)); } TEST(Intersection, _intersectsFindVisibleEdges_Edge0Only) { glm::vec2 corners[4] = { glm::vec2(-1, 1), glm::vec2(1, 1), glm::vec2(1, 2), glm::vec2(-1, 2) }; glm::vec2 projectedSphereCenter(0, 0); int numVisibleEdges; int visibleEdges[2]; numVisibleEdges = gltb::_intersectsFindVisibleEdges(projectedSphereCenter, corners, visibleEdges, false); ASSERT_EQ(1, numVisibleEdges); ASSERT_EQ(0, visibleEdges[0]); } TEST(Intersection, _intersectsFindVisibleEdges_Edge0Only_FlippedNormals) { glm::vec2 corners[4] = { glm::vec2(1, 1), glm::vec2(-1, 1), glm::vec2(-1, 2), glm::vec2(1, 2), }; glm::vec2 projectedSphereCenter(0, 0); int numVisibleEdges; int visibleEdges[2]; numVisibleEdges = gltb::_intersectsFindVisibleEdges(projectedSphereCenter, corners, visibleEdges, true); ASSERT_EQ(1, numVisibleEdges); ASSERT_EQ(0, visibleEdges[0]); } TEST(Intersection, _intersectsFindVisibleEdges_Edge0AndEdge1) { glm::vec2 corners[4] = { glm::vec2(-1, 1), glm::vec2(1, 1), glm::vec2(4, 2), glm::vec2(2, 2) }; glm::vec2 projectedSphereCenter(0, 0); int numVisibleEdges; int visibleEdges[2]; numVisibleEdges = gltb::_intersectsFindVisibleEdges(projectedSphereCenter, corners, visibleEdges, false); ASSERT_EQ(2, numVisibleEdges); ASSERT_EQ(0, visibleEdges[0]); ASSERT_EQ(1, visibleEdges[1]); } TEST(Intersection, _intersectsFindVisibleEdges_Edge2Only) { glm::vec2 corners[4] = { glm::vec2(1, -2), glm::vec2(-1, -2), glm::vec2(-1, -1), glm::vec2(1, -1), }; glm::vec2 projectedSphereCenter(0, 0); int numVisibleEdges; int visibleEdges[2]; numVisibleEdges = gltb::_intersectsFindVisibleEdges(projectedSphereCenter, corners, visibleEdges, true); ASSERT_EQ(1, numVisibleEdges); ASSERT_EQ(2, visibleEdges[0]); } TEST(Intersection, _intersectsFindVisibleEdges_Edge2AndEdge3) { glm::vec2 corners[4] = { glm::vec2(4, -2), glm::vec2(2, -2), glm::vec2(-1, -1), glm::vec2(1, -1), }; glm::vec2 projectedSphereCenter(0, 0); int numVisibleEdges; int visibleEdges[2]; numVisibleEdges = gltb::_intersectsFindVisibleEdges(projectedSphereCenter, corners, visibleEdges, true); ASSERT_EQ(2, numVisibleEdges); ASSERT_EQ(2, visibleEdges[0]); ASSERT_EQ(3, visibleEdges[1]); } TEST(Intersection, _intersectSquareDistanceToEdge_DistanceToLine) { glm::vec3 a(-1, 1, 0); glm::vec3 b(1, 1, 0); ASSERT_FLOAT_EQ(1, gltb::_intersectsSquareDistanceToEdge(a, b)); } TEST(Intersection, _intersectSquareDistanceToEdge_DistanceToPointA) { glm::vec3 a(1, 1, 0); glm::vec3 b(2, 1, 0); ASSERT_FLOAT_EQ(2, gltb::_intersectsSquareDistanceToEdge(a, b)); } TEST(Intersection, _intersectSquareDistanceToEdge_DistanceToPointB) { glm::vec3 a(2, 1, 0); glm::vec3 b(1, 1, 0); ASSERT_FLOAT_EQ(2, gltb::_intersectsSquareDistanceToEdge(a, b)); } TEST(Intersection, _intersectsProjectFace_AlongX) { glm::vec3 corners[] = { glm::vec3(1, -1, -1), glm::vec3(1, 1, -1), glm::vec3(1, 1, 1), glm::vec3(-1, 1, 1), }; glm::vec3 faceNormal(-1, 0, 0); glm::vec2 projectedSphereCenter; glm::vec2 projectedCorners[4]; bool flipNormals = false; gltb::_intersectsProjectFace(corners, faceNormal, projectedSphereCenter, projectedCorners, flipNormals); for(int i = 0; i < 4; i++) { ASSERT_EQ(corners[i][1], projectedCorners[i][0]); ASSERT_EQ(corners[i][2], projectedCorners[i][1]); } ASSERT_EQ(0, projectedSphereCenter.x); ASSERT_EQ(0, projectedSphereCenter.y); ASSERT_FALSE(flipNormals); } TEST(Intersection, _intersectsProjectFace_AlongX_FlipNormal) { glm::vec3 corners[] = { glm::vec3(1, -1, -1), glm::vec3(1, 1, -1), glm::vec3(1, 1, 1), glm::vec3(-1, 1, 1), }; glm::vec3 faceNormal(1, 0, 0); glm::vec2 projectedSphereCenter; glm::vec2 projectedCorners[4]; bool flipNormals = false; gltb::_intersectsProjectFace(corners, faceNormal, projectedSphereCenter, projectedCorners, flipNormals); for(int i = 0; i < 4; i++) { ASSERT_EQ(corners[i][1], projectedCorners[i][0]); ASSERT_EQ(corners[i][2], projectedCorners[i][1]); } ASSERT_EQ(0, projectedSphereCenter.x); ASSERT_EQ(0, projectedSphereCenter.y); ASSERT_TRUE(flipNormals); } TEST(Intersection, _intersectsProjectFace_AlongY) { glm::vec3 corners[] = { glm::vec3(-1, 1, -1), glm::vec3(1, 1, -1), glm::vec3(1, 1, 1), glm::vec3(-1, 1, 1), }; glm::vec3 faceNormal(0, -1, 0); glm::vec2 projectedSphereCenter; glm::vec2 projectedCorners[4]; bool flipNormals = false; gltb::_intersectsProjectFace(corners, faceNormal, projectedSphereCenter, projectedCorners, flipNormals); for(int i = 0; i < 4; i++) { ASSERT_EQ(corners[i][0], projectedCorners[i][0]); ASSERT_EQ(corners[i][2], projectedCorners[i][1]); } ASSERT_EQ(0, projectedSphereCenter.x); ASSERT_EQ(0, projectedSphereCenter.y); ASSERT_FALSE(flipNormals); } TEST(Intersection, _intersectsProjectFace_AlongY_FlipNormal) { glm::vec3 corners[] = { glm::vec3(-1, 1, -1), glm::vec3(1, 1, -1), glm::vec3(1, 1, 1), glm::vec3(-1, 1, 1), }; glm::vec3 faceNormal(0, 1, 0); glm::vec2 projectedSphereCenter; glm::vec2 projectedCorners[4]; bool flipNormals = false; gltb::_intersectsProjectFace(corners, faceNormal, projectedSphereCenter, projectedCorners, flipNormals); for(int i = 0; i < 4; i++) { ASSERT_EQ(corners[i][0], projectedCorners[i][0]); ASSERT_EQ(corners[i][2], projectedCorners[i][1]); } ASSERT_EQ(0, projectedSphereCenter.x); ASSERT_EQ(0, projectedSphereCenter.y); ASSERT_TRUE(flipNormals); } TEST(Intersection, _intersectsProjectFace_AlongZ) { glm::vec3 corners[] = { glm::vec3(-1, -1, 1), glm::vec3(1, -1, 1), glm::vec3(1, 1, 1), glm::vec3(-1, 1, 1), }; glm::vec3 faceNormal(0, 0, -1); glm::vec2 projectedSphereCenter; glm::vec2 projectedCorners[4]; bool flipNormals = false; gltb::_intersectsProjectFace(corners, faceNormal, projectedSphereCenter, projectedCorners, flipNormals); for(int i = 0; i < 4; i++) { ASSERT_EQ(corners[i][0], projectedCorners[i][0]); ASSERT_EQ(corners[i][1], projectedCorners[i][1]); } ASSERT_EQ(0, projectedSphereCenter.x); ASSERT_EQ(0, projectedSphereCenter.y); ASSERT_FALSE(flipNormals); } TEST(Intersection, _intersectsProjectFace_AlongZ_FlipNormal) { glm::vec3 corners[] = { glm::vec3(-1, -1, 1), glm::vec3(1, -1, 1), glm::vec3(1, 1, 1), glm::vec3(-1, 1, 1), }; glm::vec3 faceNormal(0, 0, 1); glm::vec2 projectedSphereCenter; glm::vec2 projectedCorners[4]; bool flipNormals = false; gltb::_intersectsProjectFace(corners, faceNormal, projectedSphereCenter, projectedCorners, flipNormals); for(int i = 0; i < 4; i++) { ASSERT_EQ(corners[i][0], projectedCorners[i][0]); ASSERT_EQ(corners[i][1], projectedCorners[i][1]); } ASSERT_EQ(0, projectedSphereCenter.x); ASSERT_EQ(0, projectedSphereCenter.y); ASSERT_TRUE(flipNormals); } TEST(Intersection, _intersectsFace_CompleteOverlapDoesIntersect) { glm::vec3 corners[] = { glm::vec3(-1, -1, 0), glm::vec3(1, -1, 0), glm::vec3(1, 1, 0), glm::vec3(-1, 1, 0), }; glm::vec3 faceNormal(0, 0, 1); bool result = gltb::_intersectsFace(corners, faceNormal); ASSERT_FALSE(result); } TEST(Intersection, _intersectsFace_PartialOverlapDoesIntersect) { glm::vec3 corners[] = { glm::vec3(-1, -1, 0), glm::vec3(1, -1, 0), glm::vec3(1, -0.5, 0), glm::vec3(-1, -0.5, 0), }; glm::vec3 faceNormal(0, 0, 1); bool result = gltb::_intersectsFace(corners, faceNormal); ASSERT_FALSE(result); } TEST(Intersection, _intersectsFace_PlaneTooDistant_DoesNotIntersect) { glm::vec3 corners[] = { glm::vec3(-1, -1, 2), glm::vec3(1, -1, 2), glm::vec3(1, 1, 2), glm::vec3(-1, 1, 2), }; glm::vec3 faceNormal(0, 0, 1); bool result = gltb::_intersectsFace(corners, faceNormal); ASSERT_FALSE(result); } TEST(Intersection, _intersectsFace_TooDistantInPlane_DoesNotIntersect) { glm::vec3 corners[] = { glm::vec3(-6, -1, 0.5), glm::vec3(-4, -1, 0.5), glm::vec3(-6, 1, 0.5), glm::vec3(-4, 1, 0.5), }; glm::vec3 faceNormal(0, 0, 1); bool result = gltb::_intersectsFace(corners, faceNormal); ASSERT_FALSE(result); } TEST(Intersection, ellipseAABB_NoIntersection) { gltb::AABB aabb(glm::vec3(-20, -20, -20), glm::vec3(-10, -10, -10)); glm::vec3 axes[3] = { glm::vec3(1, 0, 0), glm::vec3(0, 1, 0), glm::vec3(0, 0, 1) }; float extents[3] = { 2, 3, 4 }; gltb::Ellipsoid ellipsoid(glm::vec3(3, 3, 3), axes, extents); ASSERT_FALSE(gltb::intersects(ellipsoid, aabb)); } TEST(Intersection, ellipseAABB_NoIntersection2) { gltb::AABB aabb(glm::vec3(-20, -20, -20), glm::vec3(-10, -10, -10)); glm::vec3 axes[3]; axes[0] = glm::normalize(glm::vec3(1, 1, 0)); axes[1] = glm::vec3(0, 0, 1); axes[2] = glm::cross(axes[0], axes[1]); float extents[3] = { 2, 3, 4 }; gltb::Ellipsoid ellipsoid(glm::vec3(3, 3, 3), axes, extents); ASSERT_FALSE(gltb::intersects(ellipsoid, aabb)); } TEST(Intersection, ellipseAABB_TrivialIntersection) { gltb::AABB aabb(glm::vec3(-2, -2, -2), glm::vec3(3, 3, 3)); glm::vec3 axes[3] = { glm::vec3(1, 0, 0), glm::vec3(0, 1, 0), glm::vec3(0, 0, 1) }; float extents[3] = { 2, 3, 4 }; gltb::Ellipsoid ellipsoid(glm::vec3(0, 0, 0), axes, extents); ASSERT_TRUE(gltb::intersects(ellipsoid, aabb)); } TEST(Intersection, ellipseAABB_GrazingIntersection) { gltb::AABB aabb(glm::vec3(-2, -2, -2), glm::vec3(2, -1, -1)); glm::vec3 axes[3] = { glm::vec3(1, 0, 0), glm::vec3(0, 1, 0), glm::vec3(0, 0, 1) }; float extents[3] = { 2, 3, 4 }; gltb::Ellipsoid ellipsoid(glm::vec3(0, 0, 0), axes, extents); ASSERT_TRUE(gltb::intersects(ellipsoid, aabb)); } int main(int argc, char *argv[]) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }