Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

935 lines
29 KiB

  1. //========= Copyright � 1996-2008, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "optimize_subd.h"
  8. #define PI 3.14159265
  9. #define VTXIDX(vID) m_vtxList[vID].origMeshVertID
  10. #define VTXPOS(vID) *m_vtxData->Position( m_vtxList[vID].origMeshVertID )
  11. #define VTXNOR(vID) *m_vtxData->Normal( m_vtxList[vID].origMeshVertID )
  12. static Vector project_and_normalize( Vector v, Vector n )
  13. {
  14. v = v - DotProduct(v, n)*n;
  15. VectorNormalize(v);
  16. return v;
  17. }
  18. static int MOD4[8] = {0,1,2,3,0,1,2,3};
  19. namespace OptimizedModel
  20. {
  21. class NeighborCornerBitfield
  22. {
  23. public:
  24. unsigned short *bitfield;
  25. NeighborCornerBitfield(unsigned short *field): index(0), bitfield(field) { *bitfield = 0; }
  26. void pushBit( bool bit )
  27. {
  28. *bitfield |= bit<<index; index++;
  29. }
  30. void popBit()
  31. {
  32. index--; *bitfield &= ~(1<<index);
  33. }
  34. bool getBitAt( unsigned short i )
  35. {
  36. return ((*bitfield & (1<<i))>>i) == 1;
  37. }
  38. void insertBitAt( unsigned short i, bool bit )
  39. {
  40. unsigned short preMask = (1<<i)-1;
  41. *bitfield = (*bitfield & preMask) + ((*bitfield & (~preMask))<<1) + (bit<<i);
  42. index++;
  43. }
  44. void removeBitAt( unsigned short i )
  45. {
  46. unsigned short preMask = (1<<i)-1;
  47. unsigned short postMask = ~((1<<(i+1))-1);
  48. *bitfield = ((*bitfield & postMask)>>1) + (*bitfield & preMask);
  49. index--;
  50. }
  51. void clearBits()
  52. {
  53. *bitfield = 0;
  54. }
  55. private:
  56. unsigned short index;
  57. };
  58. COptimizeSubDBuilder::COptimizeSubDBuilder(SubD_FaceList_t& subDFaceList, const SubD_VertexList_t& vertexList, const SubD_VertexData_t &vertexData, bool bIsTagged, bool bMendVertices)
  59. : m_faceList(subDFaceList), m_vtxList(vertexList), m_vtxData(vertexData)
  60. {
  61. m_numPatches = (int) subDFaceList.Count();
  62. ProcessPatches(bIsTagged,bMendVertices);
  63. }
  64. void dumpPatch(SubD_Face_t *patch)
  65. {
  66. Msg( "Patch: %d\n", patch->patchID );
  67. Msg( " vtxIDs: %d %d %d %d\n", patch->vtxIDs[0], patch->vtxIDs[1], patch->vtxIDs[2], patch->vtxIDs[3] );
  68. Msg( " valences: %d %d %d %d\n", patch->valences[0], patch->valences[1], patch->valences[2], patch->valences[3] );
  69. Msg( " vtx1RingSize: %d %d %d %d\n", patch->vtx1RingSize[0], patch->vtx1RingSize[1], patch->vtx1RingSize[2], patch->vtx1RingSize[3] );
  70. Msg( " vtx1RingCenterQuadOffset: %d %d %d %d\n", patch->vtx1RingCenterQuadOffset[0], patch->vtx1RingCenterQuadOffset[1], patch->vtx1RingCenterQuadOffset[2], patch->vtx1RingCenterQuadOffset[3] );
  71. Msg( " bndVtx: %d %d %d %d\n", patch->bndVtx[0], patch->bndVtx[1], patch->bndVtx[2], patch->bndVtx[3] );
  72. Msg( " cornerVtx: %d %d %d %d\n", patch->cornerVtx[0], patch->cornerVtx[1], patch->cornerVtx[2], patch->cornerVtx[3] );
  73. Msg( " BndEdge: %d %d %d %d\n", patch->bndEdge[0], patch->bndEdge[1], patch->bndEdge[2], patch->bndEdge[3] );
  74. Msg( " halfEdges.twin: %d/%d %d/%d %d/%d %d/%d\n",
  75. patch->halfEdges[0].twin ? patch->halfEdges[0].twin->patch->patchID : -1, patch->halfEdges[0].twin ? patch->halfEdges[0].twin->localID: -1,
  76. patch->halfEdges[1].twin ? patch->halfEdges[1].twin->patch->patchID : -1, patch->halfEdges[1].twin ? patch->halfEdges[1].twin->localID: -1,
  77. patch->halfEdges[2].twin ? patch->halfEdges[2].twin->patch->patchID : -1, patch->halfEdges[2].twin ? patch->halfEdges[2].twin->localID: -1,
  78. patch->halfEdges[3].twin ? patch->halfEdges[3].twin->patch->patchID : -1, patch->halfEdges[3].twin ? patch->halfEdges[3].twin->localID: -1 );
  79. Msg( " halfEdges.sectorStart: %d/%d %d/%d %d/%d %d/%d\n",
  80. patch->halfEdges[0].sectorStart ? patch->halfEdges[0].sectorStart->patch->patchID : -1, patch->halfEdges[0].sectorStart ? patch->halfEdges[0].sectorStart->localID: -1,
  81. patch->halfEdges[1].sectorStart ? patch->halfEdges[1].sectorStart->patch->patchID : -1, patch->halfEdges[1].sectorStart ? patch->halfEdges[1].sectorStart->localID: -1,
  82. patch->halfEdges[2].sectorStart ? patch->halfEdges[2].sectorStart->patch->patchID : -1, patch->halfEdges[2].sectorStart ? patch->halfEdges[2].sectorStart->localID: -1,
  83. patch->halfEdges[3].sectorStart ? patch->halfEdges[3].sectorStart->patch->patchID : -1, patch->halfEdges[3].sectorStart ? patch->halfEdges[3].sectorStart->localID: -1 );
  84. Msg( " nbCornerVtx: %x %x %x %x\n", patch->nbCornerVtx[0], patch->nbCornerVtx[1], patch->nbCornerVtx[2], patch->nbCornerVtx[3] );
  85. Msg( " loopGapAngle: %d %d %d %d\n", patch->loopGapAngle[0], patch->loopGapAngle[1], patch->loopGapAngle[2], patch->loopGapAngle[3] );
  86. }
  87. void dumpPatches( SubD_FaceList_t &quads )
  88. {
  89. size_t nQuads = quads.Count();
  90. for (size_t k=0; k<nQuads; k++)
  91. {
  92. dumpPatch(&quads[k]);
  93. }
  94. }
  95. void COptimizeSubDBuilder::ProcessPatches( bool bIsTagged, bool bMendVertices )
  96. {
  97. // Init attributes
  98. for ( int i=0; i<m_numPatches; ++i )
  99. {
  100. SubD_Face_t *pPatch = &m_faceList[i];
  101. for (int k=0; k<4; ++k)
  102. {
  103. pPatch->patchID = i;
  104. if ( !bIsTagged )
  105. {
  106. pPatch->bndVtx[k] = false;
  107. pPatch->bndEdge[k] = false;
  108. pPatch->cornerVtx[k] = false;
  109. }
  110. pPatch->nbCornerVtx[k] = 0;
  111. pPatch->valences[k] = 0;
  112. pPatch->minOneRingIndex[k] = 0;
  113. pPatch->loopGapAngle[k] = 65535;
  114. pPatch->edgeBias[2*k] = 16384;
  115. pPatch->edgeBias[2*k+1] = 16384;
  116. pPatch->halfEdges[k].twin = NULL;
  117. pPatch->halfEdges[k].sectorStart = &pPatch->halfEdges[k]; // start one-ring with this halfedge
  118. pPatch->halfEdges[k].localID = k;
  119. pPatch->halfEdges[k].patch = pPatch;
  120. }
  121. }
  122. RemapIndices();
  123. BuildNeighborhoodInfo();
  124. CheckForManifoldMesh();
  125. ConsistentPatchOrientation();
  126. if ( !bIsTagged )
  127. {
  128. TagCreases();
  129. }
  130. // dumpPatches(m_QuadArray);
  131. // first pass --------------------------------------------------------------------
  132. for ( int i=0; i<m_numPatches; i++ )
  133. {
  134. SubD_Face_t *pPatch = &m_faceList[i];
  135. for ( int k=0; k<4; k++ )
  136. {
  137. ComputeSectorStart( pPatch, k );
  138. ComputePerVertexInfo( pPatch, k );
  139. ComputeSectorOneRing( pPatch, k );
  140. ComputeSectorAngle( pPatch, k );
  141. }
  142. }
  143. // dumpPatches(m_faceList);
  144. // second pass requires all per-vertex-per-face variables to be computed ----------
  145. for ( int i=0; i<m_numPatches; i++ )
  146. {
  147. SubD_Face_t *pPatch = &m_faceList[i];
  148. for ( int k=0; k<4; k++ )
  149. {
  150. ComputeNbCorners( pPatch, k );
  151. }
  152. }
  153. // third pass computes neighboring texcoords for watertight displacement mapping ----------
  154. for ( int i=0; i<m_numPatches; i++ )
  155. {
  156. SubD_Face_t *pPatch = &m_faceList[i];
  157. ComputeNeighborTexcoords( pPatch );
  158. }
  159. // Compute offsets into one-rings, necessary for subsequent evaluation consistency
  160. SetMinOneRingIndices();
  161. // Sort patches by regular vs extraordinary
  162. SubD_FaceList_t regFaceList;
  163. SubD_FaceList_t extraFaceList;
  164. for ( int i=0; i<m_numPatches; i++ )
  165. {
  166. SubD_Face_t *pPatch = &m_faceList[i];
  167. if ( FaceIsRegular( pPatch ) )
  168. {
  169. regFaceList.AddToTail( *pPatch );
  170. }
  171. else
  172. {
  173. extraFaceList.AddToTail( *pPatch );
  174. }
  175. }
  176. // recombine
  177. int nRegFaces = regFaceList.Count();
  178. for ( int i=0; i<nRegFaces; i++ )
  179. {
  180. m_faceList[i] = regFaceList[i];
  181. }
  182. int nExtraFaces = extraFaceList.Count();
  183. for ( int i=0; i<nExtraFaces; i++ )
  184. {
  185. m_faceList[i+nRegFaces] = extraFaceList[i];
  186. }
  187. // mend vertices at the end ----------
  188. /*if ( bMendVertices )
  189. {
  190. for ( int i=0; i<m_numPatches; i++ )
  191. {
  192. SubD_Face_t *pPatch = &m_faceList[i];
  193. for (int k=0; k<4; k++)
  194. {
  195. mendVertices( pPatch, k );
  196. }
  197. }
  198. }*/
  199. }
  200. HalfEdge *COptimizeSubDBuilder::FindTwin( HalfEdge &he )
  201. {
  202. Vector p0 = VTXPOS( he.patch->vtxIDs[ MOD4[he.localID+0] ] );
  203. Vector p1 = VTXPOS( he.patch->vtxIDs[ MOD4[he.localID+1] ] ); // twin face will have edge p1->p0
  204. for (int i=0; i<m_numPatches; i++)
  205. {
  206. SubD_Face_t *patch = &m_faceList[i];
  207. for ( unsigned short k=0; k<4; k++ )
  208. {
  209. if ( ( VTXPOS( patch->vtxIDs[ MOD4[k + 0] ] ) == p1 ) &&
  210. ( VTXPOS( patch->vtxIDs[ MOD4[k + 1] ] ) == p0 ) )
  211. {
  212. return &patch->halfEdges[k];
  213. }
  214. }
  215. }
  216. return NULL;
  217. }
  218. // Set the minimum one-ring index for each of the four vertices of a patch.
  219. // This value is used during the mapping from vertices to Bezier control
  220. // points in order to ensure consistent evaluation order and avoid cracks
  221. void COptimizeSubDBuilder::SetMinOneRingIndices()
  222. {
  223. for ( int i=0; i<m_numPatches; i++ ) // Walk patches
  224. {
  225. SubD_Face_t* pPatch = &m_faceList[i];
  226. int nFirstNeighbor = 0; // First neighbor in a given vertex's one-ring
  227. for ( int k=0; k<4; k++ ) // For each vertex of the patch
  228. {
  229. int nMinNeighborIdx = m_IndexRemapTable[pPatch->oneRing[nFirstNeighbor]]; // Remapped Index
  230. int nMinNeighborOffset = 0; // Neighbor zero is the current min
  231. int nLastNeighbor = nFirstNeighbor + pPatch->vtx1RingSize[k] - 1; // Last neighbor
  232. for ( int j=nFirstNeighbor; j<=nLastNeighbor; j++ ) // First neighbor to the last neighbor, inclusive
  233. {
  234. int nNeighborIdx = m_IndexRemapTable[pPatch->oneRing[j]]; // Use only remapped indices
  235. if ( nNeighborIdx < nMinNeighborIdx ) // If we have a smaller remapped index
  236. {
  237. nMinNeighborIdx = nNeighborIdx; // Set as new min index
  238. nMinNeighborOffset = j - nFirstNeighbor; // Offset into THIS vertex's one-ring
  239. }
  240. }
  241. pPatch->minOneRingIndex[k] = nMinNeighborOffset; // Set the offset into THIS vertex's one-ring
  242. nFirstNeighbor = nLastNeighbor + 1; // Go to next range of indices in the one-ring array
  243. }
  244. }
  245. }
  246. // Positions appear redundantly in vertex data, so we need a mapping so that SetMinOneRingIndices() can do the right thing
  247. void COptimizeSubDBuilder::RemapIndices()
  248. {
  249. for ( int i=0; i<m_vtxList.Count(); i++ )
  250. {
  251. m_IndexRemapTable.AddToTail(i); // Set identity mapping
  252. }
  253. for ( int i=0; i<m_vtxList.Count(); i++ ) // Walk indices again
  254. {
  255. for ( int j=i+1; j<m_vtxList.Count(); j++ ) // Look at later indices
  256. {
  257. Vector vPosi = VTXPOS( i );
  258. Vector vPosj = VTXPOS( j );
  259. if ( vPosi == vPosj ) // If the positions are equivalent, set index remapping
  260. {
  261. m_IndexRemapTable[j] = MIN( i, j );
  262. m_IndexRemapTable[i] = MIN( i, j );
  263. }
  264. }
  265. }
  266. /*
  267. for ( int i=0; i<m_vtxList.Count(); i++ )
  268. {
  269. if ( i != m_IndexRemapTable[i] )
  270. {
  271. Msg( "(%d, %d) ***\n", i, m_IndexRemapTable[i] );
  272. }
  273. else
  274. {
  275. Msg( "(%d, %d)\n", i, m_IndexRemapTable[i] );
  276. }
  277. }
  278. */
  279. }
  280. void COptimizeSubDBuilder::BuildNeighborhoodInfo( )
  281. {
  282. for ( int i=0; i<m_numPatches; i++ )
  283. {
  284. SubD_Face_t* pPatch = &m_faceList[i];
  285. for ( int k=0; k<4; k++ )
  286. {
  287. if ( !pPatch->halfEdges[k].twin )
  288. {
  289. HalfEdge *pTwin = FindTwin(pPatch->halfEdges[k]);
  290. pPatch->halfEdges[k].twin = pTwin; // record twin
  291. if ( pTwin )
  292. {
  293. pPatch->halfEdges[k].twin->twin = &pPatch->halfEdges[k]; // record twin's twin
  294. }
  295. else
  296. {
  297. pPatch->bndEdge[k] = true;
  298. pPatch->bndVtx[MOD4[k+0]] = true;
  299. pPatch->bndVtx[MOD4[k+1]] = true;
  300. }
  301. }
  302. }
  303. }
  304. }
  305. void COptimizeSubDBuilder::CheckForManifoldMesh( )
  306. {
  307. for ( int i=0; i<m_numPatches; i++ )
  308. {
  309. SubD_Face_t* pPatch = &m_faceList[i];
  310. for (unsigned short k=0; k<4; ++k)
  311. {
  312. if (( pPatch->halfEdges[k].twin != NULL ) && (pPatch->halfEdges[k].twin->twin != &pPatch->halfEdges[k]) )
  313. {
  314. Msg( "Topology error at vertices %d, %d, %d\n", pPatch->vtxIDs[MOD4[k+3]], pPatch->vtxIDs[MOD4[k+0]], pPatch->vtxIDs[MOD4[k+1]] );
  315. Vector vA = VTXPOS( pPatch->vtxIDs[MOD4[k+3]] );
  316. Vector vB = VTXPOS( pPatch->vtxIDs[MOD4[k+0]] );
  317. Vector vC = VTXPOS( pPatch->vtxIDs[MOD4[k+1]] );
  318. Msg( "spaceLocator -p %.4f %.4f %.4f;\n", vA.x, vA.y, vA.z );
  319. Msg( "spaceLocator -p %.4f %.4f %.4f;\n", vB.x, vB.y, vB.z );
  320. Msg( "spaceLocator -p %.4f %.4f %.4f;\n", vC.x, vC.y, vC.z );
  321. }
  322. }
  323. }
  324. }
  325. void COptimizeSubDBuilder::ComputeSectorStart(SubD_Face_t *pPatch, unsigned short k)
  326. {
  327. HalfEdge *sectorStart, *next = &pPatch->halfEdges[k];
  328. do
  329. {
  330. sectorStart = next;
  331. if ( next->BndEdge() )
  332. {
  333. next = NULL;
  334. }
  335. else
  336. {
  337. next = next->PrevByTail();
  338. }
  339. }
  340. while ( ( next != NULL ) && ( next != &(pPatch->halfEdges[k]) ) );
  341. if ( next == NULL )
  342. {
  343. pPatch->halfEdges[k].sectorStart = sectorStart; // only update sectorStart if we actually hit a boundary
  344. }
  345. }
  346. // Propagates bndVtx to faces that do not have a BndEdge to this vertex, sets cornerVtx,
  347. // Requires sectorStart, corrects sectorStart and bndVtx for dangling crease edges.
  348. void COptimizeSubDBuilder::ComputePerVertexInfo(SubD_Face_t *baseQuad, unsigned short baseLocalID)
  349. {
  350. unsigned short nBndEdges = 0;
  351. HalfEdge *sectorStart = baseQuad->halfEdges[ MOD4[baseLocalID] ].sectorStart, *he = sectorStart;
  352. // Find first sector
  353. HalfEdge *next = he->PrevByTail();
  354. while ( ( next!=NULL ) && ( next!=sectorStart ) )
  355. {
  356. he = next;
  357. next = next->PrevByTail();
  358. }
  359. if ( next != NULL )
  360. {
  361. he = sectorStart;
  362. }
  363. if ( he->BndEdge() )
  364. {
  365. nBndEdges++;
  366. }
  367. HalfEdge *heEnd = he->twin;
  368. he = he->PrevInFace();
  369. do
  370. {
  371. if ( he->BndEdge() )
  372. {
  373. nBndEdges++;
  374. }
  375. he = he->NextByHead();
  376. } while (( he != NULL ) && (he != heEnd));
  377. // Set flags
  378. if ( nBndEdges == 1 ) // dangling BndEdge -> correct sectorStart
  379. {
  380. baseQuad->halfEdges[ baseLocalID ].sectorStart = &baseQuad->halfEdges[ baseLocalID ];
  381. baseQuad->bndVtx[baseLocalID] = false;
  382. }
  383. else if ( nBndEdges >= 2 )
  384. {
  385. baseQuad->bndVtx[baseLocalID] = true;
  386. if ( nBndEdges > 2 )
  387. {
  388. baseQuad->cornerVtx[baseLocalID] = true; // more than 2 BndEdges -> cornerVtx
  389. }
  390. }
  391. }
  392. //
  393. // Writes oneRing, vtx1RingSize, vtx1RingCenterQuadOffset, valence
  394. //
  395. void COptimizeSubDBuilder::ComputeSectorOneRing( SubD_Face_t *baseQuad, unsigned short baseLocalID )
  396. {
  397. unsigned short *oneRing = baseQuad->oneRing;
  398. for ( unsigned short k=0; k < baseLocalID; k++ )
  399. {
  400. oneRing += baseQuad->vtx1RingSize[k];
  401. }
  402. unsigned short &centerOffset = baseQuad->vtx1RingCenterQuadOffset[baseLocalID] = 1;
  403. unsigned short &valence = baseQuad->valences[baseLocalID] = 0;
  404. unsigned short &oneRingSize = baseQuad->vtx1RingSize[baseLocalID] = 0;
  405. HalfEdge *heBase = &baseQuad->halfEdges[ MOD4[baseLocalID] ];
  406. HalfEdge *he = heBase->sectorStart;
  407. oneRing[oneRingSize++] = he->patch->vtxIDs[ MOD4[he->localID+0] ];
  408. valence++;
  409. oneRing[oneRingSize++] = he->patch->vtxIDs[ MOD4[he->localID+1] ];
  410. HalfEdge *heEnd = he->twin;
  411. he = he->PrevInFace();
  412. do
  413. {
  414. oneRing[oneRingSize++] = he->patch->vtxIDs[ MOD4[he->localID+3] ];
  415. valence++;
  416. oneRing[oneRingSize++] = he->patch->vtxIDs[ MOD4[he->localID+0] ];
  417. if ( he->twin == heBase )
  418. {
  419. centerOffset = oneRingSize - 1;
  420. }
  421. he = (he->BndEdge() && baseQuad->bndVtx[baseLocalID]) ? NULL : he->NextByHead(); // make sure we only step over BndEdge if it is dangling.
  422. } while ( ( he != NULL ) && ( he != heEnd ) );
  423. if ( ( he != NULL) && ( he == heEnd ) ) // if we closed the loop, add off-edge vertex from last quad.
  424. {
  425. oneRing[oneRingSize++] = he->patch->vtxIDs[ MOD4[ he->localID+3 ]];
  426. }
  427. }
  428. // Depends on bndVtx, cornerVtx, valence
  429. void COptimizeSubDBuilder::ComputeSectorAngle( SubD_Face_t *baseQuad, unsigned short baseLocalID )
  430. {
  431. if ( !baseQuad->bndVtx[baseLocalID] ) // If no boundary vertex, nothing needs to be done (includes dangling crease)
  432. return;
  433. if ( !baseQuad->cornerVtx[baseLocalID] ) // If no corner, set loopGapAngle = PI (or PI/2 for valence==2)
  434. {
  435. baseQuad->loopGapAngle[baseLocalID] = 65535 / ( baseQuad->valences[baseLocalID] == 2 ? 4 : 2 );
  436. return;
  437. }
  438. HalfEdge *he = baseQuad->halfEdges[ MOD4[baseLocalID] ].sectorStart;
  439. Vector center_pos = VTXPOS( he->patch->vtxIDs[ he->localID ] );
  440. Vector center_nor = VTXNOR( he->patch->vtxIDs[ he->localID ] );
  441. VectorNormalize(center_nor);
  442. int debugVtxID = he->patch->vtxIDs[ MOD4[ he->localID+1 ] ];
  443. Vector eVec1 = VTXPOS( he->patch->vtxIDs[ MOD4[ he->localID+1 ] ] ) - center_pos, eVec2;
  444. Vector npVec1 = project_and_normalize( eVec1, center_nor ), npVec2;
  445. float sector_angle = 0;
  446. he = he->PrevInFace();
  447. do
  448. {
  449. debugVtxID = he->patch->vtxIDs[ MOD4[ he->localID ] ];
  450. eVec2 = VTXPOS( he->patch->vtxIDs[ MOD4[ he->localID ] ] ) - center_pos;
  451. npVec2 = project_and_normalize( eVec2, center_nor );
  452. sector_angle += acosf( DotProduct( npVec1, npVec2 ) );
  453. he = he->BndEdge() ? NULL : he->NextByHead(); // make sure we only step over BndEdge if it is dangling.
  454. npVec1 = npVec2;
  455. } while ( he != NULL ); // only way to terminate is to hit BndEdge
  456. VectorNormalize( eVec1 );
  457. VectorNormalize( eVec2 );
  458. float loopGapAngleF = acosf( DotProduct(eVec1, eVec2) ); // measure overall gap
  459. baseQuad->loopGapAngle[baseLocalID] = (unsigned int) ( ( 65535.0 * loopGapAngleF ) / ( 2 * PI ) );
  460. }
  461. void COptimizeSubDBuilder::MendVertices(SubD_Face_t *baseQuad, unsigned short baseLocalID)
  462. {
  463. HalfEdge *he = baseQuad->halfEdges[ baseLocalID ].sectorStart;
  464. unsigned short vtxID = baseQuad->vtxIDs[ baseLocalID ];
  465. Vector p = VTXPOS( vtxID );
  466. Vector n = VTXNOR( vtxID );
  467. HalfEdge *heEnd = he->twin;
  468. he = he->PrevInFace();
  469. do
  470. {
  471. if (( VTXPOS( he->patch->vtxIDs[ MOD4[he->localID+1] ]) == p ) &&
  472. ( VTXNOR( he->patch->vtxIDs[ MOD4[he->localID+1] ]) == n ))
  473. {
  474. he->patch->vtxIDs[ MOD4[he->localID+1] ] = vtxID;
  475. }
  476. if ( (he->twin) &&
  477. ( VTXPOS( he->twin->patch->vtxIDs[ MOD4[he->twin->localID] ] ) == p) &&
  478. ( VTXNOR( he->twin->patch->vtxIDs[ MOD4[he->twin->localID] ] ) == n) )
  479. {
  480. he->twin->patch->vtxIDs[ MOD4[he->twin->localID] ] = vtxID;
  481. }
  482. he = he->NextByHead();
  483. } while (( he != NULL ) && (he != heEnd));
  484. }
  485. // Computes a bitfield with bits set if the corresponding neighbor-vertex is a concave corner
  486. // this has to go in a second pass as all per-face-per-vertex flags from the first pass to be computed beforehand
  487. void COptimizeSubDBuilder::ComputeNbCorners( SubD_Face_t *baseQuad, unsigned short baseLocalID )
  488. {
  489. NeighborCornerBitfield nbCorners( &baseQuad->nbCornerVtx[baseLocalID] );
  490. HalfEdge *he = baseQuad->halfEdges[ MOD4[baseLocalID] ].sectorStart;
  491. nbCorners.pushBit( he->patch->cornerVtx[ MOD4[he->localID+1] ] == 2 );
  492. HalfEdge *heEnd = he->twin;
  493. he = he->PrevInFace();
  494. do
  495. {
  496. nbCorners.pushBit( he->patch->cornerVtx[ he->localID ] == 2 );
  497. he = ( he->BndEdge() && baseQuad->bndVtx[baseLocalID] ) ? NULL : he->NextByHead(); // make sure we only step over BndEdge if it is dangling.
  498. } while (( he != NULL ) && (he != heEnd));
  499. }
  500. unsigned short COptimizeSubDBuilder::FindNeighborVertex( HalfEdge** ppOutMirrorEdge, const HalfEdge *pHalfEdge, int indexAlongEdge )
  501. // Finds neighboring vertex along the mirror edge of pHalfEdge.
  502. // Returns the index of the vertex.
  503. // pOutMirrorEdge is the mirror edge we took this vertex from.
  504. // pHalfEdge is the shared edge who's mirror we want to find.
  505. // indexAlongEdge is the index of the vertex along the edge. ( 0 or 1 only )
  506. {
  507. HalfEdge* pMirrorEdge = pHalfEdge->twin;
  508. unsigned short vertexID = (unsigned short)-1;
  509. if ( pMirrorEdge )
  510. {
  511. vertexID = pMirrorEdge->patch->vtxIDs[ ( pMirrorEdge->localID + indexAlongEdge ) % 4 ] ;
  512. }
  513. if ( ppOutMirrorEdge )
  514. {
  515. *ppOutMirrorEdge = pMirrorEdge;
  516. }
  517. return vertexID;
  518. }
  519. // Computes the neighboring texcoords ( Interior, EdgeV, EdgeU, Corner ) for each vertex
  520. // texcoords are computed in such a way that every shared edge or corner computes the same values
  521. // this is used as a tie-breaking scheme for creating consistent texture sampling for displacement maps
  522. void COptimizeSubDBuilder::ComputeNeighborTexcoords( SubD_Face_t *baseQuad )
  523. {
  524. unsigned short p = baseQuad->patchID;
  525. unsigned short invalidNeighborValue = (unsigned short)-1;
  526. // Loop over all 4 verts of the quad
  527. for ( int i=0; i<4; ++i )
  528. {
  529. unsigned short index = baseQuad->vtxIDs[i];
  530. // Interior point is alway the current corner
  531. baseQuad->vUV0[i] = VTXIDX( index );
  532. // Assert( index == baseQuad->vUV0[i] );
  533. // Default to original texcoord values for 1 and 2
  534. baseQuad->vUV1[i] = baseQuad->vUV0[i];
  535. baseQuad->vUV2[i] = baseQuad->vUV0[i];
  536. // Find the texture coordinates of our neighbors
  537. // Only keep the texture coordinates of the neighbor with the greatest quad index
  538. HalfEdge* pMirrorEdgeV = NULL;
  539. // V edge ( store the UVs of the patch with the greatest ID )
  540. unsigned short iNeighborPatchV = invalidNeighborValue;
  541. unsigned short iNeighborV = FindNeighborVertex( &pMirrorEdgeV, &baseQuad->halfEdges[ i ], 1 );
  542. if ( iNeighborV != invalidNeighborValue ) // hard edge test
  543. {
  544. iNeighborPatchV = pMirrorEdgeV->patch->patchID;
  545. if ( iNeighborPatchV > p )
  546. {
  547. baseQuad->vUV1[i] = VTXIDX( iNeighborV );
  548. }
  549. }
  550. HalfEdge* pMirrorEdgeU = NULL;
  551. // U edge ( store the UVs of the patch with the greatest ID )
  552. unsigned short iNeighborPatchU = invalidNeighborValue;
  553. unsigned short iNeighborU = FindNeighborVertex( &pMirrorEdgeU, &baseQuad->halfEdges[ (i+3)%4 ], 0 );
  554. if ( iNeighborU != invalidNeighborValue ) // hard edge test
  555. {
  556. iNeighborPatchU = pMirrorEdgeU->patch->patchID;
  557. if ( iNeighborPatchU > p )
  558. {
  559. baseQuad->vUV2[i] = VTXIDX( iNeighborU );
  560. }
  561. }
  562. // Corner ( store the UVs of the patch with the greatest ID ).
  563. // Walk from NeighborV to NeighborU and store data for the largest patch ID.
  564. // We may redundantly check NeighborPatchU here if this is a valence 3 vertex.
  565. HalfEdge* pMirrorEdgeCorner = pMirrorEdgeV;
  566. unsigned short iNeighborPatch = invalidNeighborValue;
  567. unsigned short iMaxNeighborCorner = index;
  568. unsigned short iMaxPatch = baseQuad->patchID;
  569. if ( pMirrorEdgeCorner )
  570. {
  571. do
  572. {
  573. HalfEdge* pNextEdge = pMirrorEdgeCorner->NextInFace();
  574. unsigned short iNeighborCorner = FindNeighborVertex( &pMirrorEdgeCorner, pNextEdge, 1 );
  575. if ( iNeighborCorner != invalidNeighborValue ) // hard edge test
  576. {
  577. iNeighborPatch = pMirrorEdgeCorner->patch->patchID;
  578. if ( pMirrorEdgeCorner->patch->patchID > iMaxPatch )
  579. {
  580. iMaxPatch = pMirrorEdgeCorner->patch->patchID;
  581. iMaxNeighborCorner = iNeighborCorner;
  582. }
  583. }
  584. } while( iNeighborPatch != iNeighborPatchU && pMirrorEdgeCorner );
  585. }
  586. // Determine whether We still need to check against U and V adjacent patches
  587. if ( pMirrorEdgeU && ( pMirrorEdgeU->patch->patchID > iMaxPatch ) )
  588. {
  589. iMaxPatch = pMirrorEdgeU->patch->patchID;
  590. iMaxNeighborCorner = iNeighborU;
  591. }
  592. if ( pMirrorEdgeV && ( pMirrorEdgeV->patch->patchID > iMaxPatch ) )
  593. {
  594. iMaxPatch = pMirrorEdgeV->patch->patchID;
  595. iMaxNeighborCorner = iNeighborV;
  596. }
  597. baseQuad->vUV3[i] = VTXIDX( iMaxNeighborCorner );
  598. }
  599. }
  600. void DumpPatchLite( SubD_Face_t *patch )
  601. {
  602. Msg( "Patch: %d\n", patch->patchID );
  603. Msg( " vtxIDs: %d %d %d %d\n", patch->vtxIDs[0], patch->vtxIDs[1], patch->vtxIDs[2], patch->vtxIDs[3] );
  604. Msg( " halfEdges.twin: %d/%d %d/%d %d/%d %d/%d\n",
  605. patch->halfEdges[0].twin ? patch->halfEdges[0].twin->patch->patchID : -1, patch->halfEdges[0].twin ? patch->halfEdges[0].twin->localID: -1,
  606. patch->halfEdges[1].twin ? patch->halfEdges[1].twin->patch->patchID : -1, patch->halfEdges[1].twin ? patch->halfEdges[1].twin->localID: -1,
  607. patch->halfEdges[2].twin ? patch->halfEdges[2].twin->patch->patchID : -1, patch->halfEdges[2].twin ? patch->halfEdges[2].twin->localID: -1,
  608. patch->halfEdges[3].twin ? patch->halfEdges[3].twin->patch->patchID : -1, patch->halfEdges[3].twin ? patch->halfEdges[3].twin->localID: -1 );
  609. Msg( " halfEdges.sectorStart: %d/%d %d/%d %d/%d %d/%d\n",
  610. patch->halfEdges[0].sectorStart ? patch->halfEdges[0].sectorStart->patch->patchID : -1, patch->halfEdges[0].sectorStart ? patch->halfEdges[0].sectorStart->localID: -1,
  611. patch->halfEdges[1].sectorStart ? patch->halfEdges[1].sectorStart->patch->patchID : -1, patch->halfEdges[1].sectorStart ? patch->halfEdges[1].sectorStart->localID: -1,
  612. patch->halfEdges[2].sectorStart ? patch->halfEdges[2].sectorStart->patch->patchID : -1, patch->halfEdges[2].sectorStart ? patch->halfEdges[2].sectorStart->localID: -1,
  613. patch->halfEdges[3].sectorStart ? patch->halfEdges[3].sectorStart->patch->patchID : -1, patch->halfEdges[3].sectorStart ? patch->halfEdges[3].sectorStart->localID: -1 );
  614. }
  615. // Rotate a particular face one step (element N grabs from element N-1)
  616. void COptimizeSubDBuilder::RotateOnce( SubD_Face_t *pPatch )
  617. {
  618. // Msg( "- Before ------------------------------------------------------------------------------------------\n" );
  619. // DumpPatchLite( pPatch );
  620. SubD_Face_t tmpFace;
  621. memcpy( &tmpFace, pPatch, sizeof( SubD_Face_t ) );
  622. HalfEdge *pTwins[4] = { NULL, NULL, NULL, NULL };
  623. for ( int i=0; i<4; i++ )
  624. {
  625. pTwins[i] = pPatch->halfEdges[i].twin; // Point to each HalfEdge's twin
  626. if ( pTwins[i] )
  627. {
  628. Assert( pTwins[i]->twin == &(pPatch->halfEdges[i]) ); // ith twin should be pointing back to ith HalfEdge
  629. }
  630. }
  631. for ( int i=0; i<4; i++ )
  632. {
  633. pPatch->vtxIDs[i] = tmpFace.vtxIDs[(i+3)%4]; // Grab from n-1
  634. pPatch->bndEdge[i] = tmpFace.bndEdge[(i+3)%4];
  635. pPatch->bndVtx[i] = tmpFace.bndVtx[(i+3)%4];
  636. memcpy( &(pPatch->halfEdges[i]), &(tmpFace.halfEdges[(i+3)%4]), sizeof(HalfEdge) );
  637. pPatch->halfEdges[i].localID = i;
  638. pPatch->halfEdges[i].sectorStart = &pPatch->halfEdges[i];
  639. }
  640. for ( int i=0; i<4; i++ )
  641. {
  642. if ( pTwins[i] )
  643. {
  644. pTwins[i]->twin = &(pPatch->halfEdges[(i+1)%4]); // Record twin's twin after we've rotated the local patch data
  645. }
  646. }
  647. // Msg( "- After ------------------------------------------------------------------------------------------\n" );
  648. // DumpPatchLite( pPatch );
  649. // Msg( "---------------------------------------------------------------------------------------------------\n" );
  650. // Msg( "---------------------------------------------------------------------------------------------------\n\n" );
  651. }
  652. void COptimizeSubDBuilder::RotateFace( SubD_Face_t *pPatch, int nTimesToRotate )
  653. {
  654. for ( int i=0; i<nTimesToRotate; i++ )
  655. {
  656. RotateOnce( pPatch );
  657. }
  658. }
  659. int COptimizeSubDBuilder::FaceEdgeIndex( SubD_Face_t *pFace, HalfEdge *pEdge )
  660. {
  661. int i = 0;
  662. while ( &(pFace->halfEdges[i]) != pEdge )
  663. {
  664. i++;
  665. }
  666. return i;
  667. }
  668. void COptimizeSubDBuilder::Propagate( CUtlVector<Orientation> & orientationArray, HalfEdge *pEdge, bool dir )
  669. {
  670. Assert( pEdge );
  671. while( true )
  672. {
  673. HalfEdge *pNeighborEdge = pEdge->twin;
  674. if ( !pNeighborEdge )
  675. break; // Stop at mesh boundaries.
  676. SubD_Face_t *pFace = pNeighborEdge->patch;
  677. if ( !pFace )
  678. break; // Stop at mesh boundaries.
  679. int nEdgeIndex = FaceEdgeIndex( pFace, pNeighborEdge );
  680. Orientation & faceOrientation = orientationArray[pFace->patchID];
  681. if ( nEdgeIndex == 1 || nEdgeIndex == 3 )
  682. {
  683. if ( faceOrientation.uSet )
  684. {
  685. Assert( faceOrientation.u == ( ( nEdgeIndex == 1 ) ^ dir ) );
  686. break;
  687. }
  688. faceOrientation.SetU( ( nEdgeIndex == 1 ) ^ dir );
  689. }
  690. else // if ( nEdgeIndex == 0 || nEdgeIndex == 2 )
  691. {
  692. if ( faceOrientation.vSet )
  693. {
  694. Assert( faceOrientation.v == ( ( nEdgeIndex == 0 ) ^ dir ) );
  695. break;
  696. }
  697. faceOrientation.SetV( ( nEdgeIndex == 0 ) ^ dir );
  698. }
  699. pEdge = pNeighborEdge->NextInFace()->NextInFace();
  700. }
  701. }
  702. static HalfEdge *FaceEdge( SubD_Face_t *pPatch, int idx )
  703. {
  704. int i = 0;
  705. HalfEdge *pEdge = &pPatch->halfEdges[0];
  706. while ( i != idx )
  707. {
  708. i++;
  709. pEdge = pEdge->NextInFace();
  710. }
  711. return pEdge;
  712. }
  713. // Reorient faces in order to avoid parametric discontinuities.
  714. void COptimizeSubDBuilder::ConsistentPatchOrientation()
  715. {
  716. CUtlVector<Orientation> orientationArray;
  717. orientationArray.AddMultipleToTail( m_numPatches );
  718. for( int f = 0; f < m_numPatches; f++ )
  719. {
  720. SubD_Face_t *pPatch = &m_faceList[f];
  721. HalfEdge *pEdges = &pPatch->halfEdges[0];
  722. if ( !orientationArray[f].uSet )
  723. {
  724. orientationArray[f].SetU( false );
  725. Propagate( orientationArray, pEdges+1, false );
  726. Propagate( orientationArray, pEdges+3, true );
  727. }
  728. if ( !orientationArray[f].vSet )
  729. {
  730. orientationArray[f].SetV( false );
  731. Propagate( orientationArray, pEdges+0, false );
  732. Propagate( orientationArray, pEdges+2, true );
  733. }
  734. }
  735. for( int f = 0; f < m_numPatches; f++ )
  736. {
  737. SubD_Face_t *pPatch = &m_faceList[f];
  738. const Orientation &o = orientationArray[f]; // Determine edge from orientation flags.
  739. static const int nTimesToRotate[4] = {0, 1, 3, 2};
  740. const int idx = nTimesToRotate[(o.v << 1) + o.u];
  741. RotateFace( pPatch, idx );
  742. }
  743. }
  744. void COptimizeSubDBuilder::TagCreases()
  745. {
  746. static int MOD4[] = {0,1,2,3,0,1,2,3};
  747. for (unsigned short i=0; i<m_numPatches; i++)
  748. {
  749. SubD_Face_t *pPatch = &m_faceList[i];
  750. for ( int k=0; k<4; k++ ) // for all vertices
  751. {
  752. if ( pPatch->halfEdges[k].twin != NULL )
  753. {
  754. HalfEdge *twin = pPatch->halfEdges[k].twin;
  755. SubD_Face_t *nbQuad = twin->patch;
  756. int quad0vtx0ID = pPatch->vtxIDs[ MOD4[k+0] ];
  757. int quad1vtx0ID = nbQuad->vtxIDs[ MOD4[twin->localID+1] ];
  758. int quad0vtx1ID = pPatch->vtxIDs[ MOD4[k+1] ];
  759. int quad1vtx1ID = nbQuad->vtxIDs[ MOD4[twin->localID+0] ];
  760. if ( ( VTXNOR( quad0vtx0ID ) != VTXNOR( quad1vtx0ID ) ) ||
  761. ( VTXNOR( quad0vtx1ID ) != VTXNOR( quad1vtx1ID ) ) )
  762. {
  763. pPatch->bndEdge[k] = true;
  764. pPatch->bndVtx[MOD4[k+0]] = true;
  765. pPatch->bndVtx[MOD4[k+1]] = true;
  766. }
  767. }
  768. }
  769. }
  770. }
  771. }; // namespace