// Check Compare before and after normals of affected faces. // If a normal changes more by more than pi/2 (90 deg), then // we will disallow this contraction and terminate early. BOOL Pair::normalFlips(SmallPtrSet& updatedFaces, SmallPtrSet& rvFaces, BOOL& smallNormalChange) { Vertex* keepVertex = getContractTarget(); Vertex* removeVertex = NULL; if (keepVertex == v1) removeVertex = v2; else removeVertex = v1; // Compute adjusted faces: rvFaces.Clear(); updatedFaces.Clear(); removeVertex->computeFaceSet(rvFaces); // problem here, rvFaces different SmallPtrSet_Difference(&rvFaces, &m_Faces, &updatedFaces); Vertex *v1, *v2, *v3; U32 SetCtx = 0; Face* face = (Face*)updatedFaces.Begin(SetCtx); smallNormalChange = TRUE; F32 dotThresh = 0.966f; // about 15 degrees F32 worstDot=1; BOOL result = FALSE; IV3D u, v, oldNormal, newNormal; F32 dot; while(face && !result) { if( !result ) { v1 = face->a->getCommonVertex(face->b); v2 = face->b->getCommonVertex(face->c); v3 = face->c->getCommonVertex(face->a); // Compute the normal - we could grab this data from the equation of the plane (A, B, C, D), // but then we'd have to keep A, B, C, D around in the faces: subtract3D ((IV3D*)&v2->v, (IV3D*)&v1->v, (IV3D*)&u); if( isZero(&u) ) { if(cost < NORMAL_FLIP_COST) cost = NORMAL_FLIP_COST; result = TRUE; } } if( !result ) { normalize3D ((IV3D*)&u); subtract3D ((IV3D*)&v3->v, (IV3D*)&v1->v, (IV3D*)&v); if( isZero(&v) ) { if(cost < NORMAL_FLIP_COST) cost = NORMAL_FLIP_COST; result = TRUE; } } if( !result ) { normalize3D ((IV3D*)&v); crossprod ((IV3D*)&u, (IV3D*)&v, &oldNormal); if( isZero(&oldNormal) ) { if(cost < NORMAL_FLIP_COST) cost = NORMAL_FLIP_COST; result = TRUE; } } if( !result ) normalize3D (&oldNormal); // Recompute the normal: if( !result ) { // Install the keep vertex into this temp version of the adjusted face: if (v1 == removeVertex) v1 = keepVertex; if (v2 == removeVertex) v2 = keepVertex; if (v3 == removeVertex) v3 = keepVertex; subtract3D ((IV3D*)&v2->v, (IV3D*)&v1->v, (IV3D*)&u); if( isZero(&u) ) { if(cost < NORMAL_FLIP_COST) cost = NORMAL_FLIP_COST; result = TRUE; } } if( !result ) { normalize3D ((IV3D*)&u); subtract3D ((IV3D*)&v3->v, (IV3D*)&v1->v, (IV3D*)&v); if( isZero(&v) ) { if(cost < NORMAL_FLIP_COST) cost = NORMAL_FLIP_COST; result = TRUE; } } if( !result ) { normalize3D ((IV3D*)&v); crossprod ((IV3D*)&u, (IV3D*)&v, (IV3D*)&newNormal); if( isZero(&newNormal) ) { if(cost < NORMAL_FLIP_COST) cost = NORMAL_FLIP_COST; result = TRUE; } } if( !result ) { normalize3D ((IV3D*)&newNormal); dot = dotProduct3D ((IV3D*)&oldNormal, (IV3D*)&newNormal); // Did the normal flip?: if (dot < cosMaxNormalChange) { // Mark it flipped: if(cost < NORMAL_FLIP_COST) cost = NORMAL_FLIP_COST; result = TRUE; } } // test if( !result ) { if(dot < worstDot) worstDot = dot; face = (Face*)updatedFaces.Next(SetCtx); } } if(worstDot < dotThresh && !result) { smallNormalChange = FALSE; } return result; }