Files
Leviathan/Client/Game/engine/Renderer/KPrimitiveSprite.cpp
T
2026-06-01 12:46:52 +02:00

348 lines
9.3 KiB
C++

#include "stdafx.h"
#include "KResource.h"
#include "KPrimitiveSprite.h"
#include "KRenderDevice.h"
#include "KPrimitiveSpriteMng.h"
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// KSpritePrimitive Implement
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int g_Debug = 0;
const float KSpritePrimitive::s_fLayerDevider = 100.f;
int KSpritePrimitive::s_nVertexStride = K3DVertexBuffer::CalcVertexStride( K3DFVF_XYZRHW | K3DFVF_DIFFUSE | K3DFVF_TEX1 );
KSpritePrimitive::KSpritePrimitive( bool bIsMng/* = true*/ )
: m_fResVisibility(1.0f), m_fVisibility(1.0f), m_colSprite(255,255,255,255), m_bUseAdditiveRender(false),
m_pClipRect(NULL),m_bMirrorH(false), m_bMirrorV(false),m_bCCWRotation(false),m_bCWRotation(false),
m_bModify(true), m_fDepthOrder(0.1f), m_bRenderValidate(true), m_bRenderEnable(true)
#ifdef _KUI_INVALIDATION
// { [sonador]
, m_vRenderOffset( 0, 0, 0 )
// }
#endif
{
m_bIsMng = bIsMng;
if( m_bIsMng )
KPrimitiveSpriteMng::GetManager()->Add( this );
m_type = KPRIMITIVE_SPRITE;
K3DMatrixIdentity(m_matTransform);
m_bIsUse = false;
}
KSpritePrimitive::~KSpritePrimitive()
{
if( m_bIsMng )
KPrimitiveSpriteMng::GetManager()->Del( this );
Clear();
}
void KSpritePrimitive::Clear()
{
}
void KSpritePrimitive::SetRenderEnable(bool bEnable)
{
m_bRenderEnable = bEnable;
}
void KSpritePrimitive::SetClipRect( KRect *cliprect )
{
m_pClipRect = cliprect;
m_bModify = true;
}
void KSpritePrimitive::SetTransform( const K3DMatrix &transform )
{
m_matTransform = transform;
m_bModify = true;
}
void KSpritePrimitive::SetVisibility( float vis )
{
m_fVisibility = vis;
m_colSprite.a = (unsigned char)(m_fResVisibility * m_fVisibility * 255);
m_bModify = true;
}
void KSpritePrimitive::SetResVisibility(float vis )
{
m_fResVisibility = vis;
m_colSprite.a = (unsigned char)(m_fResVisibility * m_fVisibility * 255);
m_bModify = true;
}
K3DVector KSpritePrimitive::GetPosition()
{
K3DVector ret;
K3DMatrixGetPosVector(ret, m_matTransform);
return ret;
}
void KSpritePrimitive::SetZPosition(float fZPos)
{
m_matTransform._43 = fZPos;
m_bModify = true;
}
#ifdef _KUI_INVALIDATION
// { [sonador]
void KSpritePrimitive::SetRenderOffset( const K3DVector& vRenderOffset )
{
m_vRenderOffset = vRenderOffset;
}
// }
#endif
void KSpritePrimitive::SetRes( KResSprite *pRes )
{
m_spRes = pRes;
if(m_spRes == NULL)
{
m_bIsUse = false;
return;
}
SetMirror( m_spRes->IsMirrorHori(), m_spRes->IsMirrorVert() );
SetCWRotation(m_spRes->IsCWRotate());
SetCCWRotation(m_spRes->IsCCWRotate());
SetAdditiveRenderMode( m_spRes->IsAdditiveRenderMode() );
SetResVisibility( m_spRes->GetVisibility() );
m_spRes->GetSourceUVRect(m_fLeft,m_fTop, m_fRight, m_fBottom);
m_fTargetWidth = m_spRes->GetSizeX(); m_fTargetHeight = m_spRes->GetSizeY();
m_bModify = true;
m_bIsUse = true;
}
void KSpritePrimitive::SetSourceRect(const KRect& rcRect)
{
m_spRes->GetSourceUVRect( m_fLeft, m_fTop, m_fRight, m_fBottom);
float fSizeX = static_cast<float>(m_spRes->GetSizeX() );
float fSizeY = static_cast<float>(m_spRes->GetSizeY() );
float fUVWidth = m_fRight - m_fLeft;
float fUVHeight = m_fBottom - m_fTop;
m_fLeft += ( (float)rcRect.left / fSizeX * fUVWidth );
m_fTop += ( (float)rcRect.top / fSizeY * fUVHeight );
m_fRight += (rcRect.right - fSizeX) / fSizeX * fUVWidth;
m_fBottom += (rcRect.bottom - fSizeY) / fSizeX * fUVWidth;
m_bModify = true;
}
void KSpritePrimitive::SetSourceRectRatio(float fLeft, float fTop, float fRight ,float fBottom)
{
m_spRes->GetSourceUVRect( m_fLeft, m_fTop, m_fRight, m_fBottom);
float fUVWidth = m_fRight - m_fLeft;
float fUVHeight = m_fBottom - m_fTop;
m_fLeft += fLeft * fUVWidth;
m_fTop += fTop * fUVHeight;
m_fRight += ( fRight - 1.0f) * fUVWidth;
m_fBottom += ( fBottom - 1.0f) * fUVHeight;
m_bModify = true;
}
void KSpritePrimitive::UpdateSprite()
{
if(m_spRes == NULL || m_spRes->GetTexture() == NULL )
return;
K3DMatrix matLocal = m_spRes->GetTransform();
K3DVector posParent, posLocal;
K3DMatrixGetPosVector( posParent, m_matTransform );
K3DMatrixGetPosVector( posLocal, matLocal);
K3DVector pos;
pos = posParent + posLocal;
float sprtx,sprty;
sprtx = pos.x + m_fTargetWidth;
sprty = pos.y + m_fTargetHeight;
K3DVector center;
center.x = pos.x + m_fTargetWidth / 2.f;
center.y = pos.y + m_fTargetHeight / 2.f;
float l = m_fLeft, t = m_fTop, r = m_fRight, b = m_fBottom;
// clipping 처리
if(m_pClipRect)
{
// No need to draw.
if ( m_pClipRect->left >= sprtx || m_pClipRect->top >= sprty ||
m_pClipRect->right <= pos.x || m_pClipRect->bottom <= pos.y )
{
m_bRenderValidate = false;
return;
}
KRect rect;
float uvwidth, uvheight;
uvwidth = r - l;
uvheight = b - t;
int texw = m_spRes->GetTexture()->GetWidth();
int texh = m_spRes->GetTexture()->GetHeight();
float actualw = texw * uvwidth;
float actualh = texh * uvheight;
float scalew = m_fTargetWidth / actualw;
float scaleh = m_fTargetHeight / actualh;
if ( m_pClipRect->left > pos.x )
{
rect.left = m_pClipRect->left;
int d = int(rect.left - pos.x);
l += uvwidth * (float(d)/m_spRes->GetSizeX()) / scalew;
}
else rect.left = int(pos.x);
if ( m_pClipRect->top > pos.y )
{
rect.top = m_pClipRect->top;
int d = int(rect.top - pos.y);
t += uvheight * (float(d)/m_spRes->GetSizeY()) / scaleh;
}
else rect.top = int(pos.y);
if ( m_pClipRect->right < sprtx )
{
rect.right = m_pClipRect->right;
int d = int(sprtx - rect.right);
r -= uvwidth * (float(d)/m_spRes->GetSizeX()) / scalew;
}
else rect.right = int(sprtx);
if ( m_pClipRect->bottom < sprty )
{
rect.bottom = m_pClipRect->bottom;
int d = int(sprty - rect.bottom);
b -= uvheight * (float(d)/m_spRes->GetSizeY()) / scaleh;
}
else rect.bottom = int(sprty);
pos.x = (float)rect.left; pos.y = (float)rect.top; sprtx = (float)rect.right; sprty = (float)rect.bottom;
center.x = pos.x + ((sprtx - pos.x)/2.f);
center.y = pos.y + ((sprty - pos.y)/2.f);
}
// For rotating around center of the sprite.
pos.x -= center.x;
pos.y -= center.y;
sprtx -= center.x;
sprty -= center.y;
float fZPos = pos.z / s_fLayerDevider;
if(m_bMirrorH)
std::swap(l,r);
if(m_bMirrorV)
std::swap(t,b);
m_VtxBuf[0].x = pos.x; m_VtxBuf[1].x = sprtx;
m_VtxBuf[0].y = pos.y; m_VtxBuf[1].y = pos.y;
m_VtxBuf[0].z = fZPos; m_VtxBuf[1].z = fZPos;
m_VtxBuf[0].w = 1; m_VtxBuf[1].w = 1;
m_VtxBuf[0].u = l; m_VtxBuf[1].u = r;
m_VtxBuf[0].v = t; m_VtxBuf[1].v = t;
m_VtxBuf[0].color = m_colSprite; m_VtxBuf[1].color = m_colSprite;
m_VtxBuf[2].x = pos.x; m_VtxBuf[3].x = sprtx;
m_VtxBuf[2].y = sprty; m_VtxBuf[3].y = sprty;
m_VtxBuf[2].z = fZPos; m_VtxBuf[3].z = fZPos;
m_VtxBuf[2].w = 1; m_VtxBuf[3].w = 1;
m_VtxBuf[2].u = l; m_VtxBuf[3].u = r;
m_VtxBuf[2].v = b; m_VtxBuf[3].v = b;
m_VtxBuf[2].color = m_colSprite; m_VtxBuf[3].color = m_colSprite;
// Rotate
static float fMatRot[2][2];
fMatRot[0][0] = m_matTransform._11 * matLocal._11 + m_matTransform._12 * matLocal._21;
fMatRot[0][1] = m_matTransform._11 * matLocal._12 + m_matTransform._12 * matLocal._22;
fMatRot[1][0] = m_matTransform._21 * matLocal._11 + m_matTransform._22 * matLocal._21;
fMatRot[1][1] = m_matTransform._21 * matLocal._12 + m_matTransform._22 * matLocal._22;
for(int i = 0; i < 4; ++i)
{
float xOrg = m_VtxBuf[i].x;
// See DX Help - Directly Mapping Texels to Pixels
m_VtxBuf[i].x = xOrg * fMatRot[0][0] + m_VtxBuf[i].y * fMatRot[1][0] + center.x - 0.5f;
m_VtxBuf[i].y = xOrg * fMatRot[0][1] + m_VtxBuf[i].y * fMatRot[1][1] + center.y - 0.5f;
#ifdef _KUI_INVALIDATION
// { [sonador]
m_VtxBuf[i].x -= m_vRenderOffset.x;
m_VtxBuf[i].y -= m_vRenderOffset.y;
// }
#endif
}
m_bRenderValidate = true;
}
/// 2011.01.18 - prodongi
void KSpritePrimitive::initScroll(bool is, DWORD type, float v, float margin)
{
m_scroll.initialize(is, type, v, margin, (void const*)m_VtxBuf);
}
/// 2011.02.23 - prodongi
void KSpritePrimitive::setScrollImgUv(int width, int height)
{
float u = (float)width/(float)m_spRes->GetTexture()->GetWidth();
float v = (float)height/(float)m_spRes->GetTexture()->GetHeight();
m_scroll.setImgUv(u, v);
}
void KSpritePrimitive::DeviceLost()
{
if(m_spRes != NULL)
{
m_spRes->GetSourceUVRect(m_fLeft,m_fTop, m_fRight, m_fBottom);
UpdateSprite();
}
}
void KSpritePrimitive::Render( KViewportObject *viewport, class K3DRenderDevice *dev, bool bUseAccum )
{
if(m_bModify && m_bRenderEnable)
{
UpdateSprite();
m_bModify = false;
}
if(m_bRenderValidate && m_bRenderEnable && m_spRes != NULL)
{
m_scroll.update(m_VtxBuf); /// 2011.01.18 - prodongi
m_scroll.setTextureAddressMode(dev);
dev->SetTexture( 0, m_spRes->GetTexture() );
dev->DrawTriangleStrip( K3DFVF_XYZRHW | K3DFVF_DIFFUSE | K3DFVF_TEX1,
m_VtxBuf, 4, s_nVertexStride);
m_scroll.restoreTextureAddressMode(dev); /// 2011.01.18 - prodongi
}
#ifdef _DEBUG
//그려지는 스프라이트 파일로 저장
static bool bFlag = false;
if( bFlag )
{
K3DTexture* pTex = m_spRes->GetTexture();
if( pTex )
pTex->SaveToFile("c:\\test.dds");
bFlag = false;
}
#endif
}