#include "stdafx.h" #include "kviewport.h" #include "KPrimitive.h" #include "KPrimitiveSprite.h" #include "KRenderObject.h" KViewportObject::KViewportObject( DWORD attr, bool bClearColorBuffer, bool bClearDepthBuffer ) { m_dwAttributes = attr; m_fogMode = K3DRenderDevice::FOGM_NONE; m_nFSAA = 0; m_fMipRange = .0f; m_fMipBias = .0f; m_bMipMode = true; m_pChildViewportObj = NULL; m_fSkyMaxHeight = 2000;//하늘 칼라 시작 점 m_fSkyMinHeight = 300 ;//하늘 칼라 끝 점 m_fSKyMidPercent = 0.5f; //m_bUseSpecular = true; //기본 설정 m_bUseViewPort = true; //뷰 포트 사용 여부 m_bUseWater = true; m_bRenderWater = false; m_vCameraCorrection = K3DVector(0, 0, 0); m_bClearColorBuf = bClearColorBuffer; m_bClearDepthBuf = bClearDepthBuffer; //m_nSpriteCount = 16384; //m_nAdditiveSpriteCount = 8192; //m_nFrontSpriteCount = 16384; //m_nFrontAdditiveSpriteCount = 8192; //m_nPrListIndex = 16384; //m_nPrAlphaIndex = 4096; //m_nPrAdditiveIndex = 4096; //m_nLightIndex = 64; m_fTerrainSpecularFactor = 0.75f; m_fSkinAmbientFactor = 1.0f; m_fSkinDiffuseFactor = 1.0f; m_fSkinSpecularFactor = 1.0f; m_fClipOffsetRatio = 0.0f; m_bSpeedTreeTransMode = true; m_fWaterHeight = 0.f; m_bInsideWater = false; m_bExistenceWaterHeight = false; m_dev = NULL; ClearRegisteredList(); } KViewportObject::~KViewportObject(void) { SAFE_DELETE( m_pChildViewportObj ); } void KViewportObject::SetUseViewPort( bool bUseViewPort ) { m_bUseViewPort = bUseViewPort; } // //void KViewportObject::GetUseViewPort() //{ // return m_bUseViewPort; //} void KViewportObject::SetUseWater( bool bUseWater ) { m_bUseWater = bUseWater; } void KViewportObject::SetUseSpecular( int nUseSpecular ) { m_nUseSpecular = nUseSpecular; } void KViewportObject::SetRenderWater( bool bRenderWater ) { m_bRenderWater = bRenderWater; } void KViewportObject::SetWaterHeight( bool bExistence, float fHeight ) { m_bExistenceWaterHeight = bExistence; m_fWaterHeight = fHeight; } void KViewportObject::SetInsideWater( bool bInside ) { m_bInsideWater = bInside; } void KViewportObject::Initilaize( K3DRenderDevice *dev, const KViewportStruct &viewarea, float nearClip, float farClip ) { m_dev = dev; memcpy( &m_viewport, viewarea, sizeof(m_viewport) ); m_viewx = viewarea.X; m_viewy = viewarea.Y; m_viewwidth = viewarea.Width; m_viewheight = viewarea.Height; m_fVertexAspect = dev->GetScreenVertexAspect(); m_fNearClip = nearClip; m_fFarClip = farClip; } void KViewportObject::SetViewArea( const KRect &viewarea ) { m_viewport.X = viewarea.left; m_viewport.Y = viewarea.top; m_viewport.Width = viewarea.right - viewarea.left; m_viewport.Height = viewarea.bottom - viewarea.top; m_viewx = m_viewport.X; m_viewy = m_viewport.Y; m_viewwidth = m_viewport.Width; m_viewheight = m_viewport.Height; if( m_dev ) { //m_fVertexAspect = (float) (m_viewport.Width / m_viewport.Height); m_fVertexAspect = m_dev->GetScreenVertexAspect(); } } void KViewportObject::Register( K3DPrimitive *pr, DWORD flag ) { } void KViewportObject::Register( KSpritePrimitive *spr, bool isFront ) { if ( spr->GetAdditiveRenderMode() ) { if ( isFront ) { assert( m_prFrontAdditiveSpriteList.size() < 500 && "인터페이스가 비정상 적으로 너무 많이 등록된다!!! 고쳐라" ); //++m_nFrontAdditiveSpriteCount; m_prFrontAdditiveSpriteList.push_back( spr ); spr->SetDepthOrder(spr->GetTransform()._43 - float(m_prFrontAdditiveSpriteList.size() / 100000.f) ); } else { assert( m_prAdditiveSpriteList.size() < 500 && "인터페이스가 비정상 적으로 너무 많이 등록된다!!! 고쳐라" ); //++m_nAdditiveSpriteCount; m_prAdditiveSpriteList.push_back( spr ); spr->SetDepthOrder(spr->GetTransform()._43 - float(m_prAdditiveSpriteList.size() / 100000.f) ); } } else { if ( isFront ) { assert( m_prFrontSpriteList.size() < 500 && "인터페이스가 비정상 적으로 너무 많이 등록된다!!! 고쳐라" ); //++m_nFrontSpriteCount; m_prFrontSpriteList.push_back( spr ); spr->SetDepthOrder(spr->GetTransform()._43 - float(m_prFrontSpriteList.size() / 100000.f) ); } else { // assert( m_prSpriteList.size() < 500 && "인터페이스가 비정상 적으로 너무 많이 등록된다!!! 고쳐라" ); //++m_nSpriteCount; m_prSpriteList.push_back( spr ); spr->SetDepthOrder(spr->GetTransform()._43 - float(m_prSpriteList.size() / 100000.f) ); } } } void KViewportObject::Register(KTilePrimitive* tpr) { m_prTileList.push_back(tpr); } void KViewportObject::Register( KBillboardPrimitive* pBillboard) { if ( pBillboard->GetAdditiveRenderMode() ) { m_prAdditiveBliiboardList.push_back( pBillboard ); } else { m_prBliiboardList.push_back( pBillboard ); } } void KViewportObject::RegisterWire( KWireUtilPrimitive *wpr ) { m_wprList.push_back( wpr ); } const K3DLight * KViewportObject::GetLight( int nIndex ) { if( nIndex >= 0 && m_pLightList.size() > nIndex ) { return m_pLightList[nIndex]; } return NULL; } void KViewportObject::SetCamera( const K3DCamera *cam ) { // 위험! - Copy constructor K3DCamera 가 필요 m_ViewCamera = *cam; //K3DMatrixMultiply(&m_MatView, &m_MatTrans, &m_MatRotate); m_vCamPos = cam->GetCamPos(); m_vTarPos = cam->GetTargetPos(); if(cam->IsCameraPerspectiveMode()) { if(cam->IsCoordinateRightHand()) { K3DMatrixLookAtRH(m_matView, m_vCamPos, m_vTarPos,cam->GetUpVector()); K3DMatrixPerspectiveFovRH( m_matProjection, cam->GetFOV(), GetVertexAspect(), GetNearClip(), GetFarClip() ); } else { K3DMatrixLookAtLH(m_matView, m_vCamPos, m_vTarPos,cam->GetUpVector()); K3DMatrixPerspectiveFovLH( m_matProjection, cam->GetFOV(), GetVertexAspect(), GetNearClip(), GetFarClip() ); } } else { if(cam->IsCoordinateRightHand()) { K3DMatrixLookAtRH(m_matView, m_vCamPos, m_vTarPos,cam->GetUpVector()); K3DMatrixOrthoRH( m_matProjection, cam->GetFOV()*GetVertexAspect(), cam->GetFOV(), GetNearClip(), GetFarClip() ); } else { K3DMatrixLookAtLH(m_matView, m_vCamPos, m_vTarPos,cam->GetUpVector()); K3DMatrixOrthoLH( m_matProjection, cam->GetFOV()*GetVertexAspect(), cam->GetFOV(), GetNearClip(), GetFarClip() ); } } K3DMatrixInverse( m_matInvView, m_matView ); //Speed Tree K3DMatrixMultiply(m_matBlendShader, m_matView, m_matProjection); // validate frustum GetCameraFrustum(0, 0, (float)m_viewwidth - 1, (float)m_viewheight -1, m_pFrustum); } K3DVector* KViewportObject::GetFrustum() { return m_pFrustum; } void KViewportObject::GetCameraSegmentView(float o_scrX, float o_scrY, K3DVector &nearPt, K3DVector &farPt) { K3DVector vtx; float sx, sy; if(m_ViewCamera.IsCameraPerspectiveMode()) { float scrX = ((o_scrX - 0)/(float)m_viewwidth*2.f - 1.f); float scrY = -((o_scrY - 0)/(float)m_viewheight*2.f - 1.f); sx = scrX*m_fNearClip*(float)tan(m_ViewCamera.GetFOV()*0.5f)*m_viewwidth/m_viewheight; sy = scrY*m_fNearClip*(float)tan(m_ViewCamera.GetFOV()*0.5f); vtx.x = sx; vtx.y = sy; if(m_ViewCamera.IsCoordinateRightHand()) vtx.z = -m_fNearClip; else vtx.z = m_fNearClip; K3DVectorTransform(nearPt, vtx, m_matInvView); sx = scrX*m_fFarClip*(float)tan(m_ViewCamera.GetFOV()*0.5f)*m_viewwidth/m_viewheight; sy = scrY*m_fFarClip*(float)tan(m_ViewCamera.GetFOV()*0.5f); vtx.x = sx; vtx.y = sy; if(m_ViewCamera.IsCoordinateRightHand()) vtx.z = -m_fFarClip; else vtx.z = m_fFarClip; K3DVectorTransform(farPt, vtx, m_matInvView); } else { float scrX = ((o_scrX - 0)/(float)m_viewwidth*2.f - 1.f); float scrY = -((o_scrY - 0)/(float)m_viewheight*2.f - 1.f); sx = scrX*m_ViewCamera.GetFOV()*0.5f*m_viewwidth/m_viewheight; sy = scrY*m_ViewCamera.GetFOV()*0.5f; vtx.x = sx; vtx.y = sy; if(m_ViewCamera.IsCoordinateRightHand()) vtx.z = -m_fNearClip; else vtx.z = m_fNearClip; K3DVectorTransform(nearPt, vtx, m_matInvView); sx = scrX*m_ViewCamera.GetFOV()*0.5f*m_viewwidth/m_viewheight; sy = scrY*m_ViewCamera.GetFOV()*0.5f; vtx.x = sx; vtx.y = sy; if(m_ViewCamera.IsCoordinateRightHand()) vtx.z = -m_fFarClip; else vtx.z = m_fFarClip; K3DVectorTransform(farPt, vtx, m_matInvView); } } void KViewportObject::GetCameraFrustum(float left, float top, float right, float bottom, K3DVector *cube) { //static int nX = 0; //static int nY = 0; int nX = ( int ) ( ( float ) ( right - left ) * m_fClipOffsetRatio * 0.5f ); int nY = ( int ) ( ( float ) ( bottom - top ) * m_fClipOffsetRatio * 0.5f ); if(m_ViewCamera.IsCoordinateRightHand()) { GetCameraSegmentView(left +nX, bottom-nY, cube[0], cube[3]); GetCameraSegmentView(right-nX, bottom-nY, cube[1], cube[2]); GetCameraSegmentView(left +nX, top +nY, cube[5], cube[6]); GetCameraSegmentView(right-nX, top +nY, cube[4], cube[7]); } else { GetCameraSegmentView(left +nX, bottom-nY, cube[3], cube[0]); GetCameraSegmentView(right-nX, bottom-nY, cube[2], cube[1]); GetCameraSegmentView(left +nX, top +nY, cube[6], cube[5]); GetCameraSegmentView(right-nX, top +nY, cube[7], cube[4]); } } void KViewportObject::SetClipOffsetRatio( float fRatio ) { m_fClipOffsetRatio = fRatio; } float KViewportObject::GetClipOffsetRatio() { return m_fClipOffsetRatio; } void KViewportObject::PickScreenPoint(const K3DVector &pos, int &x, int &y) { K3DVector res; K3DVectorTransform(res, pos, m_matView); K3DVectorTransform(res, res, m_matProjection); x = (int)(res.x*m_viewwidth/2 + m_viewwidth/2); y = (int)(-res.y*m_viewheight/2 + m_viewheight/2); } void KViewportObject::AddLight( const K3DLight *lit ) { //++m_nLightIndex; m_pLightList.push_back( lit ); } void KViewportObject::updateLight() { int i; for ( i=0 ;i<8 ; ++i ) { m_dev->SetLightEnable( i, false ); } for ( i=0 ;i<8 ; ++i ) { if ( i < m_pLightList.size() ) { m_dev->SetLight( i, m_pLightList[i] ); #ifndef _RAC m_dev->SetLightEnable( i, true ); #endif } } #ifdef _RAC if( m_pLightList.size() > 0 ) m_dev->SetLightEnable( 0, true ); #endif } void KViewportObject::ClearRegisteredList() { m_prListSky.clear(); m_prListCloud.clear(); m_prListLensFlare.clear(); m_prListWeather.clear(); // [sonador][2007.03.19] m_prListLightning.clear(); // [sonador][2007.04.12] /*m_prList.clear(); m_prVSList.clear(); m_prListSpecular.clear(); m_prVSListSpecular.clear(); m_prNoLightList.clear(); m_prNoFogList.clear(); m_prAlphaSpecularList.clear(); m_prVSAlphaSpecularList.clear(); m_prAlphaList.clear(); m_prVSAlphaList.clear(); m_prNoFogAlphaList.clear(); m_prAdditiveList.clear();*/ m_pLightList.clear(); m_prFrontSpriteList.clear(); m_prFrontAdditiveSpriteList.clear(); m_prSpriteList.clear(); m_prAdditiveSpriteList.clear(); m_prTileList.clear(); m_prListTerrain.clear(); m_prListTerrainShadow.clear(); /*m_prListBuilding.clear(); m_prListProp.clear(); //m_prListWater.clear(); //m_prListUVWrap.clear(); m_prListShadow.clear(); m_prListLightMap.clear();*/ /*m_prListAlphaBuilding.clear(); m_prListAdditiveBuilding.clear(); m_prListAlphaProp.clear(); m_prListAdditiveProp.clear(); m_prVSListProp.clear(); m_prVSListAlphaProp.clear(); m_prVSListAdditiveProp.clear();*/ m_prListBranch.clear(); m_prListFrond.clear(); m_prListLeaf.clear(); m_prListTreeBillboard.clear(); m_prListSpeedGrass.clear(); //m_prListPathEffect.clear(); m_prListQuad.clear(); m_prListLine.clear(); m_prListPolyLine.clear(); /*m_prListAlphaBranch.clear(); m_prListAlphaFrond.clear(); m_prListAlphaLeaf.clear();*/ m_nUsedMeshEXPool = 0; m_fDepth = -3.0000000e+038f; m_nAfterSpriteUsedMeshEXPool = 0; m_fAfterSpriteDepth = -3.0000000e+038f; /// m_prMesh.clear(); m_prTransMesh.clear(); m_prAfterSpriteMesh.clear(); m_prAfterSpriteTransMesh.clear(); /// m_prBliiboardList.clear(); m_prAdditiveBliiboardList.clear(); m_wprList.clear(); m_prSelectMesh.clear(); /*m_nPrListSpecularIndex = 0; m_nPrVSListSpecularIndex = 0; m_nPrListIndex = 0; m_nPrVSListIndex = 0; m_nPrNoLightListIndex = 0; m_nPrNoFogListIndex = 0; m_nPrAlphaSpecularIndex = 0; m_nPrVSAlphaSpecularIndex = 0; m_nPrAlphaIndex = 0; m_nPrVSAlphaIndex = 0; m_nPrNoFogAlphaIndex = 0; m_nPrAdditiveIndex = 0; m_nLightIndex = 0; m_nSpriteCount = 0; m_nAdditiveSpriteCount = 0; m_nFrontSpriteCount = 0; m_nFrontAdditiveSpriteCount = 0;*/ /* m_bInsideWater = false; m_fWaterHeight = 0.f; m_bExistenceWaterHeight = false;*/ } void KViewportObject::Render( K3DRenderTarget *pRT, DWORD flag, bool bClearRegister ) { KViewportStruct backview = m_viewport; m_dev->BeginScene(); m_dev->SetRenderTarget( pRT ); m_viewport.X = m_viewport.Y = 0; m_viewport.Width = pRT->GetWidth(); m_viewport.Height = pRT->GetHeight(); Render( bClearRegister ); m_dev->SetRenderTarget( NULL ); m_dev->EndScene(); m_viewport = backview; } #include "KRenderDeviceDX.h" void KViewportObject::Render( bool bClearRegister /* = true */, bool bSetRenderTarget /*= true*/ ) { if ( m_bClearDepthBuf || m_bClearColorBuf ) { int option = 0; option |= m_bClearColorBuf ? K3DRenderDevice::FILL_COLOR : 0; option |= m_bClearDepthBuf ? K3DRenderDevice::FILL_DEPTH : 0; m_dev->SetFillColor( m_colFill ); m_dev->Fill( option ); } renderDefault(); if ( bClearRegister ) ClearRegisteredList(); } namespace { struct DepthCompareFN { static K3DVector vCamPos; bool operator() ( K3DPrimitive *pr1, K3DPrimitive *pr2 ) { return ( vCamPos - pr1->GetTransform()->GetPosVector() ).SquareMagnitude() > ( vCamPos - pr2->GetTransform()->GetPosVector() ).SquareMagnitude(); } bool operator() ( KBillboardPrimitive *pr1, KBillboardPrimitive *pr2 ) { return pr1->GetDistance( vCamPos ) > pr2->GetDistance( vCamPos ); } }; struct CenterCompareFN { static K3DVector vCamPos; bool operator() ( K3DPrimitive *pr1, K3DPrimitive *pr2 ) { return ( vCamPos - pr1->GetCenterPosition() ).SquareMagnitude() > ( vCamPos - pr2->GetCenterPosition() ).SquareMagnitude(); } }; K3DVector DepthCompareFN::vCamPos; K3DVector CenterCompareFN::vCamPos; } void KViewportObject::sortCenter( K3DPrimitive** prList, int nPrCount ) { CenterCompareFN::vCamPos = m_vCamPos; std::sort( &prList[0], &prList[nPrCount], CenterCompareFN() ); } void KViewportObject::sortDepth( K3DPrimitive** prList, int nPrCount ) { DepthCompareFN::vCamPos = m_vCamPos; std::sort( &prList[0], &prList[nPrCount], DepthCompareFN() ); } void KViewportObject::sortDepth( KBillboardPrimitive** prList, int nPrCount ) { DepthCompareFN::vCamPos = m_vCamPos; std::sort( &prList[0], &prList[nPrCount], DepthCompareFN() ); } void KViewportObject::renderDefault() { } namespace { struct spriteCompareFN { bool operator() ( KSpritePrimitive *pr1, KSpritePrimitive *pr2 ) { return pr1->GetDepthOrder() > pr2->GetDepthOrder(); } }; } HRESULT KViewportObject::TestCooperativeLevel() { return m_dev->TestCooperativeLevel(); } void KViewportObject::drawSprite( KSpritePrimitive** prSpriteList, int nSpriteCount ) { // z 축으로 sort std::sort( &prSpriteList[0], &prSpriteList[nSpriteCount], spriteCompareFN() ); for(int i = 0; i < nSpriteCount; ++i) { prSpriteList[i]->Render(this,m_dev); } } //2D -> 3D void KViewportObject::Get2DVto3DV( const K3DVector & v2D, K3DVector & v3D ) { K3DMatrix wlmat; K3DMatrixIdentity( wlmat ); K3DVectorUnproject( v3D, v2D, *GetViewportStruct(), *GetProjMatrix(), *GetViewMatrix(), wlmat ); //3D 좌표가 나온다 } //3D -> 2D void KViewportObject::Get3DVto2DV( const K3DVector & v3D, K3DVector & v2D ) { K3DMatrix wlmat; K3DMatrixIdentity( wlmat ); K3DVectorProject( v2D, v3D, *GetViewportStruct(), *GetProjMatrix(), *GetViewMatrix(), wlmat ); //2D 좌표가 나온다 } #ifdef _KUI_INVALIDATION // { [sonador] void KViewportObject::RearrangeSpriteOffset( const K3DVector& vOffset ) { if ( m_prSpriteList.size() > 0 || m_prAdditiveSpriteList.size() > 0 || m_prFrontSpriteList.size() > 0 || m_prFrontAdditiveSpriteList.size() > 0 ) { if ( m_prSpriteList.size() > 0 ) { for( int index = 0; index < m_prSpriteList.size(); ++index ) m_prSpriteList[ index ]->SetRenderOffset( vOffset ); } if ( m_prAdditiveSpriteList.size() > 0 ) { for( int index = 0; index < m_prAdditiveSpriteList.size(); ++index ) m_prAdditiveSpriteList[ index ]->SetRenderOffset( vOffset ); } if ( m_prFrontSpriteList.size() > 0 ) { for( int index = 0; index < m_prFrontSpriteList.size(); ++index ) m_prFrontSpriteList[ index ]->SetRenderOffset( vOffset ); } if ( m_prFrontAdditiveSpriteList.size() > 0 ) { for( int index = 0; index < m_prFrontAdditiveSpriteList.size(); ++index ) m_prFrontAdditiveSpriteList[ index ]->SetRenderOffset( vOffset ); } } } // } #endif