From fefa8ab4c3c8e6078812aa54e59f2a8117c809c1 Mon Sep 17 00:00:00 2001 From: dibenedetto Date: Mon, 26 Sep 2005 18:33:16 +0000 Subject: [PATCH] First Commit. --- .../index/aabb_binary_tree/aabb_binary_tree.h | 408 ++++++++++++++++++ vcg/space/index/aabb_binary_tree/closest.h | 148 +++++++ .../index/aabb_binary_tree/face_functors.h | 102 +++++ .../index/aabb_binary_tree/frustum_cull.h | 200 +++++++++ vcg/space/index/aabb_binary_tree/kclosest.h | 155 +++++++ vcg/space/index/aabb_binary_tree/ray.h | 168 ++++++++ vcg/space/index/aabb_binary_tree/utils.h | 74 ++++ 7 files changed, 1255 insertions(+) create mode 100644 vcg/space/index/aabb_binary_tree/aabb_binary_tree.h create mode 100644 vcg/space/index/aabb_binary_tree/closest.h create mode 100644 vcg/space/index/aabb_binary_tree/face_functors.h create mode 100644 vcg/space/index/aabb_binary_tree/frustum_cull.h create mode 100644 vcg/space/index/aabb_binary_tree/kclosest.h create mode 100644 vcg/space/index/aabb_binary_tree/ray.h create mode 100644 vcg/space/index/aabb_binary_tree/utils.h diff --git a/vcg/space/index/aabb_binary_tree/aabb_binary_tree.h b/vcg/space/index/aabb_binary_tree/aabb_binary_tree.h new file mode 100644 index 00000000..a743d4b7 --- /dev/null +++ b/vcg/space/index/aabb_binary_tree/aabb_binary_tree.h @@ -0,0 +1,408 @@ +/**************************************************************************** +* VCGLib o o * +* Visual and Computer Graphics Library o o * +* _ O _ * +* Copyright(C) 2004 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program 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 General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +/**************************************************************************** +History + +$Log: not supported by cvs2svn $ + +****************************************************************************/ + +#ifndef __VCGLIB_AABBBINARYTREE_TYPE_H +#define __VCGLIB_AABBBINARYTREE_TYPE_H + +// standard headers +#include + +// stl headers +#include + +// vcg headers +#include +#include + +/***************************************************************************************/ + +namespace vcg { + +template +class AABBBinaryTree { + public: + typedef AABBBinaryTree ClassType; + typedef OBJTYPE ObjType; + typedef ObjType * ObjPtr; + typedef SCALARTYPE ScalarType; + typedef NODEAUXDATATYPE NodeAuxDataType; + typedef Point3 CoordType; + + typedef std::vector ObjPtrVector; + typedef typename ObjPtrVector::iterator ObjPtrVectorIterator; + typedef typename ObjPtrVector::const_iterator ObjPtrVectorConstIterator; + + public: + class AABBBinaryTreeNode { + public: + AABBBinaryTreeNode * parent; + AABBBinaryTreeNode * children[2]; + CoordType boxCenter; + CoordType boxHalfDims; + ObjPtrVectorIterator oBegin; + ObjPtrVectorIterator oEnd; + unsigned char splitAxis; + NodeAuxDataType auxData; + + inline AABBBinaryTreeNode(AABBBinaryTreeNode * pParent = 0); + inline ~AABBBinaryTreeNode(void); + + inline void Clear(void); + inline bool IsLeaf(void) const; + inline unsigned int ObjectsCount(void) const; + + inline unsigned int & Flags(void); + inline const unsigned int & Flags(void) const; + + inline ScalarType & ScalarValue(void); + inline const ScalarType & ScalarValue(void) const; + + inline int & IntValue(void); + inline const int & IntValue(void) const; + + inline unsigned int & UIntValue(void); + inline const unsigned int & UIntValue(void) const; + + inline void * & PtrValue(void); + inline const void * & PtrValue(void) const; + + protected: + union SharedDataUnion { + unsigned int flags; + int intValue; + unsigned int uintValue; + ScalarType scalarValue; + void * ptrValue; + }; + + SharedDataUnion sharedData; + }; + + typedef AABBBinaryTreeNode NodeType; + + ObjPtrVector pObjects; + NodeType * pRoot; + + inline AABBBinaryTree(void); + inline ~AABBBinaryTree(void); + + inline void Clear(void); + + template + inline bool Set(const OBJITERATOR & oBegin, const OBJITERATOR & oEnd, OBJITERATORPTRFUNCT & objPtr, OBJBOXFUNCT & objBox, OBJBARYCENTERFUNCT & objBarycenter, const unsigned int maxElemsPerLeaf = 1, const ScalarType & leafBoxMaxVolume = ((ScalarType)0), const bool useVariance = true); + + protected: + template + inline static NodeType * BoundObjects(NodeType * parent, const ObjPtrVectorIterator & oBegin, const ObjPtrVectorIterator & oEnd, const unsigned int size, const unsigned int maxElemsPerLeaf, const ScalarType & leafBoxMaxVolume, const bool useVariance, OBJBOXFUNCT & getBox, OBJBARYCENTERFUNCT & getBarycenter); + + template + inline static int BalanceMedian(const ObjPtrVectorIterator & oBegin, const ObjPtrVectorIterator & oEnd, const int size, const int splitAxis, OBJBARYCENTERFUNCT & getBarycenter, ObjPtrVectorIterator & medianIter); +}; + + + +template +AABBBinaryTree::AABBBinaryTree(void) { + this->pObjects.clear(); + this->pRoot = 0; +} + +template +AABBBinaryTree::~AABBBinaryTree(void) { + this->pObjects.clear(); + delete this->pRoot; +} + +template +void AABBBinaryTree::Clear(void) { + this->pObjects.clear(); + delete this->pRoot; + this->pRoot = 0; +} + +template +template +bool AABBBinaryTree::Set(const OBJITERATOR & oBegin, const OBJITERATOR & oEnd, OBJITERATORPTRFUNCT & objPtr, OBJBOXFUNCT & objBox, OBJBARYCENTERFUNCT & objBarycenter, const unsigned int maxElemsPerLeaf, const ScalarType & leafBoxMaxVolume, const bool useVariance) { + this->Clear(); + + if ((maxElemsPerLeaf == 0) && (leafBoxMaxVolume <= ((ScalarType)0))) { + return (false); + } + + const unsigned int size = (unsigned int)std::distance(oBegin, oEnd); + + this->pObjects.reserve(size); + for (OBJITERATOR oi=oBegin; oi!=oEnd; ++oi) { + this->pObjects.push_back(objPtr(*oi)); + } + + this->pRoot = ClassType::BoundObjects(0, this->pObjects.begin(), this->pObjects.end(), size, maxElemsPerLeaf, leafBoxMaxVolume, useVariance, objBox, objBarycenter); + + return (this->pRoot != 0); +} + +template +template +typename AABBBinaryTree::NodeType * AABBBinaryTree::BoundObjects(NodeType * parent, const ObjPtrVectorIterator & oBegin, const ObjPtrVectorIterator & oEnd, const unsigned int size, const unsigned int maxElemsPerLeaf, const ScalarType & leafBoxMaxVolume, const bool useVariance, OBJBOXFUNCT & getBox, OBJBARYCENTERFUNCT & getBarycenter) { + if (size <= 0) { + return (0); + } + + NodeType * pNode = new NodeType(parent); + if (pNode == 0) { + return (0); + } + + pNode->children[0] = 0; + pNode->children[1] = 0; + + pNode->oBegin = oBegin; + pNode->oEnd = oEnd; + + Box3 bbox; + bbox.SetNull(); + for (ObjPtrVectorConstIterator oi=pNode->oBegin; oi!=pNode->oEnd; ++oi) { + Box3 tbox; + getBox(*(*oi), tbox); + bbox.Add(tbox); + } + + pNode->boxCenter = bbox.Center(); + pNode->boxHalfDims = bbox.Dim() / ((ScalarType)2); + + const bool bMaxObjectsReached = (((maxElemsPerLeaf > 0) && (size <= maxElemsPerLeaf)) || (size == 1)); + const bool bMaxVolumeReached = ((leafBoxMaxVolume > ((ScalarType)0)) && (bbox.Volume() <= leafBoxMaxVolume)); + const bool isLeaf = bMaxObjectsReached || bMaxVolumeReached; + + if (isLeaf) { + pNode->splitAxis = 0; + return (pNode); + } + + CoordType pSplit; + + if (useVariance) { + CoordType mean((ScalarType)0, (ScalarType)0, (ScalarType)0); + CoordType variance((ScalarType)0, (ScalarType)0, (ScalarType)0); + for (ObjPtrVectorIterator oi=oBegin; oi!=oEnd; ++oi) { + CoordType bc; + getBarycenter(*(*oi), bc); + mean += bc; + variance[0] += bc[0] * bc[0]; + variance[1] += bc[1] * bc[1]; + variance[2] += bc[2] * bc[2]; + } + variance[0] -= (mean[0] * mean[0]) / ((ScalarType)size); + variance[1] -= (mean[1] * mean[1]) / ((ScalarType)size); + variance[2] -= (mean[2] * mean[2]) / ((ScalarType)size); + pSplit = variance; + } + else { + pSplit = pNode->boxHalfDims; + } + + ScalarType maxDim = pSplit[0]; + unsigned char splitAxis = 0; + if (maxDim < pSplit[1]) { + maxDim = pSplit[1]; + splitAxis = 1; + } + if (maxDim < pSplit[2]) { + maxDim = pSplit[2]; + splitAxis = 2; + } + + pNode->splitAxis = splitAxis; + + ObjPtrVectorIterator median; + const int lSize = ClassType::BalanceMedian(pNode->oBegin, pNode->oEnd, size, splitAxis, getBarycenter, median); + const int rSize = size - lSize; + + if (lSize > 0) { + pNode->children[0] = ClassType::BoundObjects(pNode, pNode->oBegin, median, lSize, maxElemsPerLeaf, leafBoxMaxVolume, useVariance, getBox, getBarycenter); + if (pNode->children[0] == 0) { + delete pNode; + return (0); + } + } + + if (rSize > 0) { + pNode->children[1] = ClassType::BoundObjects(pNode, median, pNode->oEnd, rSize, maxElemsPerLeaf, leafBoxMaxVolume, useVariance, getBox, getBarycenter); + if (pNode->children[1] == 0) { + delete pNode; + return (0); + } + } + + return (pNode); +} + +template +template +int AABBBinaryTree::BalanceMedian(const ObjPtrVectorIterator & oBegin, const ObjPtrVectorIterator & oEnd, const int size, const int splitAxis, OBJBARYCENTERFUNCT & getBarycenter, ObjPtrVectorIterator & medianIter) { + const int iMedian = (size + 1) / 2; + + ObjPtrVectorIterator l, r, i, j; + ObjPtr iTmp; + ScalarType pos; + ObjPtrVectorIterator median = oBegin + iMedian; + CoordType bc; + + l = oBegin; + r = oEnd - 1; + + while (l < r) { + getBarycenter(*(*r), bc); + pos = bc[splitAxis]; + + i = l; + j = r - 1; + + while (true) { + getBarycenter(*(*i), bc); + while ((bc[splitAxis] <= pos) && (i < r)) { + i++; + getBarycenter(*(*i), bc); + } + getBarycenter(*(*j), bc); + while ((bc[splitAxis] > pos) && (j > l)) { + j--; + getBarycenter(*(*j), bc); + } + if (i >= j) { + break; + } + iTmp = (*i); + (*i) = (*j); + (*j) = iTmp; + } + + iTmp = (*i); + (*i) = (*r); + (*r) = iTmp; + + if (i >= (median)) { + r = i - 1; + } + if (i <= (median)) { + l = i + 1; + } + } + + medianIter = median; + + return (iMedian); +} + +template +AABBBinaryTree::AABBBinaryTreeNode::AABBBinaryTreeNode(NodeType * pParent) { + this->parent = pParent; + this->children[0] = 0; + this->children[1] = 0; +} + +template +AABBBinaryTree::AABBBinaryTreeNode::~AABBBinaryTreeNode(void) { + delete this->children[0]; + delete this->children[1]; +} + +template +void AABBBinaryTree::AABBBinaryTreeNode::Clear(void) { + delete this->children[0]; + this->children[0] = 0; + + delete this->children[1]; + this->children[1] = 0; +} + +template +bool AABBBinaryTree::AABBBinaryTreeNode::IsLeaf(void) const { + return ((this->children[0] == 0) && (this->children[1] == 0)); +} + +template +unsigned int AABBBinaryTree::AABBBinaryTreeNode::ObjectsCount(void) const { + return ((unsigned int)(std::distance(this->oBegin, this->oEnd))); +} + +template +unsigned int & AABBBinaryTree::AABBBinaryTreeNode::Flags(void) { + return (this->sharedData.flags); +} + +template +const unsigned int & AABBBinaryTree::AABBBinaryTreeNode::Flags(void) const { + return (this->sharedData.flags); +} + +template +int & AABBBinaryTree::AABBBinaryTreeNode::IntValue(void) { + return (this->sharedData.intValue); +} + +template +const int & AABBBinaryTree::AABBBinaryTreeNode::IntValue(void) const { + return (this->sharedData.intValue); +} + +template +unsigned int & AABBBinaryTree::AABBBinaryTreeNode::UIntValue(void) { + return (this->sharedData.uintValue); +} + +template +const unsigned int & AABBBinaryTree::AABBBinaryTreeNode::UIntValue(void) const { + return (this->sharedData.uintValue); +} + +template +typename AABBBinaryTree::ScalarType & AABBBinaryTree::AABBBinaryTreeNode::ScalarValue(void) { + return (this->sharedData.scalarValue); +} + +template +const typename AABBBinaryTree::ScalarType & AABBBinaryTree::AABBBinaryTreeNode::ScalarValue(void) const { + return (this->sharedData.scalarValue); +} + +template +void * & AABBBinaryTree::AABBBinaryTreeNode::PtrValue(void) { + return (this->sharedData.ptrValue); +} + +template +const void * & AABBBinaryTree::AABBBinaryTreeNode::PtrValue(void) const { + return (this->sharedData.ptrValue); +} + +} // end namespace vcg + +#endif // #ifndef __VCGLIB_AABBBINARYTREE_TYPE_H diff --git a/vcg/space/index/aabb_binary_tree/closest.h b/vcg/space/index/aabb_binary_tree/closest.h new file mode 100644 index 00000000..81b4b11a --- /dev/null +++ b/vcg/space/index/aabb_binary_tree/closest.h @@ -0,0 +1,148 @@ +/**************************************************************************** +* VCGLib o o * +* Visual and Computer Graphics Library o o * +* _ O _ * +* Copyright(C) 2004 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program 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 General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +/**************************************************************************** +History + +$Log: not supported by cvs2svn $ + +****************************************************************************/ + +#ifndef __VCGLIB_AABBBINARYTREE_CLOSEST_H +#define __VCGLIB_AABBBINARYTREE_CLOSEST_H + +// stl headers +#include +#include + +// vcg headers +#include +#include + +namespace vcg { + +template +class AABBBinaryTreeClosest { +public: + typedef AABBBinaryTreeClosest ClassType; + typedef TREETYPE TreeType; + typedef typename TreeType::ScalarType ScalarType; + typedef typename TreeType::CoordType CoordType; + typedef typename TreeType::NodeType NodeType; + typedef typename TreeType::ObjPtr ObjPtr; + + template + static inline ObjPtr Closest(TreeType & tree, OBJPOINTDISTANCEFUNCT & getPointDistance, const CoordType & p, const ScalarType & maxDist, ScalarType & minDist, CoordType & q) { + typedef OBJPOINTDISTANCEFUNCT ObjPointDistanceFunct; + typedef std::vector NodePtrVector; + typedef typename NodePtrVector::const_iterator NodePtrVector_ci; + + NodeType * pRoot = tree.pRoot; + + if (pRoot == 0) { + return (0); + } + + NodePtrVector clist1; + NodePtrVector clist2; + NodePtrVector leaves; + + NodePtrVector * candidates = &clist1; + NodePtrVector * newCandidates = &clist2; + + clist1.reserve(tree.pObjects.size()); + clist2.reserve(tree.pObjects.size()); + leaves.reserve(tree.pObjects.size()); + + clist1.resize(0); + clist2.resize(0); + leaves.resize(0); + + ScalarType minMaxDist = maxDist * maxDist; + + candidates->push_back(pRoot); + + while (!candidates->empty()) { + newCandidates->resize(0); + + for (NodePtrVector_ci bv=candidates->begin(); bv!=candidates->end(); ++bv) { + const CoordType dc = Abs(p - (*bv)->boxCenter); + const ScalarType maxDist = (dc + (*bv)->boxHalfDims).SquaredNorm(); + (*bv)->ScalarValue() = LowClampToZero(dc - (*bv)->boxHalfDims).SquaredNorm(); + if (maxDist < minMaxDist) { + minMaxDist = maxDist; + } + } + + for (NodePtrVector_ci ci=candidates->begin(); ci!=candidates->end(); ++ci) { + if ((*ci)->ScalarValue() < minMaxDist) { + if ((*ci)->IsLeaf()) { + leaves.push_back(*ci); + } + else { + if ((*ci)->children[0] != 0) { + newCandidates->push_back((*ci)->children[0]); + } + if ((*ci)->children[1] != 0) { + newCandidates->push_back((*ci)->children[1]); + } + } + } + } + NodePtrVector * cSwap = candidates; + candidates = newCandidates; + newCandidates = cSwap; + } + + clist1.clear(); + clist2.clear(); + + ObjPtr closestObject = 0; + CoordType closestPoint; + ScalarType closestDist = math::Sqrt(minMaxDist) + std::numeric_limits::epsilon(); + ScalarType closestDistSq = closestDist * closestDist; + + for (NodePtrVector_ci ci=leaves.begin(); ci!=leaves.end(); ++ci) { + if ((*ci)->ScalarValue() < closestDistSq) { + for (typename TreeType::ObjPtrVectorConstIterator si=(*ci)->oBegin; si!=(*ci)->oEnd; ++si) { + if (getPointDistance(*(*si), p, closestDist, closestPoint)) { + closestDistSq = closestDist * closestDist; + closestObject = (*si); + } + } + } + } + + leaves.clear(); + + q = closestPoint; + minDist = closestDist; + + return (closestObject); + } + +}; + +} // end namespace vcg + +#endif // #ifndef __VCGLIB_AABBBINARYTREE_CLOSEST_H diff --git a/vcg/space/index/aabb_binary_tree/face_functors.h b/vcg/space/index/aabb_binary_tree/face_functors.h new file mode 100644 index 00000000..99ff0c43 --- /dev/null +++ b/vcg/space/index/aabb_binary_tree/face_functors.h @@ -0,0 +1,102 @@ +/**************************************************************************** +* VCGLib o o * +* Visual and Computer Graphics Library o o * +* _ O _ * +* Copyright(C) 2004 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program 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 General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +/**************************************************************************** +History + +$Log: not supported by cvs2svn $ + +****************************************************************************/ + +#ifndef __VCGLIB_FACEFUNCTORS +#define __VCGLIB_FACEFUNCTORS + +// vcg headers +#include +#include +#include +#include +#include + +namespace vcg { + +class FaceBarycenterFunctor { +public: + template + inline void operator () (const FACETYPE & f, COORDTYPE & b) { + b = COORDTYPE::Construct(f.Barycenter()); + } +}; + +class FaceBoxFunctor { +public: + template + inline void operator () (const FACETYPE & f, BOXTYPE & b) { + b.Set(Point3::Construct(f.P(0))); + b.Add(Point3::Construct(f.P(1))); + b.Add(Point3::Construct(f.P(2))); + } +}; + +class FacePointDistanceFunctor { +public: + template + inline bool operator () (const FACETYPE & f, const COORDTYPE & p, typename COORDTYPE::ScalarType & minDist, COORDTYPE & q) { + const Point3 fp = Point3::Construct(p); + Point3 fq; + typename FACETYPE::ScalarType md = (typename FACETYPE::ScalarType)(minDist); + const bool ret = face::PointDistance(f, fp, md, fq); + minDist = (typename COORDTYPE::ScalarType)(md); + q = COORDTYPE::Construct(fq); + return (ret); + } +}; + +template +class FaceRayIntersectFunctor { +public: + template + inline bool operator () (const FACETYPE & f, const COORDTYPE & rayOrigin, const COORDTYPE & rayDirection, typename COORDTYPE::ScalarType & t, COORDTYPE & q) { + typedef typename COORDTYPE::ScalarType ScalarType; + Line3 ln(rayOrigin, rayDirection); + ScalarType a; + ScalarType b; + + bool bret = Intersection(ln, f.P(0), f.P(1), f.P(2), a, b, t); + if (BACKFACETEST) { + if (!bret) { + bret = Intersection(ln, f.P(0), f.P(2), f.P(1), a, b, t); + } + } + + if (bret) { + q = rayOrigin + rayDirection * t; + return (true); + } + return (false); + } +}; + +} // end namespace vcg + +#endif // #ifndef __VCGLIB_FACEFUNCTORS diff --git a/vcg/space/index/aabb_binary_tree/frustum_cull.h b/vcg/space/index/aabb_binary_tree/frustum_cull.h new file mode 100644 index 00000000..1fffcbe1 --- /dev/null +++ b/vcg/space/index/aabb_binary_tree/frustum_cull.h @@ -0,0 +1,200 @@ +/**************************************************************************** +* VCGLib o o * +* Visual and Computer Graphics Library o o * +* _ O _ * +* Copyright(C) 2004 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program 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 General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +/**************************************************************************** +History + +$Log: not supported by cvs2svn $ + +****************************************************************************/ + +#ifndef __VCGLIB_AABBBINARYTREE_FRUSTUMCULL_H +#define __VCGLIB_AABBBINARYTREE_FRUSTUMCULL_H + +// vcg headers +#include +#include + +/***************************************************************************************/ + +namespace vcg { + +template +class AABBBinaryTreeFrustumCull { +public: + typedef AABBBinaryTreeFrustumCull ClassType; + typedef TREETYPE TreeType; + typedef typename TreeType::ScalarType ScalarType; + typedef typename TreeType::CoordType CoordType; + typedef typename TreeType::NodeType NodeType; + typedef typename TreeType::ObjPtr ObjPtr; + +protected: + class VFrustumPlane { + public: + CoordType normal; + ScalarType offset; + unsigned int pVertexIndex[3]; + }; + + class VFrustum { + public: + VFrustumPlane planes[6]; + }; + +public: + enum { + FC_FIRST_PLANE_BIT = 0, + FC_PARTIALLY_VISIBLE_BIT = (1 << (FC_FIRST_PLANE_BIT + 3)), + FC_FULLY_VISIBLE_BIT = (1 << (FC_FIRST_PLANE_BIT + 4)) + }; + + static inline bool IsPartiallyVisible(const NodeType * node) { + return ((node->Flags() & FC_PARTIALLY_VISIBLE_BIT) != 0); + } + + static inline bool IsFullyVisible(const NodeType * node) { + return ((node->Flags() & FC_FULLY_VISIBLE_BIT) != 0); + } + + static inline bool IsVisible(const NodeType * node) { + return ((node->Flags() & (FC_PARTIALLY_VISIBLE_BIT | FC_FULLY_VISIBLE_BIT)) != 0); + } + + static inline void Initialize(TreeType & tree) { + NodeType * pRoot = tree.pRoot; + if (pRoot == 0) { + return; + } + ClassType::InitializeNodeFlagsRec(pRoot); + } + + static inline void FrustumCull(TreeType & tree, const Plane3 frustumPlanes[6], const unsigned int minNodeObjectsCount) { + NodeType * pRoot = tree.pRoot; + if (pRoot == 0) { + return; + } + VFrustum frustum; + for (int i=0; i<6; ++i) { + frustum.planes[i].normal = frustumPlanes[i].Direction(); + frustum.planes[i].offset = frustumPlanes[i].Offset(); + frustum.planes[i].pVertexIndex[0] = (frustum.planes[i].normal[0] >= ((ScalarType)0)) ? (1) : (0); + frustum.planes[i].pVertexIndex[1] = (frustum.planes[i].normal[1] >= ((ScalarType)0)) ? (1) : (0); + frustum.planes[i].pVertexIndex[2] = (frustum.planes[i].normal[2] >= ((ScalarType)0)) ? (1) : (0); + } + + const unsigned char inMask = 0x3F; + ClassType::NodeVsFrustum(pRoot, frustum, inMask, minNodeObjectsCount); + } + +protected: + static inline void InitializeNodeFlagsRec(NodeType * node) { + node->Flags() &= ~(0x1F); + if (node->children[0] == 0) { + ClassType::InitializeNodeFlagsRec(node->children[0]); + } + if (node->children[1] == 0) { + ClassType::InitializeNodeFlagsRec(node->children[1]); + } + } + + static inline void NodeVsFrustum(NodeType * node, const VFrustum & f, unsigned char inMask, unsigned int minNodeObjectsCount) { + const CoordType bminmax[2] = { + node->boxCenter - node->boxHalfDims, + node->boxCenter + node->boxHalfDims, + }; + const unsigned int firstFail = (unsigned int)((node->Flags() >> FC_FIRST_PLANE_BIT) & 0x7); + const VFrustumPlane * fp = f.planes + firstFail; + unsigned char k = 1 << firstFail; + unsigned char newMask = 0x0; + bool fullInside = true; + + node->Flags() &= ~(FC_PARTIALLY_VISIBLE_BIT | FC_FULLY_VISIBLE_BIT); + + if ((k & inMask) != 0) { + if ( + ((fp->normal[0] * bminmax[fp->pVertexIndex[0]][0]) + + (fp->normal[1] * bminmax[fp->pVertexIndex[1]][1]) + + (fp->normal[2] * bminmax[fp->pVertexIndex[2]][2]) + + (fp->offset)) < ((ScalarType)0) + ) { + return; + } + + if ( + ((fp->normal[0] * bminmax[1 - fp->pVertexIndex[0]][0]) + + (fp->normal[1] * bminmax[1 - fp->pVertexIndex[1]][1]) + + (fp->normal[2] * bminmax[1 - fp->pVertexIndex[2]][2]) + + (fp->offset)) < ((ScalarType)0) + ) { + newMask |= k; + fullInside = false; + } + } + + k = 1; + for (unsigned int i=0; k<=inMask; ++i, k<<=1) { + if ((i != firstFail) && ((k & inMask) != 0)) { + fp = f.planes + i; + if ( + ((fp->normal[0] * bminmax[fp->pVertexIndex[0]][0]) + + (fp->normal[1] * bminmax[fp->pVertexIndex[1]][1]) + + (fp->normal[2] * bminmax[fp->pVertexIndex[2]][2]) + + (fp->offset)) < ((ScalarType)0) + ) { + node->Flags() = (node->Flags() & ((~0x0) & (0x7 << ClassType::FC_FIRST_PLANE_BIT))) | (i << ClassType::FC_FIRST_PLANE_BIT); + return; + } + + if ( + ((fp->normal[0] * bminmax[1 - fp->pVertexIndex[0]][0]) + + (fp->normal[1] * bminmax[1 - fp->pVertexIndex[1]][1]) + + (fp->normal[2] * bminmax[1 - fp->pVertexIndex[2]][2]) + + (fp->offset)) < ((ScalarType)0) + ) { + newMask |= k; + fullInside = false; + } + } + } + + if (fullInside || (node->ObjectsCount() <= minNodeObjectsCount)) { + node->Flags() |= FC_FULLY_VISIBLE_BIT; + return; + } + + node->Flags() |= FC_PARTIALLY_VISIBLE_BIT; + + if (node->children[0] != 0) { + ClassType::NodeVsFrustum(node->children[0], f, newMask, minNodeObjectsCount); + } + if (node->children[1] != 0) { + ClassType::NodeVsFrustum(node->children[1], f, newMask, minNodeObjectsCount); + } + } + +}; + +} // end namespace vcg + +#endif // #ifndef __VCGLIB_AABBBINARYTREE_FRUSTUMCULL_H diff --git a/vcg/space/index/aabb_binary_tree/kclosest.h b/vcg/space/index/aabb_binary_tree/kclosest.h new file mode 100644 index 00000000..19f32bef --- /dev/null +++ b/vcg/space/index/aabb_binary_tree/kclosest.h @@ -0,0 +1,155 @@ +/**************************************************************************** +* VCGLib o o * +* Visual and Computer Graphics Library o o * +* _ O _ * +* Copyright(C) 2004 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program 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 General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +/**************************************************************************** +History + +$Log: not supported by cvs2svn $ + +****************************************************************************/ + +#ifndef __VCGLIB_AABBBINARYTREE_KCLOSEST_H +#define __VCGLIB_AABBBINARYTREE_KCLOSEST_H + +// stl headers +#include +#include + +// vcg headers +#include + +namespace vcg { + +template +class AABBBinaryTreeKClosest { +public: + typedef AABBBinaryTreeKClosest ClassType; + typedef TREETYPE TreeType; + typedef typename TreeType::ScalarType ScalarType; + typedef typename TreeType::CoordType CoordType; + typedef typename TreeType::NodeType NodeType; + typedef typename TreeType::ObjPtr ObjPtr; + +protected: + class ClosestObjType { + public: + ObjPtr pObj; + ScalarType minDist; + CoordType closestPt; + }; + + class CompareClosest { + public: + bool operator () (const ClosestObjType & a, const ClosestObjType & b) { + return (a.minDist < b.minDist); + } + }; + + typedef std::priority_queue, CompareClosest> PQueueType; + +public: + template + static inline unsigned int KClosest(TreeType & tree, OBJPOINTDISTANCEFUNCT & getPointDistance, const unsigned int k, const CoordType & p, const ScalarType & maxDist, OBJPTRCONTAINERTYPE & objects, DISTCONTAINERTYPE & distances, POINTCONTAINERTYPE & points) { + typedef std::vector NodePtrVector; + typedef typename NodePtrVector::const_iterator NodePtrVector_ci; + + if (k == 0) { + return (0); + } + + NodeType * pRoot = tree.pRoot; + + if (pRoot == 0) { + return (0); + } + + PQueueType pq; + ScalarType mindmax = maxDist; + + ClassType::DepthFirstCollect(pRoot, getPointDistance, k, p, mindmax, pq); + + const unsigned int sz = (unsigned int)(pq.size()); + + while (!pq.empty()) { + ClosestObjType cobj = pq.top(); + pq.pop(); + objects.push_back(cobj.pObj); + distances.push_back(cobj.minDist); + points.push_back(cobj.closestPt); + } + + return (sz); + } + +protected: + template + static void DepthFirstCollect(NodeType * node, OBJPOINTDISTANCEFUNCT & getPointDistance, const unsigned int k, const CoordType & p, ScalarType & mindmax, PQueueType & pq) { + const CoordType dc = Abs(p - node->boxCenter); + + if (pq.size() >= k) { + const ScalarType dmin = LowClampToZero(dc - node->boxHalfDims).SquaredNorm(); + if (dmin >= mindmax) { + return; + } + } + + if (node->IsLeaf()) { + bool someInserted = true; + for (typename TreeType::ObjPtrVectorConstIterator si=node->oBegin; si!=node->oEnd; ++si) { + ScalarType minDst = (pq.size() >= k) ? (pq.top().minDist) : (mindmax); + ClosestObjType cobj; + if (getPointDistance(*(*si), p, minDst, cobj.closestPt)) { + someInserted = true; + cobj.pObj = (*si); + cobj.minDist = minDst; + if (pq.size() >= k) { + pq.pop(); + } + pq.push(cobj); + } + } + if (someInserted) { + if (pq.size() >= k) { + const ScalarType dmax = pq.top().minDist; + const ScalarType sqdmax = dmax * dmax; + if (sqdmax < mindmax) { + mindmax = sqdmax; + } + } + } + } + else { + if (node->children[0] != 0) { + ClassType::DepthFirstCollect(node->children[0], getPointDistance, k, p, mindmax, pq); + } + if (node->children[1] != 0) { + ClassType::DepthFirstCollect(node->children[1], getPointDistance, k, p, mindmax, pq); + } + } + } + +}; + +} // end namespace vcg + +#endif // #ifndef __VCGLIB_AABBBINARYTREE_KCLOSEST_H diff --git a/vcg/space/index/aabb_binary_tree/ray.h b/vcg/space/index/aabb_binary_tree/ray.h new file mode 100644 index 00000000..2548d912 --- /dev/null +++ b/vcg/space/index/aabb_binary_tree/ray.h @@ -0,0 +1,168 @@ +/**************************************************************************** +* VCGLib o o * +* Visual and Computer Graphics Library o o * +* _ O _ * +* Copyright(C) 2004 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program 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 General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +/**************************************************************************** +History + +$Log: not supported by cvs2svn $ + +****************************************************************************/ + +#ifndef __VCGLIB_AABBBINARYTREE_RAY_H +#define __VCGLIB_AABBBINARYTREE_RAY_H + +// stl headers +#include + +/***************************************************************************************/ + +namespace vcg { + +template +class AABBBinaryTreeRay { +public: + typedef AABBBinaryTreeRay ClassType; + typedef TREETYPE TreeType; + typedef typename TreeType::ScalarType ScalarType; + typedef typename TreeType::CoordType CoordType; + typedef typename TreeType::NodeType NodeType; + typedef typename TreeType::ObjPtr ObjPtr; + + template + static inline ObjPtr Ray(TreeType & tree, OBJRAYISECTFUNCT & rayIntersection, const CoordType & rayOrigin, const CoordType & rayDirection, ScalarType & t, CoordType & q) { + typedef std::vector NodePtrVector; + typedef typename NodePtrVector::const_iterator NodePtrVector_ci; + + NodeType * pRoot = tree.pRoot; + + if (pRoot == 0) { + return (0); + } + + ScalarType rayT = std::numeric_limits::max(); + CoordType pRes; + + Ray3Ex rayex; + rayex.origin = rayOrigin; + rayex.direction = rayDirection; + rayex.invDirection[0] = ((ScalarType)1) / rayDirection[0]; + rayex.invDirection[1] = ((ScalarType)1) / rayDirection[1]; + rayex.invDirection[2] = ((ScalarType)1) / rayDirection[2]; + rayex.sign[0] = (rayex.invDirection[0] < ((ScalarType)0)) ? (1) : (0); + rayex.sign[1] = (rayex.invDirection[1] < ((ScalarType)0)) ? (1) : (0); + rayex.sign[2] = (rayex.invDirection[2] < ((ScalarType)0)) ? (1) : (0); + + ObjPtr closestObj = 0; + + ClassType::DepthFirstRayIsect(pRoot, rayIntersection, rayex, rayT, pRes, closestObj); + + if (closestObj == 0) { + return (0); + } + + t = rayT; + q = pRes; + + return (closestObj); + } + +protected: + class Ray3Ex { + public: + CoordType origin; + CoordType direction; + CoordType invDirection; + unsigned char sign[3]; + }; + + static inline bool IntersectionBoxRay(const CoordType & boxCenter, const CoordType & boxHalfDims, const Ray3Ex & ray, ScalarType & t0) { + const CoordType bounds[2] = { + boxCenter - boxHalfDims, + boxCenter + boxHalfDims + }; + ScalarType tmin, tmax; + ScalarType tcmin, tcmax; + + tmin = (bounds[ray.sign[0]][0] - ray.origin[0]) * ray.invDirection[0]; + tmax = (bounds[1 - ray.sign[0]][0] - ray.origin[0]) * ray.invDirection[0]; + tcmin = (bounds[ray.sign[1]][1] - ray.origin[1]) * ray.invDirection[1]; + tcmax = (bounds[1 - ray.sign[1]][1] - ray.origin[1]) * ray.invDirection[1]; + if ((tmin > tcmax) || (tcmin > tmax)) { return (false); } + if (tcmin > tmin) { tmin = tcmin; } + if (tcmax < tmax) { tmax = tcmax; } + tcmin = (bounds[ray.sign[2]][2] - ray.origin[2]) * ray.invDirection[2]; + tcmax = (bounds[1-ray.sign[2]][2] - ray.origin[2]) * ray.invDirection[2]; + if ((tmin > tcmax) || (tcmin > tmax)) { return (false); } + if (tcmin > tmin) { tmin = tcmin; } + //if (tcmax < tmax) { tmax = tcmax; } + t0 = (tmin >= ((ScalarType)0)) ? (tmin) :((ScalarType)0); + return (true); + } + + template + static inline void DepthFirstRayIsect(const NodeType * node, OBJRAYISECTFUNCT & rayIntersection, const Ray3Ex & ray, ScalarType & rayT, CoordType & res, ObjPtr & closestObj) { + ScalarType rt; + CoordType pt; + if (!ClassType::IntersectionBoxRay(node->boxCenter, node->boxHalfDims, ray, rt)) { + return; + } + + if (rt >= rayT) { + return; + } + + if (node->IsLeaf()) { + ObjPtr cObj = 0; + ScalarType ar; + CoordType ap; + rt = std::numeric_limits::max(); + for (typename TreeType::ObjPtrVectorConstIterator si=node->oBegin; si!=node->oEnd; ++si) { + if (rayIntersection(*(*si), ray.origin, ray.direction, ar, ap)) { + if (ar < rt) { + rt = ar; + pt = ap; + cObj = (*si); + } + } + } + if (rt < rayT) { + rayT = rt; + res = pt; + closestObj = cObj; + } + } + else { + if (node->children[0] != 0) { + ClassType::DepthFirstRayIsect(node->children[0], rayIntersection, ray, rayT, res, closestObj); + } + if (node->children[1] != 0) { + ClassType::DepthFirstRayIsect(node->children[1], rayIntersection, ray, rayT, res, closestObj); + } + } + } + +}; + +} // end namespace vcg + +#endif // #ifndef __VCGLIB_AABBBINARYTREE_RAY_H diff --git a/vcg/space/index/aabb_binary_tree/utils.h b/vcg/space/index/aabb_binary_tree/utils.h new file mode 100644 index 00000000..492afcac --- /dev/null +++ b/vcg/space/index/aabb_binary_tree/utils.h @@ -0,0 +1,74 @@ +/**************************************************************************** +* VCGLib o o * +* Visual and Computer Graphics Library o o * +* _ O _ * +* Copyright(C) 2004 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program 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 General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +/**************************************************************************** +History + +$Log: not supported by cvs2svn $ + +****************************************************************************/ + +#ifndef __VCGLIB_AABBBINARYTREE_UTILS_H +#define __VCGLIB_AABBBINARYTREE_UTILS_H + +// vcg headers +#include +#include + +/***************************************************************************************/ + +namespace vcg { + +class EmptyClass { +public: + typedef EmptyClass ClassType; +}; + +class ObjPtrIteratorFunctor { +public: + typedef ObjPtrIteratorFunctor ClassType; + + template + inline T * operator () (T & obj) { + return (&obj); + } + + template + inline T * operator () (T * & obj) { + return (obj); + } +}; + +template +inline Point3 Abs(const Point3 & p) { + return (Point3(math::Abs(p[0]), math::Abs(p[1]), math::Abs(p[2]))); +} + +template +inline Point3 LowClampToZero(const Point3 & p) { + return (Point3(math::Max(p[0], (SCALARTYPE)0), math::Max(p[1], (SCALARTYPE)0), math::Max(p[2], (SCALARTYPE)0))); +} + +} // end namespace vcg + +#endif // #ifndef __VCGLIB_AABBBINARYTREE_UTILS_H