1
0
forked from metin2/client

Upgraded to DirectX 9

This commit is contained in:
2024-03-28 22:27:09 +02:00
parent fb64ecafe7
commit a21139193e
110 changed files with 1604 additions and 3977 deletions

View File

@ -0,0 +1,246 @@
#include "StdAfx.h"
#include "CSpeedTreeDirectX.h"
#include <d3d9.h>
#include <d3d9types.h>
#include <directxsdk/d3dx9.h>
#include "VertexShaders.h"
#include "../eterBase/Timer.h"
#include "../eterLib/StateManager.h"
#include "../eterLib/Camera.h"
CSpeedTreeDirectX::CSpeedTreeDirectX() : m_dwBranchVertexShader(NULL), m_dwLeafVertexShader(NULL) {}
CSpeedTreeDirectX::~CSpeedTreeDirectX()
{
SAFE_RELEASE(m_dwBranchVertexShader);
SAFE_RELEASE(m_dwLeafVertexShader);
}
void CSpeedTreeDirectX::UploadWindMatrix(unsigned int uiLocation, const float* pMatrix) const
{
STATEMANAGER.SetVertexShaderConstant(uiLocation, pMatrix, 4);
}
void CSpeedTreeDirectX::UpdateCompundMatrix(const D3DXVECTOR3& c_rEyeVec, const D3DXMATRIX& c_rmatView, const D3DXMATRIX& c_rmatProj)
{
D3DXMATRIX matBlend;
D3DXMatrixIdentity(&matBlend);
D3DXMATRIX matBlendShader;
D3DXMatrixMultiply(&matBlendShader, &c_rmatView, &c_rmatProj);
float afDirection[3];
afDirection[0] = matBlendShader.m[0][2];
afDirection[1] = matBlendShader.m[1][2];
afDirection[2] = matBlendShader.m[2][2];
CSpeedTreeRT::SetCamera(c_rEyeVec, afDirection);
D3DXMatrixTranspose(&matBlendShader, &matBlendShader);
STATEMANAGER.SetVertexShaderConstant(c_nVertexShader_CompoundMatrix, (const float*)&matBlendShader, 4);
}
bool CSpeedTreeDirectX::SetRenderingDevice()
{
if (!InitVertexShaders())
return false;
const float c_afLightPosition[4] = { -0.707f, -0.300f, 0.707f, 0.0f };
const float c_afLightAmbient[4] = { 0.5f, 0.5f, 0.5f, 1.0f };
const float c_afLightDiffuse[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
const float c_afLightSpecular[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
float afLight1[] =
{
c_afLightPosition[0], c_afLightPosition[1], c_afLightPosition[2],
c_afLightDiffuse[0], c_afLightDiffuse[1], c_afLightDiffuse[2],
c_afLightAmbient[0], c_afLightAmbient[1], c_afLightAmbient[2],
c_afLightSpecular[0], c_afLightSpecular[1], c_afLightSpecular[2],
c_afLightPosition[3],
1.0f, 0.0f, 0.0f
};
CSpeedTreeRT::SetLightAttributes(0, afLight1);
CSpeedTreeRT::SetLightState(0, true);
return true;
}
void CSpeedTreeDirectX::Render(unsigned long ulRenderBitVector)
{
if (m_pMainTreeMap.empty())
return;
if (!(ulRenderBitVector & Forest_RenderToShadow) && !(ulRenderBitVector & Forest_RenderToMiniMap))
UpdateCompundMatrix(CCameraManager::Instance().GetCurrentCamera()->GetEye(), ms_matView, ms_matProj);
DWORD dwLightState = STATEMANAGER.GetRenderState(D3DRS_LIGHTING);
DWORD dwColorVertexState = STATEMANAGER.GetRenderState(D3DRS_COLORVERTEX);
DWORD dwFogVertexMode = STATEMANAGER.GetRenderState(D3DRS_FOGVERTEXMODE);
STATEMANAGER.SetRenderState(D3DRS_LIGHTING, FALSE);
STATEMANAGER.SetRenderState(D3DRS_COLORVERTEX, TRUE);
UINT uiCount;
TTreeMap::const_iterator itor = m_pMainTreeMap.begin();
while (itor != m_pMainTreeMap.end())
{
CSpeedTreeWrapper* pMainTree = (itor++)->second;
CSpeedTreeWrapper** ppInstances = pMainTree->GetInstances(uiCount);
for (UINT i = 0; i < uiCount; ++i)
{
ppInstances[i]->Advance();
}
}
STATEMANAGER.SetVertexShaderConstant(c_nVertexShader_Light, m_afLighting, 3);
STATEMANAGER.SetVertexShaderConstant(c_nVertexShader_Fog, m_afFog, 1);
if (ulRenderBitVector & Forest_RenderToShadow)
{
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
}
else
{
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
STATEMANAGER.SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
STATEMANAGER.SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
STATEMANAGER.SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_ANISOTROPIC);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE);
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
STATEMANAGER.SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
STATEMANAGER.SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
}
STATEMANAGER.SaveRenderState(D3DRS_ALPHATESTENABLE, TRUE);
STATEMANAGER.SaveRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER);
STATEMANAGER.SaveRenderState(D3DRS_CULLMODE, D3DCULL_CW);
if (STATEMANAGER.GetRenderState(D3DRS_FOGENABLE)){}
STATEMANAGER.SetFVF(D3DFVF_SPEEDTREE_BRANCH_VERTEX);
STATEMANAGER.SetVertexShader(m_dwBranchVertexShader);
if (ulRenderBitVector & Forest_RenderBranches)
{
itor = m_pMainTreeMap.begin();
while (itor != m_pMainTreeMap.end())
{
CSpeedTreeWrapper* pMainTree = (itor++)->second;
CSpeedTreeWrapper** ppInstances = pMainTree->GetInstances(uiCount);
pMainTree->SetupBranchForTreeType();
for (UINT i = 0; i < uiCount; ++i)
if (ppInstances[i]->isShow())
ppInstances[i]->RenderBranches();
}
}
STATEMANAGER.SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
if (ulRenderBitVector & Forest_RenderFronds)
{
itor = m_pMainTreeMap.begin();
while (itor != m_pMainTreeMap.end())
{
CSpeedTreeWrapper* pMainTree = (itor++)->second;
CSpeedTreeWrapper** ppInstances = pMainTree->GetInstances(uiCount);
pMainTree->SetupFrondForTreeType();
for (UINT i = 0; i < uiCount; ++i)
if (ppInstances[i]->isShow())
ppInstances[i]->RenderFronds();
}
}
if (ulRenderBitVector & Forest_RenderLeaves)
{
STATEMANAGER.SetFVF(D3DFVF_SPEEDTREE_LEAF_VERTEX);
STATEMANAGER.SetVertexShader(m_dwLeafVertexShader);
if (STATEMANAGER.GetRenderState(D3DRS_FOGENABLE)){}
if (ulRenderBitVector & Forest_RenderToShadow || ulRenderBitVector & Forest_RenderToMiniMap)
{
STATEMANAGER.SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_NOTEQUAL);
STATEMANAGER.SaveRenderState(D3DRS_ALPHAREF, 0x00000000);
}
itor = m_pMainTreeMap.begin();
while (itor != m_pMainTreeMap.end())
{
CSpeedTreeWrapper* pMainTree = (itor++)->second;
CSpeedTreeWrapper** ppInstances = pMainTree->GetInstances(uiCount);
pMainTree->SetupLeafForTreeType();
for (UINT i = 0; i < uiCount; ++i)
if (ppInstances[i]->isShow())
ppInstances[i]->RenderLeaves();
}
if (ulRenderBitVector & Forest_RenderToShadow || ulRenderBitVector & Forest_RenderToMiniMap)
{
STATEMANAGER.SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER);
STATEMANAGER.RestoreRenderState(D3DRS_ALPHAREF);
}
}
if (ulRenderBitVector & Forest_RenderBillboards)
{
STATEMANAGER.SetVertexShader(NULL);
STATEMANAGER.SetFVF(D3DFVF_SPEEDTREE_BILLBOARD_VERTEX);
STATEMANAGER.SetRenderState(D3DRS_LIGHTING, FALSE);
STATEMANAGER.SetRenderState(D3DRS_COLORVERTEX, FALSE);
itor = m_pMainTreeMap.begin();
while (itor != m_pMainTreeMap.end())
{
CSpeedTreeWrapper* pMainTree = (itor++)->second;
CSpeedTreeWrapper** ppInstances = pMainTree->GetInstances(uiCount);
pMainTree->SetupBranchForTreeType();
for (UINT i = 0; i < uiCount; ++i)
if (ppInstances[i]->isShow())
ppInstances[i]->RenderBillboards();
}
}
STATEMANAGER.SetRenderState(D3DRS_LIGHTING, dwLightState);
STATEMANAGER.SetRenderState(D3DRS_COLORVERTEX, dwColorVertexState);
STATEMANAGER.SetRenderState(D3DRS_FOGVERTEXMODE, dwFogVertexMode);
if (!(ulRenderBitVector & Forest_RenderToShadow))
{
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
}
STATEMANAGER.RestoreRenderState(D3DRS_ALPHATESTENABLE);
STATEMANAGER.RestoreRenderState(D3DRS_ALPHAFUNC);
STATEMANAGER.RestoreRenderState(D3DRS_CULLMODE);
}
bool CSpeedTreeDirectX::InitVertexShaders(void)
{
m_dwBranchVertexShader = LoadBranchShader(ms_lpd3dDevice);
m_dwLeafVertexShader = LoadLeafShader(ms_lpd3dDevice);
return true;
}

View File

@ -0,0 +1,23 @@
#pragma once
#include <map>
#include "SpeedTreeForest.h"
#include "SpeedTreeMaterial.h"
class CSpeedTreeDirectX : public CSpeedTreeForest, public CGraphicBase
{
public:
CSpeedTreeDirectX();
~CSpeedTreeDirectX();
void UploadWindMatrix(unsigned int uiLocation, const float* pMatrix) const;
bool SetRenderingDevice();
void Render(unsigned long ulRenderBitVector = Forest_RenderAll);
void UpdateCompundMatrix(const D3DXVECTOR3& c_rEyeVec, const D3DXMATRIX& c_rmatView, const D3DXMATRIX& c_rmatProj);
private:
bool InitVertexShaders();
private:
LPDIRECT3DVERTEXSHADER9 m_dwBranchVertexShader;
LPDIRECT3DVERTEXSHADER9 m_dwLeafVertexShader;
};

View File

