//---------------------------------------------------------------------------- void MTMesh::AttachTriangleToEdge (int t, MTTriangle& triangle, int i, int e, MTEdge& edge) { if (edge.Triangle(0) == -1) { edge.Triangle(0) = t; } else { int a = edge.Triangle(0); MTTriangle& adjacent = mTriangles[a]; triangle.Adjacent(i) = a; for (int j = 0; j < 3; ++j) { if (adjacent.Edge(j) == e) { adjacent.Adjacent(j) = t; break; } } if (edge.Triangle(1) == -1) { edge.Triangle(1) = t; } else { assertion(false, "The mesh is not manifold.\n"); } } triangle.Edge(i) = e; }
//---------------------------------------------------------------------------- void MTMesh::AttachTriangleToEdge (int iT, MTTriangle& rkT, int i, int iE, MTEdge& rkE) { if ( rkE.Triangle(0) == -1 ) { rkE.Triangle(0) = iT; } else { int iTAdj = rkE.Triangle(0); MTTriangle& rkTAdj = m_akTriangle[iTAdj]; rkT.Adjacent(i) = iTAdj; for (int j = 0; j < 3; j++) { if ( rkTAdj.Edge(j) == iE ) { rkTAdj.Adjacent(j) = iT; break; } } if ( rkE.Triangle(1) == -1 ) { rkE.Triangle(1) = iT; } else { // mesh is not manifold assert( false ); } } rkT.Edge(i) = iE; }
//---------------------------------------------------------------------------- void MTMesh::DetachTriangleFromEdge (int t, MTTriangle& triangle, int i, int e, MTEdge& edge) { // This function leaves T only partially complete. The edge E is no // longer referenced by T, even though the vertices of T reference the // end points of E. If T has an adjacent triangle A that shares E, then // A is a complete triangle. if (edge.Triangle(0) == t) { int a = edge.Triangle(1); if (a != -1) { // T and TAdj share E, update adjacency information for both MTTriangle& adjacent = mTriangles[a]; for (int j = 0; j < 3; ++j) { if (adjacent.Edge(j) == e) { adjacent.Adjacent(j) = -1; break; } } } edge.Triangle(0) = a; } else if (edge.Triangle(1) == t) { // T and TAdj share E, update adjacency information for both MTTriangle& adjacent = mTriangles[edge.Triangle(0)]; for (int j = 0; j < 3; ++j) { if (adjacent.Edge(j) == e) { adjacent.Adjacent(j) = -1; break; } } } else { // Should not get here. The specified edge must share the input // triangle. assertion(false, "Unexpected condition.\n"); } edge.Triangle(1) = -1; triangle.Edge(i) = -1; triangle.Adjacent(i) = -1; }
//---------------------------------------------------------------------------- void MTMesh::DetachTriangleFromEdge (int iT, MTTriangle& rkT, int i, int iE, MTEdge& rkE) { // This function leaves T only partially complete. The edge E is no // longer referenced by T, even though the vertices of T reference the // end points of E. If T has an adjacent triangle A that shares E, then // A is a complete triangle. if ( rkE.Triangle(0) == iT ) { int iTAdj = rkE.Triangle(1); if ( iTAdj != -1 ) { // T and TAdj share E, update adjacency information for both MTTriangle& rkTAdj = m_akTriangle[iTAdj]; for (int j = 0; j < 3; j++) { if ( rkTAdj.Edge(j) == iE ) { rkTAdj.Adjacent(j) = -1; break; } } } rkE.Triangle(0) = iTAdj; } else if ( rkE.Triangle(1) == iT ) { // T and TAdj share E, update adjacency information for both MTTriangle& rkTAdj = m_akTriangle[rkE.Triangle(0)]; for (int j = 0; j < 3; j++) { if ( rkTAdj.Edge(j) == iE ) { rkTAdj.Adjacent(j) = -1; break; } } } else { // Should not get here. The specified edge must share the input // triangle. assert( false ); } rkE.Triangle(1) = -1; rkT.Edge(i) = -1; rkT.Adjacent(i) = -1; }
//---------------------------------------------------------------------------- void ConvexPolyhedron::ComputeTerminator (const Vector3& rkEye, vector<Vector3>& 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::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::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::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 ); }