/**************************************************************************** * 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 $ Revision 1.1 2005/09/26 18:33:16 m_di_benedetto First Commit. ****************************************************************************/ #ifndef __VCGLIB_AABBBINARYTREE_RAY_H #define __VCGLIB_AABBBINARYTREE_RAY_H // stl headers #include // vcg headers #include #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 Ray3 & ray, const ScalarType & maxDist, ScalarType & t) { typedef std::vector NodePtrVector; typedef typename NodePtrVector::const_iterator NodePtrVector_ci; NodeType * pRoot = tree.pRoot; if (pRoot == 0) { return (0); } const CoordType & rayDirection = ray.Direction(); ScalarType rayT = maxDist / rayDirection.Norm(); Ray3Ex rayex; rayex.r = ray; 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, closestObj); if (closestObj == 0) { return (0); } t = rayT; return (closestObj); } protected: class Ray3Ex { public: Ray3 r; 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; const CoordType & origin = ray.r.Origin(); tmin = (bounds[ray.sign[0]][0] - origin[0]) * ray.invDirection[0]; tmax = (bounds[1 - ray.sign[0]][0] - origin[0]) * ray.invDirection[0]; tcmin = (bounds[ray.sign[1]][1] - origin[1]) * ray.invDirection[1]; tcmax = (bounds[1 - ray.sign[1]][1] - 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] - origin[2]) * ray.invDirection[2]; tcmax = (bounds[1-ray.sign[2]][2] - 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, 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 = rayT; for (typename TreeType::ObjPtrVectorConstIterator si=node->oBegin; si!=node->oEnd; ++si) { if (rayIntersection(*(*si), ray.r, ar)) { if (ar < rt) { rt = ar; cObj = (*si); } } } if (rt < rayT) { rayT = rt; closestObj = cObj; } } else { if (node->children[0] != 0) { ClassType::DepthFirstRayIsect(node->children[0], rayIntersection, ray, rayT, closestObj); } if (node->children[1] != 0) { ClassType::DepthFirstRayIsect(node->children[1], rayIntersection, ray, rayT, closestObj); } } } }; } // end namespace vcg #endif // #ifndef __VCGLIB_AABBBINARYTREE_RAY_H