afTerrain.cpp
上传用户:kaiguan
上传日期:2007-10-28
资源大小:1074k
文件大小:30k
源码类别:

其他游戏

开发平台:

Visual C++

  1. #include "afTerrain.h"
  2. #include "afMatrix.h"
  3. #include "afPlane.h"
  4. #include "afTime.h"
  5. #include "afSettings.h"
  6. #include "afTerrainPatch.h"
  7. #include "afApplication.h"
  8. inline DWORD FtoDW( FLOAT f ) { return *((DWORD*)&f); }
  9. afTerrain::afTerrain() : iBuffer(NULL), vBuffer(NULL), fogColor(1.0f, 1.0f, 1.0f, 1.0f),
  10.  profileUpdate("update()"), profileRender("render()")
  11. {
  12. for(int i=0; i<=4; i++)
  13. patchCount[i] = 0;
  14. bufferCreateCount = 0;
  15. mergeSmallPatches = true;
  16. // default value
  17. pvs = NULL;
  18. patches = NULL;
  19. patchesX = patchesY = 0;
  20. heightmap = NULL;
  21. hmData=NULL;
  22. normals = NULL;
  23. maxError = 0.015f;
  24. desiredFPS = 0;
  25. activePatches = NULL;
  26. forceBufferCreate = true;
  27. skySpeedX = skySpeedY = 0.0f;
  28. fogNear = fogFar = 0.0f;
  29. mipFilter = afTextureStage::FILTER_LINEAR;
  30. m_pTerrainDecl=NULL;
  31. m_pTerrainShader=NULL;
  32. numNewVertices = numNewIndices = numVertices = numIndices = 0;
  33. useUnitDistance = true;
  34. updateWorldMatrix();
  35. }
  36. void afTerrain::setPatchSize(float nX, float nY, float nZ)
  37. {
  38. patchDX = nX;
  39. patchDY = nY;
  40. patchDZ = nZ;
  41. }
  42. void afTerrain::setHeightMap(afImage* nImage)
  43. {
  44. if(nImage==NULL)
  45. return;
  46. heightmap = nImage;
  47. hmData = heightmap->getData();
  48. hmWidth = heightmap->getWidth();
  49. hmHeight = heightmap->getHeight();
  50. }
  51. void afTerrain::setSkyMap(afTexture* nSkyMap, float nX, float nY, float nSpeedX, float nSpeedY)
  52. {
  53. fillPassInfo(&skyPass, nSkyMap, nX, nY, NULL);
  54. skyPosX = skyPosY = 0.0f;
  55. skySpeedX = nSpeedX;
  56. skySpeedY = nSpeedY;
  57. }
  58. inline void afTerrain::updateSkyMatrix()
  59. {
  60. if(!skyPass.texColor)
  61. return;
  62. float ftime = afTime::getLastFrameTime();
  63. skyPosX += ftime * skySpeedX;
  64. skyPosY += ftime * skySpeedY;
  65. D3DXMatrixScaling(&skyPass.matrix, skyPass.repeatX, skyPass.repeatY, 1.0f);
  66. skyPass.matrix._31 = skyPosX;
  67. skyPass.matrix._32 = skyPosY;
  68. }
  69. void afTerrain::fillPassInfo(MultiPassInfo* nPass, afTexture* nTexture, float nRepeatX, float nRepeatY, afTexture* nModTexture)
  70. {
  71. nPass->texColor = nTexture;
  72. nPass->texMod = nModTexture;
  73. if(nRepeatX==0.0f) nRepeatX = 1.0f;
  74. if(nRepeatY==0.0f) nRepeatY = 1.0f;
  75. nPass->repeatX = nRepeatX;
  76. nPass->repeatY = nRepeatY;
  77. D3DXMatrixScaling(&nPass->matrix, nPass->repeatX, nPass->repeatY, 1.0f);
  78. }
  79. void afTerrain::addPass(afTexture* nColorTexture, float nRepeatX, float nRepeatY, afTexture* nTransTexture)
  80. {
  81. MultiPassInfo* pass = new MultiPassInfo();
  82. multiPassInfos.addTail(pass);
  83. fillPassInfo(pass, nColorTexture, nRepeatX, nRepeatY, nTransTexture);
  84. }
  85. void afTerrain::calcPassVisibility(MultiPassInfo* nInfo, int nX, int nY)
  86. {
  87. int dx = nInfo->texMod->getWidth(),
  88. dy = nInfo->texMod->getHeight();
  89. int px = dx / patchesX,
  90. py = dy / patchesY;
  91. int x0 = nX*px, x1 = nX*px+px,
  92. y0 = nY*py, y1 = nY*py+py,
  93. x,y;
  94. unsigned char *data = nInfo->visData,
  95. min = 10, max = 245;
  96. int pitch = nInfo->visPitch;
  97. nInfo->inVis = nInfo->fullVis = true;
  98. for(x=x0; x<x1; x++)
  99. for(y=y0; y<y1; y++)
  100. {
  101. int idx = 4*x + (dy-1-y)*pitch + 3;
  102. unsigned char d = data[idx];
  103. if(d>=min)
  104. nInfo->inVis = false;
  105. if(d<=max)
  106. nInfo->fullVis = false;
  107. }
  108. }
  109. void afTerrain::build()
  110. {
  111. int x,y, pass, pass2;
  112. if(!heightmap)
  113. return;
  114. patches = new afTerrainPatchPPtr[patchesY];
  115. for(y=0; y<patchesY; y++)
  116. patches[y] = new afTerrainPatchPtr[patchesX];
  117. sizeX = patchDX * patchesX;
  118. sizeY = patchDY;
  119. sizeZ = patchDZ * patchesY;
  120.     
  121. if(pvsName.getLength()>0)
  122. {
  123. pvs = new afTerrainPVS();
  124. if(!pvs->load(afSettings::tmpFullPath(pvsName+".pvs")))
  125. {
  126. delete pvs;
  127. pvs = NULL;
  128. }
  129. for(pass=1; pass<multiPassInfos.getSize(); pass++)
  130. {
  131. MultiPassInfo* p = multiPassInfos[pass];
  132. bool ok = p->texMod->getData(p->visData, p->visPitch);
  133. assert(ok);
  134. }
  135. for(y=0; y<patchesY; y++)
  136. for(x=0; x<patchesX; x++)
  137. {
  138. afTerrainPatch* patch = createPatch(x,y);
  139. patches[y][x] = patch;
  140. patch->setScale(afVec3(patchDX, patchDY, patchDZ));
  141. patch->setPosition(afVec3(x*patchDX, 0.0f, y*patchDZ));
  142. patch->setHeightMapPosition(x*(afTerrainPatch::SOURCE_WIDTH-1),
  143. y*(afTerrainPatch::SOURCE_HEIGHT-1));
  144. patch->calcErrors();
  145. patch->calcMinMaxY();
  146. // calculate for each pass if there is anything to draw
  147. // (check the alpha map)
  148. int visFlags = 0,
  149. numPasses = multiPassInfos.getSize();
  150. for(pass=1; pass<numPasses; pass++)
  151. calcPassVisibility(multiPassInfos[pass], x,y);
  152. visFlags = afTerrainPatch::VIS_LAYERALL;
  153. for(pass=1; pass<numPasses; pass++) // base pass checking
  154. if(multiPassInfos[pass]->fullVis)
  155. visFlags &= ~afTerrainPatch::VIS_BASE;
  156. for(pass=1; pass<numPasses; pass++) // additional passes
  157. {
  158. if(multiPassInfos[pass]->inVis) // is this pass invisible ? (also no need to check on)
  159. {
  160. visFlags &= ~afTerrainPatch::getAddLayerFlag(pass);
  161. continue;
  162. }
  163. for(pass2=pass+1; pass2<numPasses; pass2++) // see if another pass completely covers this pass
  164. if(multiPassInfos[pass2]->fullVis)
  165. {
  166. visFlags &= ~afTerrainPatch::getAddLayerFlag(pass);
  167. break;
  168. }
  169. }
  170. patch->setVisFlags(visFlags);
  171. }
  172. // tell each patch about its neighbors
  173. //
  174. for(y=0; y<patchesY; y++)
  175. for(x=0; x<patchesX; x++)
  176. patches[y][x]->setNeighbors(x>0 ? patches[y][x-1] : NULL,
  177. x<patchesX-1 ? patches[y][x+1] : NULL,
  178. y>0 ? patches[y-1][x] : NULL,
  179. y<patchesY-1 ? patches[y+1][x] : NULL);
  180. for(pass=1; pass<multiPassInfos.getSize(); pass++)
  181. {
  182. MultiPassInfo* p = multiPassInfos[pass];
  183. p->texMod->releaseData();
  184. }
  185. BuildVertexShader();
  186. }
  187. void afTerrain::update()
  188. {
  189. if(!patches)
  190. return;
  191. afVec3 cPos, lPos,rPos;
  192. float fact=(float)tan(g_pApp->m_Camera.GetFOVX()/2.0f),
  193. farP =g_pApp->m_Camera.GetFarPlane();
  194. int x=0,y=0;
  195. D3DXVECTOR3 pt0,pt1,pt2, tpt0,tpt1,tpt2;
  196. D3DXMATRIX vMat, tMat;
  197. afTerrainPatchPtr curPatch;
  198. afPlane planes[6];
  199. profileUpdate.beginSection();
  200. if(desiredFPS>0)
  201. {
  202. if(afTime::getFPS()<desiredFPS*0.95f && maxError<0.5f)
  203. maxError *= 1.03f;
  204. else
  205. if(afTime::getFPS()>desiredFPS*1.05f && maxError>0.005f)
  206. maxError *= 0.97f;
  207. }
  208. numPatchesProcessed = 0;
  209. updateSkyMatrix();
  210. updateWorldMatrix();
  211. // calculate which rectangle of the map
  212. // is visible from the clipping frustum
  213. lPos = cPos + afVec3(-farP*fact, 0.0f, farP);
  214. rPos = cPos + afVec3( farP*fact, 0.0f, farP);
  215. pt0.x=cPos.x; pt0.y=cPos.y; pt0.z=cPos.z;
  216. pt1.x=lPos.x; pt1.y=lPos.y; pt1.z=lPos.z;
  217. pt2.x=rPos.x; pt2.y=rPos.y; pt2.z=rPos.z;
  218. D3DXMatrixInverse(&vMat, NULL, g_pApp->m_Camera.GetViewMatrix());
  219. D3DXMatrixMultiply(&tMat, &worldMatrix, &vMat);
  220. D3DXVec3TransformCoord(&tpt0, &pt0, &tMat);
  221. D3DXVec3TransformCoord(&tpt1, &pt1, &tMat);
  222. D3DXVec3TransformCoord(&tpt2, &pt2, &tMat);
  223. int x0 = (int)(tpt0.x / patchDX), y0 = (int)(tpt0.z / patchDZ),
  224. x1 = (int)(tpt1.x / patchDX), y1 = (int)(tpt1.z / patchDZ),
  225. x2 = (int)(tpt2.x / patchDX), y2 = (int)(tpt2.z / patchDZ);
  226. maxX = -1; maxY = -1; minX = patchesX+1; minY = patchesY+1;
  227. if(x0<minX) minX = x0;
  228. if(y0<minY) minY = y0;
  229. if(x0>maxX) maxX = x0;
  230. if(y0>maxY) maxY = y0;
  231. if(x1<minX) minX = x1;
  232. if(y1<minY) minY = y1;
  233. if(x1>maxX) maxX = x1;
  234. if(y1>maxY) maxY = y1;
  235. if(x2<minX) minX = x2;
  236. if(y2<minY) minY = y2;
  237. if(x2>maxX) maxX = x2;
  238. if(y2>maxY) maxY = y2;
  239. minX-=2; minY-=2; maxX+=2; maxY+=2;
  240. if(minX<0) minX = 0;
  241. if(minY<0) minY = 0;
  242. if(maxX>=patchesX) maxX = patchesX-1;
  243. if(g_pApp->m_Camera.getUpdateVisibility())
  244. {
  245. // mark all patches in the list as non active
  246. // (checkVisibility will set this to active, if
  247. // it is in the list and is active)
  248. curPatch = activePatches;
  249. while(curPatch)
  250. {
  251. curPatch->setFlagActive(false);
  252. curPatch = curPatch->getNextActive();
  253. }
  254. // create and transform the clipping planes
  255. // (we transform them here, so that checkVisibility()
  256. // doesn't need to transform any corner points)
  257. g_pApp->m_Camera.createClippingPlanes(planes);
  258. // first determine for each patch if
  259. // it will be visible during the next rendering
  260. int pvsX=-1, pvsY=-1, pvsZ=-1;
  261. if(pvs)
  262. {
  263. pvsX = tpt0.x>=0.0f ? (int)(tpt0.x / patchDX) : -1;
  264. pvsY = tpt0.z>=0.0f ? patchesY-1 - (int)(tpt0.z / patchDZ) : -1;
  265. pvsZ = (int)((tpt0.y / patchDY) * 255) / pvs->getDataDZ();
  266. }
  267. D3DXMATRIX mat;
  268. D3DXMatrixMultiply(&mat, &worldMatrix, g_pApp->m_Camera.GetViewMatrix());
  269. for(y=minY; y<=maxY; y++)
  270. for(x=minX; x<=maxX; x++)
  271. if(patches[y][x])
  272. {
  273. if(patches[y][x]->checkVisibility(&mat, planes) && pvs)
  274. {
  275. // if the patch could not be frustum-culled we try pvs (if there is pvs...)
  276. //
  277. if(!pvs->isVisible(pvsX,pvsY,pvsZ, x,patchesY-1-y))
  278. patches[y][x]->setVisible(false);
  279. }
  280. numPatchesProcessed++;
  281. }
  282. // deinit all patches will are still in the
  283. // list, but where checkVisibility() has not been called
  284. curPatch = activePatches;
  285. while(curPatch)
  286. {
  287. if(!curPatch->getFlagActive())
  288. curPatch->deinit();
  289. curPatch = curPatch->getNextActive();
  290. }
  291. // next update the projected error
  292. // and tesselation stage
  293. D3DXMATRIX mat2, matT;
  294. D3DXMatrixTranslation(&matT, 0.0f, 0.0f, 1.2f*max(patchDY,max(patchDX,patchDZ)));
  295. D3DXMatrixMultiply(&mat2, &matT, g_pApp->m_Camera.GetProjMatrix());
  296. D3DXMatrixMultiply(&mat, g_pApp->m_Camera.GetViewMatrix(), &mat2);
  297. D3DXMatrixMultiply(&mat2, &worldMatrix, &mat);
  298. curPatch = activePatches;
  299. while(curPatch)
  300. {
  301. curPatch->updateProjectedErrors(&mat2);
  302. for(int i=afTerrainPatch::MAX_SUBDIV; i>=0; i--)
  303. if(curPatch->getProjectedError(i)<maxError)
  304. {
  305. curPatch->setRealTessellation(i);
  306. curPatch->setTessellation(i);
  307. break;
  308. }
  309. curPatch = curPatch->getNextActive();
  310. }
  311. // next check that each neighbor has only a
  312. // tesselation stage difference at max. 1
  313. if(useUnitDistance)
  314. {
  315. bool changed;
  316. do
  317. {
  318. changed=false;
  319. curPatch = activePatches;
  320. while(curPatch)
  321. {
  322. int tes = curPatch->getNewTessellation(),
  323. lT = curPatch->getLeft()->getNewTessellationSafe(),
  324. rT = curPatch->getRight()->getNewTessellationSafe(),
  325. bT = curPatch->getBottom()->getNewTessellationSafe(),
  326. tT = curPatch->getTop()->getNewTessellationSafe();
  327. int sT = min(min(lT+1,rT+1) , min(bT+1,tT+1));
  328. if(tes>sT)
  329. {
  330. curPatch->setTessellation(sT);
  331. //curPatch->setRealTessellation(sT);
  332. changed = true;
  333. }
  334. curPatch = curPatch->getNextActive();
  335. }
  336. } while(changed);
  337. }
  338. // finally update tesselation to be correct to
  339. // all the neighbours' tesselation stages
  340. numNewVertices = numNewIndices = 0;
  341. curPatch = activePatches;
  342. while(curPatch)
  343. {
  344. int tes = curPatch->getNewTessellation(),
  345. lT = curPatch->getLeft()->getNewTessellationSafe(),
  346. rT = curPatch->getRight()->getNewTessellationSafe(),
  347. bT = curPatch->getBottom()->getNewTessellationSafe(),
  348. tT = curPatch->getTop()->getNewTessellationSafe();
  349. assert(tes-lT<=1);
  350. assert(tes-rT<=1);
  351. assert(tes-bT<=1);
  352. assert(tes-tT<=1);
  353. curPatch->updateTessellation();
  354. numNewVertices += curPatch->getNumVertices();
  355. numNewIndices += curPatch->getNumIndices() + 2; // two more for degen-tris
  356. curPatch = curPatch->getNextActive();
  357. }
  358. // some patch types may need a second update method
  359. // (e.g.: to adapt to each other)
  360. curPatch = activePatches;
  361. while(curPatch)
  362. {
  363. curPatch->updateTessellation2();
  364. curPatch = curPatch->getNextActive();
  365. }
  366. // some patch types may need a third update method
  367. // (e.g.: to adapt to each other)
  368. curPatch = activePatches;
  369. while(curPatch)
  370. {
  371. curPatch->updateTessellation3();
  372. curPatch = curPatch->getNextActive();
  373. }
  374. }
  375. if(numNewIndices>0)
  376. numNewIndices -= 2; // the last patch does not need degen-tris
  377. profileUpdate.endSection();
  378. }
  379. inline void afTerrain::setupTextureStages(MultiPassInfo* nPass, bool nBasePass,bool bForceSoftware)
  380. {
  381. // texture stages setup
  382. //
  383. pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP,  D3DTOP_SELECTARG1);
  384. pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  385. pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT);
  386. pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP,   nBasePass ? D3DTOP_DISABLE : D3DTOP_SELECTARG1);
  387. pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
  388. pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
  389. pd3dDevice->SetSamplerState(0,D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
  390. pd3dDevice->SetSamplerState(0,D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
  391. pd3dDevice->SetSamplerState(0,D3DSAMP_MIPFILTER, mipFilter);
  392. pd3dDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);
  393. if(nPass->texMod)
  394. {
  395. pd3dDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE);
  396. pd3dDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  397. pd3dDevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
  398. pd3dDevice->SetTextureStageState(1, D3DTSS_ALPHAOP,   nBasePass ? D3DTOP_DISABLE : D3DTOP_SELECTARG1);
  399. pd3dDevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
  400. pd3dDevice->SetTextureStageState(1, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
  401. pd3dDevice->SetSamplerState(1,D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
  402. pd3dDevice->SetSamplerState(1,D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
  403. pd3dDevice->SetSamplerState(1,D3DSAMP_MIPFILTER, mipFilter);
  404. pd3dDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX,bForceSoftware?0:1);
  405. pd3dDevice->SetTextureStageState(2, D3DTSS_COLOROP,   D3DTOP_DISABLE);
  406. pd3dDevice->SetTextureStageState(2, D3DTSS_ALPHAOP,   D3DTOP_DISABLE);
  407. }
  408. else
  409. {
  410. pd3dDevice->SetTextureStageState(1, D3DTSS_COLOROP,   D3DTOP_DISABLE);
  411. pd3dDevice->SetTextureStageState(1, D3DTSS_ALPHAOP,   D3DTOP_DISABLE);
  412. }
  413. // zbuffer, filling & culling setup
  414. //
  415. pd3dDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
  416. pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
  417. pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
  418. pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
  419. // fog setup
  420. //
  421. if(fogNear!=0.0f || fogFar!=0.0f)
  422. {
  423. float fogDens = 1.0f;
  424. pd3dDevice->SetRenderState(D3DRS_FOGENABLE, TRUE);
  425. pd3dDevice->SetRenderState(D3DRS_FOGCOLOR,  D3DCOLOR_COLORVALUE(fogColor[0], fogColor[1], fogColor[2], fogColor[3]));
  426. pd3dDevice->SetRenderState(D3DRS_FOGSTART, FtoDW(fogNear));
  427. pd3dDevice->SetRenderState(D3DRS_FOGEND, FtoDW(fogFar));
  428. pd3dDevice->SetRenderState(D3DRS_FOGDENSITY, FtoDW(fogDens));
  429. pd3dDevice->SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
  430. }
  431. else
  432. pd3dDevice->SetRenderState(D3DRS_FOGENABLE, FALSE);
  433. // set textures
  434. //
  435. pd3dDevice->SetTexture(0, nPass->texColor->getD3DTexture());
  436. pd3dDevice->SetTexture(1, nPass->texMod->getD3DTexture());
  437. // setup lighting & blending
  438. //
  439. pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
  440. if(nBasePass)
  441. pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  442. else
  443. {
  444. pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  445. pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  446. pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
  447. }
  448. // setup texture matrix for stage 0
  449. //
  450. if(bForceSoftware)
  451. {
  452. if(nPass->repeatX!=1.0f || nPass->repeatY!=1.0f)
  453. {
  454. pd3dDevice->SetTransform(D3DTS_TEXTURE0, &nPass->matrix);
  455. pd3dDevice->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
  456. }
  457. else
  458. pd3dDevice->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
  459. }
  460. else
  461. {
  462. D3DXMATRIX matTranspose;
  463. D3DXMatrixTranspose(&matTranspose, &nPass->matrix);
  464. g_pApp->m_pd3dDevice->SetVertexShaderConstantF(8,(float*)&matTranspose, 4);
  465. }
  466. pd3dDevice->SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
  467. }
  468. inline void afTerrain::setupTextureStagesForSky(bool bForceSoftware)
  469. {
  470. // texture stages setup
  471. //
  472. pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP,   D3DTOP_SELECTARG1);
  473. pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  474. pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT);
  475. pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP,   D3DTOP_SELECTARG1);
  476. pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
  477. pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
  478. pd3dDevice->SetSamplerState(0,D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
  479. pd3dDevice->SetSamplerState(0,D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
  480. pd3dDevice->SetSamplerState(0,D3DSAMP_MIPFILTER, mipFilter);
  481. pd3dDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);
  482. pd3dDevice->SetTextureStageState(1, D3DTSS_COLOROP,   D3DTOP_DISABLE);
  483. pd3dDevice->SetTextureStageState(1, D3DTSS_ALPHAOP,   D3DTOP_DISABLE);
  484. // zbuffer, filling & culling setup
  485. //
  486. pd3dDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
  487. pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
  488. pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
  489. pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
  490. // fog setup
  491. //
  492. if(fogNear!=0.0f || fogFar!=0.0f)
  493. {
  494. float fogDens = 0.0f;
  495. pd3dDevice->SetRenderState(D3DRS_FOGENABLE, TRUE);
  496. pd3dDevice->SetRenderState(D3DRS_FOGCOLOR,  D3DCOLOR_COLORVALUE(fogColor[0], fogColor[1], fogColor[2], fogColor[3]));
  497. pd3dDevice->SetRenderState(D3DRS_FOGSTART, FtoDW(fogNear));
  498. pd3dDevice->SetRenderState(D3DRS_FOGEND, FtoDW(fogFar));
  499. pd3dDevice->SetRenderState(D3DRS_FOGDENSITY, FtoDW(fogDens));
  500. pd3dDevice->SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
  501. pd3dDevice->SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_NONE);
  502. }
  503. else
  504. pd3dDevice->SetRenderState(D3DRS_FOGENABLE, FALSE);
  505. // set texture
  506. //
  507. pd3dDevice->SetTexture(0, skyPass.texColor->getD3DTexture());
  508. // setup lighting & blending
  509. //
  510. pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
  511. pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  512. pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  513. pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
  514. // setup texture matrix for stage 0
  515. //
  516. if(bForceSoftware)
  517. {
  518. if(skyPass.repeatX!=1.0f || skyPass.repeatY!=1.0f)
  519. {
  520. g_pApp->m_pd3dDevice->SetTransform(D3DTS_TEXTURE0, &skyPass.matrix);
  521. g_pApp->m_pd3dDevice->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
  522. }
  523. else
  524. g_pApp->m_pd3dDevice->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
  525. }
  526. else
  527. {
  528. D3DXMATRIX matTranspose;
  529. D3DXMatrixTranspose(&matTranspose, &skyPass.matrix);
  530. g_pApp->m_pd3dDevice->SetVertexShaderConstantF(8,(float*)&matTranspose, 4);
  531. }
  532. pd3dDevice->SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
  533. }
  534. inline void afTerrain::updateWorldMatrix()
  535. {
  536. D3DXMATRIX matScale, matMove, matRot, mat;
  537. afVec3 scale(1.0f, 1.0f, 1.0f);
  538. D3DXMatrixScaling(&matScale, scale.x, scale.y, scale.z);
  539. D3DXMatrixTranslation(&matMove, pos.x,pos.y,pos.z);
  540. D3DXMatrixRotationYawPitchRoll(&matRot, rot.x,rot.y,rot.z);
  541. D3DXMatrixMultiply(&mat, &matRot, &matMove);
  542. D3DXMatrixMultiply(&worldMatrix, &matScale, &mat);
  543. }
  544. void afTerrain::checkBuffers()
  545. {
  546. if(mergeSmallPatches)
  547. {
  548. assert(numNewIndices < 0xffff);
  549. if(numNewIndices > numIndices || forceBufferCreate)
  550. {
  551. SAFE_RELEASE(iBuffer);
  552. if(numNewIndices>0)
  553. if(FAILED(pd3dDevice->CreateIndexBuffer(numNewIndices * sizeof(WORD), D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY,
  554. D3DFMT_INDEX16, D3DPOOL_DEFAULT, &iBuffer,NULL)))
  555. {
  556. afLog::error("creating index buffer for terrain failed");
  557. return;
  558. }
  559. }
  560. numIndices = numNewIndices;
  561. if(numNewVertices > numVertices || forceBufferCreate)
  562. {
  563. SAFE_RELEASE(vBuffer);
  564. if(numNewVertices>0)
  565. {
  566. if(FAILED(pd3dDevice->CreateVertexBuffer(numNewVertices * sizeof(afTerrainPatch::PATCHVERTEX),
  567.  D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY,
  568.  D3DFVF_PATCHVERTEX, D3DPOOL_DEFAULT, &vBuffer,NULL)))
  569. {
  570. afLog::error("creating vertex buffer for terrain failed");
  571. SAFE_RELEASE(iBuffer);
  572. return;
  573. }
  574. }
  575. }
  576. numVertices = numNewVertices;
  577. }
  578. forceBufferCreate = false;
  579. }
  580. void afTerrain::render()
  581. {
  582.  
  583. profileRender.beginSection();
  584.     // activate the morph shader
  585. SetupVertexShader();
  586. afTerrainPatch* patch;
  587. afTerrainPatch::PATCHVERTEX* pVertices = NULL;
  588. WORD* pIndices = NULL;
  589. int i, pass, numTris=0, numPasses = multiPassInfos.getSize(), numPassesP;
  590. for(i=0; i<=afTerrainPatch::MAX_SUBDIV; i++)
  591. patchCount[i] = 0;
  592. numPatchesRendered = numPatchesPassesRendered = 0;
  593. if(mergeSmallPatches)
  594. {
  595. numNewVertices = 0;
  596. numNewIndices = 0;
  597. patch = activePatches;
  598. while(patch)
  599. {
  600. if(patch->getNewTessellation()==4)
  601. {
  602. numNewVertices += patch->getNumVertices();
  603. numNewIndices += patch->getNumIndices()+2;
  604. }
  605. patch = patch->getNextActive();
  606. }
  607. checkBuffers();
  608. }
  609. numPassesP = skyPass.texColor ? numPasses+1 : numPasses;
  610. for(pass=0; pass<numPassesP; pass++)
  611. {
  612. int numV=0, numI=0;
  613. if(pass<numPasses)
  614. setupTextureStages(multiPassInfos[pass], false,false);
  615. else
  616. setupTextureStagesForSky(false);
  617. if(mergeSmallPatches && vBuffer && iBuffer)
  618. {
  619. if(!SetupVertexShader())
  620. return;
  621. vBuffer->Lock(0, 0, (void**)&pVertices, D3DLOCK_NOSYSLOCK|D3DLOCK_DISCARD);
  622. iBuffer->Lock(0, 0, (void**)&pIndices, D3DLOCK_NOSYSLOCK|D3DLOCK_DISCARD);
  623. }
  624. patch = activePatches;
  625. while(patch)
  626. {
  627. int tes = patch->getNewTessellation();
  628. assert(tes>=0 && tes<=afTerrainPatch::MAX_SUBDIV);
  629. if(pass==0)
  630. {
  631. numPatchesRendered++;
  632. patchCount[tes]++;
  633. patch->setRendered(false);
  634. }
  635. if(pass<numPasses || patch->getVisFlags()&afTerrainPatch::getAddLayerFlag(pass))
  636. {
  637. if(mergeSmallPatches && tes==4)
  638. {
  639. // copy the vertex data
  640. //
  641. int numNewV = patch->fillBaseVertices(pVertices+numV);
  642. // then copy the indices, which must be updated to
  643. // reflect the moved vertex data (index shifts)
  644. //
  645. const WORD* indices = patch->getIndices();
  646. int n = patch->getNumIndices();
  647. if(numI>0) // add degen-tris to concenate strips
  648. {
  649. pIndices[numI++] = pIndices[numI-1];
  650. pIndices[numI++] = (unsigned short)(indices[0] + numV);
  651. }
  652. for(i=0; i<n; i++)
  653. pIndices[numI++] = (unsigned short)(indices[i] + numV);
  654. numV += numNewV;
  655. }
  656. else
  657. {
  658. numTris = patch->render();
  659. }
  660. patch->setRendered(true);
  661. numPatchesPassesRendered++;
  662. }
  663. patch = patch->getNextActive();
  664. }
  665. if(mergeSmallPatches && vBuffer && iBuffer)
  666. {
  667. if(pass<numPasses)
  668. setupTextureStages(multiPassInfos[pass], false,true);
  669. else
  670. setupTextureStagesForSky(true);
  671. iBuffer->Unlock();
  672. vBuffer->Unlock();
  673. assert(numV<=numNewVertices);
  674. assert(numI<=numNewIndices);
  675.             
  676. pd3dDevice->SetVertexShader(NULL);
  677. pd3dDevice->SetFVF(D3DFVF_PATCHVERTEX);
  678. pd3dDevice->SetStreamSource(0, vBuffer,0,sizeof(afTerrainPatch::PATCHVERTEX));
  679. pd3dDevice->SetIndices(iBuffer);
  680. pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP,0,0, numV, 0, numI-2);
  681. }
  682. }
  683. //afLog::info("numPatchesRendered:%d,numPatchesPassesRendered:%d",numPatchesRendered,numPatchesPassesRendered);
  684. profileRender.endSection();
  685. }
  686. float afTerrain::getHeightDif(int nX0, int nY0, int nX1, int nY1)
  687. {
  688. return getHeight(nX0,nY0) - getHeight(nX1,nY1);
  689. }
  690. void afTerrain::createNormals()
  691. {
  692. int x,y, w=heightmap->getWidth(), h=heightmap->getHeight();
  693. if(normals)
  694. delete normals;
  695. normals = new afVec3[w*h];
  696. for(y=0; y<h; y++)
  697. for(x=0; x<w; x++)
  698. {
  699. int idx = y*w+x;
  700. float dxp=0.0f,dxm=0.0f, dyp=0.0f,dym=0.0f;
  701. if(x>0 && x<w-1 && y>0 && y<w-1)
  702. {
  703. dxp =  getHeightDif(x,y, x+1,y);
  704. dxm =  getHeightDif(x,y, x-1,y);
  705. dyp =  getHeightDif(x,y, x,y+1);
  706. dym =  getHeightDif(x,y, x,y-1);
  707. }
  708. normals[idx].x = ((dxp - dxm)/2.0f) * patchDX * afTerrainPatch::SOURCE_WIDTH;
  709. normals[idx].y = patchDY;
  710. normals[idx].z = ((dyp - dym)/2.0f) * patchDZ * afTerrainPatch::SOURCE_HEIGHT;
  711. normals[idx].normalize();
  712. }
  713. normals[0] = normals[1+w];
  714. normals[w-1] = normals[w+w-2];
  715. normals[(h-1)*w] = normals[(h-2)*w+1];
  716. normals[(h-1)*w+w-1] = normals[(h-2)*w+w-2];
  717. for(x=1; x<w-1; x++)
  718. {
  719. normals[x] = normals[x+w];
  720. normals[x+(y-1)*w] = normals[x+(y-2)*w];
  721. }
  722. for(y=1; y<h-1; y++)
  723. {
  724. normals[y*w] = normals[y*w+1];
  725. normals[y*w+w-1] = normals[y*w+w-2];
  726. }
  727. }
  728. void afTerrain::deleteDeviceObjects()
  729. {
  730. int x,y;
  731. SAFE_RELEASE(iBuffer);
  732. SAFE_RELEASE(vBuffer);
  733. if(patches)
  734. {
  735. for(y=0; y<patchesY; y++)
  736. for(x=0; x<patchesX; x++)
  737. if(patches[y][x])
  738. patches[y][x]->deleteDeviceObjects();
  739. }
  740. SAFE_DELETE(pvs);
  741. for(int pass=0; pass<multiPassInfos.getSize(); pass++)
  742. {
  743. MultiPassInfo* p = multiPassInfos[pass];
  744. SAFE_DELETE(p);
  745. }
  746. DestroyVertexShader();
  747. }
  748. bool afTerrain::restoreDeviceObjects()
  749. {
  750. int x,y;
  751. forceBufferCreate = true;
  752. if(!patches)
  753. return true;
  754. for(y=0; y<patchesY; y++)
  755. for(x=0; x<patchesX; x++)
  756. if(patches[y][x])
  757. patches[y][x]->restoreDeviceObjects();
  758. return true;
  759. }
  760. void afTerrain::fillInfoString(afString& nStr)
  761. {
  762. float factor = (float)numPatchesPassesRendered/(float)numPatchesRendered;
  763. nStr.set("Terr: %d processed  %d (%d passes -> x%.2f) rendered", numPatchesProcessed, numPatchesRendered, numPatchesPassesRendered, factor);
  764. }
  765. void afTerrain::fillInfoString2(afString& nStr)
  766. {
  767. nStr.set("%d %d %d %d %d | %d", patchCount[0], patchCount[1], patchCount[2], patchCount[3], patchCount[4], bufferCreateCount);
  768. bufferCreateCount = 0;
  769. }
  770. // this method is not yet working correctly...
  771. //
  772. bool afTerrain::intersectLine(const afVec3& nPos0, const afVec3& nPos1, float& nScalarPos) const
  773. {
  774. D3DXMATRIX mat;
  775. D3DXVECTOR3 p0,p1, tp0,tp1, ds, p;
  776. float len, flatLen, f = 0.0f, h;
  777. bool startAbove=false, curAbove=false, startAboveInit=false;
  778. D3DXMatrixInverse(&mat, NULL, &worldMatrix);
  779. p0.x=nPos0.x; p0.y=nPos0.y; p0.z=nPos0.z;
  780. p1.x=nPos1.x; p1.y=nPos1.y; p1.z=nPos1.z;
  781. D3DXVec3TransformCoord(&tp0, &p0, &mat);
  782. D3DXVec3TransformCoord(&tp1, &p1, &mat);
  783. tp0.x /= sizeX; tp0.y /= sizeY; tp0.z /= sizeZ;
  784. tp1.x /= sizeX; tp1.y /= sizeY; tp1.z /= sizeZ;
  785. if((tp0.x<0.0f && tp1.x<0.0f) || (tp0.x>1.0f && tp1.x>1.0f) ||
  786.    (tp0.z<0.0f && tp1.z<0.0f) || (tp0.z>1.0f && tp1.z>1.0f))
  787.    return false;
  788. ds = tp1-tp0;
  789. //ds.x *= 255.0f;
  790. //ds.z *= 255.0f;
  791. flatLen = (float)(sqrt(ds.x*ds.x + ds.z*ds.z));
  792. if(flatLen>0.0f)
  793. {
  794. ds.x /= flatLen;
  795. ds.y /= (255.0f*flatLen);
  796. ds.z /= flatLen;
  797. }
  798. len = (float)(sqrt(ds.x*ds.x + ds.y*ds.y + ds.z*ds.z));
  799. p = tp0;
  800. do
  801. {
  802. if(p.x>=0.0f && p.x<=hmWidth && p.z>=0.0f && p.z<=hmHeight)
  803. {
  804. if(!startAboveInit)
  805. {
  806. startAboveInit = true;
  807. startAbove = getHeight((int)p.x, (int)p.z) < p.y;
  808. }
  809. p += ds;
  810. f += 1.0f;
  811. h = getHeight((int)p.x, (int)p.z);
  812. curAbove = h < p.y;
  813. if(startAboveInit && curAbove!=startAbove)
  814. {
  815. //nScalarPos = (p-tp0).GetLength() / (tp1-tp0).length();
  816. nScalarPos = 0.0f;
  817. return true;
  818. }
  819. }
  820. else
  821. {
  822. p += ds;
  823. f += 1.0f;
  824. }
  825. } while(f<flatLen);
  826. return false;
  827. }
  828. bool afTerrain::projectDown(const afVec3& nPos, afVec3& nProjected) const
  829. {
  830. D3DXMATRIX mat;
  831. D3DXVECTOR3 p, tp;
  832. D3DXMatrixInverse(&mat, NULL, &worldMatrix);
  833. p.x=nPos.x; p.y=nPos.y; p.z=nPos.z;
  834. D3DXVec3TransformCoord(&tp, &p, &mat);
  835. tp.x /= sizeX; tp.y /= sizeY; tp.z /= sizeZ;
  836. float x = hmWidth*tp.x,
  837. y = hmHeight*tp.z;
  838. x -= 0.5f;
  839. y -= 0.5f;
  840. int ix = (int)x,
  841. iy = (int)y;
  842. float u = x - ix,
  843. v = y - iy;
  844. if(ix<0 || iy<0 || ix>=hmWidth-1 || iy>=hmHeight-1)
  845. return false;
  846. float h00 = getHeight(ix+0, iy+0),
  847. h10 = getHeight(ix+1, iy+0),
  848. h01 = getHeight(ix+0, iy+1),
  849. h11 = getHeight(ix+1, iy+1);
  850. tp.y = (1.0f-v) * ((1.0f-u)*h00 + u*h10) + 
  851.  v  * ((1.0f-u)*h01 + u*h11);
  852. tp.x *= sizeX; tp.y *= sizeY; tp.z *= sizeZ;
  853. D3DXVec3TransformCoord(&p, &tp, &worldMatrix);
  854.     nProjected.x=p.x; nProjected.y=p.y; nProjected.z=p.z;
  855. return true;
  856. }
  857. bool afTerrain::moveAboveSurface(afVec3& nPos, float nHeight, float /*nGlideFactor*/) const
  858. {
  859. afVec3 downPos;
  860. if(projectDown(nPos, downPos))
  861. {
  862. if(nPos.y < downPos.y + nHeight)
  863. {
  864. nPos.y = downPos.y + nHeight;
  865. return true;
  866. }
  867. }
  868. return false;
  869. }
  870. afTerrainPatch* afTerrain::createPatch(int nX, int nY)
  871. {
  872. return new afTerrainPatch(this, nX,nY);
  873. }
  874. bool afTerrain::BuildVertexShader()
  875. {
  876. D3DVERTEXELEMENT9 declTerrain[] =
  877.     {        
  878.         { 0,  0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT,  D3DDECLUSAGE_POSITION, 0}, 
  879.         { 0, 16, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT,  D3DDECLUSAGE_TEXCOORD, 0}, 
  880.         { 0, 32, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT,  D3DDECLUSAGE_TEXCOORD, 1},        
  881.         { 0, 48, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT,  D3DDECLUSAGE_TEXCOORD, 2},     
  882.     D3DDECL_END()
  883.     };
  884. HRESULT hr;
  885. if(FAILED( hr =g_pApp->m_pd3dDevice->CreateVertexDeclaration(declTerrain, &m_pTerrainDecl)))
  886.         return false;
  887. LPD3DXBUFFER pCode = NULL;
  888. if( FAILED( hr = D3DXAssembleShaderFromFile(afSettings::tmpFullPath("shader/terrainMorph.vsh"), NULL, NULL, 0, &pCode, NULL)))  
  889. return false;
  890. if( FAILED( hr = g_pApp->m_pd3dDevice->CreateVertexShader( (DWORD*)pCode->GetBufferPointer(),
  891.                                                        &m_pTerrainShader)))
  892.     {
  893.         SAFE_RELEASE( pCode );
  894.         return false;
  895.     }
  896.     SAFE_RELEASE( pCode); 
  897. return true;
  898. }
  899. void afTerrain::DestroyVertexShader()
  900. {
  901. SAFE_RELEASE(m_pTerrainShader);
  902. SAFE_RELEASE(m_pTerrainDecl);
  903. }
  904. inline bool afTerrain::SetupVertexShader()
  905. {
  906. D3DXMATRIX mat, matTranspose;
  907. D3DXMatrixMultiply(&mat, g_pApp->m_Camera.GetViewMatrix(),g_pApp->m_Camera.GetProjMatrix());
  908. D3DXMatrixTranspose(&matTranspose, &mat);
  909. g_pApp->m_pd3dDevice->SetVertexShaderConstantF(4,(float*)&matTranspose, 4);
  910. g_pApp->m_pd3dDevice->SetVertexDeclaration(m_pTerrainDecl);
  911. if(m_pTerrainShader)
  912. return(g_pApp->m_pd3dDevice->SetVertexShader(m_pTerrainShader)==S_OK);
  913. return false;
  914. }