#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 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