Nori
|
00001 /* 00002 This class contains a implementation of a KD-Tree to compute ray-triangle 00003 intersections in three dimensions. It was originally part of Mitsuba and 00004 slightly adapted for 00005 00006 Copyright (c) 2007-2012 by Wenzel Jakob 00007 00008 Mitsuba is free software; you can redistribute it and/or modify 00009 it under the terms of the GNU General Public License Version 3 00010 as published by the Free Software Foundation. 00011 00012 Mitsuba is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with this program. If not, see <http://www.gnu.org/licenses/>. 00019 */ 00020 00021 #if !defined(__KDTREE_H) 00022 #define __KDTREE_H 00023 00024 #include <nori/gkdtree.h> 00025 #include <nori/mesh.h> 00026 00027 NORI_NAMESPACE_BEGIN 00028 00029 /** 00030 * \brief Specializes \ref GenericKDTree to a three-dimensional 00031 * tree that can be used to intersect rays against triangles meshes. 00032 * 00033 * The internal tree construction algorithm generates a surface area 00034 * heuristic (SAH) kd-tree using the "perfect splits" optimization. 00035 * 00036 * This class also implements an robust adapted version of the optimized 00037 * ray traversal algorithm (TA^B_{rec}), which is explained in Vlastimil 00038 * Havran's PhD thesis "Heuristic Ray Shooting Algorithms". 00039 * 00040 * \author Wenzel Jakob 00041 */ 00042 class KDTree : public GenericKDTree<BoundingBox3f, SurfaceAreaHeuristic3, KDTree> { 00043 protected: 00044 typedef GenericKDTree<BoundingBox3f, SurfaceAreaHeuristic3, KDTree> Parent; 00045 typedef Parent::SizeType SizeType; 00046 typedef Parent::IndexType IndexType; 00047 typedef Parent::KDNode KDNode; 00048 00049 using Parent::m_nodes; 00050 using Parent::m_bbox; 00051 using Parent::m_indices; 00052 00053 public: 00054 /// Create a new and empty kd-tree 00055 KDTree(); 00056 00057 /// Release all memory 00058 virtual ~KDTree(); 00059 00060 /** 00061 * \brief Register a triangle mesh for inclusion in the kd-tree. 00062 * 00063 * This function can only be used before \ref build() is called 00064 */ 00065 void addMesh(Mesh *mesh); 00066 00067 /// Build the kd-tree 00068 void build(); 00069 00070 /** 00071 * \brief Intersect a ray against all triangle meshes registered 00072 * with the kd-tree 00073 * 00074 * Detailed information about the intersection, if any, will be 00075 * stored in the provided \ref Intersection data record. 00076 * 00077 * The <tt>shadowRay</tt> parameter specifies whether this detailed 00078 * information is really needed. When set to \c true, the 00079 * function just checks whether or not there is occlusion, but without 00080 * providing any more detail (i.e. \c its will not be filled with 00081 * contents). This is usually much faster. 00082 * 00083 * \return \c true If an intersection was found 00084 */ 00085 bool rayIntersect(const Ray3f &ray, Intersection &its, 00086 bool shadowRay = false) const; 00087 00088 /// Return the total number of internally represented triangles 00089 inline SizeType getPrimitiveCount() const { return m_primitiveCount; } 00090 00091 /// Return the total number of meshes registered with the kd-tree 00092 inline SizeType getMeshCount() const { return (SizeType) m_meshes.size(); } 00093 00094 /// Return one of the registered meshes 00095 inline Mesh *getMesh(IndexType idx) { return m_meshes[idx]; } 00096 00097 /// Return one of the registered meshes (const version) 00098 inline const Mesh *getMesh(IndexType idx) const { return m_meshes[idx]; } 00099 00100 //// Return an axis-aligned bounding box containing the entire tree 00101 inline const BoundingBox3f &getBoundingBox() const { 00102 return m_bbox; 00103 } 00104 00105 //// Return an axis-aligned bounding box containing the given triangle 00106 inline BoundingBox3f getBoundingBox(IndexType index) const { 00107 IndexType meshIdx = findMesh(index); 00108 return m_meshes[meshIdx]->getBoundingBox(index); 00109 } 00110 00111 /** 00112 * \brief Returns the axis-aligned bounding box of a triangle after it has 00113 * clipped to the extents of another given bounding box. 00114 * 00115 * See \ref Mesh::getClippedBoundingBox() for details 00116 */ 00117 inline BoundingBox3f getClippedBoundingBox(IndexType index, const BoundingBox3f &clip) const { 00118 IndexType meshIdx = findMesh(index); 00119 return m_meshes[meshIdx]->getClippedBoundingBox(index, clip); 00120 } 00121 protected: 00122 /** 00123 * \brief Compute the mesh and triangle indices corresponding to 00124 * a primitive index used by the underlying generic kd-tree implementation. 00125 */ 00126 IndexType findMesh(IndexType &idx) const { 00127 std::vector<IndexType>::const_iterator it = std::lower_bound( 00128 m_sizeMap.begin(), m_sizeMap.end(), idx+1) - 1; 00129 idx -= *it; 00130 return (IndexType) (it - m_sizeMap.begin()); 00131 } 00132 private: 00133 std::vector<Mesh *> m_meshes; 00134 std::vector<SizeType> m_sizeMap; 00135 SizeType m_primitiveCount; 00136 }; 00137 00138 NORI_NAMESPACE_END 00139 00140 #endif /* __KDTREE_H */