@ -1,769 +0,0 @@
///////////////////////////////////////////////////////////////////////
// CSpeedGrassRT Class
//
// (c) 2003 IDV, Inc.
//
// *** INTERACTIVE DATA VISUALIZATION (IDV) PROPRIETARY INFORMATION ***
//
// This software is supplied under the terms of a license agreement or
// nondisclosure agreement with Interactive Data Visualization and may
// not be copied or disclosed except in accordance with the terms of
// that agreement.
//
// Copyright (c) 2001-2003 IDV, Inc.
// All Rights Reserved.
//
// IDV, Inc.
// 1233 Washington St. Suite 610
// Columbia, SC 29201
// Voice: (803) 799-1699
// Fax: (803) 931-0320
// Web: http://www.idvinc.com
#include "StdAfx.h"
#include "BoundaryShapeManager.h"
#ifdef USE_SPEEDGRASS
inline float VecInterpolate(float fStart, float fEnd, float fPercent)
{
return fStart + (fEnd - fStart) * fPercent;
}
#define VectorSinD(x) sinf((x) / 57.29578f)
#define VectorCosD(x) cosf((x) / 57.29578f)
using namespace std;
// macros
#ifndef max
#define max(a, b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef min
#define min(a, b) (((a) < (b)) ? (a) : (b))
#endif
// static variables
float CSpeedGrassRT::m_fLodFarDistance = 100.0f;
float CSpeedGrassRT::m_fLodTransitionLength = 37.5f;
float CSpeedGrassRT::m_afUnitBillboard[12] = { 0.0f };
float CSpeedGrassRT::m_afWindDir[4] = { 1.0f, 0.3f, 0.0f, 0.0f };
// camera
float CSpeedGrassRT::m_afCameraOut[3] = { 0.0f, 1.0f, 0.0f };
float CSpeedGrassRT::m_afCameraUp[3] = { 0.0f, 0.0f, 1.0f };
float CSpeedGrassRT::m_afCameraRight[3] = { 1.0f, 0.0f, 0.0f };
float CSpeedGrassRT::m_afCameraPos[3] = { 0.0f, 0.0f, 0.0f };
float CSpeedGrassRT::m_fFieldOfView = D3DXToRadian(40.0f);
float CSpeedGrassRT::m_fAspectRatio = 4.0f / 3.0f;
// culling
float CSpeedGrassRT::m_afFrustumBox[6] = { 0.0f };
float CSpeedGrassRT::m_afFrustumMin[2] = { FLT_MAX, FLT_MAX };
float CSpeedGrassRT::m_afFrustumMax[2] = { -FLT_MAX, -FLT_MAX };
float CSpeedGrassRT::m_afFrustumPlanes[5][4] = { 0.0f };
///////////////////////////////////////////////////////////////////////
// CSpeedGrassRT::SBlade::SBlade
CSpeedGrassRT::SBlade::SBlade( ) :
m_fSize(1.0f),
m_fNoise(0.0f),
m_fThrow(0.0f),
m_ucWhichTexture(0)
{
m_afBottomColor[0] = m_afBottomColor[1] = m_afBottomColor[2] = 1.0f;
m_afTopColor[0] = m_afTopColor[1] = m_afTopColor[2] = 1.0f;
}
///////////////////////////////////////////////////////////////////////
// CSpeedGrassRT::SRegion::SRegion
CSpeedGrassRT::SRegion::SRegion( ) :
m_bCulled(false),
m_fCullingRadius(1.0f)
{
m_afCenter[0] = m_afCenter[1] = m_afCenter[2] = 0.5f;
m_afMin[0] = m_afMin[1] = m_afMin[2] = 0.0f;
m_afMax[0] = m_afMax[1] = m_afMax[2] = 1.0f;
m_VertexBuffer.Destroy();
}
///////////////////////////////////////////////////////////////////////
// CSpeedGrassRT::CSpeedGrassRT
CSpeedGrassRT::CSpeedGrassRT( ) :
m_nNumRegions(0),
m_nNumRegionCols(0),
m_nNumRegionRows(0),
m_pRegions(NULL),
m_bAllRegionsCulled(false)
{
m_afBoundingBox[0] = m_afBoundingBox[1] = m_afBoundingBox[2] = 0.0f;
m_afBoundingBox[3] = m_afBoundingBox[4] = m_afBoundingBox[5] = 1.0f;
}
///////////////////////////////////////////////////////////////////////
// CSpeedGrassRT::~CSpeedGrassRT
CSpeedGrassRT::~CSpeedGrassRT( )
{
}
///////////////////////////////////////////////////////////////////////
// CSpeedGrassRT::DeleteRegions
void CSpeedGrassRT::DeleteRegions(void)
{
delete[] m_pRegions;
m_pRegions = NULL;
m_nNumRegions = 0;
}
///////////////////////////////////////////////////////////////////////
// CSpeedGrassRT::GetRegions
const CSpeedGrassRT::SRegion* CSpeedGrassRT::GetRegions(unsigned int& uiNumRegions)
{
uiNumRegions = m_nNumRegions;
return m_pRegions;
}
///////////////////////////////////////////////////////////////////////
// CSpeedGrassRT::ParseBsfFile
bool CSpeedGrassRT::ParseBsfFile(const char* pFilename, unsigned int nNumBlades, unsigned int uiRows, unsigned int uiCols, float fCollisionDistance)
{
bool bSuccess = false;
// copy region settings
m_nNumRegionCols = int(uiCols);
m_nNumRegionRows = int(uiRows);
// initialize bounding box
m_afBoundingBox[0] = m_afBoundingBox[1] = m_afBoundingBox[2] = FLT_MAX;
m_afBoundingBox[3] = m_afBoundingBox[4] = m_afBoundingBox[5] = -FLT_MAX;
CBoundaryShapeManager cManager;
vector<SBlade> vSceneBlades;
if (cManager.LoadBsfFile(pFilename))
{
for (unsigned int i = 0; i < nNumBlades; ++i)
{
SBlade sBlade;
// try to place a blade
if (cManager.RandomPoint(sBlade.m_afPos[0], sBlade.m_afPos[1]))
{
sBlade.m_afPos[2] = Height(sBlade.m_afPos[0], sBlade.m_afPos[1], sBlade.m_afNormal);
// CVec3 cNormal(sBlade.m_afNormal[0], sBlade.m_afNormal[1], sBlade.m_afNormal[2]);
// cNormal.Normalize( );
// cNormal[2] = -cNormal[2];
// memcpy(sBlade.m_afNormal, cNormal, 3 * sizeof(float));
D3DXVECTOR3 v3Normal(sBlade.m_afNormal[0], sBlade.m_afNormal[1], sBlade.m_afNormal[2]);
D3DXVec3Normalize(&v3Normal, &v3Normal);
v3Normal.z = -v3Normal.z;
sBlade.m_afNormal[0] = v3Normal.x;
sBlade.m_afNormal[1] = v3Normal.y;
sBlade.m_afNormal[2] = v3Normal.z;
// check against overall scene bounding box
for (int nAxis = 0; nAxis < 3; ++nAxis)
{
m_afBoundingBox[nAxis] = min(m_afBoundingBox[nAxis], sBlade.m_afPos[nAxis]);
m_afBoundingBox[nAxis + 3] = max(m_afBoundingBox[nAxis + 3], sBlade.m_afPos[nAxis]);
}
// set bottom and top color
float fHeightPercent = Color(sBlade.m_afPos[0], sBlade.m_afPos[1], sBlade.m_afNormal, sBlade.m_afTopColor, sBlade.m_afBottomColor);
sBlade.m_fSize = VecInterpolate(c_fMinBladeSize, c_fMaxBladeSize, fHeightPercent);
// assign which blade texture map
sBlade.m_ucWhichTexture = GetRandom(0, c_nNumBladeMaps - 1);
// compute wind effects
sBlade.m_fNoise = GetRandom(c_fMinBladeNoise, c_fMaxBladeNoise);
sBlade.m_fThrow = GetRandom(c_fMinBladeThrow, c_fMaxBladeThrow);
// store all blades together
vSceneBlades.push_back(sBlade);
}
}
bSuccess = true;
}
else
fprintf(stderr, "%s\n", cManager.GetCurrentError( ).c_str( ));
if (bSuccess)
CreateRegions(vSceneBlades, fCollisionDistance);
return bSuccess;
}
///////////////////////////////////////////////////////////////////////
// CSpeedGrassRT::CustomPlacement
//
// Use this function to perform custom grass blade placement. Feel free
// to add parameters as necessary but be sure to call CreateRegions( )
// at the end of the function to set up the SpeedGrass region system.
bool CSpeedGrassRT::CustomPlacement(unsigned int uiRows, unsigned int uiCols)
{
// copy region settings (do not remove)
m_nNumRegionCols = int(uiCols);
m_nNumRegionRows = int(uiRows);
// initialize bounding box (do not remove)
m_afBoundingBox[0] = m_afBoundingBox[1] = m_afBoundingBox[2] = FLT_MAX;
m_afBoundingBox[3] = m_afBoundingBox[4] = m_afBoundingBox[5] = -FLT_MAX;
// place one blade as an example
vector<SBlade> vSceneBlades;
SBlade sBlade;
sBlade.m_afPos[0] = 0.0f;
sBlade.m_afPos[1] = 0.0f;
sBlade.m_afPos[2] = 0.0f;
sBlade.m_afNormal[0] = 0.0f;
sBlade.m_afNormal[1] = 0.0f;
sBlade.m_afNormal[2] = 1.0f;
// check against overall scene bounding box (always do this)
for (int nAxis = 0; nAxis < 3; ++nAxis)
{
m_afBoundingBox[nAxis] = min(m_afBoundingBox[nAxis], sBlade.m_afPos[nAxis]);
m_afBoundingBox[nAxis + 3] = max(m_afBoundingBox[nAxis + 3], sBlade.m_afPos[nAxis]);
}
// set bottom and top color
memcpy(sBlade.m_afBottomColor, sBlade.m_afNormal, 12);
memcpy(sBlade.m_afTopColor, sBlade.m_afNormal, 12);
// assign which blade texture map
sBlade.m_ucWhichTexture = GetRandom(0, c_nNumBladeMaps - 1);
// compute wind effects
sBlade.m_fNoise = GetRandom(c_fMinBladeNoise, c_fMaxBladeNoise);
sBlade.m_fThrow = GetRandom(c_fMinBladeThrow, c_fMaxBladeThrow);
// compute dimensions
sBlade.m_fSize = GetRandom(c_fMinBladeSize, c_fMaxBladeSize);
// store all blades together
vSceneBlades.push_back(sBlade);
// create regions based on blades (do not remove)
CreateRegions(vSceneBlades);
// true = success, false = error
return true;
}
///////////////////////////////////////////////////////////////////////
// CSpeedGrassRT::GetLodParams
void CSpeedGrassRT::GetLodParams(float& fFarDistance, float& fTransitionLength)
{
fFarDistance = m_fLodFarDistance;
fTransitionLength = m_fLodTransitionLength;
}
///////////////////////////////////////////////////////////////////////
// CSpeedGrassRT::SetLodParams
void CSpeedGrassRT::SetLodParams(float fFarDistance, float fTransitionLength)
{
m_fLodFarDistance = fFarDistance;
m_fLodTransitionLength = fTransitionLength;
}
///////////////////////////////////////////////////////////////////////
// CSpeedGrassRT::Cull
//
// Using a two-dimensional projection, determine which regions
// intersect with the view frustum (+Z is assumed to be up)
void CSpeedGrassRT::Cull(void)
{
// convert raw frustum min and max values into min and max region cell indices
int anFrustumCellsMin[2], anFrustumCellsMax[2];
ConvertCoordsToCell(m_afFrustumMin, anFrustumCellsMin);
ConvertCoordsToCell(m_afFrustumMax, anFrustumCellsMax);
// set all regions to culled, modify later
for (int i = 0; i < m_nNumRegions; ++i)
m_pRegions[i].m_bCulled = true;
int nRegionsDrawn = 0;
// is the entire set of regions culled?
if ((anFrustumCellsMin[0] < 0 && anFrustumCellsMax[0] < 0) ||
(anFrustumCellsMin[0] >= m_nNumRegionCols && anFrustumCellsMax[0] >= m_nNumRegionCols) ||
(anFrustumCellsMin[1] < 0 && anFrustumCellsMax[1] < 0) ||
(anFrustumCellsMin[1] >= m_nNumRegionRows && anFrustumCellsMax[1] >= m_nNumRegionRows))
m_bAllRegionsCulled = true;
else
{
// clip cell values
anFrustumCellsMin[0] = max(anFrustumCellsMin[0], 0);
anFrustumCellsMin[1] = max(anFrustumCellsMin[1], 0);
anFrustumCellsMax[0] = min(anFrustumCellsMax[0], m_nNumRegionCols - 1);
anFrustumCellsMax[1] = min(anFrustumCellsMax[1], m_nNumRegionRows - 1);
for (i = anFrustumCellsMin[0]; i <= anFrustumCellsMax[0]; ++i)
for (int j = anFrustumCellsMin[1]; j <= anFrustumCellsMax[1]; ++j)
{
SRegion* pRegion = m_pRegions + GetRegionIndex(j, i);
pRegion->m_bCulled = OutsideFrustum(pRegion);
}
m_bAllRegionsCulled = false;
}
}
///////////////////////////////////////////////////////////////////////
// CSpeedGrassRT::SetWindDirection
void CSpeedGrassRT::SetWindDirection(const float* pWindDir)
{
memcpy(m_afWindDir, pWindDir, 3 * sizeof(float));
m_afWindDir[3] = 0.0f;
}
///////////////////////////////////////////////////////////////////////
// CSpeedGrassRT::GetWindDirection
const float* CSpeedGrassRT::GetWindDirection(void)
{
return m_afWindDir;
}
///////////////////////////////////////////////////////////////////////
// CSpeedGrassRT::GetCameraPos
const float* CSpeedGrassRT::GetCameraPos(void)
{
return m_afCameraPos;
}
///////////////////////////////////////////////////////////////////////
// CSpeedGrassRT::SetCamera
void CSpeedGrassRT::SetCamera(const float* pPosition, const double* pModelviewMatrix)
{
memcpy(m_afCameraPos, pPosition, 3 * sizeof(float));
// "right" vector
m_afCameraRight[0] = pModelviewMatrix[0];
m_afCameraRight[1] = pModelviewMatrix[4];
m_afCameraRight[2] = pModelviewMatrix[8];
// "up" vector
m_afCameraUp[0] = pModelviewMatrix[1];
m_afCameraUp[1] = pModelviewMatrix[5];
m_afCameraUp[2] = pModelviewMatrix[9];
// "out of screen" vector
m_afCameraOut[0] = pModelviewMatrix[2];
m_afCameraOut[1] = pModelviewMatrix[6];
m_afCameraOut[2] = pModelviewMatrix[10];
// with direction changed, billboard turns
ComputeUnitBillboard( );
// compute new frustum box
ComputeFrustum( );
}
///////////////////////////////////////////////////////////////////////
// CSpeedGrassRT::SetPerspective
void CSpeedGrassRT::SetPerspective(float fAspectRatio, float fFieldOfView)
{
m_fAspectRatio = fAspectRatio;
m_fFieldOfView = D3DXToRadian(fAspectRatio * fFieldOfView);
}
///////////////////////////////////////////////////////////////////////
// CSpeedGrassRT::CreateRegions
void CSpeedGrassRT::CreateRegions(const vector<SBlade>& vSceneBlades, float fCollisionDistance)
{
// create regions based on overall extents
DeleteRegions( );
m_nNumRegions = int(m_nNumRegionRows * m_nNumRegionCols);
m_pRegions = new SRegion[m_nNumRegions];
// run through all regions, computing extents for each
float fCellWidth = (m_afBoundingBox[3] - m_afBoundingBox[0]) / m_nNumRegionCols;
float fCellHeight = (m_afBoundingBox[4] - m_afBoundingBox[1]) / m_nNumRegionRows;
float fY = m_afBoundingBox[1];
for (int nRow = 0; nRow < m_nNumRegionRows; ++nRow)
{
float fX = m_afBoundingBox[0];
for (int nCol = 0; nCol < m_nNumRegionCols; ++nCol)
{
SRegion* pRegion = m_pRegions + GetRegionIndex(nRow, nCol);
// compute extents
pRegion->m_afMin[0] = fX;
pRegion->m_afMax[0] = fX + fCellWidth;
pRegion->m_afMin[1] = fY;
pRegion->m_afMax[1] = fY + fCellHeight;
// compute center
pRegion->m_afCenter[0] = 0.5f * (pRegion->m_afMin[0] + pRegion->m_afMax[0]);
pRegion->m_afCenter[1] = 0.5f * (pRegion->m_afMin[1] + pRegion->m_afMax[1]);
// compute culling radius
pRegion->m_fCullingRadius = 1.1f * sqrt(
((pRegion->m_afMax[0] - pRegion->m_afCenter[0]) * (pRegion->m_afMax[0] - pRegion->m_afCenter[0])) +
((pRegion->m_afMax[1] - pRegion->m_afCenter[1]) * (pRegion->m_afMax[1] - pRegion->m_afCenter[1]))
);
fX += fCellWidth;
}
fY += fCellHeight;
}
// assign each blade of grass to its particular region
for (vector<SBlade>::const_iterator iBlade = vSceneBlades.begin( ); iBlade != vSceneBlades.end( ); ++iBlade)
{
// convert position to row/col index
float fPercentAlongX = (iBlade->m_afPos[0] - m_afBoundingBox[0]) / (m_afBoundingBox[3] - m_afBoundingBox[0]);
float fPercentAlongY = (iBlade->m_afPos[1] - m_afBoundingBox[1]) / (m_afBoundingBox[4] - m_afBoundingBox[1]);
// clip values
unsigned int uiCol = min(fPercentAlongX * m_nNumRegionCols, m_nNumRegionCols - 1);
unsigned int uiRow = min(fPercentAlongY * m_nNumRegionRows, m_nNumRegionRows - 1);
m_pRegions[GetRegionIndex(uiRow, uiCol)].m_vBlades.push_back(*iBlade);
}
// compute z extents (now that the blades are in)
for (int i = 0; i < m_nNumRegions; ++i)
{
SRegion* pRegion = m_pRegions + i;
pRegion->m_afMin[2] = FLT_MAX;
pRegion->m_afMax[2] = -FLT_MAX;
for (vector<SBlade>::iterator iBlade = pRegion->m_vBlades.begin( ); iBlade != pRegion->m_vBlades.end( ); ++iBlade)
{
pRegion->m_afMin[2] = min(pRegion->m_afMin[2], iBlade->m_afPos[2]);
pRegion->m_afMax[2] = max(pRegion->m_afMax[2], iBlade->m_afPos[2] + iBlade->m_fSize);
}
pRegion->m_afCenter[0] = 0.5f * (pRegion->m_afMin[0] + pRegion->m_afMax[0]);
pRegion->m_afCenter[1] = 0.5f * (pRegion->m_afMin[1] + pRegion->m_afMax[1]);
pRegion->m_afCenter[2] = 0.5f * (pRegion->m_afMin[2] + pRegion->m_afMax[2]);
// compute culling radius
pRegion->m_fCullingRadius = 1.1f * sqrt(
((pRegion->m_afMax[0] - pRegion->m_afCenter[0]) * (pRegion->m_afMax[0] - pRegion->m_afCenter[0])) +
((pRegion->m_afMax[1] - pRegion->m_afCenter[1]) * (pRegion->m_afMax[1] - pRegion->m_afCenter[1])) +
((pRegion->m_afMax[2] - pRegion->m_afCenter[2]) * (pRegion->m_afMax[2] - pRegion->m_afCenter[2]))
);
}
// collision detection
if (fCollisionDistance > 0.0f)
{
fCollisionDistance *= fCollisionDistance;
for (int nRow = 0; nRow < m_nNumRegionRows; ++nRow)
{
float fX = m_afBoundingBox[0];
for (int nCol = 0; nCol < m_nNumRegionCols; ++nCol)
{
SRegion* pRegion = m_pRegions + GetRegionIndex(nRow, nCol);
// check each blade against all other blades in the region
for (DWORD i = 0; i < pRegion->m_vBlades.size( ); ++i)
{
float fX = pRegion->m_vBlades[i].m_afPos[0];
float fY = pRegion->m_vBlades[i].m_afPos[1];
bool bCollision = false;
for (DWORD j = 0; j < pRegion->m_vBlades.size( ) && !bCollision; ++j)
{
if (i != j)
{
float fDistance = (fX - pRegion->m_vBlades[j].m_afPos[0]) * (fX - pRegion->m_vBlades[j].m_afPos[0]) + (fY - pRegion->m_vBlades[j].m_afPos[1]) * (fY - pRegion->m_vBlades[j].m_afPos[1]);
if (fDistance < fCollisionDistance)
bCollision = true;
}
}
// delete the blade if necessary and adjust the main loop counter to compensate
if (bCollision)
pRegion->m_vBlades.erase(pRegion->m_vBlades.begin( ) + i--);
}
}
}
}
}
//////////////////////////////////////////////////////////////////////////
// CSpeedGrassRT::RotateAxisFromIdentity
__forceinline void CSpeedGrassRT::RotateAxisFromIdentity(D3DXMATRIX * pMat, const float & c_fAngle, const D3DXVECTOR3 & c_rv3Axis)
{
float s = VectorSinD(c_fAngle);
float c = VectorCosD(c_fAngle);
float t = 1.0 - c;
float x = c_rv3Axis.x;
float y = c_rv3Axis.y;
float z = c_rv3Axis.z;
pMat->_11 = t * x * x + c;
pMat->_12 = t * x * y + s * z;
pMat->_13 = t * x * z - s * y;
pMat->_21 = t * x * y - s * z;
pMat->_22 = t * y * y + c;
pMat->_23 = t * y * z + s * x;
pMat->_31 = t * x * z + s * y;
pMat->_32 = t * y * z - s * x;
pMat->_33 = t * z * z + c;
}
///////////////////////////////////////////////////////////////////////
// CSpeedGrassRT::ComputeFrustum
void CSpeedGrassRT::ComputeFrustum(void)
{
// setup useful vectors
// CVec3 cCameraIn(-m_afCameraOut[0], -m_afCameraOut[1], -m_afCameraOut[2]);
// CVec3 cCameraUp(m_afCameraUp[0], m_afCameraUp[1], m_afCameraUp[2]);
// CVec3 cCameraRight(m_afCameraRight[0], m_afCameraRight[1], m_afCameraRight[2]);
// CVec3 cCameraPos(m_afCameraPos[0], m_afCameraPos[1], m_afCameraPos[2]);
// CVec3 cFarPoint = cCameraPos + cCameraIn * (m_fLodFarDistance + m_fLodTransitionLength);
D3DXVECTOR3 cCameraIn(-m_afCameraOut[0], -m_afCameraOut[1], -m_afCameraOut[2]);
D3DXVECTOR3 cCameraUp(m_afCameraUp[0], m_afCameraUp[1], m_afCameraUp[2]);
D3DXVECTOR3 cCameraRight(m_afCameraRight[0], m_afCameraRight[1], m_afCameraRight[2]);
D3DXVECTOR3 cCameraPos(m_afCameraPos[0], m_afCameraPos[1], m_afCameraPos[2]);
D3DXVECTOR3 cFarPoint = cCameraPos + cCameraIn * (m_fLodFarDistance + m_fLodTransitionLength);
// far plane
// memcpy(m_afFrustumPlanes[0], cCameraIn, 3 * sizeof(float));
// m_afFrustumPlanes[0][3] = -(cCameraIn ^ cFarPoint); // operator^ is dot product
m_afFrustumPlanes[0][0] = cCameraIn.x;
m_afFrustumPlanes[0][1] = cCameraIn.y;
m_afFrustumPlanes[0][2] = cCameraIn.z;
m_afFrustumPlanes[0][3] = -D3DXVec3Dot(&cCameraIn, &cFarPoint); // operator^ is dot product
// CRotTransform cRotate(true);
D3DXMATRIX cRotate;
D3DXMatrixIdentity(&cRotate);
D3DXVECTOR3 cNormal;
// upper plane
// cRotate.RotateAxisFromIdentity(VecRad2Deg(0.5f * m_fFieldOfView * m_fAspectRatio + c_fHalfPi) , cCameraRight);
// CVec3 cNormal = cCameraIn * cRotate;
// cNormal.Normalize( );
// memcpy(m_afFrustumPlanes[1], cNormal, 3 * sizeof(float));
// m_afFrustumPlanes[1][3] = -(cNormal ^ cCameraPos);
// left plane
// cRotate.RotateAxisFromIdentity(VecRad2Deg(0.5f * m_fFieldOfView + c_fHalfPi) , cCameraUp);
// cNormal = cCameraIn * cRotate;
// cNormal.Normalize( );
// memcpy(m_afFrustumPlanes[2], cNormal, 3 * sizeof(float));
// m_afFrustumPlanes[2][3] = -(cNormal ^ cCameraPos);
// lower plane
// cRotate.RotateAxisFromIdentity(-VecRad2Deg(0.5f * m_fFieldOfView * m_fAspectRatio + c_fHalfPi) , cCameraRight);
// cNormal = cCameraIn * cRotate;
// cNormal.Normalize( );
// memcpy(m_afFrustumPlanes[3], cNormal, 3 * sizeof(float));
// m_afFrustumPlanes[3][3] = -(cNormal ^ cCameraPos);
// right plane
// cRotate.RotateAxisFromIdentity(-VecRad2Deg(0.5f * m_fFieldOfView + c_fHalfPi) , cCameraUp);
// cNormal = cCameraIn * cRotate;
// cNormal.Normalize( );
// memcpy(m_afFrustumPlanes[4], cNormal, 3 * sizeof(float));
// m_afFrustumPlanes[4][3] = -(cNormal ^ cCameraPos);
RotateAxisFromIdentity(&cRotate, D3DXToDegree(0.5f * m_fFieldOfView * m_fAspectRatio + c_fHalfPi), cCameraRight);
D3DXVec3TransformCoord(&cNormal, &cCameraIn, &cRotate);
D3DXVec3Normalize(&cNormal, &cNormal);
m_afFrustumPlanes[1][0] = cNormal.x;
m_afFrustumPlanes[1][1] = cNormal.y;
m_afFrustumPlanes[1][2] = cNormal.z;
m_afFrustumPlanes[1][3] = -D3DXVec3Dot(&cNormal, &cCameraPos); // operator^ is dot product
RotateAxisFromIdentity(&cRotate, D3DXToDegree(0.5f * m_fFieldOfView + c_fHalfPi), cCameraUp);
D3DXVec3TransformCoord(&cNormal, &cCameraIn, &cRotate);
D3DXVec3Normalize(&cNormal, &cNormal);
m_afFrustumPlanes[2][0] = cNormal.x;
m_afFrustumPlanes[2][1] = cNormal.y;
m_afFrustumPlanes[2][2] = cNormal.z;
m_afFrustumPlanes[2][3] = -D3DXVec3Dot(&cNormal, &cCameraPos); // operator^ is dot product
RotateAxisFromIdentity(&cRotate, -D3DXToDegree(0.5f * m_fFieldOfView * m_fAspectRatio + c_fHalfPi), cCameraRight);
D3DXVec3TransformCoord(&cNormal, &cCameraIn, &cRotate);
D3DXVec3Normalize(&cNormal, &cNormal);
m_afFrustumPlanes[3][0] = cNormal.x;
m_afFrustumPlanes[3][1] = cNormal.y;
m_afFrustumPlanes[3][2] = cNormal.z;
m_afFrustumPlanes[3][3] = -D3DXVec3Dot(&cNormal, &cCameraPos); // operator^ is dot product
RotateAxisFromIdentity(&cRotate, -D3DXToDegree(0.5f * m_fFieldOfView + c_fHalfPi), cCameraUp);
D3DXVec3TransformCoord(&cNormal, &cCameraIn, &cRotate);
D3DXVec3Normalize(&cNormal, &cNormal);
m_afFrustumPlanes[4][0] = cNormal.x;
m_afFrustumPlanes[4][1] = cNormal.y;
m_afFrustumPlanes[4][2] = cNormal.z;
m_afFrustumPlanes[4][3] = -D3DXVec3Dot(&cNormal, &cCameraPos); // operator^ is dot product
// frustum points
float fFrustumHeight = (m_fLodFarDistance + m_fLodTransitionLength) * tanf(0.5f * m_fFieldOfView);
float fFrustumWidth = (m_fLodFarDistance + m_fLodTransitionLength) * tanf(0.5f * m_fFieldOfView * m_fAspectRatio);
// CVec3 acFrustum[5];
D3DXVECTOR3 acFrustum[5];
acFrustum[0] = cCameraPos;
acFrustum[1] = cFarPoint + cCameraRight * fFrustumWidth + cCameraUp * fFrustumHeight;
acFrustum[2] = cFarPoint - cCameraRight * fFrustumWidth + cCameraUp * fFrustumHeight;
acFrustum[3] = cFarPoint - cCameraRight * fFrustumWidth - cCameraUp * fFrustumHeight;
acFrustum[4] = cFarPoint + cCameraRight * fFrustumWidth - cCameraUp * fFrustumHeight;
// find min/max (x,y) coordinates
m_afFrustumMin[0] = m_afFrustumMin[1] = FLT_MAX;
m_afFrustumMax[0] = m_afFrustumMax[1] = -FLT_MAX;
for (int i = 0; i < 5; ++i)
{
m_afFrustumMin[0] = min(m_afFrustumMin[0], acFrustum[i][0]);
m_afFrustumMax[0] = max(m_afFrustumMax[0], acFrustum[i][0]);
m_afFrustumMin[1] = min(m_afFrustumMin[1], acFrustum[i][1]);
m_afFrustumMax[1] = max(m_afFrustumMax[1], acFrustum[i][1]);
}
}
///////////////////////////////////////////////////////////////////////
// CSpeedGrassRT::ComputeUnitBillboard
void CSpeedGrassRT::ComputeUnitBillboard(void)
{
// float fAzimuth = D3DXToDegree(atan2(-m_afCameraOut[1], -m_afCameraOut[0]));
float fAzimuth = atan2(-m_afCameraOut[1], -m_afCameraOut[0]);
// CRotTransform cTrans;
// cTrans.RotateZ(fAzimuth);
//
// static CVec3 afCorner1(0.0f, 0.5f, 1.0f);
// static CVec3 afCorner2(0.0f, -0.5f, 1.0f);
// static CVec3 afCorner3(0.0f, -0.5f, 0.0f);
// static CVec3 afCorner4(0.0f, 0.5f, 0.0f);
//
// CVec3 afNewCorner1 = afCorner1 * cTrans;
// CVec3 afNewCorner2 = afCorner2 * cTrans;
// CVec3 afNewCorner3 = afCorner3 * cTrans;
// CVec3 afNewCorner4 = afCorner4 * cTrans;
//
// memcpy(m_afUnitBillboard + 0, afNewCorner1.m_afData, 3 * sizeof(float));
// memcpy(m_afUnitBillboard + 3, afNewCorner2.m_afData, 3 * sizeof(float));
// memcpy(m_afUnitBillboard + 6, afNewCorner3.m_afData, 3 * sizeof(float));
// memcpy(m_afUnitBillboard + 9, afNewCorner4.m_afData, 3 * sizeof(float));
D3DXMATRIX cTrans;
D3DXMatrixRotationZ(&cTrans, fAzimuth);
static D3DXVECTOR3 afCorner1(0.0f, 0.5f, 1.0f);
static D3DXVECTOR3 afCorner2(0.0f, -0.5f, 1.0f);
static D3DXVECTOR3 afCorner3(0.0f, -0.5f, 0.0f);
static D3DXVECTOR3 afCorner4(0.0f, 0.5f, 0.0f);
D3DXVECTOR3 afNewCorner1;
D3DXVECTOR3 afNewCorner2;
D3DXVECTOR3 afNewCorner3;
D3DXVECTOR3 afNewCorner4;
D3DXVec3TransformCoord(&afNewCorner1, &afCorner1, &cTrans);
D3DXVec3TransformCoord(&afNewCorner2, &afCorner2, &cTrans);
D3DXVec3TransformCoord(&afNewCorner3, &afCorner3, &cTrans);
D3DXVec3TransformCoord(&afNewCorner4, &afCorner4, &cTrans);
m_afUnitBillboard[0] = afNewCorner1.x;
m_afUnitBillboard[1] = afNewCorner1.y;
m_afUnitBillboard[2] = afNewCorner1.z;
m_afUnitBillboard[3] = afNewCorner2.x;
m_afUnitBillboard[4] = afNewCorner2.y;
m_afUnitBillboard[5] = afNewCorner2.z;
m_afUnitBillboard[6] = afNewCorner3.x;
m_afUnitBillboard[7] = afNewCorner3.y;
m_afUnitBillboard[8] = afNewCorner3.z;
m_afUnitBillboard[9] = afNewCorner4.x;
m_afUnitBillboard[10] = afNewCorner4.y;
m_afUnitBillboard[11] = afNewCorner4.z;
}
///////////////////////////////////////////////////////////////////////
// CSpeedGrassRT::ConvertCoordsToCell
void CSpeedGrassRT::ConvertCoordsToCell(const float* pCoords, int* pGridCoords) const
{
float fPercentAlongX = (pCoords[0] - m_afBoundingBox[0]) / (m_afBoundingBox[3] - m_afBoundingBox[0]);
float fPercentAlongY = (pCoords[1] - m_afBoundingBox[1]) / (m_afBoundingBox[4] - m_afBoundingBox[1]);
if (fPercentAlongX < 0.0f)
pGridCoords[0] = -1;
else if (fPercentAlongX > 1.0f)
pGridCoords[0] = m_nNumRegionCols;
else
pGridCoords[0] = fPercentAlongX * m_nNumRegionCols;
if (fPercentAlongY < 0.0f)
pGridCoords[1] = -1;
else if (fPercentAlongY > 1.0f)
pGridCoords[1] = m_nNumRegionRows;
else
pGridCoords[1] = fPercentAlongY * m_nNumRegionRows;
}
///////////////////////////////////////////////////////////////////////
// CSpeedGrassRT::OutsideFrustum
__forceinline bool CSpeedGrassRT::OutsideFrustum(CSpeedGrassRT::SRegion* pRegion)
{
bool bOutside = false;
for (int i = 0; i < 5 && !bOutside; ++i)
if (m_afFrustumPlanes[i][0] * pRegion->m_afCenter[0] +
m_afFrustumPlanes[i][1] * pRegion->m_afCenter[1] +
m_afFrustumPlanes[i][2] * pRegion->m_afCenter[2] +
m_afFrustumPlanes[i][3] > pRegion->m_fCullingRadius)
bOutside = true;
return bOutside;
}
#endif // USE_SPEEDGRASS

