Terrain ray cast benchmarks and optimization. (#7303)

* Terrain ray cast benchmarks and optimization:
- Added some benchmarks that exercise terrain ray casting.
- Optimized terrain ray casting by removing an unnecessary AABB intersection check (this was suggested by @invertednormal in the original review, but I forgot to actually remove it until now).
- Fixed a bug where we were not normalizing the ray direction before performing the Moller-Trumbore ray<->triangle intersection calculations.

Signed-off-by: bosnichd <bosnichd@amazon.com>

* Update to make work with changes pulled down from mainline.

Signed-off-by: bosnichd <bosnichd@amazon.com>
This commit is contained in:
bosnichd
2022-02-01 09:36:44 -07:00
committed by GitHub
parent 9d002860f7
commit ff4529fc60
2 changed files with 86 additions and 27 deletions
@@ -35,7 +35,6 @@ namespace
inline void FindNearestIntersection(const AZ::Aabb& aabb,
const AZ::Vector3& rayStart,
const AZ::Vector3& rayDirection,
const AZ::Vector3& rayDirectionReciprocal,
AzFramework::RenderGeometry::RayResult& result)
{
float intersectionT;
@@ -43,7 +42,7 @@ namespace
AZ::Vector3 intersectionNormal;
const int intersectionResult = AZ::Intersect::IntersectRayAABB(rayStart,
rayDirection,
rayDirectionReciprocal,
rayDirection.GetReciprocal(),
aabb,
intersectionT,
intersectionEndT,
@@ -117,7 +116,6 @@ namespace
const AZ::Aabb& aabb,
const AZ::Vector3& rayStart,
const AZ::Vector3& rayDirection,
const AZ::Vector3& rayDirectionReciprocal,
AzFramework::RenderGeometry::RayResult& result)
{
// Obtain the height values at each corner of the AABB.
@@ -132,26 +130,6 @@ namespace
point2.SetZ(terrainSystem.GetHeight(point2, AzFramework::Terrain::TerrainDataRequests::Sampler::DEFAULT));
point3.SetZ(terrainSystem.GetHeight(point3, AzFramework::Terrain::TerrainDataRequests::Sampler::DEFAULT));
// Construct a smaller AABB that tightly encloses the four terrain points.
const float refinedMinZ = AZStd::GetMin(AZStd::GetMin(AZStd::GetMin(point0.GetZ(), point1.GetZ()), point2.GetZ()), point3.GetZ());
const float refinedMaxZ = AZStd::GetMax(AZStd::GetMax(AZStd::GetMax(point0.GetZ(), point1.GetZ()), point2.GetZ()), point3.GetZ());
const AZ::Vector3 refinedMin(aabbMin.GetX(), aabbMin.GetY(), refinedMinZ);
const AZ::Vector3 refinedMax(aabbMax.GetX(), aabbMax.GetY(), refinedMaxZ);
const AZ::Aabb refinedAABB = AZ::Aabb::CreateFromMinMax(refinedMin, refinedMax);
// Check for a hit against the refined AABB.
float intersectionT;
float intersectionEndT;
const int intersectionResult = AZ::Intersect::IntersectRayAABB2(rayStart,
rayDirectionReciprocal,
refinedAABB,
intersectionT,
intersectionEndT);
if (intersectionResult == AZ::Intersect::ISECT_RAY_AABB_NONE)
{
return;
}
// Finally, triangulate the four terrain points and check for a hit,
// splitting using the top-left -> bottom-right diagonal so to match
// the current behavior of the terrain physics and rendering systems.
@@ -218,12 +196,10 @@ namespace
{
// Find the nearest intersection (if any) between the ray and terrain world bounds.
// Note that the ray might (and often will) start inside the terrain world bounds.
const AZ::Vector3 rayDirection = rayEnd - rayStart;
const AZ::Vector3 rayDirectionReciprocal = rayDirection.GetReciprocal();
const AZ::Vector3 rayDirection = (rayEnd - rayStart).GetNormalized();
FindNearestIntersection(terrainWorldBounds,
rayStart,
rayDirection,
rayDirectionReciprocal,
result);
if (!result)
{
@@ -327,7 +303,6 @@ namespace
currentVoxel,
rayStart,
rayDirection,
rayDirectionReciprocal,
result);
if (result)
{