HalfEdge& Triangle::GetHalfEdge(const FullEdge &FullE) const
{
for(UINT EdgeIndex = 0; EdgeIndex < 3; EdgeIndex++)
{
if(GetFullEdge(EdgeIndex) == FullE)
{
return *(_HalfEdges[EdgeIndex]);
}
}
SignalError("Triangle::GetHalfEdge edge not found.");
return HalfEdge::Invalid;
}
Vertex& Triangle::GetOtherVertex(const FullEdge &FullE) const
{
for(UINT VertexIndex = 0; VertexIndex < 3; VertexIndex++)
{
Vertex &CurVertex = *(_Vertices[VertexIndex]);
if(CurVertex != FullE.GetVertex(0) && CurVertex != FullE.GetVertex(1))
{
return CurVertex;
}
}
SignalError("Triangle::GetOtherVertex vertex not found.");
return Vertex::Invalid;
}
bool Triangle::ContainsEdge(const FullEdge &FullE) const
{
for(UINT i = 0; i < 3; i++)
{
if(GetFullEdge(i) == FullE)
{
return true;
}
}
return false;
}
bool Triangle::ContainsVertex(const Vertex &Vtx) const
{
for(UINT VertexIndex = 0; VertexIndex < 3; VertexIndex++)
{
if(GetVertex(VertexIndex) == Vtx)
{
return true;
}
}
return false;
}
bool Triangle::BordersTriangle(const Triangle &T) const
{
for(UINT TriangleIndex = 0; TriangleIndex < 3; TriangleIndex++)
{
if(GetNeighboringTriangle(TriangleIndex) == T)
{
return true;
}
}
return false;
}
FullEdge& Triangle::GetOtherEdge(const Vertex &Vtx) const
{
for(UINT EdgeIndex = 0; EdgeIndex < 3; EdgeIndex++)
{
FullEdge &CurFullEdge = _HalfEdges[EdgeIndex]->AcrossEdge();
if(!CurFullEdge.ContainsVertex(Vtx))
{
return CurFullEdge;
}
}
SignalError("Triangle::GetOtherEdge duplicity error.");
return FullEdge::Invalid;
}
FullEdge& Triangle::GetSharedEdge(const Triangle &T) const
{
for(UINT EdgeIndex = 0; EdgeIndex < 3; EdgeIndex++)
{
FullEdge &CurFullEdge = _HalfEdges[EdgeIndex]->AcrossEdge();
if(CurFullEdge.GetOtherTriangle(*this) == T)
{
return CurFullEdge;
}
}
SignalError("Triangle::GetSharedEdge fatal error.");
return FullEdge::Invalid;
}
FullEdge& Triangle::GetSharedEdge(const Vertex &V1, const Vertex &V2) const
{
for(UINT EdgeIndex = 0; EdgeIndex < 3; EdgeIndex++)
{
FullEdge &CurFullEdge = _HalfEdges[EdgeIndex]->AcrossEdge();
if(CurFullEdge.ContainsVertex(V1) && CurFullEdge.ContainsVertex(V2))
{
return CurFullEdge;
}
}
SignalError("Triangle::GetSharedEdge fatal error.");
return FullEdge::Invalid;
}
float Triangle::Area() const
{
Vec3f V1 = GetVertex(1).Pos() - GetVertex(0).Pos();
Vec3f V2 = GetVertex(2).Pos() - GetVertex(0).Pos();
return 0.5f * Vec3f::Cross(V1, V2).Length();
}
Vec3f Triangle::Center() const
{
return (GetVertex(0).Pos() + GetVertex(1).Pos() + GetVertex(2).Pos()) / 3.0f;
}
bool Triangle::IsBoundary() const
{
return (GetFullEdge(0).Boundary() ||
GetFullEdge(1).Boundary() ||
GetFullEdge(2).Boundary());
}
bool Triangle::OrientedWith(const FullEdge &FullE) const
{
UINT Index0 = GetVertexLocalIndex(FullE.GetVertex(0));
UINT Index1 = GetVertexLocalIndex(FullE.GetVertex(1));
return (Index1 == (Index0 + 1) % 3);
}
Vec3f Triangle::Normal() const
{
Vec3f V1 = _Vertices[1]->Pos() - _Vertices[0]->Pos();
Vec3f V2 = _Vertices[2]->Pos() - _Vertices[0]->Pos();
return Vec3f::Normalize(Vec3f::Cross(V1, V2));
}
UINT Triangle::GetVertexLocalIndex(const Vertex &VCompare) const
{
for(UINT i = 0; i < 3; i++)
{
if(GetVertex(i) == VCompare)
{
return i;
}
}
SignalError("Triangle::GetVertexIndex Fatal Error.");
return UINT(-1);
}
double Triangle::GetAngle(const Vertex &Vtx) const
{
UINT BaseIndex = GetVertexLocalIndex(Vtx);
Vec3f E1 = _Vertices[(BaseIndex + 1) % 3]->Pos() - Vtx.Pos();
Vec3f E2 = _Vertices[(BaseIndex + 2) % 3]->Pos() - Vtx.Pos();
return Vec3f::AngleBetween(E1, E2);
}
double Triangle::GetCotangent(const Vertex &Vtx) const
{
UINT BaseIndex = GetVertexLocalIndex(Vtx);
Vec3f E1 = _Vertices[(BaseIndex + 1) % 3]->Pos() - Vtx.Pos();
Vec3f E2 = _Vertices[(BaseIndex + 2) % 3]->Pos() - Vtx.Pos();
double Denominator = Vec3f::Dot(Vec3f::Cross(E1, E2), Normal());
if(Denominator == 0.0f)
{
return 0.0f;
}
else
{
return Vec3f::Dot(E1, E2) / Denominator;
}
}
float Triangle::ThetaFromTangent(const Vec3f &V) const
{
Vec3f MyNormal = Normal(), Tangent1, Tangent2;
Vec3f::CompleteOrthonormalBasis(MyNormal, Tangent1, Tangent2);
float Theta = Vec3f::AngleBetween(V, Tangent1);
if(Vec3f::Dot(Vec3f::Cross(Tangent1, V), MyNormal) > 0.0f)
{
return Theta;
}
else
{
return -Theta;
}
}
Vec3f Triangle::TangentFromTheta(float Theta) const
{
Vec3f MyNormal = Normal(), Tangent1, Tangent2;
Vec3f::CompleteOrthonormalBasis(MyNormal, Tangent1, Tangent2);
Matrix4 Rotation = Matrix4::Rotation(MyNormal, Theta);
return Rotation.TransformNormal(Tangent1);
}
Vec3f Triangle::EvaluateVFieldGradient(const Vector<double> &OneForm, float v, float w) const
{
Matrix4 Transform = Matrix4::Face(Normal(), Vec3f::eZ) * Matrix4::Translation(-Center());
Vec3f V[3];
for(UINT VertexIndex = 0; VertexIndex < 3; VertexIndex++)
{
V[VertexIndex] = Transform.TransformPoint(_Vertices[VertexIndex]->Pos());
}
float a = float(OneForm[_HalfEdges[0]->AcrossEdge().Index()]);
float b = float(OneForm[_HalfEdges[1]->AcrossEdge().Index()]);
float c = float(OneForm[_HalfEdges[2]->AcrossEdge().Index()]);
if(!OrientedWith(_HalfEdges[0]->AcrossEdge()))
{
a = -a;
}
if(!OrientedWith(_HalfEdges[1]->AcrossEdge()))
{
b = -b;
}
if(!OrientedWith(_HalfEdges[2]->AcrossEdge()))
{
c = -c;
}
float NumX = V[0].y * a + V[1].y * b + V[2].y * c;
float DenomX = (V[1].x*V[0].y - V[2].x*V[0].y - V[0].x*V[1].y + V[2].x*V[1].y + V[0].x*V[2].y - V[1].x*V[2].y);
float NumY = V[0].x * a + V[1].x * b + V[2].x * c;
float DenomY = (V[2].x*(V[0].y - V[1].y) + V[0].x*(V[1].y - V[2].y) + V[1].x*(-V[0].y + V[2].y));
Vec3f Gradient = Vec3f::Origin;
if(DenomX != 0.0f)
{
Gradient.x = NumX / DenomX;
}
if(DenomY != 0.0f)
{
Gradient.y = NumY / DenomY;
}
return Transform.Inverse().TransformNormal(Gradient);
}
Vec3f Triangle::EvaluateVField(const Vector<double> &OneForm, float v, float w) const
{
Matrix4 Rotation = Matrix4::Rotation(Normal(), Math::PIf / 2.0f);
Vec3f ab = _Vertices[1]->Pos() - _Vertices[0]->Pos();
Vec3f ac = _Vertices[2]->Pos() - _Vertices[0]->Pos();
ab = Rotation.TransformNormal(ab);
ac = Rotation.TransformNormal(ac);
float a = float(OneForm[_HalfEdges[0]->AcrossEdge().Index()]);
float b = float(OneForm[_HalfEdges[1]->AcrossEdge().Index()]);
float c = float(OneForm[_HalfEdges[2]->AcrossEdge().Index()]);
if(!OrientedWith(_HalfEdges[0]->AcrossEdge()))
{
a = -a;
}
if(!OrientedWith(_HalfEdges[1]->AcrossEdge()))
{
b = -b;
}
if(!OrientedWith(_HalfEdges[2]->AcrossEdge()))
{
c = -c;
}
float abc = a + b + c;
return ((v * abc - b) * ab + (w * abc - c) * ac) / (2.0f * Area());
}