CGI/exercise4/src/Triangle.cpp

181 lines
3.9 KiB
C++
Raw Normal View History

2018-09-06 12:35:43 +00:00
// 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;
}