Heavily reformatted and cleaned for documentation. Hopefully no semantic changes involved...

This commit is contained in:
Paolo Cignoni 2012-10-08 09:01:24 +00:00
parent c22ebbf304
commit 33e1231056
1 changed files with 164 additions and 141 deletions

View File

@ -75,58 +75,27 @@ static void PerVertexClear(ComputeMeshType &m, bool ClearAllVertNormal=false)
(*vi).N() = NormalType((ScalarType)0,(ScalarType)0,(ScalarType)0); (*vi).N() = NormalType((ScalarType)0,(ScalarType)0,(ScalarType)0);
} }
/// \brief Calculates the face normal (if stored in the current face type) /// \brief Calculates the vertex normal as the classic area weighted average. It does not need or exploit current face normals.
static void PerFace(ComputeMeshType &m)
{
if(!HasPerFaceNormal(m)) throw vcg::MissingComponentException();
for(FaceIterator f=m.face.begin();f!=m.face.end();++f)
if( !(*f).IsD() ) face::ComputeNormal(*f);
}
/// \brief Calculates the vertex normal. Exploiting or current face normals.
/** /**
The normal of a vertex v is the weigthed average of the normals of the faces incident on v. The normal of a vertex v is the classical area-weigthed average of the normals of the faces incident on v.
*/ */
static void PerVertexFromCurrentFaceNormal(ComputeMeshType &m) static void PerVertex(ComputeMeshType &m)
{ {
if(!HasPerVertexNormal(m)) throw vcg::MissingComponentException(); PerVertexClear(m);
FaceIterator f;
for(f=m.face.begin();f!=m.face.end();++f)
if( !(*f).IsD() && (*f).IsR() )
{
//typename FaceType::NormalType t = (*f).Normal();
typename FaceType::NormalType t = vcg::Normal(*f);
VertexIterator vi;
for(vi=m.vert.begin();vi!=m.vert.end();++vi)
if( !(*vi).IsD() && (*vi).IsRW() )
(*vi).N()=CoordType(0,0,0);
FaceIterator fi;
for(fi=m.face.begin();fi!=m.face.end();++fi)
if( !(*fi).IsD())
{
for(int j=0; j<3; ++j) for(int j=0; j<3; ++j)
if( !(*fi).V(j)->IsD()) if( !(*f).V(j)->IsD() && (*f).V(j)->IsRW() )
(*fi).V(j)->N() += (*fi).cN(); (*f).V(j)->N() += t;
} }
} }
/// \brief Calculates the vertex normal. Exploiting or current face normals.
/**
The normal of a face f is the average of the normals of the vertices of f.
*/
static void PerFaceFromCurrentVertexNormal(ComputeMeshType &m)
{
if(!HasPerVertexNormal(m) || !HasPerFaceNormal(m)) throw vcg::MissingComponentException();
for (FaceIterator fi=m.face.begin(); fi!=m.face.end(); ++fi)
if( !(*fi).IsD())
{
NormalType n;
n.SetZero();
for(int j=0; j<3; ++j)
n += fi->V(j)->cN();
n.Normalize();
fi->N() = n;
}
}
/// \brief Calculates the vertex normal as an angle weighted average. It does not need or exploit current face normals.
/// \brief Calculates the vertex normal. Without exploiting or touching face normals.
/** /**
The normal of a vertex v computed as a weighted sum f the incident face normals. The normal of a vertex v computed as a weighted sum f the incident face normals.
The weight is simlply the angle of the involved wedge. Described in: The weight is simlply the angle of the involved wedge. Described in:
@ -135,8 +104,7 @@ G. Thurmer, C. A. Wuthrich
"Computing vertex normals from polygonal facets" "Computing vertex normals from polygonal facets"
Journal of Graphics Tools, 1998 Journal of Graphics Tools, 1998
*/ */
static void PerVertexAngleWeighted(ComputeMeshType &m)
static void PerVertexAngleWeighted(ComputeMeshType &m)
{ {
PerVertexClear(m); PerVertexClear(m);
FaceIterator f; FaceIterator f;
@ -154,7 +122,7 @@ static void PerVertexAngleWeighted(ComputeMeshType &m)
} }
} }
/// \brief Calculates the vertex normal. Without exploiting or touching face normals. /// \brief Calculates the vertex normal using the Max et al. weighting scheme. It does not need or exploit current face normals.
/** /**
The normal of a vertex v is computed according to the formula described by Nelson Max in The normal of a vertex v is computed according to the formula described by Nelson Max in
Max, N., "Weights for Computing Vertex Normals from Facet Normals", Journal of Graphics Tools, 4(2) (1999) Max, N., "Weights for Computing Vertex Normals from Facet Normals", Journal of Graphics Tools, 4(2) (1999)
@ -180,59 +148,63 @@ static void PerVertexNelsonMaxWeighted(ComputeMeshType &m)
} }
} }
/// \brief Calculates the vertex normal. Without exploiting or touching face normals. /// \brief Calculates the face normal
/** ///
The normal of a vertex v is the classical area weigthed average of the normals of the faces incident on v. /// Not normalized. Use PerFaceNormalized() or call NormalizePerVertex() if you need unit length per face normals.
*/ static void PerFace(ComputeMeshType &m)
static void PerVertex(ComputeMeshType &m)
{ {
PerVertexClear(m); if(!HasPerFaceNormal(m)) throw vcg::MissingComponentException();
FaceIterator f; for(FaceIterator f=m.face.begin();f!=m.face.end();++f)
for(f=m.face.begin();f!=m.face.end();++f) if( !(*f).IsD() ) face::ComputeNormal(*f);
if( !(*f).IsD() && (*f).IsR() ) }
/// \brief Calculates the vertex normal by averaging the current per-face normals.
/**
The normal of a vertex v is the average of the un-normalized normals of the faces incident on v.
*/
static void PerVertexFromCurrentFaceNormal(ComputeMeshType &m)
{
if(!HasPerVertexNormal(m)) throw vcg::MissingComponentException();
VertexIterator vi;
for(vi=m.vert.begin();vi!=m.vert.end();++vi)
if( !(*vi).IsD() && (*vi).IsRW() )
(*vi).N()=CoordType(0,0,0);
FaceIterator fi;
for(fi=m.face.begin();fi!=m.face.end();++fi)
if( !(*fi).IsD())
{ {
//typename FaceType::NormalType t = (*f).Normal();
typename FaceType::NormalType t = vcg::Normal(*f);
for(int j=0; j<3; ++j) for(int j=0; j<3; ++j)
if( !(*f).V(j)->IsD() && (*f).V(j)->IsRW() ) if( !(*fi).V(j)->IsD())
(*f).V(j)->N() += t; (*fi).V(j)->N() += (*fi).cN();
} }
} }
/// \brief Calculates the face normal by averaging the current per-vertex normals.
/// \brief Calculates both vertex and face normals.
/** /**
The normal of a vertex v is the weigthed average of the normals of the faces incident on v. The normal of a face f is the average of the normals of the vertices of f.
*/ */
static void PerFaceFromCurrentVertexNormal(ComputeMeshType &m)
static void PerVertexPerFace(ComputeMeshType &m)
{ {
PerFace(m); if(!HasPerVertexNormal(m) || !HasPerFaceNormal(m)) throw vcg::MissingComponentException();
PerVertexClear(m); for (FaceIterator fi=m.face.begin(); fi!=m.face.end(); ++fi)
for(FaceIterator f=m.face.begin();f!=m.face.end();++f) if( !(*fi).IsD())
if( !(*f).IsD() && (*f).IsR() ) {
{ NormalType n;
for(int j=0; j<3; ++j) n.SetZero();
if( !(*f).V(j)->IsD() && (*f).V(j)->IsRW() ) for(int j=0; j<3; ++j)
(*f).V(j)->N() += (*f).cN(); n += fi->V(j)->cN();
} n.Normalize();
fi->N() = n;
}
} }
/// \brief Calculates both vertex and face normals.
/**
The normal of a vertex v is the weigthed average of the normals of the faces incident on v.
*/
static void PerVertexNormalizedPerFace(ComputeMeshType &m)
{
PerVertexPerFace(m);
NormalizeVertex(m);
}
/// \brief Normalize the lenght of the face normals. /// \brief Normalize the length of the vertex normals.
static void NormalizeVertex(ComputeMeshType &m) static void NormalizePerVertex(ComputeMeshType &m)
{ {
if(!HasPerVertexNormal(m)) throw vcg::MissingComponentException(); if(!HasPerVertexNormal(m)) throw vcg::MissingComponentException();
for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi) for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
@ -240,15 +212,16 @@ static void NormalizeVertex(ComputeMeshType &m)
(*vi).N().Normalize(); (*vi).N().Normalize();
} }
/// \brief Normalize the lenght of the face normals. /// \brief Normalize the length of the face normals.
static void NormalizeFace(ComputeMeshType &m) static void NormalizePerFace(ComputeMeshType &m)
{ {
if(!HasPerFaceNormal(m)) throw vcg::MissingComponentException(); if(!HasPerFaceNormal(m)) throw vcg::MissingComponentException();
for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi) for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
if( !(*fi).IsD() ) (*fi).N().Normalize(); if( !(*fi).IsD() ) (*fi).N().Normalize();
} }
static void AreaNormalizeFace(ComputeMeshType &m) /// \brief Set the length of the face normals to their area (without recomputing their directions).
static void NormalizePerFaceByArea(ComputeMeshType &m)
{ {
if(!HasPerFaceNormal(m)) throw vcg::MissingComponentException(); if(!HasPerFaceNormal(m)) throw vcg::MissingComponentException();
FaceIterator fi; FaceIterator fi;
@ -260,53 +233,44 @@ static void AreaNormalizeFace(ComputeMeshType &m)
} }
} }
/// \brief Equivalent to PerVertex() and NormalizePerVertex()
static void PerVertexNormalized(ComputeMeshType &m)
{
PerVertex(m);
NormalizePerVertex(m);
}
/// \brief Equivalent to PerFace() and NormalizePerVertex()
static void PerFaceNormalized(ComputeMeshType &m)
{
PerFace(m);
NormalizePerFace(m);
}
/// \brief Equivalent to PerVertex() and PerFace().
static void PerVertexPerFace(ComputeMeshType &m)
{
PerFace(m);
PerVertex(m);
}
/// \brief Equivalent to PerVertexNormalized() and PerFace().
static void PerVertexNormalizedPerFace(ComputeMeshType &m)
{
PerVertexPerFace(m);
NormalizePerVertex(m);
}
/// \brief Equivalent to PerVertexNormalizedPerFace() and NormalizePerFace().
static void PerVertexNormalizedPerFaceNormalized(ComputeMeshType &m) static void PerVertexNormalizedPerFaceNormalized(ComputeMeshType &m)
{ {
PerVertexNormalizedPerFace(m); PerVertexNormalizedPerFace(m);
NormalizeFace(m); NormalizePerFace(m);
}
static void PerFaceRW(ComputeMeshType &m, bool normalize=false)
{
if(!HasPerFaceNormal(m)) throw vcg::MissingComponentException();
FaceIterator f;
bool cn = true;
if(normalize)
{
for(f=m.m.face.begin();f!=m.m.face.end();++f)
if( !(*f).IsD() && (*f).IsRW() )
{
for(int j=0; j<3; ++j)
if( !(*f).V(j)->IsR()) cn = false;
if( cn ) face::ComputeNormalizedNormal(*f);
cn = true;
}
}
else
{
for(f=m.m.face.begin();f!=m.m.face.end();++f)
if( !(*f).IsD() && (*f).IsRW() )
{
for(int j=0; j<3; ++j)
if( !(*f).V(j)->IsR()) cn = false;
if( cn )
(*f).ComputeNormal();
cn = true;
}
}
} }
static void PerFaceNormalized(ComputeMeshType &m) /// \brief
{
if(!HasPerFaceNormal(m)) throw vcg::MissingComponentException();
FaceIterator f;
for(f=m.face.begin();f!=m.face.end();++f)
if( !(*f).IsD() ) face::ComputeNormalizedNormal(*f);
}
static void PerBitQuadFaceNormalized(ComputeMeshType &m) static void PerBitQuadFaceNormalized(ComputeMeshType &m)
{ {
PerFace(m); PerFace(m);
@ -322,15 +286,6 @@ static void PerBitQuadFaceNormalized(ComputeMeshType &m)
} }
/// \brief Calculates the vertex normal.
static void PerVertexNormalized(ComputeMeshType &m)
{
PerVertex(m);
for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
if( !(*vi).IsD() && (*vi).IsRW() )
(*vi).N().Normalize();
}
/// \brief Multiply the vertex normals by the matrix passed. By default, the scale component is removed. /// \brief Multiply the vertex normals by the matrix passed. By default, the scale component is removed.
static void PerVertexMatrix(ComputeMeshType &m, const Matrix44<ScalarType> &mat, bool remove_scaling= true) static void PerVertexMatrix(ComputeMeshType &m, const Matrix44<ScalarType> &mat, bool remove_scaling= true)
{ {
@ -374,6 +329,74 @@ static void PerFaceMatrix(ComputeMeshType &m, const Matrix44<ScalarType> &mat, b
(*fi).N() = mat33* (*fi).N(); (*fi).N() = mat33* (*fi).N();
} }
/// \brief Compute per wedge normals taking into account the angle between adjacent faces.
///
/// The PerWedge normals are averaged on common vertexes only if the angle between two faces is \b larger than \p angleRad.
/// It requires FFAdjacency.
static void PerWedgeCrease(ComputeMeshType &m, ScalarType angleRad)
{
if(!HasPerWedgeNormal(m) ) throw vcg::MissingComponentException();
if(!HasFFAdjacency(m)) throw vcg::MissingComponentException();
ScalarType cosangle=Cos(angleRad);
// Clear the per wedge normals
for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD())
{
(*fi).WN(0)=NormalType(0,0,0);
(*fi).WN(1)=NormalType(0,0,0);
(*fi).WN(2)=NormalType(0,0,0);
}
for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD())
{
NormalType nn= vcg::Normal(*fi);
for(int i=0;i<3;++i)
{
const NormalType &na=vcg::Normal(*(*fi).FFp(i));
if(nn*na > cosangle )
{
fi->WN((i+0)%3) +=na;
fi->WN((i+1)%3) +=na;
}
}
}
}
static void PerFaceRW(ComputeMeshType &m, bool normalize=false)
{
if(!HasPerFaceNormal(m)) throw vcg::MissingComponentException();
FaceIterator f;
bool cn = true;
if(normalize)
{
for(f=m.m.face.begin();f!=m.m.face.end();++f)
if( !(*f).IsD() && (*f).IsRW() )
{
for(int j=0; j<3; ++j)
if( !(*f).V(j)->IsR()) cn = false;
if( cn ) face::ComputeNormalizedNormal(*f);
cn = true;
}
}
else
{
for(f=m.m.face.begin();f!=m.m.face.end();++f)
if( !(*f).IsD() && (*f).IsRW() )
{
for(int j=0; j<3; ++j)
if( !(*f).V(j)->IsR()) cn = false;
if( cn )
(*f).ComputeNormal();
cn = true;
}
}
}
}; // end class }; // end class
} // End namespace } // End namespace