zfxLODTerrain.cpp
上传用户:junlon
上传日期:2022-01-05
资源大小:39075k
文件大小:32k
源码类别:

DirextX编程

开发平台:

Visual C++

  1. #include "stdafx.h"
  2. #include "zfxLODTerrain.h"
  3. #define LOWEST 100.0f
  4. #define HIGHEST 140.0f
  5. // 全局函数
  6. // num必须是一个大于0的数,返回log2(num)的整数部分,小数部分将被截掉
  7. // 例如,log2(512)返回 9, log2(514)和log2(1000)也将返回 9
  8. UINT log2(UINT num);
  9. // 先销毁该节点的子节点,再销毁该节点
  10. //void deleteTreeNode( CZFXLODTrnNode* pNode );
  11. CZFXLODTrnNode::CZFXLODTrnNode()
  12. {
  13. m_pTLChildNode = NULL;
  14. m_pBLChildNode = NULL;
  15. m_pTRChildNode = NULL;
  16. m_pBRChildNode = NULL;
  17. }
  18. CZFXLODTrnNode::~CZFXLODTrnNode()
  19. {
  20. SAFE_DELETE( m_pTLChildNode );
  21. SAFE_DELETE( m_pBLChildNode );
  22. SAFE_DELETE( m_pTRChildNode );
  23. SAFE_DELETE( m_pBRChildNode );
  24. }
  25. CZFXLODTrnNode::CZFXLODTrnNode(ZFXNODEPOSSIZE nodePosSize)
  26. {
  27. m_pParentNode = NULL;
  28. m_bIsLeaf = true;
  29. m_bReachAcceptableLevel = false;
  30. m_bTouched = false;
  31. m_bIsVisible = false;
  32. m_pTLChildNode = NULL;
  33. m_pBLChildNode = NULL;
  34. m_pTRChildNode = NULL;
  35. m_pBRChildNode = NULL;
  36. m_nodePosSize = nodePosSize;
  37. }
  38. void CZFXLODTrnNode::SplitNode()
  39. {
  40. UINT sizeDivide2 = m_nodePosSize.size >> 1;
  41. UINT sizeDivide4 = sizeDivide2 >> 1;
  42. // 左上角子节点
  43. ZFXNODEPOSSIZE nodePosSize( m_nodePosSize.x - sizeDivide4, m_nodePosSize.y - sizeDivide4, sizeDivide2 );
  44. m_pTLChildNode = new CZFXLODTrnNode( nodePosSize );
  45. m_pTLChildNode->m_pParentNode = this;
  46. m_pTLChildNode->m_level = m_level - 1;
  47. m_pTLChildNode->m_EnumValue = TOPLEFT;
  48. // 左下角子节点
  49. nodePosSize.y += sizeDivide2;
  50. m_pBLChildNode = new CZFXLODTrnNode( nodePosSize );
  51. m_pBLChildNode->m_pParentNode = this;
  52. m_pBLChildNode->m_level = m_level -1;
  53. m_pBLChildNode->m_EnumValue = BOTTOMLEFT;
  54. // 右下角子节点
  55. nodePosSize.x += sizeDivide2;
  56. m_pBRChildNode = new CZFXLODTrnNode( nodePosSize );
  57. m_pBRChildNode->m_pParentNode = this;
  58. m_pBRChildNode->m_level = m_level - 1;
  59. m_pBRChildNode->m_EnumValue = BOTTOMRIGHT;
  60. // 右上角子节点
  61. nodePosSize.y -= sizeDivide2;
  62. m_pTRChildNode = new CZFXLODTrnNode( nodePosSize );
  63. m_pTRChildNode->m_pParentNode = this;
  64. m_pTRChildNode->m_level = m_level -1;
  65. m_pTRChildNode->m_EnumValue = TOPRIGHT;
  66. // 分裂节点后,便不再是叶子节点
  67. m_bIsLeaf = false;
  68. }
  69. BOOL CZFXLODTrnNode::IsSplit()
  70. {
  71. if( m_level > 0 )
  72. return TRUE;
  73. else
  74. return FALSE;
  75. }
  76. /////////////////////////////////////////////////////////////////////////////////////////////////
  77. /////////////////////////////////////////////////////////////////////////////////////////////////
  78. // implementation of  CZFXLODTerrain
  79. CZFXLODTerrain::CZFXLODTerrain()
  80. {
  81. m_pHeadNode = NULL;
  82. m_numNodeRendered = 0;
  83. m_elevArray = NULL;
  84. m_pVB = NULL;
  85. m_pIB = NULL;
  86. m_vertexArray = NULL;
  87. m_indexArray = NULL;
  88. m_lowTexture = NULL;
  89. m_highTexture = NULL;
  90. }
  91. CZFXLODTerrain::CZFXLODTerrain( LPCTSTR strFileName )
  92. {
  93. m_pHeadNode = NULL;
  94. m_numNodeRendered = 0;
  95. // 从文件中读取地形数据。。。。。( .map文件,以float浮点形式读取)
  96. FILE* pFile = _tfopen(strFileName, "rb");
  97. int width, height;
  98. fread( &width, sizeof(int), 1, pFile );
  99. fread( &height,sizeof(int), 1, pFile );
  100. m_width = width;
  101. // 开辟二维高程数组,并以读取数据将其初始化
  102. m_elevArray = new float*[m_width];
  103. for(UINT i=0;i<m_width;i++)
  104. {
  105. m_elevArray[i] = new float[m_width];
  106. fread( m_elevArray[i], sizeof(float), m_width, pFile );
  107. }
  108. fclose(pFile);
  109. // 开辟纹理数组
  110. m_tuArray = new float[m_width];
  111. m_tvArray = new float[m_width];
  112. //在SetDimesion(...)函数中开辟空间,只有知道网格的几何宽度才能求取法线向量的值
  113. m_normalArray = NULL;
  114. for(UINT i=0;i<m_width;i++)
  115. {
  116. m_tvArray[i] = m_tuArray[i] = i * 20.0f / (int)m_width;
  117. }
  118. m_pVB = NULL;
  119. m_pIB = NULL;
  120. m_vertexArray = NULL;
  121. m_indexArray = NULL;
  122. m_lowTexture = NULL;
  123. m_highTexture = NULL;
  124. }
  125. CZFXLODTerrain::~CZFXLODTerrain()
  126. {
  127. // 销毁头结点及其所有的子节点,否则造成内存溢出
  128. SAFE_DELETE(m_pHeadNode);//调用delete pNode会在pNode的析构函数中先释放其四个子节点
  129. // 释放高程数组
  130. if( m_elevArray != NULL )
  131. {
  132. for(UINT i=0;i<m_width;i++)
  133. {
  134. delete [] m_elevArray[i];
  135. }
  136. delete [] m_elevArray;
  137. }
  138. // 释放法线向量数组
  139. if( m_normalArray != NULL )
  140. {
  141. for(UINT i=0;i<m_width;i++)
  142. {
  143. delete [] m_normalArray[i];
  144. }
  145. delete [] m_normalArray;
  146. }
  147. // 释放纹理数组
  148. delete [] m_tuArray;
  149. delete [] m_tvArray;
  150. }
  151. void CZFXLODTerrain::SetDimesion( float width, float height/*地形的几何尺寸*/,D3DXVECTOR2 centerPt/*地形的中点位置*/ )
  152. {
  153. m_fWidth = width;
  154. m_fHeight = height;
  155. m_centerPt = centerPt;
  156. m_GridWidth = m_fWidth/(m_width - 1);
  157. m_GridHeight = m_fHeight/(m_width - 1);
  158. // 开辟二维法线向量数组,并初始化
  159. m_normalArray = new D3DXVECTOR3*[m_width];
  160. for(UINT i=0;i<m_width;i++)
  161. {
  162. m_normalArray[i] = new D3DXVECTOR3[m_width];
  163. }
  164. // 二维法线向量数组初始化,不包括边界部分
  165. for(UINT i=0;i<m_width - 1;i++)
  166. {
  167. for(UINT j=0;j<m_width - 1;j++)
  168. {
  169. D3DXVECTOR3 vec[2];
  170. vec[0] = D3DXVECTOR3( -m_GridWidth, m_elevArray[i][j] - m_elevArray[i+1][j], 0 );
  171. vec[1] = D3DXVECTOR3( 0, m_elevArray[i][j] - m_elevArray[i][j+1], m_GridHeight );
  172. D3DXVec3Cross( &m_normalArray[i][j], &vec[0], &vec[1] );
  173. D3DXVec3Normalize( &m_normalArray[i][j], &m_normalArray[i][j] );
  174. }
  175. }
  176. // 地形边界处 法线向量的初始化
  177. for(UINT i=0;i<m_width;i++)
  178. {
  179. m_normalArray[i][m_width-1] = D3DXVECTOR3(0, 1, 0);
  180. m_normalArray[m_width-1][i] = D3DXVECTOR3(0, 1, 0);
  181. }
  182. }
  183. HRESULT CZFXLODTerrain::InitShader(LPDIRECT3DDEVICE9 pd3dDevice)
  184. {
  185. HRESULT hr;
  186. LPD3DXBUFFER pShaderBuffer;
  187. // Create vertex shader
  188. if( FAILED( hr = D3DXCompileShaderFromFile( "hlsl.vsd", NULL, NULL, "main", 
  189. "vs_2_0", 0/*D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION*//*Flag*/, &pShaderBuffer, NULL/*Error buffer*/, &m_pVConstTable )))
  190. return hr;
  191. if( FAILED( hr = pd3dDevice->CreateVertexShader((DWORD*)pShaderBuffer->GetBufferPointer(), &m_pVShader)))
  192. return hr;
  193. // Create pixel shader
  194. if( FAILED( hr = D3DXCompileShaderFromFile( "hlsl.psd", NULL, NULL, "main", 
  195. "ps_2_0", 0/*Flag*/, &pShaderBuffer, NULL/*Error buffer*/, &m_pPConstTable )))
  196. return hr;
  197. if( FAILED( hr = pd3dDevice->CreatePixelShader((DWORD*)pShaderBuffer->GetBufferPointer(), &m_pPShader)))
  198. return hr;
  199. return hr;
  200. }
  201. void CZFXLODTerrain::InitQuadTree()
  202. {
  203. m_pHeadNode = new CZFXLODTrnNode( ZFXNODEPOSSIZE( (m_width-1) >> 1, (m_width-1) >> 1, m_width-1 ) );
  204. m_pHeadNode->m_level = log2( m_width - 1 ) - 1;
  205. GrowQuadTree(m_pHeadNode);
  206. }
  207. void CZFXLODTerrain::LoadTextureFromFile( LPDIRECT3DDEVICE9 pd3dDevice, LPCTSTR lowTexFile, LPCTSTR highTexFile )
  208. {
  209. // 创建纹理
  210. if( FAILED( D3DXCreateTextureFromFile( pd3dDevice, lowTexFile, &m_lowTexture )))
  211. {
  212. char strTexFileName[60];
  213. sprintf( strTexFileName, "..\%s", lowTexFile );
  214. if( FAILED( D3DXCreateTextureFromFile( pd3dDevice, strTexFileName, &m_lowTexture )))
  215. m_lowTexture = NULL;
  216. }
  217. if( FAILED( D3DXCreateTextureFromFile( pd3dDevice, highTexFile, &m_highTexture )))
  218. {
  219. char strTexFileName[60];
  220. sprintf( strTexFileName, "..\%s", highTexFile );
  221. if( FAILED( D3DXCreateTextureFromFile( pd3dDevice, highTexFile, &m_highTexture )))
  222. m_highTexture = NULL;
  223. }
  224. }
  225. void CZFXLODTerrain::CreateTerrain( LPDIRECT3DDEVICE9 pd3dDevice, CZFXCamera* pCamera )
  226. {
  227. m_pCamera = pCamera;
  228. // 将根节点及其所有子节点的属性还原为false
  229. ClearTreeFlag(m_pHeadNode);
  230. // 遍历四叉树,判断节点的可见性和它的level是否达到要求,并对节点进行标记
  231. m_numNodeRendered = 0;
  232. m_frustum.Construct( pd3dDevice );
  233. ClimbQuadTree(m_pHeadNode, pd3dDevice);
  234. // 动态开辟顶点数组和索引数组
  235. UINT vertexArraySize = (m_numNodeRendered<<3) + m_numNodeRendered;  //m_numNodeRendered * 9
  236. UINT indexArraySize  = (m_numNodeRendered<<4) + (m_numNodeRendered<<3);   //m_numNodeRendered * 24
  237. m_vertexArray = new ZFXTRNVERTEX[vertexArraySize];
  238. m_indexArray  = new WORD[indexArraySize];
  239. // 遍历四叉树,寻找树中m_bReachAcceptableLevel == true的节点,并将所有符合条件的节点写进顶点数组和索引数组中
  240. m_vertexIndex = 0;
  241. m_indexIndex  = 0;
  242. RefineNode(m_pHeadNode);
  243. // 创建顶点缓冲和索引缓冲,还需设置某些flag以提高性能
  244. SAFE_RELEASE(m_pVB);
  245. SAFE_RELEASE(m_pIB);
  246. // 创建 vertex buffer
  247. if( FAILED( pd3dDevice->CreateVertexBuffer( vertexArraySize * sizeof(ZFXTRNVERTEX),
  248.         D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY/*Usage*/, D3DFVF_ZFXTRNVERTEX, D3DPOOL_SYSTEMMEM/*D3DPOOL*/, &m_pVB, NULL )))
  249. return;
  250. void* pVertices;
  251. if( FAILED(m_pVB->Lock( 0/*offset*/, vertexArraySize * sizeof(ZFXTRNVERTEX), (void**)&pVertices, 
  252. D3DLOCK_DISCARD|D3DLOCK_NOOVERWRITE/*Flag*/ )))
  253. return;
  254. memcpy( pVertices, m_vertexArray, vertexArraySize * sizeof(ZFXTRNVERTEX) );
  255. m_pVB->Unlock();
  256. // 创建 index buffer
  257. if( FAILED( pd3dDevice->CreateIndexBuffer( indexArraySize *sizeof(WORD), 
  258. D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY/*Usage*/, D3DFMT_INDEX16, D3DPOOL_SYSTEMMEM/*D3DPOOL*/, &m_pIB, NULL )))
  259. return;
  260. void* pIndices;
  261. if( FAILED(m_pIB->Lock( 0/*offset*/, indexArraySize * sizeof(WORD), (void**)&pIndices,
  262. D3DLOCK_DISCARD|D3DLOCK_NOOVERWRITE/*Flag*/ )))
  263. return;
  264. memcpy( pIndices, m_indexArray, indexArraySize * sizeof(WORD) );
  265. m_pIB->Unlock();
  266. // 创建 vertex buffer完毕,释放顶点数组
  267. delete [] m_vertexArray;
  268. // 创建 index buffer完毕,释放索引数组
  269. delete [] m_indexArray;
  270. }
  271. // 
  272. void  CZFXLODTerrain::RenderTerrain( LPDIRECT3DDEVICE9 pd3dDevice, BOOL bFog )
  273. {
  274. // pre rendering
  275. D3DXVECTOR4 lightDirVec(3.0f, 1.0f, 0, 0);
  276. // set vertex shader constant table
  277. D3DXMATRIXA16 mWorld, mView, mProj;
  278. pd3dDevice->GetTransform(D3DTS_WORLD, &mWorld);
  279. pd3dDevice->GetTransform(D3DTS_VIEW, &mView);
  280. pd3dDevice->GetTransform(D3DTS_PROJECTION, &mProj);
  281. D3DXMATRIXA16 mWorldViewProj = mWorld * mView * mProj;
  282. D3DXMATRIXA16 mWorldView = mWorld * mView;
  283. m_pVConstTable->SetMatrix(pd3dDevice, "mWorldViewProj", &mWorldViewProj);
  284. m_pVConstTable->SetMatrix(pd3dDevice, "mWorldView", &mWorldView);
  285. m_pVConstTable->SetFloat( pd3dDevice, "lowest", LOWEST);
  286. m_pVConstTable->SetFloat( pd3dDevice, "highest", HIGHEST);
  287. m_pVConstTable->SetFloat( pd3dDevice, "ambient", 0.5f);
  288. m_pVConstTable->SetVector(pd3dDevice, "lightDir", &lightDirVec);
  289. // set pixel shader constant table
  290. D3DXHANDLE hLowSmpl =  m_pPConstTable->GetConstantByName(NULL, "lowTexSmpl");
  291. D3DXHANDLE hHighSmpl = m_pPConstTable->GetConstantByName(NULL, "highTexSmpl");
  292. D3DXCONSTANT_DESC lowSmplDesc, highSmplDesc;
  293. UINT count;
  294. m_pPConstTable->GetConstantDesc(hLowSmpl, &lowSmplDesc, &count);
  295. m_pPConstTable->GetConstantDesc(hHighSmpl,&highSmplDesc,&count);
  296. // set low texture
  297. pd3dDevice->SetTexture(lowSmplDesc.RegisterIndex, m_lowTexture);
  298. pd3dDevice->SetSamplerState(lowSmplDesc.RegisterIndex, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
  299. pd3dDevice->SetSamplerState(lowSmplDesc.RegisterIndex, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
  300. pd3dDevice->SetSamplerState(lowSmplDesc.RegisterIndex, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
  301. pd3dDevice->SetSamplerState(lowSmplDesc.RegisterIndex, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR);
  302. pd3dDevice->SetSamplerState(lowSmplDesc.RegisterIndex, D3DSAMP_ADDRESSV, D3DTADDRESS_MIRROR);
  303. // set high texture
  304. pd3dDevice->SetTexture(highSmplDesc.RegisterIndex, m_highTexture);
  305. pd3dDevice->SetSamplerState(highSmplDesc.RegisterIndex, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
  306. pd3dDevice->SetSamplerState(highSmplDesc.RegisterIndex, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
  307. pd3dDevice->SetSamplerState(highSmplDesc.RegisterIndex, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
  308. pd3dDevice->SetSamplerState(highSmplDesc.RegisterIndex, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR);
  309. pd3dDevice->SetSamplerState(highSmplDesc.RegisterIndex, D3DSAMP_ADDRESSV, D3DTADDRESS_MIRROR);
  310. // set fog
  311. D3DXVECTOR4 fogColor(0.18f, 0.2f, 0.7f, 1.0f);
  312. m_pVConstTable->SetFloat(pd3dDevice, "nearFog", 200.0f);
  313. m_pVConstTable->SetFloat(pd3dDevice, "farFog", 1000.0f);
  314. m_pPConstTable->SetVector(pd3dDevice, "fogColor", &fogColor);
  315. if(bFog)
  316. m_pPConstTable->SetFloat(pd3dDevice, "bFog", 1.0f);
  317. else
  318. m_pPConstTable->SetFloat(pd3dDevice, "bFog", 0.0f);
  319. // rendering
  320. pd3dDevice->SetFVF( D3DFVF_ZFXTRNVERTEX );
  321. pd3dDevice->SetStreamSource( 0, m_pVB, 0, sizeof(ZFXTRNVERTEX) );
  322. pd3dDevice->SetVertexShader(m_pVShader);
  323. pd3dDevice->SetPixelShader(m_pPShader);
  324. pd3dDevice->SetIndices( m_pIB );
  325. pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0/*base index index*/, 0,/*MinVertexIndex*/
  326. (m_numNodeRendered << 3 ) + m_numNodeRendered/*NumVertices*/,
  327. 0/*StartIndex*/,
  328. (m_numNodeRendered << 3 )/*PrimitiveCount*/);
  329. // post rendering
  330. pd3dDevice->SetVertexShader(NULL);
  331. pd3dDevice->SetPixelShader(NULL);
  332. }
  333. // 给定X坐标和Y坐标,求出该点的地形高度  未完
  334. float CZFXLODTerrain::GetTerrainElev(float x, float z)
  335. {
  336. /*float elev;*/
  337. // 先求得对应于点 (x, z) 的相对坐标
  338. float xFloat, zFloat;
  339. xFloat = (x - m_centerPt.x) / m_GridWidth + ((m_width - 1)>>1);
  340. zFloat = (z - m_centerPt.y) / m_GridHeight + ((m_width - 1)>>1);
  341. int i, j;
  342. j = (int)xFloat;  // 取下整数
  343. i = (int)zFloat;  // 取下整数
  344. return m_elevArray[i][j];
  345. }
  346. /////////////////////////////////////////////////////////////////////////////////////////////////////
  347. // 以下为私有成员函数
  348. // 将头结点生长成一棵完全的二叉树
  349. void CZFXLODTerrain::GrowQuadTree(CZFXLODTrnNode* pNode)
  350. {
  351. if(pNode->IsSplit())
  352. {
  353. pNode->SplitNode();
  354. GrowQuadTree( pNode->m_pBLChildNode );
  355. GrowQuadTree( pNode->m_pTLChildNode );
  356. GrowQuadTree( pNode->m_pTRChildNode );
  357. GrowQuadTree( pNode->m_pBRChildNode );
  358. }
  359. }
  360. // 遍历四叉树,判断节点的可见性和它的level是否达到要求,并对节点进行标记
  361. void CZFXLODTerrain::ClimbQuadTree( CZFXLODTrnNode* pNode, LPDIRECT3DDEVICE9 pd3dDevice )
  362. {
  363. pNode->m_bTouched = true;
  364. if( IsVisible( pNode, pd3dDevice ) )// 如果头结点可见,对该节点进行处理,否则,忽略之
  365. {
  366. pNode->m_bIsVisible = true;
  367. if( IsReachAcceptableLevel( pNode )||pNode->m_bIsLeaf )
  368. {// 如果该节点的level已足够低,或者该节点是叶子节点,不再往下遍历
  369. pNode->m_bReachAcceptableLevel = true;
  370. // 下面这句话要求每个节点只能被扩展一次
  371. m_numNodeRendered ++;
  372. }
  373. else
  374. {// 如果该节点的level还不够低,并且不是叶子节点,继续往下扩展遍历
  375. // 往下扩展遍历之前,确认它的四个相邻顶点的父节点被扩展遍历过
  376. pNode->m_bReachAcceptableLevel = false;
  377. CZFXLODTrnNode* pAdjNodeArray[4];
  378. GetAdjNodeParent4( pAdjNodeArray, pNode );
  379. for(int i=0;i<4;i++)
  380. {
  381. if( pAdjNodeArray[i] != NULL && pAdjNodeArray[i]->m_bTouched == false )
  382. ClimbQuadTree( pAdjNodeArray[i], pd3dDevice );
  383. }
  384. if( false == pNode->m_pBLChildNode->m_bTouched )
  385. ClimbQuadTree( pNode->m_pBLChildNode, pd3dDevice );
  386. if( false == pNode->m_pTLChildNode->m_bTouched )
  387. ClimbQuadTree( pNode->m_pTLChildNode, pd3dDevice );
  388. if( false == pNode->m_pBRChildNode->m_bTouched )
  389. ClimbQuadTree( pNode->m_pBRChildNode, pd3dDevice );
  390. if( false == pNode->m_pTRChildNode->m_bTouched )
  391. ClimbQuadTree( pNode->m_pTRChildNode, pd3dDevice );
  392. }
  393. }
  394. else
  395. {
  396. pNode->m_bIsVisible = false;
  397. pNode->m_bReachAcceptableLevel = false;
  398. }
  399. }
  400. // 得到节点的四个相邻节点的父节点,将它们的指针存储在一个数组里
  401. void CZFXLODTerrain::GetAdjNodeParent4(CZFXLODTrnNode** pAdjNodeArray, CZFXLODTrnNode* pNode)
  402. {
  403. ZFXNODEPOSSIZE posSize = pNode->GetPosSize();
  404. // 查找该节点上面的那个节点的父节点
  405. pAdjNodeArray[0] = FindParentNode( posSize.x, posSize.y - posSize.size );
  406. // 查找该节点下面的那个节点的父节点
  407. pAdjNodeArray[1] = FindParentNode( posSize.x, posSize.y + posSize.size );
  408. // 查找该节点左边的那个节点的父节点
  409. pAdjNodeArray[2] = FindParentNode( posSize.x - posSize.size, posSize.y );
  410. // 查找该节点右边的那个节点的父节点
  411. pAdjNodeArray[3] = FindParentNode( posSize.x + posSize.size, posSize.y );
  412. }
  413. // 查找相对位置为(x, y)的那个节点的父节点
  414. CZFXLODTrnNode* CZFXLODTerrain::FindParentNode(UINT x, UINT y)
  415. {
  416. CZFXLODTrnNode* pNode = m_pHeadNode;
  417. while(1)
  418. {
  419. if( pNode == NULL )
  420. return NULL;
  421. ZFXNODEPOSSIZE posSize = pNode->GetPosSize();
  422. if( posSize.x == x )
  423. return pNode->m_pParentNode; // 找到该节点,返回它的父节点
  424. else if( posSize.x < x )
  425. {
  426. if( posSize.y < y )
  427. pNode = pNode->m_pBRChildNode;
  428. else //posSize.y > y
  429. pNode = pNode->m_pTRChildNode;
  430. }
  431. else //posSize.x > x
  432. {
  433. if( posSize.y < y )
  434. pNode = pNode->m_pBLChildNode;
  435. else //posSize.y > y
  436. pNode = pNode->m_pTLChildNode;
  437. }
  438. }
  439. }
  440. // 查找相对位置为(x, y)的那个节点
  441. CZFXLODTrnNode* CZFXLODTerrain::FindNode(UINT x, UINT y)
  442. {
  443. CZFXLODTrnNode* pNode = m_pHeadNode;
  444. while(1)
  445. {
  446. if( pNode == NULL )
  447. return NULL;
  448. ZFXNODEPOSSIZE posSize = pNode->GetPosSize();
  449. if( posSize.x == x )
  450. return pNode; // 找到该节点,返回它的父节点
  451. else if( posSize.x < x )
  452. {
  453. if( posSize.y < y )
  454. pNode = pNode->m_pBRChildNode;
  455. else //posSize.y > y
  456. pNode = pNode->m_pTRChildNode;
  457. }
  458. else //posSize.x > x
  459. {
  460. if( posSize.y < y )
  461. pNode = pNode->m_pBLChildNode;
  462. else //posSize.y > y
  463. pNode = pNode->m_pTLChildNode;
  464. }
  465. }
  466. }
  467. // 判断某个节点是否可见
  468. BOOL CZFXLODTerrain::IsVisible(CZFXLODTrnNode* pNode, LPDIRECT3DDEVICE9 pd3dDevice)
  469. {
  470. ZFXNODEPOSSIZE posSize = pNode->GetPosSize();
  471. D3DXVECTOR3 centerPos;
  472. centerPos.x = ( int(posSize.x - ((m_width - 1)>>1)) ) * m_GridWidth + m_centerPt.x;
  473. centerPos.y = m_elevArray[posSize.y][posSize.x];
  474. centerPos.z = ( int(posSize.y - ((m_width -1 )>>1)) ) * m_GridHeight + m_centerPt.y;
  475. float radius = float((int)(posSize.size) * m_GridWidth)/1.414f;
  476. return m_frustum.CheckSphere( centerPos, radius );
  477. }
  478. // 判断某个节点的level是否已足够低
  479. BOOL CZFXLODTerrain::IsReachAcceptableLevel(CZFXLODTrnNode* pNode)
  480. {
  481. // 先求取节点中心的绝对坐标值
  482. ZFXNODEPOSSIZE posSize = pNode->GetPosSize();
  483. D3DXVECTOR3 centerPos;
  484. centerPos.x = ( int(posSize.x - ((m_width - 1)>>1)) ) * m_GridWidth + m_centerPt.x;
  485. centerPos.y = m_elevArray[posSize.y][posSize.x];
  486. centerPos.z = ( int(posSize.y - ((m_width -1 )>>1)) ) * m_GridHeight + m_centerPt.y;
  487. // 再获取眼睛的绝对坐标值
  488. D3DXVECTOR3 eyePt( m_pCamera->GetPosX(), m_pCamera->GetPosY(), m_pCamera->GetPosZ() );
  489. // 求取眼睛与节点中心之间的绝对距离
  490. D3DXVECTOR3 vec3 = centerPos - eyePt;
  491. float distance = D3DXVec3Length( &vec3 );
  492. ////
  493. D3DXVECTOR3 lookAtVec;
  494. m_pCamera->GetLookVec(&lookAtVec);
  495. D3DXVec3Normalize(&lookAtVec, &lookAtVec);
  496. D3DXVec3Normalize(&vec3, &vec3);
  497. float fNum = D3DXVec3Dot(&vec3, &lookAtVec);
  498. if(fNum < 0)
  499. fNum = 0;
  500. fNum = fNum/2 + 0.5f;
  501. if( distance / fNum > float(posSize.size << 4) )
  502. return TRUE;
  503. else
  504. return FALSE;
  505. }
  506. // 遍历四叉树,寻找树中m_bReachAcceptableLevel == true的节点,并将所有符合条件的节点写进顶点数组和索引数组中
  507. // 每个节点由8个三角形组成,9个顶点数据,24个索引数据
  508. void CZFXLODTerrain::RefineNode(CZFXLODTrnNode* pNode)
  509. {
  510. if( pNode->m_bIsVisible )
  511. {
  512. if( pNode->m_bReachAcceptableLevel/* || !pNode->m_bIsVisible*//*for debug*/)
  513. {// 节点的细节已足够,将它送入顶点数组和索引数组
  514. // 顶点数组赋值,   0 1 2
  515. //                  3 4 5 
  516. //                  6 7 8
  517. // 计算顶点的位置向量和纹理坐标
  518. ZFXNODEPOSSIZE posSize = pNode->GetPosSize();
  519. UINT sizeDivide2 = posSize.size >> 1;
  520. float top = ( int(posSize.y - sizeDivide2 - ((m_width -1 )>>1)) ) * m_GridHeight + m_centerPt.y;
  521. float bottom = ( int(posSize.y + sizeDivide2 - ((m_width -1 )>>1)) ) * m_GridHeight + m_centerPt.y;
  522. float left = ( int(posSize.x - sizeDivide2 - ((m_width -1 )>>1)) ) * m_GridWidth + m_centerPt.x;
  523. float right = ( int(posSize.x + sizeDivide2 - ((m_width -1 )>>1)) ) * m_GridWidth + m_centerPt.x;
  524. float centerX = ( int(posSize.x - ((m_width -1 )>>1)) ) * m_GridWidth + m_centerPt.x;
  525. float centerY = ( int(posSize.y - ((m_width -1 )>>1)) ) * m_GridWidth + m_centerPt.y;
  526. // 左上角顶点
  527. m_vertexArray[m_vertexIndex + 0].position.x = left;
  528. m_vertexArray[m_vertexIndex + 0].position.z = top;
  529. m_vertexArray[m_vertexIndex + 0].position.y = m_elevArray[posSize.y - sizeDivide2][posSize.x - sizeDivide2];
  530. m_vertexArray[m_vertexIndex + 0].normal   = m_normalArray[posSize.y - sizeDivide2][posSize.x - sizeDivide2];
  531. // for debug
  532. //m_vertexArray[m_vertexIndex + 0].position.y = 0;
  533. m_vertexArray[m_vertexIndex + 0].tu = m_tuArray[posSize.x - sizeDivide2];
  534. m_vertexArray[m_vertexIndex + 0].tv = m_tvArray[posSize.y - sizeDivide2];
  535. // 上边顶点
  536. // 判断它上方的那个相邻节点的 m_bTouched 属性是否为true,如为真从数组中读取高程值,否则取相邻顶点高程值的平均值
  537. m_vertexArray[m_vertexIndex + 1].position.x = centerX;
  538. m_vertexArray[m_vertexIndex + 1].position.z = top;
  539. CZFXLODTrnNode* pAdjNode = FindNode( posSize.x, posSize.y - posSize.size );
  540. if( pAdjNode != NULL )
  541. {
  542. if( pAdjNode->m_bTouched )
  543. {
  544. m_vertexArray[m_vertexIndex + 1].position.y = m_elevArray[posSize.y - sizeDivide2][posSize.x];
  545. m_vertexArray[m_vertexIndex + 1].normal   = m_normalArray[posSize.y - sizeDivide2][posSize.x];
  546. }
  547. else
  548. {
  549. //m_vertexArray[m_vertexIndex + 1].position.y = m_elevArray[posSize.y - sizeDivide2][posSize.x];
  550. m_vertexArray[m_vertexIndex + 1].position.y = ( m_elevArray[posSize.y - sizeDivide2][posSize.x - sizeDivide2]
  551. + m_elevArray[posSize.y - sizeDivide2][posSize.x + sizeDivide2])/2;
  552. m_vertexArray[m_vertexIndex + 1].normal = ( m_normalArray[posSize.y - sizeDivide2][posSize.x - sizeDivide2]
  553. + m_normalArray[posSize.y - sizeDivide2][posSize.x + sizeDivide2])/2;
  554. }
  555. }
  556. else
  557. {
  558. m_vertexArray[m_vertexIndex + 1].position.y = m_elevArray[posSize.y - sizeDivide2][posSize.x];
  559. m_vertexArray[m_vertexIndex + 1].normal   = m_normalArray[posSize.y - sizeDivide2][posSize.x];
  560. }
  561. // for debug
  562. //m_vertexArray[m_vertexIndex + 1].position.y = 0;
  563. m_vertexArray[m_vertexIndex + 1].tu = m_tuArray[posSize.x];
  564. m_vertexArray[m_vertexIndex + 1].tv = m_tvArray[posSize.y - sizeDivide2];
  565. // 右上角顶点
  566. m_vertexArray[m_vertexIndex + 2].position.x = right;
  567. m_vertexArray[m_vertexIndex + 2].position.z = top;
  568. m_vertexArray[m_vertexIndex + 2].position.y = m_elevArray[posSize.y - sizeDivide2][posSize.x + sizeDivide2];
  569. m_vertexArray[m_vertexIndex + 2].normal   = m_normalArray[posSize.y - sizeDivide2][posSize.x + sizeDivide2];
  570. // for debug
  571. //m_vertexArray[m_vertexIndex + 2].position.y = 0;
  572. m_vertexArray[m_vertexIndex + 2].tu = m_tuArray[posSize.x + sizeDivide2];
  573. m_vertexArray[m_vertexIndex + 2].tv = m_tvArray[posSize.y - sizeDivide2];
  574. // 左边顶点
  575. // 判断它左方的那个相邻节点的 m_bTouched 属性是否为true,如为真从数组中读取高程值,否则取相邻顶点高程值的平均值
  576. m_vertexArray[m_vertexIndex + 3].position.x = left;
  577. m_vertexArray[m_vertexIndex + 3].position.z = centerY;
  578. pAdjNode = FindNode( posSize.x - posSize.size, posSize.y );
  579. if( pAdjNode != NULL )
  580. {
  581. if( pAdjNode->m_bTouched )
  582. {
  583. m_vertexArray[m_vertexIndex + 3].position.y = m_elevArray[posSize.y][posSize.x - sizeDivide2];
  584. m_vertexArray[m_vertexIndex + 3].normal   = m_normalArray[posSize.y][posSize.x - sizeDivide2];
  585. }
  586. else
  587. {
  588. //m_vertexArray[m_vertexIndex + 3].position.y = m_elevArray[posSize.y][posSize.x - sizeDivide2];
  589. m_vertexArray[m_vertexIndex + 3].position.y = ( m_elevArray[posSize.y - sizeDivide2][posSize.x - sizeDivide2]
  590. + m_elevArray[posSize.y + sizeDivide2][posSize.x - sizeDivide2])/2;
  591. m_vertexArray[m_vertexIndex + 3].normal = ( m_normalArray[posSize.y - sizeDivide2][posSize.x - sizeDivide2]
  592. + m_normalArray[posSize.y + sizeDivide2][posSize.x - sizeDivide2])/2;
  593. }
  594. }
  595. else
  596. {
  597. m_vertexArray[m_vertexIndex + 3].position.y = m_elevArray[posSize.y][posSize.x - sizeDivide2];
  598. m_vertexArray[m_vertexIndex + 3].normal   = m_normalArray[posSize.y][posSize.x - sizeDivide2];
  599. }
  600. // for debug
  601. //m_vertexArray[m_vertexIndex + 3].position.y = 0;
  602. m_vertexArray[m_vertexIndex + 3].tu = m_tuArray[posSize.x - sizeDivide2];
  603. m_vertexArray[m_vertexIndex + 3].tv = m_tvArray[posSize.y];
  604. // 中心顶点
  605. m_vertexArray[m_vertexIndex + 4].position.x = centerX;
  606. m_vertexArray[m_vertexIndex + 4].position.z = centerY;
  607. m_vertexArray[m_vertexIndex + 4].position.y = m_elevArray[posSize.y][posSize.x];
  608. m_vertexArray[m_vertexIndex + 4].normal   = m_normalArray[posSize.y][posSize.x];
  609. // for debug
  610. //m_vertexArray[m_vertexIndex + 4].position.y = 0;
  611. m_vertexArray[m_vertexIndex + 4].tu = m_tuArray[posSize.x];
  612. m_vertexArray[m_vertexIndex + 4].tv = m_tvArray[posSize.y];
  613. // 右边顶点
  614. // 判断它左方的那个相邻节点的 m_bTouched 属性是否为true,如为真从数组中读取高程值,否则取相邻顶点高程值的平均值
  615. m_vertexArray[m_vertexIndex + 5].position.x = right;
  616. m_vertexArray[m_vertexIndex + 5].position.z = centerY;
  617. pAdjNode = FindNode( posSize.x + posSize.size, posSize.y );
  618. if( pAdjNode != NULL )
  619. {
  620. if( pAdjNode->m_bTouched )
  621. {
  622. m_vertexArray[m_vertexIndex + 5].position.y = m_elevArray[posSize.y][posSize.x + sizeDivide2];
  623. m_vertexArray[m_vertexIndex + 5].normal   = m_normalArray[posSize.y][posSize.x + sizeDivide2];
  624. }
  625. else
  626. {
  627. //m_vertexArray[m_vertexIndex + 5].position.y = m_elevArray[posSize.y][posSize.x + sizeDivide2];
  628. m_vertexArray[m_vertexIndex + 5].position.y = ( m_elevArray[posSize.y - sizeDivide2][posSize.x + sizeDivide2]
  629. + m_elevArray[posSize.y + sizeDivide2][posSize.x + sizeDivide2])/2;
  630. m_vertexArray[m_vertexIndex + 5].normal = ( m_normalArray[posSize.y - sizeDivide2][posSize.x + sizeDivide2]
  631. + m_normalArray[posSize.y + sizeDivide2][posSize.x + sizeDivide2])/2;
  632. }
  633. }
  634. else
  635. {
  636. m_vertexArray[m_vertexIndex + 5].position.y = m_elevArray[posSize.y][posSize.x + sizeDivide2];
  637. m_vertexArray[m_vertexIndex + 5].normal = m_normalArray[posSize.y][posSize.x + sizeDivide2];
  638. }
  639. // for debug
  640. //m_vertexArray[m_vertexIndex + 5].position.y = 0;
  641. m_vertexArray[m_vertexIndex + 5].tu = m_tuArray[posSize.x + sizeDivide2];
  642. m_vertexArray[m_vertexIndex + 5].tv = m_tvArray[posSize.y];
  643. // 左下角顶点
  644. m_vertexArray[m_vertexIndex + 6].position.x = left;
  645. m_vertexArray[m_vertexIndex + 6].position.z = bottom;
  646. m_vertexArray[m_vertexIndex + 6].position.y = m_elevArray[posSize.y + sizeDivide2][posSize.x - sizeDivide2];
  647. m_vertexArray[m_vertexIndex + 6].normal   = m_normalArray[posSize.y + sizeDivide2][posSize.x - sizeDivide2];
  648. // for debug
  649. //m_vertexArray[m_vertexIndex + 6].position.y = 0;
  650. m_vertexArray[m_vertexIndex + 6].tu = m_tuArray[posSize.x - sizeDivide2];
  651. m_vertexArray[m_vertexIndex + 6].tv = m_tvArray[posSize.y + sizeDivide2];
  652. // 下边顶点
  653. // 判断它左方的那个相邻节点的 m_bTouched 属性是否为true,如为真从数组中读取高程值,否则取相邻顶点高程值的平均值
  654. m_vertexArray[m_vertexIndex + 7].position.x = centerX;
  655. m_vertexArray[m_vertexIndex + 7].position.z = bottom;
  656. pAdjNode = FindNode( posSize.x, posSize.y + posSize.size );
  657. if( pAdjNode != NULL )
  658. {
  659. if( pAdjNode->m_bTouched )
  660. {
  661. m_vertexArray[m_vertexIndex + 7].position.y = m_elevArray[posSize.y + sizeDivide2][posSize.x];
  662. m_vertexArray[m_vertexIndex + 7].normal   = m_normalArray[posSize.y + sizeDivide2][posSize.x];
  663. }
  664. else
  665. {
  666. //m_vertexArray[m_vertexIndex + 7].position.y = m_elevArray[posSize.y + sizeDivide2][posSize.x];
  667. m_vertexArray[m_vertexIndex + 7].position.y = ( m_elevArray[posSize.y + sizeDivide2][posSize.x - sizeDivide2]
  668. + m_elevArray[posSize.y + sizeDivide2][posSize.x + sizeDivide2])/2;
  669. m_vertexArray[m_vertexIndex + 7].normal = ( m_normalArray[posSize.y + sizeDivide2][posSize.x - sizeDivide2]
  670. + m_normalArray[posSize.y + sizeDivide2][posSize.x + sizeDivide2])/2;
  671. }
  672. }
  673. else
  674. {
  675. m_vertexArray[m_vertexIndex + 7].position.y = m_elevArray[posSize.y + sizeDivide2][posSize.x];
  676. m_vertexArray[m_vertexIndex + 7].normal   = m_normalArray[posSize.y + sizeDivide2][posSize.x];
  677. }
  678. // for debug
  679. //m_vertexArray[m_vertexIndex + 7].position.y = 0;
  680. m_vertexArray[m_vertexIndex + 7].tu = m_tuArray[posSize.x];
  681. m_vertexArray[m_vertexIndex + 7].tv = m_tvArray[posSize.y + sizeDivide2];
  682. // 右下角顶点
  683. m_vertexArray[m_vertexIndex + 8].position.x = right;
  684. m_vertexArray[m_vertexIndex + 8].position.z = bottom;
  685. m_vertexArray[m_vertexIndex + 8].position.y = m_elevArray[posSize.y + sizeDivide2][posSize.x + sizeDivide2];
  686. m_vertexArray[m_vertexIndex + 8].normal   = m_normalArray[posSize.y + sizeDivide2][posSize.x + sizeDivide2];
  687. // for debug
  688. //m_vertexArray[m_vertexIndex + 8].position.y = 0;
  689. m_vertexArray[m_vertexIndex + 8].tu = m_tuArray[posSize.x + sizeDivide2];
  690. m_vertexArray[m_vertexIndex + 8].tv = m_tvArray[posSize.y + sizeDivide2];
  691. //// 顶点数组赋值,   0 1 2
  692. ////                  3 4 5 
  693. ////                  6 7 8
  694. //// 计算顶点的法线向量
  695. ///*ZFXNODEPOSSIZE posSize = pNode->GetPosSize();
  696. //UINT sizeDivide2 = posSize.size >> 1;*/   // 该节点的位置信息(相对)
  697. //POINT pos[9];  //pos[9]保存了0~8个节点的相对位置信息
  698. //// pos数组赋值
  699. //pos[0].x = posSize.x - sizeDivide2;  pos[0].y = posSize.y - sizeDivide2;
  700. //pos[1].x = posSize.x;                pos[1].y = posSize.y - sizeDivide2;
  701. //pos[2].x = posSize.x + sizeDivide2;  pos[2].y = posSize.y - sizeDivide2;
  702. //pos[3].x = posSize.x - sizeDivide2;  pos[3].y = posSize.y;
  703. //pos[4].x = posSize.x;                pos[4].y = posSize.y;
  704. //pos[5].x = posSize.x + sizeDivide2;  pos[5].y = posSize.y;
  705. //pos[6].x = posSize.x - sizeDivide2;  pos[6].y = posSize.y + sizeDivide2;
  706. //pos[7].x = posSize.x;                pos[7].y = posSize.y + sizeDivide2;
  707. //pos[8].x = posSize.x + sizeDivide2;  pos[8].y = posSize.y + sizeDivide2;
  708. //for(int i=0;i<9;i++)
  709. //{
  710. // D3DXVECTOR3 vec[2];
  711. // vec[0].x = -m_GridWidth;
  712. // // 防止pos[i].x + 1冲出边界
  713. // if((UINT)(pos[i].x) < m_width - 1)
  714. // vec[0].y = m_elevArray[pos[i].y][pos[i].x] - m_elevArray[pos[i].y][pos[i].x + 1];
  715. // else
  716. // vec[0].y = m_elevArray[pos[i].y][pos[i].x - 1] - m_elevArray[pos[i].y][pos[i].x];
  717. // vec[0].z = 0;
  718. // vec[1].x = 0;
  719. // // 防止pos[i].y + 1冲出边界
  720. // if((UINT)(pos[i].y) < m_width - 1)
  721. // vec[1].y = m_elevArray[pos[i].y + 1][pos[i].x] - m_elevArray[pos[i].y][pos[i].x];
  722. // else
  723. // vec[1].y = m_elevArray[pos[i].y][pos[i].x] - m_elevArray[pos[i].y - 1][pos[i].x];
  724. // vec[1].z = m_GridHeight;
  725. // D3DXVec3Cross( &m_vertexArray[m_vertexIndex + i].normal, &vec[0], &vec[1] );
  726. //}
  727. for(UINT i=0;i<9;i++)
  728. {
  729. m_vertexArray[m_vertexIndex+i].color = 0xffffffff;
  730. }
  731. // 索引数组赋值,   0 1 2   ,顺时针旋转
  732. //                  3 4 5 
  733. //                  6 7 8
  734. m_indexArray[m_indexIndex + 0]  = m_vertexIndex + 0;
  735. m_indexArray[m_indexIndex + 1]  = m_vertexIndex + 1;
  736. m_indexArray[m_indexIndex + 2]  = m_vertexIndex + 4;
  737. m_indexArray[m_indexIndex + 3]  = m_vertexIndex + 1;
  738. m_indexArray[m_indexIndex + 4]  = m_vertexIndex + 2;
  739. m_indexArray[m_indexIndex + 5]  = m_vertexIndex + 4;
  740. m_indexArray[m_indexIndex + 6]  = m_vertexIndex + 2;
  741. m_indexArray[m_indexIndex + 7]  = m_vertexIndex + 5;
  742. m_indexArray[m_indexIndex + 8]  = m_vertexIndex + 4;
  743. m_indexArray[m_indexIndex + 9]  = m_vertexIndex + 5;
  744. m_indexArray[m_indexIndex + 10] = m_vertexIndex + 8;
  745. m_indexArray[m_indexIndex + 11] = m_vertexIndex + 4;
  746. m_indexArray[m_indexIndex + 12] = m_vertexIndex + 8;
  747. m_indexArray[m_indexIndex + 13] = m_vertexIndex + 7;
  748. m_indexArray[m_indexIndex + 14] = m_vertexIndex + 4;
  749. m_indexArray[m_indexIndex + 15] = m_vertexIndex + 7;
  750. m_indexArray[m_indexIndex + 16] = m_vertexIndex + 6;
  751. m_indexArray[m_indexIndex + 17] = m_vertexIndex + 4;
  752. m_indexArray[m_indexIndex + 18] = m_vertexIndex + 6;
  753. m_indexArray[m_indexIndex + 19] = m_vertexIndex + 3;
  754. m_indexArray[m_indexIndex + 20] = m_vertexIndex + 4;
  755. m_indexArray[m_indexIndex + 21] = m_vertexIndex + 3;
  756. m_indexArray[m_indexIndex + 22] = m_vertexIndex + 0;
  757. m_indexArray[m_indexIndex + 23] = m_vertexIndex + 4;
  758. m_vertexIndex += 9;
  759. m_indexIndex  += 24;
  760. }
  761. else
  762. {
  763. RefineNode( pNode->m_pTLChildNode );
  764. RefineNode( pNode->m_pBLChildNode );
  765. RefineNode( pNode->m_pTRChildNode );
  766. RefineNode( pNode->m_pBRChildNode );
  767. }
  768. }
  769. }
  770. UINT log2(UINT num)
  771. {
  772. UINT a = 0;
  773. while(num != 0)
  774. {
  775. num = num >> 1;
  776. a++;
  777. }
  778. return a - 1;
  779. }