void Vertex::LoadVertices()
{
_Vertices.FreeMemory();
for(UINT i = 0; i < _Triangles.Length(); i++)
{
for(UINT i2 = 0; i2 < 3; i2++)
{
Vertex &VertexToConsider = _Triangles[i]->GetVertex(i2);
if(VertexToConsider != *this)
{
bool Add = true;
for(UINT i3 = 0; i3 < _Vertices.Length(); i3++)
{
if(*(_Vertices[i3]) == VertexToConsider)
{
Add = false;
}
}
if(Add)
{
_Vertices.PushEnd(&VertexToConsider);
}
}
}
}
}
FullEdge& Vertex::GetSharedEdge(const Vertex &OtherVertex) const
{
for(UINT i = 0; i < _Triangles.Length(); i++)
{
if(_Triangles[i]->ContainsVertex(OtherVertex))
{
return _Triangles[i]->GetSharedEdge(*this, OtherVertex);
}
}
SignalError("GetSharedEdge failed");
return FullEdge::Invalid;
}
double Vertex::GaussianCurvature() const
{
double AngleSum = 0.0f;
for(UINT TriangleIndex = 0; TriangleIndex < Triangles().Length(); TriangleIndex++)
{
Triangle &CurTriangle = *(_Triangles[TriangleIndex]);
AngleSum += CurTriangle.GetAngle(*this);
}
return 2.0 * Math::PI - AngleSum;
}
double Vertex::ComputeTriangleArea()
{
double TriangleArea = 0.0f;
for(UINT TriangleIndex = 0; TriangleIndex < Triangles().Length(); TriangleIndex++)
{
TriangleArea += _Triangles[TriangleIndex]->Area();
}
return TriangleArea;
}
Vec3f Vertex::MeanCurvatureNormal()
{
Vec3f MeanCurvature = Vec3f::Origin;
float ConstantTerm = 0.0f;
for(UINT EdgeIndex = 0; EdgeIndex < Vertices().Length(); EdgeIndex++)
{
Vertex &OtherVertex = *(_Vertices[EdgeIndex]);
FullEdge &CurEdge = GetSharedEdge(OtherVertex);
float ConstantFactor = float(CurEdge.GetCotanTerm());
Assert(ConstantFactor == ConstantFactor, "ConstantFactor invalid");
MeanCurvature += ConstantFactor * (_Pos - OtherVertex.Pos());
ConstantTerm += ConstantFactor;
}
return MeanCurvature / ConstantTerm;
}
Vec3f Vertex::AreaWeightedNormal() const
{
Vec3f Normal = Vec3f::Origin;
for(UINT TriangleIndex = 0; TriangleIndex < _Triangles.Length(); TriangleIndex++)
{
Triangle &CurTriangle = *(_Triangles[TriangleIndex]);
Normal += CurTriangle.Area() * CurTriangle.Normal();
}
return Vec3f::Normalize(Normal);
}
Vec3f Vertex::EvaluateVField(const Vector<double> &OneForm) const
{
Vec3f Result = Vec3f::Origin;
float Magnitude = 0.0f;
float AreaSum = 0.0f;
for(UINT TriangleIndex = 0; TriangleIndex < _Triangles.Length(); TriangleIndex++)
{
Triangle &CurTriangle = *(_Triangles[TriangleIndex]);
float CurArea = float(CurTriangle.Area());
AreaSum += CurArea;
float Ratio1 = 0.0f;
float Ratio2 = 0.0f;
UINT Index = CurTriangle.GetVertexLocalIndex(*this);
if(Index == 1)
{
Ratio1 = 1.0f;
}
else if(Index == 2)
{
Ratio2 = 1.0f;
}
Vec3f VField = CurTriangle.EvaluateVField(OneForm, Ratio1, Ratio2);
Magnitude += CurArea * VField.Length();
Result += CurArea * Vec3f::Normalize(VField);
}
return Vec3f::Normalize(Result) * Magnitude / AreaSum;
}
bool Vertex::LocallyManifold()
{
if(!_Boundary)
{
return true;
}
UINT BoundaryEdgeCount = 0;
for(UINT VertexIndex = 0; VertexIndex < _Vertices.Length(); VertexIndex++)
{
Vertex *CurVertex = _Vertices[VertexIndex];
if(GetSharedEdge(*CurVertex).Boundary())
{
BoundaryEdgeCount++;
if(BoundaryEdgeCount > 2)
{
return false;
}
}
}
return true;
}
Vec3f Vertex::ComputeLoopSubdivisionPos()
{
Vec3f Result;
UINT n = _Vertices.Length();
if(Boundary())
{
Result = 0.75f * _Pos;
for(UINT i = 0; i < _Triangles.Length(); i++)
{
Triangle &CurTriangle = *(_Triangles[i]);
for(UINT i2 = 0; i2 < 3; i2++)
{
FullEdge &CurFullEdge = CurTriangle.GetFullEdge(i2);
if(CurFullEdge.Boundary() && CurFullEdge.ContainsVertex(*this))
{
Vertex &CurVertex = CurFullEdge.GetOtherVertex(*this);
Result += CurVertex.Pos() / 8.0f;
}
}
}
}
else
{
float Beta;
if(n == 3)
{
Beta = 3.0f / 16.0f;
}
else
{
Beta = 3.0f / (8.0f * n);
}
Result = (1.0f - n * Beta) * _Pos;
for(UINT i = 0; i < n; i++)
{
Result += _Vertices[i]->Pos() * Beta;
}
}
return Result;
}