#include "stdafx.h" #include "krenderobjectMesh.h" #include "krenderobjectEtc.h" #include "K3DCamera.h" #include "KRenderDeviceDX.h" #include "KDeviceManager.h" #include "KResourceManager.h" //#include "K3DFrustum.h" #include "GameDefine.h" #include "KResource.h" #include "KViewport.h" //////////////////////////////////////////////////////////////////////////////////////////////////////////////// // KCameraSeq Implement //////////////////////////////////////////////////////////////////////////////////////////////////////////////// KCameraSeq::KCameraSeq() { m_ViewCamera = new K3DCamera; m_ViewCamera->Reset(); } KCameraSeq::~KCameraSeq() { SAFE_DELETE(m_ViewCamera); } void KCameraSeq::SetRes( K3DResCamera *pRes) { m_spRes = pRes; if(m_spRes != NULL) { m_interval.Expand( m_spRes->GetInterval() ); } } void *KCameraSeq::Perform( KID id, KArg& msg ) { _CID( REQ_INTERSECTIONLINE ); _CID( SET_CAMERARENDER ); _CID( GET_CAMERASEQ ); if ( id == id_REQ_INTERSECTIONLINE ) { realizeTime(); KMsgREQ_INTERLINE *reqmsg = static_cast(&msg); int scrx = reqmsg->nScrx; int scry = reqmsg->nScry; KViewportObject *pViewport = reqmsg->pViewport; float fNearClip = pViewport->GetNearClip(); float fFarClip = pViewport->GetFarClip(); float scx = static_cast(scrx - pViewport->GetViewportX()) / static_cast(pViewport->GetViewportWidth()-1) * 2.f - 1.f; float scy = -(static_cast(scry - pViewport->GetViewportY()) / static_cast(pViewport->GetViewportHeight()-1) * 2.f - 1.f); // get inverse of the camera view matrix into invMat K3DMatrix invMat; K3DMatrixInverse( invMat, m_matView ); K3DVertex vtx; float sx = (scx)*fNearClip*tanf(m_fFOV*pViewport->GetVertexAspect()*0.5f); float sy = (scy)*fNearClip*tanf(m_fFOV*0.5f); vtx.x = sx; vtx.y = sy; vtx.z = -fNearClip; K3DVectorTransform(reqmsg->vNear, vtx, invMat); sx = (scx)*fFarClip*tanf(m_fFOV*pViewport->GetVertexAspect()*0.5f); sy = (scy)*fFarClip*tanf(m_fFOV*0.5f); vtx.x = sx; vtx.y = sy; vtx.z = -fFarClip; K3DVectorTransform(reqmsg->vFar, vtx, invMat); return (void*)1; } else if( id == id_SET_CAMERARENDER ) { KMsgSET_CAMERARENDER *reqmsg = static_cast(&msg); m_bRenderFlag = reqmsg->bRenderFlag; return (void*)1; } else if ( id == id_GET_CAMERASEQ ) { KMsgGET_CAMERASEQ *reqmsg = static_cast(&msg); reqmsg->pCamSeq = this; return (void*)1; } return NULL; } void KCameraSeq::Render( KViewportObject *viewport, DWORD flag, const K3DMatrix * pAttachMat ) { if( !m_bRenderFlag ) return; realizeTime(); K3DMatrix projection; if( m_ViewCamera->IsCoordinateRightHand() ) K3DMatrixPerspectiveFovRH( projection, m_fFOV, viewport->GetVertexAspect(), viewport->GetNearClip(), viewport->GetFarClip() ); else K3DMatrixPerspectiveFovLH( projection, m_fFOV, viewport->GetVertexAspect(), viewport->GetNearClip(), viewport->GetFarClip() ); viewport->SetCamera(m_ViewCamera); } KSeqObject* KCameraSeq::Clone() { KCameraSeq *obj = new KCameraSeq; obj->SetRes( m_spRes ); return obj; } void KCameraSeq::realizeTime() { if ( m_dwRealizedTime == m_dwTime ) return; m_dwRealizedTime = m_dwTime; K3DResCamera::Key *key1 = NULL, *key2 = NULL; m_spRes->GetData( m_dwTime, key1, key2 ); K3DVector respos, resview, resup; if ( key2 != NULL ) { int ctime = m_dwTime - key1->time; float ratio = (float)ctime / float(key2->time - key1->time); K3DVectorLerp( respos, key1->pos, key2->pos, ratio ); K3DVectorLerp( resview, key1->view, key2->view, ratio ); K3DVectorLerp( resup, key1->up, key2->up, ratio ); m_fFOV = key1->fov + ((key2->fov - key1->fov) * ratio); } else { respos = key1->pos; resview = key1->view; resup = key1->up; m_fFOV = key1->fov; } K3DVector at = respos + resview; m_vCamPos = respos; K3DMatrixLookAtRH( m_matView, respos, at, resup ); m_ViewCamera->SetCamPos(m_vCamPos.x, m_vCamPos.y, m_vCamPos.z); m_ViewCamera->SetTargetPos(at.x, at.y, at.z); m_ViewCamera->SetUpVector(resup.x, resup.y, resup.z); m_ViewCamera->SetFOV(m_fFOV); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////// // KLightSeq Implement //////////////////////////////////////////////////////////////////////////////////////////////////////////////// KLightSeq::KLightSeq() { } KLightSeq::~KLightSeq() { } void KLightSeq::SetRes( K3DResLight *pRes ) { m_spRes = pRes; if(m_spRes != NULL) { m_interval.Expand( m_spRes->GetInterval() ); } } void * KLightSeq::Perform( KID id, KArg& msg ) { _CID( REQ_LIGHT ); if( id == id_REQ_LIGHT ) { K3DResLight::Key *key1 = NULL, *key2 = NULL; m_spRes->GetData( 0, key1, key2 ); if ( key2 != NULL ) { int ctime = m_dwTime - key1->time; float ratio = (float)ctime / float(key2->time - key1->time); memcpy( &m_Light, &key1->light, sizeof(m_Light) ); K3DVectorLerp( m_Light.position, key1->light.position, key2->light.position, ratio ); K3DVectorLerp( m_Light.direction, key1->light.direction, key2->light.direction, ratio ); K3DColorLerp( m_Light.diffuse, key1->light.diffuse, key2->light.diffuse, ratio ); m_Light.range = key1->light.range + ((key2->light.range - key1->light.range) * ratio); } else { memcpy( &m_Light, &key1->light, sizeof(m_Light) ); } KMsgREQ_LIGHT *pmsg = static_cast(&msg); pmsg->m_pLightList.push_back( &m_Light ); return (void*)1; } return NULL; } void KLightSeq::Render( KViewportObject *viewport, DWORD flag, const K3DMatrix * pAttachMat ) { K3DResLight::Key *key1 = NULL, *key2 = NULL; m_spRes->GetData( m_dwTime, key1, key2 ); if ( key2 != NULL ) { int ctime = m_dwTime - key1->time; float ratio = (float)ctime / float(key2->time - key1->time); memcpy( &m_Light, &key1->light, sizeof(m_Light) ); K3DVectorLerp( m_Light.position, key1->light.position, key2->light.position, ratio ); K3DVectorLerp( m_Light.direction, key1->light.direction, key2->light.direction, ratio ); K3DColorLerp( m_Light.diffuse, key1->light.diffuse, key2->light.diffuse, ratio ); m_Light.range = key1->light.range + ((key2->light.range - key1->light.range) * ratio); } else { memcpy( &m_Light, &key1->light, sizeof(m_Light) ); } viewport->AddLight( &m_Light ); } KSeqObject* KLightSeq::Clone() { KLightSeq *obj = new KLightSeq; obj->SetRes( m_spRes ); return obj; } void KLightSeq::realizeTime() { } //////////////////////////////////////////////////////////////////////////////////////////////////////////////// // KSpriteSeq Implement //////////////////////////////////////////////////////////////////////////////////////////////////////////////// KSpriteSeq::KSpriteSeq() { K3DMatrixIdentity(m_matLocal); } KSpriteSeq::~KSpriteSeq() { } int KSpriteSeq::GetFrameCount() { return m_spRes->GetKeyCount(); } KResSprite *KSpriteSeq::GetFrame( int nFrame ) { return m_spRes->GetSpriteByFrame(nFrame); } int KSpriteSeq::GetCurrentIndex() { return m_spRes->GetIndexNumber(m_dwTime); } KResSprite* KSpriteSeq::GetCurrentFrame() { KResSpriteAnimation::Key *key1 = NULL, *key2 = NULL; m_spRes->GetData( m_dwTime, key1, key2 ); if(key1) return key1->spSprite; return NULL; } LPCSTR KSpriteSeq::GetSeqName() { return m_spRes->GetName(); } void KSpriteSeq::SetRes( KResSpriteAnimation *res ) { assert(m_spRes == NULL); m_spRes = res; if(m_spRes != NULL) { m_interval = m_spRes->GetInterval(); } } KResSpriteAnimation* KSpriteSeq::GetRes() { return m_spRes; } void * KSpriteSeq::Perform( KID id, KArg& msg ) { _CID( SET_RENDER_SIZE ); if( id == id_SET_RENDER_SIZE ) { KMsgSET_RENDER_SIZE *pmsg = static_cast(&msg); m_sizeRender = pmsg->sizeRender; if ( m_spRes != NULL ) { int nFrames = m_spRes->GetKeyCount(); for ( int i=0 ; iGetKey( i ); key.spSprite->SetSize( static_cast(m_sizeRender.cx), static_cast(m_sizeRender.cy) ); } } return (void*)1; } return NULL; } void KSpriteSeq::Render( KViewportObject *viewport, DWORD flag, const K3DMatrix * pAttachMat ) { KResSpriteAnimation::Key *key1 = NULL, *key2 = NULL; m_spRes->GetData( m_dwTime, key1, key2 ); K3DPoint offset = key1->spSprite->GetOffset(); K3DMatrix mat = m_matLocal; mat._41 += offset.x; mat._42 += offset.y; K3DMatrix matTrans = key1->spSprite->GetTransform(); mat *= matTrans; if ( m_pMatAttach != NULL && m_pMatParent != NULL ) { K3DMatrix matTemp; K3DMatrixMultiply( matTemp, *m_pMatAttach, *m_pMatParent ); K3DMatrixMultiply( m_matResult, m_matLocal, matTemp ); } else if ( m_pMatParent != NULL ) K3DMatrixMultiply( m_matResult, m_matLocal, *m_pMatParent ); else m_matResult = m_matLocal; m_prSprite.SetRes(key1->spSprite ); m_prSprite.SetVisibility(m_fMasterVisibility * key1->spSprite->GetVisibility()); m_prSprite.SetTransform(m_matResult); //m_prSprite.UpdateSprite(); viewport->Register( &m_prSprite ); } KSeqObject* KSpriteSeq::Clone() { KSpriteSeq *obj = new KSpriteSeq; obj->SetRes( m_spRes ); return obj; } void KSpriteSeq::realizeTime() { if ( m_dwRealizedTime == m_dwTime ) return; m_dwRealizedTime = m_dwTime; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////// // KEventBoxSeq Implement //////////////////////////////////////////////////////////////////////////////////////////////////////////////// KEventBoxSeq::KEventBoxSeq() { m_nType = KEVTYPE_BOX; } KEventBoxSeq::~KEventBoxSeq() { } KSeqObject *KEventBoxSeq::Clone() { KEventBoxSeq *obj = new KEventBoxSeq; obj->SetRes( m_spRes ); return obj; } const char *KEventBoxSeq::GetName() { if ( m_spRes != NULL ) { return m_spRes->GetName(); } return NULL; } void KEventBoxSeq::SetRes( K3DResEventBox *res ) { assert(m_spRes == NULL); m_spRes = res; if ( m_spRes != NULL ) { m_interval = m_spRes->GetInterval(); } } void KEventBoxSeq::Render( KViewportObject *viewport, DWORD flag, const K3DMatrix * pAttachMat ) { //realizeTime(); //m_bCube.Render( viewport ); } const K3DBoundRotCube &KEventBoxSeq::GetCube() { realizeTime(); return m_bCube; } void *KEventBoxSeq::Perform( KID id, KArg& msg ) { _CID( REQ_EVBOX ); if ( id == id_REQ_EVBOX ) { KMsgREQ_EVBOX *reqmsg = static_cast(&msg); reqmsg->AddBox( this ); return (void*)1; } return NULL; } void KEventBoxSeq::realizeTime() { if ( m_dwRealizedTime == m_dwTime ) return; m_dwRealizedTime = m_dwTime; if ( m_spRes != NULL ) { m_spRes->GetData( m_dwTime, &m_bCube ); } } void KEventBoxSeq::SetParentTransform( const K3DMatrix *pMatParent, const K3DMatrix *pMatAttach, BOOL bRotationLock ) { KEventSeq::SetParentTransform( pMatParent, pMatAttach, bRotationLock ); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////// // KEventPointSeq Implement //////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool KEventPointSeq::m_sIsRender = false; KEventPointSeq::KEventPointSeq() { m_nType = KEVTYPE_BOX; m_bCube = K3DBoundRotCube( -1, 1, -1, 1, -1, 1 ); K3DMatrixIdentity( m_matPoint ); } KEventPointSeq::~KEventPointSeq() { } KSeqObject *KEventPointSeq::Clone() { KEventPointSeq *obj = new KEventPointSeq; obj->SetRes( m_spRes ); return obj; } const char *KEventPointSeq::GetName() { if ( m_spRes != NULL) { return m_spRes->GetName(); } return NULL; } void KEventPointSeq::SetRes( K3DResEventPoint *res ) { assert(m_spRes == NULL); m_spRes = res; if ( m_spRes != NULL) { m_interval = m_spRes->GetInterval(); } } void KEventPointSeq::Render( KViewportObject *viewport, DWORD flag, const K3DMatrix * pAttachMat ) { if( m_sIsRender ) { realizeTime(); // m_prAxisWire01.Clear(); m_prAxisWire02.Clear(); K3DMatrix matResult; K3DMatrixIdentity( matResult ); if ( m_pMatAttach != NULL && m_pMatParent != NULL ) { //K3DMatrix Mat1 = *m_pMatAttach; //K3DVector vVectorX, vVectorY, vVectorZ; //AxisCalculation( Mat1, vVectorX, vVectorY, vVectorZ ); //m_prAxisWire01.AddLine( *K3DMatrixGetPosVector( Mat1 ), vVectorX, KColor(255,0,0,255) ); //m_prAxisWire01.AddLine( *K3DMatrixGetPosVector( Mat1 ), vVectorY, KColor(0,255,0,255) ); //m_prAxisWire01.AddLine( *K3DMatrixGetPosVector( Mat1 ), vVectorZ, KColor(0,0,255,255) ); //예전 코드 ( 문제 있음 ) // K3DMatrixMultiply( matResult, *m_pMatAttach, *m_pMatParent ); // K3DMatrixMultiply( matResult, m_matPoint, matResult ); //새로운 코드 K3DMatrixMultiply( matResult, m_matPoint, *m_pMatAttach ); K3DMatrixMultiply( matResult, matResult, *m_pMatParent ); } else if ( m_pMatParent != NULL ) { //예전 코드 K3DMatrixMultiply( matResult, matResult, *m_pMatParent ); //새로운 코드 // K3DMatrixMultiply( matResult, m_matPoint, *m_pMatParent ); } else { matResult = m_matPoint; } K3DMatrix Mat1 = matResult; K3DVector vVectorX, vVectorY, vVectorZ; AxisCalculation( Mat1, vVectorX, vVectorY, vVectorZ, 2.f ); m_prAxisWire02.AddLine( Mat1.GetPosVector(), vVectorX, KColor(255,0,0,255) ); m_prAxisWire02.AddLine( Mat1.GetPosVector(), vVectorY, KColor(0,255,0,255) ); m_prAxisWire02.AddLine( Mat1.GetPosVector(), vVectorZ, KColor(0,0,255,255) ); m_bCube.SetTransform( matResult ); m_bCube.Render( viewport ); // viewport->RegisterWire( &m_prAxisWire01 ); viewport->RegisterWire( &m_prAxisWire02 ); } } const K3DMatrix &KEventPointSeq::GetPoint() { realizeTime(); return m_matPoint; } void *KEventPointSeq::Perform( KID id, KArg& msg ) { _CID( REQ_EVPOINT ); if ( id == id_REQ_EVPOINT ) { KMsgREQ_EVPOINT *reqmsg = static_cast(&msg); reqmsg->AddPoint( this ); return (void*)1; } return NULL; } void KEventPointSeq::realizeTime() { if ( m_dwRealizedTime == m_dwTime ) return; m_dwRealizedTime = m_dwTime; if ( m_spRes != NULL ) { K3DMatrixIdentity( m_matPoint ); m_spRes->GetData( m_dwTime, &m_matPoint ); } } //////////////////////////////////////////////////////////////////////////////////////////////////////////////// // KFXSeq Implement //////////////////////////////////////////////////////////////////////////////////////////////////////////////// void KFXSeq::GetUVAniRect( int nCurFrame, int nFrameCount ) { int width = int(1.f/m_fTRight); //int height = int(1.f/m_fTBottom); assert( nFrameCount ); int txtpos = nCurFrame%nFrameCount; int px = txtpos%width; int py = txtpos/width; m_fLeft+=m_fTRight*px; m_fRight+=m_fTRight*px; m_fTop+=m_fTBottom*py; m_fBottom+=m_fTBottom*py; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////// // KFXBillboardSeq Implement //////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool KFXBillboardSeq::m_sVisbleCube = false; KFXBillboardSeq::KFXBillboardSeq() { m_nType = KFXTYPE_BILLBOARD; } KFXBillboardSeq::~KFXBillboardSeq() { } KSeqObject *KFXBillboardSeq::Clone() { KFXBillboardSeq *obj = new KFXBillboardSeq; obj->SetRes( m_spRes ); const K3DVertex* pVtx = m_boundCube.GetOriginVertices(); obj->SetCube( pVtx[0].x, pVtx[7].x, pVtx[0].y, pVtx[7].y, pVtx[0].z, pVtx[7].z ); return obj; } void KFXBillboardSeq::SetRes( KResFXBillboard *res ) { assert(m_spRes == NULL); m_spRes = res; if(m_spRes != NULL) { m_interval = m_spRes->GetInterval(); m_prBillboard.SetBillboardRes( m_spRes ); m_prBillboard.SetTransparent( true ); m_prBillboard.SetFixedAxis( m_spRes->GetFixedAxis() ); if( m_spRes->GetAdditiveRenderMode() ) m_prBillboard.SetBlendMode( K3DMaterial::MBM_ADDTIVE_BILLBOARD ); else m_prBillboard.SetBlendMode( K3DMaterial::MBM_BILLBOARD ); } } void KFXBillboardSeq::SetCube( float minx, float maxx, float miny, float maxy, float minz, float maxz ) { m_boundCube = K3DBoundRotCube( minx, maxx, miny, maxy, minz, maxz ); } void KFXBillboardSeq::Render( KViewportObject *viewport, DWORD flag, const K3DMatrix * pAttachMat ) { realizeTime(); if( !m_bRenderFlag ) return; if( m_fVisResult <= 0.f ) return; //투명한 놈이므로 안 그림 if ( m_spRes != NULL ) { m_prBillboard.SetColor( KColor( 255, 255, 255, unsigned char(255.f * (m_fVisResult * m_fMasterVisibility)) ) ); if ( m_spRes->GetUVAnimation() ) { int nMaxFrame = m_spRes->GetUVAniMaxFrame(); float fUVRatio = 1.0f / sqrtf( (float)nMaxFrame ); assert( nMaxFrame ); int nLoopFrame = m_spRes->GetUvLoopFrame(); if( nLoopFrame == 0 ) nLoopFrame = m_spRes->GetRangeEnd(); int nAniCount = int(( nMaxFrame / ( float ) nLoopFrame ) * m_dwTime); if ( nAniCount >= nMaxFrame ) nAniCount %= nMaxFrame; int width = int(1.f / fUVRatio); int txtpos = nAniCount % nMaxFrame; int px = txtpos % width; int py = txtpos / width; float l, r, t, b; l = fUVRatio * px; r = fUVRatio + fUVRatio * px; t = fUVRatio * py; b = fUVRatio + fUVRatio * py; m_prBillboard.SetUV( l, t, r, b ); } else { m_prBillboard.SetUV( .0f, .0f, 1.0f, 1.0f ); } K3DMatrix mat = m_matTransform; K3DMatrix matResult; if ( m_pMatAttach != NULL && m_pMatParent != NULL ) { K3DMatrix matTemp; K3DMatrixMultiply( matTemp, *m_pMatAttach, *m_pMatParent ); K3DMatrixMultiply( matResult, mat, matTemp ); } else if ( m_pMatParent != NULL ) K3DMatrixMultiply( matResult, mat, *m_pMatParent ); else matResult = mat; m_boundCube.SetTransform( matResult ); const K3DVector *cube = m_boundCube.GetVertices(); K3DVector vCenterPos = K3DVector(0.f, 0.f, 0.f); vCenterPos = cube[0] + (0.5f*(cube[7] - cube[0])); m_prBillboard.SetRootMat( &matResult ); m_prBillboard.SetCenterPosition( vCenterPos ); m_prBillboard.SetTransform( matResult ); m_prBillboard.SetAngle( 2.0f * K3D_PI * m_spRes->GetRotateSpeed() * ( float ) m_dwTime / 9600.0f ); if( flag == KRenderObject::RENDEREFX_AFTER_SPRITE ) viewport->Register( &m_prBillboard, flag ); else viewport->Register( &m_prBillboard, KRenderObject::RENDEREFX_NONE ); if( m_sVisbleCube ) { m_boundCube.Render( viewport ); m_prCenterWire.Clear(); K3DVector vVectorX, vVectorY, vVectorZ; vVectorX = vCenterPos; vVectorY = vCenterPos; vVectorZ = vCenterPos; vVectorX.x += 3.f; vVectorY.y += 3.f; vVectorZ.z += 3.f; //CenterPos m_prCenterWire.AddLine( vCenterPos, vVectorX, KColor(255,0,0,255) ); m_prCenterWire.AddLine( vCenterPos, vVectorY, KColor(0,255,0,255) ); m_prCenterWire.AddLine( vCenterPos, vVectorZ, KColor(0,0,255,255) ); viewport->RegisterWire( &m_prCenterWire ); } } } void *KFXBillboardSeq::Perform( KID id, KArg& msg ) { _CID( SETFORCERENDER_FLAG ); _CID( SETRENDER_FLAG ); _CID( GETMESH_ANIINFO ); if( id == id_SETFORCERENDER_FLAG) { m_bRenderFlag = FALSE; } else if( id == id_SETRENDER_FLAG ) { KMsgSET_RENDERFLAG * renderflagmsg = static_cast(&msg); m_bRenderFlag = renderflagmsg->bRenderFlag; } else if( id == id_GETMESH_ANIINFO ) { KMsgGET_MESHANI_INFO * meshani_info = static_cast(&msg); if( m_spRes != NULL ) { { if( meshani_info->nStart < m_spRes->GetInterval().GetStart() ) meshani_info->nStart = m_spRes->GetInterval().GetStart(); if( meshani_info->nEnd < m_spRes->GetInterval().GetEnd() ) meshani_info->nEnd = m_spRes->GetInterval().GetEnd(); } } } return (void*)1; } void KFXBillboardSeq::realizeTime() { if ( m_dwRealizedTime == m_dwTime ) return; m_dwRealizedTime = m_dwTime; if ( m_spRes != NULL ) { m_spRes->GetData( m_dwTime, &m_fVisResult, &m_matTransform ); } if ( m_dwTime > unsigned int(m_spRes->GetRangeEnd() + 160) ) m_fVisResult = 0; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////// // KFXParticleObject Implement //////////////////////////////////////////////////////////////////////////////////////////////////////////////// class KFXParticleObject { public: KFXParticleObject() { m_nLifeTime = 0; m_nCurTime = 0; m_bNewParticle = false; } virtual ~KFXParticleObject() {} virtual void Init( const K3DMatrix *pMatParent, KResFXParticle *res, float fRadius, int nLifeTime, int nCreateTime, const K3DVector &startpos, const K3DVector &vec, const K3DVector &velocity ) { // m_pMatParent = pMatParent; m_pRes = res; m_fRadius = fRadius; m_nLifeTime = nLifeTime; m_nCreateTime = nCreateTime; m_nCurTime = 0; m_vecStart = startpos; m_vecVector = vec; m_vecVelocity = velocity; m_fTop = m_fLeft = 0.f; m_fBottom = m_fRight = 1.0f; if ( m_pRes->GetUVAnimation() ) { m_fUVRatio = 1.0f / sqrtf( (float)m_pRes->GetUVAniMaxFrame() ); } m_bNewParticle = true; } void ChangeVector( const K3DVector &vec, const K3DVector &vel ) { m_vecVector = vec; m_vecVelocity = vel; } void Process( int time ) { m_nCurTime = abs(time - m_nCreateTime); _ProcessParticlePos(); _ProcessUVAnimation(); _ProcessTransformVisibility(); } const K3DVector &GetPos() { return m_vecPos; } const KColor &GetColor() { return m_colParticle; } float GetWidth() { return m_fWidth; } float GetHeight() { return m_fHeight; } bool IsLife() { return m_nLifeTime > m_nCurTime; } int GetLife() { return m_nLifeTime - m_nCurTime; } void GetUV( float *_left, float *_top, float *_right, float *_bottom ) { *_left = m_fLeft; *_top = m_fTop; *_right = m_fRight; *_bottom = m_fBottom; } bool IsNewParticle() { return m_bNewParticle; } void UsedParticle() { m_bNewParticle = false; } protected: virtual void _ProcessParticlePos() { float nTime = m_nCurTime / 160.f; m_vecPos.x = ( m_vecVector.x * powf( m_vecVelocity.x, nTime )) * nTime; m_vecPos.y = ( m_vecVector.y * powf( m_vecVelocity.y, nTime )) * nTime; m_vecPos.z = ( m_vecVector.z * powf( m_vecVelocity.z, nTime )) * nTime; K3DVector NorVec; NorVec = m_vecVector; Normalize( NorVec ); m_vecOldPos = m_vecPos; m_vecPos += m_fRadius * NorVec; m_vecPos += m_vecStart; } void _ProcessUVAnimation() { if ( m_pRes && m_pRes->GetUVAnimation() ) { int nMaxFrame = m_pRes->GetUVAniMaxFrame(); assert( nMaxFrame ); int nLoopFrame = m_pRes->GetUvLoopFrame(); if( nLoopFrame == 0 ) nLoopFrame = m_nLifeTime; int nAniCount = int(( nMaxFrame / ( float ) m_nLifeTime ) * m_nCurTime); if ( nAniCount >= nMaxFrame ) nAniCount %= nMaxFrame; int width = int(1.f / m_fUVRatio); int txtpos = nAniCount % nMaxFrame; int px = txtpos % width; int py = txtpos / width; m_fLeft = m_fUVRatio * px; m_fRight = m_fLeft + m_fUVRatio; m_fTop = m_fUVRatio * py; m_fBottom = m_fTop + m_fUVRatio; } else if( !m_pRes ) { _oprint( "_ProcessUVAnimation() m_pRes == NULL\n" ); } } void _ProcessTransformVisibility() { K3DMatrix matTransform; float vis; int dattime = int((float)((float)m_nCurTime/m_nLifeTime) * m_pRes->GetInterval().GetLength()); m_pRes->GetData( dattime, &vis, &matTransform ); m_colParticle = KColor( 255, 255, 255, unsigned char(vis * 255 )); // Process Matrix Transfom /* if ( m_pMatParent ) K3DMatrixMultiply( &matTransform, &mat, m_pMatParent ); else matTransform = mat;*/ // calc radius const K3DVertex *pV = m_pRes->GetVertices(); K3DVector transVtx[4]; int i; for( i=0 ; i < 4 ; ++i ) { K3DVectorTransform( transVtx[i], pV[i], matTransform ); } //K3DVector vWidth = transVtx[0] - transVtx[1]; //K3DVector vHeight = transVtx[1] - transVtx[3]; //m_fWidth = K3DVectorLength( vWidth ); m_fWidth = min( K3DVectorLength( transVtx[1] - transVtx[3] ), K3DVectorLength( transVtx[1]- transVtx[2]) ); // dirty workaround by Tyburn -_-; //m_fHeight = K3DVectorLength( vHeight ); m_fHeight = K3DVectorLength( transVtx[0] - transVtx[1] ); } const K3DMatrix* m_pMatParent; // Particle Object는 실시간에 몇천개씩 생겼다 사라지므로 일부러 Smart Pointer 사용안함 // Parent에 묶여있는 상태이므로 안전성은 보장된다. KResFXParticle* m_pRes; float m_fUVRatio; float m_fLeft, m_fRight, m_fTop, m_fBottom; float m_fRadius; KColor m_colParticle; float m_fWidth,m_fHeight; int m_nLifeTime; int m_nCurTime; int m_nCreateTime; K3DVector m_vecPos; K3DVector m_vecOldPos; K3DVector m_vecStart; K3DVector m_vecVector; K3DVector m_vecVelocity; bool m_bNewParticle; }; //////////////////////////////////////////////////////////////////////////////////////////////////////////////// // KFXGravityParticleObject Implement //////////////////////////////////////////////////////////////////////////////////////////////////////////////// class KFXGravityParticleObject : public KFXParticleObject { public: KFXGravityParticleObject() { m_fGravityAccel = 9.8f; m_vecGravity = K3DVector(0,0,-1); } virtual ~KFXGravityParticleObject() {} virtual void Init( const K3DMatrix *pMatParent, KResFXParticle *res, float fRadius, int nLifeTime, int nCreateTime, const K3DVector &startpos, const K3DVector &vec, const K3DVector &velocity ) { KFXParticleObject::Init(pMatParent,res,false,nLifeTime,nCreateTime,startpos,vec,velocity); m_fGravityAccel = res->GetGravityAccel(); m_vecGravity = res->GetGravity(); } protected: virtual void _ProcessParticlePos() { float nTime = m_nCurTime / 160.f; K3DVector temp; temp = m_vecGravity; Normalize(temp); temp *= m_fGravityAccel; m_vecPos.x = float( m_vecVector.x * nTime + 0.5 * temp.x * pow(nTime, 2) ); m_vecPos.y = float( m_vecVector.y * nTime + 0.5 * temp.y * pow(nTime, 2) ); m_vecPos.z = float( m_vecVector.z * nTime + 0.5 * temp.z * pow(nTime, 2) ); K3DVector NorVec; NorVec = m_vecVector; Normalize( NorVec ); m_vecOldPos = m_vecPos; m_vecPos += m_fRadius * NorVec; m_vecPos += m_vecStart; } float m_fGravityAccel; K3DVector m_vecGravity; }; //////////////////////////////////////////////////////////////////////////////////////////////////////////////// // KFXReverseParticleObject Implement //////////////////////////////////////////////////////////////////////////////////////////////////////////////// class KFXReverseParticleObject : public KFXParticleObject { public: KFXReverseParticleObject(){} virtual ~KFXReverseParticleObject() {} protected: virtual void _ProcessParticlePos() { int tempTime = m_nCurTime; tempTime = m_nLifeTime - tempTime; float nTime = tempTime / 160.f; m_vecPos.x = ( m_vecVector.x * powf( m_vecVelocity.x, nTime )) * nTime; m_vecPos.y = ( m_vecVector.y * powf( m_vecVelocity.y, nTime )) * nTime; m_vecPos.z = ( m_vecVector.z * powf( m_vecVelocity.z, nTime )) * nTime; K3DVector NorVec; NorVec = m_vecVector; Normalize( NorVec ); m_vecOldPos = m_vecPos; m_vecPos += m_fRadius * NorVec; m_vecPos += m_vecStart; } }; //////////////////////////////////////////////////////////////////////////////////////////////////////////////// // KFXParticleSeq Implement //////////////////////////////////////////////////////////////////////////////////////////////////////////////// KFXParticleSeq::KFXParticleSeq(DWORD dwParticleType) { m_nType = KFXTYPE_PARTICLE; m_dwParticleType = dwParticleType; m_bInited = false; m_ppParticles = NULL; m_nParticleCount = 0; m_pMatAttach = NULL; m_pMatParent = NULL; } KFXParticleSeq::~KFXParticleSeq() { _ClearObject(); } KSeqObject *KFXParticleSeq::Clone() { KFXParticleSeq *obj = new KFXParticleSeq(m_dwParticleType); obj->SetRes( m_spRes ); return obj; } void KFXParticleSeq::SetRes( KResFXParticle *res ) { assert(m_spRes == NULL); m_spRes = res; if(m_spRes != NULL) { m_interval = m_spRes->GetInterval(); m_prParticle.SetParticleRes( m_spRes ); m_prParticle.SetTransparent( true ); if( m_spRes->GetAdditiveRenderMode() ) m_prParticle.SetBlendMode( K3DMaterial::MBM_ADDTIVE_BILLBOARD ); else m_prParticle.SetBlendMode( K3DMaterial::MBM_BILLBOARD ); m_prParticle.SetAttachParent( m_spRes->IsAttachParent() ); } } void KFXParticleSeq::Render( KViewportObject *viewport, DWORD flag, const K3DMatrix * pAttachMat ) { realizeTime(); if( !m_bRenderFlag ) return; static KFXParticlePrimitive::_PARTICLE particle; if ( m_ppParticles ) { m_prParticle.ResetParticleCount(); int nDrawCount = 0; for( int i = 0 ; i < m_nParticleCount ; ++i ) { KFXParticleObject *ptc = m_ppParticles[i]; if( ptc->IsLife() == true ) { ptc->Process( m_dwMyTime ); particle.pos = ptc->GetPos(); particle.color = ptc->GetColor(); particle.fWidth = ptc->GetWidth(); particle.fHeight = ptc->GetHeight(); ptc->GetUV( &particle.l, &particle.t, &particle.r, &particle.b ); m_prParticle.SetParticleInfo( nDrawCount, particle ); if( ptc->IsNewParticle() ) { m_prParticle.NewParticle( nDrawCount ); ptc->UsedParticle(); } ++nDrawCount; } } if( flag == KRenderObject::RENDEREFX_AFTER_SPRITE ) viewport->Register( &m_prParticle, flag ); else viewport->Register( &m_prParticle, KRenderObject::RENDEREFX_NONE ); } } void *KFXParticleSeq::Perform( KID id, KArg& msg ) { _CID( SETFORCERENDER_FLAG ); _CID( GETMESH_ANIINFO ); if( id == id_SETFORCERENDER_FLAG) { m_bRenderFlag = FALSE; } else if( id == id_GETMESH_ANIINFO ) { KMsgGET_MESHANI_INFO * meshani_info = static_cast(&msg); if( m_spRes != NULL ) { // if( _stricmp( meshani_info->strFindName.c_str(), m_pResMesh->GetName() ) == 0 ) { if( meshani_info->nStart < m_spRes->GetInterval().GetStart() ) meshani_info->nStart = m_spRes->GetInterval().GetStart(); if( meshani_info->nEnd < m_spRes->GetInterval().GetEnd() ) meshani_info->nEnd = m_spRes->GetInterval().GetEnd(); } } } return (void*)1; } void KFXParticleSeq::realizeTime() { if(m_spRes == NULL) return; if ( m_bInited == false ) { _Initialize(); m_dwOldTime = m_dwTime; m_dwOldCreateTime = m_spRes->GetRangeStart(); m_dwMyTime = 0; } int nInterval = m_dwTime - m_dwOldTime; if ( nInterval < 0 ) { nInterval = m_interval.GetEnd() - m_dwOldTime + m_dwTime; if ( m_spRes->IsLoop() == false ) { _ClearObject(); m_bInited = false; return; } } m_dwMyTime += nInterval; if( (int(m_dwMyTime) - int(m_dwOldCreateTime)) >= m_spRes->GetCreateTime() ) { if ( (unsigned int)m_spRes->GetRangeStart() <= m_dwMyTime && (( m_spRes->IsLoop() == true ) || ( m_spRes->IsLoop() == false && (unsigned int)m_spRes->GetRangeEnd() > m_dwMyTime )) ) { int count = (m_dwMyTime - m_dwOldCreateTime) / m_spRes->GetCreateTime(); //gmpbigsun( 20131125 ) : 아래코드는 파티클 생성시간을 같도록 강제로 만들어버린것이다 //의도를 알수없으나, 상당히 잘못된 코드임. 주석처리된것으로 바꾸면 랜덤생성인것임. //파티클 수정 //2009-21-26 : hunee //m_dwOldCreateTime = m_dwMyTime - ((m_dwMyTime-m_dwOldCreateTime) % m_spRes->GetCreateTime()); m_dwOldCreateTime = m_dwMyTime - (m_dwMyTime - m_dwOldCreateTime); for( int i = 0 ; i < m_nParticleCount ; ++i ) { KFXParticleObject *ptc = m_ppParticles[i]; if( ptc->IsLife() == false ) { _CreateParticle( i , m_spRes->GetCreateTime() ); if ( (--count) == 0 ) break; } } } } m_dwOldTime = m_dwTime; K3DMatrix matResult; K3DMatrixIdentity( matResult ); if ( m_pMatAttach != NULL && m_pMatParent != NULL ) { K3DMatrix matTemp; K3DMatrixMultiply( matTemp, *m_pMatAttach, *m_pMatParent ); K3DMatrixMultiply( matResult, matResult, matTemp ); } else if ( m_pMatParent != NULL ) K3DMatrixMultiply( matResult, matResult, *m_pMatParent ); m_prParticle.SetRootMat( &matResult ); m_prParticle.SetCenterPosition( K3DVector( matResult._41, matResult._42, matResult._43 ) ); } /// Get random vector (vertex) from given direction vector and angle. static inline K3DVector K3DVectorGetRandom( const K3DVector &vec, float fAngle ) { K3DVector Result, Sample; float fRadius, fTheta, fPitch; float fNewRadius, fNewTheta, fNewPitch; Sample = K3DVector( 0, 0, 1 ); fRadius = sqrtf( ( Sample.x * Sample.x ) + ( Sample.y * Sample.y ) + ( Sample.z * Sample.z ) ); fPitch = acosf( Sample.z / fRadius ); if( Sample.x == 0.000000f ) fTheta = 90 * K3D_PI / 180.f; else fTheta = ( Sample.x > 0.f ) ? atanf( Sample.y / Sample.x ) : atanf( Sample.y / Sample.x ) + K3D_PI; int nUnit = int( fAngle * 10.f ); float fRandPitch = fAngle - ( 0.1f * ( rand()%(nUnit * 2) ) ); // float fRandTheta = fAngle - ( 0.1f * ( rand()%(nUnit * 2) ) ); float fRandTheta = 180 - ( 1.0f * ( rand()%(180*2) ) ); fRandPitch = fRandPitch * K3D_PI / 180.f; fRandTheta = fRandTheta * K3D_PI / 180.f; fNewRadius = fRadius; fNewPitch = fPitch + fRandPitch; // fNewTheta = fTheta + fRandTheta; fNewTheta = fRandTheta; Result.x = fNewRadius * cosf( fNewTheta ) * sinf( fNewPitch ); Result.y = fNewRadius * sinf( fNewTheta ) * sinf( fNewPitch ); Result.z = fNewRadius * cosf( fNewPitch ); Normalize( Result ); /////////////////////////////////////// /////////////////////////////////////// K3DVector va; K3DMatrix mat; float fDot = K3DVectorDot( Sample, vec ); float ffAngle = acosf( fDot ); K3DVectorCross( va, Sample, vec ); K3DMatrixRotationAxis( mat, va, ffAngle ); K3DVector Res; K3DVectorTransform( Res, Result, mat ); return Res; } void KFXParticleSeq::_CreateParticle( int index, int TimeUnit ) { if( index < 0 || index >= m_nParticleCount ) return; /* K3DMatrix mat; m_spRes->GetData( m_dwTime, &m_fVisResult, &mat ); if ( m_pMatParent ) K3DMatrixMultiply( &m_matTransform, &mat, m_pMatParent ); else m_matTransform = mat;*/ m_spRes->GetData( m_dwTime, &m_fVisResult, &m_matTransform ); // calc radius const K3DVertex *pV = m_spRes->GetVertices(); K3DVector transVtx[4]; int i; for( i=0 ; i < 4 ; ++i ) { K3DVectorTransform( transVtx[i], pV[i], m_matTransform ); } K3DVector vRadius = transVtx[0] - transVtx[1]; m_fRadius = K3DVectorLength( vRadius ); //K3DMatrixGetZVector( m_vecVector, m_matTransform ); K3DVectorTransformNormal( m_vecVector, m_spRes->GetNormal(), m_matTransform ); Normalize( m_vecVector ); m_vecVelocity = m_spRes->GetVelocity(); KFXParticleObject *ptc = m_ppParticles[index]; K3DVector pos; K3DMatrixGetPosVector( pos, m_matTransform ); K3DVector vVec = K3DVectorGetRandom( m_vecVector, m_spRes->GetSpreadAngle() ); K3DVector vBeginSpeed = m_spRes->GetBeginSpeed(); vVec *= _GetRandom( vBeginSpeed.x, vBeginSpeed.y ); int nLifeTime = m_spRes->GetLifeTime() + (rand() % (m_spRes->GetLifeTimeVariation() - m_spRes->GetLifeTime())); ptc->Init( m_pMatParent, m_spRes, m_fRadius, nLifeTime, m_dwMyTime, pos, vVec, m_vecVelocity ); } void KFXParticleSeq::_Initialize() { _ClearObject(); if ( m_spRes ) { m_nParticleCount = (m_spRes->GetLifeTime() + m_spRes->GetLifeTimeVariation()) / m_spRes->GetCreateTime(); m_prParticle.SetParticleCount( m_nParticleCount ); _GenerateObject(); m_bInited = true; } } float KFXParticleSeq::_GetRandom( float min, float variation ) { float Result; if( variation == 0.f ) return min; Result = min + ( rand() % (int)(variation) ); return Result; } void KFXParticleSeq::_GenerateObject() { assert( m_nParticleCount && "Particle Zero Count" ); if( !m_nParticleCount ) return; switch(m_dwParticleType) { case KPARTICLE_DEFAULT: { m_ppParticles = new KFXParticleObject*[m_nParticleCount]; for(int i = 0; i < m_nParticleCount; ++i) { m_ppParticles[i] = new KFXParticleObject; } break; } case KPARTICLE_GRAVITY: { m_ppParticles = reinterpret_cast( new KFXGravityParticleObject*[m_nParticleCount] ); for(int i = 0; i < m_nParticleCount; ++i) { m_ppParticles[i] = new KFXGravityParticleObject; } break; } case KPARTICLE_REVERSE: { m_ppParticles = reinterpret_cast( new KFXReverseParticleObject*[m_nParticleCount] ); for(int i = 0; i < m_nParticleCount; ++i) { m_ppParticles[i] = new KFXReverseParticleObject; } break; } default: { assert(false && "Invalid Particle Type"); } } } void KFXParticleSeq::_ClearObject() { if ( m_ppParticles ) { for(int i = 0 ; i < m_nParticleCount; ++i) SAFE_DELETE(m_ppParticles[i]); SAFE_DELETE_ARRAY(m_ppParticles); } } //////////////////////////////////////////////////////////////////////////////////////////////////////////////// // KFXAferImagerSeq Implement //////////////////////////////////////////////////////////////////////////////////////////////////////////////// namespace { const int FRAME_PER_VTX = 1; const int SPLINE_ARGUMENT = 4; } KFXAfterImageSeq::KFXAfterImageSeq() { m_bOldValidate = false; m_pMatLerp = NULL; m_dwVertexCount = 0; m_dwLastSplinePushCount = 0; m_dwLastNormalLineCount = 0; m_pVertexListOne = m_pVertexListTwo = NULL; K3DMatrixIdentity( m_matOld ); K3DMatrixIdentity( m_matRoot ); K3DMatrixIdentity( m_matLocal ); } KFXAfterImageSeq::~KFXAfterImageSeq() { SAFE_DELETE_ARRAY(m_pMatLerp); SAFE_DELETE_ARRAY(m_pVertexListOne); SAFE_DELETE_ARRAY(m_pVertexListTwo); } KSeqObject *KFXAfterImageSeq::Clone() { KFXAfterImageSeq *obj = new KFXAfterImageSeq; obj->SetRes( m_spRes ); return obj; } void KFXAfterImageSeq::SetRes( KResFXAfterImage *pRes ) { assert(m_spRes == NULL); m_spRes = pRes; if(m_spRes != NULL) { m_interval = m_spRes->GetInterval(); // 한 Frame당 4개씩 Spline 보간 m_prAfterImage.Initialize(m_spRes->GetFrameNumber() * FRAME_PER_VTX ); m_prAfterImage.SetTexture(m_spRes->GetTexture()); m_pMatLerp = new K3DMatrix[ max( m_spRes->GetFrameNumber(), FRAME_PER_VTX ) ]; // Catmull-rom Spline을 위한 Vertex m_pVertexListOne = new K3DVertex[m_spRes->GetFrameNumber()]; m_pVertexListTwo = new K3DVertex[m_spRes->GetFrameNumber()]; m_prAfterImage.SetBlendMode( m_spRes->GetBlendMode() ); } } void KFXAfterImageSeq::Render( KViewportObject *pViewport, DWORD flag, const K3DMatrix * pAttachMat ) { realizeTime(); float vis = m_fMasterVisibility * m_fVisResult; if( vis <= 0.f ) return; if ( m_pMatAttach != NULL && m_pMatParent != NULL ) { m_matRoot = *m_pMatParent; m_matLocal = *m_pMatAttach; K3DMatrix matResult; K3DMatrixMultiply( matResult, *m_pMatAttach, *m_pMatParent ); m_prAfterImage.SetRootMat( &matResult ); m_prAfterImage.SetCenterPosition( K3DVector( matResult._41, matResult._42, matResult._43 ) ); } else if ( m_pMatParent != NULL ) { m_matRoot = *m_pMatParent; m_prAfterImage.SetRootMat( &m_matRoot ); m_prAfterImage.SetCenterPosition( K3DVector( m_matRoot._41, m_matRoot._42, m_matRoot._43 ) ); } m_prAfterImage.SetVisibility( vis ); pViewport->Register(&m_prAfterImage, KRenderObject::RENDEREFX_NONE ); } void* KFXAfterImageSeq::Perform( int id, KArg& msg) { _CID( AFTER_IMAGE_MOVE ); if ( id == id_AFTER_IMAGE_MOVE ) { KMsgAfterImage_MOVE * pMoveMsg = static_cast(&msg); this->m_prAfterImage.SetMoveAdded(pMoveMsg->GetMoveAdded() ); K3DVertex vPos; K3DMatrixGetPosVector(vPos, m_matOld); vPos+= pMoveMsg->GetMoveAdded(); m_matOld.SetPosVector(vPos); } return NULL; } void KFXAfterImageSeq::realizeTime() { // realize 할 필요 없음 (이미 했으므로) if ( m_dwRealizedTime == m_dwTime ) return; if( m_spRes == NULL) return; // Old Matrix값의 초기화 if( m_bOldValidate == false ) { m_bOldValidate = true; return; } int nInterval = static_cast(m_dwTime - m_dwRealizedTime); if(nInterval < 0) nInterval += m_interval.GetLength(); // 추가될 Spline Frame의 갯수 int dwAddFrames = min( nInterval / m_spRes->GetFrameTime(), m_spRes->GetFrameNumber() ); if( dwAddFrames == 0) { _PushNormalLine( nInterval ); return; } //// Spline을 만들수 없을때는 리턴 //if( m_dwVertexCount + dwAddFrames < SPLINE_ARGUMENT) // return; _MakeLerpMatrix(dwAddFrames, nInterval); // 새로운 vertex를 얻어서 저장. (시간이 늦은 vertex부터 추가하자) K3DSPRITEVERTEX vtx0, vtx1; for(int i = dwAddFrames - 1; i >= 0; --i) { int nTime = static_cast( m_dwTime - (i * m_spRes->GetFrameTime()) ); // 시간이 한번 loop 를 돈 경우 if(nTime < 0) nTime += m_interval.GetLength(); m_spRes->GetData(nTime, vtx0, vtx1, m_pMatLerp[i], m_fVisResult); DWORD dwIndex = m_dwVertexCount % (m_spRes->GetFrameNumber()); m_pVertexListOne[dwIndex] = vtx0.pos; m_pVertexListTwo[dwIndex] = vtx1.pos; m_dwVertexCount++; } // Spline을 만들수 없을때는 리턴 if( m_dwVertexCount + dwAddFrames < SPLINE_ARGUMENT) return; // Spline 생성 _PushSpline( dwAddFrames); // 새로운 vertex가 추가 되었던 시간을 기록한다. m_dwRealizedTime = m_dwTime; } void KFXAfterImageSeq::_MakeLerpMatrix(DWORD dwAddFrames, int nInterval) { // i 가 작은 값이 current time 가깝고, i 가 커질수록 old time에 근접한다. for(unsigned int i = 0; i < dwAddFrames; ++i) { K3DMatrixIdentity(m_pMatLerp[i]); DWORD dwDiff = abs( nInterval - (int)i * m_spRes->GetFrameTime() ); float fWeight = static_cast(dwDiff)/ static_cast( nInterval ); // 예전에 이동했던 값과 비교해서 matrix 보간 if ( m_pMatParent != NULL ) K3DMatrixLerp(m_pMatLerp[i], m_matOld, m_matOld, fWeight); } } void KFXAfterImageSeq::_PushNormalLine(int nInterval) { // 추가될 Spline Frame의 갯수 DWORD dwFrameTime = m_spRes->GetFrameTime() / FRAME_PER_VTX; if(dwFrameTime <= 0) return; DWORD dwAddFrames = min( (DWORD)nInterval / dwFrameTime, (DWORD)FRAME_PER_VTX ); if( dwAddFrames == 0) return; m_prAfterImage.PopVertex( m_dwLastNormalLineCount); m_dwLastNormalLineCount = dwAddFrames; _MakeLerpMatrix(dwAddFrames, nInterval); m_prAfterImage.ReserveVtx( dwAddFrames ); K3DSPRITEVERTEX vtx0, vtx1; for(int i = dwAddFrames - 1; i >= 0; --i) { int nTime = static_cast( m_dwTime - (i * dwFrameTime) ); // 시간이 한번 loop 를 돈 경우 if(nTime < 0) nTime += m_interval.GetLength(); m_spRes->GetData(nTime, vtx0, vtx1, m_pMatLerp[i], m_fVisResult); m_prAfterImage.PushVertex( vtx0, vtx1); } m_prAfterImage.UpdateVertex(); } void KFXAfterImageSeq::_PushSpline(DWORD dwAddFrames) { m_prAfterImage.PopVertex( m_dwLastSplinePushCount + m_dwLastNormalLineCount); m_dwLastSplinePushCount = 0; m_dwLastNormalLineCount = 0; DWORD dwMaxFrameNumber = m_spRes->GetFrameNumber(); DWORD dwOldVertexCount = m_dwVertexCount - dwAddFrames; const float fScaleLargeUnit = 1.f / (float)FRAME_PER_VTX; DWORD dwOffset = 0; if( dwMaxFrameNumber < dwAddFrames + SPLINE_ARGUMENT) dwOffset = SPLINE_ARGUMENT -1 - dwMaxFrameNumber + dwAddFrames; // 예전에 저장된 Frame의 Vertex count가 Spline Argument를 만족하지 못함. if( dwOldVertexCount < SPLINE_ARGUMENT) dwOffset = SPLINE_ARGUMENT -1 - dwOldVertexCount; //dwAddFrames -= dwOffset; if( dwAddFrames >= dwOffset ) dwAddFrames -= dwOffset; else return; DWORD dwIndexList[SPLINE_ARGUMENT]; // 더해지는 Frame 만큼 Spline 생성 K3DSPRITEVERTEX vtx0, vtx1; m_dwLastSplinePushCount = FRAME_PER_VTX + 1; m_prAfterImage.ReserveVtx( dwAddFrames * FRAME_PER_VTX + m_dwLastSplinePushCount ); for(unsigned int i = 0; i < dwAddFrames; ++i) { // 가장 최근 Frame은 Index 값이 낮음. for(DWORD m = 0; m < SPLINE_ARGUMENT; ++m) dwIndexList[m] = (dwOldVertexCount + i + dwOffset - m) % dwMaxFrameNumber; // Frame 별로 넣어주자. for(DWORD k = 0; k < FRAME_PER_VTX; ++k) { K3DVectorCatMullRom(vtx0.pos, m_pVertexListOne[dwIndexList[3] ], m_pVertexListOne[dwIndexList[2] ], m_pVertexListOne[dwIndexList[1] ], m_pVertexListOne[dwIndexList[0] ], fScaleLargeUnit * k); K3DVectorCatMullRom(vtx1.pos, m_pVertexListTwo[dwIndexList[3] ], m_pVertexListTwo[dwIndexList[2] ], m_pVertexListTwo[dwIndexList[1] ], m_pVertexListTwo[dwIndexList[0] ], fScaleLargeUnit * k); m_prAfterImage.PushVertex(vtx0, vtx1); } } // 마지막 연결부위 (이 부분은 넣었다 뺐다 한다) for(DWORD m = 0; m < SPLINE_ARGUMENT; ++m) dwIndexList[m] = (m_dwVertexCount - 1 - m) % dwMaxFrameNumber; for(DWORD k = 0; k < m_dwLastSplinePushCount; ++k) { K3DVectorCatMullRom(vtx0.pos, m_pVertexListOne[dwIndexList[2] ], m_pVertexListOne[dwIndexList[1] ], m_pVertexListOne[dwIndexList[0] ], m_pVertexListOne[dwIndexList[0] ], fScaleLargeUnit * k); K3DVectorCatMullRom(vtx1.pos, m_pVertexListTwo[dwIndexList[2] ], m_pVertexListTwo[dwIndexList[1] ], m_pVertexListTwo[dwIndexList[0] ], m_pVertexListTwo[dwIndexList[0] ], fScaleLargeUnit * k); m_prAfterImage.PushVertex(vtx0, vtx1); } m_prAfterImage.UpdateVertex(); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////// // KSeqTextureRender Implement //////////////////////////////////////////////////////////////////////////////////////////////////////////////// KSeqTextureRender::KSeqTextureRender() { m_bSourceRenderFlag =true; m_pSeqSource = NULL; m_pRenderTarget = NULL; m_pCamera = NULL; m_sizeTarget = KSize( 256, 256 ); m_formatTarget = K3DFMT_A8R8G8B8; m_pViewport = NULL; // Default Render Freq is 60frame. SetRenderFreq(KSEQ_RENDER_60); m_dwTime = 0; K3DMatrixIdentity(m_matLocal); } KSeqTextureRender::~KSeqTextureRender() { m_vtUserLight.clear(); SAFE_DELETE(m_pViewport); SAFE_DELETE(m_pSeqSource); } void KSeqTextureRender::Initialize( KSeqObject *src, const KSize &targetSize, const K3DFORMAT &texformat) { m_sizeTarget = targetSize; m_formatTarget = texformat; m_pSeqSource = src; KViewportStruct vp; vp.Width = targetSize.cx; vp.Height = targetSize.cy; vp.X = vp.Y = 0; vp.MinZ = 0; vp.MaxZ = 1.0f; m_pViewport = new KViewportObject(KViewportObject::VIEWPORT_GAME, true, true); m_pViewport->Initilaize( KDeviceManager::GetDeviceManager()->GetRenderDevice(), vp, 1, 50000 ); m_pViewport->SetFillColor( K3DColor(0,0,0) ); m_pViewport->SetSceneAmbient( KColor( 250, 250, 250, 255 ) ); m_interval = m_pSeqSource->GetInterval(); KResSprite * pResSprite = new KResSprite; //m_pRenderTarget = KDeviceManager::GetDeviceManager()->GetRenderDevice()->CreateRenderTarget( targetSize.cx, targetSize.cy, 1, m_formatTarget, true ); m_pRenderTarget = KDeviceManager::GetDeviceManager()->GetRenderDevice()->CreateRenderTarget( targetSize.cx, targetSize.cy, 1, m_formatTarget, K3DRenderTarget::DEPTH_ENABLE ); pResSprite->SetTexture(m_pRenderTarget,NULL); m_prSprite.SetRes(pResSprite); m_prSprite.SetTargetSize((float)m_sizeTarget.cx,(float)m_sizeTarget.cy); } void KSeqTextureRender::SetUserCamera( K3DCamera *pCam ) { m_bSourceRenderFlag = true; m_pCamera = pCam; } void KSeqTextureRender::AddUserLight(K3DLight * pLight) { m_bSourceRenderFlag = true; m_vtUserLight.push_back(pLight); } void KSeqTextureRender::SetRenderFreq(DWORD dwRenderFreq) { switch(dwRenderFreq) { case KSEQ_RENDER_ALL: m_dwRenderFrameTime = 1; break; case KSEQ_RENDER_60: m_dwRenderFrameTime = 1000 / 60; break; case KSEQ_RENDER_30: m_dwRenderFrameTime = 1000 / 30; break; case KSEQ_RENDER_ONCE: m_dwRenderFrameTime = 0; break; default: { assert(false && "Render Freq Argument is false"); } } } void KSeqTextureRender::SetAddictive(bool bUseAddictive) { m_prSprite.SetAdditiveRenderMode(bUseAddictive); } void KSeqTextureRender::Render( KViewportObject *viewport, DWORD flag, const K3DMatrix * pAttachMat ) { realizeTime(); if(m_pRenderTarget == NULL) return; if ( m_pMatParent != NULL ) K3DMatrixMultiply( m_matResult, m_matLocal, *m_pMatParent ); else m_matResult = m_matLocal; m_prSprite.SetTransform( m_matResult ); m_prSprite.SetVisibility( m_fMasterVisibility ); if(!m_bSourceRenderFlag) { viewport->Register( &m_prSprite); return; } m_pViewport->SetFillColor( KColor(0,0,0,0) ); if ( m_pCamera == NULL) { { assert(false && "Must Set Camera!"); } } //m_pCamera->Render( m_pViewport ); m_pViewport->SetCamera(m_pCamera); for(int i = 0; i < (int)m_vtUserLight.size(); ++i) { m_pViewport->AddLight(m_vtUserLight.at(i) ); } m_pSeqSource->Render( m_pViewport ); m_pViewport->Render( m_pRenderTarget ); viewport->Register( &m_prSprite); m_bSourceRenderFlag = false; } KSeqObject* KSeqTextureRender::Clone() { KSeqTextureRender *obj = new KSeqTextureRender; obj->Initialize( m_pSeqSource, m_sizeTarget,m_formatTarget ); return obj; } void KSeqTextureRender::realizeTime() { if ( m_dwRealizedTime == m_dwTime || m_dwRenderFrameTime == 0 || m_dwTime - m_dwRealizedTime < m_dwRenderFrameTime ) { return; } m_bSourceRenderFlag = true; m_dwRealizedTime = m_dwTime; if ( m_pSeqSource != NULL ) { m_pSeqSource->SetTime( m_dwRealizedTime ); m_pSeqSource->realizeTime(); } }