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

其他游戏

开发平台:

Visual C++

  1. #include "stdafx.h"
  2. #include "afTerrainPatch.h"
  3. #include "afLog.h"
  4. #include "afMatrix.h"
  5. #include "afPlane.h"
  6. #include "afTerrain.h"
  7. #include <assert.h>
  8. #define setD3DVec(v1, v0)  {  v1.x = v0.x;  v1.y = v0.y;  v1.z = v0.z;  }
  9. struct PATCHVERTEX_MORPH_HW
  10. {
  11. float posX,posZ;
  12. float texX,texY;
  13. float posY, yMoveSelf, v0,v1,
  14. yMoveLeft, yMoveLeft2, yMoveRight, yMoveRight2,
  15. yMoveBottom, yMoveBottom2, yMoveTop, yMoveTop2;
  16. };
  17. afTerrainPatch::afTerrainPatch(afTerrain* nMaster, int nX, int nY) : active(false), scale(1.0f, 1.0f, 1.0f)
  18. {
  19. visFlags = 0;
  20. gridX = nX;
  21. gridY = nY;
  22. minY = maxY = -1.0f;
  23. master = nMaster;
  24. realSelfTes = newRealSelfTes = newSelfTes = selfTes = leftTes = rightTes = topTes = bottomTes = 5;
  25. oldRealSelfTes = 5;
  26. vertices = NULL;
  27. indices = NULL;
  28. indexMap = NULL;
  29. next = prev = NULL;
  30. left = right = bottom = top = NULL;
  31. lowVertMethod2 = false;
  32. currentError = -1.0f;
  33. vBuffer = NULL;
  34. iBuffer = NULL;
  35. verticesLow = NULL;
  36. yMoveSelf = yMoveLeft = yMoveLeft2 = yMoveRight = yMoveRight2 = yMoveBottom = yMoveBottom2 = yMoveTop = yMoveTop2 = NULL;
  37. newFollowsLeft = followsLeft = newFollowsRight = followsRight = newFollowsBottom = followsBottom = newFollowsTop = followsTop = false;
  38. recalcBorderLeft = recalcBorderRight = recalcBorderBottom = recalcBorderTop = false;
  39. forceRetessellation = false;
  40. }
  41. void afTerrainPatch::setNeighbors(const afTerrainPatch* nLeft, const afTerrainPatch* nRight, const afTerrainPatch *nBottom, const afTerrainPatch* nTop)
  42. {
  43. left = nLeft;
  44. right = nRight;
  45. bottom = nBottom;
  46. top = nTop;
  47. }
  48. void afTerrainPatch::init()
  49. {
  50. newSelfTes = selfTes = leftTes = rightTes = topTes = bottomTes = 5;
  51. oldRealSelfTes = 5;
  52. vertices = new PATCHVERTEX[MAX_VERTICES];
  53. indices = new unsigned short[MAX_INDICES];
  54. indexMap = new unsigned short[MAX_VERTICES];
  55. numIndices = numVertices = 0;
  56. numNewVertices = numNewIndices = 0;
  57. forceBufferCreate = true;
  58. active = true;
  59. addToActiveList();
  60. verticesLow = new PATCHVERTEX[MAX_VERTICES];
  61. yMoveSelf = new float[MAX_VERTICES];
  62. yMoveLeft = new float[MAX_VERTICES];
  63. yMoveLeft2 = new float[MAX_VERTICES];
  64. yMoveRight = new float[MAX_VERTICES];
  65. yMoveRight2 = new float[MAX_VERTICES];
  66. yMoveTop = new float[MAX_VERTICES];
  67. yMoveTop2 = new float[MAX_VERTICES];
  68. yMoveBottom = new float[MAX_VERTICES];
  69. yMoveBottom2 = new float[MAX_VERTICES];
  70. newFollowsLeft = followsLeft = newFollowsRight = followsRight = newFollowsBottom = followsBottom = newFollowsTop = followsTop = false;
  71. recalcBorderLeft = recalcBorderRight = recalcBorderBottom = recalcBorderTop = false;
  72. forceRetessellation = false;
  73. }
  74. void afTerrainPatch::deinit()
  75. {
  76. if(vertices)
  77. delete vertices;
  78. vertices = NULL;
  79. if(indices)
  80. delete indices;
  81. indices = NULL;
  82. if(indexMap)
  83. delete indexMap;
  84. indexMap = NULL;
  85. currentError = -1.0f;
  86. active = false;
  87. removeFromActiveList();
  88. if(verticesLow)
  89. delete verticesLow;
  90. verticesLow = NULL;
  91. if(yMoveSelf)
  92. delete yMoveSelf;
  93. yMoveSelf = NULL;
  94. if(yMoveLeft)
  95. delete yMoveLeft;
  96. yMoveLeft = NULL;
  97. if(yMoveLeft2)
  98. delete yMoveLeft2;
  99. yMoveLeft2 = NULL;
  100. if(yMoveRight)
  101. delete yMoveRight;
  102. yMoveRight = NULL;
  103. if(yMoveRight2)
  104. delete yMoveRight2;
  105. yMoveRight2 = NULL;
  106. if(yMoveBottom)
  107. delete yMoveBottom;
  108. yMoveBottom = NULL;
  109. if(yMoveBottom2)
  110. delete yMoveBottom2;
  111. yMoveBottom2 = NULL;
  112. if(yMoveTop)
  113. delete yMoveTop;
  114. yMoveTop = NULL;
  115. if(yMoveTop2)
  116. delete yMoveTop2;
  117. yMoveTop2 = NULL;
  118. deleteDeviceObjects();
  119. }
  120. void afTerrainPatch::addToActiveList()
  121. {
  122. assert(master);
  123. assert(prev==NULL);
  124. assert(next==NULL);
  125. prev = NULL;
  126. next = master->getActiveList();
  127. if(next)
  128. next->prev = this;
  129. master->getActiveList() = this;
  130. }
  131. void afTerrainPatch::removeFromActiveList()
  132. {
  133. if(prev)
  134. prev->next = next;
  135. if(next)
  136. next->prev = prev;
  137. if(master->getActiveList() == this)
  138. {
  139. assert(prev==NULL);
  140. master->getActiveList() = next;
  141. }
  142. prev = next = NULL;
  143. }
  144. void afTerrainPatch::deleteDeviceObjects()
  145. {
  146. SAFE_RELEASE(iBuffer);
  147. SAFE_RELEASE(vBuffer);
  148. }
  149. bool afTerrainPatch::restoreDeviceObjects()
  150. {
  151. forceBufferCreate = true;
  152. return true;
  153. }
  154. int afTerrainPatch::fillBaseVertices(afTerrainPatch::PATCHVERTEX* nDest)
  155. {
  156. memcpy(nDest, vertices, numVertices*sizeof(afTerrainPatch::PATCHVERTEX));
  157. return numVertices;
  158. }
  159. void afTerrainPatch::setScale(const afVec3& nScale)
  160. {
  161. scale = nScale;
  162. }
  163. void afTerrainPatch::setHeightMapPosition(int nX0, int nY0)
  164. {
  165. hmX0 = nX0;
  166. hmY0 = nY0;
  167. }
  168. void afTerrainPatch::setRealTessellation(int nTes)
  169. {
  170. oldRealSelfTes = realSelfTes;
  171. newRealSelfTes = nTes;
  172. }
  173. bool afTerrainPatch::updateTessellation()
  174. {
  175. if(left && left->oldRealSelfTes<5 && left->newRealSelfTes!=left->oldRealSelfTes)
  176. recalcBorderLeft = true;
  177. if(right && right->oldRealSelfTes<5 && right->newRealSelfTes!=right->oldRealSelfTes)
  178. recalcBorderRight = true;
  179. if(bottom && bottom->oldRealSelfTes<5 && bottom->newRealSelfTes!=bottom->oldRealSelfTes)
  180. recalcBorderBottom = true;
  181. if(top && top->oldRealSelfTes<5 && top->newRealSelfTes!=top->oldRealSelfTes)
  182. recalcBorderTop = true;
  183. int lT = left->getNewTessellationSafe(),
  184. rT = right->getNewTessellationSafe(),
  185. bT = bottom->getNewTessellationSafe(),
  186. tT = top->getNewTessellationSafe();
  187. //oldRealSelfTes = realSelfTes;
  188. //bool lReTes = leftTes!=lT && lT>selfTes;
  189. if(forceBufferCreate || newRealSelfTes!=realSelfTes || newSelfTes!=selfTes || leftTes!=lT || rightTes!=rT || bottomTes!=bT || topTes!=tT)
  190. {
  191. realSelfTes = newRealSelfTes;
  192. selfTes = newSelfTes;
  193. leftTes = lT;
  194. rightTes = rT;
  195. bottomTes = bT;
  196. topTes = tT;
  197. //selfTes = 1;
  198. //leftTes = rightTes = topTes = bottomTes = 2;
  199. assert(selfTes-lT<=1);
  200. assert(selfTes-rT<=1);
  201. assert(selfTes-bT<=1);
  202. assert(selfTes-tT<=1);
  203. createTessellation(selfTes, leftTes, rightTes, bottomTes, topTes);
  204. forceBufferCreate = false;
  205. //numVertices = numNewVertices;
  206. //numIndices = numNewIndices;
  207. forceBufferCreate = true;
  208. }
  209. float er0 = errors[realSelfTes].diff,
  210. er1 = errors[realSelfTes+1].diff,
  211. maxErr = master->getMaxError();
  212. if(realSelfTes>=MAX_SUBDIV)
  213. er1 = 2.0f*er0;
  214. currentError = (maxErr-er0)/(er1-er0);
  215. if(realSelfTes>=4 && currentError>1.0f)
  216. currentError = 1.0f;
  217. assert(currentError<=1.0f);
  218. return false;
  219. }
  220. bool afTerrainPatch::updateTessellation2()
  221. {
  222. float selfTesEx = getExactTessellation(),
  223. leftTesEx = (left && left->isActive()) ? left->getExactTessellation() : -1.0f,
  224. rightTesEx = (right && right->isActive()) ? right->getExactTessellation() : -1.0f,
  225. bottomTesEx = (bottom && bottom->isActive()) ? bottom->getExactTessellation() : -1.0f,
  226. topTesEx = (top && top->isActive()) ? top->getExactTessellation() : -1.0f;
  227. newFollowsLeft = (selfTesEx<leftTesEx) || (selfTesEx==leftTesEx&& !left->newFollowsRight);
  228. newFollowsRight = (selfTesEx<rightTesEx) || (selfTesEx==rightTesEx && !right->newFollowsLeft);
  229. newFollowsBottom = (selfTesEx<bottomTesEx) || (selfTesEx==bottomTesEx && !bottom->newFollowsTop);
  230. newFollowsTop = (selfTesEx<topTesEx) || (selfTesEx==topTesEx && !top->newFollowsBottom);
  231. // check if this patch does no longer follow a neighbor
  232. // if there was no retessellation due to some other reason, we have to do one NOW
  233. if(!forceBufferCreate)
  234. if((!newFollowsLeft && followsLeft) || (!newFollowsRight && followsRight) ||
  235.    (!newFollowsBottom && followsBottom) || (!newFollowsTop && followsTop))
  236. {
  237. assert(selfTes-leftTes<=1);
  238. assert(selfTes-rightTes<=1);
  239. assert(selfTes-bottomTes<=1);
  240. assert(selfTes-topTes<=1);
  241. createTessellation(selfTes, leftTes, rightTes, bottomTes, topTes);
  242. numVertices = numNewVertices;
  243. numIndices = numNewIndices;
  244. forceRetessellation = true;
  245. }
  246. fillMorphVertices();
  247. return false;
  248. }
  249. bool afTerrainPatch::updateTessellation3()
  250. {
  251. checkBorderLeft();
  252. checkBorderRight();
  253. checkBorderBottom();
  254. checkBorderTop();
  255. fillBuffers();
  256. followsLeft = newFollowsLeft;
  257. followsRight = newFollowsRight;
  258. followsBottom = newFollowsBottom;
  259. followsTop = newFollowsTop;
  260. recalcBorderLeft = false;
  261. recalcBorderRight = false;
  262. recalcBorderBottom = false;
  263. recalcBorderTop = false;
  264. forceRetessellation = false;
  265. return false;
  266. }
  267. int afTerrainPatch::render()
  268. {
  269. if(!isVisible())
  270. return 0;
  271. if(iBuffer==NULL || vBuffer==NULL) // nothing to do ?
  272. return 0;
  273. float factorLeft2=0.0f, factorRight2=0.0f, factorBottom2=0.0f, factorTop2=0.0f;
  274. assert(selfTes>=0 && selfTes<=MAX_SUBDIV);
  275. factorSelf = 1.0f-currentError;
  276. factorLeft = left ? 1.0f-left->getCurrentError() : 0.0f;
  277. factorRight = right ? 1.0f-right->getCurrentError() : 0.0f;
  278. factorBottom = bottom ? 1.0f-bottom->getCurrentError() : 0.0f;
  279. factorTop = top ? 1.0f-top->getCurrentError() : 0.0f;
  280. assert(factorSelf>=0.0f);
  281. assert(factorLeft>=0.0f);
  282. assert(factorRight>=0.0f);
  283. assert(factorBottom>=0.0f);
  284. assert(factorTop>=0.0f);
  285. // clamping for patches which use selfTes!=realSelfTes
  286. //
  287. if(factorSelf>=1.0f)
  288. factorSelf = 1.0f;
  289. if(factorLeft>=1.0f)
  290. factorLeft = 1.0f;
  291. if(factorRight>=1.0f)
  292. factorRight = 1.0f;
  293. if(factorBottom>=1.0f)
  294. factorBottom = 1.0f;
  295. if(factorTop>=1.0f)
  296. factorTop = 1.0f;
  297. factorLeft2 = (1.0f-factorSelf) * factorLeft;
  298. factorRight2 = (1.0f-factorSelf) * factorRight;
  299. factorBottom2 = (1.0f-factorSelf) * factorBottom;
  300. factorTop2 = (1.0f-factorSelf) * factorTop;
  301. D3DXVECTOR4 weights0(factorSelf, 0.0f, 0.5f, 1.0f),
  302. weights2(factorLeft, factorLeft2, factorRight, factorRight2),
  303. weights3(factorBottom, factorBottom2, factorTop, factorTop2);
  304. pd3dDevice->SetVertexShaderConstantF(0, (float*)&weights0, 1);
  305. pd3dDevice->SetVertexShaderConstantF(2, (float*)&weights2, 1);
  306. pd3dDevice->SetVertexShaderConstantF(3, (float*)&weights3, 1);
  307. pd3dDevice->SetStreamSource(0, vBuffer, 0,sizeof(PATCHVERTEX_MORPH_HW));
  308. pd3dDevice->SetIndices(iBuffer);
  309. // draw the patch with one single D3D call
  310. HRESULT hr = pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP,0, 0, numVertices, 0, numIndices-2);
  311. if(hr==D3D_OK)
  312. return numIndices-2;
  313. else
  314. return 0;
  315. }
  316. // check if the patch is visible on the screen (clipping)
  317. //
  318. bool afTerrainPatch::checkVisibility(const D3DXMATRIX* nMatrix, const afPlane nPlanes[6])
  319. {
  320. D3DXVECTOR3 pt0,pt1,pt2,pt3,pt4,pt5,pt6,pt7, tpt0,tpt1,tpt2,tpt3,tpt4,tpt5,tpt6,tpt7, tp0,tp1,tp2,tp3;
  321. const D3DXMATRIX& mat = *nMatrix;
  322. //visible = true;
  323. //return;
  324. // create and transform the cubes corners vertices
  325. //
  326. pt0.x = pos.x; pt0.y = pos.y + minY; pt0.z = pos.z;
  327. pt1.x = pos.x + scale.x; pt1.y = pos.y + minY; pt1.z = pos.z;
  328. pt2.x = pos.x; pt2.y = pos.y + minY; pt2.z = pos.z + scale.z;
  329. pt3.x = pos.x + scale.x; pt3.y = pos.y + minY; pt3.z = pos.z + scale.z;
  330. pt4.x = pt0.x; pt4.y = pt0.y + maxY; pt4.z = pt0.z;
  331. pt5.x = pt1.x; pt5.y = pt1.y + maxY; pt5.z = pt1.z;
  332. pt6.x = pt2.x; pt6.y = pt2.y + maxY; pt6.z = pt2.z;
  333. pt7.x = pt3.x; pt7.y = pt3.y + maxY; pt7.z = pt3.z;
  334. D3DXVec3TransformCoord(&tpt0, &pt0, &mat);
  335. D3DXVec3TransformCoord(&tpt1, &pt1, &mat);
  336. D3DXVec3TransformCoord(&tpt2, &pt2, &mat);
  337. D3DXVec3TransformCoord(&tpt3, &pt3, &mat);
  338. D3DXVec3TransformCoord(&tpt4, &pt4, &mat);
  339. D3DXVec3TransformCoord(&tpt5, &pt5, &mat);
  340. D3DXVec3TransformCoord(&tpt6, &pt6, &mat);
  341. D3DXVec3TransformCoord(&tpt7, &pt7, &mat);
  342. // check against all six planes
  343. //
  344. for(int i=0; i<6; i++)
  345. {
  346. const afPlane& p = nPlanes[i];
  347. bool v = false;
  348. if(tpt0.x*p.x + tpt0.y*p.y + tpt0.z*p.z < p.d)
  349. v = true;
  350. else
  351. if(tpt1.x*p.x + tpt1.y*p.y + tpt1.z*p.z < p.d)
  352. v = true;
  353. else
  354. if(tpt2.x*p.x + tpt2.y*p.y + tpt2.z*p.z < p.d)
  355. v = true;
  356. else
  357. if(tpt3.x*p.x + tpt3.y*p.y + tpt3.z*p.z < p.d)
  358. v = true;
  359. else
  360. if(tpt4.x*p.x + tpt4.y*p.y + tpt4.z*p.z < p.d)
  361. v = true;
  362. else
  363. if(tpt5.x*p.x + tpt5.y*p.y + tpt5.z*p.z < p.d)
  364. v = true;
  365. else
  366. if(tpt6.x*p.x + tpt6.y*p.y + tpt6.z*p.z < p.d)
  367. v = true;
  368. else
  369. if(tpt7.x*p.x + tpt7.y*p.y + tpt7.z*p.z < p.d)
  370. v = true;
  371. if(v==false)
  372. {
  373. setVisible(false);
  374. return false;
  375. }
  376. }
  377. setVisible(true);
  378. return true;
  379. }
  380. void afTerrainPatch::setVisible(bool nVis)
  381. {
  382. visible = nVis;
  383. if(visible)
  384. {
  385. flagActive = true;
  386. if(!active)
  387. init();
  388. }
  389. else if(active)
  390. deinit();
  391. }
  392. void afTerrainPatch::calcMinMaxY()
  393. {
  394. afVec3 p;
  395. minY = scale.y;
  396. maxY = 0.0f;
  397. for(int x=0; x<SOURCE_WIDTH; x++)
  398. for(int y=0; y<SOURCE_HEIGHT; y++)
  399. {
  400. getVertex(x,y, p);
  401. if(p.y<minY)
  402. minY = p.y;
  403. if(p.y>maxY)
  404. maxY = p.y;
  405. }
  406. }
  407. void afTerrainPatch::updateProjectedErrors(const D3DXMATRIX* nMatrix)
  408. {
  409. D3DXVECTOR3 corr0, real0, corr, real;
  410. setD3DVec(corr0, errors[1].correct);
  411. D3DXVec3TransformCoord(&corr, &corr0, nMatrix);
  412. assert(corr.z>0.0f);
  413. if(corr.z<0.0f)
  414. corr.z = 0.0f;
  415. for(int i=1; i<=MAX_SUBDIV; i++)
  416. {
  417. setD3DVec(real0, errors[i].real);
  418. D3DXVec3TransformCoord(&real, &real0, nMatrix);
  419. assert(real.z>0.0f);
  420. if(real.z<0.0f)
  421. real.z = 0.0f;
  422. afVec3 diff(corr.x-real.x, corr.y-real.y, corr.z-real.z);
  423. errors[i].diff = diff.length();
  424. if(errors[i].diff<errors[i-1].diff*1.1f)
  425. errors[i].diff = errors[i-1].diff*1.1f;
  426. }
  427. }
  428. void afTerrainPatch::calcErrors()
  429. {
  430. for(int i=0; i<=MAX_SUBDIV; i++)
  431. calcError(i);
  432. }
  433. void afTerrainPatch::calcError(int nTes)
  434. {
  435. float sumError = 0.0f;
  436. int numErrors = 0;
  437. if(nTes!=0)
  438. {
  439. int pow = getPowerTwo(nTes),
  440. x0,y0, xi,yi;
  441. for(y0=0; y0<SOURCE_HEIGHT-pow; y0+=pow)
  442. for(x0=0; x0<SOURCE_WIDTH-pow; x0+=pow)
  443. for(yi=1; yi<pow; yi++)
  444. for(xi=1; xi<pow; xi++)
  445. {
  446. int x = x0+xi,
  447. y = y0+yi;
  448. float fx0 = (float)xi/(float)pow, fx1 = 1.0f-fx0,
  449. fy0 = (float)yi/(float)pow, fy1 = 1.0f-fy0;
  450. float height00 = getHeight(x0,y0),
  451. height10 = getHeight(x0+pow,y0),
  452. height01 = getHeight(x0,y0+pow),
  453. height11 = getHeight(x0+pow,y0+pow);
  454. float paintHeight = fx1*fy1 * height00 +
  455. fx0*fy1 * height10 +
  456. fx1*fy0 * height01 +
  457. fx0*fy0 * height11,
  458. correctHeight =  getHeight(x,y);
  459. float er = (float)fabs(correctHeight - paintHeight);
  460. numErrors++;
  461. sumError += er;
  462. }
  463. float error = sumError / numErrors;
  464. getVertex(SOURCE_WIDTH/2, SOURCE_HEIGHT/2, errors[nTes].correct);
  465. errors[nTes].real = errors[nTes].correct;
  466. errors[nTes].real.y += error;
  467. errors[nTes].diff = error;
  468. }
  469. }
  470. float afTerrainPatch::getExactTessellation() const
  471. {
  472. if(realSelfTes<0)
  473. return -1.0f;
  474. if(currentError<0.0f)
  475. return (float)realSelfTes;
  476. else
  477. return (float)realSelfTes + currentError;
  478. }
  479. int afTerrainPatch::getPowerTwo(int nVal)
  480. {
  481. switch(nVal)
  482. {
  483. case 0:
  484. default:
  485. return 1;
  486. case 1:
  487. return 2;
  488. case 2:
  489. return 4;
  490. case 3:
  491. return 8;
  492. case 4:
  493. return 16;
  494. case 5:
  495. return 32;
  496. case 6:
  497. return 64;
  498. }
  499. }
  500. void afTerrainPatch::createTessellation(int nCenter, int nLeft, int nRight, int nBottom, int nTop)
  501. {
  502. assert(indexMap);
  503. assert(vertices);
  504. assert(indices);
  505. memset(indexMap, 0xff, MAX_VERTICES*sizeof(unsigned short));
  506. numNewVertices = numNewIndices = 0;
  507. int pow = getPowerTwo(nCenter);
  508. assert(nCenter-nLeft<=1);
  509. assert(nCenter-nRight<=1);
  510. assert(nCenter-nBottom<=1);
  511. assert(nCenter-nTop<=1);
  512. bool bLeft(nLeft<nCenter), bRight(nRight<nCenter), bBottom(nBottom<nCenter), bTop(nTop<nCenter);
  513. if(pow==16)
  514. addLevel4PatchTriangles(bLeft, bRight, bBottom, bTop);
  515. else
  516. for(int y=0; y<SOURCE_HEIGHT-pow; y+=pow)
  517. addTriangleRow(y, pow, bLeft, bRight, bBottom, bTop);
  518. assert((numNewIndices&1) == 0); // indices must always be an even number (we store quads as two triangles)
  519. if(realSelfTes>selfTes)
  520. reduceShapeTo(realSelfTes, vertices);
  521. makeBordersSimpler(vertices);
  522. }
  523. /****************************************************************************************
  524. *                                                                                        *
  525. *                                                                                        *
  526. *                                Tessellation Sub Methods                                 *
  527. *                                                                                        *
  528. *                                                                                        *
  529. ****************************************************************************************/
  530. // calls makeSimpler() sequentially to make a mesh with
  531. // selfTes<nTes to look like being created with nTes
  532. void afTerrainPatch::reduceShapeTo(int nTes, PATCHVERTEX *nData)
  533. {
  534. for(int t=nTes; t>0; t--)
  535. if(selfTes<t)
  536. makeSimpler(t, nData);
  537. }
  538. void afTerrainPatch::makeBordersSimpler(PATCHVERTEX *nData)
  539. {
  540. int sT = selfTes;
  541. int x,y, idx,idx0,idx1, pow,
  542. lDiff = sT-leftTes,
  543. rDiff = sT-rightTes,
  544. bDiff = sT-bottomTes,
  545. tDiff = sT-topTes;
  546. if((lDiff==1 || lDiff==-1) && left)
  547. {
  548. pow = getPowerTwo(min(leftTes,sT));
  549. for(y=pow; y<SOURCE_HEIGHT-1; y+=2*pow)
  550. {
  551. idx = indexMap[0 + y*SOURCE_WIDTH];
  552. idx0 = indexMap[0 + (y-pow)*SOURCE_WIDTH];
  553. idx1 = indexMap[0 + (y+pow)*SOURCE_WIDTH];
  554. assert(idx!=0xffff);
  555. assert(idx0!=0xffff);
  556. assert(idx1!=0xffff);
  557. nData[idx].pos.y = (nData[idx0].pos.y + nData[idx1].pos.y)/2.0f;
  558. }
  559. }
  560. if((rDiff==1 || rDiff==-1) && right)
  561. {
  562. pow = getPowerTwo(min(rightTes,sT));
  563. for(y=pow; y<SOURCE_HEIGHT-1; y+=2*pow)
  564. {
  565. idx = indexMap[SOURCE_WIDTH-1 + y*SOURCE_WIDTH];
  566. idx0 = indexMap[SOURCE_WIDTH-1 + (y-pow)*SOURCE_WIDTH];
  567. idx1 = indexMap[SOURCE_WIDTH-1 + (y+pow)*SOURCE_WIDTH];
  568. assert(idx!=0xffff);
  569. assert(idx0!=0xffff);
  570. assert(idx1!=0xffff);
  571. nData[idx].pos.y = (nData[idx0].pos.y + nData[idx1].pos.y)/2.0f;
  572. }
  573. }
  574. if((bDiff==1 || bDiff==-1) && bottom)
  575. {
  576. pow = getPowerTwo(min(bottomTes, sT));
  577. for(x=pow; x<SOURCE_WIDTH-1; x+=2*pow)
  578. {
  579. idx = indexMap[x + 0*SOURCE_WIDTH];
  580. idx0 = indexMap[x-pow + 0*SOURCE_WIDTH];
  581. idx1 = indexMap[x+pow + 0*SOURCE_WIDTH];
  582. assert(idx!=0xffff);
  583. assert(idx0!=0xffff);
  584. assert(idx1!=0xffff);
  585. nData[idx].pos.y = (nData[idx0].pos.y + nData[idx1].pos.y)/2.0f;
  586. }
  587. }
  588. if((tDiff==1 || tDiff==-1) && top)
  589. {
  590. pow = getPowerTwo(min(topTes,sT));
  591. for(x=pow; x<SOURCE_WIDTH-1; x+=2*pow)
  592. {
  593. idx = indexMap[x + (SOURCE_HEIGHT-1)*SOURCE_WIDTH];
  594. idx0 = indexMap[x-pow + (SOURCE_HEIGHT-1)*SOURCE_WIDTH];
  595. idx1 = indexMap[x+pow + (SOURCE_HEIGHT-1)*SOURCE_WIDTH];
  596. assert(idx!=0xffff);
  597. assert(idx0!=0xffff);
  598. assert(idx1!=0xffff);
  599. nData[idx].pos.y = (nData[idx0].pos.y + nData[idx1].pos.y)/2.0f;
  600. }
  601. }
  602. }
  603. // this methods makes the mesh looking simpler by
  604. // putting vertices into position inbetween its neighbors
  605. // this method can do only for one step at a time
  606. // (to make a tes_1 mesh look like tes_3 first call
  607. // makeSimpler(3,...) then makeSimpler(2,...)
  608. // Call reduceShapeTo() which cares about those constraints
  609. // automatically
  610. void afTerrainPatch::makeSimpler(int nTes, PATCHVERTEX *nData)
  611. {
  612. assert(selfTes<nTes);
  613. assert(nTes>0);
  614. int pow = getPowerTwo(nTes-1),
  615. x,y, xc,yc;
  616. for(yc=y=0; y<SOURCE_HEIGHT; y+=pow,yc++)
  617. for(xc=x=0; x<SOURCE_WIDTH; x+=pow,xc++)
  618. calculateInbetweenVertex(x, y, xc, yc, pow, nData);
  619. }
  620. void afTerrainPatch::calculateInbetweenVertex(int x, int y, int xc, int yc, int pow, PATCHVERTEX *nData)
  621. {
  622. float heightLeftTop=0.0f, heightRightBottom=0.0f;
  623. int idx, idxLT,idxRB;
  624. idx = calculateDiagonalVertices(x, y, xc, yc, pow, nData, heightLeftTop, idxLT, heightRightBottom, idxRB);
  625. if(idx>=0)
  626. nData[idx].pos.y = (heightLeftTop + heightRightBottom) / 2.0f;
  627. }
  628. int afTerrainPatch::calculateDiagonalVertices(int x, int y, int xc, int yc, int pow, PATCHVERTEX *nData,
  629.   float& nHeightLeftTop, int& idxLT, float& nHeightRightBottom, int& idxRB)
  630. {
  631. int c = (xc&1) + (yc&1)*2,
  632. idx = indexMap[x + y*SOURCE_WIDTH];
  633. assert(idx!=0xffff);
  634. switch(c)
  635. {
  636. case 0: // even-x & even-y
  637. // nothing to do...
  638. return -1;
  639. case 1: // odd-x & even-y
  640. assert(x>0 && x<SOURCE_WIDTH-1);
  641. idxLT = indexMap[x-pow + y*SOURCE_WIDTH];
  642. idxRB = indexMap[x+pow + y*SOURCE_WIDTH];
  643. assert(idxLT!=0xffff);
  644. assert(idxRB!=0xffff);
  645. nHeightLeftTop = nData[idxLT].pos.y;
  646. nHeightRightBottom = nData[idxRB].pos.y;
  647. return idx;
  648. case 2: // even-x & odd-y
  649. assert(y>0 && y<SOURCE_HEIGHT-1);
  650. idxLT = indexMap[x + (y+pow)*SOURCE_WIDTH];
  651. idxRB = indexMap[x + (y-pow)*SOURCE_WIDTH];
  652. assert(idxLT!=0xffff);
  653. assert(idxRB!=0xffff);
  654. nHeightLeftTop = nData[idxLT].pos.y;
  655. nHeightRightBottom = nData[idxRB].pos.y;
  656. return idx;
  657. case 3: // odd-x & odd-y
  658. assert(x>0 && x<SOURCE_WIDTH-1);
  659. assert(y>0 && y<SOURCE_HEIGHT-1);
  660. idxLT = indexMap[x-pow + (y+pow)*SOURCE_WIDTH];
  661. idxRB = indexMap[x+pow + (y-pow)*SOURCE_WIDTH];
  662. assert(idxLT!=0xffff);
  663. assert(idxRB!=0xffff);
  664. nHeightLeftTop = nData[idxLT].pos.y;
  665. nHeightRightBottom = nData[idxRB].pos.y;
  666. return idx;
  667. default:
  668. assert(false); // should never come here...
  669. return -1;
  670. }
  671. //nData[idx].pos.y = (y0+y1)/2.0f;
  672. }
  673. void afTerrainPatch::addTriangleRow(int nY, int nPow, bool nLeft, bool nRight, bool nBottom, bool nTop)
  674. {
  675. int powH = nPow/2;
  676. // special case: bottom line with nBottom
  677. //
  678. if(nY==0 && nBottom)
  679. {
  680. addTriangleBottomRow(nPow, nLeft, nRight);
  681. return;
  682. }
  683. if(nY!=0)
  684. {
  685. addLastIndexAgain();
  686. addIndex(getIndex(0,nY));
  687. }
  688. // special case: top line with nTop
  689. //
  690. if(nY>=SOURCE_HEIGHT-2*nPow && nTop)
  691. {
  692. addTriangleTopRow(nPow, nLeft, nRight);
  693. return;
  694. }
  695. // all other cases
  696. //
  697. int x, x0=0, x1=SOURCE_WIDTH;
  698. if(nLeft)
  699. {
  700. assert(powH>=1);
  701. addIndex(getIndex(0,nY));
  702. addIndex(getIndex(0,nY+powH));
  703. addIndex(getIndex(nPow,nY));
  704. addIndex(getIndex(0,nY+nPow));
  705. addIndex(getIndex(nPow,nY+nPow));
  706. addLastIndexAgain(); // finalize sub-strip
  707. x0 = nPow;
  708. }
  709. if(nRight)
  710. x1 -= nPow;
  711. for(x=x0; x<x1; x+=nPow)
  712. {
  713. addIndex(getIndex(x,nY));
  714. addIndex(getIndex(x,nY+nPow));
  715. }
  716. if(nRight)
  717. {
  718. assert(powH>=1);
  719. addIndex(getIndex(SOURCE_WIDTH-1-nPow,nY));
  720. addLastIndexAgain(); // reverse oriented triangles
  721. addIndex(getIndex(SOURCE_WIDTH-1,nY));
  722. addIndex(getIndex(SOURCE_WIDTH-1-nPow,nY+nPow));
  723. addIndex(getIndex(SOURCE_WIDTH-1,nY+powH));
  724. addIndex(getIndex(SOURCE_WIDTH-1,nY+nPow));
  725. }
  726. }
  727. void afTerrainPatch::addTriangleBottomRow(int nPow, bool nLeft, bool nRight)
  728. {
  729. int powH = nPow/2;
  730. int x0=0, x1=SOURCE_WIDTH-1;
  731. assert(powH>=1);
  732. if(nLeft)
  733. {
  734. addIndex(getIndex(0,0));
  735. addIndex(getIndex(0,powH));
  736. addIndex(getIndex(powH,0));
  737. addIndex(getIndex(0,nPow));
  738. addIndex(getIndex(nPow,0));
  739. addIndex(getIndex(nPow,nPow));
  740. x0 = nPow;
  741. }
  742. assert((numNewIndices&1) == 0);
  743. if(nRight)
  744. x1 -= nPow;
  745. for(int x=x0; x<x1; x+=nPow)
  746. {
  747. addIndex(getIndex(x,0));
  748. addLastIndexAgain(); // reverse oriented triangles
  749. addIndex(getIndex(x+powH,0));
  750. addIndex(getIndex(x,nPow));
  751. addIndex(getIndex(x+nPow,0));
  752. addIndex(getIndex(x+nPow,nPow));
  753. }
  754. assert((numNewIndices&1) == 0);
  755. if(nRight)
  756. {
  757. addIndex(getIndex(SOURCE_WIDTH-1-nPow,0));
  758. addIndex(getIndex(SOURCE_WIDTH-1-nPow,nPow));
  759. addIndex(getIndex(SOURCE_WIDTH-1-powH,0));
  760. addIndex(getIndex(SOURCE_WIDTH-1,0));
  761. addLastIndexAgain(); // finalize sub-strip
  762. addIndex(getIndex(SOURCE_WIDTH-1-nPow,nPow));
  763. addIndex(getIndex(SOURCE_WIDTH-1,powH));
  764. addIndex(getIndex(SOURCE_WIDTH-1,nPow));
  765. }
  766. assert((numNewIndices&1) == 0);
  767. }
  768. void afTerrainPatch::addTriangleTopRow(int nPow, bool nLeft, bool nRight)
  769. {
  770. int powH = nPow/2;
  771. int x0=0, x1=SOURCE_WIDTH-1;
  772. assert(powH>=1);
  773. if(nLeft)
  774. {
  775. addIndex(getIndex(0,SOURCE_HEIGHT-1-nPow));
  776. addIndex(getIndex(0,SOURCE_HEIGHT-1-powH));
  777. addIndex(getIndex(nPow,SOURCE_HEIGHT-1-nPow));
  778. addIndex(getIndex(0,SOURCE_HEIGHT-1));
  779. addIndex(getIndex(powH,SOURCE_HEIGHT-1));
  780. addLastIndexAgain(); // reverse oriented triangles
  781. addIndex(getIndex(nPow,SOURCE_HEIGHT-1-nPow));
  782. addIndex(getIndex(nPow,SOURCE_HEIGHT-1));
  783. x0 = nPow;
  784. }
  785. assert((numNewIndices&1) == 0);
  786. if(nRight)
  787. x1 -= nPow;
  788. for(int x=x0; x<x1; x+=nPow)
  789. {
  790. addIndex(getIndex(x,SOURCE_HEIGHT-1-nPow));
  791. addIndex(getIndex(x,SOURCE_HEIGHT-1));
  792. addIndex(getIndex(x+nPow,SOURCE_HEIGHT-1-nPow));
  793. addIndex(getIndex(x+powH,SOURCE_HEIGHT-1));
  794. addIndex(getIndex(x+nPow,SOURCE_HEIGHT-1));
  795. addLastIndexAgain(); // reverse oriented triangles
  796. }
  797. if(nRight)
  798. {
  799. addIndex(getIndex(x,SOURCE_HEIGHT-1-nPow));
  800. addIndex(getIndex(x,SOURCE_HEIGHT-1));
  801. addIndex(getIndex(x+nPow,SOURCE_HEIGHT-1-nPow));
  802. addIndex(getIndex(x+powH,SOURCE_HEIGHT-1));
  803. addIndex(getIndex(x+nPow,SOURCE_HEIGHT-1-powH));
  804. addIndex(getIndex(x+nPow,SOURCE_HEIGHT-1));
  805. }
  806. }
  807. void afTerrainPatch::addLevel4PatchTriangles(bool nLeft, bool nRight, bool nBottom, bool nTop)
  808. {
  809. const int powH = 8, pow = 16;
  810. int code = (nLeft ? 1 : 0) | (nRight ? 2 : 0) | (nBottom ? 4 : 0) | (nTop ? 8 : 0);
  811. // use the created code for fast selection of the case to build...
  812. //
  813. switch(code)
  814. {
  815. case 0:
  816. addIndex(getIndex(0,0));
  817. addIndex(getIndex(0,pow));
  818. addIndex(getIndex(pow,0));
  819. addIndex(getIndex(pow,pow));
  820. break;
  821. case 1:
  822. addIndex(getIndex(0,0));
  823. addIndex(getIndex(0,powH));
  824. addIndex(getIndex(pow,0));
  825. addIndex(getIndex(0,pow));
  826. addIndex(getIndex(pow,pow));
  827. addLastIndexAgain();
  828. break;
  829. case 2:
  830. addIndex(getIndex(pow,pow));
  831. addIndex(getIndex(pow,powH));
  832. addIndex(getIndex(0,pow));
  833. addIndex(getIndex(pow,0));
  834. addIndex(getIndex(0,0));
  835. addLastIndexAgain();
  836. break;
  837. case 3:
  838. addIndex(getIndex(0,0));
  839. addIndex(getIndex(0,powH));
  840. addIndex(getIndex(pow,0));
  841. addIndex(getIndex(0,pow));
  842. addIndex(getIndex(pow,powH));
  843. addIndex(getIndex(pow,pow));
  844. break;
  845. case 4:
  846. addIndex(getIndex(0,0));
  847. addLastIndexAgain();
  848. addIndex(getIndex(powH,0));
  849. addIndex(getIndex(0,pow));
  850. addIndex(getIndex(pow,0));
  851. addIndex(getIndex(pow,pow));
  852. break;
  853. case 5:
  854. addIndex(getIndex(0,0));
  855. addIndex(getIndex(0,powH));
  856. addIndex(getIndex(powH,0));
  857. addIndex(getIndex(0,pow));
  858. addIndex(getIndex(pow,0));
  859. addIndex(getIndex(pow,pow));
  860. break;
  861. case 6:
  862. addIndex(getIndex(0,0));
  863. addIndex(getIndex(0,pow));
  864. addIndex(getIndex(powH,0));
  865. addIndex(getIndex(pow,0));
  866. addLastIndexAgain();
  867. addIndex(getIndex(0,pow));
  868. addIndex(getIndex(pow,powH));
  869. addIndex(getIndex(pow,pow));
  870. break;
  871. case 7:
  872. addIndex(getIndex(pow,pow));
  873. addIndex(getIndex(pow,powH));
  874. addIndex(getIndex(0,pow));
  875. addIndex(getIndex(pow,0));
  876. addIndex(getIndex(0,powH));
  877. addIndex(getIndex(powH,0));
  878. addIndex(getIndex(0,0));
  879. addLastIndexAgain();
  880. break;
  881. case 8:
  882. addIndex(getIndex(pow,pow));
  883. addLastIndexAgain();
  884. addIndex(getIndex(powH,pow));
  885. addIndex(getIndex(pow,0));
  886. addIndex(getIndex(0,pow));
  887. addIndex(getIndex(0,0));
  888. break;
  889. case 9:
  890. addIndex(getIndex(pow,pow));
  891. addIndex(getIndex(pow,0));
  892. addIndex(getIndex(powH,pow));
  893. addIndex(getIndex(0,pow));
  894. addLastIndexAgain();
  895. addIndex(getIndex(pow,0));
  896. addIndex(getIndex(0,powH));
  897. addIndex(getIndex(0,0));
  898. break;
  899. case 10:
  900. addIndex(getIndex(pow,pow));
  901. addIndex(getIndex(pow,powH));
  902. addIndex(getIndex(powH,pow));
  903. addIndex(getIndex(pow,0));
  904. addIndex(getIndex(0,pow));
  905. addIndex(getIndex(0,0));
  906. break;
  907. case 11:
  908. addIndex(getIndex(0,0));
  909. addIndex(getIndex(0,powH));
  910. addIndex(getIndex(pow,0));
  911. addIndex(getIndex(0,pow));
  912. addIndex(getIndex(pow,powH));
  913. addIndex(getIndex(powH,pow));
  914. addIndex(getIndex(pow,pow));
  915. addLastIndexAgain();
  916. break;
  917. case 12:
  918. addIndex(getIndex(0,0));
  919. addLastIndexAgain();
  920. addIndex(getIndex(powH,0));
  921. addIndex(getIndex(0,pow));
  922. addIndex(getIndex(pow,0));
  923. addIndex(getIndex(powH,pow));
  924. addIndex(getIndex(pow,pow));
  925. addLastIndexAgain();
  926. break;
  927. case 13:
  928. addIndex(getIndex(0,0));
  929. addIndex(getIndex(0,powH));
  930. addIndex(getIndex(powH,0));
  931. addIndex(getIndex(0,pow));
  932. addIndex(getIndex(pow,0));
  933. addIndex(getIndex(powH,pow));
  934. addIndex(getIndex(pow,pow));
  935. addLastIndexAgain();
  936. break;
  937. case 14:
  938. addIndex(getIndex(pow,pow));
  939. addIndex(getIndex(pow,powH));
  940. addIndex(getIndex(powH,pow));
  941. addIndex(getIndex(pow,0));
  942. addIndex(getIndex(0,pow));
  943. addIndex(getIndex(powH,0));
  944. addIndex(getIndex(0,0));
  945. addLastIndexAgain();
  946. break;
  947. case 15:
  948. addIndex(getIndex(0,0));
  949. addIndex(getIndex(0,powH));
  950. addIndex(getIndex(powH,0));
  951. addIndex(getIndex(0,pow));
  952. addIndex(getIndex(pow,0));
  953. addIndex(getIndex(powH,pow));
  954. addIndex(getIndex(pow,powH));
  955. addIndex(getIndex(pow,pow));
  956. break;
  957. }
  958. assert((numNewIndices&1) == 0); // indices must always be an even number (we store quads as two triangles)
  959. }
  960. inline float afTerrainPatch::getHeight(int nX, int nY) const
  961. {
  962. assert(nX>=0 && nX<SOURCE_WIDTH);
  963. assert(nY>=0 && nY<SOURCE_HEIGHT);
  964. assert(master);
  965. return pos.y + scale.y * master->getHeight(hmX0+nX, hmY0+nY); // - scale.y*0.5f;
  966. }
  967. inline void afTerrainPatch::getVertex(int nX, int nY, afVec3& nPoint) const
  968. {
  969. assert(nX>=0 && nX<SOURCE_WIDTH);
  970. assert(nY>=0 && nY<SOURCE_HEIGHT);
  971. nPoint.x = pos.x+scale.x*nX / (float)(SOURCE_WIDTH-1);
  972. nPoint.y = getHeight(nX,nY);
  973. nPoint.z = pos.z+scale.z*nY / (float)(SOURCE_HEIGHT-1);
  974. }
  975. inline void afTerrainPatch::getTexCoord(int nX, int nY, afVec2& nTCoord) const
  976. {
  977. assert(nX>=0 && nX<SOURCE_WIDTH);
  978. assert(nY>=0 && nY<SOURCE_HEIGHT);
  979. assert(master);
  980. master->getTexCoord(hmX0+nX, hmY0+nY, nTCoord);
  981. }
  982. inline void afTerrainPatch::getNormal(int nX, int nY, afVec3& nNormal) const
  983. {
  984. assert(nX>=0 && nX<SOURCE_WIDTH);
  985. assert(nY>=0 && nY<SOURCE_HEIGHT);
  986. assert(master);
  987. master->getNormal(hmX0+nX, hmY0+nY, nNormal);
  988. }
  989. unsigned short afTerrainPatch::getIndex(int nX, int nY)
  990. {
  991. int idx = nX + nY * SOURCE_WIDTH;
  992. assert(nX>=0 && nX<SOURCE_WIDTH);
  993. assert(nY>=0 && nY<SOURCE_HEIGHT);
  994. assert(idx<MAX_VERTICES);
  995. if(indexMap[idx]==0xffff)
  996. {
  997. indexMap[idx] = (unsigned short)numNewVertices;
  998. getVertex(nX,nY, vertices[numNewVertices].pos);
  999. getTexCoord(nX,nY, vertices[numNewVertices].tex);
  1000. numNewVertices++;
  1001. }
  1002. return indexMap[idx];
  1003. }
  1004. int afTerrainPatch::getNewTessellationSafe() const
  1005. {
  1006. if(this==NULL)
  1007. return MAX_SUBDIV;
  1008. if(!isVisible())
  1009. return  selfTes; // MAX_SUBDIV;
  1010. return getNewTessellation();
  1011. }
  1012. void afTerrainPatch::fillMorphVertices()
  1013. {
  1014. if(forceBufferCreate || forceRetessellation)
  1015. {
  1016. memcpy(verticesLow, vertices, numNewVertices*sizeof(PATCHVERTEX));
  1017. if(realSelfTes<4)
  1018. {
  1019. reduceShapeTo(realSelfTes+1, verticesLow);
  1020. makeBordersSimpler(verticesLow);
  1021. }
  1022. //if(selfTes==realSelfTes+1)
  1023. // memcpy(verticesLow, vertices, numNewVertices*sizeof(PATCHVERTEX));
  1024. for(int i=0; i<numNewVertices; i++)
  1025. yMoveSelf[i] = vertices[i].pos.y - verticesLow[i].pos.y;
  1026. }
  1027. }
  1028. void afTerrainPatch::checkBorderLeft()
  1029. {
  1030. int i, y,yc, pow;
  1031. if(forceBufferCreate || forceRetessellation || followsLeft!=newFollowsLeft)
  1032. {
  1033. for(i=0; i<numNewVertices; i++)
  1034. yMoveLeft[i] = 0.0f;
  1035. for(i=0; i<numNewVertices; i++)
  1036. yMoveLeft2[i] = 0.0f;
  1037. }
  1038. if(newFollowsLeft && (!followsLeft || forceBufferCreate || forceRetessellation || recalcBorderLeft))
  1039. {
  1040. // copy shared border column
  1041. //
  1042. assert(selfTes==left->rightTes);
  1043. assert(leftTes==left->selfTes);
  1044. assert(left->indexMap);
  1045. pow = getPowerTwo(min(selfTes,leftTes));
  1046. for(y=pow; y<SOURCE_HEIGHT-1; y+=pow)
  1047. {
  1048. int idx = indexMap[0 + y * SOURCE_WIDTH],
  1049. idxL = left->indexMap[SOURCE_WIDTH-1 + y * SOURCE_WIDTH];
  1050. assert(idx!=0xffff);
  1051. assert(idxL!=0xffff);
  1052. verticesLow[idx].pos.y = left->verticesLow[idxL].pos.y;
  1053. vertices[idx].pos.y = left->vertices[idxL].pos.y;
  1054. yMoveLeft[idx] = left->yMoveSelf[idxL];
  1055. yMoveSelf[idx] = 0.0f;
  1056. }
  1057. if(selfTes>=3)
  1058. return;
  1059. // correct border neighbors
  1060. //
  1061. pow = getPowerTwo(selfTes);
  1062. for(y=pow,yc=1; y<SOURCE_HEIGHT-1; y+=pow,yc++)
  1063. {
  1064. float yLT=0.0f,yRB=0.0f;
  1065. int idx, idxLT=0,idxRB=0;
  1066. idx = calculateDiagonalVertices(pow, y, 1, yc, pow, verticesLow, yLT,idxLT, yRB,idxRB);
  1067. assert(idx>=0 && idx!=0xffff);
  1068. float moveLT = vertices[idxLT].pos.y - verticesLow[idxLT].pos.y;
  1069. verticesLow[idx].pos.y = (yLT + yRB) / 2.0f;
  1070. // our vertex is moved 50% by the left (-top) neighbor
  1071. // this garanties that this vertex is on the diagonal when currentError is 0.0f
  1072. yMoveLeft2[idx] = moveLT * 0.5f;
  1073. yMoveSelf[idx] = vertices[idx].pos.y - verticesLow[idx].pos.y;
  1074. }
  1075. // correct neighbors to lie on a diagonal
  1076. //
  1077. if(selfTes!=realSelfTes)
  1078. {
  1079. pow = getPowerTwo(selfTes);
  1080. for(y=pow,yc=1; y<SOURCE_HEIGHT-1; y+=pow,yc++)
  1081. {
  1082. float yLT=0.0f,yRB=0.0f;
  1083. int idx, idxLT=0,idxRB=0;
  1084. idx = calculateDiagonalVertices(pow, y, 1, yc, pow, verticesLow, yLT,idxLT, yRB,idxRB);
  1085. assert(idx>=0 && idx!=0xffff);
  1086. verticesLow[idx].pos.y = (yLT + yRB) * 0.5f;
  1087. vertices[idx].pos.y = (vertices[idxLT].pos.y + vertices[idxRB].pos.y) * 0.5f;
  1088. // the real new part: this vertex always STAYS on the diagonal
  1089. //
  1090. yMoveLeft2[idx] = 0.0f;
  1091. yMoveLeft[idx] = (vertices[idxLT].pos.y - verticesLow[idxLT].pos.y) * 0.5f;
  1092. yMoveSelf[idx] = (vertices[idxRB].pos.y - verticesLow[idxRB].pos.y) * 0.5f;
  1093. }
  1094. // necessary to recorrect the shared right-top border neighbor
  1095. //
  1096. if(followsBottom)
  1097. recalcBorderBottom = true;
  1098. }
  1099. }
  1100. }
  1101. void afTerrainPatch::checkBorderRight()
  1102. {
  1103. int i, y,yc, pow, xcMax;
  1104. if(forceBufferCreate || forceRetessellation || followsRight!=newFollowsRight)
  1105. {
  1106. for(i=0; i<numNewVertices; i++)
  1107. yMoveRight[i] = 0.0f;
  1108. for(i=0; i<numNewVertices; i++)
  1109. yMoveRight2[i] = 0.0f;
  1110. }
  1111. if(newFollowsRight && (!followsRight || forceBufferCreate || forceRetessellation || recalcBorderRight))
  1112. {
  1113. // copy shared border column
  1114. //
  1115. assert(selfTes==right->leftTes);
  1116. assert(rightTes==right->selfTes);
  1117. assert(right->indexMap);
  1118. pow = getPowerTwo(min(selfTes,rightTes));
  1119. for(y=pow; y<SOURCE_HEIGHT-1; y+=pow)
  1120. {
  1121. int idx = indexMap[SOURCE_WIDTH-1 + y * SOURCE_WIDTH],
  1122. idxR = right->indexMap[0 + y * SOURCE_WIDTH];
  1123. assert(idx!=0xffff);
  1124. assert(idxR!=0xffff);
  1125. verticesLow[idx].pos.y = right->verticesLow[idxR].pos.y;
  1126. vertices[idx].pos.y = right->vertices[idxR].pos.y;
  1127. yMoveRight[idx] = right->yMoveSelf[idxR];
  1128. yMoveSelf[idx] = 0.0f;
  1129. }
  1130. // correct border neighbors
  1131. //
  1132. if(realSelfTes<3)
  1133. {
  1134. pow = getPowerTwo(realSelfTes);
  1135. xcMax = (SOURCE_WIDTH-1-pow)/pow;
  1136. for(y=pow,yc=1; y<SOURCE_HEIGHT-1; y+=pow,yc++)
  1137. {
  1138. float yLT=0.0f,yRB=0.0f;
  1139. int idx, idxLT=0,idxRB=0;
  1140. idx = calculateDiagonalVertices(SOURCE_WIDTH-1-pow, y, xcMax, yc, pow, verticesLow, yLT,idxLT, yRB,idxRB);
  1141. assert(idx>=0 && idx!=0xffff);
  1142. verticesLow[idx].pos.y = (yLT + yRB) * 0.5f;
  1143. // our vertex is moved 50% by the right (-bottom) neighbor
  1144. // this garanties that this vertex is on the diagonal when currentError is 0.0f
  1145. yMoveRight2[idx] = (vertices[idxRB].pos.y - verticesLow[idxRB].pos.y) * 0.5f;
  1146. yMoveSelf[idx] = vertices[idx].pos.y - verticesLow[idx].pos.y;
  1147. }
  1148. }
  1149. // correct neighbors to lie on a diagonal
  1150. //
  1151. if(selfTes!=realSelfTes)
  1152. {
  1153. pow = getPowerTwo(selfTes);
  1154. xcMax = (SOURCE_WIDTH-1-pow)/pow;
  1155. for(y=pow,yc=1; y<SOURCE_HEIGHT-1; y+=pow,yc++)
  1156. {
  1157. float yLT=0.0f,yRB=0.0f;
  1158. int idx, idxLT=0,idxRB=0;
  1159. idx = calculateDiagonalVertices(SOURCE_WIDTH-1-pow, y, xcMax, yc, pow, verticesLow, yLT,idxLT, yRB,idxRB);
  1160. assert(idx>=0 && idx!=0xffff);
  1161. verticesLow[idx].pos.y = (yLT + yRB) * 0.5f;
  1162. vertices[idx].pos.y = (vertices[idxLT].pos.y + vertices[idxRB].pos.y) * 0.5f;
  1163. // the real new part: this vertex always STAYS on the diagonal
  1164. //
  1165. yMoveRight2[idx] = 0.0f;
  1166. yMoveRight[idx] = (vertices[idxRB].pos.y - verticesLow[idxRB].pos.y) * 0.5f;
  1167. yMoveSelf[idx] = (vertices[idxLT].pos.y - verticesLow[idxLT].pos.y) * 0.5f;
  1168. }
  1169. // necessary to recorrect the shared right-top border neighbor
  1170. //
  1171. if(followsTop)
  1172. recalcBorderTop = true;
  1173. }
  1174. }
  1175. }
  1176. void afTerrainPatch::checkBorderBottom()
  1177. {
  1178. int i, x,xc, pow;
  1179. if(forceBufferCreate || forceRetessellation || followsBottom!=newFollowsBottom)
  1180. {
  1181. for(i=0; i<numNewVertices; i++)
  1182. yMoveBottom[i] = 0.0f;
  1183. for(i=0; i<numNewVertices; i++)
  1184. yMoveBottom2[i] = 0.0f;
  1185. }
  1186. if(newFollowsBottom && (!followsBottom || forceBufferCreate || forceRetessellation || recalcBorderBottom))
  1187. {
  1188. // copy shared border column
  1189. //
  1190. assert(selfTes==bottom->topTes);
  1191. assert(bottomTes==bottom->selfTes);
  1192. assert(bottom->indexMap);
  1193. pow = getPowerTwo(min(selfTes,bottomTes));
  1194. for(x=pow; x<SOURCE_WIDTH-1; x+=pow)
  1195. {
  1196. int idx = indexMap[x + 0 * SOURCE_WIDTH],
  1197. idxB = bottom->indexMap[x + (SOURCE_WIDTH-1) * SOURCE_WIDTH];
  1198. assert(idx!=0xffff);
  1199. assert(idxB!=0xffff);
  1200. verticesLow[idx].pos.y = bottom->verticesLow[idxB].pos.y;
  1201. vertices[idx].pos.y = bottom->vertices[idxB].pos.y;
  1202. yMoveBottom[idx] = bottom->yMoveSelf[idxB];
  1203. yMoveSelf[idx] = 0.0f;
  1204. }
  1205. if(selfTes>=3)
  1206. return;
  1207. // correct border neighbors
  1208. //
  1209. pow = getPowerTwo(selfTes);
  1210. for(x=pow,xc=1; x<SOURCE_WIDTH-1; x+=pow,xc++)
  1211. {
  1212. float yLT=0.0f,yRB=0.0f;
  1213. int idx, idxLT=0,idxRB=0;
  1214. idx = calculateDiagonalVertices(x, pow, xc, 1, pow, verticesLow, yLT,idxLT, yRB,idxRB);
  1215. assert(idx>=0 && idx!=0xffff);
  1216. float moveRB = vertices[idxRB].pos.y - verticesLow[idxRB].pos.y;
  1217. verticesLow[idx].pos.y = (yLT + yRB) / 2.0f;
  1218. // our vertex is moved 50% by the right (-bottom) neighbor
  1219. // this garanties that this vertex is on the diagonal when currentError is 0.0f
  1220. yMoveBottom2[idx] = moveRB * 0.5f;
  1221. yMoveSelf[idx] = vertices[idx].pos.y - verticesLow[idx].pos.y;
  1222. }
  1223. // correct neighbors to lie on a diagonal
  1224. //
  1225. if(selfTes!=realSelfTes)
  1226. {
  1227. pow = getPowerTwo(selfTes);
  1228. for(x=pow,xc=1; x<SOURCE_WIDTH-1; x+=pow,xc++)
  1229. {
  1230. float yLT=0.0f,yRB=0.0f;
  1231. int idx, idxLT=0,idxRB=0;
  1232. idx = calculateDiagonalVertices(x, pow, xc, 1, pow, verticesLow, yLT,idxLT, yRB,idxRB);
  1233. assert(idx>=0 && idx!=0xffff);
  1234. verticesLow[idx].pos.y = (yLT + yRB) * 0.5f;
  1235. vertices[idx].pos.y = (vertices[idxLT].pos.y + vertices[idxRB].pos.y) * 0.5f;
  1236. // the real new part: this vertex always STAYS on the diagonal
  1237. //
  1238. yMoveBottom2[idx] = 0.0f;
  1239. yMoveBottom[idx] = (vertices[idxRB].pos.y - verticesLow[idxRB].pos.y) * 0.5f;
  1240. if(yMoveLeft[idx]==0.0f)
  1241. yMoveSelf[idx] = (vertices[idxLT].pos.y - verticesLow[idxLT].pos.y) * 0.5f;
  1242. else
  1243. yMoveSelf[idx] = 0.0f;
  1244. }
  1245. }
  1246. }
  1247. }
  1248. void afTerrainPatch::checkBorderTop()
  1249. {
  1250. int i, x,xc, pow, ycMax;
  1251. if(forceBufferCreate || forceRetessellation || followsTop!=newFollowsTop)
  1252. {
  1253. for(i=0; i<numNewVertices; i++)
  1254. yMoveTop[i] = 0.0f;
  1255. for(i=0; i<numNewVertices; i++)
  1256. yMoveTop2[i] = 0.0f;
  1257. }
  1258. if(newFollowsTop && (!followsTop || forceBufferCreate || forceRetessellation || recalcBorderTop))
  1259. {
  1260. // copy shared border column
  1261. //
  1262. assert(selfTes==top->bottomTes);
  1263. assert(topTes==top->selfTes);
  1264. assert(top->indexMap);
  1265. pow = getPowerTwo(min(selfTes,topTes));
  1266. for(x=pow; x<SOURCE_WIDTH-1; x+=pow)
  1267. {
  1268. int idx = indexMap[x + (SOURCE_HEIGHT-1) * SOURCE_WIDTH],
  1269. idxT = top->indexMap[x + 0 * SOURCE_WIDTH];
  1270. assert(idx!=0xffff);
  1271. assert(idxT!=0xffff);
  1272. verticesLow[idx].pos.y = top->verticesLow[idxT].pos.y;
  1273. vertices[idx].pos.y = top->vertices[idxT].pos.y;
  1274. yMoveTop[idx] = top->yMoveSelf[idxT];
  1275. yMoveSelf[idx] = 0.0f;
  1276. }
  1277. if(selfTes>=3)
  1278. return;
  1279. // correct border neighbors
  1280. //
  1281. pow = getPowerTwo(selfTes);
  1282. ycMax = (SOURCE_WIDTH-1-pow)/pow;
  1283. for(x=pow,xc=1; x<SOURCE_WIDTH-1; x+=pow,xc++)
  1284. {
  1285. float yLT=0.0f,yRB=0.0f;
  1286. int idx, idxLT=0,idxRB=0;
  1287. idx = calculateDiagonalVertices(x, SOURCE_HEIGHT-1-pow, xc, ycMax, pow, verticesLow, yLT,idxLT, yRB,idxRB);
  1288. assert(idx>=0 && idx!=0xffff);
  1289. float moveLT = vertices[idxLT].pos.y - verticesLow[idxLT].pos.y;
  1290. verticesLow[idx].pos.y = (yLT + yRB) / 2.0f;
  1291. // our vertex is moved 50% by the left (-top) neighbor
  1292. // this garanties that this vertex is on the diagonal when currentError is 0.0f
  1293. yMoveTop2[idx] = moveLT * 0.5f;
  1294. yMoveSelf[idx] = vertices[idx].pos.y - verticesLow[idx].pos.y;
  1295. }
  1296. // correct neighbors to lie on a diagonal
  1297. //
  1298. if(selfTes!=realSelfTes)
  1299. {
  1300. pow = getPowerTwo(selfTes);
  1301. ycMax = (SOURCE_WIDTH-1-pow)/pow;
  1302. for(x=pow,xc=1; x<SOURCE_WIDTH-1; x+=pow,xc++)
  1303. {
  1304. float yLT=0.0f,yRB=0.0f;
  1305. int idx, idxLT=0,idxRB=0;
  1306. idx = calculateDiagonalVertices(x, SOURCE_HEIGHT-1-pow, xc, ycMax, pow, verticesLow, yLT,idxLT, yRB,idxRB);
  1307. assert(idx>=0 && idx!=0xffff);
  1308. verticesLow[idx].pos.y = (yLT + yRB) * 0.5f;
  1309. vertices[idx].pos.y = (vertices[idxLT].pos.y + vertices[idxRB].pos.y) * 0.5f;
  1310. // the real new part: this vertex always STAYS on the diagonal
  1311. //
  1312. yMoveTop2[idx] = 0.0f;
  1313. yMoveTop[idx] = (vertices[idxLT].pos.y - verticesLow[idxLT].pos.y) * 0.5f;
  1314. if(yMoveRight[idx]==0.0f)
  1315. yMoveSelf[idx] = (vertices[idxRB].pos.y - verticesLow[idxRB].pos.y) * 0.5f;
  1316. else
  1317. yMoveSelf[idx] = 0.0f;
  1318. }
  1319. }
  1320. }
  1321. }
  1322. bool afTerrainPatch::fillBuffers()
  1323. {
  1324. if(master->getMergePatches() && selfTes==4)
  1325. {
  1326. numIndices = numNewIndices;
  1327. numVertices = numNewVertices;
  1328. forceBufferCreate = false;
  1329. return true;
  1330. }
  1331. if(!forceBufferCreate && !forceRetessellation &&
  1332. followsLeft==newFollowsLeft && !recalcBorderLeft &&
  1333. followsRight==newFollowsRight && !recalcBorderRight &&
  1334. followsBottom==newFollowsBottom && !recalcBorderBottom &&
  1335. followsTop==newFollowsTop && !recalcBorderTop)
  1336. return true;
  1337. if(!checkBuffers())
  1338. return false;
  1339. if(numVertices==0 || numIndices==0) // nothing to do ???
  1340. return true;
  1341. int i;
  1342. //if(forceBufferCreate)
  1343. master->addBufferCreateCount();
  1344. // fill vertex buffer
  1345. //
  1346. PATCHVERTEX_MORPH_HW* pVertices = NULL;
  1347. vBuffer->Lock(0, 0, (void**)&pVertices, D3DLOCK_NOSYSLOCK|D3DLOCK_DISCARD);
  1348. for(i=0; i<numVertices; i++)
  1349. {
  1350. pVertices[i].posX = vertices[i].pos.x;
  1351. pVertices[i].posZ = vertices[i].pos.z;
  1352. pVertices[i].texX = vertices[i].tex.x;
  1353. pVertices[i].texY = vertices[i].tex.y;
  1354. pVertices[i].posY = verticesLow[i].pos.y;
  1355. pVertices[i].yMoveSelf = yMoveSelf[i];
  1356. pVertices[i].v0 = 0.0f,
  1357. pVertices[i].v1 = 1.0f,
  1358. pVertices[i].yMoveLeft = yMoveLeft[i];
  1359. pVertices[i].yMoveLeft2 = yMoveLeft2[i];
  1360. pVertices[i].yMoveRight = yMoveRight[i];
  1361. pVertices[i].yMoveRight2 = yMoveRight2[i];
  1362. pVertices[i].yMoveBottom = yMoveBottom[i];
  1363. pVertices[i].yMoveBottom2 = yMoveBottom2[i];
  1364. pVertices[i].yMoveTop = yMoveTop[i];
  1365. pVertices[i].yMoveTop2 = yMoveTop2[i];
  1366. }
  1367. vBuffer->Unlock();
  1368. // fill index buffer
  1369. //
  1370. WORD* pIndices = NULL;
  1371. iBuffer->Lock(0, 0, (void**)&pIndices, D3DLOCK_NOSYSLOCK|D3DLOCK_DISCARD);
  1372. for(i=0; i<numIndices; i++)
  1373. {
  1374. pIndices[i] = indices[i];
  1375. //pgLog::trace("%d: %dn", i, indices[i]);
  1376. }
  1377. iBuffer->Unlock();
  1378. //pgLog::trace("patch buffers (%d|%d) filledn", gridX,gridY);
  1379. return true;
  1380. }
  1381. bool afTerrainPatch::checkBuffers()
  1382. {
  1383. // create new buffers if the size changed
  1384. //
  1385. if(numIndices<numNewIndices || forceBufferCreate)
  1386. {
  1387. numIndices = numNewIndices;
  1388. SAFE_RELEASE(iBuffer)
  1389. if(numIndices>0)
  1390. if(FAILED(pd3dDevice->CreateIndexBuffer(numIndices * sizeof(WORD), D3DUSAGE_WRITEONLY|D3DUSAGE_DYNAMIC,
  1391. D3DFMT_INDEX16, D3DPOOL_DEFAULT, &iBuffer,NULL)))
  1392. {
  1393. afLog::error("creating index buffer for terrainpatch failed");
  1394. return false;
  1395. }
  1396. //pgLog::trace("index-buffer (%d|%d) recreatedn", gridX,gridY);
  1397. }
  1398. if(numVertices<numNewVertices  || forceBufferCreate)
  1399. {
  1400. numVertices = numNewVertices;
  1401. SAFE_RELEASE(vBuffer)
  1402. if(numVertices>0)
  1403. if(FAILED(pd3dDevice->CreateVertexBuffer(numVertices * sizeof(PATCHVERTEX_MORPH_HW), D3DUSAGE_WRITEONLY|D3DUSAGE_DYNAMIC,
  1404.  0, D3DPOOL_DEFAULT, &vBuffer,NULL)))
  1405. {
  1406. afLog::error("creating base vertex buffer for terrainpatch failed");
  1407. SAFE_RELEASE(iBuffer);
  1408. return false;
  1409. }
  1410. }
  1411. forceBufferCreate = false;
  1412. return true;
  1413. }