PageRenderTime 55ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/CS/migrated/branches/R0_16/libs/csterr/struct/ddgtmesh.cpp

#
C++ | 601 lines | 416 code | 46 blank | 139 comment | 87 complexity | f853e749b7ecd195304822fb9b2e2a54 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, LGPL-2.0
  1. /*
  2. Copyright (C) 1997, 1998, 1999 by Alex Pfaffe
  3. (Digital Dawn Graphics Inc)
  4. This library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public
  6. License as published by the Free Software Foundation; either
  7. version 2 of the License, or (at your option) any later version.
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Library General Public License for more details.
  12. You should have received a copy of the GNU Library General Public
  13. License along with this library; if not, write to the Free
  14. Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. */
  16. //
  17. #include "struct/ddgtmesh.h"
  18. #include "struct/ddgbtree.h"
  19. // ----------------------------------------------------------------------
  20. //const unsigned int TBinMesh_size = 64; // 64 seems to be a good size.
  21. ddgTBinMesh::ddgTBinMesh( ddgHeightMap * h )
  22. {
  23. _heightMap = h; // Temporary
  24. _scale = h->scale();
  25. _base = h->base();
  26. _bintreeMax = 2*(h->cols()-1)/(ddgTBinMesh_size) * (h->rows()-1)/(ddgTBinMesh_size);
  27. typedef ddgTBinTree *ddgTBinTreeP;
  28. _bintree = new ddgTBinTreeP[_bintreeMax];
  29. ddgAsserts(_bintree,"Failed to Allocate memory");
  30. ddgMemorySet(ddgTBinTreeP,_bintreeMax);
  31. _minDetail = 4000;
  32. _maxDetail = 4200;
  33. _absMaxDetail = 8000;
  34. _absMaxHeight = -0xFFFF;
  35. _absMinHeight = 0xFFFF;
  36. _absDiffHeight = 0;
  37. // Note Z axis is negative into the screen (Right Handed coord sys).
  38. farClip(200);
  39. _merge = true;
  40. _splitRun = true; // 1st run should be a split only run.
  41. _nearClip = 1;
  42. // Allocate memory for active triangles.
  43. _tcache.init(((_bintreeMax + _absMaxDetail) * 11)/10); // (# of tiles + #of triangles/frame ) + 10 %
  44. // Create the default entry and the scratch entry.
  45. ddgTNode *tn = _tcache.get(0);
  46. // Initialize the default entry.
  47. tn->tindex(0);
  48. tn->priority(0);
  49. tn->vis(0);
  50. // Allocate scratch entry.
  51. _tcache.allocNode();
  52. _triVis = 0;
  53. _maxLevel = (unsigned int) (log(ddgTBinMesh_size)/log(2.0) * 2.01); // Could be constant.
  54. _triNo = (unsigned int)pow(2,(_maxLevel)); // Inside points can be shared.
  55. _leafTriNo = _triNo / 2;
  56. stri = new ddgMSTri[_triNo+2];
  57. ddgAsserts(stri,"Failed to Allocate memory");
  58. ddgMemorySet(ddgMSTri,_triNo+2);
  59. _indexLUT = new ddgTriIndex[(ddgTBinMesh_size+1)*(ddgTBinMesh_size+1)];
  60. ddgAsserts(_indexLUT,"Failed to Allocate memory");
  61. ddgMemorySet(ddgTriIndex,(ddgTBinMesh_size+1)*(ddgTBinMesh_size+1));
  62. // Queues to hold the visible, clipped and sorted visible triangles.
  63. // Estimate how many entries we can possibly have in the split and merge queues.
  64. _qscache.init(_absMaxDetail, ddgPriorityResolution);
  65. _qmcache.init(_absMaxDetail, ddgPriorityResolution,true);
  66. unsigned int i;
  67. for (i = 0; i < _bintreeMax; i++ )
  68. _bintree[i] = NULL;
  69. i = 0;
  70. while (i < (ddgTBinMesh_size+1)*(ddgTBinMesh_size+1))
  71. {
  72. _indexLUT[i] = 9999;
  73. i++;
  74. }
  75. // Top level triangles.
  76. stri[0].row = 0;
  77. stri[0].col = 0;
  78. // Corner entries.
  79. stri[_triNo].row = ddgTBinMesh_size;
  80. stri[_triNo].col = 0;
  81. stri[_triNo+1].row = 0;
  82. stri[_triNo+1].col = ddgTBinMesh_size;
  83. _indexLUT[0] = 0;
  84. _indexLUT[ddgTBinMesh_size] = _triNo+1;
  85. _indexLUT[(ddgTBinMesh_size+1)*(ddgTBinMesh_size+1)-ddgTBinMesh_size-1] = _triNo;
  86. _indexLUT[(ddgTBinMesh_size+1)*(ddgTBinMesh_size+1)-1] = 0;
  87. // Initialize the other vertices.
  88. initVertex(1,0,_triNo,_triNo+1,1);
  89. initNeighbours();
  90. /// Total number of triangles rendered by this camera.
  91. _triCount = 0;
  92. /// Total number of priorities calculated by this camera.
  93. _priCount = 0;
  94. /// Total number of queue insertions by this camera.
  95. _insCount = 0;
  96. /// Total number of queue removals by this camera.
  97. _remCount = 0;
  98. /// Total number of queue updates by this camera.
  99. _movCount = 0;
  100. _visCount = 0;
  101. }
  102. //unsigned short *_normalidx = 0;
  103. ddgTBinMesh::~ddgTBinMesh(void)
  104. {
  105. delete [] stri;
  106. delete _bintree;
  107. delete[] _indexLUT;
  108. }
  109. /// Function to add a bintree.
  110. void ddgTBinMesh::addBinTree( ddgTBinTree *bt )
  111. {
  112. unsigned int i = 0;
  113. while (i < _bintreeMax && _bintree[i] != NULL) i++;
  114. if (i < _bintreeMax)
  115. {
  116. _bintree[i] = bt;
  117. }
  118. }
  119. /// Function to remove a bintree.
  120. void ddgTBinMesh::removeBinTree( ddgTBinTree *bt )
  121. {
  122. unsigned int i = 0;
  123. while (i < _bintreeMax && _bintree[i] != bt) i++;
  124. if (i < _bintreeMax)
  125. {
  126. _bintree[i] = NULL;
  127. }
  128. }
  129. /** Initialize the bintree structure including
  130. * the wedges and other mesh values.
  131. */
  132. bool ddgTBinMesh::init( ddgContext *ctx )
  133. {
  134. ddgTBinTree *bintree1 = NULL,
  135. *bintree2 = NULL;
  136. // Created the enough bintrees to cover the terrain.
  137. unsigned int i, j;
  138. _nc = (_heightMap->cols()-1)/ddgTBinMesh_size;
  139. _nr = (_heightMap->rows()-1)/ddgTBinMesh_size;
  140. ddgConsole::s("Creating "); ddgConsole::i(_nc);ddgConsole::s(" x ");ddgConsole::i(_nr);ddgConsole::s(" Tiles");
  141. ddgConsole::end();
  142. ddgTBinTree::initContext(ctx,this);
  143. ddgTreeIndex index = 0;
  144. for (i = 0; i < _nr; i++)
  145. {
  146. for (j = 0; j < _nc; j++)
  147. {
  148. bintree1 = new ddgTBinTree(index,i*ddgTBinMesh_size,j*ddgTBinMesh_size);
  149. ddgMemorySet(ddgTBinTree,1);
  150. addBinTree(bintree1);
  151. index++;
  152. bintree2 = new ddgTBinTree(index,(i+1)*ddgTBinMesh_size,(j+1)*ddgTBinMesh_size,true);
  153. ddgMemorySet(ddgTBinTree,1);
  154. addBinTree(bintree2);
  155. index++;
  156. }
  157. }
  158. // Define relationship between meshes.
  159. for (i = 0; i < _nr; i++)
  160. {
  161. for (j = 0; j < _nc; j++)
  162. {
  163. _bintree[2*(i*_nc+j)]->pNeighbourDiag( _bintree[2*(i*_nc+j)+1]);
  164. _bintree[2*(i*_nc+j)]->pNeighbourLeft( (j==0)? 0: _bintree[2*(i*_nc+j-1)+1]);
  165. _bintree[2*(i*_nc+j)]->pNeighbourTop( (i==0)? 0: _bintree[2*((i-1)*_nc+j)+1]);
  166. //
  167. _bintree[2*(i*_nc+j)+1]->pNeighbourDiag( _bintree[2*(i*_nc+j)]);
  168. _bintree[2*(i*_nc+j)+1]->pNeighbourLeft( (j+1==_nc)? 0: _bintree[2*(i*_nc+j+1)]);
  169. _bintree[2*(i*_nc+j)+1]->pNeighbourTop( (i+1==_nr)? 0: _bintree[2*((i+1)*_nc+j)]);
  170. }
  171. }
  172. // We call this function twice.
  173. for (i = 0; i < _bintreeMax; i++)
  174. {
  175. if (_bintree[i])
  176. {
  177. _bintree[i]->init();
  178. if ( _bintree[i]->rawMaxVal(0) > _absMaxHeight)
  179. _absMaxHeight = _bintree[i]->rawMaxVal(0);
  180. if ( _bintree[i]->rawMinVal(0) < _absMinHeight)
  181. _absMinHeight = _bintree[i]->rawMinVal(0);
  182. }
  183. ddgConsole::progress( "Initializing blocks", i,_bintreeMax-1);
  184. }
  185. // The difference between the highest point and the lowest point.
  186. _absDiffHeight = _absMaxHeight - _absMinHeight;
  187. // Call it again to update the DiffHeight etc info.
  188. ddgTBinTree::initContext(ctx,this);
  189. // Let go of the height map we do not need it anymore.
  190. _heightMap = 0;
  191. ddgConsole::end() ;
  192. return ddgSuccess;
  193. }
  194. /**
  195. * Initialize the vertex and row/col data of the STri.
  196. * Passed in are the triangles which carry the points
  197. * that describe the current triangle.
  198. * va is immediate parent.
  199. * v1 and v0 are the left and right vertices of va.
  200. */
  201. void ddgTBinMesh::initVertex( unsigned int level,
  202. ddgTriIndex va, // Top
  203. ddgTriIndex v0, // Left
  204. ddgTriIndex v1, // Right
  205. ddgTriIndex vc) // Centre
  206. {
  207. // Initialize row and col for this triangle.
  208. stri[vc].row = (stri[v0].row + stri[v1].row) / 2;
  209. stri[vc].col = (stri[v0].col + stri[v1].col) / 2;
  210. // See if we are not at the bottom.
  211. if (level < _maxLevel)
  212. {
  213. initVertex(level+1,vc,va,v0,ddgTBinTree::left(vc)),
  214. initVertex(level+1,vc,v1,va,ddgTBinTree::right(vc));
  215. }
  216. stri[vc].v0 = v0;
  217. stri[vc].v1 = v1;
  218. unsigned int r = stri[vc].row, c = stri[vc].col;
  219. unsigned int rp = ddgTBinMesh_size - c, cp = ddgTBinMesh_size - r;
  220. _indexLUT[r*(ddgTBinMesh_size+1)+c] = vc;
  221. // Fill in the mirror side.
  222. if (r + c < ddgTBinMesh_size)
  223. _indexLUT[rp*(ddgTBinMesh_size+1)+cp] = vc;
  224. }
  225. // Constant used for identifying neighbour.
  226. const unsigned int ddgNINIT = 0xFFFFFFFF;
  227. // Precompute the neighbour field, this is used for merge diamonds.
  228. // This function can now initialize in constant time, there is an algoritm!
  229. void ddgTBinMesh::initNeighbours( void )
  230. {
  231. // Find the neighbours of all triangles.
  232. unsigned int t, b, k = 2, lk = 1, l = 0, klk, kk, kt;
  233. // initialize all neighbours to ddgNINIT.
  234. for (t = 0; t < _triNo+2; t++)
  235. stri[t].neighbour = ddgNINIT;
  236. stri[1].neighbour = 1;
  237. stri[0].neighbour = 0;
  238. stri[_triNo].neighbour = _triNo;
  239. stri[_triNo+1].neighbour = _triNo+1;
  240. // Find the neighbour of each tri.
  241. while ((++l) < _maxLevel)
  242. {
  243. b = lk;
  244. klk = k+lk;
  245. kk = k+k;
  246. for (t = 0; t < lk; t++) // Only do half because of symmetry.
  247. {
  248. kt = k+t;
  249. if (stri[kt].neighbour != ddgNINIT)
  250. {
  251. continue;
  252. }
  253. else if (l > 2 && l % 2 == 1) // Odd levels are a double copy of prev even level.
  254. {
  255. stri[kt].neighbour = stri[lk+t].neighbour + b;
  256. stri[klk+t].neighbour = stri[lk+t].neighbour + lk + b;
  257. }
  258. // Check Edge cases
  259. else if ((b = edge(kt)) != 0)
  260. {
  261. if (b==3) // Diagonal.
  262. {
  263. stri[kt].neighbour = kk-t-1;
  264. stri[kk-t-1].neighbour = kt;
  265. }
  266. else
  267. {
  268. stri[kt].neighbour = klk-t-1;
  269. stri[kk-t-1].neighbour = klk+t;
  270. }
  271. }
  272. // Normal case
  273. else
  274. {
  275. ddgAssert(stri[kt].neighbour == ddgNINIT);
  276. // If the same row in the previous level was known, inherit.
  277. if (lk && t < lk && !edge(lk + t))
  278. {
  279. stri[kt].neighbour = stri[lk + t].neighbour + lk;
  280. stri[stri[kt].neighbour].neighbour = kt;
  281. stri[klk+t].neighbour = stri[lk + t].neighbour + k;
  282. stri[lk+stri[kt].neighbour].neighbour = klk + t;
  283. }
  284. else // It is a new neighbour.
  285. {
  286. b = k - 1 - t;
  287. ddgAssert ( stri[kt].col == stri[k+b].col
  288. && stri[kt].row == stri[k+b].row);
  289. stri[kt].neighbour = k+b;
  290. stri[k+b].neighbour = kt;
  291. }
  292. }
  293. }
  294. lk = k;
  295. k = kk; // 2^n
  296. ddgConsole::progress("Computing neighbours",k,_triNo);
  297. }
  298. ddgConsole::progress("Computing neighbours",1,1);
  299. ddgConsole::end();
  300. }
  301. bool ddgTBinMesh::calculate( ddgContext *ctx )
  302. {
  303. static ddgVector3 lastForward(0,0,0);
  304. static ddgVector3 lastPosition(0,0,0);
  305. float deltaMoveDistance = 0.0;
  306. float deltaViewAngle = 1.0;
  307. _splitRun = false;
  308. // Initialize world to camera space matrix and viewing frustrum.
  309. ddgTBinTree::updateContext(ctx,this);
  310. // See if we moved.
  311. if (lastPosition != *(ctx->control()->position()))
  312. {
  313. lastPosition -= ctx->control()->position();
  314. deltaMoveDistance = lastPosition.size();
  315. lastPosition = ctx->control()->position();
  316. }
  317. // See if we changed our orientation.
  318. if (lastForward != *(ctx->forward()))
  319. {
  320. deltaViewAngle = lastForward.dot(ctx->forward());
  321. lastForward.set(ctx->forward());
  322. // If the view angle change was greater than ~70 degrees, do a split.
  323. if (deltaViewAngle < 0.1)
  324. _splitRun = true;
  325. }
  326. // Check if we didn't go anywhere and we have enough detail in the view.
  327. if (deltaViewAngle == 1.0 && deltaMoveDistance == 0.0
  328. && _triVis >= _minDetail && _triVis <= _maxDetail)
  329. return false;
  330. // Calculate visibility info for all triangles currently in the mesh
  331. // at the current camera position.
  332. // Clear queue.
  333. unsigned int i = 0;
  334. // If the merge queue is not active we are only doing splits.
  335. if (!merge())
  336. _splitRun = true;
  337. // Reset state in case of split only or if 1st run
  338. // with merge enabled.
  339. if (_splitRun)
  340. {
  341. // If the merge queue was enabled amd has content, reset it.
  342. if (merge() && qmcache()->size())
  343. {
  344. qmcache()->reset();
  345. }
  346. qscache()->reset();
  347. tcache()->reset();
  348. _triVis = 0;
  349. i = 0;
  350. while (i < _bintreeMax)
  351. {
  352. if (_bintree[i])
  353. {
  354. // Clear any cache entries we were holding onto.
  355. ddgCacheIndex ci = _bintree[i]->chain();
  356. while (ci)
  357. {
  358. ddgTNode *tn = (ddgTNode*) tcache()->get(ci);
  359. _bintree[i]->tcacheId(tn->tindex(), 0);
  360. ci = tn->next();
  361. }
  362. // Empty the active triangles chain for the bintree.
  363. _bintree[i]->freeChain();
  364. }
  365. i++;
  366. }
  367. i = 0;
  368. while (i < _bintreeMax)
  369. {
  370. if (_bintree[i])
  371. {
  372. _bintree[i]->insertSQ(1,ddgMAXPRI,0,ddgUNDEF);
  373. }
  374. i++;
  375. }
  376. }
  377. // Update the current state.
  378. else
  379. {
  380. i = 0;
  381. while (i < _bintreeMax)
  382. {
  383. if (_bintree[i])
  384. {
  385. _bintree[i]->updateSplit(1,ddgUNDEF);
  386. }
  387. i++;
  388. }
  389. /*
  390. unsigned int r, c;
  391. // Include a 2 block border.
  392. float d = _farClip+2*ddgTBinMesh_size;
  393. // Only update those triangles which could possibly be in visible range.
  394. // See if the triangle is too far from the camera. Ingore height component.
  395. ddgVector2 pos( ctx->control()->position()->v[0], ctx->control()->position()->v[2]);
  396. ddgVector2 min = pos - ddgVector2(d,d);
  397. ddgVector2 max = pos + ddgVector2(d,d);
  398. max /= ddgTBinMesh_size;
  399. min /= ddgTBinMesh_size;
  400. if (min[0] < 0) min[0] = 0;
  401. if (min[1] < 0) min[1] = 0;
  402. if (max[0] > _nc) max[0] = _nc;
  403. if (max[1] > _nr) max[1] = _nr;
  404. unsigned int rmin = (unsigned int)min[1];
  405. unsigned int rmax = (unsigned int)max[1];
  406. unsigned int cmin = (unsigned int)min[0];
  407. unsigned int cmax = (unsigned int)max[0];
  408. // Update the potentially visible square.
  409. for (r = rmin; r < rmax; r++)
  410. for (c = cmin; c < cmax; c++)
  411. {
  412. i = 2*(_nc * r + c);
  413. // Recursively update the state of the mesh
  414. if ( _bintree[i])
  415. {
  416. _bintree[i]->updateSplit(1,ddgUNDEF);
  417. }
  418. if ( _bintree[i+1])
  419. {
  420. _bintree[i+1]->updateSplit(1,ddgUNDEF);
  421. }
  422. }
  423. */
  424. // Validate the merge queue.
  425. ddgCacheIndex ci = qmcache()->head();
  426. while (ci)
  427. {
  428. // Note cannot iterate over this and update directly since
  429. // updateMerge modifies the order of items in the queue
  430. ddgQNode *qn = qmcache()->get(ci);
  431. ci = qmcache()->next(ci);
  432. getBinTree(qn->tree())->updateMerge(qn->tindex(),ddgMAXPRI);
  433. ddgAssert(i < 5000);
  434. }
  435. }
  436. // Get the optimal number of visible triangles by balancing the queue.
  437. unsigned int priDiff = _minDetail/30; // Allowable difference in priorities between queues.
  438. unsigned int minDiff = _minDetail-_minDetail/100; // Min # triangles to start merging.
  439. bool done = false;
  440. unsigned int count = 0;
  441. ddgQNode *qn;
  442. ddgTBinTree *sbt = 0, *mbt;
  443. ddgTriIndex si = 0, mi;
  444. ddgPriority sp, mp;
  445. ddgCacheIndex csi, cmi;
  446. while (!done)
  447. {
  448. count++;
  449. if (count > _minDetail)
  450. {
  451. ddgAsserts(0,"Too many iterations to stabilization");
  452. done = true;
  453. break;
  454. }
  455. csi = qscache()->head();
  456. sp = 0;
  457. if (csi)
  458. {
  459. qn = qscache()->get(csi);
  460. sbt = getBinTree(qn->tree());
  461. si = qn->tindex();
  462. // Split priority is stored in the tcache.
  463. sp = sbt->priority(si);
  464. }
  465. if (merge())
  466. {
  467. cmi = qmcache()->head();
  468. if (cmi)
  469. {
  470. qn = qmcache()->get(cmi);
  471. mbt = getBinTree(qn->tree());
  472. mi = qn->tindex();
  473. // Note merge priority is stored in the queue itself.
  474. mp = qmcache()->convert(qn->bucket());
  475. ddgAssert(sp == 0 || sp == qscache()->convert(qscache()->get(csi)->bucket()));
  476. if (( _triVis > _maxDetail) // We have too many triangles.
  477. || (mp == 0) // We have useless merge diamonds, merge these 1st.
  478. // We are safely beyond the minimum # of triangles, and
  479. // there is significant difference between the
  480. // priorities of the split and merge queues.
  481. ||(_triVis > minDiff && (sp > mp + priDiff)) )
  482. {
  483. ddgAsserts(mi > 0,"Its a root node");
  484. mbt->forceMerge(mi);
  485. continue;
  486. }
  487. }
  488. }
  489. if (csi && _triVis < _minDetail )
  490. {
  491. ddgAsserts( sbt->visible(si), "Non visible triangle in the split queue!")
  492. sbt->forceSplit(si);
  493. continue;
  494. }
  495. // Nothing we can do, we probably ran out of triangles.
  496. done = true;
  497. }
  498. _balCount = count;
  499. // Track the number of triangles produced by this calculation.
  500. _triCount += _triVis;
  501. return true;
  502. }
  503. bool ddgTBinMesh::mapPosToTree(float *x, float *z, ddgTBinTree **bt, unsigned int *r, unsigned int *c)
  504. {
  505. // Check that we are within limit.
  506. if (*x < 0 || *x > _nr * ddgTBinMesh_size
  507. || *z < 0 || *z > _nc * ddgTBinMesh_size)
  508. {
  509. *bt = NULL;
  510. return ddgFailure;
  511. }
  512. // Find the global(mesh) column and row of this coordinate.
  513. unsigned int gr = (unsigned int)(*x/ddgTBinMesh_size);
  514. unsigned int gc = (unsigned int)(*z/ddgTBinMesh_size);
  515. // Find the offset in the tree and row and column within the tree.
  516. *x = *x - gr * ddgTBinMesh_size;
  517. *z = *z - gc * ddgTBinMesh_size;
  518. // Do we fall in to the tree across the diagonal?
  519. bool mirror = (*x+*z < ddgTBinMesh_size)?false:true;
  520. // If so calculate the row and column w.r.t. that tree.
  521. if (mirror)
  522. {
  523. *x = ddgTBinMesh_size - *x;
  524. *z = ddgTBinMesh_size - *z;
  525. }
  526. *r = (unsigned int)*x;
  527. *c = (unsigned int)*z;
  528. // Calculate the distance from the triangle origin to the coord.
  529. *x = *x - *r;
  530. *z = *z - *c;
  531. // Calculate the bin tree.
  532. *bt = _bintree[(gr * _nc + gc)*2+(mirror?1:0)];
  533. if (*bt)
  534. return ddgSuccess;
  535. else
  536. return ddgFailure;
  537. }
  538. float ddgTBinMesh::height(float x, float z)
  539. {
  540. // Find the binTree which owns this coordinate.
  541. ddgTBinTree *bt = 0;
  542. unsigned int r, c;
  543. if (mapPosToTree(&x,&z,&bt, &r, &c) == ddgSuccess)
  544. {
  545. ddgAssert(bt);
  546. // Find mesh height at this location.
  547. return bt->treeHeight(r,c,x,z);
  548. }
  549. else
  550. return 0.0;
  551. }