618 lines
23 KiB
C++
618 lines
23 KiB
C++
|
|
#include "stdafx.h"
|
|
#include "KViewport.h"
|
|
#include "KPrimitiveSpeedTree.h"
|
|
#include "KSeqSpeedTree.h"
|
|
#include <SpeedTreeRT/SpeedTreeRT.h>
|
|
#include "SSpeedTreeConfig.h"
|
|
#include "SSpeedTreeVertexShaders.h"
|
|
#include "KRenderDeviceDX.h"
|
|
|
|
#include <dump/XException.h>
|
|
|
|
namespace {
|
|
const DWORD SPEEDTREE_BRANCHALPHATEST=0;
|
|
const DWORD SPEEDTREE_FRONDALPHATEST=96;
|
|
const DWORD SPEEDTREE_LEAFALPHATEST=64;
|
|
const DWORD SPEEDTREE_BILLBOARDALPHATEST=32;
|
|
|
|
bool SPEEDTREEPRIMITIVE_TRANSPARENTRENDERMODE=false;
|
|
}
|
|
|
|
SSpeedTreePrimitive::SSpeedTreePrimitive()
|
|
: m_nSubCount(0), m_nTexCount(0), m_nTexActiveCount(0), m_ppVB(NULL), m_ppIB(NULL), m_ppTex(NULL), m_ppMtl(NULL), m_nRenderState(0)
|
|
{
|
|
m_type = KPRIMITIVE_SSPEEDTREE;
|
|
|
|
m_registerTable = 0;
|
|
m_cntTable = 0;
|
|
m_pTable = NULL;
|
|
|
|
m_bIsValid = true;
|
|
|
|
m_registerVecConstant = 0;
|
|
m_cntVecConstant = 0;
|
|
m_pvecConstant = NULL;
|
|
|
|
m_registerUsefulConstants = 0;
|
|
m_cntUsefulConstants = 0;
|
|
m_pafUsefulConstants = NULL;
|
|
|
|
m_registerMaterial = 0;
|
|
m_cntMaterial = 0;
|
|
m_pafMaterial = NULL;
|
|
|
|
m_pGeometryCache = NULL;
|
|
m_pSpeedTree = NULL;
|
|
m_nType = -1;
|
|
|
|
m_pBranchIndexCounts = NULL;
|
|
m_pFrondIndexCounts = NULL;
|
|
m_bLeavesUpdatedByCpu = false;
|
|
}
|
|
|
|
SSpeedTreePrimitive::~SSpeedTreePrimitive()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
void SSpeedTreePrimitive::Clear()
|
|
{
|
|
SAFE_DELETE_ARRAY( m_ppVB );
|
|
SAFE_DELETE_ARRAY( m_ppIB );
|
|
SAFE_DELETE_ARRAY( m_ppTex );
|
|
SAFE_DELETE_ARRAY( m_ppMtl );
|
|
}
|
|
|
|
void SSpeedTreePrimitive::SetSubMeshCount( int count )
|
|
{
|
|
if( count == 0 )
|
|
{
|
|
// _oprint( "SpeedTree Mesh Count Invalid!!!\n" );
|
|
return;
|
|
}
|
|
|
|
Clear();
|
|
m_ppIB = new K3DIndexBuffer*[count];
|
|
memset( m_ppIB, 0, sizeof(K3DIndexBuffer*)*count );
|
|
m_ppVB = new K3DVertexBuffer*[count];
|
|
m_ppMtl = new K3DMaterial*[count];
|
|
for( int i(0); count>i; i++ )
|
|
{
|
|
m_ppVB[i] = NULL;
|
|
m_ppMtl[i] = NULL;
|
|
}
|
|
|
|
m_nSubCount = count;
|
|
}
|
|
|
|
void SSpeedTreePrimitive::SetTextureCount( int count )
|
|
{
|
|
m_ppTex = new K3DTexture*[count];
|
|
m_nTexCount = count;
|
|
}
|
|
|
|
namespace {
|
|
void SetShaderConstants(K3DRenderDevice *dev, const float* pMaterial, float leaflightingadj, float opacity=1.0f)
|
|
{
|
|
//
|
|
// Lighting direction에 의해 감소되는 광량이 leaflightingadj이하로 내려가지 않게 vertex shader에서 계산함
|
|
//
|
|
const float afUsefulConstants[] =
|
|
{
|
|
leaflightingadj, 0.0f, 0.0f, 0.0f
|
|
};
|
|
dev->SetVertexShaderConstant(c_nVertexShader_LeafLightingAdjustment, afUsefulConstants, 1);
|
|
|
|
|
|
//
|
|
// Vertex color rgba
|
|
//
|
|
const float afMaterial[] =
|
|
{ //Modulate 2X
|
|
// pMaterial[0]/2.f, pMaterial[1]/2.f, pMaterial[2]/2.f, opacity, // 1.0f,
|
|
// pMaterial[3]/2.f, pMaterial[4]/2.f, pMaterial[5]/2.f, opacity // 1.0f
|
|
|
|
pMaterial[0], pMaterial[1], pMaterial[2], opacity, // 1.0f,
|
|
pMaterial[3], pMaterial[4], pMaterial[5], opacity // 1.0f
|
|
};
|
|
|
|
//m_prBranch.SetShaderMaterial( c_nVertexShader_Material, m_afMaterial, 2 );
|
|
//m_prFrond.SetShaderMaterial ( c_nVertexShader_Material, m_afMaterial, 2 );
|
|
//m_prLeaf.SetShaderMaterial ( c_nVertexShader_Material, m_afMaterial, 2 );
|
|
dev->SetVertexShaderConstant(c_nVertexShader_Material, afMaterial, 2); // Vertex shader에 직접 넘김
|
|
}
|
|
};
|
|
|
|
|
|
void SSpeedTreePrimitive::setTransparentRenderMode(bool bTransparent)
|
|
{
|
|
SPEEDTREEPRIMITIVE_TRANSPARENTRENDERMODE=bTransparent;
|
|
}
|
|
|
|
bool SSpeedTreePrimitive::getTransparentRenderMode()
|
|
{
|
|
return SPEEDTREEPRIMITIVE_TRANSPARENTRENDERMODE;
|
|
}
|
|
|
|
|
|
void SSpeedTreePrimitive::Render( KViewportObject *viewport, class K3DRenderDevice *dev, bool bUseAccum )
|
|
{
|
|
if( m_nType == -1 ) return;
|
|
if(!IsValid()) return;
|
|
|
|
//if( m_ppVB[0] == NULL ) return;
|
|
//if( m_nType != TREE_BILLBOARD && ( m_ppVB[0] == NULL )) return; // ??
|
|
|
|
K3DMatrix world;
|
|
K3DMatrixIdentity( world );
|
|
K3DMatrixMultiply( world, *m_pTransform, m_RootMat );
|
|
K3DVector posvec;
|
|
K3DMatrixGetPosVector( posvec, world );
|
|
K3DMatrixIdentity( world );
|
|
world.SetPosVector( posvec );
|
|
dev->SetTransform( K3DRenderDevice::TS_WORLD, &world );
|
|
D3DXVECTOR4 vecConstant = D3DXVECTOR4( posvec.x, posvec.y, posvec.z, 0.0f);
|
|
SetShaderVecConstant( c_nVertexShader_TreePos, ( float* ) &vecConstant, 1 );
|
|
|
|
if( m_pvecConstant )
|
|
dev->SetVertexShaderConstant( m_registerVecConstant , m_pvecConstant , m_cntVecConstant );
|
|
//dev->SetVertexShaderConstant( c_nVertexShader_TreePos, ( float* ) &vecConstant, 1 );
|
|
/*if( m_pafUsefulConstants )
|
|
dev->SetVertexShaderConstant( m_registerUsefulConstants, m_pafUsefulConstants, m_cntUsefulConstants );
|
|
if( m_pafMaterial )
|
|
dev->SetVertexShaderConstant( m_registerMaterial , m_pafMaterial , m_cntMaterial );*/
|
|
if( m_pTable && m_nType == TREE_LEAF )
|
|
dev->SetVertexShaderConstant( m_registerTable , m_pTable , m_cntTable );
|
|
|
|
|
|
//
|
|
// 바람 효과 계산 (Vertex shader사용 안할 경우만)
|
|
//
|
|
if( m_nType == TREE_BRANCH )
|
|
{
|
|
#ifdef WRAPPER_USE_CPU_WIND
|
|
// ?? m_pSpeedTree->GetGeometry(*m_pGeometryCache, SpeedTree_BranchGeometry);
|
|
|
|
if (m_pGeometryCache->m_sBranches.m_usNumStrips > 0)
|
|
{
|
|
// update the vertex array
|
|
SFVFBranchVertex* pVertexBuffer = NULL;
|
|
int nVtxSize = 0;
|
|
m_ppVB[0]->Lock( reinterpret_cast<void**>(&pVertexBuffer), nVtxSize );
|
|
assert(pVertexBuffer && "m_ppVB[0]->Lock( reinterpret_cast<void**>(&pVertexBuffer), nVtxSize );");
|
|
|
|
for (unsigned int i = 0; i < m_unVertexCount; ++i)
|
|
{
|
|
memcpy(&(pVertexBuffer[i].m_vPosition), &(m_pGeometryCache->m_sBranches.m_pCoords[i * 3]), sizeof(pVertexBuffer[i].m_vPosition));
|
|
}
|
|
|
|
m_ppVB[0]->Unlock( );
|
|
}
|
|
#endif
|
|
}
|
|
else if( m_nType == TREE_FROND )
|
|
{
|
|
#ifdef WRAPPER_USE_CPU_WIND
|
|
// update the frond geometry for CPU wind
|
|
m_pSpeedTree->GetGeometry(*m_pGeometryCache, SpeedTree_FrondGeometry);
|
|
|
|
if (m_pGeometryCache->m_sFronds.m_usNumStrips > 0)
|
|
{
|
|
// update the vertex array
|
|
SFVFBranchVertex* pVertexBuffer = NULL;
|
|
int nVtxSize = 0;
|
|
m_ppVB[0]->Lock(reinterpret_cast<void**>(&pVertexBuffer), nVtxSize);
|
|
assert(pVertexBuffer && "m_ppVB[0]->Lock(reinterpret_cast<void**>(&pVertexBuffer), nVtxSize);");
|
|
|
|
for (unsigned int i = 0; i < m_unVertexCount; ++i)
|
|
{
|
|
memcpy(&(pVertexBuffer[i].m_vPosition), &(m_pGeometryCache->m_sFronds.m_pCoords[i * 3]), sizeof(pVertexBuffer[i].m_vPosition));
|
|
}
|
|
|
|
m_ppVB[0]->Unlock( );
|
|
}
|
|
#endif
|
|
}
|
|
else if( m_nType == TREE_LEAF )
|
|
{
|
|
#ifdef WRAPPER_USE_GPU_LEAF_PLACEMENT
|
|
m_pSpeedTree->GetGeometry(*m_pGeometryCache, SpeedTree_LeafGeometry, -1, -1, 0);
|
|
#endif
|
|
m_pSpeedTree->GetGeometry(*m_pGeometryCache, SpeedTree_LeafGeometry);
|
|
|
|
// update the LOD level vertex arrays we need
|
|
#if defined(WRAPPER_USE_GPU_LEAF_PLACEMENT) && defined(WRAPPER_USE_GPU_WIND)
|
|
// do nothing
|
|
#else
|
|
#if !defined WRAPPER_USE_NO_WIND || defined WRAPPER_USE_CPU_LEAF_PLACEMENT
|
|
// might need to draw 2 LOD's
|
|
for (unsigned int i = 0; i < 2; ++i)
|
|
{
|
|
// reference to leaves structure
|
|
const CSpeedTreeRT::SGeometry::SLeaf* pLeaf = (i == 0) ? &m_pGeometryCache->m_sLeaves0 : &m_pGeometryCache->m_sLeaves1;
|
|
int unLod = pLeaf->m_nDiscreteLodLevel;
|
|
|
|
#if defined WRAPPER_USE_GPU_LEAF_PLACEMENT
|
|
//if (pLeaf->m_bIsActive && !m_bLeavesUpdatedByCpu)
|
|
if (pLeaf->m_bIsActive && pLeaf->m_usLeafCount > 0 && !m_bLeavesUpdatedByCpu)
|
|
{
|
|
// update the centers
|
|
SFVFLeafVertex* pVertex = NULL;
|
|
int nVtxSize = 0;
|
|
|
|
// ??
|
|
m_ppVB[unLod]->Lock(reinterpret_cast<void**>(&pVertex), nVtxSize);
|
|
assert(pVertex && "m_ppVB[unLod]->Lock(reinterpret_cast<void**>(&pVertex), nVtxSize);");
|
|
|
|
for (unsigned int unLeaf = 0; unLeaf < pLeaf->m_usLeafCount; ++unLeaf)
|
|
{
|
|
D3DXVECTOR3 vecCenter(&(pLeaf->m_pCenterCoords[unLeaf * 3]));
|
|
(pVertex++)->m_vPosition = vecCenter; // vertex 0
|
|
(pVertex++)->m_vPosition = vecCenter; // vertex 1
|
|
(pVertex++)->m_vPosition = vecCenter; // vertex 2
|
|
(pVertex++)->m_vPosition = vecCenter; // vertex 0
|
|
(pVertex++)->m_vPosition = vecCenter; // vertex 2
|
|
(pVertex++)->m_vPosition = vecCenter; // vertex 3
|
|
}
|
|
|
|
m_ppVB[unLod]->Unlock( );
|
|
|
|
m_bLeavesUpdatedByCpu = true;
|
|
}
|
|
#else
|
|
//if (pLeaf->m_bIsActive)
|
|
if (pLeaf->m_bIsActive && pLeaf->m_usLeafCount > 0)
|
|
{
|
|
// update the vertices
|
|
SFVFLeafVertex* pVertex = NULL;
|
|
int nVtxSize = 0;
|
|
m_ppVB[unLod]->Lock(reinterpret_cast<void**>(&pVertex),nVtxSize);
|
|
assert(pVertex && "m_ppVB[unLod]->Lock(reinterpret_cast<void**>(&pVertex),nVtxSize);");
|
|
|
|
for (unsigned int unLeaf = 0; unLeaf < pLeaf->m_usLeafCount; ++unLeaf)
|
|
{
|
|
D3DXVECTOR3 vecCenter(&(pLeaf->m_pCenterCoords[unLeaf * 3]));
|
|
D3DXVECTOR3 vec0(&pLeaf->m_pLeafMapCoords[unLeaf][0]);
|
|
D3DXVECTOR3 vec1(&pLeaf->m_pLeafMapCoords[unLeaf][4]);
|
|
D3DXVECTOR3 vec2(&pLeaf->m_pLeafMapCoords[unLeaf][8]);
|
|
D3DXVECTOR3 vec3(&pLeaf->m_pLeafMapCoords[unLeaf][12]);
|
|
|
|
(pVertex++)->m_vPosition = vecCenter + vec0; // vertex 0
|
|
(pVertex++)->m_vPosition = vecCenter + vec1; // vertex 1
|
|
(pVertex++)->m_vPosition = vecCenter + vec2; // vertex 2
|
|
(pVertex++)->m_vPosition = vecCenter + vec0; // vertex 0
|
|
(pVertex++)->m_vPosition = vecCenter + vec2; // vertex 2
|
|
(pVertex++)->m_vPosition = vecCenter + vec3; // vertex 3
|
|
}
|
|
|
|
m_ppVB[unLod]->Unlock( );
|
|
}
|
|
#endif // #if defined WRAPPER_USE_GPU_LEAF_PLACEMENT
|
|
}
|
|
#endif // #if !defined WRAPPER_USE_NO_WIND || defined WRAPPER_USE_CPU_LEAF_PLACEMENT
|
|
#endif // #if defined(WRAPPER_USE_GPU_LEAF_PLACEMENT) && defined(WRAPPER_USE_GPU_WIND)
|
|
}
|
|
else if(m_nType == TREE_BILLBOARD)
|
|
{
|
|
//m_pSpeedTree->GetGeometry(*m_pGeometryCache, SpeedTree_BillboardGeometry);
|
|
}
|
|
|
|
|
|
//
|
|
// 텍스처 설정 / fog설정
|
|
// Note : vertex 돌아가는 방향 설정 (CW/CCW)이 caller가 아니라 여기 어디쯤 있어야 맞는게 아닐까? (flag로 연속 XOR?)
|
|
//
|
|
for ( int j=0 ; j<m_nTexActiveCount ; ++j )
|
|
dev->SetTexture( j, m_ppTex[j] );
|
|
|
|
float fFogStart, fFogEnd;
|
|
((K3DRenderDeviceDX*) dev)->GetD3DDevice()->GetRenderState(D3DRS_FOGSTART, (DWORD*)&fFogStart);
|
|
((K3DRenderDeviceDX*) dev)->GetD3DDevice()->GetRenderState(D3DRS_FOGEND, (DWORD*)&fFogEnd);
|
|
|
|
|
|
//
|
|
// 폴리곤 draw
|
|
//
|
|
for ( int j=0 ; j<m_nSubCount ; ++j )
|
|
{
|
|
if( m_ppMtl[0] )
|
|
{
|
|
m_ppMtl[0]->SetTransparency( m_fVisibility );
|
|
|
|
//dev->SetMaterial( m_ppMtl[0] );
|
|
//CSpeedTreeMaterial mtl;
|
|
//mtl.Set(m_pSpeedTree->GetBranchMaterial());
|
|
//dev->SetMaterial( mtl.m_cMaterial );
|
|
}
|
|
if( m_nType == TREE_BRANCH && m_ppIB[0] != NULL )
|
|
{
|
|
m_pSpeedTree->GetGeometry(*m_pGeometryCache, SpeedTree_BranchGeometry); // ??
|
|
|
|
if (m_pGeometryCache->m_fBranchAlphaTestValue > 0.0f)
|
|
{
|
|
if (m_pBranchIndexCounts && m_pGeometryCache->m_sBranches.m_nDiscreteLodLevel > -1 && m_pBranchIndexCounts[m_pGeometryCache->m_sBranches.m_nDiscreteLodLevel] > 0)
|
|
{
|
|
const K3DLight * pLight = viewport->GetLight(m_nLightIndex);
|
|
|
|
CSpeedTreeMaterial mtl;
|
|
mtl.Set(m_pSpeedTree->GetBranchMaterial());
|
|
//mtl.SetLight( pLight );
|
|
dev->SetMaterial( mtl.GetMaterial() );
|
|
|
|
SetShaderConstants(dev, m_pSpeedTree->GetBranchMaterial(), m_pSpeedTree->GetLeafLightingAdjustment(), m_fVisibility);
|
|
|
|
#ifndef _RAC //TOOL
|
|
dev->SetAlpharef(0x00000000/*DWORD(m_pGeometryCache->m_fBranchAlphaTestValue)*/); // ??
|
|
#else
|
|
if (SPEEDTREEPRIMITIVE_TRANSPARENTRENDERMODE)
|
|
dev->SetAlpharef(SPEEDTREE_BRANCHALPHATEST);
|
|
else
|
|
dev->SetAlpharef(SPEEDTREE_BRANCHALPHATEST/*DWORD(m_pGeometryCache->m_fBranchAlphaTestValue)*/);
|
|
#endif
|
|
|
|
//나무 몸통 그리는곳 문제가 생길것 같아서 수정
|
|
//vb, ib 0번만 적용 하게 수정
|
|
//폴리곤이 생성될때 1개씩만 만들어 진다.
|
|
//2009-12-23 : hunee
|
|
dev->DrawIndexedTriangleStripVB( m_ppVB[0], m_ppIB[0], m_pGeometryCache->m_sBranches.m_usVertexCount, m_pBranchIndexCounts[m_pGeometryCache->m_sBranches.m_nDiscreteLodLevel] - 2 );
|
|
}
|
|
}
|
|
}
|
|
else if( m_nType == TREE_FROND && m_ppIB[0] != NULL )
|
|
{
|
|
m_pSpeedTree->GetGeometry(*m_pGeometryCache, SpeedTree_FrondGeometry); // ??
|
|
|
|
if (m_pGeometryCache->m_fFrondAlphaTestValue > 0.0f)
|
|
{
|
|
if (m_pFrondIndexCounts && m_pGeometryCache->m_sFronds.m_nDiscreteLodLevel > -1 && m_pFrondIndexCounts[m_pGeometryCache->m_sFronds.m_nDiscreteLodLevel] > 0)
|
|
{
|
|
const K3DLight * pLight = viewport->GetLight(m_nLightIndex);
|
|
|
|
CSpeedTreeMaterial mtl;
|
|
mtl.Set(m_pSpeedTree->GetFrondMaterial());
|
|
//mtl.SetLight( pLight );
|
|
dev->SetMaterial( mtl.GetMaterial() );
|
|
|
|
SetShaderConstants(dev, m_pSpeedTree->GetFrondMaterial(), m_pSpeedTree->GetLeafLightingAdjustment(), m_fVisibility);
|
|
|
|
#ifndef _RAC //TOOL
|
|
dev->SetAlpharef( 0x00000000/*DWORD(m_pGeometryCache->m_fFrondAlphaTestValue)*/ );
|
|
#else
|
|
if (SPEEDTREEPRIMITIVE_TRANSPARENTRENDERMODE)
|
|
dev->SetAlpharef(SPEEDTREE_FRONDALPHATEST);
|
|
else
|
|
dev->SetAlpharef( DWORD(m_pGeometryCache->m_fFrondAlphaTestValue) );
|
|
#endif
|
|
|
|
//dev->DrawIndexedTriangleStripVB( m_ppVB[j], m_ppIB[j], m_pGeometryCache->m_sFronds.m_usVertexCount, m_pFrondIndexCounts[m_pGeometryCache->m_sFronds.m_nDiscreteLodLevel] - 2 );
|
|
dev->DrawIndexedTriangleStripVB( m_ppVB[0], m_ppIB[m_pGeometryCache->m_sFronds.m_nDiscreteLodLevel], m_pGeometryCache->m_sFronds.m_usVertexCount, m_pFrondIndexCounts[m_pGeometryCache->m_sFronds.m_nDiscreteLodLevel] - 2 );
|
|
}
|
|
}
|
|
}
|
|
else if( m_nType == TREE_LEAF )
|
|
{
|
|
// might need to draw 2 LOD's
|
|
for (unsigned int unLeafLevel = 0; unLeafLevel < 2; ++unLeafLevel)
|
|
{
|
|
const CSpeedTreeRT::SGeometry::SLeaf* pLeaf = (unLeafLevel == 0) ?
|
|
&m_pGeometryCache->m_sLeaves0 : pLeaf = &m_pGeometryCache->m_sLeaves1;
|
|
|
|
//
|
|
int unLod = pLeaf->m_nDiscreteLodLevel;
|
|
|
|
// if this LOD is active and has leaves, draw it
|
|
if (unLod > -1 && pLeaf->m_bIsActive && pLeaf->m_usLeafCount > 0)
|
|
{
|
|
const K3DLight * pLight = viewport->GetLight(m_nLightIndex);
|
|
|
|
CSpeedTreeMaterial mtl;
|
|
mtl.Set(m_pSpeedTree->GetLeafMaterial());
|
|
//mtl.SetLight( pLight );
|
|
dev->SetMaterial( mtl.GetMaterial() );
|
|
|
|
//dev->SetRenderState( K3DRenderDevice::RS_SPEED_TREE );
|
|
//dev->SetCullMode( K3DRenderDevice::KCM_CCW );
|
|
|
|
#ifndef _RAC //TOOL
|
|
SetShaderConstants(dev, m_pSpeedTree->GetLeafMaterial(), m_pSpeedTree->GetLeafLightingAdjustment());
|
|
dev->SetAlpharef( DWORD(pLeaf->m_fAlphaTestValue) );
|
|
#else
|
|
if (SPEEDTREEPRIMITIVE_TRANSPARENTRENDERMODE) {
|
|
SetShaderConstants(dev, m_pSpeedTree->GetLeafMaterial(), m_pSpeedTree->GetLeafLightingAdjustment(), m_fVisibility);
|
|
dev->SetAlpharef(SPEEDTREE_LEAFALPHATEST);
|
|
} else
|
|
{
|
|
SetShaderConstants(dev, m_pSpeedTree->GetLeafMaterial(), m_pSpeedTree->GetLeafLightingAdjustment());
|
|
dev->SetAlpharef( DWORD(pLeaf->m_fAlphaTestValue) );
|
|
}
|
|
#endif
|
|
|
|
//dev->DrawTriangleVB( m_ppVB[unLod], pLeaf->m_usLeafCount * 2 );
|
|
dev->DrawTriangleVB( m_ppVB[unLod], pLeaf->m_usLeafCount * 6 );
|
|
}
|
|
}
|
|
m_bLeavesUpdatedByCpu = false;
|
|
return; // <- 여기 왜 있는것일까??
|
|
}
|
|
else if( m_nType == TREE_BILLBOARD )
|
|
{
|
|
//if (m_pGeometryCache->m_fBranchAlphaTestValue > 0.0f)
|
|
{
|
|
//if (m_pBranchIndexCounts && m_pGeometryCache->m_sBranches.m_nDiscreteLodLevel > -1 && m_pBranchIndexCounts[m_pGeometryCache->m_sBranches.m_nDiscreteLodLevel] > 0)
|
|
{
|
|
//CSpeedTreeMaterial mtl;
|
|
//memset(&mtl, 0, sizeof(mtl)); // ??
|
|
//mtl.Set(m_pSpeedTree->GetBranchMaterial());
|
|
//dev->SetMaterial( mtl.GetMaterial() );
|
|
//SetShaderConstants(dev, m_pSpeedTree->GetBranchMaterial(), m_pSpeedTree->GetLeafLightingAdjustment());
|
|
|
|
//dev->SetAlpharef( 0/*DWORD(m_pGeometryCache->m_fBranchAlphaTestValue)*/ );
|
|
|
|
//dev->DrawIndexedTriangleStripVB( m_ppVB[j], m_ppIB[j], m_pGeometryCache->m_sBranches.m_usVertexCount, m_pBranchIndexCounts[m_pGeometryCache->m_sBranches.m_nDiscreteLodLevel] - 2 );
|
|
|
|
// draw billboards in immediate mode (as close as directx gets to immediate mode)
|
|
//#ifdef WRAPPER_BILLBOARD_MODE
|
|
//PositionTree( );
|
|
|
|
// sonador #2.1.7.1 스피드 트리 퍼포먼스 증가
|
|
struct SBillboardVertex
|
|
{
|
|
float fX, fY, fZ;
|
|
float fNX, fNY, fNZ;
|
|
//DWORD color;
|
|
float fU, fV;
|
|
};
|
|
|
|
m_pSpeedTree->GetGeometry(*m_pGeometryCache, SpeedTree_BillboardGeometry);
|
|
|
|
//dev->SetCullMode(K3DRenderDevice::KCM_CCW);
|
|
//dev->SetCullMode(K3DRenderDevice::KCM_CW);
|
|
//dev->SetCullMode(K3DRenderDevice::KCM_NONE);
|
|
//dev->EnableLightEffect(true);
|
|
|
|
const K3DLight * pLight = viewport->GetLight(m_nLightIndex);
|
|
|
|
// ?? ->
|
|
CSpeedTreeMaterial mtl;
|
|
mtl.Set(m_pSpeedTree->GetLeafMaterial());
|
|
//mtl.SetLight(pLight);
|
|
dev->SetMaterial( mtl.GetMaterial() );
|
|
SetShaderConstants(dev, m_pSpeedTree->GetLeafMaterial(), m_pSpeedTree->GetLeafLightingAdjustment());
|
|
// <- ??
|
|
|
|
// ?? ->
|
|
//IDirect3DDevice9* pD3dDev = ((K3DRenderDeviceDX*) dev)->GetD3DDevice();
|
|
//pD3dDev->SetRenderState(D3DRS_FOGENABLE, FALSE);
|
|
//float f = fFogEnd/3.0f;
|
|
//pD3dDev->SetRenderState(D3DRS_FOGSTART, *(DWORD*)(&f));
|
|
|
|
// <- ??
|
|
|
|
if (m_pGeometryCache->m_sBillboard0.m_bIsActive)
|
|
{
|
|
const float* pCoords = m_pGeometryCache->m_sBillboard0.m_pCoords;
|
|
const float* pTexCoords = m_pGeometryCache->m_sBillboard0.m_pTexCoords;
|
|
|
|
K3DVector view = -pLight->direction;
|
|
|
|
SBillboardVertex sVertex[4] =
|
|
{
|
|
{ pCoords[0], pCoords[1], pCoords[2], /*0xffffffff*/view.x, view.y, view.z, pTexCoords[2], pTexCoords[3] },
|
|
{ pCoords[3], pCoords[4], pCoords[5], /*0xffffffff*/view.x, view.y, view.z, pTexCoords[0], pTexCoords[1] },
|
|
{ pCoords[6], pCoords[7], pCoords[8], /*0xffffffff*/view.x, view.y, view.z, pTexCoords[6], pTexCoords[7] },
|
|
{ pCoords[9], pCoords[10], pCoords[11], /*0xffffffff*/view.x, view.y, view.z, pTexCoords[4], pTexCoords[5] },
|
|
|
|
/*{ pCoords[0], pCoords[1], pCoords[2], 0xffffff, pTexCoords[0], pTexCoords[1] },
|
|
{ pCoords[3], pCoords[4], pCoords[5], 0xffffff, pTexCoords[2], pTexCoords[3] },
|
|
{ pCoords[6], pCoords[7], pCoords[8], 0xffffff, pTexCoords[4], pTexCoords[5] },
|
|
{ pCoords[9], pCoords[10], pCoords[11], 0xffffff, pTexCoords[6], pTexCoords[7] },
|
|
|
|
{ pCoords[0], pCoords[1], pCoords[2], pTexCoords[0], pTexCoords[1] },
|
|
{ pCoords[3], pCoords[4], pCoords[5], pTexCoords[2], pTexCoords[3] },
|
|
{ pCoords[6], pCoords[7], pCoords[8], pTexCoords[4], pTexCoords[5] },
|
|
{ pCoords[9], pCoords[10], pCoords[11], pTexCoords[6], pTexCoords[7] },
|
|
*/
|
|
};
|
|
|
|
//m_pDx->SetFVF(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1);
|
|
//m_pDx->SetRenderState(D3DRS_ALPHAREF, DWORD(m_pGeometryCache->m_sBillboard0.m_fAlphaTestValue));
|
|
//m_pDx->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, sVertex, sizeof(SBillboardVertex));
|
|
|
|
#ifndef _RAC //TOOL
|
|
dev->SetAlpharef(DWORD(m_pGeometryCache->m_sBillboard0.m_fAlphaTestValue));
|
|
#else
|
|
if (SPEEDTREEPRIMITIVE_TRANSPARENTRENDERMODE) dev->SetAlpharef(SPEEDTREE_BILLBOARDALPHATEST);
|
|
else dev->SetAlpharef(DWORD(m_pGeometryCache->m_sBillboard0.m_fAlphaTestValue));
|
|
#endif
|
|
|
|
dev->DrawTriangleFan(D3DFVF_SPEEDTREE_BILLBOARD_VERTEX, sVertex, 4, sizeof(SBillboardVertex));
|
|
//dev->DrawTriangleFan(D3DFVF_XYZ | D3DFVF_TEX1, sVertex, 4, sizeof(SBillboardVertex));
|
|
//dev->DrawTriangleFan(D3DFVF_XYZ, sVertex, 4, sizeof(SBillboardVertex));
|
|
}
|
|
|
|
// if there is a 360 degree billboard, then we need to draw the second one
|
|
if (m_pGeometryCache->m_sBillboard1.m_bIsActive)
|
|
{
|
|
const float* pCoords = m_pGeometryCache->m_sBillboard1.m_pCoords;
|
|
const float* pTexCoords = m_pGeometryCache->m_sBillboard1.m_pTexCoords;
|
|
|
|
K3DVector view = -pLight->direction;
|
|
|
|
SBillboardVertex sVertex[4] =
|
|
{
|
|
{ pCoords[0], pCoords[1], pCoords[2], /*0xffffffff*/view.x, view.y, view.z, pTexCoords[2], pTexCoords[3] },
|
|
{ pCoords[3], pCoords[4], pCoords[5], /*0xffffffff*/view.x, view.y, view.z, pTexCoords[0], pTexCoords[1] },
|
|
{ pCoords[6], pCoords[7], pCoords[8], /*0xffffffff*/view.x, view.y, view.z, pTexCoords[6], pTexCoords[7] },
|
|
{ pCoords[9], pCoords[10], pCoords[11], /*0xffffffff*/view.x, view.y, view.z, pTexCoords[4], pTexCoords[5] },
|
|
/*
|
|
{ pCoords[0], pCoords[1], pCoords[2], pTexCoords[0], pTexCoords[1] },
|
|
{ pCoords[3], pCoords[4], pCoords[5], pTexCoords[2], pTexCoords[3] },
|
|
{ pCoords[6], pCoords[7], pCoords[8], pTexCoords[4], pTexCoords[5] },
|
|
{ pCoords[9], pCoords[10], pCoords[11], pTexCoords[6], pTexCoords[7] },
|
|
*/
|
|
};
|
|
|
|
//m_pDx->SetRenderState(D3DRS_ALPHAREF, DWORD(m_pGeometryCache->m_sBillboard1.m_fAlphaTestValue));
|
|
//m_pDx->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, sVertex, sizeof(SBillboardVertex));
|
|
|
|
#ifndef _RAC //TOOL
|
|
dev->SetAlpharef(DWORD(m_pGeometryCache->m_sBillboard1.m_fAlphaTestValue));
|
|
#else
|
|
if (SPEEDTREEPRIMITIVE_TRANSPARENTRENDERMODE) dev->SetAlpharef(SPEEDTREE_BILLBOARDALPHATEST);
|
|
else dev->SetAlpharef(DWORD(m_pGeometryCache->m_sBillboard1.m_fAlphaTestValue));
|
|
#endif
|
|
|
|
dev->DrawTriangleFan(D3DFVF_SPEEDTREE_BILLBOARD_VERTEX, sVertex, 4, sizeof(SBillboardVertex));
|
|
//dev->DrawTriangleFan(D3DFVF_XYZ | D3DFVF_TEX1, sVertex, 4, sizeof(SBillboardVertex));
|
|
//dev->DrawTriangleFan(D3DFVF_XYZ, sVertex, 4, sizeof(SBillboardVertex));
|
|
}
|
|
|
|
// if we have a horizontal bilboard and it is enabled, draw it too
|
|
#ifdef WRAPPER_RENDER_HORIZONTAL_BILLBOARD
|
|
if (m_pGeometryCache->m_sHorizontalBillboard.m_bIsActive)
|
|
{
|
|
const float* pCoords = m_pGeometryCache->m_sHorizontalBillboard.m_pCoords;
|
|
const float* pTexCoords = m_pGeometryCache->m_sHorizontalBillboard.m_pTexCoords;
|
|
SBillboardVertex sVertex[4] =
|
|
{
|
|
{ pCoords[0], pCoords[1], pCoords[2], 0xffffffff, pTexCoords[0], pTexCoords[1] },
|
|
{ pCoords[3], pCoords[4], pCoords[5], 0xffffffff, pTexCoords[2], pTexCoords[3] },
|
|
{ pCoords[6], pCoords[7], pCoords[8], 0xffffffff, pTexCoords[4], pTexCoords[5] },
|
|
{ pCoords[9], pCoords[10], pCoords[11], 0xffffffff, pTexCoords[6], pTexCoords[7] },
|
|
/*
|
|
{ pCoords[0], pCoords[1], pCoords[2], pTexCoords[0], pTexCoords[1] },
|
|
{ pCoords[3], pCoords[4], pCoords[5], pTexCoords[2], pTexCoords[3] },
|
|
{ pCoords[6], pCoords[7], pCoords[8], pTexCoords[4], pTexCoords[5] },
|
|
{ pCoords[9], pCoords[10], pCoords[11], pTexCoords[6], pTexCoords[7] },
|
|
*/
|
|
};
|
|
|
|
//m_pDx->SetRenderState(D3DRS_ALPHAREF, DWORD(m_pGeometryCache->m_sHorizontalBillboard.m_fAlphaTestValue));
|
|
//m_pDx->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, sVertex, sizeof(SBillboardVertex));
|
|
|
|
#ifndef _RAC //TOOL
|
|
dev->SetAlpharef(DWORD(m_pGeometryCache->m_sHorizontalBillboard.m_fAlphaTestValue));
|
|
#else
|
|
if (SPEEDTREEPRIMITIVE_TRANSPARENTRENDERMODE) dev->SetAlpharef(SPEEDTREE_BILLBOARDALPHATEST);
|
|
else dev->SetAlpharef(DWORD(m_pGeometryCache->m_sHorizontalBillboard.m_fAlphaTestValue));
|
|
#endif
|
|
|
|
dev->DrawTriangleFan(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1, sVertex, 4, sizeof(SBillboardVertex));
|
|
//dev->DrawTriangleFan(D3DFVF_XYZ | D3DFVF_TEX1, sVertex, 4, sizeof(SBillboardVertex));
|
|
//dev->DrawTriangleFan(D3DFVF_XYZ, sVertex, 4, sizeof(SBillboardVertex));
|
|
}
|
|
#endif
|
|
//#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
((K3DRenderDeviceDX*) dev)->GetD3DDevice()->SetRenderState(D3DRS_FOGSTART, *((DWORD*)&fFogStart));
|
|
}
|
|
|
|
for ( int j=0 ; j<m_nTexCount ; ++j )
|
|
dev->SetTexture( j, NULL );
|
|
}
|