SpeedTreeLib: port 40250 wrapper/forest verbatim over a CSpeedTreeRT stand-in

Delete the platform proxy tree renderer and copy SpeedTreeWrapper, SpeedTreeForest,
SpeedTreeForestDirectX8, SpeedTreeConfig.h and VertexShaders.h from 40250. The SDK
SpeedTreeRT.h public API becomes the shim; the closed CSpeedTreeRT is reimplemented in
platform/SpeedTreeLib/SpeedTreeRT.cpp (procedural geometry, static lighting, single LOD,
DIVERGENT). Shims gain the D3D8 vertex shader declaration tokens, D3D_OK,
CreateVertexShader/DeleteVertexShader, ID3DXBuffer/D3DXAssembleShader, MessageBox and
__min/__max.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
shenlei
2026-09-28 13:31:57 +09:00
co-authored by Claude Opus 5.5
parent 86e602cb32
commit d817bd7cab
19 changed files with 4373 additions and 1516 deletions
@@ -0,0 +1,120 @@
///////////////////////////////////////////////////////////////////////
// SpeedTreeRT runtime configuration #defines
//
// (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
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;
// vertex shader constant locations
const int c_nVertexShader_LeafLightingAdjustment = 70;
const int c_nVertexShader_Light = 71;
const int c_nVertexShader_Material = 74;
const int c_nVertexShader_TreePos = 52;
const int c_nVertexShader_CompoundMatrix = 0;
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
#if defined WRAPPER_USE_STATIC_LIGHTING && defined WRAPPER_USE_DYNAMIC_LIGHTING
#error Please define exactly one lighting mode
#endif
// setup wind (enable ONE of the three below)
//#define WRAPPER_USE_GPU_WIND
//#define WRAPPER_USE_CPU_WIND
#define WRAPPER_USE_NO_WIND
#if defined WRAPPER_USE_GPU_WIND && defined WRAPPER_USE_CPU_WIND
#error Please define exactly one lighting mode
#elif defined WRAPPER_USE_GPU_WIND && defined WRAPPER_USE_NO_WIND
#error Please define exactly one lighting mode
#elif defined WRAPPER_USE_CPU_WIND && defined WRAPPER_USE_NO_WIND
#error Please define exactly one lighting mode
#endif
// leaf placement algorithm (enable ONE of the two below)
//#define WRAPPER_USE_GPU_LEAF_PLACEMENT
#define WRAPPER_USE_CPU_LEAF_PLACEMENT
#if defined WRAPPER_USE_GPU_LEAF_PLACEMENT && defined WRAPPER_USE_CPU_LEAF_PLACEMENT
#error Please define exactly one leaf placement algorithm
#endif
// texture coordinates (enable this define for DirectX-based engines)
#define WRAPPER_FLIP_T_TEXCOORD
// up vector
//#define WRAPPER_UP_POS_Y
#define WRAPPER_UP_POS_Z
#if defined WRAPPER_UP_POS_Y && defined WRAPPER_UP_POS_Z
#error Please define exactly one up vector
#endif
// loading from STF or clones/instances? (enable ONE of the two below)
//#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
#endif
// billboard modes
#define WRAPPER_BILLBOARD_MODE
//#define WRAPPER_RENDER_HORIZONTAL_BILLBOARD
// 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
@@ -0,0 +1,316 @@
///////////////////////////////////////////////////////////////////////
// CSpeedTreeForest Class
///////////////////////////////////////////////////////////////////////
// Include Files
#include "StdAfx.h"
#include <vector>
#include "../EterBase/Filename.h"
#include "../EterBase/MappedFile.h"
#include "../EterPack/EterPackManager.h"
#include "SpeedTreeForest.h"
#include "SpeedTreeConfig.h"
#include <cfloat>
using namespace std;
///////////////////////////////////////////////////////////////////////
// CSpeedTreeForest constructor
CSpeedTreeForest::CSpeedTreeForest() : m_fWindStrength(0.0f)
{
CSpeedTreeRT::SetNumWindMatrices(c_nNumWindMatrices);
m_afForestExtents[0] = m_afForestExtents[1] = m_afForestExtents[2] = FLT_MAX;
m_afForestExtents[3] = m_afForestExtents[4] = m_afForestExtents[5] = -FLT_MAX;
}
///////////////////////////////////////////////////////////////////////
// CSpeedTreeForest destructor
CSpeedTreeForest::~CSpeedTreeForest()
{
Clear();
}
void CSpeedTreeForest::Clear()
{
TTreeMap::iterator itor = m_pMainTreeMap.begin();
UINT uiCount;
while (itor != m_pMainTreeMap.end())
{
CSpeedTreeWrapper * pMainTree = (itor++)->second;
CSpeedTreeWrapper ** ppInstances = pMainTree->GetInstances(uiCount);
for (UINT i = 0; i < uiCount; ++i)
delete ppInstances[i];
delete pMainTree;
}
m_pMainTreeMap.clear();
}
CSpeedTreeWrapper * CSpeedTreeForest::GetMainTree(DWORD dwCRC)
{
TTreeMap::iterator itor = m_pMainTreeMap.find(dwCRC);
if (itor == m_pMainTreeMap.end())
return NULL;
return itor->second;
}
BOOL CSpeedTreeForest::GetMainTree(DWORD dwCRC, CSpeedTreeWrapper ** ppMainTree, const char * c_pszFileName)
{
TTreeMap::iterator itor = m_pMainTreeMap.find(dwCRC);
CSpeedTreeWrapper * pTree;
if (itor != m_pMainTreeMap.end())
pTree = itor->second;
else
{
CMappedFile file;
LPCVOID c_pvData;
// NOTE : 파일이 없을때는 return FALSE 아닌가요? - [levites]
if (!CEterPackManager::Instance().Get(file, c_pszFileName, &c_pvData))
return FALSE;
pTree = new CSpeedTreeWrapper;
if (!pTree->LoadTree(c_pszFileName, (const BYTE *) c_pvData, file.Size()))
{
delete pTree;
return FALSE;
}
m_pMainTreeMap.insert(std::map<DWORD, CSpeedTreeWrapper *>::value_type(dwCRC, pTree));
file.Destroy();
}
*ppMainTree = pTree;
return TRUE;
}
CSpeedTreeWrapper* CSpeedTreeForest::CreateInstance(float x, float y, float z, DWORD dwTreeCRC, const char * c_szTreeName)
{
CSpeedTreeWrapper * pMainTree;
if (!GetMainTree(dwTreeCRC, &pMainTree, c_szTreeName))
return NULL;
CSpeedTreeWrapper* pTreeInst = pMainTree->MakeInstance();
pTreeInst->SetPosition(x, y, z);
pTreeInst->RegisterBoundingSphere();
return pTreeInst;
}
void CSpeedTreeForest::DeleteInstance(CSpeedTreeWrapper * pInstance)
{
if (!pInstance)
return;
CSpeedTreeWrapper * pParentTree = pInstance->InstanceOf();
if (!pParentTree)
return;
pParentTree->DeleteInstance(pInstance);
}
void CSpeedTreeForest::UpdateSystem(float fCurrentTime)
{
// 업데이트 할 때 한번
static float fLastTime = fCurrentTime;
float fElapsedTime = fCurrentTime - fLastTime;
CSpeedTreeRT::SetTime(fElapsedTime);
m_fAccumTime += fElapsedTime;
SetupWindMatrices(m_fAccumTime);
}
///////////////////////////////////////////////////////////////////////
// CSpeedTreeForest::AdjustExtents
void CSpeedTreeForest::AdjustExtents(float x, float y, float z)
{
// min
m_afForestExtents[0] = __min(m_afForestExtents[0], x);
m_afForestExtents[1] = __min(m_afForestExtents[1], y);
m_afForestExtents[2] = __min(m_afForestExtents[2], z);
// max
m_afForestExtents[3] = __max(m_afForestExtents[3], x);
m_afForestExtents[4] = __max(m_afForestExtents[4], y);
m_afForestExtents[5] = __max(m_afForestExtents[5], z);
}
///////////////////////////////////////////////////////////////////////
// CSpeedTreeForest::SetWindStrength
void CSpeedTreeForest::SetWindStrength(float fStrength)
{
if (m_fWindStrength == fStrength)
return;
m_fWindStrength = fStrength;
TTreeMap::iterator itor = m_pMainTreeMap.begin();
UINT uiCount;
while (itor != m_pMainTreeMap.end())
{
CSpeedTreeWrapper * pMainTree = (itor++)->second;
CSpeedTreeWrapper ** ppInstances = pMainTree->GetInstances(uiCount);
for (UINT i = 0; i < uiCount; ++i)
ppInstances[i]->GetSpeedTree()->SetWindStrength(m_fWindStrength);
}
}
///////////////////////////////////////////////////////////////////////
// CSpeedTreeForest::SetupWindMatrices
void CSpeedTreeForest::SetupWindMatrices(float fTimeInSecs)
{
// matrix computational data
static float afMatrixTimes[c_nNumWindMatrices] = { 0.0f };
static float afFrequencies[c_nNumWindMatrices][2] =
{
{ 0.15f, 0.17f },
{ 0.25f, 0.15f },
{ 0.19f, 0.05f },
{ 0.15f, 0.22f }
};
// compute time since last call
static float fTimeOfLastCall = 0.0f;
float fTimeSinceLastCall = fTimeInSecs - fTimeOfLastCall;
fTimeOfLastCall = fTimeInSecs;
// wind strength
static float fOldStrength = m_fWindStrength;
// increment matrix times
for (int i = 0; i < c_nNumWindMatrices; ++i)
afMatrixTimes[i] += fTimeSinceLastCall;
// compute maximum branch throw
float fBaseAngle = m_fWindStrength * 35.0f;
// build rotation matrices
for (int j = 0; j < c_nNumWindMatrices; ++j)
{
// adjust time to prevent "jumping"
if (m_fWindStrength != 0.0f)
afMatrixTimes[j] = (afMatrixTimes[j] * fOldStrength) / m_fWindStrength;
// compute percentages for each axis
float fBaseFreq = m_fWindStrength * 20.0f;
float fXPercent = sinf(fBaseFreq * afFrequencies[j % c_nNumWindMatrices][0] * afMatrixTimes[j]);
float fYPercent = cosf(fBaseFreq * afFrequencies[j % c_nNumWindMatrices][1] * afMatrixTimes[j]);
// build compound rotation matrix (rotate on 'x' then on 'y')
const float c_fDeg2Rad = 57.2957795f;
float fSinX = sinf(fBaseAngle * fXPercent / c_fDeg2Rad);
float fSinY = sinf(fBaseAngle * fYPercent / c_fDeg2Rad);
float fCosX = cosf(fBaseAngle * fXPercent / c_fDeg2Rad);
float fCosY = cosf(fBaseAngle * fYPercent / c_fDeg2Rad);
float afMatrix[16] = { 0.0f };
afMatrix[0] = fCosY;
afMatrix[2] = -fSinY;
afMatrix[4] = fSinX * fSinY;
afMatrix[5] = fCosX;
afMatrix[6] = fSinX * fCosY;
afMatrix[8] = fSinY * fCosX;
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];
m_afLighting[1] = afDirection[1];
m_afLighting[2] = afDirection[2];
m_afLighting[3] = 1.0f;
m_afLighting[4] = afAmbient[0];
m_afLighting[5] = afAmbient[1];
m_afLighting[6] = afAmbient[2];
m_afLighting[7] = afAmbient[3];
m_afLighting[8] = afDiffuse[0];
m_afLighting[9] = afDiffuse[1];
m_afLighting[10] = afDiffuse[2];
m_afLighting[11] = afDiffuse[3];
}
void CSpeedTreeForest::SetFog(float fFogNear, float fFogFar)
{
const float c_fFogLinearScale = (1.0f / (fFogFar - fFogNear));
m_afFog[0] = fFogNear;
m_afFog[1] = fFogFar;
m_afFog[2] = c_fFogLinearScale;
m_afFog[3] = 0.0f;
}
@@ -0,0 +1,344 @@
///////////////////////////////////////////////////////////////////////
// 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);
// 셀프섀도우로 쓰는 TextureStage 1의 COLOROP와 ALPHAOP를 꺼줘야 다음 렌더링 할 놈들이
// 제대로 나온다. (안그러면 검게 나올 가능성이..)
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);
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,332 @@
///////////////////////////////////////////////////////////////////////
// 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 "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
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
};
///////////////////////////////////////////////////////////////////////
// Branch/Frond Vertex Program
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
};
///////////////////////////////////////////////////////////////////////
// LoadBranchShader
static DWORD LoadBranchShader(LPDIRECT3DDEVICE8 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;
}
///////////////////////////////////////////////////////////////////////
// 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
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
};
///////////////////////////////////////////////////////////////////////
// Leaf Vertex Program
static const char g_achLeafVertexProgram[] =
{
"vs.1.1\n" // identity shader version
"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"
// 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
};
///////////////////////////////////////////////////////////////////////
// LoadLeafShader
static DWORD LoadLeafShader(LPDIRECT3DDEVICE8 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;
}
+45
View File
@@ -503,6 +503,49 @@ typedef enum _D3DVERTEXBLENDFLAGS {
#define D3DFVF_TEX8 0x800
#define D3DFVF_LASTBETA_UBYTE4 0x1000
#define D3DFVF_RESERVED2 0xE000
// d3d8.h
#define D3D_OK S_OK
// d3d8types.h vertex shader declaration tokens
typedef enum _D3DVSD_TOKENTYPE
{
D3DVSD_TOKEN_NOP = 0,
D3DVSD_TOKEN_STREAM = 1,
D3DVSD_TOKEN_STREAMDATA = 2,
D3DVSD_TOKEN_TESSELLATOR = 3,
D3DVSD_TOKEN_CONSTMEM = 4,
D3DVSD_TOKEN_EXT = 5,
D3DVSD_TOKEN_END = 7,
D3DVSD_FORCE_DWORD = 0x7fffffff,
} D3DVSD_TOKENTYPE;
#define D3DVSD_TOKENTYPESHIFT 29
#define D3DVSD_TOKENTYPEMASK (7 << D3DVSD_TOKENTYPESHIFT)
#define D3DVSD_DATATYPESHIFT 16
#define D3DVSD_MAKETOKENTYPE(tokenType) ((tokenType << D3DVSD_TOKENTYPESHIFT) & D3DVSD_TOKENTYPEMASK)
#define D3DVSD_STREAM(_StreamNumber) (D3DVSD_MAKETOKENTYPE(D3DVSD_TOKEN_STREAM) | (_StreamNumber))
#define D3DVSD_REG(_VertexRegister, _Type) \
(D3DVSD_MAKETOKENTYPE(D3DVSD_TOKEN_STREAMDATA) | ((_Type) << D3DVSD_DATATYPESHIFT) | (_VertexRegister))
#define D3DVSD_END() 0xFFFFFFFF
#define D3DVSDT_FLOAT1 0x00
#define D3DVSDT_FLOAT2 0x01
#define D3DVSDT_FLOAT3 0x02
#define D3DVSDT_FLOAT4 0x03
#define D3DVSDT_D3DCOLOR 0x04
#define D3DVSDT_UBYTE4 0x05
#define D3DVSDT_SHORT2 0x06
#define D3DVSDT_SHORT4 0x07
#define D3DVSDE_POSITION 0
#define D3DVSDE_BLENDWEIGHT 1
#define D3DVSDE_BLENDINDICES 2
#define D3DVSDE_NORMAL 3
#define D3DVSDE_PSIZE 4
#define D3DVSDE_DIFFUSE 5
#define D3DVSDE_SPECULAR 6
#define D3DVSDE_TEXCOORD0 7
#define D3DVSDE_TEXCOORD1 8
#define D3DVSDE_TEXCOORD2 9
#define D3DVSDE_TEXCOORD3 10
#define D3DFVF_TEXTUREFORMAT2 0
#define D3DFVF_TEXTUREFORMAT1 3
#define D3DFVF_TEXTUREFORMAT3 1
@@ -777,6 +820,8 @@ struct IDirect3DDevice8
virtual HRESULT SetRenderState(D3DRENDERSTATETYPE State, DWORD Value) = 0;
virtual HRESULT SetTexture(DWORD Stage, IDirect3DBaseTexture8* pTexture) = 0;
virtual HRESULT SetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) = 0;
virtual HRESULT CreateVertexShader(const DWORD* pDeclaration, const DWORD* pFunction, DWORD* pHandle, DWORD Usage) = 0;
virtual HRESULT DeleteVertexShader(DWORD Handle) = 0;
virtual HRESULT SetVertexShader(DWORD Handle) = 0;
virtual HRESULT SetPixelShader(DWORD Handle) = 0;
virtual HRESULT SetVertexShaderConstant(DWORD Register, const void* pConstantData, DWORD ConstantCount) = 0;
+6
View File
@@ -423,3 +423,9 @@ LPSTR CharPrevExA(WORD CodePage, LPCSTR lpStart, LPCSTR lpCurrentChar, DWORD dwF
}
#endif // !_WIN32
int MessageBox(HWND, LPCSTR lpText, LPCSTR lpCaption, UINT)
{
std::fprintf(stderr, "[MessageBox] %s: %s\n", lpCaption ? lpCaption : "", lpText ? lpText : "");
return IDOK;
}
+15
View File
@@ -72,6 +72,21 @@ BOOL FindNextFile(HANDLE handle, WIN32_FIND_DATA* data);
BOOL FindClose(HANDLE handle);
void Sleep(DWORD milliseconds);
// MSVC <stdlib.h> __min / __max
#ifndef __min
#define __min(a, b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef __max
#define __max(a, b) (((a) > (b)) ? (a) : (b))
#endif
// user32 MessageBox (ANSI): no dialog on these hosts; writes caption and text to stderr, returns IDOK.
#define MB_OK 0x00000000L
#define MB_ICONHAND 0x00000010L
#define MB_ICONSTOP MB_ICONHAND
#define IDOK 1
int MessageBox(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);
// winmm `timeGetTime`: milliseconds since system start, wrapping at 2^32.
DWORD timeGetTime();
DWORD GetTickCount();
+457 -15
View File
@@ -1,21 +1,463 @@
#pragma once
// Shim for IDV SpeedTreeRT <SpeedTreeRT.h> (40250 extern/include): the CSpeedTreeRT members that
// SpeedTreeLib headers name. Tree geometry and wind go through platform/, which defines them.
// Shim for IDV SpeedTreeRT 1.6.0 <SpeedTreeRT.h> (40250 extern/include): the public section below is
// the SDK header verbatim. SpeedTreeRT.lib is closed Windows COFF, so the private section is replaced
// by one opaque pointer and the members SpeedTreeLib calls are implemented in
// platform/SpeedTreeLib/SpeedTreeRT.cpp. <cstddef> stands in for the size_t the SDK got from <windows.h>.
#include <cstddef>
///////////////////////////////////////////////////////////////////////
// Name: SpeedTreeRT.h
//
// *** INTERACTIVE DATA VISUALIZATION (IDV) PROPRIETARY INFORMATION ***
//
// 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
//
// 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.
//
// Release version 1.6.0 (December 19, 2003)
class CSpeedTreeRT
#pragma once
// define static or dynamic library build
#ifdef SPEEDTREERT_DYNAMIC_LIB
#ifdef IDV_SPEEDTREERT_EXPORTS
#define BUILD_SPEED_TREE_RT_SET __declspec(dllexport)
#else
#define BUILD_SPEED_TREE_RT_SET __declspec(dllimport)
#endif
#else
#define BUILD_SPEED_TREE_RT_SET
#endif
// big or little endian system
#ifdef __ppc__
#define ST_BIG_ENDIAN
#else
#define ST_LITTLE_ENDIAN
#endif
// Macintosh-specific
#ifdef __ppc__
#pragma export on
#endif
// forward refernces
class CIndexedGeometry;
class CTreeEngine;
class CLeafGeometry;
class CLightingEngine;
class CWindEngine;
class CTreeFileAccess;
class CSimpleBillboard;
class CFrondEngine;
struct STreeInstanceData;
struct SInstanceList;
struct SEmbeddedTexCoords;
struct SCollisionObjects;
class CProjectedShadow;
///////////////////////////////////////////////////////////////////////
// class SpeedTreeRT
//
// In an effort to make the SpeedTreeRT.h header file dependency free
// and easy to include into almost any project, a number of steps have
// been taken:
//
// 1. No external header files need to be included by SpeedTreeRT.h
// or by the application before including it.
//
// 2. Most of the implementation of the class is hidden by pointers
// to the major sections of the library (the internal classes
// can then just be forward-referenced)
//
// 3. Where possible, basic C++ datatypes are used to define the
// member functions' parameters.
//
// Because almost all of the implementation details are hidden, none of
// the functions for CSpeedTreeRT are inlined. However, inlined functions
// were copiously used within the library.
class BUILD_SPEED_TREE_RT_SET CSpeedTreeRT
{
public:
enum ECollisionObjectType
{
CO_SPHERE,
CO_CYLINDER,
CO_BOX
};
///////////////////////////////////////////////////////////////////////
// Enumerations
struct SGeometry;
struct STextures;
enum EWindMethod
{
WIND_GPU, WIND_CPU, WIND_NONE
};
float GetLeafLightingAdjustment() const;
float SetWindStrength(float fNewStrength, float fOldStrength = -1.0f, float fFrequencyTimeOffset = -1.0f);
void GetCollisionObject(unsigned int nIndex, ECollisionObjectType& eType, float* pPosition, float* pDimensions);
enum ELodMethod
{
LOD_POP, LOD_SMOOTH, LOD_NONE = 3
};
enum ELightingMethod
{
LIGHT_DYNAMIC, LIGHT_STATIC
};
enum EStaticLightingStyle
{
SLS_BASIC, SLS_USE_LIGHT_SOURCES, SLS_SIMULATE_SHADOWS
};
enum ECollisionObjectType
{
CO_SPHERE, CO_CYLINDER, CO_BOX
};
///////////////////////////////////////////////////////////////////////
// SGeometry bit vectors
//
// Passed into GetGeometry() in order to mask out unneeded geometric elements
#define SpeedTree_BranchGeometry (1 << 0)
#define SpeedTree_FrondGeometry (1 << 1)
#define SpeedTree_LeafGeometry (1 << 2)
#define SpeedTree_BillboardGeometry (1 << 3)
#define SpeedTree_SimpleBillboardOverride (1 << 4)
#define SpeedTree_AllGeometry SpeedTree_BranchGeometry + SpeedTree_FrondGeometry + SpeedTree_LeafGeometry + SpeedTree_BillboardGeometry
///////////////////////////////////////////////////////////////////////
// struct SGeometry declaration
struct BUILD_SPEED_TREE_RT_SET SGeometry
{
SGeometry( );
~SGeometry( );
///////////////////////////////////////////////////////////////////////
// struct SGeometry::SIndexed declaration
struct BUILD_SPEED_TREE_RT_SET SIndexed
{
SIndexed( );
~SIndexed( );
// these values change depending on the active discrete LOD level
int m_nDiscreteLodLevel; // range: [0, GetNumBranch/FrondLodLevels( ) - 1], -1 if inactive
unsigned short m_usNumStrips; // total number of strips in current LOD
const unsigned short* m_pStripLengths; // lengths of strips in current LOD (m_usNumStrips in length)
const unsigned short** m_pStrips; // triangle strip indices (m_usNumStrips in length)
// these values are shared across all discete LOD levels
unsigned short m_usVertexCount; // total vertex count in tables, referenced by all LOD levels
const unsigned long* m_pColors; // RGBA values for each leaf - static lighting only (m_usVertexCount in length)
const float* m_pNormals; // normals for each vertex (3 * m_usVertexCount in length)
const float* m_pBinormals; // binormals (bump mapping) for each vertex (3 * m_usVertexCount in length)
const float* m_pTangents; // tangents (bump mapping) for each vertex (3 * m_usVertexCount in length)
const float* m_pCoords; // coordinates for each vertex (3 * m_usVertexCount in length)
const float* m_pTexCoords0; // 1st layer (s,t) texcoords for each vertex (2 * m_usVertexCount in length)
const float* m_pTexCoords1; // 2nd layer (s,t) texcoords for each vertex (2 * m_usVertexCount in length)
const float* m_pWindWeights; // values from from 0.0 for rigid to 1.0 for flexible (m_usVertexCount in length)
const unsigned char* m_pWindMatrixIndices; // table of wind matrix indices (m_usVertexCount in length)
};
///////////////////////////////////////////////////////////////////////
// struct SGeometry::SLeaf declaration
struct BUILD_SPEED_TREE_RT_SET SLeaf
{
SLeaf( );
~SLeaf( );
// active LOD level data
bool m_bIsActive; // flag indicating visibility
float m_fAlphaTestValue; // 0.0 to 255.0 alpha testing value, used for fading
int m_nDiscreteLodLevel; // range: [0, GetNumLeafLodLevels( ) - 1]
unsigned short m_usLeafCount; // number of leaves stored in this structure
// tables for referencing the leaf cluster table
const unsigned char* m_pLeafMapIndices; // references which leaf texture map used for each leaf (m_usLeafCount in length)
const unsigned char* m_pLeafClusterIndices; // references which leaf cluster used for each leaf (m_usLeafCount in length)
const float* m_pCenterCoords; // (x,y,z) values for the centers of leaf clusters (3 * m_usLeafCount in length)
const float** m_pLeafMapTexCoords; // table of unique leaf cluster texcoords (m_usLeafCount in length) - each entry
// points to 4 pairs of (s,t) texcoords stored in one contiguous array
const float** m_pLeafMapCoords; // table of unique leaf cluster coordinates (m_usLeafCount in length) - each entry
// points to 4 sets of (x,y,z,0) coordinates stored in one contiguous array
// remaining vertex attributes
const unsigned long* m_pColors; // RGBA values for each leaf (m_usLeafCount in length)
const float* m_pNormals; // normals for each leaf (3 * m_usLeafCount in length)
const float* m_pBinormals; // binormals (bump mapping) for each leaf (3 * m_usLeafCount in length)
const float* m_pTangents; // tangents (bump mapping) for each leaf (3 * m_usLeafCount in length)
const float* m_pWindWeights; // values from from 0.0 for rigid to 1.0 for flexible (m_usLeafCount in length)
const unsigned char* m_pWindMatrixIndices; // table of wind matrix indices (m_usLeafCount in length)
};
///////////////////////////////////////////////////////////////////////
// struct SGeometry::SBillboard declaration
struct BUILD_SPEED_TREE_RT_SET SBillboard
{
SBillboard( );
~SBillboard( );
bool m_bIsActive; // flag indicating visibility
const float* m_pTexCoords; // 4 pairs of (s,t) texcoords stored in one contiguous array
const float* m_pCoords; // 4 sets of (x,y,z) coordindates stored in one contiguous array
float m_fAlphaTestValue; // 0.0 to 255.0 alpha testing value, used for fading
};
///////////////////////////////////////////////////////////////////////
// branch geometry
SIndexed m_sBranches; // holds the branch vertices and index buffers for all
// of the discrete LOD levels
float m_fBranchAlphaTestValue; // 0.0 to 255.0 alpha testing value, used for fading
///////////////////////////////////////////////////////////////////////
// frond geometry
SIndexed m_sFronds; // holds the frond vertices and index buffers for all
// of the discrete LOD levels
float m_fFrondAlphaTestValue; // 0.0 to 255.0 alpha testing value, used for fading
///////////////////////////////////////////////////////////////////////
// leaf geometry
SLeaf m_sLeaves0; // holds the primary leaf geometry, alpha fades into
SLeaf m_sLeaves1; // m_sLeaves1 during LOD transitions
///////////////////////////////////////////////////////////////////////
// billboard geometry
SBillboard m_sBillboard0; // holds the main simple billboard geometry, alpha fades
SBillboard m_sBillboard1; // into m_sBillboard1 in 360 degree mode
SBillboard m_sHorizontalBillboard; // optional horizontal billboard used for aerial views
};
///////////////////////////////////////////////////////////////////////
// struct SGeometry::STextures declaration
struct BUILD_SPEED_TREE_RT_SET STextures
{
STextures( );
~STextures( );
// branches
const char* m_pBranchTextureFilename; // null-terminated string
// leaves
unsigned int m_uiLeafTextureCount; // the number of char* elements in m_pLeafTextureFilenames
const char** m_pLeafTextureFilenames; // array of null-terminated strings m_uiLeafTextureCount in size
// fronds
unsigned int m_uiFrondTextureCount; // the number of char* elements in m_pFrondTextureFilenames
const char** m_pFrondTextureFilenames; // array of null-terminated strings m_uiFrondTextureCount in size
// composite
const char* m_pCompositeFilename; // null-terminated string
// self-shadow
const char* m_pSelfShadowFilename; // null-terminated string
};
///////////////////////////////////////////////////////////////////////
// Constructor/Destructor
CSpeedTreeRT( );
~CSpeedTreeRT( );
///////////////////////////////////////////////////////////////////////
// Memory allocation
static void* operator new(size_t nSize);
static void* operator new[](size_t nSize);
static void operator delete(void* pRawMemory);
static void operator delete[](void* pRawMemory);
///////////////////////////////////////////////////////////////////////
// Specifying a tree model
bool Compute(const float* pTransform = 0, unsigned int nSeed = 1, bool bCompositeStrips = true);
CSpeedTreeRT* Clone(float x = 0.0f, float y = 0.0f, float z = 0.0f, unsigned int nSeed = 0) const;
const CSpeedTreeRT* InstanceOf(void) const;
CSpeedTreeRT* MakeInstance(void);
void DeleteTransientData(void);
bool LoadTree(const char* pFilename);
bool LoadTree(const unsigned char* pBlock, unsigned int nNumBytes);
unsigned char* SaveTree(unsigned int& nNumBytes, bool bSaveLeaves = false) const;
void GetTreeSize(float& fSize, float& fVariance) const;
void SetTreeSize(float fNewSize, float fNewVariance = 0.0f);
unsigned int GetSeed( ) const;
const float* GetTreePosition(void) const;
void SetTreePosition(float x, float y, float z);
void SetLeafTargetAlphaMask(unsigned char ucMask = 0x54);
///////////////////////////////////////////////////////////////////////
// Lighting
// lighting style
ELightingMethod GetBranchLightingMethod(void) const;
void SetBranchLightingMethod(ELightingMethod eMethod);
ELightingMethod GetLeafLightingMethod(void) const;
void SetLeafLightingMethod(ELightingMethod eMethod);
ELightingMethod GetFrondLightingMethod(void) const;
void SetFrondLightingMethod(ELightingMethod eMethod);
EStaticLightingStyle GetStaticLightingStyle(void) const;
void SetStaticLightingStyle(EStaticLightingStyle eStyle);
float GetLeafLightingAdjustment( ) const;
void SetLeafLightingAdjustment(float fScalar);
// global lighting state
static bool GetLightState(unsigned int nLightIndex);
static void SetLightState(unsigned int nLightIndex, bool bLightOn);
static const float* GetLightAttributes(unsigned int nLightIndex);
static void SetLightAttributes(unsigned int nLightIndex, const float* pLightAttributes);
// branch material
const float* GetBranchMaterial(void) const;
void SetBranchMaterial(const float* pMaterial);
// leaf material
const float* GetLeafMaterial(void) const;
void SetLeafMaterial(const float* pMaterial);
// frond material
const float* GetFrondMaterial(void) const;
void SetFrondMaterial(const float* pMaterial);
///////////////////////////////////////////////////////////////////////
// Camera
static void GetCamera(float* pPosition, float* pDirection);
static void SetCamera(const float* pPosition, const float* pDirection);
///////////////////////////////////////////////////////////////////////
// Wind
static void SetTime(float fTime);
void ComputeWindEffects(bool bBranches, bool bLeaves, bool bFronds = true);
void ResetLeafWindState(void);
bool GetLeafRockingState(void) const;
void SetLeafRockingState(bool bFlag);
void SetNumLeafRockingGroups(unsigned int nRockingGroups);
EWindMethod GetLeafWindMethod(void) const;
void SetLeafWindMethod(EWindMethod eMethod);
EWindMethod GetBranchWindMethod(void) const;
void SetBranchWindMethod(EWindMethod eMethod);
EWindMethod GetFrondWindMethod(void) const;
void SetFrondWindMethod(EWindMethod eMethod);
float GetWindStrength(void) const;
float SetWindStrength(float fNewStrength, float fOldStrength = -1.0f, float fFrequencyTimeOffset = -1.0f);
static void SetNumWindMatrices(unsigned int nNumMatrices);
static void SetWindMatrix(unsigned int nMatrixIndex, const float* pMatrix);
void GetLocalMatrices(unsigned int& nStartingIndex, unsigned int& nMatrixSpan);
void SetLocalMatrices(unsigned int nStartingMatrix, unsigned int nMatrixSpan);
///////////////////////////////////////////////////////////////////////
// LOD
void ComputeLodLevel(void);
float GetLodLevel(void) const;
void SetLodLevel(float fLodLevel);
static void SetDropToBillboard(bool bFlag);
void GetLodLimits(float& fNear, float& fFar) const;
void SetLodLimits(float fNear, float fFar);
short GetDiscreteBranchLodLevel(float fLodLevel = -1.0f) const;
unsigned short GetDiscreteLeafLodLevel(float fLodLevel = -1.0f) const;
short GetDiscreteFrondLodLevel(float fLodLevel = -1.0f) const;
unsigned short GetNumBranchLodLevels(void) const;
unsigned short GetNumLeafLodLevels(void) const;
unsigned short GetNumFrondLodLevels(void) const;
///////////////////////////////////////////////////////////////////////
// Geometry
void DeleteBranchGeometry(void);
void DeleteFrondGeometry(void);
unsigned char* GetFrondGeometryMapIndexes(int nLodLevel) const;
const float* GetLeafBillboardTable(unsigned int& nEntryCount) const;
const float* GetLeafLodSizeAdjustments(void);
void GetGeometry(SGeometry& sGeometry, unsigned long ulBitVector = SpeedTree_AllGeometry, short sOverrideBranchLodValue = -1, short sOverrideFrondLodValue = -1, short sOverrideLeafLodValue = -1);
///////////////////////////////////////////////////////////////////////
// Textures
void GetTextures(STextures& sTextures) const;
void SetLeafTextureCoords(unsigned int nLeafMapIndex, const float* pTexCoords);
void SetFrondTextureCoords(unsigned int nFrondMapIndex, const float* pTexCoords);
static bool GetTextureFlip(void);
static void SetTextureFlip(bool bFlag);
void SetBranchTextureFilename(const char* pFilename);
void SetLeafTextureFilename(unsigned int nLeafMapIndex, const char* pFilename);
void SetFrondTextureFilename(unsigned int nFrondMapIndex, const char* pFilename);
///////////////////////////////////////////////////////////////////////
// Statistics & information
static void Authorize(const char* pKey);
static bool IsAuthorized(void);
static const char* GetCurrentError(void);
static void ResetError(void);
void GetBoundingBox(float* pBounds) const;
unsigned int GetLeafTriangleCount(float fLodLevel = -1.0f) const;
unsigned int GetBranchTriangleCount(float fLodLevel = -1.0f) const;
unsigned int GetFrondTriangleCount(float fLodLevel = -1.0f) const;
///////////////////////////////////////////////////////////////////////
// Collision objects
unsigned int GetCollisionObjectCount(void);
void GetCollisionObject(unsigned int nIndex, ECollisionObjectType& eType, float* pPosition, float* pDimensions);
///////////////////////////////////////////////////////////////////////
// User Data
const char* GetUserData(void) const;
private:
// PORT: the SDK's private engine members (m_pEngine .. m_afHorizontalCoords) are opaque here.
struct SImpl;
SImpl* m_pImpl;
CSpeedTreeRT(const CSpeedTreeRT&) = delete;
CSpeedTreeRT& operator=(const CSpeedTreeRT&) = delete;
};
// Macintosh-specific
#ifdef __ppc__
#pragma export off
#endif
@@ -3,6 +3,27 @@
// opaque, owned by platform/.
#include "d3d8.h"
// d3dx8core.h ID3DXBuffer / D3DXAssembleShader. There is no D3D8 shader assembler here:
// D3DXAssembleShader fails with no code and no error buffer.
struct ID3DXBuffer
{
virtual ~ID3DXBuffer() = default;
virtual ULONG Release() = 0;
virtual void* GetBufferPointer() = 0;
virtual DWORD GetBufferSize() = 0;
};
typedef ID3DXBuffer* LPD3DXBUFFER;
inline HRESULT D3DXAssembleShader(const void*, UINT, DWORD, LPD3DXBUFFER* ppConstants, LPD3DXBUFFER* ppCompiledShader, LPD3DXBUFFER* ppCompilationErrors)
{
if (ppConstants)
*ppConstants = nullptr;
if (ppCompiledShader)
*ppCompiledShader = nullptr;
if (ppCompilationErrors)
*ppCompilationErrors = nullptr;
return E_FAIL;
}
struct ID3DXMesh;
typedef ID3DXMesh* LPD3DXMESH;
struct ID3DXMatrixStack;