View File

@ -1,180 +0,0 @@
///////////////////////////////////////////////////////////////////////
// CSpeedGrassRT Class
//
// (c) 2003 IDV, Inc.
//
// *** INTERACTIVE DATA VISUALIZATION (IDV) PROPRIETARY INFORMATION ***
//
// This software is supplied under the terms of a license agreement or
// nondisclosure agreement with Interactive Data Visualization and may
// not be copied or disclosed except in accordance with the terms of
// that agreement.
//
// Copyright (c) 2001-2003 IDV, Inc.
// All Rights Reserved.
//
// IDV, Inc.
// 1233 Washington St. Suite 610
// Columbia, SC 29201
// Voice: (803) 799-1699
// Fax: (803) 931-0320
// Web: http://www.idvinc.com
#pragma once
//#include <vector>
//#include "Constants.h"
//#include "../Common Source/IdvVertexBuffer.h"
#ifdef USE_SPEEDGRASS
// forward reference
class CIdvTerrain;
///////////////////////////////////////////////////////////////////////
// class CSpeedGrassRT declaration
class CSpeedGrassRT
{
public:
CSpeedGrassRT( );
virtual ~CSpeedGrassRT( );
///////////////////////////////////////////////////////////////////////
// struct SBlade
struct SBlade
{
SBlade( );
// geometry
float m_afPos[3];
float m_afNormal[3];
float m_fSize;
unsigned char m_ucWhichTexture;
// wind
float m_fNoise;
float m_fThrow;
// color
float m_afBottomColor[3];
float m_afTopColor[3];
};
///////////////////////////////////////////////////////////////////////
// struct SRegion
struct SRegion
{
SRegion( );
// dimensions
float m_afCenter[3];
float m_afMin[3];
float m_afMax[3];
// culling
bool m_bCulled;
float m_fCullingRadius;
// grass/brush blades
std::vector<SBlade> m_vBlades;
// CIdvVertexBuffer* m_pVertexBuffer;
CGraphicVertexBuffer m_VertexBuffer;
};
void DeleteRegions(void);
const SRegion* GetRegions(unsigned int& uiNumRegions);
bool ParseBsfFile(const char* pFilename, unsigned int nNumBlades, unsigned int uiRows, unsigned int uiCols, float fCollisionDistance = 0.0f);
bool CustomPlacement(unsigned int uiRows, unsigned int uiCols);
//////////////////////////////////////////////////////////////////////////
// Utility
static void RotateAxisFromIdentity(D3DXMATRIX * pMat, const float & c_fAngle, const D3DXVECTOR3 & c_rv3Axis);
///////////////////////////////////////////////////////////////////////
// Geometry
static const float* GetUnitBillboard(void) { return m_afUnitBillboard; }
///////////////////////////////////////////////////////////////////////
// LOD
static void GetLodParams(float& fFarDistance, float& fTransitionLength);
static void SetLodParams(float fFarDistance, float fTransitionLength);
///////////////////////////////////////////////////////////////////////
// Culling
bool AllRegionsAreCulled(void) const { return m_bAllRegionsCulled; }
void Cull(void);
///////////////////////////////////////////////////////////////////////
// Wind
static void SetWindDirection(const float* pWindDir);
static const float* GetWindDirection(void);
///////////////////////////////////////////////////////////////////////
// Camera
static const float* GetCameraPos(void);
static void SetCamera(const float* pPosition, const double* pModelviewMatrix);
static void SetPerspective(float fAspectRatio, float fFieldOfView);
///////////////////////////////////////////////////////////////////////
// Terrain hugging
virtual float Color(float fX, float fY, const float* pNormal, float* pTopColor, float* pBottomColor) const { return 0.0f; }
virtual float Height(float fX, float fY, float* pNormal) const { return 0.0f; }
protected:
void CreateRegions(const std::vector<SBlade>& vSceneBlades, float fCollisionDistance = 0.0f);
static void ComputeFrustum(void);
static void ComputeUnitBillboard(void);
void ConvertCoordsToCell(const float* pCoords, int* pGridCoords) const;
unsigned int GetRegionIndex(unsigned int uiRow, unsigned int uiCol) const { return uiRow * m_nNumRegionCols + uiCol; }
static bool OutsideFrustum(SRegion* pRegion);
// general
static float m_fLodFarDistance;
static float m_fLodTransitionLength;
static float m_afUnitBillboard[12];
static float m_afWindDir[4];
// regions
int m_nNumRegions;
int m_nNumRegionCols;
int m_nNumRegionRows;
SRegion* m_pRegions;
// camera
static float m_afCameraOut[3];
static float m_afCameraRight[3];
static float m_afCameraUp[3];
static float m_afCameraPos[3];
static float m_fFieldOfView;
static float m_fAspectRatio;
// culling
static float m_afFrustumBox[6];
static float m_afFrustumMin[2];
static float m_afFrustumMax[2];
static float m_afFrustumPlanes[5][4];
float m_afBoundingBox[6];
bool m_bAllRegionsCulled;
};
extern float VecInterpolate(float fStart, float fEnd, float fPercent);
#endif // USE_SPEEDGRASS

