180 lines
3.9 KiB
C++
180 lines
3.9 KiB
C++
// This source code is property of the Computer Graphics and Visualization
|
|
// chair of the TU Dresden. Do not distribute!
|
|
// Copyright (C) CGV TU Dresden - All Rights Reserved
|
|
|
|
#include "Triangle.h"
|
|
#include "GridUtils.h"
|
|
#include <tuple>
|
|
|
|
|
|
//default constructor
|
|
Triangle::Triangle()
|
|
{
|
|
}
|
|
//constructs a triangle using the vertex positions v0,v1 and v2
|
|
Triangle::Triangle(const Eigen::Vector3f& v0, const Eigen::Vector3f& v1,const Eigen::Vector3f& v2): v0(v0),v1(v1),v2(v2)
|
|
{
|
|
}
|
|
//constructs a triangle from the face f of the given halfedge mesh m
|
|
Triangle::Triangle(const HEMesh&m, const OpenMesh::FaceHandle& f):h(f)
|
|
{
|
|
OpenMesh::HalfedgeHandle he = m.halfedge_handle(f);
|
|
v0 = ToEigenVector(m.point(m.from_vertex_handle(he)));
|
|
he = m.next_halfedge_handle(he);
|
|
v1 = ToEigenVector(m.point(m.from_vertex_handle(he)));
|
|
he = m.next_halfedge_handle(he);
|
|
v2 = ToEigenVector(m.point(m.from_vertex_handle(he)));
|
|
}
|
|
//returns the smallest axis aligned bounding box of the triangle
|
|
Box Triangle::ComputeBounds() const
|
|
{
|
|
/* Task 3.2.2 */
|
|
Box b;
|
|
return b;
|
|
}
|
|
|
|
|
|
//returns true if the triangle overlaps the given box b
|
|
bool Triangle::Overlaps(const Box& b) const
|
|
{
|
|
/* Task 3.2.2 */
|
|
//carefully look at the interface of the box class, there might be a lot of useful helper functions
|
|
return true;
|
|
}
|
|
//returns the barycentric coordinates of the point with the smallest distance to point p which lies on the triangle
|
|
void Triangle::ClosestPointBarycentric(const Eigen::Vector3f& p, float& l0, float& l1, float& l2) const
|
|
{
|
|
Eigen::Vector3f edge0 = v1 - v0;
|
|
Eigen::Vector3f edge1 = v2 - v0;
|
|
Eigen::Vector3f v = v0 - p;
|
|
|
|
float a = edge0.dot( edge0 );
|
|
float b = edge0.dot( edge1 );
|
|
float c = edge1.dot( edge1 );
|
|
float d = edge0.dot( v );
|
|
float e = edge1.dot( v );
|
|
|
|
float det = a*c - b*b;
|
|
float s = b*e - c*d;
|
|
float t = b*d - a*e;
|
|
|
|
if ( s + t < det )
|
|
{
|
|
if ( s < 0.f )
|
|
{
|
|
if ( t < 0.f )
|
|
{
|
|
if ( d < 0.f )
|
|
{
|
|
s=-d/a;
|
|
s=std::min(std::max(s,0.0f),1.0f);
|
|
t = 0.f;
|
|
}
|
|
else
|
|
{
|
|
s = 0.f;
|
|
t = -e/c;
|
|
t = std::min(std::max(t,0.0f),1.0f);
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
s = 0.f;
|
|
t = -e/c;
|
|
t = std::min(std::max(t,0.0f),1.0f);
|
|
}
|
|
}
|
|
else if ( t < 0.f )
|
|
{
|
|
s = -d/a;
|
|
s=std::min(std::max(s,0.0f),1.0f);
|
|
t = 0.f;
|
|
}
|
|
else
|
|
{
|
|
float invDet = 1.f / det;
|
|
s *= invDet;
|
|
t *= invDet;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( s < 0.f )
|
|
{
|
|
float tmp0 = b+d;
|
|
float tmp1 = c+e;
|
|
if ( tmp1 > tmp0 )
|
|
{
|
|
float numer = tmp1 - tmp0;
|
|
float denom = a-2*b+c;
|
|
s = numer/denom;
|
|
s=std::min(std::max(s,0.0f),1.0f);
|
|
t = 1-s;
|
|
}
|
|
else
|
|
{
|
|
t = -e/c;
|
|
t=std::min(std::max(t,0.0f),1.0f);
|
|
s = 0.f;
|
|
}
|
|
}
|
|
else if ( t < 0.f )
|
|
{
|
|
if ( a+d > b+e )
|
|
{
|
|
float numer = c+e-b-d;
|
|
float denom = a-2*b+c;
|
|
s = numer/denom;
|
|
s=std::min(std::max(s,0.0f),1.0f);
|
|
|
|
t = 1-s;
|
|
}
|
|
else
|
|
{
|
|
s = -e/c;
|
|
s=std::min(std::max(s,0.0f),1.0f);
|
|
t = 0.f;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
float numer = c+e-b-d;
|
|
float denom = a-2*b+c;
|
|
|
|
s = numer/denom;
|
|
s=std::min(std::max(s,0.0f),1.0f);
|
|
t = 1.f - s;
|
|
}
|
|
}
|
|
l0 = 1-s-t;
|
|
l1 = s;
|
|
l2 = t;
|
|
}
|
|
//returns the point with smallest distance to point p which lies on the triangle
|
|
Eigen::Vector3f Triangle::ClosestPoint(const Eigen::Vector3f& p) const
|
|
{
|
|
float l0,l1,l2;
|
|
ClosestPointBarycentric(p,l0,l1,l2);
|
|
return l0*v0 + l1*v1 +l2* v2;
|
|
|
|
}
|
|
//returns the squared distance between point p and the triangle
|
|
float Triangle::SqrDistance(const Eigen::Vector3f& p) const
|
|
{
|
|
Eigen::Vector3f d = p-ClosestPoint(p);
|
|
return d.squaredNorm();
|
|
}
|
|
//returns the euclidean distance between point p and the triangle
|
|
float Triangle::Distance(const Eigen::Vector3f& p) const
|
|
{
|
|
return sqrt(SqrDistance(p));
|
|
}
|
|
//returns a reference point which is on the triangle and is used to sort the primitive in the AABB tree construction
|
|
Eigen::Vector3f Triangle::ReferencePoint() const
|
|
{
|
|
return (v0+v1+v2)/3.0f;
|
|
}
|
|
|
|
|
|
|