Files
Leviathan/Client/Game/engine/Renderer/KViewport.cpp
T
2026-06-01 12:46:52 +02:00

649 lines
16 KiB
C++

#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