View File

@ -1,322 +0,0 @@
///////////////////////////////////////////////////////////////////////
// CSpeedGrassWrapper Class
//
// (c) 2003 IDV, Inc.
//
// *** INTERACTIVE DATA VISUALIZATION (IDV) PROPRIETARY INFORMATION ***
//
// This software is supplied under the terms of a license agreement or
// nondisclosure agreement with Interactive Data Visualization and may
// not be copied or disclosed except in accordance with the terms of
// that agreement.
//
// Copyright (c) 2001-2003 IDV, Inc.
// All Rights Reserved.
//
// IDV, Inc.
// 1233 Washington St. Suite 610
// Columbia, SC 29201
// Voice: (803) 799-1699
// Fax: (803) 931-0320
// Web: http://www.idvinc.com
#include "StdAfx.h"
#include <stdlib.h>
#include <stdio.h>
#include <vector>
//#include "../Common Source/extgl.h"
//#include "SpeedGrassWrapper.h"
//#include "Scene.h"
//#include "../Common Source/nv_dds.h"
//#include "../Common Source/Random.h"
//#include "TextureLayers.h"
using namespace std;
#ifdef USE_SPEEDGRASS
///////////////////////////////////////////////////////////////////////
// CSpeedGrassWrapper::CSpeedGrassWrapper
CSpeedGrassWrapper::CSpeedGrassWrapper() : m_pMapOutdoor(NULL), m_lpD3DTexure8(NULL)//m_uiTexture(0)
{
}
///////////////////////////////////////////////////////////////////////
// CSpeedGrassWrapper::~CSpeedGrassWrapper
CSpeedGrassWrapper::~CSpeedGrassWrapper( )
{
}
///////////////////////////////////////////////////////////////////////
// CSpeedGrassWrapper::Draw
int CSpeedGrassWrapper::Draw(float fDensity)
{
int nTriangleCount = 0;
// // determine which regions are visible
// Cull( );
//
// // setup opengl state
// glPushAttrib(GL_ENABLE_BIT);
// glDisable(GL_CULL_FACE);
// glDisable(GL_BLEND);
//
// glEnable(GL_TEXTURE_2D);
// glBindTexture(GL_TEXTURE_2D, m_uiTexture);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
//
// glEnable(GL_ALPHA_TEST);
// glAlphaFunc(GL_GREATER, 0.4f);
// glDisable(GL_LIGHTING);
//
// unsigned int uiCount = 0;
// unsigned int uiNumRegions = 0;
// const SRegion* pRegions = GetRegions(uiNumRegions);
//
// // setup for vertex buffer rendering (enable client buffers)
// CIdvVertexBuffer::Enable(true);
// if (uiNumRegions > 0)
// pRegions[0].m_pVertexBuffer->EnableClientStates( );
//
// // run through the regions and render those that aren't culled
// for (unsigned int i = 0; i < uiNumRegions; ++i)
// {
// if (!pRegions[i].m_bCulled)
// {
// pRegions[i].m_pVertexBuffer->Bind( );
// unsigned int uiNumBlades = int(fDensity * pRegions[i].m_vBlades.size( ));
// glDrawArrays(GL_QUADS, 0, uiNumBlades * 4);
// nTriangleCount += uiNumBlades * 2;
// }
// }
//
// // disable client buffers
// if (uiNumRegions > 0)
// pRegions[0].m_pVertexBuffer->DisableClientStates( );
// CIdvVertexBuffer::Disable(true);
//
// // restore opengl state
// glPopAttrib( );
return nTriangleCount;
}
///////////////////////////////////////////////////////////////////////
// CSpeedGrassWrapper::InitFromBsfFile
bool CSpeedGrassWrapper::InitFromBsfFile(const char* pFilename,
unsigned int nNumBlades,
unsigned int uiRows,
unsigned int uiCols,
float fCollisionDistance)
{
bool bSuccess = false;
if (pFilename)
{
// use SpeedGrass's built-in parse function
if (ParseBsfFile(pFilename, nNumBlades, uiRows, uiCols, fCollisionDistance))
bSuccess = true;
}
InitGraphics( );
return bSuccess;
}
///////////////////////////////////////////////////////////////////////
// CSpeedGrassWrapper::Color
float CSpeedGrassWrapper::Color(float fX, float fY, const float* pNormal, float* pTopColor, float* pBottomColor) const
{
const float c_fColorAdjust = 0.3f; // controls how much the color of the top vertices of each grass blade can vary
const float c_fColorThrow = 1.0f; // controls how much the r, g, and b components can vary
const float c_fColorRandomness = 0.01f; // controls how much the r, g, and b components can vary
const float c_TopLight = 0.75f;
float afLowColor[4] = { 0.0f }, afHighColor[4] = { 0.0f };
if (m_pMapOutdoor->GetBrushColor(fX, fY, afLowColor, afHighColor))
{
pBottomColor[0] = afLowColor[2];
pBottomColor[1] = afLowColor[1];
pBottomColor[2] = afLowColor[0];
float fColorThrow = GetRandom(0.0f, c_fColorThrow);
pTopColor[0] = VecInterpolate(pBottomColor[0], afHighColor[2], fColorThrow) + GetRandom(-c_fColorRandomness, c_fColorRandomness);
pTopColor[1] = VecInterpolate(pBottomColor[1], afHighColor[1], fColorThrow) + GetRandom(-c_fColorRandomness, c_fColorRandomness);
pTopColor[2] = VecInterpolate(pBottomColor[2], afHighColor[0], fColorThrow) + GetRandom(-c_fColorRandomness, c_fColorRandomness);
float fLargest = pTopColor[0];
if (pTopColor[1] > fLargest)
fLargest = pTopColor[1];
if (pTopColor[2] > fLargest)
fLargest = pTopColor[2];
if (fLargest > 1.0f)
{
pTopColor[0] /= fLargest;
pTopColor[1] /= fLargest;
pTopColor[2] /= fLargest;
}
pTopColor[0] = max(0.0f, pTopColor[0]);
pTopColor[1] = max(0.0f, pTopColor[1]);
pTopColor[2] = max(0.0f, pTopColor[2]);
}
return afLowColor[3];
}
///////////////////////////////////////////////////////////////////////
// CSpeedGrassWrapper::Height
float CSpeedGrassWrapper::Height(float fX, float fY, float* pNormal) const
{
float fHeight = 0.0f;
float afPos[3] = { fX, fY, 0.0f };
fHeight = m_pMapOutdoor->GetHeight(afPos);
pNormal[0] = 0.0f;
pNormal[1] = 0.0f;
pNormal[2] = 1.0f;
return fHeight;
}
///////////////////////////////////////////////////////////////////////
// CSpeedGrassWrapper::InitGraphics
void CSpeedGrassWrapper::InitGraphics(void)
{
// load texture
// m_uiTexture = LoadDDS((c_strDataPath + string("brush_2.dds")).c_str( ));
CGraphicImage * pImage = (CGraphicImage *) CResourceManager::Instance().GetResourcePointer("D:/ymir work/special/brush_2.dds");
m_GrassImageInstance.SetImagePointer(pImage);
m_lpD3DTexure8 = m_GrassImageInstance.GetTexturePointer()->GetD3DTexture();
// prepare static vertex buffers
for (int i = 0; i < m_nNumRegions; ++i)
{
SRegion* pRegion = m_pRegions + i;
// pRegion->m_pVertexBuffer = new CIdvVertexBuffer;
// setup up temporary buffer to copy later
const int c_nNumCorners = 4;
unsigned int uiNumBlades = pRegion->m_vBlades.size( );
unsigned int uiBufferSize = uiNumBlades * c_nNumCorners * c_nGrassVertexTotalSize;
unsigned char* pBuffer = new unsigned char[uiBufferSize];
// setup initial pointers for individual attribute copying
float* pTexCoords0 = reinterpret_cast<float*>(pBuffer + 0);
float* pTexCoords1 = reinterpret_cast<float*>(pTexCoords0 + c_nGrassVertexTexture0Size * uiNumBlades * c_nNumCorners / sizeof(float));
unsigned char* pColors = (unsigned char*) pTexCoords1 + c_nGrassVertexTexture1Size * uiNumBlades * c_nNumCorners;
float* pPositions = reinterpret_cast<float*>(pColors + c_nGrassVertexColorSize * uiNumBlades * c_nNumCorners);
for (vector<SBlade>::const_iterator iBlade = pRegion->m_vBlades.begin( ); iBlade != pRegion->m_vBlades.end( ); ++iBlade)
{
float fS1 = float(iBlade->m_ucWhichTexture) / c_nNumBladeMaps;
float fS2 = float(iBlade->m_ucWhichTexture + 1) / c_nNumBladeMaps;
for (int nCorner = 0; nCorner < c_nNumCorners; ++nCorner)
{
// texcoord 0
switch (nCorner)
{
case 0:
pTexCoords0[0] = fS2;
pTexCoords0[1] = 1.0f;
break;
case 1:
pTexCoords0[0] = fS1;
pTexCoords0[1] = 1.0f;
break;
case 2:
pTexCoords0[0] = fS1;
pTexCoords0[1] = 0.0f;
break;
case 3:
pTexCoords0[0] = fS2;
pTexCoords0[1] = 0.0f;
break;
default:
assert(false);
}
pTexCoords0 += c_nGrassVertexTexture0Size / sizeof(float);
// texcoord 1
switch (nCorner)
{
case 0:
pTexCoords1[0] = c_nShaderGrassBillboard;
pTexCoords1[2] = iBlade->m_fThrow;
break;
case 1:
pTexCoords1[0] = c_nShaderGrassBillboard + 1;
pTexCoords1[2] = iBlade->m_fThrow;
break;
case 2:
pTexCoords1[0] = c_nShaderGrassBillboard + 2;
pTexCoords1[2] = 0.0f;
break;
case 3:
pTexCoords1[0] = c_nShaderGrassBillboard + 3;
pTexCoords1[2] = 0.0f;
break;
default:
assert(false);
}
// same for all corners
pTexCoords1[1] = iBlade->m_fSize;
pTexCoords1[3] = iBlade->m_fNoise;
pTexCoords1 += c_nGrassVertexTexture1Size / sizeof(float);
// color
unsigned long ulColor = 0;
if (nCorner == 0 || nCorner == 1)
ulColor = (int(iBlade->m_afTopColor[0] * 255.0f) << 0) +
(int(iBlade->m_afTopColor[1] * 255.0f) << 8) +
(int(iBlade->m_afTopColor[2] * 255.0f) << 16) +
0xff000000;
else
ulColor = (int(iBlade->m_afBottomColor[0] * 255.0f) << 0) +
(int(iBlade->m_afBottomColor[1] * 255.0f) << 8) +
(int(iBlade->m_afBottomColor[2] * 255.0f) << 16) +
0xff000000;
memcpy(pColors, &ulColor, c_nGrassVertexColorSize);
pColors += c_nGrassVertexColorSize;
// position
memcpy(pPositions, iBlade->m_afPos, c_nGrassVertexPositionSize);
pPositions += c_nGrassVertexPositionSize / sizeof(float);
}
}
// assert((unsigned char*) pTexCoords0 - pBuffer == c_nGrassVertexTexture0Size * uiNumBlades * c_nNumCorners);
// assert(pTexCoords1 - pTexCoords0 == (c_nGrassVertexTexture1Size * uiNumBlades * c_nNumCorners) / sizeof(float));
// assert(pColors - (unsigned char*) pTexCoords1 == c_nGrassVertexColorSize * uiNumBlades * c_nNumCorners);
// assert((unsigned char*) pPositions - pColors == c_nGrassVertexPositionSize * uiNumBlades * c_nNumCorners);
// pRegion->m_pVertexBuffer->SetBuffer(pBuffer, uiBufferSize, true);
// pRegion->m_pVertexBuffer->SetStride(CIdvVertexBuffer::VERTEX_TEXCOORD0, 2, GL_FLOAT, 0, 0);
// pRegion->m_pVertexBuffer->SetStride(CIdvVertexBuffer::VERTEX_TEXCOORD1, 4, GL_FLOAT, 0, (unsigned char*) pTexCoords0 - pBuffer);
// pRegion->m_pVertexBuffer->SetStride(CIdvVertexBuffer::VERTEX_COLOR, 4, GL_UNSIGNED_BYTE, 0, (unsigned char*) pTexCoords1 - pBuffer);
// pRegion->m_pVertexBuffer->SetStride(CIdvVertexBuffer::VERTEX_POSITION, 3, GL_FLOAT, 0, pColors - pBuffer);
DWORD dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1;
// pRegion->m_VertexBuffer.Create();
delete[] pBuffer;
}
}
#endif // USE_SPEEDGRASS

