1447 lines
48 KiB
C++
1447 lines
48 KiB
C++
// KSeqSpeedTree.cpp: implementation of the KSeqSpeedTree class.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include "KViewport.h"
|
|
#include "KResource.h"
|
|
#include "KSeqSpeedTree.h"
|
|
#include "KResourceManager.h"
|
|
#include "KRenderObjectMesh.h"
|
|
#include "SSpeedTreeVertexShaders.h"
|
|
#include <toolkit/XStringUtil.h>
|
|
//#include "K3DFrustum.h"
|
|
#include "gamedefine.h"
|
|
|
|
#include "k3dpccp.h"
|
|
|
|
#include "KRenderDeviceDX.h"
|
|
|
|
const int DEFAULT_LOD_UNIT_SIZE = 12; // 1미터가 좌표상으로 얼마인지를 정의 <- 게임 룰에서 가져온 것이므로, 변경되면 함께 변경 요망.
|
|
|
|
const float TREE_TRANSPARENT_MAX = 0.6f; // 투명화되는 순간의 최대 투명값
|
|
|
|
bool KSeqSpeedTree::s_bTransparentMode = true;
|
|
bool KSeqSpeedTree::S_bSpeedTreeRender = true;
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Construction/Destruction
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#define AGBR2ARGB(dwColor) (dwColor & 0xff00ff00) + ((dwColor & 0x00ff0000) >> 16) + ((dwColor & 0x000000ff) << 16)
|
|
|
|
unsigned int KSeqSpeedTree::m_unNumWrappersActive = 0;
|
|
K3DRenderDevice * KSeqSpeedTree::m_pDevice = NULL;
|
|
K3DVector KSeqSpeedTree::m_afCameraPos(0.); // Camera position
|
|
K3DVector KSeqSpeedTree::m_afCameraDirection(0.); // Camera direction
|
|
K3DVector KSeqSpeedTree::m_afCameraTargetPos(0.); // Camera target position
|
|
|
|
|
|
|
|
KSeqSpeedTree::KSeqSpeedTree( bool bInstance ) :
|
|
m_bIsInstance(false),
|
|
m_pInstanceOf(NULL),
|
|
m_pGeometryCache(NULL),
|
|
m_usNumLeafLods(0),
|
|
m_unNumFrondLods(0),
|
|
m_pBranchIndexCounts(NULL),
|
|
m_pFrondIndexCounts(NULL),
|
|
m_spFrondIndexBufferArray(NULL),
|
|
m_spLeafVertexBufferArray(NULL),
|
|
m_pLeavesUpdatedByCpu(NULL)
|
|
{
|
|
m_afPos = K3DVector( 0.0f, 0.0f, 0.0f );
|
|
|
|
m_bLoad = FALSE;
|
|
m_bIsClip = false; //외부 Prop 에서 함.
|
|
|
|
// wind states
|
|
m_fWindStrength = 1.f;
|
|
m_fNearLod = 5.f;
|
|
m_fFarLod = 6000;
|
|
|
|
m_fCurrLodLevel = 1.f;
|
|
|
|
m_pSpeedTree = NULL;
|
|
|
|
if( bInstance == false )
|
|
{
|
|
m_pSpeedTree = new CSpeedTreeRT;
|
|
m_pSpeedTree->SetWindStrength(m_fWindStrength);
|
|
m_pSpeedTree->SetLocalMatrices(0, 4);
|
|
}
|
|
|
|
m_prBranch.SetSpeedTree( m_pSpeedTree );
|
|
m_prFrond.SetSpeedTree( m_pSpeedTree );
|
|
m_prLeaf.SetSpeedTree( m_pSpeedTree );
|
|
|
|
#ifdef WRAPPER_BILLBOARD_MODE
|
|
m_prBillboard.SetSpeedTree( m_pSpeedTree );
|
|
#endif
|
|
|
|
m_pTextureInfo = NULL;
|
|
|
|
m_unNumWrappersActive++;
|
|
|
|
m_bIsProcessed = false;
|
|
|
|
K3DMatrixIdentity( m_matWorld );
|
|
}
|
|
|
|
KSeqSpeedTree::~KSeqSpeedTree()
|
|
{
|
|
if (!m_bIsInstance)
|
|
{
|
|
SAFE_DELETE_ARRAY(m_pBranchIndexCounts);
|
|
SAFE_DELETE_ARRAY(m_spFrondIndexBufferArray);
|
|
SAFE_DELETE_ARRAY(m_pFrondIndexCounts);
|
|
|
|
SAFE_DELETE_ARRAY(m_spLeafVertexBufferArray);
|
|
SAFE_DELETE_ARRAY(m_pLeavesUpdatedByCpu);
|
|
|
|
SAFE_DELETE(m_pTextureInfo);
|
|
|
|
_oprint( "Delete original Tree\n" );
|
|
SAFE_DELETE(m_pGeometryCache);
|
|
}
|
|
|
|
// always delete the SpeedTree
|
|
SAFE_DELETE(m_pSpeedTree);
|
|
|
|
--m_unNumWrappersActive;
|
|
}
|
|
|
|
void KSeqSpeedTree::GetBranchTextureName(std::string& name)
|
|
{
|
|
if( !m_pTextureInfo ) return;
|
|
name = m_pTextureInfo->m_pBranchTextureFilename;
|
|
}
|
|
|
|
/*
|
|
void KSeqSpeedTree::GetFrondTextureName(std::string& name)
|
|
{
|
|
name = m_pTextureInfo->m_pFrondTextureFilenames;
|
|
}
|
|
|
|
void KSeqSpeedTree::GetLeafTextureName(std::string& name)
|
|
{
|
|
name = m_pTextureInfo->m_pLeafTextureFilename;
|
|
}
|
|
*/
|
|
|
|
void KSeqSpeedTree::GetCompositeTextureName(std::string& name)
|
|
{
|
|
if( !m_pTextureInfo ) return;
|
|
name = m_pTextureInfo->m_pCompositeFilename;
|
|
}
|
|
|
|
int KSeqSpeedTree::GetBranchPolyCount(float fLod)
|
|
{
|
|
if( !m_pSpeedTree ) return 0;
|
|
return m_pSpeedTree->GetBranchTriangleCount(fLod);
|
|
}
|
|
|
|
int KSeqSpeedTree::GetFrondPolyCount(float fLod)
|
|
{
|
|
if( !m_pSpeedTree ) return 0;
|
|
return m_pSpeedTree->GetFrondTriangleCount(fLod);
|
|
}
|
|
|
|
int KSeqSpeedTree::GetLeafPolyCount(float fLod)
|
|
{
|
|
if( !m_pSpeedTree ) return 0;
|
|
return m_pSpeedTree->GetLeafTriangleCount(fLod);
|
|
}
|
|
|
|
void *KSeqSpeedTree::Perform( KID id, KArg& msg )
|
|
{
|
|
_CID( REQ_BOUNDBOX );
|
|
if( id == id_REQ_BOUNDBOX )
|
|
{
|
|
KMsgREQ_BOUNDBOX *boundReq = static_cast<KMsgREQ_BOUNDBOX*>(&msg);
|
|
|
|
boundReq->AddBound( GetBoundCube() );
|
|
}
|
|
|
|
return (void*)1;
|
|
}
|
|
|
|
int KSeqSpeedTree::Process( DWORD dwTime )
|
|
{
|
|
int process_state = (m_bIsPlaying) ? (SEQINFO_PLAYING) : (SEQINFO_STOPPED);
|
|
|
|
if( !m_bLoad ) return SEQINFO_STOPPED;
|
|
|
|
{
|
|
//나무 퀄리티 올려주기
|
|
//2009-12-23 : hunee
|
|
//Advance(false, 1.0f);
|
|
Advance(true, m_fCurrLodLevel);
|
|
}
|
|
|
|
{
|
|
SetupBranchForTreeType();
|
|
SetupFrondForTreeType();
|
|
SetupLeafForTreeType();
|
|
EndLeafForTreeType();
|
|
}
|
|
|
|
if( !m_bIsProcessed )
|
|
m_bIsProcessed = true;
|
|
|
|
return process_state;
|
|
}
|
|
|
|
|
|
void KSeqSpeedTree::ClipTest( const K3DVector* pFrustum )
|
|
{
|
|
// m_bIsClip = ( pFrustum->ISContainCube(m_BoundCube) == K3DFrustum::FRUSTUM_OUT );
|
|
m_bIsClip = KPCCP::nonuniformcube_collide_nonuniformcube(pFrustum, m_BoundCube.GetVertices()) == false;
|
|
}
|
|
|
|
void KSeqSpeedTree::Render( KViewportObject *viewport, DWORD flag, const K3DMatrix * pAttachMat )
|
|
{
|
|
if( !m_bLoad ) return;
|
|
|
|
if( m_bIsClip ) return;
|
|
|
|
if( !S_bSpeedTreeRender ) return;
|
|
|
|
if( !m_bIsProcessed ) return;
|
|
|
|
bool bTransparent = m_fMasterVisibility >= 1.0 ? false : true;
|
|
// sonador #2.1.7.1 스피드 트리 퍼포먼스 증가
|
|
//bTransparent = false;
|
|
|
|
{
|
|
PositionTree( );
|
|
}
|
|
|
|
{
|
|
#ifndef _RAC //TOOL
|
|
|
|
bool bTransparent = m_fMasterVisibility >= 1.0 ? false : true;
|
|
bTransparent = false;
|
|
|
|
m_prBranch.SetVisibility( m_fMasterVisibility );
|
|
m_prFrond.SetVisibility( m_fMasterVisibility );
|
|
m_prLeaf.SetVisibility( m_fMasterVisibility );
|
|
m_prBillboard.SetVisibility( m_fMasterVisibility );
|
|
m_prBranch.SetTransparent( bTransparent );
|
|
m_prFrond.SetTransparent( bTransparent );
|
|
m_prLeaf.SetTransparent( bTransparent );
|
|
m_prBillboard.SetTransparent( bTransparent );
|
|
#else
|
|
//
|
|
// 카메라 위치로부터 투명도 계산
|
|
//
|
|
float playerDist, treeDist;
|
|
float opacity;
|
|
//bool isTransparent;
|
|
K3DMatrix *transform=m_prBranch.GetTransform();
|
|
K3DVector v;
|
|
v.x=transform->m30;
|
|
v.y=transform->m31;
|
|
v.z=transform->m32;
|
|
|
|
|
|
playerDist=(m_afCameraTargetPos-m_afCameraPos).Magnitude(); // 플레이어-카메라 거리
|
|
treeDist=(v-m_afCameraPos).Magnitude(); // 나무-카메라 거리
|
|
if (treeDist>playerDist) { // Tree is farther than player distance : Full opaque
|
|
//isTransparent=false; // 불투명
|
|
opacity=TREE_TRANSPARENT_MAX * m_fMasterVisibility; // 불투명도 max
|
|
} else { // Near-camera trees : make transparent
|
|
//isTransparent=true; // 투명
|
|
bTransparent=true; // 투명
|
|
opacity=1.0f * ( treeDist / playerDist ) * m_fMasterVisibility; // 불투명도 = 나무거리 / 플레이어거리 <- 나중에 적당히 숫자 곱하거나 n승해서 조절할 것
|
|
}
|
|
|
|
m_prBranch.SetVisibility( opacity );
|
|
m_prFrond.SetVisibility( opacity );
|
|
m_prLeaf.SetVisibility( opacity );
|
|
|
|
#ifdef WRAPPER_BILLBOARD_MODE
|
|
m_prBillboard.SetVisibility( opacity );
|
|
#endif
|
|
|
|
m_prBranch.SetTransparent( IsTranparentMode() && bTransparent );
|
|
m_prFrond.SetTransparent( IsTranparentMode() && bTransparent );
|
|
m_prLeaf.SetTransparent( IsTranparentMode() && bTransparent );
|
|
|
|
#ifdef WRAPPER_BILLBOARD_MODE
|
|
m_prBillboard.SetTransparent( IsTranparentMode() && bTransparent );
|
|
#endif
|
|
#endif
|
|
|
|
|
|
// RenderBillboards();
|
|
//if (m_pGeometryCache->m_sBillboard0.m_bIsActive)
|
|
//{
|
|
// int a = 1;
|
|
// a = 2;
|
|
//}
|
|
|
|
if( m_prBranch.IsValid() )
|
|
viewport->Register( &m_prBranch, KRenderObject::RENDEREFX_SPEEDTREE_BRANCH | (SHADOW_ST_CAST<<16) );
|
|
if( m_prFrond.IsValid() )
|
|
viewport->Register( &m_prFrond , KRenderObject::RENDEREFX_SPEEDTREE_FROND );
|
|
if( m_prLeaf.IsValid() )
|
|
viewport->Register( &m_prLeaf , KRenderObject::RENDEREFX_SPEEDTREE_LEAF | (SHADOW_ST_CAST<<16) );
|
|
|
|
#ifdef WRAPPER_BILLBOARD_MODE
|
|
if( m_prBillboard.IsValid() )
|
|
viewport->Register( &m_prBillboard, KRenderObject::RENDEREFX_SPEEDTREE_BILLBOARD );
|
|
#endif
|
|
//viewport->Register( &m_prBillboard, KRenderObject::RENDEREFX_SPEEDTREE_BILLBOARD | (SHADOW_ST_CAST<<16) );
|
|
}
|
|
|
|
// m_BoundCube.Render( viewport );
|
|
}
|
|
|
|
void KSeqSpeedTree::SetTransform( const K3DMatrix &mat )
|
|
{
|
|
// m_matTransform = mat;
|
|
SetPos( mat._41, mat._42, mat._43 );
|
|
// m_BoundCube.SetTransform( m_matTransform );
|
|
// if( m_pSpeedTree->Compute(NULL,1) )
|
|
// {
|
|
// float fSize, fVariance;
|
|
// m_pSpeedTree->GetTreeSize( fSize, fVariance );
|
|
// m_pSpeedTree->SetTreeSize( fSize*m_matTransform._11, fVariance );
|
|
// }
|
|
}
|
|
|
|
K3DBoundRotCube* KSeqSpeedTree::GetBoundCube( const char * pName )
|
|
{
|
|
realizeTime();
|
|
m_BoundCube.SetTransform(m_matResult);
|
|
m_BoundCube.GetVertices(); //미리 한번 계산 되게~
|
|
|
|
return &m_BoundCube;
|
|
}
|
|
|
|
bool KSeqSpeedTree::_load( unsigned int nSeed, float fSize, float fSizeVariance, const float * pTransform )
|
|
{
|
|
bool bSuccess = false;
|
|
|
|
// override the lighting method stored in the spt file
|
|
#ifdef WRAPPER_USE_DYNAMIC_LIGHTING
|
|
m_pSpeedTree->SetBranchLightingMethod(CSpeedTreeRT::LIGHT_DYNAMIC);
|
|
m_pSpeedTree->SetLeafLightingMethod(CSpeedTreeRT::LIGHT_DYNAMIC);
|
|
m_pSpeedTree->SetFrondLightingMethod(CSpeedTreeRT::LIGHT_DYNAMIC);
|
|
#else
|
|
m_pSpeedTree->SetBranchLightingMethod(CSpeedTreeRT::LIGHT_STATIC);
|
|
m_pSpeedTree->SetLeafLightingMethod(CSpeedTreeRT::LIGHT_STATIC);
|
|
m_pSpeedTree->SetFrondLightingMethod(CSpeedTreeRT::LIGHT_STATIC);
|
|
#endif
|
|
|
|
// set the wind method
|
|
#ifdef WRAPPER_USE_GPU_WIND
|
|
m_pSpeedTree->SetBranchWindMethod(CSpeedTreeRT::WIND_GPU);
|
|
m_pSpeedTree->SetLeafWindMethod(CSpeedTreeRT::WIND_GPU);
|
|
m_pSpeedTree->SetFrondWindMethod(CSpeedTreeRT::WIND_GPU);
|
|
#endif
|
|
#ifdef WRAPPER_USE_CPU_WIND
|
|
m_pSpeedTree->SetBranchWindMethod(CSpeedTreeRT::WIND_CPU);
|
|
m_pSpeedTree->SetLeafWindMethod(CSpeedTreeRT::WIND_CPU);
|
|
m_pSpeedTree->SetFrondWindMethod(CSpeedTreeRT::WIND_CPU);
|
|
#endif
|
|
#ifdef WRAPPER_USE_NO_WIND
|
|
m_pSpeedTree->SetBranchWindMethod(CSpeedTreeRT::WIND_NONE);
|
|
m_pSpeedTree->SetLeafWindMethod(CSpeedTreeRT::WIND_NONE);
|
|
m_pSpeedTree->SetFrondWindMethod(CSpeedTreeRT::WIND_NONE);
|
|
#endif
|
|
|
|
m_pSpeedTree->SetNumLeafRockingGroups(1);
|
|
|
|
// override the size, if necessary
|
|
if (fSize >= 0.0f && fSizeVariance >= 0.0f)
|
|
m_pSpeedTree->SetTreeSize(fSize, fSizeVariance);
|
|
//{
|
|
// float oriSize, oriSizeVariance;
|
|
// m_pSpeedTree->GetTreeSize( oriSize, oriSizeVariance );
|
|
// m_pSpeedTree->SetTreeSize(fSize*oriSize, fSizeVariance);
|
|
//}
|
|
|
|
/*float afLeafMaterial[ ] =
|
|
{
|
|
1.0f, 1.0f, 1.0f, // diffuse
|
|
0.2f, 0.2f, 0.2f, // ambient
|
|
0.0f, 0.0f, 0.0f, // specular
|
|
0.0f, 0.0f, 0.0f, // emissive
|
|
0.0f // shininess
|
|
};
|
|
m_pSpeedTree->SetLeafMaterial(afLeafMaterial);*/
|
|
|
|
// generate tree geometry
|
|
if (m_pSpeedTree->Compute(pTransform, nSeed))
|
|
{
|
|
//const char * pError = m_pSpeedTree->GetCurrentError();
|
|
|
|
// get the dimensions
|
|
m_pSpeedTree->GetBoundingBox(m_afBoundingBox);
|
|
|
|
m_BoundCube = K3DBoundRotCube( m_afBoundingBox[0], m_afBoundingBox[3], m_afBoundingBox[1], m_afBoundingBox[4], m_afBoundingBox[2], m_afBoundingBox[5] );
|
|
|
|
// make the leaves rock in the wind
|
|
m_pSpeedTree->SetLeafRockingState(true);
|
|
|
|
// billboard setup
|
|
#ifdef WRAPPER_BILLBOARD_MODE
|
|
CSpeedTreeRT::SetDropToBillboard(true);
|
|
#else
|
|
CSpeedTreeRT::SetDropToBillboard(false);
|
|
#endif
|
|
|
|
// query & set materials
|
|
m_cBranchMaterial.Set(m_pSpeedTree->GetBranchMaterial( ));
|
|
m_cFrondMaterial.Set(m_pSpeedTree->GetFrondMaterial( ));
|
|
m_cLeafMaterial.Set(m_pSpeedTree->GetLeafMaterial( ));
|
|
|
|
// adjust lod distances
|
|
float fHeight = m_afBoundingBox[5] - m_afBoundingBox[2];
|
|
m_pSpeedTree->SetLodLimits( fHeight * m_fNearLod, fHeight * m_fFarLod);
|
|
|
|
// query textures
|
|
m_pTextureInfo = new CSpeedTreeRT::STextures;
|
|
m_pSpeedTree->GetTextures(*m_pTextureInfo);
|
|
|
|
// load branch textures
|
|
m_spTexBranchTexture = LoadTexture( m_pTextureInfo->m_pBranchTextureFilename ); //DDS 포멧 사용
|
|
if( m_spTexBranchTexture == NULL )
|
|
{
|
|
_oprint( "->>Branch Texture Not DDS : %s\n", "_load()" );
|
|
m_spTexBranchTexture = LoadTexture( m_pTextureInfo->m_pBranchTextureFilename ); //tga 포멧 사용
|
|
}
|
|
|
|
#ifdef WRAPPER_RENDER_SELF_SHADOWS
|
|
if (m_pTextureInfo->m_pSelfShadowFilename != NULL && m_spTexShadow == NULL)
|
|
{
|
|
if( m_pTextureInfo->m_pSelfShadowFilename && m_pTextureInfo->m_pSelfShadowFilename[0] )
|
|
{
|
|
//DDS 처리
|
|
size_t nPos = 0;
|
|
std::string strFileName = m_pTextureInfo->m_pSelfShadowFilename;
|
|
|
|
nPos = strFileName.rfind( ".");
|
|
if(nPos != std::string::npos)
|
|
{
|
|
strFileName.erase(strFileName.begin() + nPos, strFileName.end());
|
|
}
|
|
|
|
strFileName += ".dds";
|
|
|
|
m_spTexShadow = LoadTexture( strFileName.c_str() );
|
|
|
|
if(m_spTexShadow == NULL)
|
|
{
|
|
//TGA 처리
|
|
XStringUtil::Replace( strFileName, ".dds", ".tga" );
|
|
|
|
m_spTexShadow = LoadTexture( strFileName.c_str() );
|
|
}
|
|
|
|
}
|
|
}
|
|
#endif
|
|
//통합 화일이 있으면,
|
|
if( strlen(m_pTextureInfo->m_pCompositeFilename) )
|
|
{
|
|
//DDS 처리
|
|
size_t nPos = 0;
|
|
std::string strFileName = m_pTextureInfo->m_pCompositeFilename;
|
|
|
|
nPos = strFileName.rfind( ".");
|
|
if(nPos != std::string::npos)
|
|
{
|
|
strFileName.erase(strFileName.begin() + nPos, strFileName.end());
|
|
}
|
|
|
|
strFileName += ".dds";
|
|
|
|
m_spTexFrondTexture = LoadTexture( strFileName.c_str() );
|
|
|
|
if(m_spTexFrondTexture == NULL)
|
|
{
|
|
//TGA 처리
|
|
XStringUtil::Replace( strFileName, ".dds", ".tga" );
|
|
|
|
m_spTexFrondTexture = LoadTexture( strFileName.c_str() );
|
|
}
|
|
|
|
m_spTexLeafTexture = m_spTexFrondTexture;
|
|
|
|
#ifdef WRAPPER_BILLBOARD_MODE
|
|
m_spTexBillboardTexture = m_spTexFrondTexture;
|
|
#endif
|
|
}
|
|
//else
|
|
//{ //개별 Load
|
|
// for( unsigned int i(0); m_pTextureInfo->m_uiFrondTextureCount>i; i++ )
|
|
// {
|
|
// const char * pFrondName = m_pTextureInfo->m_pFrondTextureFilenames[i];
|
|
// if( m_spTexFrondTexture == NULL )
|
|
// {
|
|
// m_spTexFrondTexture = LoadTexture( pFrondName );
|
|
// }
|
|
// }
|
|
|
|
// for( unsigned int i(0); m_pTextureInfo->m_uiLeafTextureCount>i; i++ )
|
|
// {
|
|
// const char * pLeafName = m_pTextureInfo->m_pLeafTextureFilenames[i];
|
|
// if( m_spTexLeafTexture == NULL )
|
|
// {
|
|
// m_spTexLeafTexture = LoadTexture( pLeafName );
|
|
// }
|
|
// }
|
|
//}
|
|
|
|
// setup the vertex and index buffers
|
|
SetupBuffers( );
|
|
|
|
m_prBranch.SetSubMeshCount( 1 );
|
|
m_prBranch.SetVertexBuffer( 0, m_spBranchVertexBuffer, SSpeedTreePrimitive::TREE_BRANCH,m_unBranchVertexCount, m_pBranchIndexCounts );
|
|
|
|
if( m_spBranchVertexBuffer )
|
|
m_prBranch.SetValid( m_spBranchVertexBuffer->IsValidVtx() );
|
|
else
|
|
m_prBranch.SetValid( false );
|
|
|
|
m_prBranch.SetIndexBuffer( 0, m_spBranchIndexBuffer );
|
|
//m_prBranch.SetTextureCount( 1 );
|
|
m_prBranch.SetTextureCount( 2 );
|
|
m_prBranch.SetTexture( 0, m_spTexBranchTexture );
|
|
|
|
m_prFrond.SetGeometry( m_pGeometryCache );
|
|
m_prFrond.SetSpeedTree( m_pSpeedTree );
|
|
m_prFrond.SetSubMeshCount( m_unNumFrondLods );
|
|
|
|
if( m_spFrondVertexBuffer != NULL)
|
|
m_prFrond.SetVertexBuffer( 0, m_spFrondVertexBuffer, SSpeedTreePrimitive::TREE_FROND, m_unFrondVertexCount, m_pFrondIndexCounts );
|
|
|
|
for(unsigned int i = 0; i < m_unNumFrondLods; i++)
|
|
{
|
|
m_prFrond.SetIndexBuffer(i, m_spFrondIndexBufferArray[i]);
|
|
|
|
if( m_spFrondVertexBuffer )
|
|
m_prFrond.SetValid( m_spFrondVertexBuffer->IsValidVtx() );
|
|
else
|
|
m_prFrond.SetValid( false );
|
|
}
|
|
//m_prFrond.SetTextureCount( 1 );
|
|
m_prFrond.SetTextureCount( 2 );
|
|
m_prFrond.SetTexture( 0, m_spTexFrondTexture );
|
|
|
|
m_prLeaf.SetGeometry( m_pGeometryCache );
|
|
m_prLeaf.SetSpeedTree( m_pSpeedTree );
|
|
m_prLeaf.SetSubMeshCount( m_usNumLeafLods );
|
|
for( int i(0); m_usNumLeafLods>i; i++ )
|
|
{
|
|
m_prLeaf.SetVertexBuffer( i,m_spLeafVertexBufferArray[i], SSpeedTreePrimitive::TREE_LEAF, 0, NULL );
|
|
if( m_spLeafVertexBufferArray[i] && m_spLeafVertexBufferArray[i]->IsValidVtx() == false )
|
|
m_prLeaf.SetValid( m_spLeafVertexBufferArray[i]->IsValidVtx() );
|
|
}
|
|
m_prLeaf.SetTextureCount( 1 );
|
|
//m_prLeaf.SetTextureCount( 2 );
|
|
m_prLeaf.SetTexture( 0, m_spTexLeafTexture );
|
|
|
|
#ifdef WRAPPER_BILLBOARD_MODE
|
|
m_prBillboard.SetGeometry(m_pGeometryCache);
|
|
m_prBillboard.SetSpeedTree(m_pSpeedTree);
|
|
m_prBillboard.SetSubMeshCount(1);
|
|
m_prBillboard.SetVertexBuffer(0, NULL, SSpeedTreePrimitive::TREE_BILLBOARD, 0, 0);
|
|
m_prBillboard.SetIndexBuffer(0, NULL);
|
|
m_prBillboard.SetTextureCount(1);
|
|
//m_prBillboard.SetTextureCount(2);
|
|
//m_prBillboard.SetTexture(0, m_spTexCompositeMap );
|
|
m_prBillboard.SetTexture(0, m_spTexBillboardTexture );
|
|
#endif
|
|
|
|
// everything appeared to go well023
|
|
bSuccess = true;
|
|
m_bLoad = TRUE;
|
|
}
|
|
else // tree failed to compute
|
|
_oprint( "\nFatal Error, cannot compute tree [%s]\n\n", CSpeedTreeRT::GetCurrentError( ));
|
|
|
|
return bSuccess;
|
|
}
|
|
|
|
bool KSeqSpeedTree::LoadTree(KStream* pszSptStream, unsigned int nSeed, float fSize, float fSizeVariance, const float * pTransform)
|
|
{
|
|
bool bSuccess = false;
|
|
|
|
// directx, so allow for flipping of the texture coordinate
|
|
#ifdef WRAPPER_FLIP_T_TEXCOORD
|
|
m_pSpeedTree->SetTextureFlip(true);
|
|
#endif
|
|
|
|
// load the tree file
|
|
if (m_pSpeedTree->LoadTree(pszSptStream))
|
|
{
|
|
bSuccess = _load( nSeed, fSize, fSizeVariance, pTransform );
|
|
}
|
|
else // tree failed to load
|
|
_oprint( "SpeedTreeRT Error: %s\n", CSpeedTreeRT::GetCurrentError( ));
|
|
|
|
return bSuccess;
|
|
}
|
|
|
|
bool KSeqSpeedTree::LoadTree(const char* pszSptFile, unsigned int nSeed, float fSize, float fSizeVariance, const float * pTransform )
|
|
{
|
|
bool bSuccess = false;
|
|
|
|
// _oprint( "Speed Tree : %s\n", pszSptFile );
|
|
|
|
// directx, so allow for flipping of the texture coordinate
|
|
#ifdef WRAPPER_FLIP_T_TEXCOORD
|
|
m_pSpeedTree->SetTextureFlip(true);
|
|
#endif
|
|
|
|
// load the tree file
|
|
if (m_pSpeedTree->LoadTree(pszSptFile))
|
|
{
|
|
bSuccess = _load( nSeed, fSize, fSizeVariance, pTransform );
|
|
}
|
|
else // tree failed to load
|
|
_oprint( "SpeedTreeRT Error: %s\n", CSpeedTreeRT::GetCurrentError( ));
|
|
|
|
return bSuccess;
|
|
}
|
|
void KSeqSpeedTree::SetupBuffers(void)
|
|
{
|
|
// read all the geometry for highest LOD into the geometry cache
|
|
m_pSpeedTree->SetLodLevel(1.f);
|
|
if (m_pGeometryCache == NULL)
|
|
{
|
|
static int nCnt = 0;
|
|
m_pGeometryCache = new CSpeedTreeRT::SGeometry;
|
|
// _oprint( "SetupBuffers : new m_pGeometryCache - %d\n", nCnt++ );
|
|
}
|
|
m_pSpeedTree->GetGeometry(*m_pGeometryCache);
|
|
|
|
m_prBranch.SetGeometry( m_pGeometryCache );
|
|
m_prFrond.SetGeometry( m_pGeometryCache );
|
|
m_prLeaf.SetGeometry( m_pGeometryCache );
|
|
|
|
#ifdef WRAPPER_BILLBOARD_MODE
|
|
m_prBillboard.SetGeometry(m_pGeometryCache);
|
|
#endif
|
|
|
|
////BillBoard
|
|
// m_pSpeedTree->GetGeometry(*m_pGeometryCache, SpeedTree_BillboardGeometry);
|
|
// m_pGeometryCache->m_sBillboard0.m_pTexCoords;
|
|
|
|
// setup the buffers for each tree part
|
|
SetupBranchBuffers( );
|
|
SetupFrondBuffers( );
|
|
SetupLeafBuffers( );
|
|
//SetupBillboardBuffers();
|
|
}
|
|
|
|
void KSeqSpeedTree::SetupBranchBuffers(void)
|
|
{
|
|
// reference to the branch structure
|
|
CSpeedTreeRT::SGeometry::SIndexed* pBranches = &(m_pGeometryCache->m_sBranches);
|
|
m_unBranchVertexCount = pBranches->m_usVertexCount; // we asked for a contiguous strip
|
|
|
|
// check if this tree has branches
|
|
if (m_unBranchVertexCount > 1)
|
|
{
|
|
// create the vertex buffer for storing branch vertices
|
|
#ifdef WRAPPER_USE_GPU_WIND
|
|
m_spBranchVertexBuffer = m_pDevice->CreateVertexBufferSpeedTree( sizeof(SFVFBranchVertex), D3DUSAGE_WRITEONLY, D3DFVF_SPEEDTREE_BRANCH_VERTEX, m_unBranchVertexCount );
|
|
#else
|
|
m_spBranchVertexBuffer = m_pDevice->CreateVertexBufferSpeedTree( sizeof(SFVFBranchVertex), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_SPEEDTREE_BRANCH_VERTEX, m_unBranchVertexCount );
|
|
#endif
|
|
if( m_spBranchVertexBuffer == NULL || !m_spBranchVertexBuffer->IsValidVtx() ) return;
|
|
|
|
// fill the vertex buffer by interleaving SpeedTree data
|
|
int nVtxSize = 0;
|
|
SFVFBranchVertex* pVertexBuffer = NULL;
|
|
#ifdef WRAPPER_USE_GPU_WIND
|
|
m_spBranchVertexBuffer->Lock(reinterpret_cast<void**>(&pVertexBuffer), nVtxSize);
|
|
#else
|
|
m_spBranchVertexBuffer->Lock(reinterpret_cast<void**>(&pVertexBuffer), nVtxSize, D3DLOCK_NOSYSLOCK | D3DLOCK_DISCARD);
|
|
#endif
|
|
|
|
assert(pVertexBuffer && "m_spBranchVertexBuffer->Lock(reinterpret_cast<void**>(&pVertexBuffer), nVtxSize);");
|
|
unsigned int i;
|
|
if( pVertexBuffer )
|
|
{
|
|
for (i = 0; i < m_unBranchVertexCount; ++i)
|
|
{
|
|
// position
|
|
memcpy(&pVertexBuffer->m_vPosition, &(pBranches->m_pCoords[i * 3]), sizeof(pVertexBuffer->m_vPosition));
|
|
|
|
// normal or color
|
|
#ifdef WRAPPER_USE_DYNAMIC_LIGHTING
|
|
memcpy(&pVertexBuffer->m_vNormal, &(pBranches->m_pNormals[i * 3]), sizeof(pVertexBuffer->m_vNormal));
|
|
#else
|
|
pVertexBuffer->m_dwDiffuseColor = AGBR2ARGB(pBranches->m_pColors[i]);
|
|
#endif
|
|
|
|
// texcoords for layer 0
|
|
pVertexBuffer->m_fTexCoords[0] = pBranches->m_pTexCoords0[i * 2];
|
|
pVertexBuffer->m_fTexCoords[1] = pBranches->m_pTexCoords0[i * 2 + 1];
|
|
|
|
// texcoords for layer 1 (if enabled)
|
|
#ifdef WRAPPER_RENDER_SELF_SHADOWS
|
|
pVertexBuffer->m_fShadowCoords[0] = pBranches->m_pTexCoords1[i * 2];
|
|
pVertexBuffer->m_fShadowCoords[1] = pBranches->m_pTexCoords1[i * 2 + 1];
|
|
#endif
|
|
|
|
// gpu wind data
|
|
#ifdef WRAPPER_USE_GPU_WIND
|
|
pVertexBuffer->m_fWindIndex = 4.0f * pBranches->m_pWindMatrixIndices[i];
|
|
pVertexBuffer->m_fWindWeight = (float)pBranches->m_pWindWeights[i];
|
|
#endif
|
|
|
|
++pVertexBuffer;
|
|
}
|
|
m_spBranchVertexBuffer->Unlock( );
|
|
|
|
m_spBranchVertexBuffer->Backup();
|
|
}
|
|
|
|
// create and fill the index counts for each LOD
|
|
unsigned int unNumLodLevels = m_pSpeedTree->GetNumBranchLodLevels( );
|
|
m_pBranchIndexCounts = new unsigned short[unNumLodLevels];
|
|
for (i = 0; i < unNumLodLevels; ++i)
|
|
{
|
|
// force geometry update for this LOD
|
|
m_pSpeedTree->GetGeometry(*m_pGeometryCache, SpeedTree_BranchGeometry, (short)i);
|
|
|
|
// check if this LOD has branches
|
|
if (pBranches->m_usNumStrips > 0)
|
|
m_pBranchIndexCounts[i] = pBranches->m_pStripLengths[0];
|
|
else
|
|
m_pBranchIndexCounts[i] = 0;
|
|
}
|
|
// force update of geometry to highest LOD
|
|
m_pSpeedTree->GetGeometry(*m_pGeometryCache, SpeedTree_BranchGeometry, 0);
|
|
|
|
// the first LOD level contains the most indices of all the levels, so
|
|
// we use its size to allocate the index buffer
|
|
m_spBranchIndexBuffer = m_pDevice->CreateIndexBuffer( m_pBranchIndexCounts[0] );
|
|
|
|
// fill the index buffer
|
|
unsigned short* pIndexBuffer = NULL;
|
|
int nIdxSize = 0;
|
|
m_spBranchIndexBuffer->Lock( reinterpret_cast<void**>(&pIndexBuffer), nIdxSize);
|
|
assert(pIndexBuffer && "m_spBranchIndexBuffer->Lock( reinterpret_cast<void**>(&pIndexBuffer), nIdxSize);");
|
|
if( pIndexBuffer )
|
|
{
|
|
memcpy(pIndexBuffer, pBranches->m_pStrips[0], pBranches->m_pStripLengths[0] * sizeof(unsigned short));
|
|
m_spBranchIndexBuffer->Unlock( );
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
// CSpeedTreeWrapper::SetupFrondBuffers
|
|
|
|
void KSeqSpeedTree::SetupFrondBuffers(void)
|
|
{
|
|
// reference to frond structure
|
|
CSpeedTreeRT::SGeometry::SIndexed* pFronds = &(m_pGeometryCache->m_sFronds);
|
|
m_unFrondVertexCount = pFronds->m_usVertexCount; // we asked for a contiguous strip
|
|
|
|
// check if this tree has fronds
|
|
if (m_unFrondVertexCount > 1)
|
|
{
|
|
// create the vertex buffer for storing frond vertices
|
|
#ifdef WRAPPER_USE_GPU_WIND
|
|
m_spFrondVertexBuffer = m_pDevice->CreateVertexBufferSpeedTree( sizeof(SFVFBranchVertex), D3DUSAGE_WRITEONLY, D3DFVF_SPEEDTREE_BRANCH_VERTEX, m_unFrondVertexCount );
|
|
#else
|
|
m_spFrondVertexBuffer = m_pDevice->CreateVertexBufferSpeedTree( sizeof(SFVFBranchVertex), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_SPEEDTREE_BRANCH_VERTEX, m_unFrondVertexCount);
|
|
#endif
|
|
if( m_spFrondVertexBuffer == NULL || !m_spFrondVertexBuffer->IsValidVtx() ) return;
|
|
|
|
// fill the vertex buffer by interleaving SpeedTree data
|
|
SFVFBranchVertex* pVertexBuffer = NULL;
|
|
int nVtxSize = 0;
|
|
#ifdef WRAPPER_USE_GPU_WIND
|
|
m_spFrondVertexBuffer->Lock(reinterpret_cast<void**>(&pVertexBuffer), nVtxSize);
|
|
#else
|
|
m_spFrondVertexBuffer->Lock(reinterpret_cast<void**>(&pVertexBuffer), nVtxSize, D3DLOCK_NOSYSLOCK | D3DLOCK_DISCARD);
|
|
#endif
|
|
|
|
assert(pVertexBuffer && "m_spFrondVertexBuffer->Lock(reinterpret_cast<void**>(&pVertexBuffer), nVtxSize);");
|
|
for (unsigned short i = 0; i < m_unFrondVertexCount; ++i)
|
|
{
|
|
// position
|
|
memcpy(&pVertexBuffer->m_vPosition, &(pFronds->m_pCoords[i * 3]), sizeof(pVertexBuffer->m_vPosition));
|
|
|
|
// normal or color
|
|
#ifdef WRAPPER_USE_DYNAMIC_LIGHTING
|
|
memcpy(&pVertexBuffer->m_vNormal, &(pFronds->m_pNormals[i * 3]), sizeof(pVertexBuffer->m_vNormal));
|
|
#else
|
|
pVertexBuffer->m_dwDiffuseColor = AGBR2ARGB(pFronds->m_pColors[i]);
|
|
#endif
|
|
|
|
// texcoords for layer 0
|
|
pVertexBuffer->m_fTexCoords[0] = pFronds->m_pTexCoords0[i * 2];
|
|
pVertexBuffer->m_fTexCoords[1] = pFronds->m_pTexCoords0[i * 2 + 1];
|
|
|
|
// texcoords for layer 1 (if enabled)
|
|
#ifdef WRAPPER_RENDER_SELF_SHADOWS
|
|
pVertexBuffer->m_fShadowCoords[0] = pFronds->m_pTexCoords1[i * 2];
|
|
pVertexBuffer->m_fShadowCoords[1] = pFronds->m_pTexCoords1[i * 2 + 1];
|
|
#endif
|
|
|
|
// gpu wind data
|
|
#ifdef WRAPPER_USE_GPU_WIND
|
|
pVertexBuffer->m_fWindIndex = 4.0f * pFronds->m_pWindMatrixIndices[i];
|
|
pVertexBuffer->m_fWindWeight = pFronds->m_pWindWeights[i];
|
|
#endif
|
|
|
|
++pVertexBuffer;
|
|
}
|
|
m_spFrondVertexBuffer->Unlock( );
|
|
m_spFrondVertexBuffer->Backup();
|
|
|
|
// create and fill the index counts for each LOD
|
|
//unsigned int unNumLodLevels = m_pSpeedTree->GetNumFrondLodLevels( );
|
|
//m_pFrondIndexCounts = new unsigned short[unNumLodLevels];
|
|
m_unNumFrondLods = m_pSpeedTree->GetNumFrondLodLevels();
|
|
m_pFrondIndexCounts = new unsigned short[m_unNumFrondLods];
|
|
|
|
|
|
// 이런 위험한 짓을 -_-
|
|
m_spFrondIndexBufferArray = new K3DIndexBufferSPtr[m_unNumFrondLods];
|
|
|
|
//for (i = 0; i < unNumLodLevels; ++i)
|
|
for (unsigned int i = 0; i < m_unNumFrondLods; ++i)
|
|
{
|
|
// force update of geometry for this LOD
|
|
m_pSpeedTree->GetGeometry(*m_pGeometryCache, SpeedTree_FrondGeometry, -1, i);
|
|
|
|
// check if this LOD has fronds
|
|
if (pFronds->m_usNumStrips > 0)
|
|
m_pFrondIndexCounts[i] = pFronds->m_pStripLengths[0];
|
|
else
|
|
m_pFrondIndexCounts[i] = 0;
|
|
|
|
if (m_pFrondIndexCounts[i] > 0)
|
|
{
|
|
m_spFrondIndexBufferArray[i] = m_pDevice->CreateIndexBuffer(m_pFrondIndexCounts[i]);
|
|
|
|
// fill the index buffer
|
|
unsigned short* pIndexBuffer = NULL;
|
|
int nIdxSize = 0;
|
|
m_spFrondIndexBufferArray[i]->Lock(reinterpret_cast<void**>(&pIndexBuffer), nIdxSize);
|
|
assert(pIndexBuffer && "m_spFrondIndexBufferArray[i]->Lock(reinterpret_cast<void**>(&pIndexBuffer), nIdxSize);");
|
|
memcpy(pIndexBuffer, pFronds->m_pStrips[0], m_pFrondIndexCounts[i] * sizeof(unsigned short));
|
|
m_spFrondIndexBufferArray[i]->Unlock( );
|
|
}
|
|
}
|
|
// force update of geometry to highest LOD
|
|
m_pSpeedTree->GetGeometry(*m_pGeometryCache, SpeedTree_FrondGeometry, -1, 0);
|
|
|
|
// the first LOD level contains the most indices of all the levels, so
|
|
// we use its size to allocate the index buffer
|
|
//m_spFrondIndexBufferArray = m_pDevice->CreateIndexBuffer(m_pFrondIndexCounts[0]);
|
|
// fill the index buffer
|
|
//unsigned short* pIndexBuffer = NULL;
|
|
//int nIdxSize = 0;
|
|
//m_spFrondIndexBufferArray->Lock(reinterpret_cast<void**>(&pIndexBuffer), nIdxSize);
|
|
//memcpy(pIndexBuffer, pFronds->m_pStrips[0], pFronds->m_pStripLengths[0] * sizeof(unsigned short));
|
|
//m_spFrondIndexBufferArray->Unlock( );
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
// CSpeedTreeWrapper::SetupLeafBuffers
|
|
|
|
void KSeqSpeedTree::SetupLeafBuffers(void)
|
|
{
|
|
// set up constants
|
|
const short anVertexIndices[6] = { 0, 1, 2, 0, 2, 3 };
|
|
|
|
// set up the leaf counts for each LOD
|
|
m_usNumLeafLods = m_pSpeedTree->GetNumLeafLodLevels( );
|
|
|
|
// create arrays for the number of LOD levels
|
|
//별로 안 좋다.
|
|
m_spLeafVertexBufferArray = new K3DVertexBufferSPtr[m_usNumLeafLods];
|
|
m_pLeavesUpdatedByCpu = new bool[m_usNumLeafLods];
|
|
|
|
for (unsigned int unLod = 0; unLod < m_usNumLeafLods; ++unLod)
|
|
{
|
|
m_pSpeedTree->GetGeometry(*m_pGeometryCache, SpeedTree_LeafGeometry, -1, -1, unLod);
|
|
m_pLeavesUpdatedByCpu[unLod] = false;
|
|
|
|
// if this level has no leaves, then skip it
|
|
unsigned short usLeafCount = m_pGeometryCache->m_sLeaves0.m_usLeafCount;
|
|
if (usLeafCount < 1)
|
|
continue;
|
|
|
|
// create the vertex buffer for storing leaf vertices
|
|
#if defined(WRAPPER_USE_GPU_WIND) && defined(WRAPPER_USE_GPU_LEAF_PLACEMENT)
|
|
m_spLeafVertexBufferArray[unLod] = m_pDevice->CreateVertexBufferSpeedTree( sizeof(SFVFLeafVertex), D3DUSAGE_WRITEONLY, D3DFVF_SPEEDTREE_LEAF_VERTEX, usLeafCount * 6 );
|
|
#else
|
|
m_spLeafVertexBufferArray[unLod] = m_pDevice->CreateVertexBufferSpeedTree( sizeof(SFVFLeafVertex), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_SPEEDTREE_LEAF_VERTEX, usLeafCount * 6 );
|
|
#endif
|
|
if( m_spLeafVertexBufferArray[unLod] == NULL || !m_spLeafVertexBufferArray[unLod]->IsValidVtx() ) continue;
|
|
|
|
// fill the vertex buffer by interleaving SpeedTree data
|
|
SFVFLeafVertex* pVertexBuffer = NULL;
|
|
int nVtxSize = 0;
|
|
#if defined(WRAPPER_USE_GPU_WIND) && defined(WRAPPER_USE_GPU_LEAF_PLACEMENT)
|
|
m_spLeafVertexBufferArray[unLod]->Lock( reinterpret_cast<void**>(&pVertexBuffer), nVtxSize );
|
|
#else
|
|
m_spLeafVertexBufferArray[unLod]->Lock( reinterpret_cast<void**>(&pVertexBuffer), nVtxSize, D3DLOCK_NOSYSLOCK | D3DLOCK_DISCARD );
|
|
#endif
|
|
assert(pVertexBuffer && "m_spLeafVertexBufferArray[unLod]->Lock( reinterpret_cast<void**>(&pVertexBuffer), nVtxSize );");
|
|
|
|
if( pVertexBuffer )
|
|
{
|
|
SFVFLeafVertex* pVertex = pVertexBuffer;
|
|
for (unsigned int unLeaf = 0; unLeaf < usLeafCount; ++unLeaf)
|
|
{
|
|
const CSpeedTreeRT::SGeometry::SLeaf* pLeaf = &(m_pGeometryCache->m_sLeaves0);
|
|
for (unsigned int unVert = 0; unVert < 6; ++unVert) // 6 verts == 2 triangles
|
|
{
|
|
// position
|
|
memcpy(pVertex->m_vPosition, &(pLeaf->m_pCenterCoords[unLeaf * 3]), sizeof(pVertex->m_vPosition));
|
|
|
|
#ifdef WRAPPER_USE_DYNAMIC_LIGHTING
|
|
// normal
|
|
memcpy(&pVertex->m_vNormal, &(pLeaf->m_pNormals[unLeaf * 3]), sizeof(pVertex->m_vNormal));
|
|
#else
|
|
// color
|
|
pVertex->m_dwDiffuseColor = AGBR2ARGB(pLeaf->m_pColors[unLeaf]);
|
|
#endif
|
|
|
|
// tex coord
|
|
memcpy(pVertex->m_fTexCoords, &(pLeaf->m_pLeafMapTexCoords[unLeaf][anVertexIndices[unVert] * 2]), sizeof(pVertex->m_fTexCoords));
|
|
|
|
// wind weights
|
|
#ifdef WRAPPER_USE_GPU_WIND
|
|
pVertex->m_fWindIndex = 4.0f * pLeaf->m_pWindMatrixIndices[unLeaf];
|
|
pVertex->m_fWindWeight = pLeaf->m_pWindWeights[unLeaf];
|
|
#endif
|
|
|
|
// gpu leaf placement data
|
|
#ifdef WRAPPER_USE_GPU_LEAF_PLACEMENT
|
|
pVertex->m_fLeafPlacementIndex = c_nVertexShader_LeafTables + pLeaf->m_pLeafClusterIndices[unLeaf] * 4.0f + anVertexIndices[unVert];
|
|
pVertex->m_fLeafScalarValue = m_pSpeedTree->GetLeafLodSizeAdjustments( )[unLod];
|
|
#endif
|
|
|
|
++pVertex;
|
|
}
|
|
|
|
}
|
|
m_spLeafVertexBufferArray[unLod]->Unlock( );
|
|
m_spLeafVertexBufferArray[unLod]->Backup();
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
// CSpeedTreeWrapper::Advance
|
|
|
|
void KSeqSpeedTree::Advance(bool bControlLod, float fLodLevel)
|
|
{
|
|
if( !m_bLoad ) return;
|
|
|
|
// DWORD Stime = GetSafeTickCount();
|
|
|
|
if(bControlLod)
|
|
{
|
|
m_pSpeedTree->SetLodLevel(fLodLevel);
|
|
}
|
|
else
|
|
{
|
|
// compute LOD level (based on distance from camera)
|
|
m_pSpeedTree->ComputeLodLevel( );
|
|
}
|
|
|
|
// compute wind
|
|
#ifdef WRAPPER_USE_CPU_WIND
|
|
m_pSpeedTree->ComputeWindEffects(true, true, true);
|
|
#endif
|
|
|
|
// _oprint( "Advance Time : %d\n", GetSafeTickCount()-Stime );
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
// CSpeedTreeWrapper::MakeInstance
|
|
|
|
XCriticalSection xCS;
|
|
|
|
bool KSeqSpeedTree::CopyFrom( KThreadResource* pResource )
|
|
{
|
|
THREAD_SYNCRONIZE( &xCS );
|
|
CopyFromTree( static_cast< KSeqSpeedTree* >( pResource ) );
|
|
|
|
return true;
|
|
}
|
|
|
|
void KSeqSpeedTree::CopyFromTree(KSeqSpeedTree* pSource)
|
|
{
|
|
// create a new object
|
|
KSeqSpeedTree* pInstance = this;
|
|
|
|
// make an instance of this object's SpeedTree
|
|
pInstance->m_bIsInstance = true;
|
|
pInstance->m_pSpeedTree = pSource->m_pSpeedTree->MakeInstance( );
|
|
pInstance->m_bLoad = pSource->m_bLoad;
|
|
|
|
if (pInstance->m_pSpeedTree)
|
|
{
|
|
//pInstance->m_pSpeedTree->ComputeLodLevel();
|
|
//pInstance->m_pSpeedTree->Compute(NULL, 0);
|
|
pInstance->m_fWindStrength = pSource->m_fWindStrength;
|
|
pInstance->m_fNearLod = pSource->m_fNearLod;
|
|
pInstance->m_fFarLod = pSource->m_fFarLod;
|
|
|
|
// use the same materials
|
|
pInstance->m_cBranchMaterial = pSource->m_cBranchMaterial;
|
|
pInstance->m_cLeafMaterial = pSource->m_cLeafMaterial;
|
|
pInstance->m_cFrondMaterial = pSource->m_cFrondMaterial;
|
|
pInstance->m_spTexBranchTexture = pSource->m_spTexBranchTexture;
|
|
pInstance->m_spTexShadow = pSource->m_spTexShadow;
|
|
pInstance->m_pTextureInfo = pSource->m_pTextureInfo;
|
|
|
|
// use the same geometry cache
|
|
pInstance->m_pGeometryCache = pSource->m_pGeometryCache;
|
|
|
|
// use the same buffers
|
|
pInstance->m_spBranchIndexBuffer = pSource->m_spBranchIndexBuffer;
|
|
pInstance->m_pBranchIndexCounts = pSource->m_pBranchIndexCounts;
|
|
pInstance->m_spBranchVertexBuffer = pSource->m_spBranchVertexBuffer;
|
|
pInstance->m_unBranchVertexCount = pSource->m_unBranchVertexCount;
|
|
|
|
pInstance->m_spFrondIndexBufferArray = pSource->m_spFrondIndexBufferArray;
|
|
pInstance->m_unNumFrondLods = m_unNumFrondLods;
|
|
pInstance->m_pFrondIndexCounts = pSource->m_pFrondIndexCounts;
|
|
pInstance->m_spFrondVertexBuffer = pSource->m_spFrondVertexBuffer;
|
|
pInstance->m_unFrondVertexCount = pSource->m_unFrondVertexCount;
|
|
|
|
pInstance->m_spLeafVertexBufferArray = pSource->m_spLeafVertexBufferArray;
|
|
pInstance->m_usNumLeafLods = pSource->m_usNumLeafLods;
|
|
pInstance->m_pLeavesUpdatedByCpu = pSource->m_pLeavesUpdatedByCpu;
|
|
|
|
// new stuff
|
|
memcpy(pInstance->m_afPos, pSource->m_afPos, sizeof(pInstance->m_afPos));
|
|
memcpy(pInstance->m_afBoundingBox, pSource->m_afBoundingBox, sizeof(pInstance->m_afBoundingBox));
|
|
pInstance->GetBoundCube()->SetCube( (K3DVertex *)pSource->m_BoundCube.GetVertices() );
|
|
pInstance->m_pInstanceOf = pSource;
|
|
|
|
pInstance->m_prBranch.SetGeometry( pInstance->m_pGeometryCache );
|
|
pInstance->m_prBranch.SetSpeedTree( pInstance->m_pSpeedTree );
|
|
pInstance->m_prBranch.SetSubMeshCount( 1 );
|
|
pInstance->m_prBranch.SetVertexBuffer( 0, pSource->m_spBranchVertexBuffer, SSpeedTreePrimitive::TREE_BRANCH,pSource-> m_unBranchVertexCount, pSource->m_pBranchIndexCounts );
|
|
if( pSource->m_spBranchVertexBuffer )
|
|
pInstance->m_prBranch.SetValid( pSource->m_spBranchVertexBuffer->IsValidVtx() );
|
|
pInstance->m_prBranch.SetIndexBuffer( 0, pSource->m_spBranchIndexBuffer );
|
|
//pInstance->m_prBranch.SetTextureCount( 1 );
|
|
pInstance->m_prBranch.SetTextureCount( 2 );
|
|
pInstance->m_prBranch.SetTexture( 0, pSource->m_spTexBranchTexture );
|
|
|
|
pInstance->m_prFrond.SetGeometry( pInstance->m_pGeometryCache );
|
|
pInstance->m_prFrond.SetSpeedTree( pInstance->m_pSpeedTree );
|
|
pInstance->m_prFrond.SetSubMeshCount( pSource->m_unNumFrondLods );
|
|
pInstance->m_prFrond.SetVertexBuffer( 0, pSource->m_spFrondVertexBuffer, SSpeedTreePrimitive::TREE_FROND, pSource->m_unFrondVertexCount, pSource->m_pFrondIndexCounts );
|
|
|
|
if( pSource->m_spFrondVertexBuffer )
|
|
pInstance->m_prFrond.SetValid( pSource->m_spFrondVertexBuffer->IsValidVtx() );
|
|
|
|
for(unsigned int i = 0; i < pSource->m_unNumFrondLods; i++)
|
|
{
|
|
pInstance->m_prFrond.SetIndexBuffer(i, pSource->m_spFrondIndexBufferArray[i]);
|
|
}
|
|
//pInstance->m_prFrond.SetTextureCount( 1 );
|
|
pInstance->m_prFrond.SetTextureCount( 2 );
|
|
pInstance->m_prFrond.SetTexture( 0, pSource->m_spTexFrondTexture );
|
|
|
|
pInstance->m_prLeaf.SetGeometry( pInstance->m_pGeometryCache );
|
|
pInstance->m_prLeaf.SetSpeedTree( pInstance->m_pSpeedTree );
|
|
pInstance->m_prLeaf.SetSubMeshCount( pSource->m_usNumLeafLods );
|
|
for( int i(0); pSource->m_usNumLeafLods>i; i++ )
|
|
{
|
|
pInstance->m_prLeaf.SetVertexBuffer( i,pSource-> m_spLeafVertexBufferArray[i], SSpeedTreePrimitive::TREE_LEAF, 0, NULL );
|
|
if( pSource->m_spLeafVertexBufferArray[i] && pSource->m_spLeafVertexBufferArray[i]->IsValidVtx() == false )
|
|
pInstance->m_prLeaf.SetValid( pSource->m_spLeafVertexBufferArray[i]->IsValidVtx() );
|
|
}
|
|
pInstance->m_prLeaf.SetTextureCount( 1 );
|
|
pInstance->m_prLeaf.SetTexture( 0, pSource->m_spTexLeafTexture );
|
|
|
|
#ifdef WRAPPER_BILLBOARD_MODE
|
|
pInstance->m_prBillboard.SetGeometry( pInstance->m_pGeometryCache );
|
|
pInstance->m_prBillboard.SetSpeedTree( pInstance->m_pSpeedTree );
|
|
pInstance->m_prBillboard.SetSubMeshCount( 1 );
|
|
pInstance->m_prBillboard.SetVertexBuffer( 0, NULL, SSpeedTreePrimitive::TREE_BILLBOARD, 0, 0 );
|
|
pInstance->m_prBillboard.SetIndexBuffer( 0, NULL );
|
|
pInstance->m_prBillboard.SetTextureCount( 1 );
|
|
//pInstance->m_prBillboard.SetTexture( 0, pSource->m_spTexCompositeMap );
|
|
pInstance->m_prBillboard.SetTexture( 0, pSource->m_spTexBillboardTexture );
|
|
#endif
|
|
|
|
pSource->m_vInstances.push_back(pInstance);
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, "SpeedTreeRT Error: %s\n", m_pSpeedTree->GetCurrentError( ));
|
|
}
|
|
}
|
|
|
|
//KSeqSpeedTree** KSeqSpeedTree::GetInstances(unsigned int& nCount)
|
|
//{
|
|
// nCount = (int)m_vInstances.size( );
|
|
// return &(m_vInstances[0]);
|
|
//}
|
|
|
|
void KSeqSpeedTree::SetupBranchForTreeType(void)
|
|
{
|
|
#ifdef WRAPPER_USE_DYNAMIC_LIGHTING
|
|
// set lighting material
|
|
|
|
//Primitive를 만들어서, Render로 따로 만들자~
|
|
|
|
/* K3DMaterial mat;
|
|
mat=*m_cBranchMaterial.GetMaterial();
|
|
mat.SetTransparency(1.0f); // Set transparency for branch
|
|
m_prBranch.SetMaterial( 0, &mat );
|
|
*/ m_prBranch.SetMaterial( 0, m_cBranchMaterial.GetMaterial() );
|
|
|
|
|
|
SetShaderConstants(m_pSpeedTree->GetBranchMaterial( ));
|
|
#endif
|
|
|
|
// set texture map
|
|
if (m_spTexBranchTexture)
|
|
m_prBranch.SetTexture( 0, m_spTexBranchTexture );
|
|
|
|
// bind shadow texture (if enabled)
|
|
#ifdef WRAPPER_RENDER_SELF_SHADOWS
|
|
if (m_spTexShadow)
|
|
m_prBranch.SetTexture(1, m_spTexShadow);
|
|
#endif
|
|
|
|
// if tree has branches, bind the buffers
|
|
if (m_pGeometryCache->m_sBranches.m_usVertexCount > 0)
|
|
{
|
|
//Primitive를 만들어서, Render로 따로 만들자~
|
|
// activate the branch vertex buffer
|
|
m_prBranch.SetVertexBuffer( 0, m_spBranchVertexBuffer, SSpeedTreePrimitive::TREE_BRANCH, m_unBranchVertexCount, m_pBranchIndexCounts );
|
|
// set the index buffer
|
|
m_prBranch.SetIndexBuffer( 0, m_spBranchIndexBuffer );
|
|
}
|
|
}
|
|
|
|
void KSeqSpeedTree::SetLodLevel( float fValue /*0.f~1.f*/ )
|
|
{
|
|
m_fCurrLodLevel = fValue;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
// CSpeedTreeWrapper::SetupFrondForTreeType
|
|
|
|
void KSeqSpeedTree::SetupFrondForTreeType(void)
|
|
{
|
|
#ifdef WRAPPER_USE_DYNAMIC_LIGHTING
|
|
// set lighting material
|
|
m_prFrond.SetMaterial( 0, m_cFrondMaterial.GetMaterial() );
|
|
SetShaderConstants(m_pSpeedTree->GetFrondMaterial( ));
|
|
#endif
|
|
|
|
// bind shadow texture (if enabled)
|
|
#ifdef WRAPPER_RENDER_SELF_SHADOWS
|
|
if (m_spTexShadow)
|
|
m_prFrond.SetTexture( 1, m_spTexShadow );
|
|
#endif
|
|
|
|
// if tree has fronds, bind the buffers
|
|
if (m_pGeometryCache->m_sFronds.m_usVertexCount > 0)
|
|
{
|
|
// activate the frond vertex buffer
|
|
m_prFrond.SetVertexBuffer( 0, m_spFrondVertexBuffer, SSpeedTreePrimitive::TREE_FROND, m_unFrondVertexCount, m_pFrondIndexCounts );
|
|
//// set the index buffer
|
|
for(unsigned int i = 0; i < m_unNumFrondLods; i++)
|
|
{
|
|
m_prFrond.SetIndexBuffer(i, m_spFrondIndexBufferArray[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
// CSpeedTreeWrapper::SetupLeafForTreeType
|
|
|
|
void KSeqSpeedTree::SetupLeafForTreeType(void)
|
|
{
|
|
#ifdef WRAPPER_USE_DYNAMIC_LIGHTING
|
|
// set lighting material
|
|
m_prLeaf.SetMaterial( 0, m_cLeafMaterial.GetMaterial() );
|
|
SetShaderConstants(m_pSpeedTree->GetLeafMaterial( ));
|
|
#endif
|
|
|
|
// send leaf tables to the gpu
|
|
#ifdef WRAPPER_USE_GPU_LEAF_PLACEMENT
|
|
UploadLeafTables(c_nVertexShader_LeafTables);
|
|
#endif
|
|
|
|
// bind shadow texture (if enabled)
|
|
#ifdef WRAPPER_RENDER_SELF_SHADOWS
|
|
if (m_spTexShadow)
|
|
m_prLeaf.SetTexture( 1, NULL );
|
|
#endif
|
|
for( int i(0); m_usNumLeafLods>i; i++ )
|
|
{
|
|
m_prLeaf.SetVertexBuffer( i, m_spLeafVertexBufferArray[i], SSpeedTreePrimitive::TREE_LEAF, 0, NULL );
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
// CSpeedTreeWrapper::UploadLeafTables
|
|
|
|
#ifdef WRAPPER_USE_GPU_LEAF_PLACEMENT
|
|
void KSeqSpeedTree::UploadLeafTables(unsigned int uiLocation)
|
|
{
|
|
// query leaf cluster table from RT
|
|
unsigned int uiEntryCount = 0;
|
|
const float* pTable = m_pSpeedTree->GetLeafBillboardTable(uiEntryCount);
|
|
|
|
// upload for vertex shader use
|
|
m_prLeaf.SetShaderTable( uiLocation, pTable, uiEntryCount / 4 );
|
|
}
|
|
#endif
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
// CSpeedTreeWrapper::EndLeafForTreeType
|
|
|
|
void KSeqSpeedTree::EndLeafForTreeType(void)
|
|
{
|
|
// reset flags for CPU data copying
|
|
for (unsigned int i = 0; i < m_usNumLeafLods; ++i)
|
|
m_pLeavesUpdatedByCpu[i] = false;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
// CSpeedTreeWrapper::RenderBillboards
|
|
|
|
void KSeqSpeedTree::RenderBillboards(void)
|
|
{
|
|
// // draw billboards in immediate mode (as close as directx gets to immediate mode)
|
|
//#ifdef WRAPPER_BILLBOARD_MODE
|
|
// PositionTree( );
|
|
//
|
|
// struct SBillboardVertex
|
|
// {
|
|
// float fX, fY, fZ;
|
|
// DWORD dColor;
|
|
// float fU, fV;
|
|
// };
|
|
//
|
|
// m_pSpeedTree->GetGeometry(*m_pGeometryCache, SpeedTree_BillboardGeometry);
|
|
// 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;
|
|
// SBillboardVertex sVertex[4] =
|
|
// {
|
|
// { 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] },
|
|
// };
|
|
// //m_pDevice->SetFVF(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1);
|
|
// //m_pDevice->SetRenderState(D3DRS_ALPHAREF, DWORD(m_pGeometryCache->m_sBillboard0.m_fAlphaTestValue));
|
|
// //m_pDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, sVertex, 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;
|
|
// SBillboardVertex sVertex[4] =
|
|
// {
|
|
// { 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] },
|
|
// };
|
|
// //m_pDevice->SetRenderState(D3DRS_ALPHAREF, DWORD(m_pGeometryCache->m_sBillboard1.m_fAlphaTestValue));
|
|
// //m_pDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, sVertex, 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], 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_pDevice->SetRenderState(D3DRS_ALPHAREF, DWORD(m_pGeometryCache->m_sHorizontalBillboard.m_fAlphaTestValue));
|
|
// //m_pDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, sVertex, sizeof(SBillboardVertex));
|
|
// }
|
|
//
|
|
//#endif
|
|
//#endif
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
// CSpeedTreeWrapper::CleanUpMemory
|
|
|
|
void KSeqSpeedTree::CleanUpMemory(void)
|
|
{
|
|
if (!m_bIsInstance)
|
|
m_pSpeedTree->DeleteTransientData( );
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
// CSpeedTreeWrapper::SetPos
|
|
|
|
void KSeqSpeedTree::SetPos(float x, float y,float z)
|
|
{
|
|
m_afPos.x = x;
|
|
m_afPos.y = y;
|
|
m_afPos.z = z;
|
|
|
|
K3DMatrixTranslation( m_matTransform, m_afPos.x, m_afPos.y, m_afPos.z );
|
|
|
|
if( m_bLoad ) m_pSpeedTree->SetTreePosition(m_afPos.x, m_afPos.y, m_afPos.z);
|
|
}
|
|
|
|
void KSeqSpeedTree::SetPos(const float* pPos)
|
|
{
|
|
m_afPos.x = pPos[0];
|
|
m_afPos.y = pPos[1];
|
|
m_afPos.z = pPos[2];
|
|
|
|
K3DMatrixTranslation( m_matTransform, m_afPos.x, m_afPos.y, m_afPos.z );
|
|
|
|
if( m_bLoad ) m_pSpeedTree->SetTreePosition(pPos[0], pPos[1], pPos[2]);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
// CSpeedTreeWrapper::PositionTree
|
|
|
|
void KSeqSpeedTree::PositionTree(void)
|
|
{
|
|
realizeTime();
|
|
// D3DXVECTOR3 vecPosition = m_pSpeedTree->GetTreePosition( );
|
|
//K3DMatrixIdentity(m_matResult);
|
|
//K3DMatrixTranslation( &m_matResult, m_matTransform._41, m_matTransform._42, m_matTransform._43 );
|
|
|
|
m_prBranch.SetTransform( &m_matResult, &m_matWorld );
|
|
m_prFrond.SetTransform( &m_matResult, &m_matWorld );
|
|
m_prLeaf.SetTransform( &m_matResult, &m_matWorld );
|
|
|
|
#ifdef WRAPPER_BILLBOARD_MODE
|
|
m_prBillboard.SetTransform(&m_matResult, &m_matWorld);
|
|
#endif
|
|
//// store translation for use in vertex shader
|
|
//m_vecConstant = D3DXVECTOR4(m_matResult._41, m_matResult._42, m_matResult._43, 0.0f);
|
|
|
|
//m_prBranch.SetShaderVecConstant( c_nVertexShader_TreePos, (float*)&m_vecConstant, 1 );
|
|
//m_prFrond.SetShaderVecConstant ( c_nVertexShader_TreePos, (float*)&m_vecConstant, 1 );
|
|
//m_prLeaf.SetShaderVecConstant ( c_nVertexShader_TreePos, (float*)&m_vecConstant, 1 );
|
|
//m_prBillboard.SetShaderVecConstant ( c_nVertexShader_TreePos, (float*) &m_vecConstant, 1);
|
|
|
|
////Sort 용으로 사용.
|
|
//m_prLeaf.SetCenterPosition( K3DVector( m_matResult._41, m_matResult._42, m_matResult._43 ) );
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
// CSpeedTreeWrapper::LoadTexture
|
|
|
|
K3DTexture* KSeqSpeedTree::LoadTexture(const char* pFilename)
|
|
{
|
|
//TODO : 리소스 옵션 로딩 추가 작업 중.
|
|
NX3LoadPack loadpack;
|
|
loadpack.Init();
|
|
|
|
if( KTextureManager::GetManager()->IsExistTexture( pFilename, &loadpack ) )
|
|
{
|
|
// sonador 4.3.1 텍스쳐 로딩시 널 참조 수정
|
|
K3DTexture* pTexture = KTextureManager::GetManager()->GetTexture( pFilename, &loadpack, true, KTextureManager::GetManager()->GetMipMapBiasLevel()-1 );
|
|
if( pTexture )
|
|
{
|
|
pTexture->Flags() |= TEXFLAG_SPEEDTREE;
|
|
return pTexture;
|
|
}
|
|
}
|
|
_oprint( "Resource Error: Speed Tree Texture Not Found - %s\n", pFilename );
|
|
return NULL;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
// CSpeedTreeWrapper::SetShaderConstants
|
|
|
|
void KSeqSpeedTree::SetShaderConstants(const float* pMaterial)
|
|
{
|
|
m_afUsefulConstants[0] = m_pSpeedTree->GetLeafLightingAdjustment();
|
|
m_afUsefulConstants[1] = 0.0f;
|
|
m_afUsefulConstants[2] = 0.0f;
|
|
m_afUsefulConstants[3] = 0.0f;
|
|
|
|
m_prBranch.SetShaderUsefulConstant( c_nVertexShader_LeafLightingAdjustment, m_afUsefulConstants, 1 );
|
|
m_prFrond.SetShaderUsefulConstant ( c_nVertexShader_LeafLightingAdjustment, m_afUsefulConstants, 1 );
|
|
m_prLeaf.SetShaderUsefulConstant ( c_nVertexShader_LeafLightingAdjustment, m_afUsefulConstants, 1 );
|
|
|
|
#ifdef WRAPPER_BILLBOARD_MODE
|
|
m_prBillboard.SetShaderUsefulConstant ( c_nVertexShader_LeafLightingAdjustment, m_afUsefulConstants, 1);
|
|
#endif
|
|
|
|
m_afMaterial[0] = pMaterial[0];
|
|
m_afMaterial[1] = pMaterial[1];
|
|
m_afMaterial[2] = pMaterial[2];
|
|
|
|
m_afMaterial[3] = 1.f; //m_afMaterial[3] = 1.f;
|
|
|
|
|
|
m_afMaterial[4] = pMaterial[3];
|
|
m_afMaterial[5] = pMaterial[4];
|
|
m_afMaterial[6] = pMaterial[5];
|
|
|
|
m_afMaterial[7] = 1.f; //m_afMaterial[7] = 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 );
|
|
|
|
#ifdef WRAPPER_BILLBOARD_MODE
|
|
m_prBillboard.SetShaderMaterial(c_nVertexShader_Material, m_afMaterial, 2);
|
|
#endif
|
|
}
|
|
|
|
|
|
////////////////////////////////////////
|
|
// Utility
|
|
|
|
|
|
void KSeqSpeedTree::SetCamera(const K3DVector cameraPos, const K3DVector cameraDirection) // CSpeedTree::SetCamera()를 실행한다
|
|
{
|
|
// 좌표 저장
|
|
m_afCameraPos=cameraPos;
|
|
m_afCameraDirection=cameraDirection;
|
|
|
|
// CSpeedTreeRT모듈에 카메라 위치 보내기
|
|
float afDirection[3], campos[3];
|
|
afDirection[0] = cameraDirection.x;
|
|
afDirection[1] = cameraDirection.y;
|
|
afDirection[2] = cameraDirection.z;
|
|
campos[0] = cameraPos.x;
|
|
campos[1] = cameraPos.y;
|
|
campos[2] = cameraPos.z;
|
|
|
|
CSpeedTreeRT::SetCamera(campos, afDirection);
|
|
}
|
|
|
|
void KSeqSpeedTree::SetCameraTargetPosition(const K3DVector targetPos) // 내부적으로 camera target위치를 저장한다 (카메라 가리는 나무 반투명 처리용)
|
|
{
|
|
m_afCameraTargetPos=targetPos;
|
|
}
|
|
|