static glm::vec3 Center() noexcept { return glm::vec3(8.0f); }
static float Radius() noexcept { return 27.71281292110203669632f; /* 16 * √3 */ }
+ /// get bounding box relative to given reference chunk
+ AABB RelativeBounds(const ExactLocation::Coarse &ref) const noexcept {
+ AABB bounds;
+ bounds.min = (position - ref) * ExactLocation::Extent();
+ bounds.max = bounds.min + ExactLocation::FExtent();
+ return bounds;
+ }
+
static constexpr bool InBounds(const ExactLocation::Fine &pos) noexcept {
return
pos.x >= 0.0f && pos.x < fside &&
const ExactLocation::Coarse &reference,
float &dist
) const noexcept {
- return blank::Intersection(ray, Bounds(), Transform(reference), &dist);
+ return blank::Intersection(ray, RelativeBounds(reference), dist);
}
/// check if given ray intersects any block of this chunk
Ray Entity::Aim(const ExactLocation::Coarse &chunk_offset) const noexcept {
glm::mat4 transform = ViewTransform(chunk_offset);
- return Ray{ glm::vec3(transform[3]), -glm::vec3(transform[2]) };
+ Ray ray{ glm::vec3(transform[3]), -glm::vec3(transform[2]) };
+ ray.Update();
+ return ray;
}
void Entity::Update(World &world, float dt) {
candidates.clear();
- // TODO: convert to coords based iteration and trim based
- // on ray direction
+ // TODO: change this so the test starts at the chunk of the ray's
+ // origin and "walks" forward until it hits (actually casting
+ // the ray, so to say). if this performs well (at least, better
+ // than now), this could also qualify for the chunk test itself
+ // see Bresenham's line algo or something similar
for (Chunk *cur_chunk : *index) {
float cur_dist;
if (cur_chunk && cur_chunk->Intersection(ray, reference, cur_dist)) {
}
+void IntersectionTest::testSimpleRayBoxIntersection() {
+ Ray ray{ { 0, 0, 0 }, { 1, 0, 0 } }; // at origin, pointing right
+ ray.Update();
+ AABB box{ { -1, -1, -1 }, { 1, 1, 1 } }; // 2x2x2 cube centered around origin
+
+ const float delta = std::numeric_limits<float>::epsilon();
+
+ float distance = 0;
+
+ CPPUNIT_ASSERT_MESSAGE(
+ "ray at origin not intersecting box at origin",
+ Intersection(ray, box, distance)
+ );
+
+ // move ray outside the box, but have it still point at it
+ // should be 4 units to the left now
+ ray.orig.x = -5;
+ CPPUNIT_ASSERT_MESSAGE(
+ "ray pointing at box doesn't intersect",
+ Intersection(ray, box, distance)
+ );
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
+ "intersection distance way off",
+ 4.0f, distance, delta
+ );
+
+ // move ray to the other side, so it's pointing away now
+ ray.orig.x = 5;
+ CPPUNIT_ASSERT_MESSAGE(
+ "ray pointing away from box still intersects",
+ !Intersection(ray, box, distance)
+ );
+
+ // 45 deg down from 4 units away, so should be about 4 * sqrt(2)
+ ray.orig = { -5.0f, 4.5f, 0.0f };
+ ray.dir = { 0.70710678118654752440f, -0.70710678118654752440f, 0.0f };
+ ray.Update();
+ CPPUNIT_ASSERT_MESSAGE(
+ "ray pointing at box doesn't intersect",
+ Intersection(ray, box, distance)
+ );
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
+ "intersection distance way off",
+ 5.65685424949238019520f, distance, delta
+ );
+}
+
void IntersectionTest::testRayBoxIntersection() {
Ray ray{ { 0, 0, 0 }, { 1, 0, 0 } }; // at origin, pointing right
AABB box{ { -1, -1, -1 }, { 1, 1, 1 } }; // 2x2x2 cube centered around origin
"ray at origin not intersecting box at origin",
Intersection(ray, box, M, &distance)
);
- CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
- "intersection distance way off",
- 0.0f, distance, delta
- );
// normal undefined, so can't test
// move ray outside the box, but have it still point at it
"ray pointing away from box still intersects",
!Intersection(ray, box, M)
);
+
+ // 45 deg down from 4 units away, so should be about 4 * sqrt(2)
+ ray.orig = { -5.0f, 4.5f, 0.0f };
+ ray.dir = { 0.70710678118654752440f, -0.70710678118654752440f, 0.0f };
+ CPPUNIT_ASSERT_MESSAGE(
+ "ray pointing at box doesn't intersect",
+ Intersection(ray, box, M, &distance, &normal)
+ );
+ CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
+ "intersection distance way off",
+ 5.65685424949238019520f, distance, delta
+ );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ "wrong surface normal at intersection point",
+ glm::vec3(-1, 0, 0), normal
+ );
}
void IntersectionTest::testBoxBoxIntersection() {