View File

@ -1,64 +0,0 @@
///////////////////////////////////////////////////////////////////////
// CSpeedGrassWrapper Class
//
// (c) 2003 IDV, Inc.
//
// *** INTERACTIVE DATA VISUALIZATION (IDV) PROPRIETARY INFORMATION ***
//
// This software is supplied under the terms of a license agreement or
// nondisclosure agreement with Interactive Data Visualization and may
// not be copied or disclosed except in accordance with the terms of
// that agreement.
//
// Copyright (c) 2001-2003 IDV, Inc.
// All Rights Reserved.
//
// IDV, Inc.
// 1233 Washington St. Suite 610
// Columbia, SC 29201
// Voice: (803) 799-1699
// Fax: (803) 931-0320
// Web: http://www.idvinc.com
#pragma once
//#include "SpeedGrassRT.h"
#ifdef USE_SPEEDGRASS
//#include "../Common Source/IdvVertexBuffer.h"
//#include <vector>
// forward reference
//class CScene;
class CMapOutdoor;
///////////////////////////////////////////////////////////////////////
// class CSpeedGrassWrapper declaration
class CSpeedGrassWrapper : public CSpeedGrassRT
{
public:
CSpeedGrassWrapper( );
virtual ~CSpeedGrassWrapper( );
void SetMapOutdoor(CMapOutdoor* pMapOutdoor) { m_pMapOutdoor = pMapOutdoor; }
int Draw(float fDensity);
bool InitFromBsfFile(const char* pFilename,
unsigned int nNumBlades,
unsigned int uiRows,
unsigned int uiCols,
float fCollisionDistance);
private:
virtual float Color(float fX, float fY, const float* pNormal, float* pTopColor, float* pBottomColor) const;
virtual float Height(float fX, float fY, float* pNormal) const;
void InitGraphics(void);
CMapOutdoor * m_pMapOutdoor;
LPDIRECT3DTEXTURE8 m_lpD3DTexure8;
CGraphicImageInstance m_GrassImageInstance;
};
#endif // USE_SPEEDGRASS

View File

