Files
2022-10-26 12:25:11 +08:00

371 lines
8.7 KiB
C++

#include "SunClientPrecompiledHeader.h"
#include "ObjectAttachment.h"
#include "ResourceManager.h"
#include "GameFunc.h"
#include "GlobalFunc.h"
const DWORD ciInterpolateTick = 400;
const float cAttachmentAccelater = 2.0f;
ObjectAttachment::ObjectAttachment()
{
m_pUnitDraw = NULL;
m_bAnimate = FALSE;
m_animID = 0;
}
BOOL ObjectAttachment::InitializeAttachment( BOOL bPlayer, const AttachmentInfo& AttachmentInfo, float fRequestRateResizeTexture)
{
if (AttachmentInfo.GetResourceID() == 0)
{
ReleaseAttachment();
return FALSE;
}
// 기존에 할당된것이 있다면 Delete 시켜준다.
if (m_pUnitDraw)
{
if ((m_pUnitDraw->GetWzUnit() == NULL) ||
(m_pUnitDraw->GetWzUnit()->GetType() != AttachmentInfo.GetResourceID()) )
{
ResourceManager::Instance()->FreeResourceUnitDraw(m_pUnitDraw);
if( bPlayer == TRUE )
m_pUnitDraw = ResourceManager::Instance()->AllocResourceUnitDraw( AttachmentInfo.GetResourceID(), fRequestRateResizeTexture, false);
else
m_pUnitDraw = ResourceManager::Instance()->AllocResourceUnitDraw( AttachmentInfo.GetResourceID(), fRequestRateResizeTexture, true );
}
}
else
{
if( bPlayer == TRUE )
m_pUnitDraw = ResourceManager::Instance()->AllocResourceUnitDraw( AttachmentInfo.GetResourceID(), fRequestRateResizeTexture, false);
else
m_pUnitDraw = ResourceManager::Instance()->AllocResourceUnitDraw( AttachmentInfo.GetResourceID(), fRequestRateResizeTexture, true );
}
//리소스코드 & 인첸트 & 디바인 이 같다면 셋팅해줄필요없다
if (( m_AttachmentInfo.GetResourceID() == AttachmentInfo.GetResourceID() ) &&
( m_AttachmentInfo.GetSubType() == AttachmentInfo.GetSubType() ) &&
( m_AttachmentInfo.IsSpecularVariation() == AttachmentInfo.IsSpecularVariation() ) )
{
return FALSE;
}
if ( m_pUnitDraw != NULL )
{
if ((m_pUnitDraw->GetWzUnit() != NULL) &&
(AttachmentInfo.GetSubType() < m_pUnitDraw->GetWzUnit()->GetNumSubType()))
{
//서브타입이 다를때만 해준다
m_pUnitDraw->SetSubType( AttachmentInfo.GetSubType() );
}
else
{
m_pUnitDraw->SetSubType(0);
}
}
// Set Info
m_AttachmentInfo = AttachmentInfo;
if ( m_AttachmentInfo.GetAttachType() == ATTACHTYPE_INTERPOLATION )
{
SetVector(&m_wvInterpolateOffsetAttachment, 0.f, 0.f, 0.f);
m_iInterpolateTick = 0;
m_fAccelerate = cAttachmentAccelater;
}
return TRUE;
}
BOOL ObjectAttachment::ReleaseAttachment()
{
if ( m_pUnitDraw != NULL )
{
ResourceManager::Instance()->FreeResourceUnitDraw(m_pUnitDraw);
m_pUnitDraw = NULL;
m_animID = 0;
m_bAnimate = FALSE;
m_AttachmentInfo.SetResourceID(0);
m_AttachmentInfo.SetBoneIndex(-1);
m_AttachmentInfo.SetItemCode(0);
}
return TRUE;
}
void ObjectAttachment::Animate( CWzUnitDraw* pBasePart, const WzVector& VisiblePosition, float fHeightOffset )
{
if ( m_pUnitDraw == NULL )
return;
int BoneIndex = m_AttachmentInfo.GetBoneIndex();
const WzMatrix& rotate_matrix = m_AttachmentInfo.GetRotateMatrix();
WzMatrix offset_matrix;
MatrixTranslation(&offset_matrix,
m_AttachmentInfo.GetOffset().x,
m_AttachmentInfo.GetOffset().y,
m_AttachmentInfo.GetOffset().z);
// 본따라 움직이지않는다 attachment(엘리의 특악)
if ( BoneIndex == -1 )
{
//현재 offsetMatrix에서는 오직 z값만 옵셋만 변경하고있다
WzMatrix mat;
MatrixIdentity(&mat);
// 위치값 옵셋
WzMatrix ret_mat;
MatrixMultiply(&ret_mat, &offset_matrix, &mat);
mat = ret_mat;
//! 회전을 적용시킨다.i
MatrixMultiply(&ret_mat, &rotate_matrix, &mat);
mat = ret_mat;
mat._41 = VisiblePosition.x;
mat._42 = VisiblePosition.y;
mat._43 += VisiblePosition.z + fHeightOffset;
g_pSunRenderer->AnimateUnit(m_pUnitDraw, 0, &mat);
}
else if( BoneIndex < pBasePart->GetTransformBufferSize() )
{
//본따라서 움직이는 Attachment
WzMatrix* pBoneMatrix = pBasePart->GetTransformBuffer();
if ( pBoneMatrix == NULL)
{
return;
}
WzMatrix mat = pBoneMatrix[BoneIndex];
// 위치값 옵셋
WzMatrix ret_mat;
MatrixMultiply(&ret_mat, &offset_matrix, &mat);
mat = ret_mat;
//! 회전을 적용시킨다.
MatrixMultiply(&ret_mat, &rotate_matrix, &mat);
mat = ret_mat;
if ( GetAttachmentInfo().GetAttachType() == ATTACHTYPE_INTERPOLATION )
{
if (m_iInterpolateTick)
{
WzVector dest_pos;
dest_pos.x = mat._41;
dest_pos.y = mat._42;
dest_pos.z = mat._43;
float rate =
(float)(ciInterpolateTick - m_iInterpolateTick) / (float) ciInterpolateTick;
rate = min(rate, 1.0f);
rate = max(rate, 0.0f);
WzVector cur_pos = dest_pos;
//선형 보간
cur_pos = m_vOldPos * (1.0f - rate) + dest_pos * (rate);
mat._41 =cur_pos.x;
mat._42 =cur_pos.y;
mat._43 =cur_pos.z;
g_pSunRenderer->AnimateUnit(m_pUnitDraw, 0, &mat);
}
else
{
g_pSunRenderer->AnimateUnit(m_pUnitDraw, 0, &mat);
}
}
else
{
g_pSunRenderer->AnimateUnit(m_pUnitDraw, 0, &mat);
}
}
}
void ObjectAttachment::SetAnimation(WzID animID, BOOL bLoop, BOOL bRestart)
{
if (animID == 0)
{
m_animID = animID;
m_bAnimate = FALSE;
if (m_pUnitDraw)
{
m_pUnitDraw->SetFrame(0.0f);
}
}
else
{
m_animID = animID;
m_bAnimate = TRUE;
if (bLoop == TRUE)
{
bRestart = FALSE;
}
if (m_pUnitDraw && m_pUnitDraw->GetWzUnit())
{
//wzu파일에 해당 애니ID가 있다면 SetCurrentAnimation
BOOL bYes = FALSE;
int iCnt = m_pUnitDraw->GetWzUnit()->GetCountAnimationInfo();
for(int i = 0; i < iCnt; i++)
{
WzAnimationInfo* pAI = m_pUnitDraw->GetWzUnit()->GetAnimationInfoByIndex(i);
if( (pAI) && (animID == pAI->m_wiAction) )
{
bYes = TRUE;
break;
}
}
if(bYes)
m_pUnitDraw->SetCurrentAnimation(animID, bLoop, bRestart);
else
m_pUnitDraw->SetCurrentAnimation(0, bLoop, bRestart);
}
}
}
void ObjectAttachment::ProcessAnimation( DWORD dwTick )
{
if( m_pUnitDraw != NULL )
{
int BoneIndex = m_AttachmentInfo.GetBoneIndex();
// 후에 boneindex가 유효한지 체크하는 루틴 필요.
if (BoneIndex != -1)
{
if (m_bAnimate)
{
g_pSunRenderer->ProgressUnitFrame( m_pUnitDraw, (float)dwTick);
}
else
{
g_pSunRenderer->ProgressUnitFrame( m_pUnitDraw, 0.0f);
}
}
else
{
if (m_bAnimate)
{
g_pSunRenderer->ProgressUnitFrame( m_pUnitDraw, (float)dwTick);
}
else
{
g_pSunRenderer->ProgressUnitFrame( m_pUnitDraw, 1);
}
}
}
}
void ObjectAttachment::ProcessInterpolation( CWzUnitDraw* pBasePart, DWORD dwTick )
{
if ( m_pUnitDraw == NULL )
{
return;
}
if ( m_AttachmentInfo.GetAttachType() != ATTACHTYPE_INTERPOLATION )
{
return;
}
// 보간
WzVector vDestPos;
if ( GameFunc::GetBonePos( pBasePart, m_AttachmentInfo.GetBoneIndex(), &vDestPos) )
{
const WzVector& wvCurPos = m_pUnitDraw->GetPosition();
m_wvInterpolateOffsetAttachment = vDestPos - wvCurPos;
if (m_iInterpolateTick <= 0)
{
m_iInterpolateTick = 0;
}
else
{
//틱이 커지면 빨리 이동 한다.
// ApplyInterpolateAccesory 부착 물 마다 있어야 함.초기화 해주는데서
m_fAccelerate -= 0.084f * dwTick;
m_fAccelerate = max(m_fAccelerate, 0.5f);
dwTick = DWORD(float(dwTick) * m_fAccelerate);
m_iInterpolateTick -= dwTick;
}
}
}
void ObjectAttachment::Render()
{
if ( m_pUnitDraw == NULL )
return;
if ( g_pSunRenderer->CheckUnitLoaded(m_pUnitDraw) == FALSE )
return;
if ( m_AttachmentInfo.IsSpecularVariation() )
{
m_pUnitDraw->SetSpecularIntensity(g_fSpecularVariation);
}
BOOL bReslt = g_pSunRenderer->RenderUnit( m_pUnitDraw );
if ( bReslt == FALSE )
{
//COMMENT:로그
WRITELOG(eLOG_LEVEL_ERR, c_wOUTPUT_LOG_FILE | c_wOUTPUT_LOG_CONSOLE, "ObjectAttachment::Render - %s(%d)", __FILE__, __LINE__ );
}
}
void ObjectAttachment::ApplyInterpolateAccesory( CWzUnitDraw* pBasePart )
{
if ( pBasePart == NULL )
return;
if ( m_pUnitDraw == NULL )
return;
if ( m_AttachmentInfo.GetAttachType() != ATTACHTYPE_INTERPOLATION )
return;
if ( m_iInterpolateTick > 0 )
return;
int BoneIndex = m_AttachmentInfo.GetBoneIndex();
if ( BoneIndex == -1 )
return;
if ( WzMatrix* pBoneMatrix = pBasePart->GetTransformBuffer() )
{
WzMatrix mat = pBoneMatrix[BoneIndex];
WzMatrix offset_matrix;
MatrixTranslation(&offset_matrix,
m_AttachmentInfo.GetOffset().x,
m_AttachmentInfo.GetOffset().y,
m_AttachmentInfo.GetOffset().z);
WzMatrix ret_mat;
MatrixMultiply(&ret_mat, &offset_matrix, &mat);
mat = ret_mat;
m_iInterpolateTick = ciInterpolateTick;
m_fAccelerate = cAttachmentAccelater;
m_vOldPos.x = mat._41;
m_vOldPos.y = mat._42;
m_vOldPos.z = mat._43;
}
}