File indexing completed on 2024-05-19 14:56:22

0001 /*
0002 * Copyright (c) 2009 Erin Catto http://www.box2d.org
0003 *
0004 * This software is provided 'as-is', without any express or implied
0005 * warranty.  In no event will the authors be held liable for any damages
0006 * arising from the use of this software.
0007 * Permission is granted to anyone to use this software for any purpose,
0008 * including commercial applications, and to alter it and redistribute it
0009 * freely, subject to the following restrictions:
0010 * 1. The origin of this software must not be misrepresented; you must not
0011 * claim that you wrote the original software. If you use this software
0012 * in a product, an acknowledgment in the product documentation would be
0013 * appreciated but is not required.
0014 * 2. Altered source versions must be plainly marked as such, and must not be
0015 * misrepresented as being the original software.
0016 * 3. This notice may not be removed or altered from any source distribution.
0017 */
0018 
0019 #ifndef B2_DYNAMIC_TREE_H
0020 #define B2_DYNAMIC_TREE_H
0021 
0022 #include <Box2D/Collision/b2Collision.h>
0023 #include <Box2D/Common/b2GrowableStack.h>
0024 
0025 #define b2_nullNode (-1)
0026 
0027 /// A node in the dynamic tree. The client does not interact with this directly.
0028 struct b2TreeNode
0029 {
0030     bool IsLeaf() const
0031     {
0032         return child1 == b2_nullNode;
0033     }
0034 
0035     /// Enlarged AABB
0036     b2AABB aabb;
0037 
0038     void* userData;
0039 
0040     union
0041     {
0042         int32 parent;
0043         int32 next;
0044     };
0045 
0046     int32 child1;
0047     int32 child2;
0048 
0049     // leaf = 0, free node = -1
0050     int32 height;
0051 };
0052 
0053 /// A dynamic AABB tree broad-phase, inspired by Nathanael Presson's btDbvt.
0054 /// A dynamic tree arranges data in a binary tree to accelerate
0055 /// queries such as volume queries and ray casts. Leafs are proxies
0056 /// with an AABB. In the tree we expand the proxy AABB by b2_fatAABBFactor
0057 /// so that the proxy AABB is bigger than the client object. This allows the client
0058 /// object to move by small amounts without triggering a tree update.
0059 ///
0060 /// Nodes are pooled and relocatable, so we use node indices rather than pointers.
0061 class b2DynamicTree
0062 {
0063 public:
0064     /// Constructing the tree initializes the node pool.
0065     b2DynamicTree();
0066 
0067     /// Destroy the tree, freeing the node pool.
0068     ~b2DynamicTree();
0069 
0070     /// Create a proxy. Provide a tight fitting AABB and a userData pointer.
0071     int32 CreateProxy(const b2AABB& aabb, void* userData);
0072 
0073     /// Destroy a proxy. This asserts if the id is invalid.
0074     void DestroyProxy(int32 proxyId);
0075 
0076     /// Move a proxy with a swepted AABB. If the proxy has moved outside of its fattened AABB,
0077     /// then the proxy is removed from the tree and re-inserted. Otherwise
0078     /// the function returns immediately.
0079     /// @return true if the proxy was re-inserted.
0080     bool MoveProxy(int32 proxyId, const b2AABB& aabb1, const b2Vec2& displacement);
0081 
0082     /// Get proxy user data.
0083     /// @return the proxy user data or 0 if the id is invalid.
0084     void* GetUserData(int32 proxyId) const;
0085 
0086     /// Get the fat AABB for a proxy.
0087     const b2AABB& GetFatAABB(int32 proxyId) const;
0088 
0089     /// Query an AABB for overlapping proxies. The callback class
0090     /// is called for each proxy that overlaps the supplied AABB.
0091     template <typename T>
0092     void Query(T* callback, const b2AABB& aabb) const;
0093 
0094     /// Ray-cast against the proxies in the tree. This relies on the callback
0095     /// to perform a exact ray-cast in the case were the proxy contains a shape.
0096     /// The callback also performs the any collision filtering. This has performance
0097     /// roughly equal to k * log(n), where k is the number of collisions and n is the
0098     /// number of proxies in the tree.
0099     /// @param input the ray-cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1).
0100     /// @param callback a callback class that is called for each proxy that is hit by the ray.
0101     template <typename T>
0102     void RayCast(T* callback, const b2RayCastInput& input) const;
0103 
0104     /// Validate this tree. For testing.
0105     void Validate() const;
0106 
0107     /// Compute the height of the binary tree in O(N) time. Should not be
0108     /// called often.
0109     int32 GetHeight() const;
0110 
0111     /// Get the maximum balance of an node in the tree. The balance is the difference
0112     /// in height of the two children of a node.
0113     int32 GetMaxBalance() const;
0114 
0115     /// Get the ratio of the sum of the node areas to the root area.
0116     float32 GetAreaRatio() const;
0117 
0118     /// Build an optimal tree. Very expensive. For testing.
0119     void RebuildBottomUp();
0120 
0121     /// Shift the world origin. Useful for large worlds.
0122     /// The shift formula is: position -= newOrigin
0123     /// @param newOrigin the new origin with respect to the old origin
0124     void ShiftOrigin(const b2Vec2& newOrigin);
0125 
0126 private:
0127 
0128     int32 AllocateNode();
0129     void FreeNode(int32 node);
0130 
0131     void InsertLeaf(int32 node);
0132     void RemoveLeaf(int32 node);
0133 
0134     int32 Balance(int32 index);
0135 
0136     int32 ComputeHeight() const;
0137     int32 ComputeHeight(int32 nodeId) const;
0138 
0139     void ValidateStructure(int32 index) const;
0140     void ValidateMetrics(int32 index) const;
0141 
0142     int32 m_root;
0143 
0144     b2TreeNode* m_nodes;
0145     int32 m_nodeCount;
0146     int32 m_nodeCapacity;
0147 
0148     int32 m_freeList;
0149 
0150     /// This is used to incrementally traverse the tree for re-balancing.
0151     uint32 m_path;
0152 
0153     int32 m_insertionCount;
0154 };
0155 
0156 inline void* b2DynamicTree::GetUserData(int32 proxyId) const
0157 {
0158     b2Assert(0 <= proxyId && proxyId < m_nodeCapacity);
0159     return m_nodes[proxyId].userData;
0160 }
0161 
0162 inline const b2AABB& b2DynamicTree::GetFatAABB(int32 proxyId) const
0163 {
0164     b2Assert(0 <= proxyId && proxyId < m_nodeCapacity);
0165     return m_nodes[proxyId].aabb;
0166 }
0167 
0168 template <typename T>
0169 inline void b2DynamicTree::Query(T* callback, const b2AABB& aabb) const
0170 {
0171     b2GrowableStack<int32, 256> stack;
0172     stack.Push(m_root);
0173 
0174     while (stack.GetCount() > 0)
0175     {
0176         int32 nodeId = stack.Pop();
0177         if (nodeId == b2_nullNode)
0178         {
0179             continue;
0180         }
0181 
0182         const b2TreeNode* node = m_nodes + nodeId;
0183 
0184         if (b2TestOverlap(node->aabb, aabb))
0185         {
0186             if (node->IsLeaf())
0187             {
0188                 bool proceed = callback->QueryCallback(nodeId);
0189                 if (proceed == false)
0190                 {
0191                     return;
0192                 }
0193             }
0194             else
0195             {
0196                 stack.Push(node->child1);
0197                 stack.Push(node->child2);
0198             }
0199         }
0200     }
0201 }
0202 
0203 template <typename T>
0204 inline void b2DynamicTree::RayCast(T* callback, const b2RayCastInput& input) const
0205 {
0206     b2Vec2 p1 = input.p1;
0207     b2Vec2 p2 = input.p2;
0208     b2Vec2 r = p2 - p1;
0209     b2Assert(r.LengthSquared() > 0.0f);
0210     r.Normalize();
0211 
0212     // v is perpendicular to the segment.
0213     b2Vec2 v = b2Cross(1.0f, r);
0214     b2Vec2 abs_v = b2Abs(v);
0215 
0216     // Separating axis for segment (Gino, p80).
0217     // |dot(v, p1 - c)| > dot(|v|, h)
0218 
0219     float32 maxFraction = input.maxFraction;
0220 
0221     // Build a bounding box for the segment.
0222     b2AABB segmentAABB;
0223     {
0224         b2Vec2 t = p1 + maxFraction * (p2 - p1);
0225         segmentAABB.lowerBound = b2Min(p1, t);
0226         segmentAABB.upperBound = b2Max(p1, t);
0227     }
0228 
0229     b2GrowableStack<int32, 256> stack;
0230     stack.Push(m_root);
0231 
0232     while (stack.GetCount() > 0)
0233     {
0234         int32 nodeId = stack.Pop();
0235         if (nodeId == b2_nullNode)
0236         {
0237             continue;
0238         }
0239 
0240         const b2TreeNode* node = m_nodes + nodeId;
0241 
0242         if (b2TestOverlap(node->aabb, segmentAABB) == false)
0243         {
0244             continue;
0245         }
0246 
0247         // Separating axis for segment (Gino, p80).
0248         // |dot(v, p1 - c)| > dot(|v|, h)
0249         b2Vec2 c = node->aabb.GetCenter();
0250         b2Vec2 h = node->aabb.GetExtents();
0251         float32 separation = b2Abs(b2Dot(v, p1 - c)) - b2Dot(abs_v, h);
0252         if (separation > 0.0f)
0253         {
0254             continue;
0255         }
0256 
0257         if (node->IsLeaf())
0258         {
0259             b2RayCastInput subInput;
0260             subInput.p1 = input.p1;
0261             subInput.p2 = input.p2;
0262             subInput.maxFraction = maxFraction;
0263 
0264             float32 value = callback->RayCastCallback(subInput, nodeId);
0265 
0266             if (value == 0.0f)
0267             {
0268                 // The client has terminated the ray cast.
0269                 return;
0270             }
0271 
0272             if (value > 0.0f)
0273             {
0274                 // Update segment bounding box.
0275                 maxFraction = value;
0276                 b2Vec2 t = p1 + maxFraction * (p2 - p1);
0277                 segmentAABB.lowerBound = b2Min(p1, t);
0278                 segmentAABB.upperBound = b2Max(p1, t);
0279             }
0280         }
0281         else
0282         {
0283             stack.Push(node->child1);
0284             stack.Push(node->child2);
0285         }
0286     }
0287 }
0288 
0289 #endif