@ -11,6 +11,7 @@
*/
# include <AzCore/std/numeric.h>
# include <AzCore/std/limits.h>
# include <Atom/RPI.Reflect/Model/ModelKdTree.h>
# include <AzCore/Math/IntersectSegment.h>
@ -191,10 +192,10 @@ namespace AZ
if ( ModelLodAsset * lodAssetPtr = model - > GetLodAssets ( ) [ 0 ] . Get ( ) )
{
AZ_Warning ( " ModelKdTree " , lodAssetPtr - > GetMeshes ( ) . size ( ) < = s td: : numeric_limits < AZ : : u8 > : : max ( ) + 1 ,
AZ_Warning ( " ModelKdTree " , lodAssetPtr - > GetMeshes ( ) . size ( ) < = AZS td: : numeric_limits < AZ : : u8 > : : max ( ) + 1 ,
" KdTree generation doesn't support models with greater than 256 meshes. RayIntersection results will be incorrect "
" unless the meshes are merged or broken up into multiple models " ) ;
const size_t size = AZStd : : min < size_t > ( lodAssetPtr - > GetMeshes ( ) . size ( ) , s td: : numeric_limits < AZ : : u8 > : : max ( ) + 1 ) ;
const size_t size = AZStd : : min < size_t > ( lodAssetPtr - > GetMeshes ( ) . size ( ) , AZS td: : numeric_limits < AZ : : u8 > : : max ( ) + 1 ) ;
m_meshes . reserve ( size ) ;
AZStd : : transform (
lodAssetPtr - > GetMeshes ( ) . begin ( ) , AZStd : : next ( lodAssetPtr - > GetMeshes ( ) . begin ( ) , size ) ,
@ -204,20 +205,42 @@ namespace AZ
}
}
bool ModelKdTree : : RayIntersection ( const AZ : : Vector3 & raySrc , const AZ : : Vector3 & rayDir , float & distance , AZ : : Vector3 & normal ) const
bool ModelKdTree : : RayIntersection (
const AZ : : Vector3 & raySrc , const AZ : : Vector3 & rayDir , float & distanceNormalized , AZ : : Vector3 & normal ) const
{
return RayIntersectionRecursively ( m_pRootNode . get ( ) , raySrc , rayDir , distance , normal ) ;
float closestDistanceNormalized = AZStd : : numeric_limits < float > : : max ( ) ;
if ( RayIntersectionRecursively ( m_pRootNode . get ( ) , raySrc , rayDir , closestDistanceNormalized , normal ) )
{
distanceNormalized = closestDistanceNormalized ;
return true ;
}
return false ;
}
bool ModelKdTree : : RayIntersectionRecursively ( ModelKdTreeNode * pNode , const AZ : : Vector3 & raySrc , const AZ : : Vector3 & rayDir , float & distance , AZ : : Vector3 & normal ) const
bool ModelKdTree : : RayIntersectionRecursively (
ModelKdTreeNode * pNode ,
const AZ : : Vector3 & raySrc ,
const AZ : : Vector3 & rayDir ,
float & distanceNormalized ,
AZ : : Vector3 & normal ) const
{
using Intersect : : IntersectRayAABB2 ;
using Intersect : : IntersectSegmentTriangleCCW ;
using Intersect : : ISECT_RAY_AABB_NONE ;
if ( ! pNode )
{
return false ;
}
float start , end ;
if ( AZ : : Intersect : : IntersectRayAABB2 ( raySrc , rayDir . GetReciprocal ( ) , pNode - > GetBoundBox ( ) , start , end ) = = Intersect : : ISECT_RAY_AABB_NONE )
if ( IntersectRayAABB2 ( raySrc , rayDir . GetReciprocal ( ) , pNode - > GetBoundBox ( ) , start , end ) = = ISECT_RAY_AABB_NONE )
{
return false ;
}
if ( start > distanceNormalized )
{
return false ;
}
@ -235,17 +258,13 @@ namespace AZ
return false ;
}
AZ : : Vector3 intersectionNormal ;
float hitDistanceNormalized ;
const float maxDist ( FLT_MAX ) ;
float nearestDist = maxDist ;
float nearestDistanceNormalized = distanceNormalized ;
for ( AZ : : u32 i = 0 ; i < nVBuffSize ; + + i )
{
const auto & [ first , second , third ] = pNode - > GetVertexIndex ( i ) ;
const AZ : : u32 nObjIndex = pNode - > GetObjIndex ( i ) ;
AZStd : : array_view < float > positionBuffer = m_meshes [ nObjIndex ] . m_vertexData ;
const AZStd : : array_view < float > positionBuffer = m_meshes [ nObjIndex ] . m_vertexData ;
if ( positionBuffer . empty ( ) )
{
@ -258,25 +277,23 @@ namespace AZ
AZ : : Vector3 { positionBuffer [ third * 3 + 0 ] , positionBuffer [ third * 3 + 1 ] , positionBuffer [ third * 3 + 2 ] } ,
} ;
const AZ : : Vector3 rayEnd = raySrc + rayDir * distance ;
if ( AZ : : Intersect : : IntersectSegmentTriangleCCW ( raySrc , rayEnd , trianglePoints [ 0 ] , trianglePoints [ 1 ] , trianglePoints [ 2 ] ,
intersectionNormal , hitDistanceNormalized ) ! = Intersect : : ISECT_RAY_AABB_NONE )
float hitDistanceNormalized ;
AZ : : Vector3 intersectionNormal ;
const AZ : : Vector3 rayEnd = raySrc + rayDir ;
if ( IntersectSegmentTriangleCCW ( raySrc , rayEnd , trianglePoints [ 0 ] , trianglePoints [ 1 ] , trianglePoints [ 2 ] ,
intersectionNormal , hitDistanceNormalized ) ! = ISECT_RAY_AABB_NONE )
{
float hitDistance = hitDistanceNormalized * distance ;
if ( nearestDist > hitDistance )
if ( nearestDistanceNormalized > hitDistanceNormalized )
{
normal = intersectionNormal ;
nearestDistanceNormalized = hitDistanceNormalized ;
}
nearestDist = AZStd : : GetMin ( nearestDist , hitDistance ) ;
}
}
if ( nearestDist < maxDist )
if ( nearestDist anceNormalized < distanceNormalized )
{
distance = AZStd : : GetMin ( distance , nearestDist ) ;
distance Normalized = nearestDistanceNormalized ;
return true ;
}
@ -284,8 +301,8 @@ namespace AZ
}
// running both sides to find the closest intersection
const bool bFoundChild0 = RayIntersectionRecursively ( pNode - > GetChild ( 0 ) , raySrc , rayDir , distance , normal ) ;
const bool bFoundChild1 = RayIntersectionRecursively ( pNode - > GetChild ( 1 ) , raySrc , rayDir , distance , normal ) ;
const bool bFoundChild0 = RayIntersectionRecursively ( pNode - > GetChild ( 0 ) , raySrc , rayDir , distance Normalized , normal ) ;
const bool bFoundChild1 = RayIntersectionRecursively ( pNode - > GetChild ( 1 ) , raySrc , rayDir , distance Normalized , normal ) ;
return bFoundChild0 | | bFoundChild1 ;
}
@ -311,5 +328,5 @@ namespace AZ
GetPenetratedBoxesRecursively ( pNode - > GetChild ( 0 ) , raySrc , rayDir , outBoxes ) ;
GetPenetratedBoxesRecursively ( pNode - > GetChild ( 1 ) , raySrc , rayDir , outBoxes ) ;
}
}
}
} // namespace RPI
} // namespace AZ