From 8e24a0919d30f939140e776bc5e64bd77767e99c Mon Sep 17 00:00:00 2001 From: Egor Yusov Date: Sun, 12 Nov 2017 18:54:50 -0800 Subject: Updated to Diligent Engine 2.1 --- Common/interface/AdvancedMath.h | 308 ++++++++++++++++++++++++++++++++++------ Common/interface/BasicMath.h | 75 ++++++++-- Common/interface/Object.h | 2 +- 3 files changed, 325 insertions(+), 60 deletions(-) (limited to 'Common/interface') diff --git a/Common/interface/AdvancedMath.h b/Common/interface/AdvancedMath.h index d90488f7..a4287b67 100644 --- a/Common/interface/AdvancedMath.h +++ b/Common/interface/AdvancedMath.h @@ -37,91 +37,311 @@ struct ViewFrustum Plane3D LeftPlane, RightPlane, BottomPlane, TopPlane, NearPlane, FarPlane; }; +struct ViewFrustumExt : public ViewFrustum +{ + float3 FrustumCorners[8]; +}; + // For OpenGL, matrix is still considered row-major. The only difference is that // near clip plane is at -1, not 0. -inline void ExtractViewFrustumPlanesFromMatrix(const float4x4 &Matrix, ViewFrustum &ViewFrustum, bool bIsDirectX) +inline void ExtractViewFrustumPlanesFromMatrix(const float4x4 &Matrix, ViewFrustum &Frustum, bool bIsDirectX) { // For more details, see Gribb G., Hartmann K., "Fast Extraction of Viewing Frustum Planes from the // World-View-Projection Matrix" (the paper is available at // http://gamedevs.org/uploads/fast-extraction-viewing-frustum-planes-from-world-view-projection-matrix.pdf) // Left clipping plane - ViewFrustum.LeftPlane.Normal.x = Matrix._14 + Matrix._11; - ViewFrustum.LeftPlane.Normal.y = Matrix._24 + Matrix._21; - ViewFrustum.LeftPlane.Normal.z = Matrix._34 + Matrix._31; - ViewFrustum.LeftPlane.Distance = Matrix._44 + Matrix._41; + Frustum.LeftPlane.Normal.x = Matrix._14 + Matrix._11; + Frustum.LeftPlane.Normal.y = Matrix._24 + Matrix._21; + Frustum.LeftPlane.Normal.z = Matrix._34 + Matrix._31; + Frustum.LeftPlane.Distance = Matrix._44 + Matrix._41; // Right clipping plane - ViewFrustum.RightPlane.Normal.x = Matrix._14 - Matrix._11; - ViewFrustum.RightPlane.Normal.y = Matrix._24 - Matrix._21; - ViewFrustum.RightPlane.Normal.z = Matrix._34 - Matrix._31; - ViewFrustum.RightPlane.Distance = Matrix._44 - Matrix._41; + Frustum.RightPlane.Normal.x = Matrix._14 - Matrix._11; + Frustum.RightPlane.Normal.y = Matrix._24 - Matrix._21; + Frustum.RightPlane.Normal.z = Matrix._34 - Matrix._31; + Frustum.RightPlane.Distance = Matrix._44 - Matrix._41; // Top clipping plane - ViewFrustum.TopPlane.Normal.x = Matrix._14 - Matrix._12; - ViewFrustum.TopPlane.Normal.y = Matrix._24 - Matrix._22; - ViewFrustum.TopPlane.Normal.z = Matrix._34 - Matrix._32; - ViewFrustum.TopPlane.Distance = Matrix._44 - Matrix._42; + Frustum.TopPlane.Normal.x = Matrix._14 - Matrix._12; + Frustum.TopPlane.Normal.y = Matrix._24 - Matrix._22; + Frustum.TopPlane.Normal.z = Matrix._34 - Matrix._32; + Frustum.TopPlane.Distance = Matrix._44 - Matrix._42; // Bottom clipping plane - ViewFrustum.BottomPlane.Normal.x = Matrix._14 + Matrix._12; - ViewFrustum.BottomPlane.Normal.y = Matrix._24 + Matrix._22; - ViewFrustum.BottomPlane.Normal.z = Matrix._34 + Matrix._32; - ViewFrustum.BottomPlane.Distance = Matrix._44 + Matrix._42; + Frustum.BottomPlane.Normal.x = Matrix._14 + Matrix._12; + Frustum.BottomPlane.Normal.y = Matrix._24 + Matrix._22; + Frustum.BottomPlane.Normal.z = Matrix._34 + Matrix._32; + Frustum.BottomPlane.Distance = Matrix._44 + Matrix._42; // Near clipping plane if( bIsDirectX ) { // 0 <= z <= w - ViewFrustum.NearPlane.Normal.x = Matrix._13; - ViewFrustum.NearPlane.Normal.y = Matrix._23; - ViewFrustum.NearPlane.Normal.z = Matrix._33; - ViewFrustum.NearPlane.Distance = Matrix._43; + Frustum.NearPlane.Normal.x = Matrix._13; + Frustum.NearPlane.Normal.y = Matrix._23; + Frustum.NearPlane.Normal.z = Matrix._33; + Frustum.NearPlane.Distance = Matrix._43; } else { // -w <= z <= w - ViewFrustum.NearPlane.Normal.x = Matrix._14 + Matrix._13; - ViewFrustum.NearPlane.Normal.y = Matrix._24 + Matrix._23; - ViewFrustum.NearPlane.Normal.z = Matrix._34 + Matrix._33; - ViewFrustum.NearPlane.Distance = Matrix._44 + Matrix._43; + Frustum.NearPlane.Normal.x = Matrix._14 + Matrix._13; + Frustum.NearPlane.Normal.y = Matrix._24 + Matrix._23; + Frustum.NearPlane.Normal.z = Matrix._34 + Matrix._33; + Frustum.NearPlane.Distance = Matrix._44 + Matrix._43; } // Far clipping plane - ViewFrustum.FarPlane.Normal.x = Matrix._14 - Matrix._13; - ViewFrustum.FarPlane.Normal.y = Matrix._24 - Matrix._23; - ViewFrustum.FarPlane.Normal.z = Matrix._34 - Matrix._33; - ViewFrustum.FarPlane.Distance = Matrix._44 - Matrix._43; + Frustum.FarPlane.Normal.x = Matrix._14 - Matrix._13; + Frustum.FarPlane.Normal.y = Matrix._24 - Matrix._23; + Frustum.FarPlane.Normal.z = Matrix._34 - Matrix._33; + Frustum.FarPlane.Distance = Matrix._44 - Matrix._43; } +inline void ExtractViewFrustumPlanesFromMatrix(const float4x4 &Matrix, ViewFrustumExt &FrustumExt, bool bIsDirectX) +{ + ExtractViewFrustumPlanesFromMatrix(Matrix, static_cast(FrustumExt), bIsDirectX); + + // Compute frustum corners + float4x4 InvMatrix = inverseMatrix(Matrix); + + float nearClipZ = bIsDirectX ? 0.f : -1.f; + static const float3 ProjSpaceCorners[] = + { + float3(-1,-1, nearClipZ), + float3( 1,-1, nearClipZ), + float3(-1, 1, nearClipZ), + float3( 1, 1, nearClipZ), + + float3(-1,-1, 1), + float3( 1,-1, 1), + float3(-1, 1, 1), + float3( 1, 1, 1), + }; + for(int i = 0; i < 8; ++i) + FrustumExt.FrustumCorners[i] = ProjSpaceCorners[i] * InvMatrix; +} struct BoundBox { + // Order must not be changed! float fMinX, fMaxX, fMinY, fMaxY, fMinZ, fMaxZ; }; +enum class BoxVisibility +{ + // Bounding box is guaranteed to be outside of the view frustum + // . + // . ' | + // . ' | + // | | + // . | + // ___ ' . | + // | | ' . + // |___| + // + Invisible, + + // Bounding box intersects the frustum + // . + // . ' | + // . ' | + // | | + // _.__ | + // | '|. | + // |____| ' . + // + Intersecting, + + // Bounding box is fully inside the view frustum + // . + // . ' | + // . '___ | + // | | | | + // . |___| | + // ' . | + // ' . + // + FullyVisible +}; + +template +inline BoxVisibility GetBoxVisibilityAgainstPlane(const Plane3D& Plane, const BoundBox &Box) +{ + const float3& Normal = Plane.Normal; + + float3 MaxPoint( + (Normal.x > 0) ? Box.fMaxX : Box.fMinX, + (Normal.y > 0) ? Box.fMaxY : Box.fMinY, + (Normal.z > 0) ? Box.fMaxZ : Box.fMinZ + ); + + float DMax = dot( MaxPoint, Normal ) + Plane.Distance; + + if( DMax < 0 ) + return BoxVisibility::Invisible; + + if (TestFullVisibility) + { + float3 MinPoint( + (Normal.x > 0) ? Box.fMinX : Box.fMaxX, + (Normal.y > 0) ? Box.fMinY : Box.fMaxY, + (Normal.z > 0) ? Box.fMinZ : Box.fMaxZ + ); + + float DMin = dot(MinPoint, Normal) + Plane.Distance; + + if (DMin > 0) + return BoxVisibility::FullyVisible; + } + + return BoxVisibility::Intersecting; +} + // Tests if bounding box is visible by the camera -inline bool IBoxVisible(const ViewFrustum &ViewFrustum, const BoundBox &Box) +template +inline BoxVisibility GetBoxVisibility(const ViewFrustum &ViewFrustum, const BoundBox &Box) { - Plane3D *pPlanes = (Plane3D *)&ViewFrustum; - // If bounding box is "behind" some plane, then it is invisible - // Otherwise it is treated as visible + const Plane3D *pPlanes = reinterpret_cast(&ViewFrustum); + + int NumPlanesInside = 0; for(int iViewFrustumPlane = 0; iViewFrustumPlane < 6; iViewFrustumPlane++) { - Plane3D *pCurrPlane = pPlanes + iViewFrustumPlane; - float3 *pCurrNormal = &pCurrPlane->Normal; - float3 MaxPoint; - - MaxPoint.x = (pCurrNormal->x > 0) ? Box.fMaxX : Box.fMinX; - MaxPoint.y = (pCurrNormal->y > 0) ? Box.fMaxY : Box.fMinY; - MaxPoint.z = (pCurrNormal->z > 0) ? Box.fMaxZ : Box.fMinZ; - - float DMax = dot( MaxPoint, *pCurrNormal ) + pCurrPlane->Distance; + const Plane3D &CurrPlane = pPlanes[iViewFrustumPlane]; + auto VisibilityAgainstPlane = GetBoxVisibilityAgainstPlane(CurrPlane, Box); - if( DMax < 0 ) - return false; + // If bounding box is "behind" one of the planes, it is definitely invisible + if (VisibilityAgainstPlane == BoxVisibility::Invisible) + return BoxVisibility::Invisible; + + // Count total number of planes the bound box is inside + if (VisibilityAgainstPlane == BoxVisibility::FullyVisible) + ++NumPlanesInside; + } + + return (TestFullVisibility && NumPlanesInside == 6) ? BoxVisibility::FullyVisible : BoxVisibility::Intersecting; +} + +template +inline BoxVisibility GetBoxVisibility(const ViewFrustumExt &ViewFrustumExt, const BoundBox &Box) +{ + auto Visibility = GetBoxVisibility(static_cast(ViewFrustumExt), Box); + 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 / . ' | + // / /. ' | + // ' . / | | + // * . | | + // ' . | + // ' . | + // ' . + + for(int iBoundBoxPlane = 0; iBoundBoxPlane < 6; ++iBoundBoxPlane) + { + // struct BoundBox + // { + // float fMinX, fMaxX, fMinY, fMaxY, fMinZ, fMaxZ; + // }; + float CurrPlaneCoord = reinterpret_cast(&Box)[iBoundBoxPlane]; + int iCoordOrder = iBoundBoxPlane / 2; // 0, 0, 1, 1, 2, 2 + float fSign = (iBoundBoxPlane & 0x01) ? +1.f : -1.f; + bool bAllCornersOutside = true; + for(int iCorner=0; iCorner < 8; iCorner++) + { + float CurrCornerCoord = ViewFrustumExt.FrustumCorners[iCorner][iCoordOrder]; + if( fSign * (CurrPlaneCoord - CurrCornerCoord) > 0) + { + bAllCornersOutside = false; + break; + } + } + if( bAllCornersOutside ) + return BoxVisibility::Invisible; } + return BoxVisibility::Intersecting; +} + +inline float GetPointToBoxDistance(const BoundBox &BndBox, const float3 &Pos) +{ + VERIFY_EXPR(BndBox.fMaxX >= BndBox.fMinX && + BndBox.fMaxY >= BndBox.fMinY && + BndBox.fMaxZ >= BndBox.fMinZ); + float fdX = (Pos.x > BndBox.fMaxX) ? (Pos.x - BndBox.fMaxX) : ( (Pos.x < BndBox.fMinX) ? (BndBox.fMinX - Pos.x) : 0.f ); + float fdY = (Pos.y > BndBox.fMaxY) ? (Pos.y - BndBox.fMaxY) : ( (Pos.y < BndBox.fMinY) ? (BndBox.fMinY - Pos.y) : 0.f ); + float fdZ = (Pos.z > BndBox.fMaxZ) ? (Pos.z - BndBox.fMaxZ) : ( (Pos.z < BndBox.fMinZ) ? (BndBox.fMinZ - Pos.z) : 0.f ); + VERIFY_EXPR(fdX >= 0 && fdY >= 0 && fdZ >= 0); + + float3 RangeVec(fdX, fdY, fdZ); + return length( RangeVec ); +} + +inline bool operator == (const Plane3D &p1, const Plane3D &p2) +{ + return p1.Normal == p2.Normal && + p1.Distance == p2.Distance; +} + +inline bool operator == (const ViewFrustum &f1, const ViewFrustum &f2) +{ + return f1.LeftPlane == f2.LeftPlane && + f1.RightPlane == f2.RightPlane && + f1.BottomPlane == f2.BottomPlane && + f1.TopPlane == f2.TopPlane && + f1.NearPlane == f2.NearPlane && + f1.FarPlane == f2.FarPlane; +} + +inline bool operator == (const ViewFrustumExt &f1, const ViewFrustumExt &f2) +{ + if (! (static_cast(f1) == static_cast(f2)) ) + return false; + + for (int c = 0; c < _countof(f1.FrustumCorners); ++c) + if (f1.FrustumCorners[c] != f2.FrustumCorners[c]) + return false; + return true; } + +namespace std +{ + template<> + struct hash + { + size_t operator()( const Plane3D &Plane ) const + { + return Diligent::ComputeHash(Plane.Normal, Plane.Distance); + } + }; + + template<> + struct hash + { + size_t operator()( const ViewFrustum &Frustum ) const + { + return Diligent::ComputeHash(Frustum.LeftPlane, Frustum.RightPlane, Frustum.BottomPlane, Frustum.TopPlane, Frustum.NearPlane, Frustum.FarPlane); + } + }; + + template<> + struct hash + { + size_t operator()( const ViewFrustumExt &Frustum ) const + { + auto Seed = Diligent::ComputeHash(static_cast(Frustum)); + for (int Corner = 0; Corner < _countof(Frustum.FrustumCorners); ++Corner) + Diligent::HashCombine(Seed, Frustum.FrustumCorners[Corner]); + return Seed; + } + }; +} diff --git a/Common/interface/BasicMath.h b/Common/interface/BasicMath.h index b1ecdf17..1e7ebc9a 100644 --- a/Common/interface/BasicMath.h +++ b/Common/interface/BasicMath.h @@ -35,8 +35,7 @@ #define _USE_MATH_DEFINES #include -// This header defines math and matrix helper functions and structures used -// by DirectX SDK samples. +#include "HashUtils.h" // Common Constants @@ -930,16 +929,13 @@ inline float4x4 scaleMatrix(float x, float y, float z) 0, 0, 0, 1); } -inline float4x4 rotationX(float degreeX) +inline float4x4 rotationX(float angleInRadians) { - float angleInRadians = degreeX * (PI_F / 180.0f); - float sinAngle = sinf(angleInRadians); float cosAngle = cosf(angleInRadians); float4x4 mOut; - UNSUPPORTED("This function is not tested, it might be incorrect.") mOut._11 = 1.0f; mOut._12 = 0.0f; mOut._13 = 0.0f; mOut._14 = 0.0f; mOut._21 = 0.0f; mOut._22 = cosAngle; mOut._23 = -sinAngle; mOut._24 = 0.0f; mOut._31 = 0.0f; mOut._32 = sinAngle; mOut._33 = cosAngle; mOut._34 = 0.0f; @@ -948,16 +944,13 @@ inline float4x4 rotationX(float degreeX) return mOut; } -inline float4x4 rotationY(float degreeY) +inline float4x4 rotationY(float angleInRadians) { - float angleInRadians = degreeY * (PI_F / 180.0f); - float sinAngle = sinf(angleInRadians); float cosAngle = cosf(angleInRadians); float4x4 mOut; - UNSUPPORTED("This function is not tested, it might be incorrect.") mOut._11 = cosAngle; mOut._12 = 0.0f; mOut._13 = sinAngle; mOut._14 = 0.0f; mOut._21 = 0.0f; mOut._22 = 1.0f; mOut._23 = 0.0f; mOut._24 = 0.0f; mOut._31 = -sinAngle; mOut._32 = 0.0f; mOut._33 = cosAngle; mOut._34 = 0.0f; @@ -966,16 +959,13 @@ inline float4x4 rotationY(float degreeY) return mOut; } -inline float4x4 rotationZ(float degreeZ) +inline float4x4 rotationZ(float angleInRadians) { - float angleInRadians = degreeZ * (PI_F / 180.0f); - float sinAngle = sinf(angleInRadians); float cosAngle = cosf(angleInRadians); float4x4 mOut; - UNSUPPORTED("This function is not tested, it might be incorrect.") mOut._11 = cosAngle; mOut._12 = -sinAngle; mOut._13 = 0.0f; mOut._14 = 0.0f; mOut._21 = sinAngle; mOut._22 = cosAngle; mOut._23 = 0.0f; mOut._24 = 0.0f; mOut._31 = 0.0f; mOut._32 = 0.0f; mOut._33 = 1.0f; mOut._34 = 0.0f; @@ -1341,4 +1331,59 @@ namespace std std::min( Left.w, Right.w ) ); } -} \ No newline at end of file + + + template + struct hash> + { + size_t operator()( const Vector2 &v2 ) const + { + return Diligent::ComputeHash(v2.x, v2.y); + } + }; + + template + struct hash> + { + size_t operator()( const Vector3 &v3 ) const + { + return Diligent::ComputeHash(v3.x, v3.y, v3.z); + } + }; + + template + struct hash> + { + size_t operator()( const Vector4 &v4 ) const + { + return Diligent::ComputeHash(v4.x, v4.y, v4.z, v4.w); + } + }; + + template + struct hash> + { + size_t operator()( const Matrix3x3 &m ) const + { + return Diligent::ComputeHash( + m._m00, m._m01, m._m02, + m._m10, m._m11, m._m12, + m._m20, m._m21, m._m22 + ); + } + }; + + template + struct hash> + { + size_t operator()( const Matrix4x4 &m ) const + { + return Diligent::ComputeHash( + m._m00, m._m01, m._m02, m._m03, + m._m10, m._m11, m._m12, m._m13, + m._m20, m._m21, m._m22, m._m23, + m._m30, m._m31, m._m32, m._m33 + ); + } + }; +} diff --git a/Common/interface/Object.h b/Common/interface/Object.h index 88181522..a4ac6c2d 100644 --- a/Common/interface/Object.h +++ b/Common/interface/Object.h @@ -71,7 +71,7 @@ public: /// Returns the pointer to IReferenceCounters interface of the associated - /// reference counters object. The metod does *NOT* increment + /// reference counters object. The method does *NOT* increment /// the number of strong references to the returned object. virtual IReferenceCounters* GetReferenceCounters()const = 0; }; -- cgit v1.2.3