498 lines
14 KiB
C++
498 lines
14 KiB
C++
#include "stdafx.h"
|
|
#include "KPrimitive.h"
|
|
#include "KResource.h"
|
|
#include "KPrimitiveFXParticle.h"
|
|
#include "KViewport.h"
|
|
#include "KRenderDevice.h"
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// KFXBillboardPrimitive Implement
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
KCommonParticleIndexBuffer& KCommonParticleIndexBuffer::GetInstance()
|
|
{
|
|
static KCommonParticleIndexBuffer indexbuffer;
|
|
return indexbuffer;
|
|
}
|
|
|
|
int KFXBillboardPrimitive::s_nVertexStride = K3DVertexBuffer::CalcVertexStride(K3DFVF_SPRITE);
|
|
|
|
KFXBillboardPrimitive::KFXBillboardPrimitive()
|
|
{
|
|
m_type = KPRIMITIVE_FXBILLBOARD;
|
|
}
|
|
KFXBillboardPrimitive::~KFXBillboardPrimitive()
|
|
{
|
|
}
|
|
void KFXBillboardPrimitive::SetBillboardRes( KResFXBillboard *pRes )
|
|
{
|
|
m_spRes = pRes;
|
|
|
|
}
|
|
KResFXBillboard* KFXBillboardPrimitive::GetBillboardRes()
|
|
{
|
|
return m_spRes;
|
|
}
|
|
void KFXBillboardPrimitive::SetTransform( const K3DMatrix &transform )
|
|
{
|
|
m_matTransform = transform;
|
|
}
|
|
const K3DMatrix &KFXBillboardPrimitive::GetTransform()
|
|
{
|
|
return m_matTransform;
|
|
}
|
|
void KFXBillboardPrimitive::SetColor ( const KColor &color )
|
|
{
|
|
m_colSprite = color;
|
|
}
|
|
const KColor& KFXBillboardPrimitive::GetColor()
|
|
{
|
|
return m_colSprite;
|
|
}
|
|
|
|
/// Rendering source target rectangle.
|
|
void KFXBillboardPrimitive::SetUV( float _l, float _t, float _r, float _b )
|
|
{
|
|
l = _l; t = _t; r = _r; b = _b;
|
|
}
|
|
|
|
void KFXBillboardPrimitive::GetUV( float *_l, float *_t, float *_r, float *_b )
|
|
{
|
|
*_l = l; *_t = t; *_r = r; *_b = b;
|
|
}
|
|
|
|
void KFXBillboardPrimitive::SetFixedAxis( int nAxis )
|
|
{
|
|
m_nFixedAxis = nAxis;
|
|
}
|
|
|
|
void KFXBillboardPrimitive::SetAngle( float fAngle )
|
|
{
|
|
m_fAngle = fAngle;
|
|
}
|
|
|
|
void KFXBillboardPrimitive::Render( KViewportObject *viewport, class K3DRenderDevice *dev, bool bUseAccum )
|
|
{
|
|
_UpdateBillboard(viewport, dev);
|
|
dev->SetTexture( 0, m_spRes->GetTexture() );
|
|
dev->DrawTriangleStrip(K3DFVF_SPRITE, m_VtxBuf, 4, s_nVertexStride);
|
|
}
|
|
|
|
template< typename T > static inline T _min( const T& a, const T& b ) { return a < b ? a : b; }
|
|
|
|
void KFXBillboardPrimitive::_UpdateBillboard(KViewportObject* pViewport, K3DRenderDevice* pDev)
|
|
{
|
|
const K3DVertex* pVtx = m_spRes->GetVertices();
|
|
|
|
for ( int i = 0 ; i < 4; i++ )
|
|
{
|
|
K3DVectorTransform( m_VtxBuf[ i ].pos, pVtx[ i ], m_RootMat );
|
|
m_VtxBuf[i].diffuse = m_colSprite;
|
|
}
|
|
|
|
K3DMatrix matViewMatrix = *pViewport->GetViewMatrix();
|
|
|
|
static K3DVector vPos;
|
|
K3DMatrixGetPosVector(vPos, m_RootMat);
|
|
|
|
static float fHalfWidth, fHalfHeight;
|
|
static bool bSwapWidthHeight = false;
|
|
if ( fabsf( pVtx[ 0 ].x - pVtx[ 1 ].x ) < fabsf( pVtx[ 0 ].z - pVtx[ 1 ].z ) )
|
|
bSwapWidthHeight = true;
|
|
else
|
|
bSwapWidthHeight = false;
|
|
|
|
K3DVector vCenterOffset = ( m_VtxBuf[ 0 ].pos + m_VtxBuf[ 1 ].pos + m_VtxBuf[ 2 ].pos + m_VtxBuf[ 3 ].pos ) / 4.0f;
|
|
vCenterOffset = ( vPos - vCenterOffset ) * 2.0f;
|
|
vCenterOffset.y = fabsf( vCenterOffset.y ) >= fabsf( vCenterOffset.z ) ? vCenterOffset.y : vCenterOffset.z;
|
|
vCenterOffset.z = 0.0f;
|
|
|
|
fHalfWidth = K3DVectorLength( m_VtxBuf[ 0 ].pos - m_VtxBuf[ 1 ].pos );
|
|
fHalfHeight = min( K3DVectorLength( m_VtxBuf[ 1 ].pos - m_VtxBuf[ 3 ].pos ), K3DVectorLength( m_VtxBuf[ 1 ].pos - m_VtxBuf[ 2 ].pos ) );
|
|
|
|
if ( bSwapWidthHeight )
|
|
{
|
|
float fTemp = fHalfWidth;
|
|
fHalfWidth = fHalfHeight;
|
|
fHalfHeight = fTemp;
|
|
}
|
|
|
|
K3DVector vecLeft, vecRight, vecUp, vecDown, vecView;
|
|
if ( m_nFixedAxis == 2 )
|
|
{
|
|
vecRight = K3DVector( 1.0f, 0.0f, 0.0f );
|
|
vecUp = K3DVector( 0.0f, 0.0f, 1.0f );
|
|
K3DVectorTransformNormal( vecUp, vecUp, matViewMatrix );
|
|
K3DVectorCross( vecView, vecUp, vecRight );
|
|
|
|
vecLeft = -vecRight * fHalfWidth - vecRight * vCenterOffset.x;
|
|
vecRight = vecRight * fHalfWidth - vecRight * vCenterOffset.x;
|
|
vecDown = -vecUp * fHalfHeight - vecUp * vCenterOffset.y;
|
|
vecUp = vecUp * fHalfHeight - vecUp * vCenterOffset.y;
|
|
}
|
|
else
|
|
{
|
|
vecRight = K3DVector( 1.0f, 0.0f, 0.0f );
|
|
vecUp = K3DVector( 0.0f, 1.0f, 0.0f );
|
|
K3DVectorCross( vecView, vecUp, vecRight );
|
|
|
|
vecLeft = -vecRight * fHalfWidth - vecRight * vCenterOffset.x;
|
|
vecRight = vecRight * fHalfWidth - vecRight * vCenterOffset.x;
|
|
vecDown = -vecUp * fHalfHeight - vecUp * vCenterOffset.y;
|
|
vecUp = vecUp * fHalfHeight - vecUp * vCenterOffset.y;
|
|
}
|
|
|
|
K3DMatrix matRotate;
|
|
K3DMatrixRotationAxis( matRotate, vecView, m_fAngle );
|
|
K3DVectorTransformNormal( vecLeft, vecLeft, matRotate );
|
|
K3DVectorTransformNormal( vecRight, vecRight, matRotate );
|
|
K3DVectorTransformNormal( vecUp, vecUp, matRotate );
|
|
K3DVectorTransformNormal( vecDown, vecDown, matRotate );
|
|
|
|
K3DMatrixInverse( matViewMatrix, matViewMatrix );
|
|
matViewMatrix.SetPosVector( vPos );
|
|
|
|
m_VtxBuf[ 0 ].pos = vecLeft + vecDown;
|
|
m_VtxBuf[ 1 ].pos = vecLeft + vecUp;
|
|
m_VtxBuf[ 2 ].pos = vecRight + vecDown;
|
|
m_VtxBuf[ 3 ].pos = vecRight + vecUp;
|
|
|
|
for(int i = 0 ; i < 4; ++i)
|
|
{
|
|
K3DVectorTransform( m_VtxBuf[ i ].pos, m_VtxBuf[ i ].pos, matViewMatrix );
|
|
}
|
|
|
|
// Set UV
|
|
m_VtxBuf[0].texel.u = l; m_VtxBuf[0].texel.v = b;
|
|
m_VtxBuf[1].texel.u = l; m_VtxBuf[1].texel.v = t;
|
|
m_VtxBuf[2].texel.u = r; m_VtxBuf[2].texel.v = b;
|
|
m_VtxBuf[3].texel.u = r; m_VtxBuf[3].texel.v = t;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// KFXParticlePrimitive Implement
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
int KFXParticlePrimitive::s_nVertexStride = K3DVertexBuffer::CalcVertexStride(K3DFVF_SPRITE);
|
|
|
|
KFXParticlePrimitive::KFXParticlePrimitive()
|
|
{
|
|
m_type = KPRIMITIVE_FXPARTICLE;
|
|
m_pParticles = NULL;
|
|
m_nParticleCount = 0;
|
|
|
|
m_pVtxBuf = NULL;
|
|
m_pIdxBuf = NULL;
|
|
|
|
m_nDrawParticleCount = 0;
|
|
|
|
m_bIsAttachParent = false;
|
|
}
|
|
KFXParticlePrimitive::~KFXParticlePrimitive()
|
|
{
|
|
SAFE_DELETE_ARRAY(m_pParticles);
|
|
SAFE_DELETE_ARRAY(m_pVtxBuf);
|
|
}
|
|
|
|
void KFXParticlePrimitive::ResetParticleCount()
|
|
{
|
|
m_nDrawParticleCount = 0;
|
|
}
|
|
void KFXParticlePrimitive::SetParticleRes( KResFXParticle *pRes )
|
|
{
|
|
m_spRes = pRes;
|
|
}
|
|
KResFXParticle* KFXParticlePrimitive::GetParticleRes()
|
|
{
|
|
return m_spRes;
|
|
}
|
|
|
|
void KFXParticlePrimitive::SetParticleCount( int count )
|
|
{
|
|
SAFE_DELETE_ARRAY(m_pParticles);
|
|
SAFE_DELETE_ARRAY(m_pVtxBuf);
|
|
|
|
m_nParticleCount = count;
|
|
|
|
m_pParticles = new _PARTICLE[m_nParticleCount];
|
|
m_pVtxBuf = new K3DSPRITEVERTEX[m_nParticleCount * 4];
|
|
|
|
m_pIdxBuf = GetIndexbufferInstance().GetCommonIndexbuffer( m_nParticleCount );
|
|
}
|
|
|
|
void KFXParticlePrimitive::SetParticleInfo( int num, _PARTICLE& particle )
|
|
{
|
|
if( m_nParticleCount > num )
|
|
{
|
|
m_pParticles[num].pos = particle.pos;
|
|
m_pParticles[num].fWidth = particle.fWidth;
|
|
m_pParticles[num].fHeight = particle.fHeight;
|
|
m_pParticles[num].color = particle.color;
|
|
|
|
m_pParticles[num].l = particle.l;
|
|
m_pParticles[num].t = particle.t;
|
|
m_pParticles[num].r = particle.r;
|
|
m_pParticles[num].b = particle.b;
|
|
|
|
++m_nDrawParticleCount;
|
|
}
|
|
}
|
|
|
|
void KFXParticlePrimitive::GetParticleUV( int num, float *_l, float *_t, float *_r, float *_b )
|
|
{
|
|
*_l = m_pParticles[num].l; *_t = m_pParticles[num].t; *_r = m_pParticles[num].r; *_b = m_pParticles[num].b;
|
|
}
|
|
|
|
void KFXParticlePrimitive::NewParticle( int num )
|
|
{
|
|
m_pParticles[num].newparticle = true;
|
|
}
|
|
|
|
void KFXParticlePrimitive::SetAttachParent( bool bAttachParent )
|
|
{
|
|
m_bIsAttachParent = bAttachParent;
|
|
}
|
|
|
|
const KFXParticlePrimitive::_PARTICLE & KFXParticlePrimitive::GetParticle( int num )
|
|
{
|
|
return m_pParticles[num];
|
|
}
|
|
int KFXParticlePrimitive::GetMaxParticleCount()
|
|
{
|
|
return m_nParticleCount;
|
|
}
|
|
int KFXParticlePrimitive::GetDrawParticleCount()
|
|
{
|
|
return m_nDrawParticleCount;
|
|
}
|
|
|
|
void KFXParticlePrimitive::Render( KViewportObject *viewport, class K3DRenderDevice *dev, bool bUseAccum )
|
|
{
|
|
if(m_nDrawParticleCount > 0 && IsValidIndexBuffer() )
|
|
{
|
|
_UpdateParticle(viewport, dev);
|
|
dev->SetTexture( 0, m_spRes->GetTexture() );
|
|
dev->DrawTriangles( K3DFVF_SPRITE,m_pVtxBuf, m_nDrawParticleCount * 4, s_nVertexStride, m_pIdxBuf, m_nDrawParticleCount * 6);
|
|
}
|
|
}
|
|
|
|
static inline void K3DMatrixAddPosVector( K3DMatrix &mat, const K3DVector &v )
|
|
{
|
|
mat._41 += v.x; mat._42 += v.y; mat._43 += v.z;
|
|
}
|
|
|
|
static inline void K3DMatrixSubtractPosVector( K3DMatrix &mat, const K3DVector &v )
|
|
{
|
|
mat._41 -= v.x; mat._42 -= v.y; mat._43 -= v.z;
|
|
}
|
|
|
|
void KFXParticlePrimitive::_UpdateParticle(KViewportObject* pViewport, K3DRenderDevice* pDev)
|
|
{
|
|
static float l,t,r,b;
|
|
static float fWidth, fHeight;
|
|
|
|
static K3DVertex vPos;
|
|
|
|
K3DMatrix matBillboard = *pViewport->GetViewMatrix();
|
|
matBillboard._41 = matBillboard._42 = matBillboard._43 = 0.0f;
|
|
matBillboard._44 = 1.0f;
|
|
|
|
K3DMatrixInverse( matBillboard, matBillboard );
|
|
|
|
K3DVector vCamPos = K3DVector( 0.0f, 0.0f, 0.0f );
|
|
if( pViewport->IsLocalCoord() )
|
|
vCamPos = pViewport->GetBackUpViewCamera()->GetCamPos();
|
|
|
|
K3DMatrix matOriParent = m_RootMat;
|
|
K3DMatrixAddPosVector( matOriParent, vCamPos );
|
|
|
|
K3DMatrix matTrans;
|
|
for(int i = 0 ; i < m_nDrawParticleCount; ++i)
|
|
{
|
|
K3DMatrixTranslation( matTrans, m_pParticles[i].pos.x, m_pParticles[i].pos.y, m_pParticles[i].pos.z );
|
|
|
|
if( m_bIsAttachParent )
|
|
{
|
|
matTrans = matTrans * m_RootMat;
|
|
|
|
m_pParticles[i].matParent = matOriParent;
|
|
m_pParticles[i].newparticle = false;
|
|
}
|
|
else
|
|
{
|
|
if( m_pParticles[i].newparticle )
|
|
{
|
|
matTrans = matTrans * m_RootMat;
|
|
|
|
m_pParticles[i].matParent = matOriParent;
|
|
m_pParticles[i].newparticle = false;
|
|
}
|
|
else
|
|
{
|
|
K3DMatrix matParent = m_pParticles[i].matParent;
|
|
K3DMatrixSubtractPosVector( matParent, vCamPos );
|
|
|
|
matTrans = matTrans * matParent;
|
|
}
|
|
}
|
|
|
|
matBillboard._41 = matTrans._41;
|
|
matBillboard._42 = matTrans._42;
|
|
matBillboard._43 = matTrans._43;
|
|
|
|
// 원래는 * 0.5f 해줘야 함 (max size 대로 나오게)
|
|
fWidth = m_pParticles[i].fWidth;
|
|
fHeight = m_pParticles[i].fHeight;
|
|
l = m_pParticles[i].l; t = m_pParticles[i].t; r = m_pParticles[i].r; b = m_pParticles[i].b;
|
|
|
|
static const float MULTIPLYER[4][2] = { {-1.f, -1.f} , {1.f, -1.f}, {-1.f, 1.f }, {1.f, 1.f} };
|
|
|
|
// Position, Color
|
|
for(int j = 0; j < 4; ++j)
|
|
{
|
|
m_pVtxBuf[i * 4 + j].pos.x = MULTIPLYER[j][0] * fWidth;
|
|
m_pVtxBuf[i * 4 + j].pos.y = MULTIPLYER[j][1] * fHeight;
|
|
m_pVtxBuf[i * 4 + j].pos.z = 0.0f;
|
|
|
|
m_pVtxBuf[i * 4 + j].diffuse = m_pParticles[i].color;
|
|
|
|
K3DVectorTransform( m_pVtxBuf[i * 4 + j].pos, m_pVtxBuf[i * 4 + j].pos, matBillboard );
|
|
}
|
|
|
|
// UV 셋팅
|
|
m_pVtxBuf[i * 4 + 0].texel.u = l; m_pVtxBuf[i * 4 + 0].texel.v = b;
|
|
m_pVtxBuf[i * 4 + 1].texel.u = r; m_pVtxBuf[i * 4 + 1].texel.v = b;
|
|
m_pVtxBuf[i * 4 + 2].texel.u = l; m_pVtxBuf[i * 4 + 2].texel.v = t;
|
|
m_pVtxBuf[i * 4 + 3].texel.u = r; m_pVtxBuf[i * 4 + 3].texel.v = t;
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// KFXAfterImagePrimitive Implement
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
KFXAfterImagePrimitive::KFXAfterImagePrimitive()
|
|
{
|
|
m_type = KPRIMITIVE_FXAFTERIMAGE;
|
|
m_nDepth = 0;
|
|
m_nDrawCount = 0;
|
|
m_pVtx = NULL;
|
|
m_nCurPos = 0;
|
|
m_nVertexStride = K3DVertexBuffer::CalcVertexStride( K3DFVF_SPRITE );
|
|
m_bIsTrans = true;
|
|
K3DMatrixIdentity(m_Transform);
|
|
}
|
|
/// Delete two custom vertex's array.
|
|
KFXAfterImagePrimitive::~KFXAfterImagePrimitive()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
void KFXAfterImagePrimitive::Clear()
|
|
{
|
|
SAFE_DELETE_ARRAY(m_pVtx);
|
|
}
|
|
void KFXAfterImagePrimitive::SetTransform( const K3DMatrix &transform )
|
|
{
|
|
m_Transform = transform;
|
|
}
|
|
void KFXAfterImagePrimitive::SetTexture( K3DTexture *pTex )
|
|
{
|
|
m_spTex = pTex;
|
|
}
|
|
void KFXAfterImagePrimitive::Initialize ( int nDepth )
|
|
{
|
|
Clear();
|
|
m_nDepth = nDepth;
|
|
m_nDrawCount = 0;
|
|
m_nCurPos = 0;
|
|
m_pVtx = new K3DSPRITEVERTEX[nDepth * 2];
|
|
}
|
|
|
|
void KFXAfterImagePrimitive::ReserveVtx(int nCount)
|
|
{
|
|
nCount = nCount - ( m_nDepth - m_nCurPos );
|
|
|
|
if( nCount <= 0)
|
|
return;
|
|
|
|
m_nCurPos = max(0, m_nCurPos - nCount);
|
|
m_nDrawCount = max(0, m_nDrawCount - nCount);
|
|
|
|
memcpy( m_pVtx, &m_pVtx[nCount * 2], sizeof(K3DSPRITEVERTEX) * 2 * (m_nCurPos) );
|
|
}
|
|
|
|
void KFXAfterImagePrimitive::PopVertex(int nCount)
|
|
{
|
|
m_nCurPos = max(0, m_nCurPos - nCount);
|
|
m_nDrawCount = max(0, m_nDrawCount - nCount);
|
|
}
|
|
|
|
|
|
void KFXAfterImagePrimitive::PushVertex( const K3DSPRITEVERTEX &vtx1, const K3DSPRITEVERTEX &vtx2)
|
|
{
|
|
if ( m_nCurPos == m_nDepth )
|
|
{
|
|
memcpy( m_pVtx, &m_pVtx[2], sizeof(K3DSPRITEVERTEX)*2*(m_nDepth-1) );
|
|
m_nCurPos = m_nDepth-1;
|
|
}
|
|
|
|
m_pVtx[m_nCurPos*2] = vtx1;
|
|
m_pVtx[m_nCurPos*2+1] = vtx2;
|
|
|
|
++m_nCurPos;
|
|
|
|
if ( ++m_nDrawCount > m_nDepth )
|
|
m_nDrawCount = m_nDepth;
|
|
}
|
|
|
|
void KFXAfterImagePrimitive::UpdateVertex()
|
|
{
|
|
if ( m_nDrawCount > 1 )
|
|
{
|
|
for ( int i=0 ; i<m_nDrawCount ; ++i )
|
|
{
|
|
m_pVtx[i*2+0].texel.u = .0f;
|
|
m_pVtx[i*2+1].texel.u= 1.0f;
|
|
|
|
m_pVtx[i*2+0].texel.v = m_pVtx[i*2+1].texel.v= (float)i/(float)(m_nDrawCount-1);
|
|
m_pVtx[i*2+0].diffuse = m_pVtx[i*2+1].diffuse = KColor(255,255,255, unsigned char( 255.0f * m_fVisibility * (float)i/(float)(m_nDrawCount-1) ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
void KFXAfterImagePrimitive::RemoveVertex()
|
|
{
|
|
m_nDrawCount = 0;
|
|
m_nCurPos = 0;
|
|
}
|
|
void KFXAfterImagePrimitive::Render( KViewportObject *viewport, class K3DRenderDevice *dev, bool bUseAccum )
|
|
{
|
|
if ( m_nDrawCount > 1 )
|
|
{
|
|
K3DMatrix world;
|
|
K3DMatrixMultiply(world, m_Transform, m_RootMat);
|
|
dev->SetTransform( K3DRenderDevice::TS_WORLD, &world );
|
|
dev->SetTexture( 0, m_spTex );
|
|
|
|
//임시로 컬모드 설정
|
|
int nOldCullMode = dev->GetCullMode();
|
|
dev->SetCullMode( K3DRenderDevice::KCM_NONE );
|
|
dev->DrawTriangleStrip( K3DFVF_SPRITE, m_pVtx, m_nDrawCount*2, m_nVertexStride );
|
|
dev->SetCullMode( nOldCullMode );
|
|
}
|
|
}
|
|
|
|
void KFXAfterImagePrimitive::SetMoveAdded(const K3DVertex & vMoveAdded)
|
|
{
|
|
if ( m_nDrawCount > 1 )
|
|
{
|
|
for ( int i=0 ; i<m_nDrawCount ; ++i )
|
|
{
|
|
m_pVtx[i*2].pos += vMoveAdded;
|
|
m_pVtx[i*2+1].pos += vMoveAdded;
|
|
}
|
|
}
|
|
}
|