Commit 40905ac4 authored by Martin Heistermann's avatar Martin Heistermann
Browse files

Extend ACG BSPTree to support OpenVolumeMesh meshes with face valence 3

parent d46f1884
......@@ -37,7 +37,13 @@ if (NOT OPENMESH_FOUND)
message (FATAL_ERROR "OpenMesh not found!")
endif ()
find_package(OpenVolumeMesh)
if(NOT OPENVOLUMEMESH_FOUND)
message (INFO "OpenVolumeMesh not found, building without OVM support.")
endif()
set(INCLUDE_DIRS ${OPENMESH_INCLUDE_DIRS}
${OPENVOLUMEMESH_INCLUDE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/ShaderUtils
${CMAKE_CURRENT_BINARY_DIR}
......@@ -86,6 +92,7 @@ set (directories
Geometry
Config
Geometry/Types
Geometry/bsp
GL
Glut
IO
......
......@@ -68,16 +68,16 @@
//== CLASS DEFINITION =========================================================
// Node of the tree: contains parent, children and splitting plane
template <class Mesh>
template <class BSPTraits>
struct TreeNode
{
typedef typename Mesh::FaceHandle Handle;
typedef typename Mesh::Point Point;
typedef typename Mesh::VertexHandle VertexHandle;
typedef std::vector<Handle> Handles;
typedef typename Handles::iterator HandleIter;
typedef typename Point::value_type Scalar;
typedef ACG::Geometry::PlaneT<Scalar> Plane;
typedef typename BSPTraits::Handle Handle;
typedef typename BSPTraits::Point Point;
typedef typename BSPTraits::VertexHandle VertexHandle;
typedef std::vector<Handle> Handles;
typedef typename Handles::iterator HandleIter;
typedef typename Point::value_type Scalar;
typedef ACG::Geometry::PlaneT<Scalar> Plane;
TreeNode(const Handles& _handles, TreeNode* _parent)
: handles_(_handles),
......@@ -194,10 +194,10 @@ struct TreeNode
};
template<class Mesh>
std::ostream &operator<< (std::ostream &stream, const TreeNode<Mesh> &node) {
template<class BSPTraits>
std::ostream &operator<< (std::ostream &stream, const TreeNode<BSPTraits> &node) {
stream << "[TreeNode instance. Handles: ";
for (typename std::vector<typename TreeNode<Mesh>::Handle>::const_iterator it = node.handles_.begin(), it_end = node.handles_.end();
for (typename TreeNode<BSPTraits>::Handles::const_iterator it = node.handles_.begin(), it_end = node.handles_.end();
it != it_end; ++it) {
stream << it->idx();
if (it < it_end-1) stream << ", ";
......
......@@ -66,8 +66,8 @@
#include "TriangleBSPCoreT.hh"
#include "BSPImplT.hh"
//== CLASS DEFINITION =========================================================
#include <list>
//== CLASS DEFINITION =========================================================
template <class BSPTraits>
class TriangleBSPT : public BSPImplT< TriangleBSPCoreT<BSPTraits> >
......@@ -81,129 +81,144 @@ public:
//== CLASS DEFINITION =========================================================
template <class Mesh>
class OpenMeshTriangleBSPTraits
template <class Mesh, class SpecificTraits>
class OVMOMCommonBSPTraits : public SpecificTraits
{
public:
typedef typename Mesh::Scalar Scalar;
typedef typename Mesh::Point Point;
typedef typename Mesh::FaceHandle Handle;
typedef std::vector<Handle> Handles;
typedef typename Handles::iterator HandleIter;
typedef TreeNode<Mesh> Node;
typedef typename SpecificTraits::Point Point;
typedef typename SpecificTraits::Handle Handle;
typedef typename Point::value_type Scalar;
typedef std::vector<Handle> Handles;
typedef typename Handles::iterator HandleIter;
typedef TreeNode<SpecificTraits> Node;
OpenMeshTriangleBSPTraits(const Mesh& _mesh) : mesh_(_mesh) {}
OVMOMCommonBSPTraits(const Mesh& _mesh) : SpecificTraits(_mesh) {}
/// Returns the points belonging to the face handle _h
inline void points(const Handle _h, Point& _p0, Point& _p1, Point& _p2) const
{
typename Mesh::CFVIter fv_it(mesh_.cfv_iter(_h));
_p0 = mesh_.point(*fv_it);
++fv_it;
_p1 = mesh_.point(*fv_it);
++fv_it;
_p2 = mesh_.point(*fv_it);
}
Scalar sqrdist(const Handle _h, const Point& _p) const
{
Point p0, p1, p2, q;
points(_h, p0, p1, p2);
return ACG::Geometry::distPointTriangleSquaredStable(_p, p0, p1, p2, q);
}
void calculateBoundingBox(Node* _node, Point& median, int& axis)
{
//determine splitting axis
HandleIter it_h;
Point p0, p1, p2, bb_min, bb_max;
bb_min.vectorize(std::numeric_limits<typename Point::value_type>::infinity());
bb_max.vectorize(-std::numeric_limits<typename Point::value_type>::infinity());
std::list<Point> vertices;
for (it_h = _node->begin(); it_h != _node->end(); ++it_h) {
points(*it_h, p0, p1, p2);
/*
bb_min.minimize(p0);
bb_min.minimize(p1);
bb_min.minimize(p2);
bb_max.maximize(p0);
bb_max.maximize(p1);
bb_max.maximize(p2);*/
vertices.push_back(p0);
vertices.push_back(p1);
vertices.push_back(p2);
}
bb_min = _node->bb_min;
bb_max = _node->bb_max;
// split longest side of bounding box
Point bb = bb_max - bb_min;
Scalar length = bb[0];
axis = 0;
if (bb[1] > length)
length = bb[(axis = 1)];
if (bb[2] > length)
length = bb[(axis = 2)];
//calculate the median value in axis-direction
switch (axis) {
case 0:
vertices.sort(x_sort());
break;
case 1:
vertices.sort(y_sort());
break;
case 2:
vertices.sort(z_sort());
break;
Scalar sqrdist(const Handle _h, const Point& _p) const
{
Point p0, p1, p2, q;
this->points(_h, p0, p1, p2);
return ACG::Geometry::distPointTriangleSquaredStable(_p, p0, p1, p2, q);
}
vertices.unique(); ///todo: does this work with Points?!
size_t size = vertices.size();
typename std::list<Point>::iterator it_v;
it_v = vertices.begin();
std::advance(it_v, size / 2);
median = *it_v;
void calculateBoundingBox(Node* _node, Point& median, int& axis)
{
//determine splitting axis
HandleIter it_h;
Point p0, p1, p2, bb_min, bb_max;
bb_min.vectorize(std::numeric_limits<typename Point::value_type>::infinity());
bb_max.vectorize(-std::numeric_limits<typename Point::value_type>::infinity());
std::list<Point> vertices;
for (it_h = _node->begin(); it_h != _node->end(); ++it_h) {
this->points(*it_h, p0, p1, p2);
/*
bb_min.minimize(p0);
bb_min.minimize(p1);
bb_min.minimize(p2);
bb_max.maximize(p0);
bb_max.maximize(p1);
bb_max.maximize(p2);*/
vertices.push_back(p0);
vertices.push_back(p1);
vertices.push_back(p2);
}
bb_min = _node->bb_min;
bb_max = _node->bb_max;
// split longest side of bounding box
Point bb = bb_max - bb_min;
Scalar length = bb[0];
axis = 0;
if (bb[1] > length)
length = bb[(axis = 1)];
if (bb[2] > length)
length = bb[(axis = 2)];
//calculate the median value in axis-direction
switch (axis) {
case 0:
vertices.sort(x_sort());
break;
case 1:
vertices.sort(y_sort());
break;
case 2:
vertices.sort(z_sort());
break;
}
vertices.unique(); ///todo: does this work with Points?!
size_t size = vertices.size();
typename std::list<Point>::iterator it_v;
it_v = vertices.begin();
std::advance(it_v, size / 2);
median = *it_v;
}
}
void calculateBoundingBoxRoot(Node* _node)
{
HandleIter it;
Point p0, p1, p2, bb_min, bb_max;
bb_min.vectorize(FLT_MAX);
bb_max.vectorize(-FLT_MAX);
for (it = _node->begin(); it != _node->end(); ++it) {
points(*it, p0, p1, p2);
bb_min.minimize(p0);
bb_min.minimize(p1);
bb_min.minimize(p2);
bb_max.maximize(p0);
bb_max.maximize(p1);
bb_max.maximize(p2);
void calculateBoundingBoxRoot(Node* _node)
{
HandleIter it;
Point p0, p1, p2, bb_min, bb_max;
bb_min.vectorize(FLT_MAX);
bb_max.vectorize(-FLT_MAX);
for (it = _node->begin(); it != _node->end(); ++it) {
this->points(*it, p0, p1, p2);
bb_min.minimize(p0);
bb_min.minimize(p1);
bb_min.minimize(p2);
bb_max.maximize(p0);
bb_max.maximize(p1);
bb_max.maximize(p2);
}
_node->bb_min = bb_min;
_node->bb_max = bb_max;
}
_node->bb_min = bb_min;
_node->bb_max = bb_max;
}
private:
const Mesh& mesh_;
//functors for sorting in different directions
struct x_sort { bool operator()(const Point& first, const Point& second) { return (first[0] < second[0]); } };
struct y_sort { bool operator()(const Point& first, const Point& second) { return (first[1] < second[1]); } };
struct z_sort { bool operator()(const Point& first, const Point& second) { return (first[2] < second[2]); } };
//functors for sorting in different directions
struct x_sort { bool operator()(const Point& first, const Point& second) { return (first[0] < second[0]); } };
struct y_sort { bool operator()(const Point& first, const Point& second) { return (first[1] < second[1]); } };
struct z_sort { bool operator()(const Point& first, const Point& second) { return (first[2] < second[2]); } };
};
//== CLASS DEFINITION =========================================================
template <class Mesh>
class OMSpecificTriangleBSPTraits
{
public:
typedef typename Mesh::Point Point;
typedef typename Mesh::FaceHandle Handle;
typedef typename Mesh::VertexHandle VertexHandle;
OMSpecificTriangleBSPTraits(const Mesh& _mesh) : mesh_(_mesh) {}
/// Returns the points belonging to the face handle _h
inline void points(const Handle &_h, Point& _p0, Point& _p1, Point& _p2) const
{
const auto &mesh = this->mesh_;
typename Mesh::CFVIter fv_it(mesh.cfv_iter(_h));
_p0 = mesh.point(*fv_it);
++fv_it;
_p1 = mesh.point(*fv_it);
++fv_it;
_p2 = mesh.point(*fv_it);
}
protected:
const Mesh& mesh_;
};
template<class Mesh>
using OpenMeshTriangleBSPTraits = OVMOMCommonBSPTraits<Mesh, OMSpecificTriangleBSPTraits<Mesh>>;
//== CLASS DEFINITION =========================================================
template <class Mesh>
class OpenMeshTriangleBSPT
class OpenMeshTriangleBSPT
: public TriangleBSPT<OpenMeshTriangleBSPTraits<Mesh> >
{
public:
......@@ -211,9 +226,65 @@ public:
typedef TriangleBSPT<Traits> Base;
typedef typename Traits::Scalar Scalar;
OpenMeshTriangleBSPT(const Mesh& _mesh,
const Scalar& _infinity = std::numeric_limits<Scalar>::infinity()) : Base(Traits(_mesh), _infinity) {}
const Scalar& _infinity = std::numeric_limits<Scalar>::infinity())
: Base(Traits(_mesh), _infinity) {}
};
#ifdef ENABLE_OPENVOLUMEMESH
namespace OpenVolumeMesh {
class VertexHandle;
class FaceHandle;
}
//== CLASS DEFINITION =========================================================
// Make sure all faces of the mesh have valence 3.
template <class Mesh>
class OVMSpecificTriangleBSPTraits
{
public:
typedef typename Mesh::PointT Point;
typedef OpenVolumeMesh::FaceHandle Handle;
typedef OpenVolumeMesh::VertexHandle VertexHandle;
OVMSpecificTriangleBSPTraits(const Mesh& _mesh) : mesh_(_mesh) {}
/// Returns the points belonging to the face handle _h
inline void points(const Handle &_h, Point& _p0, Point& _p1, Point& _p2) const
{
const auto &mesh = this->mesh_;
assert(mesh.valence(_h) == 3);
auto hfv_it (mesh.hfv_iter(mesh.halfface_handle(_h, 0)));
_p0 = mesh.vertex(*hfv_it++);
_p1 = mesh.vertex(*hfv_it++);
_p2 = mesh.vertex(*hfv_it++);
}
protected:
const Mesh& mesh_;
};
template<class Mesh>
using OpenVolumeMeshTriangleBSPTraits = OVMOMCommonTriangleBSPTraits<Mesh, OVMSpecificTriangleBSPTraits<Mesh>>;
//== CLASS DEFINITION =========================================================
template <class Mesh>
class OpenVolumeMeshTriangleBSPT
: public TriangleBSPT<OpenVolumeMeshTriangleBSPTraits<Mesh> >
{
public:
typedef OpenVolumeMeshTriangleBSPTraits<Mesh> Traits;
typedef TriangleBSPT<Traits> Base;
typedef typename Traits::Scalar Scalar;
OpenVolumeMeshTriangleBSPT(const Mesh& _mesh,
const Scalar& _infinity = std::numeric_limits<Scalar>::infinity())
: Base(Traits(_mesh), _infinity) {}
};
#endif // ENABLE_OPENVOLUMEMESH
//=============================================================================
#endif // MB_TRIANGLEBSP_HH defined
//=============================================================================
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment