Commit 0e44cdcd authored by Hans-Christian Ebke's avatar Hans-Christian Ebke

Moved BSP into ACG.


git-svn-id: http://www.openflipper.org/svnrepo/OpenFlipper/branches/Free@14136 383ad7c9-94d9-4d36-a494-682f7c89f535
parent 0a13e88a
/*===========================================================================*\
* *
* OpenFlipper *
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
* www.openflipper.org *
* *
*--------------------------------------------------------------------------- *
* This file is part of OpenFlipper. *
* *
* OpenFlipper is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of *
* the License, or (at your option) any later version with the *
* following exceptions: *
* *
* If other files instantiate templates or use macros *
* or inline functions from this file, or you compile this file and *
* link it with other files to produce an executable, this file does *
* not by itself cause the resulting executable to be covered by the *
* GNU Lesser General Public License. This exception does not however *
* invalidate any other reasons why the executable file might be *
* covered by the GNU Lesser General Public License. *
* *
* OpenFlipper is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU LesserGeneral Public *
* License along with OpenFlipper. If not, *
* see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
/*===========================================================================*\
* *
* $Revision$ *
* $LastChangedBy$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// CLASS BSPImplT
//
//=============================================================================
#define BSPIMPLT_C
//== INCLUDES =================================================================
#include "BSPImplT.hh"
#include <float.h>
//== CLASS DEFINITION =========================================================
#include <vector>
template <class BSPCore>
typename BSPImplT<BSPCore>::NearestNeighbor
BSPImplT<BSPCore>::
nearest(const Point& _p) const
{
NearestNeighborData data;
data.ref = _p;
data.dist = FLT_MAX;
_nearest(this->root_, data);
return NearestNeighbor(data.nearest, sqrt(data.dist));
}
//-----------------------------------------------------------------------------
template <class BSPCore>
void
BSPImplT<BSPCore>::
_nearest(Node* _node, NearestNeighborData& _data) const
{
// terminal node
if (!_node->left_child_)
{
Scalar dist;
for (HandleIter it=_node->begin(); it!=_node->end(); ++it)
{
dist = this->traits_.sqrdist(*it, _data.ref);
if (dist < _data.dist)
{
_data.dist = dist;
_data.nearest = *it;
}
}
}
// non-terminal node
else
{
Scalar dist = _node->plane_.distance(_data.ref);
if (dist > 0.0)
{
_nearest(_node->left_child_, _data);
if (dist*dist < _data.dist)
_nearest(_node->right_child_, _data);
}
else
{
_nearest(_node->right_child_, _data);
if (dist*dist < _data.dist)
_nearest(_node->left_child_, _data);
}
}
}
//-----------------------------------------------------------------------------
template <class BSPCore>
typename BSPImplT<BSPCore>::RayCollision
BSPImplT<BSPCore>::
raycollision(const Point& _p, const Point& _r) const
{
RayCollisionData data;
data.ref = _p;
data.dist = FLT_MAX;
data.ray = _r;
data.hit_vertices.clear();
_raycollision(this->root_, data);
return RayCollision(data.nearest, data.dist, data.hit_vertices);
}
//-----------------------------------------------------------------------------
template <class BSPCore>
void
BSPImplT<BSPCore>::
_raycollision(Node* _node, RayCollisionData& _data) const
{
// terminal node
if (!_node->left_child_)
{
Scalar dist;
Point v0, v1, v2;
Scalar u, v;
for (HandleIter it=_node->begin(); it!=_node->end(); ++it)
{
this->traits_.points(*it, v0, v1, v2);
if (ACG::Geometry::triangleIntersection(_data.ref, _data.ray, v0, v1, v2, dist, u, v)) {
_data.hit_vertices.push_back(*it);
//face intersects with ray. But is it closer than any that we have found so far?
if (dist < _data.dist)
{
_data.dist = dist;
_data.nearest = *it;
}
}
}
}
// non-terminal node
else
{
Scalar tmin, tmax;
bool used = false;
if ( _node->left_child_ && ACG::Geometry::axisAlignedBBIntersection( _data.ref, _data.ray, _node->left_child_->bb_min, _node->left_child_->bb_max, tmin, tmax)) {
_raycollision(_node->left_child_, _data);
}
if ( _node->right_child_ && ACG::Geometry::axisAlignedBBIntersection( _data.ref, _data.ray, _node->right_child_->bb_min, _node->right_child_->bb_max, tmin, tmax)) {
_raycollision(_node->right_child_, _data);
}
}
}
//=============================================================================
\ No newline at end of file
/*===========================================================================*\
* *
* OpenFlipper *
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
* www.openflipper.org *
* *
*--------------------------------------------------------------------------- *
* This file is part of OpenFlipper. *
* *
* OpenFlipper is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of *
* the License, or (at your option) any later version with the *
* following exceptions: *
* *
* If other files instantiate templates or use macros *
* or inline functions from this file, or you compile this file and *
* link it with other files to produce an executable, this file does *
* not by itself cause the resulting executable to be covered by the *
* GNU Lesser General Public License. This exception does not however *
* invalidate any other reasons why the executable file might be *
* covered by the GNU Lesser General Public License. *
* *
* OpenFlipper is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU LesserGeneral Public *
* License along with OpenFlipper. If not, *
* see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
/*===========================================================================*\
* *
* $Revision$ *
* $LastChangedBy$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// CLASS BSPImplT
//
//=============================================================================
#ifndef BSPIMPLT_HH
#define BSPIMPLT_HH
//== INCLUDES =================================================================
#include <OpenMesh/Core/Geometry/VectorT.hh>
//== CLASS DEFINITION =========================================================
#include <vector>
template <class BSPCore>
class BSPImplT : public BSPCore
{
public: //---------------------------------------------------------------------
typedef typename BSPCore::Traits Traits;
typedef typename BSPCore::Handle Handle;
typedef typename BSPCore::Point Point;
typedef typename BSPCore::Scalar Scalar;
typedef typename BSPCore::Node Node;
typedef typename BSPCore::Handles Handles;
typedef typename BSPCore::HandleIter HandleIter;
public: //---------------------------------------------------------------------
BSPImplT(const Traits& _traits) : BSPCore(_traits) {}
~BSPImplT() {}
/// Store nearest neighbor information
struct NearestNeighbor
{
NearestNeighbor() {}
NearestNeighbor(Handle _h, Scalar _d) : handle(_h), dist(_d) {}
Handle handle;
Scalar dist;
};
/// Store nearest neighbor information
struct RayCollision
{
RayCollision() {}
RayCollision(Handle _h, Scalar _d, std::vector<Handle> _v) : handle(_h), dist(_d), hit_vertices(_v) {}
Handle handle;
Scalar dist;
std::vector<Handle> hit_vertices;
};
/// Return handle of the nearest neighbor face
NearestNeighbor nearest(const Point& _p) const;
/// Return handles of all hit collided faces, and the handle of the nearest collided face
RayCollision raycollision (const Point& _p, const Point& _r) const;
private: //---------------------------------------------------------------------
/// Store nearest neighbor information
struct NearestNeighborData
{
Point ref;
Scalar dist;
Handle nearest;
};
/// Store ray collide information
struct RayCollisionData
{
Point ref;
Point ray;
Scalar dist;
Handle nearest;
std::vector<Handle> hit_vertices;
};
// Recursive part of nearest()
void _nearest(Node* _node, NearestNeighborData& _data) const;
//resursive part of raycollide()
void _raycollision(Node* _node, RayCollisionData& _data) const;
};
//=============================================================================
#if defined(OM_INCLUDE_TEMPLATES) && !defined(BSPIMPLT_C)
# define BSPIMPLT_TEMPLATES
# include "BSPImplT.cc"
#endif
//=============================================================================
#endif // BSPIMPLT_HH defined
//=============================================================================
/*===========================================================================*\
* *
* OpenFlipper *
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
* www.openflipper.org *
* *
*--------------------------------------------------------------------------- *
* This file is part of OpenFlipper. *
* *
* OpenFlipper is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of *
* the License, or (at your option) any later version with the *
* following exceptions: *
* *
* If other files instantiate templates or use macros *
* or inline functions from this file, or you compile this file and *
* link it with other files to produce an executable, this file does *
* not by itself cause the resulting executable to be covered by the *
* GNU Lesser General Public License. This exception does not however *
* invalidate any other reasons why the executable file might be *
* covered by the GNU Lesser General Public License. *
* *
* OpenFlipper is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU LesserGeneral Public *
* License along with OpenFlipper. If not, *
* see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
/*===========================================================================*\
* *
* $Revision$ *
* $LastChangedBy$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// CLASS TreeNode
//
//=============================================================================
#ifndef MB_BSPTREENODE_HH
#define MB_BSPTREENODE_HH
//== INCLUDES =================================================================
#include <ACG/Geometry/Types/PlaneT.hh>
#include <ACG/Geometry/Algorithms.hh>
#include <ObjectTypes/PolyMesh/PolyMeshTypes.hh>
//== CLASS DEFINITION =========================================================
// Node of the tree: contains parent, children and splitting plane
template <class Mesh>
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;
TreeNode(const Handles& _handles, TreeNode* _parent)
: handles_(_handles),
parent_(_parent), left_child_(0), right_child_(0) {}
~TreeNode()
{
delete left_child_;
delete right_child_;
if (parent_)
{
if (this == parent_->left_child_)
parent_->left_child_ = 0;
else
parent_->right_child_ = 0;
}
}
HandleIter begin() {
return handles_.begin();
}
HandleIter end() {
return handles_.end();
}
Handles handles_;
TreeNode *parent_, *left_child_, *right_child_;
Plane plane_;
Point bb_min, bb_max;
/// This visualizes the bounding boxes
void visualizeTree(PolyMesh *_object, int _max_depth)
{
if (_max_depth > 0 && (left_child_ || right_child_) )
{
if (left_child_)
left_child_->visualizeTree(_object, _max_depth-1);
if (right_child_)
right_child_->visualizeTree(_object, _max_depth-1);
}
else
{
Point size_ = bb_max - bb_min;
std::vector<VertexHandle> vhandle(8);
vhandle[0] = _object->add_vertex(bb_min+Point(0.0,0.0,size_[2]));
vhandle[1] = _object->add_vertex(bb_min+Point(size_[0],0.0,size_[2]));
vhandle[2] = _object->add_vertex(bb_min+Point(size_[0],size_[1],size_[2]));
vhandle[3] = _object->add_vertex(bb_min+Point(0.0,size_[1],size_[2]));
vhandle[4] = _object->add_vertex(bb_min+Point(0.0,0.0,0.0));
vhandle[5] = _object->add_vertex(bb_min+Point(size_[0],0.0,0.0));
vhandle[6] = _object->add_vertex(bb_min+Point(size_[0],size_[1],0.0));
vhandle[7] = _object->add_vertex(bb_min+Point(0.0,size_[1],0.0));
// generate (quadrilateral) faces
std::vector<VertexHandle> face_vhandles;
face_vhandles.clear();
face_vhandles.push_back(vhandle[0]);
face_vhandles.push_back(vhandle[1]);
face_vhandles.push_back(vhandle[2]);
face_vhandles.push_back(vhandle[3]);
_object->add_face(face_vhandles);
face_vhandles.clear();
face_vhandles.push_back(vhandle[7]);
face_vhandles.push_back(vhandle[6]);
face_vhandles.push_back(vhandle[5]);
face_vhandles.push_back(vhandle[4]);
_object->add_face(face_vhandles);
face_vhandles.clear();
face_vhandles.push_back(vhandle[1]);
face_vhandles.push_back(vhandle[0]);
face_vhandles.push_back(vhandle[4]);
face_vhandles.push_back(vhandle[5]);
_object->add_face(face_vhandles);
face_vhandles.clear();
face_vhandles.push_back(vhandle[2]);
face_vhandles.push_back(vhandle[1]);
face_vhandles.push_back(vhandle[5]);
face_vhandles.push_back(vhandle[6]);
_object->add_face(face_vhandles);
face_vhandles.clear();
face_vhandles.push_back(vhandle[3]);
face_vhandles.push_back(vhandle[2]);
face_vhandles.push_back(vhandle[6]);
face_vhandles.push_back(vhandle[7]);
_object->add_face(face_vhandles);
face_vhandles.clear();
face_vhandles.push_back(vhandle[0]);
face_vhandles.push_back(vhandle[3]);
face_vhandles.push_back(vhandle[7]);
face_vhandles.push_back(vhandle[4]);
_object->add_face(face_vhandles);
}
}
};
//=============================================================================
#endif // MB_BSPTREENODE_HH defined
//=============================================================================
/*===========================================================================*\
* *
* OpenFlipper *
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
* www.openflipper.org *
* *
*--------------------------------------------------------------------------- *
* This file is part of OpenFlipper. *
* *
* OpenFlipper is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of *
* the License, or (at your option) any later version with the *
* following exceptions: *
* *
* If other files instantiate templates or use macros *
* or inline functions from this file, or you compile this file and *
* link it with other files to produce an executable, this file does *
* not by itself cause the resulting executable to be covered by the *
* GNU Lesser General Public License. This exception does not however *
* invalidate any other reasons why the executable file might be *
* covered by the GNU Lesser General Public License. *
* *
* OpenFlipper is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU LesserGeneral Public *
* License along with OpenFlipper. If not, *
* see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
/*===========================================================================*\
* *
* $Revision$ *
* $LastChangedBy$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// CLASS TriangleBSPCoreT
//
//=============================================================================
#define TRIANGLEBSPCORET_C
//== INCLUDES =================================================================
#include "TriangleBSPCoreT.hh"
//== CLASS DEFINITION =========================================================
template <class BSPTraits>
void
TriangleBSPCoreT<BSPTraits>::
build(unsigned int _max_handles, unsigned int _max_depth)
{
// init
delete root_;
root_ = new Node(handles_, 0);
// delete own handles (don't store them twice)
handles_ = Handles();
nodes=1;
traits_.calculateBoundingBoxRoot (root_);
// call recursive helper
_build(root_, _max_handles, _max_depth);
}
//-----------------------------------------------------------------------------
template <class BSPTraits>
void
TriangleBSPCoreT<BSPTraits>::
_build(Node* _node,
unsigned int _max_handles,
unsigned int _depth)
{
// should we stop at this level ?
if ((_depth == 0) || ((_node->end()-_node->begin()) <= (int)_max_handles))
return;
Point median;
int axis;
// compute bounding boxes for children
traits_.calculateBoundingBox (_node, median, axis);
// construct splitting plane
const Point XYZ[3] = { Point(1,0,0), Point(0,1,0), Point(0,0,1) };
_node->plane_ = Plane(median, XYZ[axis]);
// partition for left and right child
Handles lhandles, rhandles;
lhandles.reserve(_node->handles_.size()/2);
rhandles.reserve(_node->handles_.size()/2);
HandleIter it;
Point p0, p1, p2;
bool left, right;
for (it=_node->begin(); it!=_node->end(); ++it)
{
traits_.points(*it, p0, p1, p2);
left = right = false;
if (_node->plane_(p0)) left = true;
else right = true;
if (_node->plane_(p1)) left = true;
else right = true;
if (_node->plane_(p2)) left = true;
else right = true;
if (left) lhandles.push_back(*it);
if (right) rhandles.push_back(*it);
}
// check it
if (lhandles.size() == _node->handles_.size() ||
rhandles.size() == _node->handles_.size())
return;
else
_node->handles_ = Handles();
// create children
_node->left_child_ = new Node(lhandles, _node); lhandles = Handles();
_node->right_child_ = new Node(rhandles, _node); rhandles = Handles();
nodes+=2;
//save bounding boxes for children
/*
_node->left_child_->bb_min = _node->bb_min;
_node->left_child_->bb_max = _node->bb_max;
_node->left_child_->bb_max[axis] = median [axis];
_node->right_child_->bb_min = _node->bb_min;
_node->right_child_->bb_min[axis] = median [axis];
_node->right_child_->bb_max = _node->bb_max;
*/
_node->right_child_->bb_min = _node->bb_min;
_node->right_child_->bb_max = _node->bb_max;
_node->right_child_->bb_max[axis] = median [axis];
_node->left_child_->bb_min = _node->bb_min;
_node->left_child_->bb_min[axis] = median [axis];
_node->left_child_->bb_max = _node->bb_max;
// recurse to childen
_build(_node->left_child_, _max_handles, _depth-1);
_build(_node->right_child_, _max_handles, _depth-1);
}
//=============================================================================
template <class BSPTraits>
void
TriangleBSPCoreT<BSPTraits>::
visualizeTree(PolyMesh *_object, int _max_depth)
{
root_->visualizeTree(_object, _max_depth-1);
_object->update_normals();
}
//=============================================================================
/*===========================================================================*\
* *
* OpenFlipper *
* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
* www.openflipper.org *
* *
*--------------------------------------------------------------------------- *
* This file is part of OpenFlipper. *
* *
* OpenFlipper is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of *
* the License, or (at your option) any later version with the *
* following exceptions: *
* *
* If other files instantiate templates or use macros *
* or inline functions from this file, or you compile this file and *
* link it with other files to produce an executable, this file does *
* not by itself cause the resulting executable to be covered by the *
* GNU Lesser General Public License. This exception does not however *
* invalidate any other reasons why the executable file might be *
* covered by the GNU Lesser General Public License. *
* *
* OpenFlipper is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU LesserGeneral Public *
* License along with OpenFlipper. If not, *
* see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
/*===========================================================================*\
* *
* $Revision$ *
* $LastChangedBy$ *
* $Date$ *
* *
\*===========================================================================*/