1
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3
* OPCODE - Optimized Collision Detection
4
* Copyright (C) 2001 Pierre Terdiman
5
* Homepage: http://www.codercorner.com/Opcode.htm
7
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11
* Contains code for optimized trees.
12
* \file OPC_OptimizedTree.h
13
* \author Pierre Terdiman
14
* \date March, 20, 2001
16
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
18
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
20
#ifndef __OPC_OPTIMIZEDTREE_H__
21
#define __OPC_OPTIMIZEDTREE_H__
29
//! Common interface for a node of an implicit tree
30
#define IMPLEMENT_IMPLICIT_NODE(base_class, volume) \
32
/* Constructor / Destructor */ \
33
inline_ base_class() : mData(0) {} \
34
inline_ ~base_class() {} \
36
inline_ BOOL IsLeaf() const { return mData&1; } \
38
inline_ const base_class* GetPos() const { return (base_class*)mData; } \
39
inline_ const base_class* GetNeg() const { return ((base_class*)mData)+1; } \
40
/* Modified by S-cubed, Inc. */ \
41
inline_ const base_class* GetB() const { return mB; } \
42
inline_ udword GetPrimitive() const { return (mData>>1); } \
44
inline_ udword GetNodeSize() const { return SIZEOFOBJECT; } \
48
/* Modified by S-cubed, Inc. */ \
51
//! Common interface for a node of a no-leaf tree
52
#define IMPLEMENT_NOLEAF_NODE(base_class, volume) \
54
/* Constructor / Destructor */ \
55
inline_ base_class() : mPosData(0), mNegData(0) {} \
56
inline_ ~base_class() {} \
58
inline_ BOOL HasPosLeaf() const { return mPosData&1; } \
59
inline_ BOOL HasNegLeaf() const { return mNegData&1; } \
61
inline_ const base_class* GetPos() const { return (base_class*)mPosData; } \
62
inline_ const base_class* GetNeg() const { return (base_class*)mNegData; } \
63
/* Modified by S-cubed, Inc. */ \
64
inline_ const base_class* GetB() const { return mB; } \
65
inline_ udword GetPosPrimitive() const { return (mPosData>>1); } \
66
inline_ udword GetNegPrimitive() const { return (mNegData>>1); } \
68
inline_ udword GetNodeSize() const { return SIZEOFOBJECT; } \
73
/* Modified by S-cubed, Inc. */ \
76
class OPCODE_API AABBCollisionNode
78
IMPLEMENT_IMPLICIT_NODE(AABBCollisionNode, CollisionAABB)
80
inline_ float GetVolume() const { return mAABB.mExtents.x * mAABB.mExtents.y * mAABB.mExtents.z; }
81
inline_ float GetSize() const { return mAABB.mExtents.SquareMagnitude(); }
82
inline_ udword GetRadius() const
84
udword* Bits = (udword*)&mAABB.mExtents.x;
86
if(Bits[1]>Max) Max = Bits[1];
87
if(Bits[2]>Max) Max = Bits[2];
91
// NB: using the square-magnitude or the true volume of the box, seems to yield better results
92
// (assuming UNC-like informed traversal methods). I borrowed this idea from PQP. The usual "size"
93
// otherwise, is the largest box extent. In SOLID that extent is computed on-the-fly each time it's
94
// needed (the best approach IMHO). In RAPID the rotation matrix is permuted so that Extent[0] is
95
// always the greatest, which saves looking for it at runtime. On the other hand, it yields matrices
96
// whose determinant is not 1, i.e. you can't encode them anymore as unit quaternions. Not a very
100
class OPCODE_API AABBQuantizedNode
102
IMPLEMENT_IMPLICIT_NODE(AABBQuantizedNode, QuantizedAABB)
104
inline_ uword GetSize() const
106
const uword* Bits = mAABB.mExtents;
108
if(Bits[1]>Max) Max = Bits[1];
109
if(Bits[2]>Max) Max = Bits[2];
112
// NB: for quantized nodes I don't feel like computing a square-magnitude with integers all
113
// over the place.......!
116
class OPCODE_API AABBNoLeafNode
118
IMPLEMENT_NOLEAF_NODE(AABBNoLeafNode, CollisionAABB)
121
class OPCODE_API AABBQuantizedNoLeafNode
123
IMPLEMENT_NOLEAF_NODE(AABBQuantizedNoLeafNode, QuantizedAABB)
126
//! Common interface for a collision tree
127
#define IMPLEMENT_COLLISION_TREE(base_class, node) \
129
/* Constructor / Destructor */ \
131
virtual ~base_class(); \
132
/* Builds from a standard tree */ \
133
override(AABBOptimizedTree) bool Build(AABBTree* tree); \
134
/* Refits the tree */ \
135
override(AABBOptimizedTree) bool Refit(const MeshInterface* mesh_interface); \
136
/* Walks the tree */ \
137
override(AABBOptimizedTree) bool Walk(GenericWalkingCallback callback, void* user_data) const; \
139
inline_ const node* GetNodes() const { return mNodes; } \
141
override(AABBOptimizedTree) udword GetUsedBytes() const { return mNbNodes*sizeof(node); } \
145
typedef bool (*GenericWalkingCallback) (const void* current, void* user_data);
147
class OPCODE_API AABBOptimizedTree
150
// Constructor / Destructor
151
AABBOptimizedTree() :
154
virtual ~AABBOptimizedTree() {}
156
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
158
* Builds the collision tree from a generic AABB tree.
159
* \param tree [in] generic AABB tree
160
* \return true if success
162
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
163
virtual bool Build(AABBTree* tree) = 0;
165
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
167
* Refits the collision tree after vertices have been modified.
168
* \param mesh_interface [in] mesh interface for current model
169
* \return true if success
171
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
172
virtual bool Refit(const MeshInterface* mesh_interface) = 0;
174
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
176
* Walks the tree and call the user back for each node.
177
* \param callback [in] walking callback
178
* \param user_data [in] callback's user data
179
* \return true if success
181
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
182
virtual bool Walk(GenericWalkingCallback callback, void* user_data) const = 0;
185
virtual udword GetUsedBytes() const = 0;
186
inline_ udword GetNbNodes() const { return mNbNodes; }
192
class OPCODE_API AABBCollisionTree : public AABBOptimizedTree
194
IMPLEMENT_COLLISION_TREE(AABBCollisionTree, AABBCollisionNode)
197
class OPCODE_API AABBNoLeafTree : public AABBOptimizedTree
199
IMPLEMENT_COLLISION_TREE(AABBNoLeafTree, AABBNoLeafNode)
202
class OPCODE_API AABBQuantizedTree : public AABBOptimizedTree
204
IMPLEMENT_COLLISION_TREE(AABBQuantizedTree, AABBQuantizedNode)
211
class OPCODE_API AABBQuantizedNoLeafTree : public AABBOptimizedTree
213
IMPLEMENT_COLLISION_TREE(AABBQuantizedNoLeafTree, AABBQuantizedNoLeafNode)
220
#endif // __OPC_OPTIMIZEDTREE_H__