Commit 4fb7e84e authored by Julian Schakib's avatar Julian Schakib
Browse files

latest tg, resort tests

parent f08895dd
Pipeline #13548 failed with stage
in 7 minutes and 46 seconds
typed-geometry @ f9d4c005
Subproject commit 05a2decab2dd312a5984469e166161c7fa39af08
Subproject commit f9d4c00561c281f740d3633d106b319a5555a46a
......@@ -2,269 +2,6 @@
#include <typed-geometry/tg-std.hh>
/*
TG_FUZZ_TEST(TypedGeometry, IntersectionRay3Polyhedron)
{
// six sided cube as polyhedron
auto halfext = uniform(rng, 1.0f, 5.0f) / 2;
// TODO - or + halfext?
auto p0 = tg::plane(tg::dir3::pos_y, halfext);
auto p1 = tg::plane(tg::dir3::neg_y, halfext);
auto p2 = tg::plane(tg::dir3::pos_x, halfext);
auto p3 = tg::plane(tg::dir3::neg_x, halfext);
auto p4 = tg::plane(tg::dir3::pos_z, halfext);
auto p5 = tg::plane(tg::dir3::neg_z, halfext);
auto box = tg::aabb3(tg::pos3(-halfext), tg::pos3(halfext));
auto cube = tg::polyhedron<6, tg::f32>({p0, p1, p2, p3, p4, p5});
{
auto ray = tg::ray(tg::pos3::zero, tg::dir3::neg_x);
CHECK(tg::intersects(ray, cube));
CHECK(tg::intersects(ray, box));
}
{
auto ray = tg::ray(tg::pos3(halfext * 2), tg::dir3::pos_x);//normalize(tg::vec3(0.2f, 1, 0.1f))); // TODO test below only works if parallel to no face
CHECK(!tg::intersects(ray, cube));
CHECK(!tg::intersects(ray, box));
}
// auto ray = tg::ray(uniform(rng, tg::aabb3(tg::pos3(-10), tg::pos3(10))), normalize(tg::vec3(uniform(rng, tg::aabb3(tg::pos3(-10), tg::pos3(10))))));
{
auto ray = tg::ray3(uniform(rng, box), normalize(tg::vec3(uniform(rng, box))));
CHECK(tg::intersects(ray, cube) == tg::intersects(ray, box));
}
{
auto box2 = tg::aabb3(box.min * 2, box.max * 2);
auto out = tg::pos3::zero;
while (tg::contains(box, out))
out = uniform(rng, box2);
auto ray = tg::ray3(out, normalize(-tg::vec3(out)));
CHECK(tg::intersects(ray, box));
CHECK(tg::intersects(ray, cube));
}
}*/
TG_FUZZ_TEST(TypedGeometry, IntersectionRay3AABB3)
{
auto box3 = tg::aabb3(tg::pos3(0.0f), tg::pos3(10.0f));
auto min = uniform(rng, box3);
auto aabb = tg::aabb3(min, uniform(rng, box3) + tg::vec3(min));
auto diag = normalize(aabb.max - min);
{
auto ray = tg::ray3(min, diag);
CHECK(tg::intersects(ray, aabb));
}
{
auto ray = tg::ray3(aabb.max + diag, diag);
CHECK(!tg::intersects(ray, aabb));
}
// axis aligned rays
{
auto ray = tg::ray3(aabb.max + tg::dir3::pos_z * 0.1f, tg::dir3::neg_z);
CHECK(tg::intersects(ray, aabb, tg::f32(0.01f)));
}
{
auto ray = tg::ray3(aabb.max + tg::dir3::pos_x * 0.1f, tg::dir3::neg_x);
CHECK(tg::intersects(ray, aabb, tg::f32(0.01f)));
}
{
auto ray = tg::ray3(aabb.max + tg::dir3::pos_x * 0.1f, tg::dir3::neg_x);
CHECK(tg::intersects(ray, aabb, tg::f32(0.01f)));
}
// ray inside box
{
auto ray = tg::ray3(uniform(rng, aabb), normalize(tg::vec3(uniform(rng, aabb))));
CHECK(tg::intersects(ray, aabb));
}
}
TG_FUZZ_TEST(TypedGeometry, IntersectionRay3InfCone3)
{
auto box3 = tg::aabb3(tg::pos3(-10.0f), tg::pos3(10.0f));
// random ray
auto r1 = tg::ray3(uniform(rng, box3), normalize(tg::vec3(uniform(rng, box3))));
auto mirrored = tg::ray3(r1.origin - r1.dir * 0.01f, -r1.dir);
// random cone with random opening angle in (pi / 2, pi / 4]
auto cone = tg::inf_cone3(r1.origin, r1.dir, tg::radians(tg::pi_scalar<tg::f32> / uniform(rng, 2.0f + tg::epsilon<tg::f32> * 10, 4.0f)));
CHECK(tg::intersects(r1, cone));
CHECK(!tg::intersects(mirrored, cone));
auto eps = -tg::radians(tg::epsilon<tg::f32> * 10);
auto boundaryDir = normalize(cone.opening_dir + tg::any_normal(cone.opening_dir) * tan(cone.opening_angle + eps));
auto borderRay = tg::ray3(cone.apex, boundaryDir);
CHECK(tg::intersects(borderRay, cone));
{
auto boundaryDir = normalize(cone.opening_dir + tg::any_normal(cone.opening_dir) * tan(cone.opening_angle));
auto borderRay = tg::ray3(cone.apex, boundaryDir);
CHECK(tg::intersects(borderRay, cone));
}
// does not intersect boundary but the inside of the cone!
auto innerRay = tg::ray3(cone.apex + cone.opening_dir, cone.opening_dir);
CHECK(!tg::intersects(innerRay, cone));
// CHECK(tg::contains(cone, innerRay.origin));
}
TG_FUZZ_TEST(TypedGeometry, IntersectionRay3Ray3)
{
auto box3 = tg::aabb3(tg::pos3(-10.0f), tg::pos3(10.0f));
// random ray
auto r1 = tg::ray3(uniform(rng, box3), normalize(tg::vec3(uniform(rng, box3))));
// not-parallel new direction
auto newDir = r1.dir;
while (tg::abs(dot(newDir, r1.dir)) > 0.9f)
newDir = normalize(tg::vec3(uniform(rng, box3)));
{
// different direction, same origin
auto r2 = tg::ray3(r1.origin, newDir);
CHECK(tg::intersects(r1, r2));
}
{
// same direction, offset from origin
auto off = uniform(rng, 0.2f, 1.0f);
auto r2 = tg::ray3(r1.origin - r1.dir * off, r1.dir);
CHECK(distance(r2.origin + r2.dir * off, r1.origin) <= tg::epsilon<tg::f32> * 10);
// ray 2 hits origin 1
CHECK(tg::intersects(r1, r2, tg::epsilon<tg::f32> * 10));
}
{
// flipped direction, offset from origin
auto off = uniform(rng, 0.1f, 1.0f);
auto r2 = tg::ray3(r1.origin - r1.dir * off, -r1.dir); // flipped
CHECK(distance(r2.origin + r2.dir * off, r1.origin) > tg::epsilon<tg::f32> * 10);
// both rays point away from one another
CHECK(!tg::intersects(r1, r2));
}
{
// flipped direction, offset from origin
// r1 dir flipped too!
auto off = uniform(rng, 0.2f, 1.0f);
auto r2 = tg::ray3(r1.origin - r1.dir * off, -r1.dir); // flipped
// flip r1
r1.dir = -r1.dir;
CHECK(distance(r1.origin + r1.dir * off, r2.origin) <= tg::epsilon<tg::f32> * 10);
// ray 1 hits origin 2
CHECK(tg::intersects(r1, r2, tg::epsilon<tg::f32> * 10));
}
{
// rays do not share origin and directions not parallel
auto off = uniform(rng, 0.1f, 1.0f);
auto r2 = tg::ray3(r1.origin - r1.dir * off + newDir * off, newDir);
CHECK(!tg::intersects(r1, r2));
}
}
TG_FUZZ_TEST(TypedGeometry, IntersectionRay3Sphere3)
{
auto box1 = tg::aabb1(tg::pos1(-1.0f), tg::pos1(1.0f));
auto box3 = tg::aabb3(tg::pos3(-1.0f), tg::pos3(1.0f));
// random sphere
auto s = tg::sphere3(uniform(rng, box3) * 10.0f, tg::abs(uniform(rng, box1).x));
{
// ray from sphere origin to random direction
auto randomDir3 = normalize(tg::vec3(uniform(rng, box3)));
auto r = tg::ray3(s.center, randomDir3);
auto result = tg::intersection(r, s);
CHECK(result.size() == 1);
CHECK(distance(result[0], s.center) == approx(s.radius));
// inside (or on surface of) sphere moved along its direction
auto m = uniform(rng, box1).x * s.radius;
auto rv = tg::vec3::zero;
while (length(rv) == 0)
rv = tg::vec3(uniform(rng, box3));
r.dir = normalize(rv);
r.origin += m * r.dir;
result = tg::intersection(r, s);
CHECK(result.size() == 1);
CHECK(distance(result[0], r.origin) == approx(s.radius - m));
// close to surface and perpendicular shots
auto eps = tg::f32(1e-2);
auto n = r.dir;
auto t = any_normal(n);
auto rnd = tg::abs(uniform(rng, box1).x); // positive
// moved slightly below surface
{
r.origin = s.center + s.radius * (1.0f - eps) * n;
result = tg::intersection(r, s);
CHECK(result.size() == 1);
// shoot from outside
r.origin += t * s.radius * (1.0f + eps + rnd);
r.dir = -t;
result = tg::intersection(r, s);
CHECK(result.size() == 2);
}
// moved slightly above surface
{
r.dir = n;
r.origin = s.center + s.radius * (1.0f + eps) * n;
result = tg::intersection(r, s);
CHECK(result.size() == 0);
// shoot from outside
r.origin += t * s.radius * rnd * 10.0f;
r.dir = -t;
result = tg::intersection(r, s);
CHECK(result.size() == 0);
}
// ray outside sphere
{
r.origin = s.center + s.radius * (1.0f + eps + rnd) * randomDir3;
// shooting at center (expecting two intersections)
r.dir = normalize(s.center - r.origin);
result = tg::intersection(r, s);
CHECK(result.size() == 2);
// shooting away from center (expecting no intersection)
r.dir = -r.dir;
result = tg::intersection(r, s);
CHECK(result.size() == 0);
}
}
}
TEST_CASE("TypedGeometry.IntersectionSphere3Sphere3")
{
{ // touching spheres 1 (side-by-side)
......@@ -490,76 +227,3 @@ TEST_CASE("TypedGeometry.IntersectionCircle2Circle2")
CHECK(res.value().second.y == approx(tg::sqrt(0.75f)));
}
}
TG_FUZZ_TEST(Triangle, Intersection)
{
auto bb = tg::aabb3(-10, 10);
auto v0 = uniform(rng, bb);
auto v1 = uniform(rng, bb);
auto v2 = uniform(rng, bb);
auto origin = uniform(rng, bb);
auto t0 = tg::triangle(v0, v1, v2);
auto t1 = tg::triangle(v1, v2, v0);
auto t2 = tg::triangle(v2, v0, v1);
auto t3 = tg::triangle(v2, v1, v0);
auto t4 = tg::triangle(v1, v0, v2);
auto t5 = tg::triangle(v0, v2, v1);
auto p = uniform(rng, t0);
auto rdir = normalize(p - origin);
auto ray = tg::ray(origin, rdir);
auto nray = tg::ray(origin, -rdir);
CHECK(tg::intersects(ray, t0));
CHECK(tg::intersects(ray, t1));
CHECK(tg::intersects(ray, t2));
CHECK(tg::intersects(ray, t3));
CHECK(tg::intersects(ray, t4));
CHECK(tg::intersects(ray, t5));
CHECK(tg::intersects(ray, tg::plane3(rdir, p)));
CHECK(tg::intersects(ray, tg::plane3(-rdir, p)));
CHECK(!tg::intersects(nray, t0));
CHECK(!tg::intersects(nray, t1));
CHECK(!tg::intersects(nray, t2));
CHECK(!tg::intersects(nray, t3));
CHECK(!tg::intersects(nray, t4));
CHECK(!tg::intersects(nray, t5));
CHECK(!tg::intersects(nray, tg::plane3(rdir, p)));
CHECK(!tg::intersects(nray, tg::plane3(-rdir, p)));
auto ip0 = tg::intersection(ray, t0);
auto ip1 = tg::intersection(ray, t1);
auto ip2 = tg::intersection(ray, t2);
auto ip3 = tg::intersection(ray, t3);
auto ip4 = tg::intersection(ray, t4);
auto ip5 = tg::intersection(ray, t5);
CHECK(ip0.has_value());
CHECK(ip1.has_value());
CHECK(ip2.has_value());
CHECK(ip3.has_value());
CHECK(ip4.has_value());
CHECK(ip5.has_value());
CHECK(ip0.value() == approx(p, 0.01f));
CHECK(ip1.value() == approx(p, 0.01f));
CHECK(ip2.value() == approx(p, 0.01f));
CHECK(ip3.value() == approx(p, 0.01f));
CHECK(ip4.value() == approx(p, 0.01f));
CHECK(ip5.value() == approx(p, 0.01f));
auto a = uniform(rng, -2.f, 2.f);
auto b = uniform(rng, -2.f, 2.f);
auto c = 1 - a - b;
auto p2 = t0[{a,b,c}];
auto rdir2 = normalize(p2 - origin);
auto ray2 = tg::ray(origin, rdir2);
auto nray2 = tg::ray(origin, -rdir2);
CHECK(!tg::intersects(nray2, t0));
if (a < 0 || b < 0 || c < 0)
CHECK(!tg::intersects(ray2, t0));
}
......@@ -63,3 +63,342 @@ TG_FUZZ_TEST(Ray, Intersect)
CHECK(distance(ip.value(), c) == approx(0).epsilon(1e-2f));
}
}
TG_FUZZ_TEST(TypedGeometry, IntersectionRay3AABB3)
{
auto box3 = tg::aabb3(tg::pos3(0.0f), tg::pos3(10.0f));
auto min = uniform(rng, box3);
auto aabb = tg::aabb3(min, uniform(rng, box3) + tg::vec3(min));
auto diag = normalize(aabb.max - min);
{
auto ray = tg::ray3(min, diag);
CHECK(tg::intersects(ray, aabb));
}
{
auto ray = tg::ray3(aabb.max + diag, diag);
CHECK(!tg::intersects(ray, aabb));
}
// axis aligned rays
{
auto ray = tg::ray3(aabb.max + tg::dir3::pos_z * 0.1f, tg::dir3::neg_z);
CHECK(tg::intersects(ray, aabb, tg::f32(0.01f)));
}
{
auto ray = tg::ray3(aabb.max + tg::dir3::pos_x * 0.1f, tg::dir3::neg_x);
CHECK(tg::intersects(ray, aabb, tg::f32(0.01f)));
}
{
auto ray = tg::ray3(aabb.max + tg::dir3::pos_x * 0.1f, tg::dir3::neg_x);
CHECK(tg::intersects(ray, aabb, tg::f32(0.01f)));
}
// ray inside box
{
auto ray = tg::ray3(uniform(rng, aabb), normalize(tg::vec3(uniform(rng, aabb))));
CHECK(tg::intersects(ray, aabb));
}
}
TG_FUZZ_TEST(TypedGeometry, IntersectionRay3InfCone3)
{
auto box3 = tg::aabb3(tg::pos3(-10.0f), tg::pos3(10.0f));
// random ray
auto r1 = tg::ray3(uniform(rng, box3), normalize(tg::vec3(uniform(rng, box3))));
auto mirrored = tg::ray3(r1.origin - r1.dir * 0.01f, -r1.dir);
// random cone with random opening angle in (pi / 2, pi / 4]
auto cone = tg::inf_cone3(r1.origin, r1.dir, tg::radians(tg::pi_scalar<tg::f32> / uniform(rng, 2.0f + tg::epsilon<tg::f32> * 10, 4.0f)));
CHECK(tg::intersects(r1, cone));
CHECK(!tg::intersects(mirrored, cone));
auto eps = -tg::radians(tg::epsilon<tg::f32> * 10);
auto boundaryDir = normalize(cone.opening_dir + tg::any_normal(cone.opening_dir) * tan(cone.opening_angle + eps));
auto borderRay = tg::ray3(cone.apex, boundaryDir);
CHECK(tg::intersects(borderRay, cone));
{
auto boundaryDir = normalize(cone.opening_dir + tg::any_normal(cone.opening_dir) * tan(cone.opening_angle));
auto borderRay = tg::ray3(cone.apex, boundaryDir);
CHECK(tg::intersects(borderRay, cone));
}
// does not intersect boundary but the inside of the cone!
auto innerRay = tg::ray3(cone.apex + cone.opening_dir, cone.opening_dir);
CHECK(!tg::intersects(innerRay, cone));
// CHECK(tg::contains(cone, innerRay.origin));
}
TG_FUZZ_TEST(TypedGeometry, IntersectionRay3Ray3)
{
auto box3 = tg::aabb3(tg::pos3(-10.0f), tg::pos3(10.0f));
// random ray
auto r1 = tg::ray3(uniform(rng, box3), normalize(tg::vec3(uniform(rng, box3))));
// not-parallel new direction
auto newDir = r1.dir;
while (tg::abs(dot(newDir, r1.dir)) > 0.9f)
newDir = normalize(tg::vec3(uniform(rng, box3)));
{
// different direction, same origin
auto r2 = tg::ray3(r1.origin, newDir);
CHECK(tg::intersects(r1, r2));
}
{
// same direction, offset from origin
auto off = uniform(rng, 0.2f, 1.0f);
auto r2 = tg::ray3(r1.origin - r1.dir * off, r1.dir);
CHECK(distance(r2.origin + r2.dir * off, r1.origin) <= tg::epsilon<tg::f32> * 10);
// ray 2 hits origin 1
CHECK(tg::intersects(r1, r2, tg::epsilon<tg::f32> * 10));
}
{
// flipped direction, offset from origin
auto off = uniform(rng, 0.1f, 1.0f);
auto r2 = tg::ray3(r1.origin - r1.dir * off, -r1.dir); // flipped
CHECK(distance(r2.origin + r2.dir * off, r1.origin) > tg::epsilon<tg::f32> * 10);
// both rays point away from one another
CHECK(!tg::intersects(r1, r2));
}
{
// flipped direction, offset from origin
// r1 dir flipped too!
auto off = uniform(rng, 0.2f, 1.0f);
auto r2 = tg::ray3(r1.origin - r1.dir * off, -r1.dir); // flipped
// flip r1
r1.dir = -r1.dir;
CHECK(distance(r1.origin + r1.dir * off, r2.origin) <= tg::epsilon<tg::f32> * 10);
// ray 1 hits origin 2
CHECK(tg::intersects(r1, r2, tg::epsilon<tg::f32> * 10));
}
{
// rays do not share origin and directions not parallel
auto off = uniform(rng, 0.1f, 1.0f);
auto r2 = tg::ray3(r1.origin - r1.dir * off + newDir * off, newDir);
CHECK(!tg::intersects(r1, r2));
}
}
TG_FUZZ_TEST(TypedGeometry, IntersectionRay3Sphere3)
{
auto box1 = tg::aabb1(tg::pos1(-1.0f), tg::pos1(1.0f));
auto box3 = tg::aabb3(tg::pos3(-1.0f), tg::pos3(1.0f));
// random sphere
auto s = tg::sphere3(uniform(rng, box3) * 10.0f, tg::abs(uniform(rng, box1).x));
{
// ray from sphere origin to random direction
auto randomDir3 = normalize(tg::vec3(uniform(rng, box3)));
auto r = tg::ray3(s.center, randomDir3);
auto result = tg::intersection(r, s);
CHECK(result.size() == 1);
CHECK(distance(result[0], s.center) == approx(s.radius));
// inside (or on surface of) sphere moved along its direction
auto m = uniform(rng, box1).x * s.radius;
auto rv = tg::vec3::zero;
while (length(rv) == 0)
rv = tg::vec3(uniform(rng, box3));
r.dir = normalize(rv);
r.origin += m * r.dir;
result = tg::intersection(r, s);
CHECK(result.size() == 1);
CHECK(distance(result[0], r.origin) == approx(s.radius - m));
// close to surface and perpendicular shots
auto eps = tg::f32(1e-2);
auto n = r.dir;
auto t = any_normal(n);
auto rnd = tg::abs(uniform(rng, box1).x); // positive
// moved slightly below surface
{
r.origin = s.center + s.radius * (1.0f - eps) * n;
result = tg::intersection(r, s);
CHECK(result.size() == 1);
// shoot from outside
r.origin += t * s.radius * (1.0f + eps + rnd);
r.dir = -t;
result = tg::intersection(r, s);
CHECK(result.size() == 2);
}
// moved slightly above surface
{
r.dir = n;
r.origin = s.center + s.radius * (1.0f + eps) * n;
result = tg::intersection(r, s);
CHECK(result.size() == 0);
// shoot from outside
r.origin += t * s.radius * rnd * 10.0f;
r.dir = -t;
result = tg::intersection(r, s);
CHECK(result.size() == 0);
}
// ray outside sphere
{
r.origin = s.center + s.radius * (1.0f + eps + rnd) * randomDir3;
// shooting at center (expecting two intersections)
r.dir = normalize(s.center - r.origin);
result = tg::intersection(r, s);
CHECK(result.size() == 2);
// shooting away from center (expecting no intersection)
r.dir = -r.dir;
result = tg::intersection(r, s);
CHECK(result.size() == 0);
}
}
}
TG_FUZZ_TEST(Triangle, Intersection)
{
auto bb = tg::aabb3(-10, 10);
auto v0 = uniform(rng, bb);
auto v1 = uniform(rng, bb);
auto v2 = uniform(rng, bb);
auto origin = uniform(rng, bb);