Added a function Flip a mesh so that its normals are orented outside.
Just for safety it uses a voting scheme. It assumes that * mesh has already has coherent normals. * mesh is watertight and single component.
This commit is contained in:
parent
d967184dee
commit
5233b20f12
|
@ -1150,6 +1150,60 @@ private:
|
||||||
std::swap((*fi).WT(0),(*fi).WT(1));
|
std::swap((*fi).WT(0),(*fi).WT(1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// Flip a mesh so that its normals are orented outside.
|
||||||
|
/// Just for safety it uses a voting scheme.
|
||||||
|
/// It assumes that
|
||||||
|
/// mesh has already has coherent normals.
|
||||||
|
/// mesh is watertight and signle component.
|
||||||
|
static bool FlipNormalOutside(MeshType &m)
|
||||||
|
{
|
||||||
|
if(m.vert.empty()) return false;
|
||||||
|
|
||||||
|
tri::UpdateNormals<MeshType>::PerVertexAngleWeighted(m);
|
||||||
|
tri::UpdateNormals<MeshType>::NormalizeVertex(m);
|
||||||
|
|
||||||
|
std::vector< VertexPointer > minVertVec;
|
||||||
|
std::vector< VertexPointer > maxVertVec;
|
||||||
|
|
||||||
|
// The set of directions to be choosen
|
||||||
|
std::vector< Point3x > dirVec;
|
||||||
|
dirVec.push_back(Point3x(1,0,0));
|
||||||
|
dirVec.push_back(Point3x(0,1,0));
|
||||||
|
dirVec.push_back(Point3x(0,0,1));
|
||||||
|
dirVec.push_back(Point3x( 1, 1,1));
|
||||||
|
dirVec.push_back(Point3x(-1, 1,1));
|
||||||
|
dirVec.push_back(Point3x(-1,-1,1));
|
||||||
|
dirVec.push_back(Point3x( 1,-1,1));
|
||||||
|
for(size_t i=0;i<dirVec.size();++i)
|
||||||
|
{
|
||||||
|
Normalize(dirVec[i]);
|
||||||
|
minVertVec.push_back(&*m.vert.begin());
|
||||||
|
maxVertVec.push_back(&*m.vert.begin());
|
||||||
|
}
|
||||||
|
for (VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) if(!(*vi).IsD())
|
||||||
|
{
|
||||||
|
for(size_t i=0;i<dirVec.size();++i)
|
||||||
|
{
|
||||||
|
if( (*vi).cP().dot(dirVec[i]) < minVertVec[i]->P().dot(dirVec[i])) minVertVec[i] = &*vi;
|
||||||
|
if( (*vi).cP().dot(dirVec[i]) > maxVertVec[i]->P().dot(dirVec[i])) maxVertVec[i] = &*vi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int voteCount=0;
|
||||||
|
ScalarType angleThreshold = cos(math::ToRad(85.0));
|
||||||
|
for(size_t i=0;i<dirVec.size();++i)
|
||||||
|
{
|
||||||
|
// qDebug("Min vert along (%f %f %f) is %f %f %f",dirVec[i][0],dirVec[i][1],dirVec[i][2],minVertVec[i]->P()[0],minVertVec[i]->P()[1],minVertVec[i]->P()[2]);
|
||||||
|
// qDebug("Max vert along (%f %f %f) is %f %f %f",dirVec[i][0],dirVec[i][1],dirVec[i][2],maxVertVec[i]->P()[0],maxVertVec[i]->P()[1],maxVertVec[i]->P()[2]);
|
||||||
|
if(minVertVec[i]->N().dot(dirVec[i]) > angleThreshold ) voteCount++;
|
||||||
|
if(maxVertVec[i]->N().dot(dirVec[i]) < -angleThreshold ) voteCount++;
|
||||||
|
}
|
||||||
|
// qDebug("votecount = %i",voteCount);
|
||||||
|
if(voteCount < dirVec.size()/2) return false;
|
||||||
|
FlipMesh(m);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Search and remove small single triangle folds
|
// Search and remove small single triangle folds
|
||||||
// - a face has normal opposite to all other faces
|
// - a face has normal opposite to all other faces
|
||||||
// - choose the edge that brings to the face f1 containing the vertex opposite to that edge.
|
// - choose the edge that brings to the face f1 containing the vertex opposite to that edge.
|
||||||
|
|
Loading…
Reference in New Issue