DragonNest/Common/EngineUtil/EtCollisionPrimitive.cpp
Cussrro 47f7895977 Revert "修复编码问题"
This reverts commit 9e69c01767.
2024-12-21 10:04:04 +08:00

161 lines
No EOL
5.3 KiB
C++

#include "Stdafx.h"
#include "EtCollisionPrimitive.h"
#include "EtComputeDist.h"
#ifdef _DEBUG
#define new new(_NORMAL_BLOCK,__FILE__,__LINE__)
#endif
void UpdateCollisionPrimitive( SCollisionPrimitive &DestPrimitive, SCollisionPrimitive &SourPrimitive, const EtMatrix &WorldMat, const EtVector3 &vScale )
{
float fScale = max( max( vScale.x, vScale.y ), vScale.z );
switch( SourPrimitive.Type )
{
case CT_BOX:
{
SCollisionBox *pDestBox = ( SCollisionBox * )&DestPrimitive;
SCollisionBox *pSourBox = ( SCollisionBox * )&SourPrimitive;
int i;
EtVec3TransformCoord( &pDestBox->vCenter, &pSourBox->vCenter, &WorldMat );
EtMatrix WorldNormalMat = WorldMat;
EtVector3 vLength;
vLength.x = EtVec3Length((EtVector3*)&WorldNormalMat._11);
vLength.y = EtVec3Length((EtVector3*)&WorldNormalMat._21);
vLength.z = EtVec3Length((EtVector3*)&WorldNormalMat._31);
*(EtVector3*)(&WorldNormalMat._11) /= vLength.x;
*(EtVector3*)(&WorldNormalMat._21) /= vLength.y;
*(EtVector3*)(&WorldNormalMat._31) /= vLength.z;
// Non-Uniform Scale Matrix 로 좌표계를 변환할 경우 변환뒤에 Normalize를 해주더라도
// 세개의 축이 직교함을 보장하지 못하므로, 미리 Orthogonal Matrix 로 만든뒤 변환한다.
EtMatrix InvWorldMat;
EtMatrixInverse( &InvWorldMat, NULL, &WorldMat );
for( i = 0; i < 3; i++ )
{
EtVec3TransformNormal( pDestBox->vAxis + i, pSourBox->vAxis + i, &WorldNormalMat );
pDestBox->fExtent[ i ] = pSourBox->fExtent[ i ] * ((FLOAT*)&vLength.x)[ i ];
}
}
break;
case CT_SPHERE:
{
SCollisionSphere *pDestSphere = ( SCollisionSphere * )&DestPrimitive;
SCollisionSphere *pSourSphere = ( SCollisionSphere * )&SourPrimitive;
EtVec3TransformCoord( &pDestSphere->vCenter, &pSourSphere->vCenter, &WorldMat );
pDestSphere->fRadius = pSourSphere->fRadius * fScale;
}
break;
case CT_CAPSULE:
{
SCollisionCapsule *pDestCapsule = ( SCollisionCapsule * )&DestPrimitive;
SCollisionCapsule *pSourCapsule = ( SCollisionCapsule * )&SourPrimitive;
EtVec3TransformCoord( &pDestCapsule->Segment.vOrigin, &pSourCapsule->Segment.vOrigin, &WorldMat );
EtVector3 vOriginFar = pSourCapsule->Segment.vOrigin + pSourCapsule->Segment.vDirection;
EtVec3TransformCoord( &vOriginFar, &vOriginFar, &WorldMat );
pDestCapsule->Segment.vDirection = vOriginFar - pDestCapsule->Segment.vOrigin;
pDestCapsule->fRadius = pSourCapsule->fRadius * fScale;
if( fScale != 1.0f )
{
pDestCapsule->Segment.vOrigin = pDestCapsule->Segment.vOrigin - ( fScale - 1.0f ) * 0.5f * pDestCapsule->Segment.vDirection;
pDestCapsule->Segment.vDirection += pDestCapsule->Segment.vDirection * ( fScale - 1.0f ) * 0.5f;
}
}
break;
case CT_TRIANGLE_LIST:
{
SCollisionTriangleList *pDestTriList = ( SCollisionTriangleList * )&DestPrimitive;
SCollisionTriangleList *pSourTriList = ( SCollisionTriangleList * )&SourPrimitive;
int i;
pDestTriList->vecTriangle.resize( pSourTriList->vecTriangle.size() );
for( i = 0; i < ( int )pDestTriList->vecTriangle.size(); i++ )
{
EtVector3 vPoint[ 3 ];
vPoint[ 0 ] = pSourTriList->vecTriangle[ i ].vOrigin;
vPoint[ 1 ] = pSourTriList->vecTriangle[ i ].vOrigin + pSourTriList->vecTriangle[ i ].vEdge1;
vPoint[ 2 ] = pSourTriList->vecTriangle[ i ].vOrigin + pSourTriList->vecTriangle[ i ].vEdge2;
EtVec3TransformCoordArray( vPoint, sizeof( EtVector3 ), vPoint, sizeof( EtVector3 ), &WorldMat, 3 );
pDestTriList->vecTriangle[ i ].vOrigin = vPoint[ 0 ];
pDestTriList->vecTriangle[ i ].vEdge1 = vPoint[ 1 ] - vPoint[ 0 ];
pDestTriList->vecTriangle[ i ].vEdge2 = vPoint[ 2 ] - vPoint[ 0 ];
}
}
break;
}
}
bool IsInside( SCollisionPrimitive &Primitive, EtVector3 &vPoint )
{
switch( Primitive.Type )
{
case CT_BOX:
{
SCollisionBox *pBox = ( SCollisionBox * )&Primitive;
EtVector3 vVertex = vPoint - pBox->vCenter;
float fDot = fabs( EtVec3Dot( &pBox->vAxis[ 0 ], &vVertex ) );
if( fDot > pBox->fExtent[ 0 ] ) return false;
fDot = fabs( EtVec3Dot( &pBox->vAxis[ 1 ], &vVertex ) );
if( fDot > pBox->fExtent[ 1 ] ) return false;
fDot = fabs( EtVec3Dot( &pBox->vAxis[ 2 ], &vVertex ) );
if( fDot > pBox->fExtent[ 2 ] ) return false;
return true;
}
break;
case CT_SPHERE:
{
SCollisionSphere *pSphere = ( SCollisionSphere * )&Primitive;
float fLengthSq;
fLengthSq = EtVec3LengthSq( &( vPoint - pSphere->vCenter ) );
return fLengthSq <= pSphere->fRadius * pSphere->fRadius;
}
break;
case CT_CAPSULE:
{
SCollisionCapsule *pCapsule = ( SCollisionCapsule * )&Primitive;
float fSegParam, fLengthSq;
fLengthSq = DistPointToSegment( vPoint, pCapsule->Segment, fSegParam );
return fLengthSq <= pCapsule->fRadius * pCapsule->fRadius;
}
break;
default:
return false;
}
}
void GetCenterPos( SCollisionPrimitive &Primitive, EtVector3 &vPoint )
{
switch( Primitive.Type )
{
case CT_BOX:
{
SCollisionBox *pBox = ( SCollisionBox * )&Primitive;
vPoint = pBox->vCenter;
return;
}
break;
case CT_SPHERE:
{
SCollisionSphere *pSphere = ( SCollisionSphere * )&Primitive;
vPoint = pSphere->vCenter;
}
break;
case CT_CAPSULE:
{
SCollisionCapsule *pCapsule = ( SCollisionCapsule * )&Primitive;
vPoint = pCapsule->Segment.vOrigin + pCapsule->Segment.vDirection * 0.5f;
}
break;
}
}