#include "stdafx.h" #include "SGameCircleShadowFX.h" #include "KRenderObject.h" #include "SGameViewPort.h" #include "KResourceManager.h" #include "SGameWorld.h" #include "KPrimitive.h" #include "SGameAvatarEx.h" #include "SDebug_Util.h" namespace { float getCountPerMesc() { LARGE_INTEGER counter; QueryPerformanceFrequency( &counter); return (float)counter.LowPart / 1000.f; } const float COUNT_PER_MESC = getCountPerMesc(); DWORD getPerformanceCounter() { static LARGE_INTEGER counter; QueryPerformanceCounter(&counter); return counter.LowPart; } } class KStopWatch { public: KStopWatch() : m_dwCount(0), m_dwTime(0), m_dwHoldTime(0), m_bHold(false) { } void Start() { if (m_dwCount == 0) m_dwTime = getPerformanceCounter(); m_dwCount++; } void Stop() { assert (m_dwCount > 0); m_dwCount--; if (m_dwCount == 0) { m_dwTime = getPerformanceCounter() - m_dwTime; } } void Hold() { m_dwHoldTime = getPerformanceCounter(); m_bHold = true; } void Unhold() { assert(m_bHold); // add hold time to start time m_dwTime += getPerformanceCounter() - m_dwHoldTime; m_dwHoldTime = 0; m_bHold = false; } void Reset() { m_dwCount = m_dwTime = 0; } DWORD GetTime() const { return m_dwTime; } // 1/1000 sec Time float GetMsecTime() const { return (float)m_dwTime / COUNT_PER_MESC; } protected: DWORD m_dwCount; DWORD m_dwTime; DWORD m_dwHoldTime; bool m_bHold; }; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // SGameCircleShadowPrimitive Implement //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class SGameCircleShadowPrimitive : public K3DPrimitive { public: SGameCircleShadowPrimitive(K3DBLENDEDBUMPVERTEX* pVtx, const K3DINDEXED_WATER* pIdx, K3DTexture* pTex) { m_pTexBack = pTex; m_pVertexBufferUP = pVtx; m_pIndexBufferUP = pIdx; SetBlendMode(K3DMaterial::MBM_CIRCLE_FX); SetTransparent(true); } virtual void Render( KViewportObject *pViewport, K3DRenderDevice *pDev, bool bUseAccum = true ) { pDev->SetTransform( K3DRenderDevice::TS_WORLD, &m_RootMat); pDev->SetVertexShaderConstant( CONSTANT_VISIBILITY, &m_fVisibility, 1 ); pDev->SetTexture( 0, m_pTexBack ); pDev->DrawIndexedPrimitiveUP_VS( 0, m_pVertexBufferUP, (SHADOW_SEGMENT_COUNT*SHADOW_SEGMENT_COUNT), sizeof(K3DBLENDEDBUMPVERTEX), &m_pIndexBufferUP[0].a, SHADOW_SEGMENET_INDEX_COUNT * 3 ); } private: K3DTexture* m_pTexBack; K3DBLENDEDBUMPVERTEX* m_pVertexBufferUP; const K3DINDEXED_WATER* m_pIndexBufferUP; }; SCircleShadowCommonInfo& SCircleShadowCommonInfo::GetInstance() { static SCircleShadowCommonInfo indexbuffer; return indexbuffer; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // SGameCircleShadowFX Implement //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// SGameCircleShadowFX::SGameCircleShadowFX() { m_vPos = K3DVector(0.f,0.f,0.f); m_nAddOnType = SGAME_CIRCLE_SHADOW_FX; } void SGameCircleShadowFX::Initialize() { m_fScale = m_pGameObj->GetScale() * m_pGameObj->GetSize() * (float)(GameRule::DEFAULT_UNIT_SIZE); _oprint("Scale is %f\n", m_fScale); ///가로 세로 거리를 세그먼트로 나눈다 m_fWidthLength = m_fScale / (float)(SHADOW_SEGMENT_COUNT-1); m_fHeightLength = m_fScale / (float)(SHADOW_SEGMENT_COUNT-1); m_fWidthCenter = m_fScale / 2.f; m_fHeightCenter = m_fScale / 2.f; // Vertex Initialize m_pVertex = new K3DBLENDEDBUMPVERTEX[SHADOW_SEGMENT_COUNT*SHADOW_SEGMENT_COUNT]; K3DBLENDEDBUMPVERTEX* pVertex = m_pVertex; for(int h = 0; h < SHADOW_SEGMENT_COUNT; h++ ) { for( int w = 0; w < SHADOW_SEGMENT_COUNT; w++) { pVertex->position = K3DVector( 0.f, 0.f, 0.f ); pVertex->normal = K3DVector( 0.f, 1.f, 0.f ); pVertex->color = 0xffffffff; pVertex->texcoord.x = (static_cast(w)/ (SHADOW_SEGMENT_COUNT-1) ); pVertex->texcoord.y = (static_cast(h)/ (SHADOW_SEGMENT_COUNT-1) ); pVertex->tangent = K3DVector4( 0.f, 0.f, 0.f, 0.f ); pVertex->matrixIndices = 0; pVertex->matrixWeights.x = 0.f; pVertex->matrixWeights.y = 0.f; ++pVertex; } } m_pPrimitive = new SGameCircleShadowPrimitive(m_pVertex, SCircleShadowCommonInfo::GetInstance().GetCircleShadowIndexBuffer(), SCircleShadowCommonInfo::GetInstance().GetCircleShadowTexture() ); } SGameCircleShadowFX::~SGameCircleShadowFX() { SAFE_DELETE( m_pPrimitive ); SAFE_DELETE_ARRAY( m_pVertex ); } void SGameCircleShadowFX::Refresh() { m_fScale = m_pGameObj->GetScale() * m_pGameObj->GetSize() * (float)(GameRule::DEFAULT_UNIT_SIZE); _oprint("Scale is %f\n", m_fScale); ///가로 세로 거리를 세그먼트로 나눈다 m_fWidthLength = m_fScale / (float)(SHADOW_SEGMENT_COUNT-1); m_fHeightLength = m_fScale / (float)(SHADOW_SEGMENT_COUNT-1); m_fWidthCenter = m_fScale / 2.f; m_fHeightCenter = m_fScale / 2.f; // Vertex Initialize K3DBLENDEDBUMPVERTEX* pVertex = m_pVertex; for(int h = 0; h < SHADOW_SEGMENT_COUNT; h++ ) { for( int w = 0; w < SHADOW_SEGMENT_COUNT; w++) { pVertex->position = K3DVector( 0.f, 0.f, 0.f ); pVertex->normal = K3DVector( 0.f, 1.f, 0.f ); pVertex->color = 0xffffffff; pVertex->texcoord.x = (static_cast(w)/ (SHADOW_SEGMENT_COUNT-1) ); pVertex->texcoord.y = (static_cast(h)/ (SHADOW_SEGMENT_COUNT-1) ); pVertex->tangent = K3DVector4( 0.f, 0.f, 0.f, 0.f ); pVertex->matrixIndices = 0; pVertex->matrixWeights.x = 0.f; pVertex->matrixWeights.y = 0.f; ++pVertex; } } m_vPos = K3DVector(0.f,0.f,0.f); } void SGameCircleShadowFX::Render( class KViewportObject** ppViewportList, int nViewportCount ) { const float EPSILON = 0.1f; const float ON_PROP_HEIGHT = 1.f; const float ON_TERRAIN_HEIGHT = 0.3f; K3DVector vPos = *m_pGameObj->GetPosition(); if( m_hCreaturehandle ) { SGameObject* pCreature = m_pGameObj->GetGameObject( m_hCreaturehandle ); if( pCreature ) vPos = *pCreature->GetPosition(); m_hCreaturehandle = 0; } // 이동할때만 바꾸3 if( abs(m_vPos.x - vPos.x) > EPSILON || abs(m_vPos.y - vPos.y) > EPSILON ) { m_vPos = vPos; m_pPrimitive->GetRootMat()->_41 = m_vPos.x; m_pPrimitive->GetRootMat()->_42 = m_vPos.y; float fXPos, fYPos; K3DBLENDEDBUMPVERTEX* pVertex = m_pVertex; bool bIsOnProp = false; WORD wTile = 0; for( int h = 0; h < SHADOW_SEGMENT_COUNT; h++ ) { for( int w = 0; w < SHADOW_SEGMENT_COUNT; w++ ) { fXPos = (-m_fWidthCenter ) + (w*m_fWidthLength); fYPos = m_fHeightCenter - (h*m_fHeightLength); //0,0 으로 땡겨 찍은 좌표 pVertex->position.x = fXPos; pVertex->position.y = fYPos; //월드로 변환된 좌표 bIsOnProp = m_pGameObj->GetHeight( fXPos + m_vPos.x , fYPos + m_vPos.y, pVertex->position.z, wTile ); pVertex->position.z += bIsOnProp ? ON_PROP_HEIGHT : ON_TERRAIN_HEIGHT; ++pVertex; } } m_vPos.z += bIsOnProp ? ON_PROP_HEIGHT : ON_TERRAIN_HEIGHT; } m_pPrimitive->SetVisibility( m_pGameObj->GetVisibility() ); m_pPrimitive->SetCenterPosition( K3DVector( m_vPos.x, m_vPos.y, m_vPos.z) ); for(int vit = 0; vit < nViewportCount; ++vit) { if( ppViewportList[vit]->GetAttributes() & KViewportObject::VIEWPORT_GAME ) { ppViewportList[0]->Register( m_pPrimitive, KRenderObject::RENDEREFX_NONE ); break; } } }