blob: fc445e66ee8a9d35f2d5d0586c6a0d14a4dd033a [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/ui/lib/escher/geometry/intersection.h"
#include <lib/syslog/cpp/macros.h>
#include <gtest/gtest.h>
#include "src/ui/lib/escher/geometry/bounding_box.h"
#include "src/ui/lib/escher/geometry/types.h"
#include "src/ui/lib/escher/mesh/indexed_triangle_mesh_upload.h"
#include "src/ui/lib/escher/mesh/tessellation.h"
#include "src/ui/lib/escher/test/common/gtest_escher.h"
namespace {
using namespace escher;
TEST(Intersection, SimpleBoundingBox) {
BoundingBox box(glm::vec3(0, 0, 0), glm::vec3(5, 5, 5));
ray4 ray{.origin = glm::vec4(1, 1, -1, 1), .direction = glm::vec4(0, 0, 1, 0)};
Interval out_interval;
bool result = IntersectRayBox(ray, box, &out_interval);
EXPECT_TRUE(result);
}
TEST(Intersection, BoundingBoxBehind) {
BoundingBox box(glm::vec3(0, 0, 0), glm::vec3(5, 5, 5));
ray4 ray{.origin = glm::vec4(1, 1, 10, 1), .direction = glm::vec4(0, 0, 1, 0)};
Interval out_interval;
bool result = IntersectRayBox(ray, box, &out_interval);
EXPECT_TRUE(!result);
}
TEST(Intersection, RayInsideBox) {
BoundingBox box(glm::vec3(0, 0, 0), glm::vec3(5, 5, 5));
ray4 ray{.origin = glm::vec4(1, 1, 2, 1), .direction = glm::vec4(0, 0, 1, 0)};
Interval out_interval;
bool result = IntersectRayBox(ray, box, &out_interval);
EXPECT_TRUE(result);
EXPECT_EQ(out_interval.min(), 0.f);
}
// Test that intersection code still works with nullptrs passed into the
// out min/max fields.
TEST(Intersection, NullInterval) {
BoundingBox box(glm::vec3(0, 0, 0), glm::vec3(5, 5, 5));
ray4 ray{.origin = glm::vec4(1, 1, -1, 1), .direction = glm::vec4(0, 0, 1, 0)};
bool result = IntersectRayBox(ray, box, nullptr);
EXPECT_TRUE(result);
}
TEST(Intersection, TriangleParallel) {
ray4 ray{.origin = glm::vec4(0, 0, 0, 1), .direction = glm::vec4(0, 0, 1, 0)};
// Triangle laying on the YZ plane
glm::vec3 v0(0, 0, 5);
glm::vec3 v1(0, 0, 10);
glm::vec3 v2(0, 5, 7);
float out_distance;
bool hit = IntersectRayTriangle(ray, v0, v1, v2, &out_distance);
EXPECT_FALSE(hit);
}
TEST(Intersection, TriangleBehind) {
ray4 ray{.origin = glm::vec4(0, 0, 0, 1), .direction = glm::vec4(0, 0, 1, 0)};
glm::vec3 v0(-5, 0, -5);
glm::vec3 v1(5, 0, -5);
glm::vec3 v2(0, 5, -5);
float out_distance;
bool hit = IntersectRayTriangle(ray, v0, v1, v2, &out_distance);
EXPECT_FALSE(hit);
}
TEST(Intersection, TriangleStraightAhead) {
ray4 ray{.origin = glm::vec4(0, 0, 0, 1), .direction = glm::vec4(0, 0, 1, 0)};
glm::vec3 v0(-5, 0, 5);
glm::vec3 v1(5, 0, 5);
glm::vec3 v2(0, 5, 5);
float out_distance;
bool hit = IntersectRayTriangle(ray, v0, v1, v2, &out_distance);
EXPECT_TRUE(hit);
EXPECT_EQ(out_distance, 5.f);
}
// Ray is pointed straight up the Y-axis, offset 5 units from the origin.
// Triangle is parallel to the XZ axis at a Y elevation of 100, centered
// over the ray.
TEST(Intersection, TriangleStraightAheadPart2) {
ray4 ray{.origin = glm::vec4(0, 5, 0, 1), .direction = glm::vec4(0, 1, 0, 0)};
glm::vec3 v0(-5, 100, 0);
glm::vec3 v1(5, 100, -5);
glm::vec3 v2(5, 100, 5);
float out_distance;
bool hit = IntersectRayTriangle(ray, v0, v1, v2, &out_distance);
EXPECT_TRUE(hit);
EXPECT_EQ(out_distance, 95.f);
}
// The triangle is in front of the ray, but its off to the side and thus
// the ray misses it.
TEST(Intersection, TriangleOffToTheSide) {
ray4 ray{.origin = glm::vec4(0, 5, 0, 1), .direction = glm::vec4(0, 1, 0, 0)};
glm::vec3 v0(-15, 100, 0);
glm::vec3 v1(-5, 100, -5);
glm::vec3 v2(-5, 100, 5);
float out_distance;
bool hit = IntersectRayTriangle(ray, v0, v1, v2, &out_distance);
EXPECT_FALSE(hit);
}
} // namespace