Skip to content

Commit

Permalink
More performant rayOBBParametric.
Browse files Browse the repository at this point in the history
  • Loading branch information
kring committed Aug 28, 2024
1 parent 68341f6 commit ef273ac
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 43 deletions.
5 changes: 3 additions & 2 deletions Cesium3DTilesSelection/src/Tileset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -327,8 +327,9 @@ bool Tileset::tryCompleteHeightRequest(

for (Tile* pCandidate : query.previousCandidateTiles) {
TileLoadState loadState = pCandidate->getState();
if (loadState == TileLoadState::Done ||
loadState == TileLoadState::Failed) {
if (!pCandidate->getChildren().empty() &&
(loadState == TileLoadState::Done ||
loadState == TileLoadState::Failed)) {
query.findCandidateTiles(pCandidate, warnings);
} else {
query.candidateTiles.emplace_back(pCandidate);
Expand Down
4 changes: 2 additions & 2 deletions CesiumGeometry/include/CesiumGeometry/AxisAlignedBox.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace CesiumGeometry {

struct CESIUMGEOMETRY_API AxisAlignedBox final {

AxisAlignedBox() noexcept
constexpr AxisAlignedBox() noexcept
: minimumX(0.0),
minimumY(0.0),
minimumZ(0.0),
Expand All @@ -20,7 +20,7 @@ struct CESIUMGEOMETRY_API AxisAlignedBox final {
lengthZ(0.0),
center(0.0) {}

AxisAlignedBox(
constexpr AxisAlignedBox(
double minimumX_,
double minimumY_,
double minimumZ_,
Expand Down
59 changes: 23 additions & 36 deletions CesiumGeometry/src/IntersectionTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,43 +230,30 @@ IntersectionTests::rayOBB(const Ray& ray, const OrientedBoundingBox& obb) {
std::optional<double> IntersectionTests::rayOBBParametric(
const Ray& ray,
const OrientedBoundingBox& obb) {
// Extract the rotation from the OBB's rotatin/scale transformation and
// invert it. This code assumes that there is not a negative scale, that
// there's no skew, that there's no other funny business. Non-uniform scale
// is fine!
const glm::dmat3& halfAxes = obb.getHalfAxes();
glm::dmat4 cubeToWorld = glm::dmat4(
glm::dvec4(halfAxes[0], 0.0),
glm::dvec4(halfAxes[1], 0.0),
glm::dvec4(halfAxes[2], 0.0),
glm::dvec4(obb.getCenter(), 1.0));
glm::dmat4 worldToCube = glm::affineInverse(cubeToWorld);

Ray rayForAABB = ray.transform(worldToCube);
std::optional<double> intersection = IntersectionTests::rayAABBParametric(
rayForAABB,
AxisAlignedBox(-1.0, -1.0, -1.0, 1.0, 1.0, 1.0));

if (!intersection)
return intersection;

glm::dvec3 pointRelativeToAABB = rayForAABB.pointFromDistance(*intersection);
return glm::length(
glm::dvec3(cubeToWorld * glm::dvec4(pointRelativeToAABB, 1.0)) -
ray.getOrigin());

// const glm::dmat3x3& inverseHalfAxis = obb.getInverseHalfAxes();
// glm::dmat4x4 transformation(
// glm::dvec4(glm::normalize(inverseHalfAxis[0]), 0.0),
// glm::dvec4(glm::normalize(inverseHalfAxis[1]), 0.0),
// glm::dvec4(glm::normalize(inverseHalfAxis[2]), 0.0),
// glm::dvec4(0.0, 0.0, 0.0, 1.0));

// glm::dvec3 center =
// glm::dvec3(transformation * glm::dvec4(obb.getCenter(), 1.0));
// glm::dvec3 halfLengths = obb.getLengths() / 2.0;
// glm::dvec3 ll = center - halfLengths;
// glm::dvec3 ur = center + halfLengths;

// return rayAABBParametric(
// ray.transform(transformation),
// AxisAlignedBox(ll.x, ll.y, ll.z, ur.x, ur.y, ur.z));
glm::dvec3 halfLengths = obb.getLengths() * 0.5;
glm::dmat3 rotationOnly(
halfAxes[0] / halfLengths.x,
halfAxes[1] / halfLengths.y,
halfAxes[2] / halfLengths.z);
glm::dmat3 inverseRotation = glm::transpose(rotationOnly);

// Find the equivalent ray in the coordinate system where the OBB is not
// rotated or translated. That is, where it's an AABB at the origin.
glm::dvec3 relativeOrigin = ray.getOrigin() - obb.getCenter();
glm::dvec3 rayOrigin(inverseRotation * relativeOrigin);
glm::dvec3 rayDirection(inverseRotation * ray.getDirection());

// Find the distance to the new ray's intersection with the AABB, which is
// equivalent to the distance of the original ray intersection with the OBB.
glm::dvec3 ll = -halfLengths;
glm::dvec3 ur = +halfLengths;
AxisAlignedBox aabb(ll.x, ll.y, ll.z, ur.x, ur.y, ur.z);
return rayAABBParametric(Ray(rayOrigin, rayDirection), aabb);
}

std::optional<glm::dvec3>
Expand Down
71 changes: 68 additions & 3 deletions CesiumGeometry/test/TestIntersectionTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "CesiumUtility/Math.h"

#include <catch2/catch.hpp>
#include <glm/gtc/matrix_inverse.hpp>
#include <glm/gtx/transform.hpp>

#include <array>
Expand Down Expand Up @@ -265,7 +266,17 @@ TEST_CASE("IntersectionTests::rayOBB") {
glm::dvec3(10.0, 10.0, 10.0),
glm::dmat3(
glm::rotate(glm::radians(-45.0), glm::dvec3(1.0, 0.0, 0.0)))),
glm::dvec3(10.0, 10.0, 10.0 + glm::sqrt(2))},
glm::dvec3(10.0, 10.0, 10.0 + glm::sqrt(2.0))},
// 2x2x2 obb at (10,20,30) that is rotated -45 degrees on the x-axis and
// hit from an angle.
TestCase{
Ray(glm::dvec3(10.0, 20.0 + 2.0, 30.0 + 1.0 + glm::sqrt(2)),
glm::normalize(glm::dvec3(0.0, -2.0, -1.0))),
OrientedBoundingBox(
glm::dvec3(10.0, 20.0, 30.0),
glm::dmat3(
glm::rotate(glm::radians(-45.0), glm::dvec3(1.0, 0.0, 0.0)))),
glm::dvec3(10.0, 20.0, 30.0 + glm::sqrt(2.0))},
// 4x4x4 obb at (10,10,10) that is rotated -45 degrees on the x-axis.
TestCase{
Ray(glm::dvec3(10.0, 10.0, 20.0), glm::dvec3(0.0, 0.0, -1.0)),
Expand All @@ -274,7 +285,18 @@ TEST_CASE("IntersectionTests::rayOBB") {
2.0 * glm::dmat3(glm::rotate(
glm::radians(-45.0),
glm::dvec3(1.0, 0.0, 0.0)))),
glm::dvec3(10.0, 10.0, 10.0 + glm::sqrt(8))},
glm::dvec3(10.0, 10.0, 10.0 + glm::sqrt(8.0))},
// 4x4x4 obb at (10,20,30) that is rotated -45 degrees on the x-axis and
// hit from an angle
TestCase{
Ray(glm::dvec3(10.0, 20.0 + 10.0, 30.0 + 20.0 + glm::sqrt(8.0)),
glm::normalize(glm::dvec3(0.0, -1.0, -2.0))),
OrientedBoundingBox(
glm::dvec3(10.0, 20.0, 30.0),
2.0 * glm::dmat3(glm::rotate(
glm::radians(-45.0),
glm::dvec3(1.0, 0.0, 0.0)))),
glm::dvec3(10.0, 20.0, 30.0 + glm::sqrt(8.0))},
// 4x4x2 obb at (10,10,10) that is not rotated.
TestCase{
Ray(glm::dvec3(10.0, 10.0, 20.0), glm::dvec3(0.0, 0.0, -1.0)),
Expand All @@ -298,7 +320,50 @@ TEST_CASE("IntersectionTests::rayOBB") {
glm::dmat3(glm::rotate(
glm::radians(45.0),
glm::dvec3(0.0, 1.0, 0.0)))),
glm::dvec3(10.0, 20.0, 30.0 + glm::sqrt(2.0))});
glm::dvec3(10.0, 20.0, 30.0 + glm::sqrt(2.0))},
// 2x4x2 obb at (10,20,30) that is rotated 45 degrees on the X-axis.
TestCase{
Ray(glm::dvec3(10.0, 20.0, 40.0), glm::dvec3(0.0, 0.0, -1.0)),
OrientedBoundingBox(
glm::dvec3(10.0, 20.0, 30.0),
glm::dmat3(
glm::rotate(glm::radians(45.0), glm::dvec3(1.0, 0.0, 0.0))) *
glm::dmat3(glm::scale(glm::dvec3(1.0, 2.0, 1.0)))),
glm::dvec3(10.0, 20.0, 30.0 + 1.0 / glm::cos(glm::radians(45.0)))},
// 2x4x2 obb at (10,20,30) that is rotated 225 degrees on the Y-axis.
TestCase{
Ray(glm::dvec3(10.0, 20.0, 40.0), glm::dvec3(0.0, 0.0, -1.0)),
OrientedBoundingBox(
glm::dvec3(10.0, 20.0, 30.0),
glm::dmat3(glm::scale(glm::dvec3(1.0, 2.0, 1.0))) *
glm::dmat3(glm::rotate(
glm::radians(225.0),
glm::dvec3(0.0, 1.0, 0.0)))),
glm::dvec3(10.0, 20.0, 30.0 + glm::sqrt(2.0))},
// 2x2x4 obb at (10,20,30) that is rotated 90 degrees on the X-axis and
// hit from an angle.
TestCase{
Ray(glm::dvec3(10.0, 20.0 + 2.0, 30.0 + 1.0 + 1.0),
glm::normalize(glm::dvec3(0.0, -2.0, -1.0))),
OrientedBoundingBox(
glm::dvec3(10.0, 20.0, 30.0),
glm::dmat3(
glm::rotate(glm::radians(90.0), glm::dvec3(1.0, 0.0, 0.0))) *
glm::dmat3(glm::scale(glm::dvec3(1.0, 1.0, 2.0)))),
glm::dvec3(10.0, 20.0, 30.0 + 1.0)},
// 2x2x2 obb at (10,20,30) that is rotated 45 degrees on the X- and
// Y-axis.
TestCase{
Ray(glm::dvec3(10.0, 20.0, 40.0), glm::dvec3(0.0, 0.0, -1.0)),
OrientedBoundingBox(
glm::dvec3(10.0, 20.0, 30.0),
(glm::dmat3(glm::rotate(
glm::atan(1.0 / 2.0, glm::sqrt(2) / 2.0),
glm::dvec3(1.0, 0.0, 0.0)))) *
glm::dmat3(glm::rotate(
glm::radians(45.0),
glm::dvec3(0.0, 1.0, 0.0)))),
glm::dvec3(10.0, 20.0, 30.0 + glm::sqrt(3.0))});
std::optional<glm::dvec3> intersectionPoint =
IntersectionTests::rayOBB(testCase.ray, testCase.obb);
CHECK(glm::all(glm::lessThan(
Expand Down

0 comments on commit ef273ac

Please sign in to comment.