@ -22,15 +22,9 @@
#pragma once
const int c_nNumWindMatrices = 4;
const int c_nNumInstancesPerModel = 10;
const float c_fForestSize = 200.0f;
const float c_fSpacingTolerance = 30.0f;
const int c_nMaxPlacementIterations = 500;
const int c_nDefaultAlphaTestValue = 84;
const float c_fNearLodFactor = 2.0f;
const float c_fFarLodFactor = 9.0f;
const float c_fBenchmarkPeriod = 1.0f;
const int c_nNumWindMatrices = 40;
const float c_fNearLodFactor = 1000000000.0f;
const float c_fFarLodFactor = 50000000000.0f;
// vertex shader constant locations
const int c_nVertexShader_LeafLightingAdjustment = 70;
@ -42,14 +36,6 @@ const int c_nVertexShader_WindMatrices = 54;
const int c_nVertexShader_LeafTables = 4;
const int c_nVertexShader_Fog = 85;
// lighting
const float c_afLightPosition[4] = { -0.707f, 0.0f, 0.707f, 0.0f };
const float c_afLightAmbient[4] = { 0.5f, 0.5f, 0.5f, 1.0f };
const float c_afLightDiffuse[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
const float c_afLightSpecular[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
const float c_afLightGlobalAmbient[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
// setup lighting (enable ONE of the two below)
#define WRAPPER_USE_STATIC_LIGHTING
//#define WRAPPER_USE_DYNAMIC_LIGHTING
@ -91,8 +77,8 @@ const float c_afLightGlobalAmbient[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
#endif
// loading from STF or clones/instances? (enable ONE of the two below)
//#define WRAPPER_FOREST_FROM_STF
#define WRAPPER_FOREST_FROM_INSTANCES
#define WRAPPER_FOREST_FROM_STF
//#define WRAPPER_FOREST_FROM_INSTANCES
#if defined WRAPPER_FOREST_FROM_STF && defined WRAPPER_FOREST_FROM_INSTANCES
#error Please define exactly one loading mechanism
@ -103,18 +89,18 @@ const float c_afLightGlobalAmbient[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
//#define WRAPPER_RENDER_HORIZONTAL_BILLBOARD
// render self-shadows
#define WRAPPER_RENDER_SELF_SHADOWS
//#define WRAPPER_RENDER_SELF_SHADOWS
// use fog
#define WRAPPER_USE_FOG
// derived constants
#ifdef WRAPPER_USE_GPU_WIND
#define BRANCHES_USE_SHADERS
#define FRONDS_USE_SHADERS
#define LEAVES_USE_SHADERS
#endif
#ifdef WRAPPER_USE_GPU_LEAF_PLACEMENT
#define LEAVES_USE_SHADERS
#endif
//#ifdef WRAPPER_USE_GPU_WIND
// #define BRANCHES_USE_SHADERS
// #define FRONDS_USE_SHADERS
// #define LEAVES_USE_SHADERS
//#endif
//
//#ifdef WRAPPER_USE_GPU_LEAF_PLACEMENT
// #define LEAVES_USE_SHADERS
//#endif

View File

@ -87,6 +87,7 @@ BOOL CSpeedTreeForest::GetMainTree(DWORD dwCRC, CSpeedTreeWrapper ** ppMainTree,
if (!pTree->LoadTree(c_pszFileName, (const BYTE *) c_pvData, file.Size()))
{
delete pTree;
pTree = nullptr;
return FALSE;
}
@ -230,63 +231,12 @@ void CSpeedTreeForest::SetupWindMatrices(float fTimeInSecs)
afMatrix[9] = -fSinX;
afMatrix[10] = fCosX * fCosY;
afMatrix[15] = 1.0f;
#ifdef WRAPPER_USE_CPU_WIND
CSpeedTreeRT::SetWindMatrix(j, afMatrix);
#endif
#ifdef WRAPPER_USE_GPU_WIND
// graphics API specific
UploadWindMatrix(c_nVertexShader_WindMatrices + j * 4, afMatrix);
#endif
}
// track wind strength
fOldStrength = m_fWindStrength;
}
///////////////////////////////////////////////////////////////////////
// CSpeedTreeForest::SetLodLimits
/*
void CSpeedTreeForest::SetLodLimits(void)
{
// find tallest tree
float fTallest = -1.0f;
TTreeMap::iterator itor = m_pMainTreeMap.begin();
UINT uiCount;
while (itor != m_pMainTreeMap.end())
{
CSpeedTreeWrapper * pMainTree = (itor++)->second;
CSpeedTreeWrapper ** ppInstances = pMainTree->GetInstances(uiCount);
float fHeight;
fHeight = pMainTree->GetBoundingBox()[5] - pMainTree->GetBoundingBox()[0];
fTallest = __max(fHeight, fTallest);
for (UINT i = 0; i < uiCount; ++i)
{
fHeight = ppInstances[i]->GetBoundingBox()[5] - ppInstances[i]->GetBoundingBox()[0];
fTallest = __max(fHeight, fTallest);
}
}
itor = m_pMainTreeMap.begin();
while (itor != m_pMainTreeMap.end())
{
CSpeedTreeWrapper * pMainTree = (itor++)->second;
CSpeedTreeWrapper ** ppInstances = pMainTree->GetInstances(uiCount);
pMainTree->GetSpeedTree()->SetLodLimits(fTallest * c_fNearLodFactor, fTallest * c_fFarLodFactor);
for (UINT i = 0; i < uiCount; ++i)
ppInstances[i]->GetSpeedTree()->SetLodLimits(fTallest * c_fNearLodFactor, fTallest * c_fFarLodFactor);
}
}
*/
void CSpeedTreeForest::SetLight(const float * afDirection, const float * afAmbient, const float * afDiffuse)
{
m_afLighting[0] = afDirection[0];

View File

@ -32,7 +32,7 @@
///////////////////////////////////////////////////////////////////////
// Include Files
#include <SpeedTreeRT.h>
#include <speedtree/SpeedTreeRT.h>
#include "SpeedTreeWrapper.h"
#include <vector>
@ -52,7 +52,7 @@
///////////////////////////////////////////////////////////////////////
// class CSpeedTreeForest declaration
class CSpeedTreeForest
class CSpeedTreeForest : public CSingleton<CSpeedTreeForest>
{
public:
typedef std::map<DWORD, CSpeedTreeWrapper *> TTreeMap;
@ -71,8 +71,6 @@ class CSpeedTreeForest
CSpeedTreeWrapper * CreateInstance(float x, float y, float z, DWORD dwTreeCRC, const char * c_pszTreeName);
void DeleteInstance(CSpeedTreeWrapper * pTree);
//void SetLodLimits(void);
void UpdateSystem(float fCurrentTime);
void Clear();
@ -90,8 +88,10 @@ class CSpeedTreeForest
// overridden by specific graphics API
virtual void UploadWindMatrix(unsigned int uiLocation, const float* pMatrix) const = 0;
virtual void Render(unsigned long ulRenderBitVector) = 0;
virtual void Render(unsigned long ulRenderBitVector = Forest_RenderAll) = 0;
virtual bool SetRenderingDevice() = 0;
virtual void UpdateCompundMatrix(const D3DXVECTOR3& c_rEyeVec, const D3DXMATRIX& c_rmatView, const D3DXMATRIX& c_rmatProj) = 0;
protected:
TTreeMap m_pMainTreeMap;

View File

@ -1,344 +0,0 @@
///////////////////////////////////////////////////////////////////////
// CSpeedTreeForestDirectX8 Class
//
// (c) 2003 IDV, Inc.
//
// This class is provided to illustrate one way to incorporate
// SpeedTreeRT into an OpenGL application. All of the SpeedTreeRT
// calls that must be made on a per tree basis are done by this class.
// Calls that apply to all trees (i.e. static SpeedTreeRT functions)
// are made in the functions in main.cpp.
//
//
// *** INTERACTIVE DATA VISUALIZATION (IDV) PROPRIETARY INFORMATION ***
//
// This software is supplied under the terms of a license agreement or
// nondisclosure agreement with Interactive Data Visualization and may
// not be copied or disclosed except in accordance with the terms of
// that agreement.
//
// Copyright (c) 2001-2003 IDV, Inc.
// All Rights Reserved.
//
// IDV, Inc.
// 1233 Washington St. Suite 610
// Columbia, SC 29201
// Voice: (803) 799-1699
// Fax: (803) 931-0320
// Web: http://www.idvinc.com
#include "StdAfx.h"
#include <stdio.h>
#include <d3d8.h>
#include <d3d8types.h>
#include <d3dx8.h>
#include "../eterBase/Timer.h"
#include "../eterlib/StateManager.h"
#include "../eterlib/Camera.h"
#include "SpeedTreeForestDirectX8.h"
#include "SpeedTreeConfig.h"
#include "VertexShaders.h"
///////////////////////////////////////////////////////////////////////
// CSpeedTreeForestDirectX8::CSpeedTreeForestDirectX8
CSpeedTreeForestDirectX8::CSpeedTreeForestDirectX8() : m_dwBranchVertexShader(0), m_dwLeafVertexShader(0)
{
}
///////////////////////////////////////////////////////////////////////
// CSpeedTreeForestDirectX8::~CSpeedTreeForestDirectX8
CSpeedTreeForestDirectX8::~CSpeedTreeForestDirectX8()
{
}
///////////////////////////////////////////////////////////////////////
// CSpeedTreeForestDirectX8::InitVertexShaders
bool CSpeedTreeForestDirectX8::InitVertexShaders(void)
{
NANOBEGIN
// load the vertex shaders
if (!m_dwBranchVertexShader)
m_dwBranchVertexShader = LoadBranchShader(m_pDx);
if (!m_dwLeafVertexShader)
m_dwLeafVertexShader = LoadLeafShader(m_pDx);
if (m_dwBranchVertexShader && m_dwLeafVertexShader)
{
CSpeedTreeWrapper::SetVertexShaders(m_dwBranchVertexShader, m_dwLeafVertexShader);
return true;
}
NANOEND
return false;
}
bool CSpeedTreeForestDirectX8::SetRenderingDevice(LPDIRECT3DDEVICE8 lpDevice)
{
m_pDx = lpDevice;
if (!InitVertexShaders())
return false;
const float c_afLightPosition[4] = { -0.707f, -0.300f, 0.707f, 0.0f };
const float c_afLightAmbient[4] = { 0.5f, 0.5f, 0.5f, 1.0f };
const float c_afLightDiffuse[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
const float c_afLightSpecular[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
float afLight1[] =
{
c_afLightPosition[0], c_afLightPosition[1], c_afLightPosition[2], // pos
c_afLightDiffuse[0], c_afLightDiffuse[1], c_afLightDiffuse[2], // diffuse
c_afLightAmbient[0], c_afLightAmbient[1], c_afLightAmbient[2], // ambient
c_afLightSpecular[0], c_afLightSpecular[1], c_afLightSpecular[2], // specular
c_afLightPosition[3], // directional flag
1.0f, 0.0f, 0.0f // attenuation (constant, linear, quadratic)
};
CSpeedTreeRT::SetNumWindMatrices(c_nNumWindMatrices);
CSpeedTreeRT::SetLightAttributes(0, afLight1);
CSpeedTreeRT::SetLightState(0, true);
return true;
}
///////////////////////////////////////////////////////////////////////
// CSpeedTreeForestDirectX8::UploadWindMatrix
void CSpeedTreeForestDirectX8::UploadWindMatrix(UINT uiLocation, const float* pMatrix) const
{
STATEMANAGER.SetVertexShaderConstant(uiLocation, pMatrix, 4);
}
void CSpeedTreeForestDirectX8::UpdateCompundMatrix(const D3DXVECTOR3 & c_rEyeVec, const D3DXMATRIX & c_rmatView, const D3DXMATRIX & c_rmatProj)
{
// setup composite matrix for shader
D3DXMATRIX matBlend;
D3DXMatrixIdentity(&matBlend);
D3DXMATRIX matBlendShader;
D3DXMatrixMultiply(&matBlendShader, &c_rmatView, &c_rmatProj);
float afDirection[3];
afDirection[0] = matBlendShader.m[0][2];
afDirection[1] = matBlendShader.m[1][2];
afDirection[2] = matBlendShader.m[2][2];
CSpeedTreeRT::SetCamera(c_rEyeVec, afDirection);
D3DXMatrixTranspose(&matBlendShader, &matBlendShader);
STATEMANAGER.SetVertexShaderConstant(c_nVertexShader_CompoundMatrix, &matBlendShader, 4);
}
///////////////////////////////////////////////////////////////////////
// CSpeedTreeForestDirectX8::Render
void CSpeedTreeForestDirectX8::Render(unsigned long ulRenderBitVector)
{
UpdateSystem(CTimer::Instance().GetCurrentSecond());
if (m_pMainTreeMap.empty())
return;
if (!(ulRenderBitVector & Forest_RenderToShadow) && !(ulRenderBitVector & Forest_RenderToMiniMap))
UpdateCompundMatrix(CCameraManager::Instance().GetCurrentCamera()->GetEye(), ms_matView, ms_matProj);
DWORD dwLightState = STATEMANAGER.GetRenderState(D3DRS_LIGHTING);
DWORD dwColorVertexState = STATEMANAGER.GetRenderState(D3DRS_COLORVERTEX);
DWORD dwFogVertexMode = STATEMANAGER.GetRenderState(D3DRS_FOGVERTEXMODE);
#ifdef WRAPPER_USE_DYNAMIC_LIGHTING
STATEMANAGER.SetRenderState(D3DRS_LIGHTING, TRUE);
#else
STATEMANAGER.SetRenderState(D3DRS_LIGHTING, FALSE);
STATEMANAGER.SetRenderState(D3DRS_COLORVERTEX, TRUE);
#endif
TTreeMap::iterator itor;
UINT uiCount;
itor = m_pMainTreeMap.begin();
while (itor != m_pMainTreeMap.end())
{
CSpeedTreeWrapper * pMainTree = (itor++)->second;
CSpeedTreeWrapper ** ppInstances = pMainTree->GetInstances(uiCount);
for (UINT i = 0; i < uiCount; ++i)
{
ppInstances[i]->Advance();
}
}
STATEMANAGER.SetVertexShaderConstant(c_nVertexShader_Light, m_afLighting, 3);
STATEMANAGER.SetVertexShaderConstant(c_nVertexShader_Fog, m_afFog, 1);
if (ulRenderBitVector & Forest_RenderToShadow)
{
//STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
}
else
{
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
STATEMANAGER.SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
STATEMANAGER.SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE);
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
STATEMANAGER.SetTextureStageState(1, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
STATEMANAGER.SetTextureStageState(1, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
}
STATEMANAGER.SaveRenderState(D3DRS_ALPHATESTENABLE, TRUE);
STATEMANAGER.SaveRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER);
STATEMANAGER.SaveRenderState(D3DRS_CULLMODE, D3DCULL_CW);
// set up fog if it is enabled
if (STATEMANAGER.GetRenderState(D3DRS_FOGENABLE))
{
#ifdef WRAPPER_USE_GPU_WIND
STATEMANAGER.SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_NONE); // GPU needs to work on all cards
#endif
}
// choose fixed function pipeline or custom shader for fronds and branches
STATEMANAGER.SetVertexShader(m_dwBranchVertexShader);
// render branches
if (ulRenderBitVector & Forest_RenderBranches)
{
itor = m_pMainTreeMap.begin();
while (itor != m_pMainTreeMap.end())
{
CSpeedTreeWrapper * pMainTree = (itor++)->second;
CSpeedTreeWrapper ** ppInstances = pMainTree->GetInstances(uiCount);
pMainTree->SetupBranchForTreeType();
for (UINT i = 0; i < uiCount; ++i)
if (ppInstances[i]->isShow())
ppInstances[i]->RenderBranches();
}
}
// set render states
STATEMANAGER.SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
// render fronds
if (ulRenderBitVector & Forest_RenderFronds)
{
itor = m_pMainTreeMap.begin();
while (itor != m_pMainTreeMap.end())
{
CSpeedTreeWrapper * pMainTree = (itor++)->second;
CSpeedTreeWrapper ** ppInstances = pMainTree->GetInstances(uiCount);
pMainTree->SetupFrondForTreeType();
for (UINT i = 0; i < uiCount; ++i)
if (ppInstances[i]->isShow())
ppInstances[i]->RenderFronds();
}
}
// render leaves
if (ulRenderBitVector & Forest_RenderLeaves)
{
STATEMANAGER.SetVertexShader(m_dwLeafVertexShader);
if (STATEMANAGER.GetRenderState(D3DRS_FOGENABLE))
{
#if defined WRAPPER_USE_GPU_WIND || defined WRAPPER_USE_GPU_LEAF_PLACEMENT
STATEMANAGER.SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
#endif
}
if (ulRenderBitVector & Forest_RenderToShadow || ulRenderBitVector & Forest_RenderToMiniMap)
{
STATEMANAGER.SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_NOTEQUAL);
STATEMANAGER.SaveRenderState(D3DRS_ALPHAREF, 0x00000000);
}
itor = m_pMainTreeMap.begin();
while (itor != m_pMainTreeMap.end())
{
CSpeedTreeWrapper * pMainTree = (itor++)->second;
CSpeedTreeWrapper ** ppInstances = pMainTree->GetInstances(uiCount);
pMainTree->SetupLeafForTreeType();
for (UINT i = 0; i < uiCount; ++i)
if (ppInstances[i]->isShow())
ppInstances[i]->RenderLeaves();
}
while (itor != m_pMainTreeMap.end())
(itor++)->second->EndLeafForTreeType();
if (ulRenderBitVector & Forest_RenderToShadow || ulRenderBitVector & Forest_RenderToMiniMap)
{
STATEMANAGER.SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER);
STATEMANAGER.RestoreRenderState(D3DRS_ALPHAREF);
}
}
// render billboards
#ifndef WRAPPER_NO_BILLBOARD_MODE
if (ulRenderBitVector & Forest_RenderBillboards)
{
STATEMANAGER.SetRenderState(D3DRS_LIGHTING, FALSE);
STATEMANAGER.SetRenderState(D3DRS_COLORVERTEX, FALSE);
itor = m_pMainTreeMap.begin();
while (itor != m_pMainTreeMap.end())
{
CSpeedTreeWrapper * pMainTree = (itor++)->second;
CSpeedTreeWrapper ** ppInstances = pMainTree->GetInstances(uiCount);
pMainTree->SetupBranchForTreeType();
for (UINT i = 0; i < uiCount; ++i)
if (ppInstances[i]->isShow())
ppInstances[i]->RenderBillboards();
}
}
#endif
STATEMANAGER.SetRenderState(D3DRS_LIGHTING, dwLightState);
STATEMANAGER.SetRenderState(D3DRS_COLORVERTEX, dwColorVertexState);
STATEMANAGER.SetRenderState(D3DRS_FOGVERTEXMODE, dwFogVertexMode);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> TextureStage 1<><31> COLOROP<4F><50> ALPHAOP<4F><50> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>´<EFBFBD>. (<28>ȱ׷<C8B1><D7B7><EFBFBD> <20>˰<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ɼ<EFBFBD><C9BC><EFBFBD>..)
if (!(ulRenderBitVector & Forest_RenderToShadow))
{
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
}
STATEMANAGER.RestoreRenderState(D3DRS_ALPHATESTENABLE);
STATEMANAGER.RestoreRenderState(D3DRS_ALPHAFUNC);
STATEMANAGER.RestoreRenderState(D3DRS_CULLMODE);
}

View File

@ -1,64 +0,0 @@
///////////////////////////////////////////////////////////////////////
// CSpeedTreeForestOpenGL Class
//
// (c) 2003 IDV, Inc.
//
// This class is provided to illustrate one way to incorporate
// SpeedTreeRT into an OpenGL application. All of the SpeedTreeRT
// calls that must be made on a per tree basis are done by this class.
// Calls that apply to all trees (i.e. static SpeedTreeRT functions)
// are made in the functions in main.cpp.
//
//
// *** INTERACTIVE DATA VISUALIZATION (IDV) PROPRIETARY INFORMATION ***
//
// This software is supplied under the terms of a license agreement or
// nondisclosure agreement with Interactive Data Visualization and may
// not be copied or disclosed except in accordance with the terms of
// that agreement.
//
// Copyright (c) 2001-2003 IDV, Inc.
// All Rights Reserved.
//
// IDV, Inc.
// 1233 Washington St. Suite 610
// Columbia, SC 29201
// Voice: (803) 799-1699
// Fax: (803) 931-0320
// Web: http://www.idvinc.com
#pragma once
///////////////////////////////////////////////////////////////////////
// Include Files
//#include <map>
#define SPEEDTREE_DATA_FORMAT_DIRECTX
#include "SpeedTreeForest.h"
#include "SpeedTreeMaterial.h"
///////////////////////////////////////////////////////////////////////
// class CSpeedTreeForestDirectX8 declaration
class CSpeedTreeForestDirectX8 : public CSpeedTreeForest, public CGraphicBase, public CSingleton<CSpeedTreeForestDirectX8>
{
public:
CSpeedTreeForestDirectX8();
virtual ~CSpeedTreeForestDirectX8();
void UploadWindMatrix(unsigned int uiLocation, const float* pMatrix) const;
void UpdateCompundMatrix(const D3DXVECTOR3 & c_rEyeVec, const D3DXMATRIX & c_rmatView, const D3DXMATRIX & c_rmatProj);
void Render(unsigned long ulRenderBitVector = Forest_RenderAll);
bool SetRenderingDevice(LPDIRECT3DDEVICE8 pDevice);
private:
bool InitVertexShaders();
private:
LPDIRECT3DDEVICE8 m_pDx; // the rendering context
DWORD m_dwBranchVertexShader; // branch/frond vertex shaders
DWORD m_dwLeafVertexShader; // leaf vertex shader
};

View File

@ -339,46 +339,7 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='VTune|Win32'">
</PrecompiledHeader>
</ClCompile>
<ClCompile Include="SpeedGrassRT.cpp">
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization>
<BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">EnableFastChecks</BasicRuntimeChecks>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</PrecompiledHeader>
<BrowseInformation Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</BrowseInformation>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Distribute|Win32'">MaxSpeed</Optimization>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Distribute|Win32'">
</PrecompiledHeader>
<Optimization Condition="'$(Configuration)|$(Platform)'=='MfcDebug|Win32'">Disabled</Optimization>
<BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='MfcDebug|Win32'">EnableFastChecks</BasicRuntimeChecks>
<BrowseInformation Condition="'$(Configuration)|$(Platform)'=='MfcDebug|Win32'">true</BrowseInformation>
<Optimization Condition="'$(Configuration)|$(Platform)'=='MfcRelease|Win32'">MaxSpeed</Optimization>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">MaxSpeed</Optimization>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</PrecompiledHeader>
<FavorSizeOrSpeed Condition="'$(Configuration)|$(Platform)'=='VTune|Win32'">Size</FavorSizeOrSpeed>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='VTune|Win32'">
</PrecompiledHeader>
</ClCompile>
<ClCompile Include="SpeedGrassWrapper.cpp">
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization>
<BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">EnableFastChecks</BasicRuntimeChecks>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</PrecompiledHeader>
<BrowseInformation Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</BrowseInformation>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Distribute|Win32'">MaxSpeed</Optimization>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Distribute|Win32'">
</PrecompiledHeader>
<Optimization Condition="'$(Configuration)|$(Platform)'=='MfcDebug|Win32'">Disabled</Optimization>
<BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='MfcDebug|Win32'">EnableFastChecks</BasicRuntimeChecks>
<BrowseInformation Condition="'$(Configuration)|$(Platform)'=='MfcDebug|Win32'">true</BrowseInformation>
<Optimization Condition="'$(Configuration)|$(Platform)'=='MfcRelease|Win32'">MaxSpeed</Optimization>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">MaxSpeed</Optimization>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</PrecompiledHeader>
<FavorSizeOrSpeed Condition="'$(Configuration)|$(Platform)'=='VTune|Win32'">Size</FavorSizeOrSpeed>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='VTune|Win32'">
</PrecompiledHeader>
</ClCompile>
<ClCompile Include="CSpeedTreeDirectX.cpp" />
<ClCompile Include="SpeedTreeForest.cpp">
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization>
<BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">EnableFastChecks</BasicRuntimeChecks>
@ -399,26 +360,6 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='VTune|Win32'">
</PrecompiledHeader>
</ClCompile>
<ClCompile Include="SpeedTreeForestDirectX8.cpp">
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization>
<BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">EnableFastChecks</BasicRuntimeChecks>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</PrecompiledHeader>
<BrowseInformation Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</BrowseInformation>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Distribute|Win32'">MaxSpeed</Optimization>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Distribute|Win32'">
</PrecompiledHeader>
<Optimization Condition="'$(Configuration)|$(Platform)'=='MfcDebug|Win32'">Disabled</Optimization>
<BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='MfcDebug|Win32'">EnableFastChecks</BasicRuntimeChecks>
<BrowseInformation Condition="'$(Configuration)|$(Platform)'=='MfcDebug|Win32'">true</BrowseInformation>
<Optimization Condition="'$(Configuration)|$(Platform)'=='MfcRelease|Win32'">MaxSpeed</Optimization>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">MaxSpeed</Optimization>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</PrecompiledHeader>
<FavorSizeOrSpeed Condition="'$(Configuration)|$(Platform)'=='VTune|Win32'">Size</FavorSizeOrSpeed>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='VTune|Win32'">
</PrecompiledHeader>
</ClCompile>
<ClCompile Include="SpeedTreeWrapper.cpp">
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization>
<BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">EnableFastChecks</BasicRuntimeChecks>
@ -457,11 +398,9 @@
<ItemGroup>
<ClInclude Include="BoundaryShapeManager.h" />
<ClInclude Include="Constants.h" />
<ClInclude Include="SpeedGrassRT.h" />
<ClInclude Include="SpeedGrassWrapper.h" />
<ClInclude Include="CSpeedTreeDirectX.h" />
<ClInclude Include="SpeedTreeConfig.h" />
<ClInclude Include="SpeedTreeForest.h" />
<ClInclude Include="SpeedTreeForestDirectX8.h" />
<ClInclude Include="SpeedTreeMaterial.h" />
<ClInclude Include="SpeedTreeWrapper.h" />
<ClInclude Include="StdAfx.h" />

View File

@ -14,24 +14,18 @@
<ClCompile Include="BoundaryShapeManager.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SpeedGrassRT.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SpeedGrassWrapper.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SpeedTreeForest.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SpeedTreeForestDirectX8.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SpeedTreeWrapper.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="StdAfx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="CSpeedTreeDirectX.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="BoundaryShapeManager.h">
@ -40,21 +34,12 @@
<ClInclude Include="Constants.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="SpeedGrassRT.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="SpeedGrassWrapper.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="SpeedTreeConfig.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="SpeedTreeForest.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="SpeedTreeForestDirectX8.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="SpeedTreeMaterial.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -67,5 +52,8 @@
<ClInclude Include="VertexShaders.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CSpeedTreeDirectX.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -30,14 +30,15 @@
#pragma once
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
// Include Files
#include <d3d8.h>
#include <d3d8types.h>
#include <d3dx8.h>
#include <d3d9.h>
#include <d3d9types.h>
#include <directxsdk/d3dx9.h>
#include "../eterLib/StateManager.h"
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
// class CSpeedTreeMaterial declaration/definiton
class CSpeedTreeMaterial
@ -45,10 +46,10 @@ class CSpeedTreeMaterial
public:
CSpeedTreeMaterial()
{
m_cMaterial.Ambient.r = m_cMaterial.Diffuse.r = m_cMaterial.Specular.r = m_cMaterial.Emissive.r = 1.0f;
m_cMaterial.Ambient.g = m_cMaterial.Diffuse.g = m_cMaterial.Specular.g = m_cMaterial.Emissive.g = 1.0f;
m_cMaterial.Ambient.b = m_cMaterial.Diffuse.b = m_cMaterial.Specular.b = m_cMaterial.Emissive.b = 1.0f;
m_cMaterial.Ambient.a = m_cMaterial.Diffuse.a = m_cMaterial.Specular.a = m_cMaterial.Emissive.a = 1.0f;
m_cMaterial.Ambient.r = m_cMaterial.Diffuse.r = m_cMaterial.Specular.r = m_cMaterial.Emissive.r = 3.0f;
m_cMaterial.Ambient.g = m_cMaterial.Diffuse.g = m_cMaterial.Specular.g = m_cMaterial.Emissive.g = 3.0f;
m_cMaterial.Ambient.b = m_cMaterial.Diffuse.b = m_cMaterial.Specular.b = m_cMaterial.Emissive.b = 3.0f;
m_cMaterial.Ambient.a = m_cMaterial.Diffuse.a = m_cMaterial.Specular.a = m_cMaterial.Emissive.a = 3.0f;
m_cMaterial.Power = 5.0f;
}
@ -68,12 +69,11 @@ class CSpeedTreeMaterial
m_cMaterial.Power = pMaterialArray[12];
}
D3DMATERIAL8 * Get()
void Activate(const LPDIRECT3DDEVICE9& pDx) const
{
return &m_cMaterial;
STATEMANAGER.SetMaterial(&m_cMaterial);
}
private:
D3DMATERIAL8 m_cMaterial; // the material object
};
D3DMATERIAL9 m_cMaterial; // the material object
};

File diff suppressed because it is too large Load Diff

View File

@ -29,17 +29,16 @@
//
#pragma once
#pragma warning (disable : 4786)
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
// Include files
#include "SpeedTreeMaterial.h"
#include <SpeedTreeRT.h>
#include <speedtree/SpeedTreeRT.h>
#include <d3d8.h>
#include <d3d8types.h>
#include <d3dx8.h>
#include <d3d9.h>
#include <d3d9types.h>
#include <directxsdk/d3dx9.h>
#include <vector>
#include "../eterLib/GrpObjectInstance.h"
@ -57,13 +56,12 @@
#define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p) = NULL; } }
#endif
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
// class CSpeedTreeWrapper declaration
#pragma warning(push)
#pragma warning(disable:4100)
class CSpeedTreeWrapper : public CGraphicObjectInstance
{
public:
enum
{
ID = TREE_OBJECT
@ -72,13 +70,15 @@ class CSpeedTreeWrapper : public CGraphicObjectInstance
// Collision Data
protected:
virtual void OnUpdateCollisionData(const CStaticCollisionDataVector * pscdVector);
virtual void OnUpdateHeighInstance(CAttributeInstance * pAttributeInstance) {}
virtual bool OnGetObjectHeight(float fX, float fY, float * pfHeight) { return false; }
UINT GetCollisionObjectCount();
void GetCollisionObject(UINT nIndex, CSpeedTreeRT::ECollisionObjectType& eType, float* pPosition, float* pDimensions);
virtual void OnUpdateCollisionData(const CStaticCollisionDataVector* pscdVector);
virtual void OnUpdateHeighInstance(CAttributeInstance* pAttributeInstance) {}
virtual bool OnGetObjectHeight(float fX, float fY, float* pfHeight) { return false; }
// Bounding Sphere
public:
virtual bool GetBoundingSphere(D3DXVECTOR3 & v3Center, float & fRadius);
public:
static bool ms_bSelfShadowOn;
@ -86,62 +86,47 @@ public:
// methods from CGraphicObjectInstance
virtual void SetPosition(float x, float y, float z);
virtual void CalculateBBox();
virtual void OnRender(); // Render <20>ÿ<EFBFBD> <20>޼ҵ<DEBC>, <20>׷<EFBFBD><D7B7><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>䳪 Ư<><C6AF><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><ECBFA1> <20><><EFBFBD><EFBFBD> Render <20><><EFBFBD><EFBFBD> <20>θ<EFBFBD><CEB8><EFBFBD>
// <20><> <20>̿ܿ<CCBF><DCBF><EFBFBD> RenderBranches, RenderFronds <20><><EFBFBD><EFBFBD> <20>޼ҵ带 CSpeedTreeForest<73><74><EFBFBD><EFBFBD> ȣ<><C8A3><EFBFBD>Ѵ<EFBFBD>.
virtual void OnRender();
virtual void OnRenderPCBlocker();
virtual void OnBlendRender() {}
virtual void OnRenderToShadowMap() {}
virtual void OnRenderShadow() {}
virtual void OnRenderPCBlocker();
public:
CSpeedTreeWrapper();
virtual ~CSpeedTreeWrapper();
const float * GetPosition();
static void SetVertexShaders(DWORD dwBranchVertexShader, DWORD dwLeafVertexShader);
// geometry
bool LoadTree(const char * pszSptFile, const BYTE * c_pbBlock = NULL, unsigned int uiBlockSize = 0, unsigned int nSeed = 1, float fSize = -1.0f, float fSizeVariance = -1.0f);
const float * GetBoundingBox(void) const { return m_afBoundingBox; }
void GetTreeSize(float & r_fSize, float & r_fVariance);
UINT GetCollisionObjectCount();
void GetCollisionObject(unsigned int nIndex, CSpeedTreeRT::ECollisionObjectType& eType, float* pPosition, float* pDimensions);
// geometry
bool LoadTree(const char* pszSptFile, const BYTE* c_pbBlock, unsigned int uiBlockSize, unsigned int nSeed = 1, float fSize = -1.0f, float fSizeVariance = -1.0f);
const float* GetBoundingBox(void) const { return m_afBoundingBox; }
// rendering
void SetupBranchForTreeType(void) const;
void SetupFrondForTreeType(void) const;
void SetupLeafForTreeType(void) const;
void EndLeafForTreeType(void);
#ifdef WRAPPER_USE_GPU_LEAF_PLACEMENT
void UploadLeafTables(unsigned int uiLocation) const;
#endif
void RenderBranches(void) const;
void RenderFronds(void) const;
void RenderFronds(void) const;
void RenderLeaves(void) const;
void RenderBillboards(void) const;
// instancing
CSpeedTreeWrapper ** GetInstances(unsigned int& nCount);
CSpeedTreeWrapper * InstanceOf(void) const { return m_pInstanceOf; }
CSpeedTreeWrapper * MakeInstance();
void DeleteInstance(CSpeedTreeWrapper * pInstance);
CSpeedTreeRT * GetSpeedTree(void) const { return m_pSpeedTree; }
// lighting
CSpeedTreeWrapper** GetInstances(unsigned int& nCount);
CSpeedTreeWrapper* InstanceOf(void) const { return m_pInstanceOf; }
CSpeedTreeWrapper* MakeInstance(void);
void DeleteInstance(CSpeedTreeWrapper* pInstance);
CSpeedTreeRT* GetSpeedTree(void) const { return m_pSpeedTree; }
// lighting
const CSpeedTreeMaterial & GetBranchMaterial(void) const { return m_cBranchMaterial; }
const CSpeedTreeMaterial & GetFrondMaterial(void) const { return m_cFrondMaterial; }
const CSpeedTreeMaterial & GetLeafMaterial(void) const { return m_cLeafMaterial; }
float GetLeafLightingAdjustment(void) const { return m_pSpeedTree->GetLeafLightingAdjustment( ); }
// wind
void SetWindStrength(float fStrength) { m_pSpeedTree->SetWindStrength(fStrength); }
// wind
void Advance(void);
// utility
LPDIRECT3DTEXTURE8 GetBranchTexture(void) const;
void CleanUpMemory(void);
private:
@ -166,20 +151,21 @@ private:
CSpeedTreeRT::SGeometry* m_pGeometryCache; // cache for pulling geometry from SpeedTree avoids lots of reallocation
// branch buffers
LPDIRECT3DVERTEXBUFFER8 m_pBranchVertexBuffer; // branch vertex buffer
LPDIRECT3DVERTEXBUFFER9 m_pBranchVertexBuffer; // branch vertex buffer
unsigned int m_unBranchVertexCount; // number of vertices in branches
LPDIRECT3DINDEXBUFFER8 m_pBranchIndexBuffer; // branch index buffer
LPDIRECT3DINDEXBUFFER9 m_pBranchIndexBuffer; // branch index buffer
unsigned short* m_pBranchIndexCounts; // number of indexes per branch LOD level
// frond buffers
LPDIRECT3DVERTEXBUFFER8 m_pFrondVertexBuffer; // frond vertex buffer
LPDIRECT3DVERTEXBUFFER9 m_pFrondVertexBuffer; // frond vertex buffer
unsigned int m_unFrondVertexCount; // number of vertices in frond
LPDIRECT3DINDEXBUFFER8 m_pFrondIndexBuffer; // frond index buffer
unsigned short* m_pFrondIndexCounts; // number of indexes per frond LOD level
unsigned int m_unNumFrondLods;
LPDIRECT3DINDEXBUFFER9* m_pFrondIndexBuffers;
unsigned short* m_pFrondIndexCounts;
// leaf buffers
unsigned short m_usNumLeafLods; // the number of leaf LODs
LPDIRECT3DVERTEXBUFFER8* m_pLeafVertexBuffer; // leaf vertex buffer
LPDIRECT3DVERTEXBUFFER9* m_pLeafVertexBuffer; // leaf vertex buffer
bool* m_pLeavesUpdatedByCpu; // stores which LOD's have been updated already per frame
// tree properties
@ -196,8 +182,8 @@ private:
CGraphicImageInstance m_ShadowImageInstance; // shadow texture object (used if shadows are enabled)
CGraphicImageInstance m_CompositeImageInstance;
static DWORD ms_dwBranchVertexShader;
static DWORD ms_dwLeafVertexShader;
};
static unsigned int m_unNumWrappersActive;
#pragma warning(pop)
static LPDIRECT3DVERTEXSHADER9 ms_lpBranchVertexShader;
static LPDIRECT3DVERTEXSHADER9 ms_lpLeafVertexShader;
};

View File

@ -1,19 +1,4 @@
#pragma once
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <assert.h>
//#include <crtdbg.h>
//#include "Forest.h"
#include "SpeedTreeForestDirectX8.h"
// Armadillo nanomite protection
#if !defined(NANOBEGIN) && !defined(NANOEND)
#ifdef _DEBUG
#define NANOBEGIN
#define NANOEND
#else
#include <armadillo/SecuredSections.h>
#endif
#endif
#include "CSpeedTreeDirectX.h"

View File

@ -1,332 +1,84 @@
///////////////////////////////////////////////////////////////////////
// SpeedTreeRT DirectX Example
//
// (c) 2003 IDV, Inc.
//
// This example demonstrates how to render trees using SpeedTreeRT
// and DirectX. Techniques illustrated include ".spt" file parsing,
// static lighting, dynamic lighting, LOD implementation, cloning,
// instancing, and dynamic wind effects.
//
//
// *** INTERACTIVE DATA VISUALIZATION (IDV) PROPRIETARY INFORMATION ***
//
// This software is supplied under the terms of a license agreement or
// nondisclosure agreement with Interactive Data Visualization and may
// not be copied or disclosed except in accordance with the terms of
// that agreement.
//
// Copyright (c) 2001-2003 IDV, Inc.
// All Rights Reserved.
//
// IDV, Inc.
// 1233 Washington St. Suite 610
// Columbia, SC 29201
// Voice: (803) 799-1699
// Fax: (803) 931-0320
// Web: http://www.idvinc.com
///////////////////////////////////////////////////////////////////////
// Includes
#pragma once
#include <d3d9.h>
#include <directxsdk/d3dx9.h>
#include "SpeedTreeConfig.h"
#include <map>
#include <string>
///////////////////////////////////////////////////////////////////////
// Branch & Frond Vertex Formats
static DWORD D3DFVF_SPEEDTREE_BRANCH_VERTEX =
D3DFVF_XYZ | // always have the position
#ifdef WRAPPER_USE_DYNAMIC_LIGHTING // precomputed colors or geometric normals
D3DFVF_NORMAL |
#else
D3DFVF_DIFFUSE |
#endif
#ifdef WRAPPER_RENDER_SELF_SHADOWS
D3DFVF_TEX2 | D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE2(1) // shadow texture coordinates
#else
D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2(0) // always have first texture layer coords
#endif
#ifdef WRAPPER_USE_GPU_WIND
| D3DFVF_TEX3 | D3DFVF_TEXCOORDSIZE2(2) // GPU Only - wind weight and index passed in second texture layer
#endif
;
///////////////////////////////////////////////////////////////////////
// FVF Branch Vertex Structure
static DWORD D3DFVF_SPEEDTREE_BRANCH_VERTEX = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX2 | D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE2(1);
struct SFVFBranchVertex
{
D3DXVECTOR3 m_vPosition; // Always Used
#ifdef WRAPPER_USE_DYNAMIC_LIGHTING
D3DXVECTOR3 m_vNormal; // Dynamic Lighting Only
#else
DWORD m_dwDiffuseColor; // Static Lighting Only
#endif
FLOAT m_fTexCoords[2]; // Always Used
#ifdef WRAPPER_RENDER_SELF_SHADOWS
FLOAT m_fShadowCoords[2]; // Texture coordinates for the shadows
#endif
#ifdef WRAPPER_USE_GPU_WIND
FLOAT m_fWindIndex; // GPU Only
FLOAT m_fWindWeight;
#endif
D3DXVECTOR3 m_vPosition;
DWORD m_dwDiffuseColor;
FLOAT m_fTexCoords[2];
FLOAT m_fShadowCoords[2];
};
///////////////////////////////////////////////////////////////////////
// Branch/Frond Vertex Program
static const char g_achSimpleVertexProgram[] =
static const char g_achSimpleVertexProgram[] =
{
"vs.1.1\n" // identity shader version
"mov oT0.xy, v7\n" // always pass texcoord0 through
#ifdef WRAPPER_RENDER_SELF_SHADOWS
"mov oT1.xy, v8\n" // pass shadow texcoords through if enabled
#endif
// retrieve and convert wind matrix index
"mov a0.x, v9.x\n"
// perform wind interpolation
"m4x4 r1, v0, c[54+a0.x]\n" // compute full wind effect
"sub r2, r1, v0\n" // compute difference between full wind and none
"mov r3.x, v9.y\n" // mad can't access two v's at once, use r3.x as tmp
"mad r1, r2, r3.x, v0\n" // perform interpolation
"add r2, c[52], r1\n" // translate to tree's position
"m4x4 oPos, r2, c[0]\n" // project to screen
#ifdef WRAPPER_USE_FOG
"dp4 r1, r2, c[2]\n" // find distance to vertex
"sub r2.x, c[85].y, r1.z\n" // linear fogging
"mul oFog, r2.x, c[85].z\n" // write to fog register
#endif
#ifdef WRAPPER_USE_STATIC_LIGHTING
"mov oD0, v5\n" // pass color through
#else
"mov r1, c[74]\n" // can only use one const register per instruction
"mul r5, c[73], r1\n" // diffuse values
"mov r1, c[75]\n" // can only use one const register per instruction
"mul r4, c[72], r1\n" // ambient values
"dp3 r2, v3, c[71]\n" // dot light direction with normal
// "max r2.x, r2.x, c[70].x\n" // limit it
"mad oD0, r2.x, r5, r4\n" // compute the final color
#endif
"vs.1.1\n"
"dcl_position v0\n"
"dcl_color v5\n"
"dcl_texcoord0 v7\n"
"dcl_texcoord1 v8\n"
"mov oT0.xy, v7\n"
"mov oT1.xy, v8\n"
"mov a0.x, v8.x\n"
"m4x4 r1, v0, c[54+a0.x]\n"
"sub r2, r1, v0\n"
"mov r3.x, v8.y\n"
"mad r1, r2, r3.x, v0\n"
"add r2, c[52], r1\n"
"m4x4 oPos, r2, c[0]\n"
#ifdef WRAPPER_USE_FOG
"dp4 r1, r2, c[2]\n"
"sub r2.x, c[85].y, r1.z\n"
"mul oFog, r2.x, c[85].z\n"
#endif
"mov oD0, v5\n"
};
///////////////////////////////////////////////////////////////////////
// LoadBranchShader
static DWORD LoadBranchShader(LPDIRECT3DDEVICE8 pDx)
inline LPDIRECT3DVERTEXSHADER9 LoadBranchShader(LPDIRECT3DDEVICE9 pDx)
{
#ifndef WRAPPER_USE_GPU_WIND
return D3DFVF_SPEEDTREE_BRANCH_VERTEX;
#endif
// branch shader declaration
DWORD pBranchShaderDecl[] =
{
D3DVSD_STREAM(0),
D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),
#ifdef WRAPPER_USE_DYNAMIC_LIGHTING
D3DVSD_REG(D3DVSDE_NORMAL, D3DVSDT_FLOAT3),
#else
D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR),
#endif
D3DVSD_REG(D3DVSDE_TEXCOORD0, D3DVSDT_FLOAT2),
#ifdef WRAPPER_RENDER_SELF_SHADOWS
D3DVSD_REG(D3DVSDE_TEXCOORD1, D3DVSDT_FLOAT2),
#endif
#ifdef WRAPPER_USE_GPU_WIND
D3DVSD_REG(D3DVSDE_TEXCOORD2, D3DVSDT_FLOAT2),
#endif
D3DVSD_END( )
};
// assemble shader
DWORD dwShader;
LPD3DXBUFFER pCode, pError;
if (D3DXAssembleShader(g_achSimpleVertexProgram, sizeof(g_achSimpleVertexProgram) - 1, 0, NULL, &pCode, &pError) == D3D_OK)
{
if (pDx->CreateVertexShader(pBranchShaderDecl, (DWORD*) pCode->GetBufferPointer( ), &dwShader, 0) != D3D_OK)
{
char szError[1024];
sprintf(szError, "Failed to create branch vertex shader.");
MessageBox(NULL, szError, "Vertex Shader Error", MB_ICONSTOP);
}
}
else
{
char szError[1024];
sprintf(szError, "Failed to assemble branch vertex shader.\nThe error reported is [ %s ].\n", pError->GetBufferPointer( ));
MessageBox(NULL, szError, "Vertex Shader Error", MB_ICONSTOP);
}
if (pCode)
pCode->Release();
return dwShader;
UNREFERENCED_PARAMETER(pDx);
return NULL;
}
///////////////////////////////////////////////////////////////////////
// Leaf Vertex Formats
static DWORD D3DFVF_SPEEDTREE_LEAF_VERTEX =
D3DFVF_XYZ | // always have the position
#ifdef WRAPPER_USE_DYNAMIC_LIGHTING // precomputed colors or geometric normals
D3DFVF_NORMAL |
#else
D3DFVF_DIFFUSE |
#endif
D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2(0) // always have first texture layer coords
#if defined WRAPPER_USE_GPU_WIND || defined WRAPPER_USE_GPU_LEAF_PLACEMENT
| D3DFVF_TEX3 | D3DFVF_TEXCOORDSIZE4(2) // GPU Only - wind weight and index passed in second texture layer
#endif
;
///////////////////////////////////////////////////////////////////////
// FVF Leaf Vertex Structure
static DWORD D3DFVF_SPEEDTREE_LEAF_VERTEX = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE2(1) | D3DFVF_TEXCOORDSIZE2(2) | D3DFVF_TEX1;
struct SFVFLeafVertex
{
D3DXVECTOR3 m_vPosition; // Always Used
#ifdef WRAPPER_USE_DYNAMIC_LIGHTING
D3DXVECTOR3 m_vNormal; // Dynamic Lighting Only
#else
DWORD m_dwDiffuseColor; // Static Lighting Only
#endif
FLOAT m_fTexCoords[2]; // Always Used
#if defined WRAPPER_USE_GPU_WIND || defined WRAPPER_USE_GPU_LEAF_PLACEMENT
FLOAT m_fWindIndex; // Only used when GPU is involved
FLOAT m_fWindWeight;
FLOAT m_fLeafPlacementIndex;
FLOAT m_fLeafScalarValue;
#endif
D3DXVECTOR3 m_vPosition;
DWORD m_dwDiffuseColor;
FLOAT m_fTexCoords[2];
};
///////////////////////////////////////////////////////////////////////
// Leaf Vertex Program
static const char g_achLeafVertexProgram[] =
static const char g_achLeafVertexProgram[] =
{
"vs.1.1\n" // identity shader version
"vs.1.1\n"
"mov oT0.xy, v7\n" // always pass texcoord0 through
#ifdef WRAPPER_USE_GPU_WIND
// retrieve and convert wind matrix index
"mov a0.x, v9.x\n"
"dcl_position v0\n"
"dcl_color v5\n"
"dcl_texcoord0 v7\n"
"dcl_texcoord1 v8\n"
"dcl_texcoord2 v9\n"
"mov oT0.xy, v7\n"
"mov r0, v0\n"
"add r0, c[52], r0\n"
"m4x4 oPos, r0, c[0]\n"
// perform wind interpolation
"m4x4 r1, v0, c[54+a0.x]\n" // compute full wind effect
"sub r2, r1, v0\n" // compute difference between full wind and none
"mov r3.x, v9.y\n" // mad can't access two v's at once, use r3.x as tmp
"mad r0, r2, r3.x, v0\n" // perform interpolation
#else
"mov r0, v0\n" // wind already handled, pass the vertex through
#endif
#ifdef WRAPPER_USE_GPU_LEAF_PLACEMENT
"mov a0.x, v9.z\n" // place the leaves
"mul r1, c[a0.x], v9.w\n"
"add r0, r1, r0\n"
#endif
"add r0, c[52], r0\n" // translate to tree's position
"m4x4 oPos, r0, c[0]\n" // project to screen
#ifdef WRAPPER_USE_FOG
"dp4 r1, r0, c[2]\n" // find distance to vertex
"sub r2.x, c[85].y, r1.z\n" //
"mul oFog, r2.x, c[85].z\n"
#endif
#ifdef WRAPPER_USE_STATIC_LIGHTING
"mov oD0, v5\n" // pass color through
#else
"mov r1, c[74]\n" // can only use one const register per instruction
"mul r5, c[73], r1\n" // diffuse values
"mov r1, c[75]\n" // can only use one const register per instruction
"mul r4, c[72], r1\n" // ambient values
"dp3 r2.x, v3, c[71]\n" // dot light direction with normal
"max r2.x, r2.x, c[70].x\n" // limit it
"mad oD0, r2.x, r5, r4\n" // compute the final color
#endif
#ifdef WRAPPER_USE_FOG
"dp4 r1, r0, c[2]\n"
"sub r2.x, c[85].y, r1.z\n"
"mul oFog, r2.x, c[85].z\n"
#endif
"mov oD0, v5\n"
};
///////////////////////////////////////////////////////////////////////
// LoadLeafShader
static DWORD LoadLeafShader(LPDIRECT3DDEVICE8 pDx)
inline LPDIRECT3DVERTEXSHADER9 LoadLeafShader(LPDIRECT3DDEVICE9 pDx)
{
DWORD dwShader = D3DFVF_SPEEDTREE_LEAF_VERTEX;
#if defined WRAPPER_USE_GPU_LEAF_PLACEMENT || defined WRAPPER_USE_GPU_WIND
// leaf shader declaration
DWORD pLeafShaderDecl[ ] =
{
D3DVSD_STREAM(0),
D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),
#ifdef WRAPPER_USE_DYNAMIC_LIGHTING
D3DVSD_REG(D3DVSDE_NORMAL, D3DVSDT_FLOAT3),
#else
D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR),
#endif
D3DVSD_REG(D3DVSDE_TEXCOORD0, D3DVSDT_FLOAT2),
D3DVSD_REG(D3DVSDE_TEXCOORD2, D3DVSDT_FLOAT4),
D3DVSD_END( )
};
// assemble shader
LPD3DXBUFFER pCode, pError;
if (D3DXAssembleShader(g_achLeafVertexProgram, sizeof(g_achLeafVertexProgram) - 1, 0, NULL, &pCode, &pError) == D3D_OK)
{
if (pDx->CreateVertexShader(pLeafShaderDecl, (DWORD*) pCode->GetBufferPointer( ), &dwShader, 0) != D3D_OK)
{
Tracef("Failed to create leaf vertex shader.");
/*
char szError[1024];
sprintf(szError, "Failed to create leaf vertex shader.");
MessageBox(NULL, szError, "Vertex Shader Error", MB_ICONSTOP);
*/
}
}
else
{
Tracef("Failed to assemble leaf vertex shader. The error reported is [ %s ].\n", pError->GetBufferPointer( ));
/*
char szError[1024];
sprintf(szError, "Failed to assemble leaf vertex shader. The error reported is [ %s ].\n", pError->GetBufferPointer( ));
MessageBox(NULL, szError, "Vertex Shader Error", MB_ICONSTOP);
*/
}
if (pCode)
pCode->Release( );
#else
dwShader = D3DFVF_SPEEDTREE_LEAF_VERTEX;
#endif
return dwShader;
LPDIRECT3DVERTEXSHADER9 dwShader = NULL;
return dwShader;
}
static DWORD D3DFVF_SPEEDTREE_BILLBOARD_VERTEX = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1;