diff options
| author | Egor Yusov <egor.yusov@gmail.com> | 2019-07-21 18:42:10 +0000 |
|---|---|---|
| committer | Egor Yusov <egor.yusov@gmail.com> | 2019-07-21 18:42:10 +0000 |
| commit | 843245afade24e2337491d3a7b38d9c166a9fd0b (patch) | |
| tree | 1ae92986452ba334ac424783af4d9db3a8328f9d /Common/interface | |
| parent | Math lib: updated visibility test functions (diff) | |
| download | DiligentCore-843245afade24e2337491d3a7b38d9c166a9fd0b.tar.gz DiligentCore-843245afade24e2337491d3a7b38d9c166a9fd0b.zip | |
Math lib: updated box visibility test functions to take frustum plane flags
Diffstat (limited to 'Common/interface')
| -rw-r--r-- | Common/interface/AdvancedMath.h | 148 | ||||
| -rw-r--r-- | Common/interface/BasicMath.h | 4 |
2 files changed, 98 insertions, 54 deletions
diff --git a/Common/interface/AdvancedMath.h b/Common/interface/AdvancedMath.h index e610256f..0a8d0a6b 100644 --- a/Common/interface/AdvancedMath.h +++ b/Common/interface/AdvancedMath.h @@ -23,8 +23,10 @@ #pragma once -#include "BasicMath.h" #include "../../Platforms/interface/PlatformDefinitions.h" +#include "../../Primitives/interface/FlagEnum.h" + +#include "BasicMath.h" namespace Diligent { @@ -171,24 +173,26 @@ enum class BoxVisibility FullyVisible }; -inline BoxVisibility GetBoxVisibilityAgainstPlane(const Plane3D& Plane, const BoundBox &Box) +inline BoxVisibility GetBoxVisibilityAgainstPlane(const Plane3D& Plane, const BoundBox& Box) { const float3& Normal = Plane.Normal; - float3 MaxPoint( + float3 MaxPoint + { (Normal.x > 0) ? Box.Max.x : Box.Min.x, (Normal.y > 0) ? Box.Max.y : Box.Min.y, (Normal.z > 0) ? Box.Max.z : Box.Min.z - ); - float DMax = dot( MaxPoint, Normal ) + Plane.Distance; + }; + float DMax = dot(MaxPoint, Normal) + Plane.Distance; if( DMax < 0 ) return BoxVisibility::Invisible; - float3 MinPoint( + float3 MinPoint + { (Normal.x > 0) ? Box.Min.x : Box.Max.x, (Normal.y > 0) ? Box.Min.y : Box.Max.y, (Normal.z > 0) ? Box.Min.z : Box.Max.z - ); + }; float DMin = dot(MinPoint, Normal) + Plane.Distance; if (DMin > 0) return BoxVisibility::FullyVisible; @@ -196,15 +200,48 @@ inline BoxVisibility GetBoxVisibilityAgainstPlane(const Plane3D& Plane, const Bo return BoxVisibility::Intersecting; } +// Flags must be listed in the same order as planes in the ViewFrustum struct: +// LeftPlane, RightPlane, BottomPlane, TopPlane, NearPlane, FarPlane +enum FRUSTUM_PLANE_FLAGS : Uint32 +{ + FRUSTUM_PLANE_FLAG_NONE = 0x00, + FRUSTUM_PLANE_FLAG_LEFT_PLANE = 0x01, + FRUSTUM_PLANE_FLAG_RIGHT_PLANE = 0x02, + FRUSTUM_PLANE_FLAG_BOTTOM_PLANE = 0x04, + FRUSTUM_PLANE_FLAG_TOP_PLANE = 0x08, + FRUSTUM_PLANE_FLAG_NEAR_PLANE = 0x10, + FRUSTUM_PLANE_FLAG_FAR_PLANE = 0x20, + + FRUSTUM_PLANE_FLAG_FULL_FRUSTUM = FRUSTUM_PLANE_FLAG_LEFT_PLANE | + FRUSTUM_PLANE_FLAG_RIGHT_PLANE | + FRUSTUM_PLANE_FLAG_BOTTOM_PLANE | + FRUSTUM_PLANE_FLAG_TOP_PLANE | + FRUSTUM_PLANE_FLAG_NEAR_PLANE | + FRUSTUM_PLANE_FLAG_FAR_PLANE, + + FRUSTUM_PLANE_FLAG_OPEN_NEAR = FRUSTUM_PLANE_FLAG_LEFT_PLANE | + FRUSTUM_PLANE_FLAG_RIGHT_PLANE | + FRUSTUM_PLANE_FLAG_BOTTOM_PLANE | + FRUSTUM_PLANE_FLAG_TOP_PLANE | + FRUSTUM_PLANE_FLAG_FAR_PLANE +}; +DEFINE_FLAG_ENUM_OPERATORS(FRUSTUM_PLANE_FLAGS); + // Tests if bounding box is visible by the camera -inline BoxVisibility GetBoxVisibility(const ViewFrustum &ViewFrustum, const BoundBox &Box) +inline BoxVisibility GetBoxVisibility(const ViewFrustum& ViewFrustum, + const BoundBox& Box, + FRUSTUM_PLANE_FLAGS PlaneFlags = FRUSTUM_PLANE_FLAG_FULL_FRUSTUM) { - const Plane3D *pPlanes = reinterpret_cast<const Plane3D*>(&ViewFrustum); + const Plane3D* pPlanes = reinterpret_cast<const Plane3D*>(&ViewFrustum); int NumPlanesInside = 0; - for(int iViewFrustumPlane = 0; iViewFrustumPlane < 6; iViewFrustumPlane++) + int TotalPlanes = 0; + for (int iViewFrustumPlane = 0; iViewFrustumPlane < 6; iViewFrustumPlane++) { - const Plane3D &CurrPlane = pPlanes[iViewFrustumPlane]; + if ( (PlaneFlags & (1 << iViewFrustumPlane)) == 0 ) + continue; + + const Plane3D& CurrPlane = pPlanes[iViewFrustumPlane]; auto VisibilityAgainstPlane = GetBoxVisibilityAgainstPlane(CurrPlane, Box); // If bounding box is "behind" one of the planes, it is definitely invisible @@ -214,59 +251,66 @@ inline BoxVisibility GetBoxVisibility(const ViewFrustum &ViewFrustum, const Boun // Count total number of planes the bound box is inside if (VisibilityAgainstPlane == BoxVisibility::FullyVisible) ++NumPlanesInside; + + ++TotalPlanes; } - return (NumPlanesInside == 6) ? BoxVisibility::FullyVisible : BoxVisibility::Intersecting; + return (NumPlanesInside == TotalPlanes) ? BoxVisibility::FullyVisible : BoxVisibility::Intersecting; } -inline BoxVisibility GetBoxVisibility(const ViewFrustumExt &ViewFrustumExt, const BoundBox &Box) +inline BoxVisibility GetBoxVisibility(const ViewFrustumExt& ViewFrustumExt, + const BoundBox& Box, + FRUSTUM_PLANE_FLAGS PlaneFlags = FRUSTUM_PLANE_FLAG_FULL_FRUSTUM) { - auto Visibility = GetBoxVisibility(static_cast<const ViewFrustum&>(ViewFrustumExt), Box); + auto Visibility = GetBoxVisibility(static_cast<const ViewFrustum&>(ViewFrustumExt), Box, PlaneFlags); if (Visibility == BoxVisibility::FullyVisible || Visibility == BoxVisibility::Invisible) return Visibility; - // Additionally test if the whole frustum is outside one of - // the the bounding box planes. This helps in the following situation: - // - // - // . - // / ' . . - // / AABB / . ' | - // / /. ' | - // ' . / | | - // * . | | - // ' . | - // ' . | - // ' . - - // Test all frustum corners against every bound box plane - for(int iBoundBoxPlane = 0; iBoundBoxPlane < 6; ++iBoundBoxPlane) + if ((PlaneFlags & FRUSTUM_PLANE_FLAG_FULL_FRUSTUM) == FRUSTUM_PLANE_FLAG_FULL_FRUSTUM) { - // struct BoundBox - // { - // float3 Min; - // float3 Max; - // }; - float CurrPlaneCoord = reinterpret_cast<const float*>(&Box)[iBoundBoxPlane]; - // Bound box normal is one of the axis, so we just need to pick the right coordinate - int iCoordOrder = iBoundBoxPlane % 3; // 0, 1, 2, 0, 1, 2 - // Since plane normal is directed along one of the axis, we only need to select - // if it is pointing in the positive (max planes) or negative (min planes) direction - float fSign = (iBoundBoxPlane >= 3) ? +1.f : -1.f; - bool bAllCornersOutside = true; - for(int iCorner=0; iCorner < 8; iCorner++) + // Additionally test if the whole frustum is outside one of + // the the bounding box planes. This helps in the following situation: + // + // + // . + // / ' . . + // / AABB / . ' | + // / /. ' | + // ' . / | | + // * . | | + // ' . | + // ' . | + // ' . + + // Test all frustum corners against every bound box plane + for (int iBoundBoxPlane = 0; iBoundBoxPlane < 6; ++iBoundBoxPlane) { - // Pick the frustum corner coordinate - float CurrCornerCoord = ViewFrustumExt.FrustumCorners[iCorner][iCoordOrder]; - // Dot product is simply the coordinate difference multiplied by the sign - if( fSign * (CurrPlaneCoord - CurrCornerCoord) > 0) - { - bAllCornersOutside = false; - break; + // struct BoundBox + // { + // float3 Min; + // float3 Max; + // }; + float CurrPlaneCoord = reinterpret_cast<const float*>(&Box)[iBoundBoxPlane]; + // Bound box normal is one of the axis, so we just need to pick the right coordinate + int iCoordOrder = iBoundBoxPlane % 3; // 0, 1, 2, 0, 1, 2 + // Since plane normal is directed along one of the axis, we only need to select + // if it is pointing in the positive (max planes) or negative (min planes) direction + float fSign = (iBoundBoxPlane >= 3) ? +1.f : -1.f; + bool bAllCornersOutside = true; + for (int iCorner=0; iCorner < 8; iCorner++) + { + // Pick the frustum corner coordinate + float CurrCornerCoord = ViewFrustumExt.FrustumCorners[iCorner][iCoordOrder]; + // Dot product is simply the coordinate difference multiplied by the sign + if (fSign * (CurrPlaneCoord - CurrCornerCoord) > 0) + { + bAllCornersOutside = false; + break; + } } + if (bAllCornersOutside) + return BoxVisibility::Invisible; } - if( bAllCornersOutside ) - return BoxVisibility::Invisible; } return BoxVisibility::Intersecting; diff --git a/Common/interface/BasicMath.h b/Common/interface/BasicMath.h index 77a80bcd..8e720034 100644 --- a/Common/interface/BasicMath.h +++ b/Common/interface/BasicMath.h @@ -44,11 +44,11 @@ /// Since mul(WorldViewProj, WorldPos) == mul(WorldPos, transpose(WorldViewProj)), the results will /// be consistent with D3D case. -#include "../../Platforms/Basic/interface/DebugUtilities.h" - #include <cmath> #include <algorithm> +#include "../../Platforms/Basic/interface/DebugUtilities.h" + #include "HashUtils.h" #ifdef _MSC_VER |
