//---------------------------------------------------------------------------- void VETable::RemoveTriangles (V3Array& rkVA, T3Array& rkTA) { // ear-clip the wireframe to get the triangles Triangle3 kTri; while ( Remove(kTri) ) { int iV0 = (int)rkVA.size(), iV1 = iV0+1, iV2 = iV1+1; rkTA.push_back(Triangle3(iV0,iV1,iV2)); const Vertex& rkV0 = m_akVertex[kTri.i0]; const Vertex& rkV1 = m_akVertex[kTri.i1]; const Vertex& rkV2 = m_akVertex[kTri.i2]; rkVA.push_back(Vertex3(rkV0.m_fX,rkV0.m_fY,rkV0.m_fZ)); rkVA.push_back(Vertex3(rkV1.m_fX,rkV1.m_fY,rkV1.m_fZ)); rkVA.push_back(Vertex3(rkV2.m_fX,rkV2.m_fY,rkV2.m_fZ)); } }
void ConvexPolyhedron3<Real>::ComputeTerminator (const Vector3<Real>& rkEye, V3Array& rkTerminator) { // temporary storage for signed distances from eye to triangles int iTQuantity = m_akTriangle.GetQuantity(); vector<Real> afDistance(iTQuantity); int i, j; for (i = 0; i < iTQuantity; i++) afDistance[i] = Math<Real>::MAX_REAL; // Start a search for a front-facing triangle that has an adjacent // back-facing triangle or for a back-facing triangle that has an // adjacent front-facing triangle. int iTCurrent = 0; MTTriangle* pkTCurrent = &m_akTriangle[iTCurrent]; Real fTriDist = GetDistance(rkEye,iTCurrent,afDistance); int iEFirst = -1; for (i = 0; i < iTQuantity; i++) { // Check adjacent neighbors for edge of terminator. Such an // edge occurs if the signed distance changes sign. int iMinIndex = -1; Real fMinAbsDist = Math<Real>::MAX_REAL; Real afAdjDist[3]; for (j = 0; j < 3; j++) { afAdjDist[j] = GetDistance(rkEye,pkTCurrent->Adjacent(j), afDistance); if ( IsNegativeProduct(fTriDist,afAdjDist[j]) ) { iEFirst = pkTCurrent->Edge(j); break; } Real fAbsDist = Math<Real>::FAbs(afAdjDist[j]); if ( fAbsDist < fMinAbsDist ) { fMinAbsDist = fAbsDist; iMinIndex = j; } } if ( j < 3 ) break; // First edge not found during this iteration. Move to adjacent // triangle whose distance is smallest of all adjacent triangles. iTCurrent = pkTCurrent->Adjacent(iMinIndex); pkTCurrent = &m_akTriangle[iTCurrent]; fTriDist = afAdjDist[iMinIndex]; } assert( i < iTQuantity ); MTEdge& rkEFirst = m_akEdge[iEFirst]; rkTerminator.push_back(m_akPoint[GetVLabel(rkEFirst.Vertex(0))]); rkTerminator.push_back(m_akPoint[GetVLabel(rkEFirst.Vertex(1))]); // walk along the terminator int iVFirst = rkEFirst.Vertex(0); int iV = rkEFirst.Vertex(1); int iE = iEFirst; int iEQuantity = m_akEdge.GetQuantity(); for (i = 0; i < iEQuantity; i++) { // search all edges sharing the vertex for another terminator edge int j, jMax = m_akVertex[iV].GetEdgeQuantity(); for (j = 0; j < m_akVertex[iV].GetEdgeQuantity(); j++) { int iENext = m_akVertex[iV].GetEdge(j); if ( iENext == iE ) continue; Real fDist0 = GetDistance(rkEye,m_akEdge[iENext].GetTriangle(0), afDistance); Real fDist1 = GetDistance(rkEye,m_akEdge[iENext].GetTriangle(1), afDistance); if ( IsNegativeProduct(fDist0,fDist1) ) { if ( m_akEdge[iENext].GetVertex(0) == iV ) { iV = m_akEdge[iENext].GetVertex(1); rkTerminator.push_back(m_akPoint[GetVLabel(iV)]); if ( iV == iVFirst ) return; } else { iV = m_akEdge[iENext].GetVertex(0); rkTerminator.push_back(m_akPoint[GetVLabel(iV)]); if ( iV == iVFirst ) return; } iE = iENext; break; } } assert( j < jMax ); } assert( i < iEQuantity ); }