Files
2026-06-01 12:46:52 +02:00

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 );
}