1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
* OPCODE - Optimized Collision Detection
* Copyright (C) 2001 Pierre Terdiman
* Homepage: http://www.codercorner.com/Opcode.htm
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains code for tree builders.
* \file OPC_TreeBuilders.h
* \author Pierre Terdiman
* \date March, 20, 2001
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __OPC_TREEBUILDERS_H__
#define __OPC_TREEBUILDERS_H__
//! Tree splitting rules
enum SplittingRules
{
// Primitive split
SPLIT_LARGEST_AXIS = (1<<0), //!< Split along the largest axis
SPLIT_SPLATTER_POINTS = (1<<1), //!< Splatter primitive centers (QuickCD-style)
SPLIT_BEST_AXIS = (1<<2), //!< Try largest axis, then second, then last
SPLIT_BALANCED = (1<<3), //!< Try to keep a well-balanced tree
SPLIT_FIFTY = (1<<4), //!< Arbitrary 50-50 split
// Node split
SPLIT_GEOM_CENTER = (1<<5), //!< Split at geometric center (else split in the middle)
//
SPLIT_FORCE_DWORD = 0x7fffffff
};
//! Simple wrapper around build-related settings [Opcode 1.3]
struct OPCODE_API BuildSettings
{
inline_ BuildSettings() : mLimit(1), mRules(SPLIT_FORCE_DWORD) {}
udword mLimit; //!< Limit number of primitives / node. If limit is 1, build a complete tree (2*N-1 nodes)
udword mRules; //!< Building/Splitting rules (a combination of SplittingRules flags)
};
class OPCODE_API AABBTreeBuilder
{
public:
//! Constructor
AABBTreeBuilder() :
mNbPrimitives(0),
mNodeBase(null),
mCount(0),
mNbInvalidSplits(0) {}
//! Destructor
virtual ~AABBTreeBuilder() {}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the AABB of a set of primitives.
* \param primitives [in] list of indices of primitives
* \param nb_prims [in] number of indices
* \param global_box [out] global AABB enclosing the set of input primitives
* \return true if success
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual bool ComputeGlobalBox(const udword* primitives, udword nb_prims, AABB& global_box) const = 0;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the splitting value along a given axis for a given primitive.
* \param index [in] index of the primitive to split
* \param axis [in] axis index (0,1,2)
* \return splitting value
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual float GetSplittingValue(udword index, udword axis) const = 0;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Computes the splitting value along a given axis for a given node.
* \param primitives [in] list of indices of primitives
* \param nb_prims [in] number of indices
* \param global_box [in] global AABB enclosing the set of input primitives
* \param axis [in] axis index (0,1,2)
* \return splitting value
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual float GetSplittingValue(const udword* primitives, udword nb_prims, const AABB& global_box, udword axis) const
{
// Default split value = middle of the axis (using only the box)
return global_box.GetCenter(axis);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Validates node subdivision. This is called each time a node is considered for subdivision, during tree building.
* \param primitives [in] list of indices of primitives
* \param nb_prims [in] number of indices
* \param global_box [in] global AABB enclosing the set of input primitives
* \return TRUE if the node should be subdivised
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual BOOL ValidateSubdivision(const udword* primitives, udword nb_prims, const AABB& global_box)
{
// Check the user-defined limit
if(nb_prims<=mSettings.mLimit) return FALSE;
return TRUE;
}
BuildSettings mSettings; //!< Splitting rules & split limit [Opcode 1.3]
udword mNbPrimitives; //!< Total number of primitives.
void* mNodeBase; //!< Address of node pool [Opcode 1.3]
// Stats
inline_ void SetCount(udword nb) { mCount=nb; }
inline_ void IncreaseCount(udword nb) { mCount+=nb; }
inline_ udword GetCount() const { return mCount; }
inline_ void SetNbInvalidSplits(udword nb) { mNbInvalidSplits=nb; }
inline_ void IncreaseNbInvalidSplits() { mNbInvalidSplits++; }
inline_ udword GetNbInvalidSplits() const { return mNbInvalidSplits; }
private:
udword mCount; //!< Stats: number of nodes created
udword mNbInvalidSplits; //!< Stats: number of invalid splits
};
class OPCODE_API AABBTreeOfVerticesBuilder : public AABBTreeBuilder
{
public:
//! Constructor
AABBTreeOfVerticesBuilder() : mVertexArray(null) {}
//! Destructor
virtual ~AABBTreeOfVerticesBuilder() {}
override(AABBTreeBuilder) bool ComputeGlobalBox(const udword* primitives, udword nb_prims, AABB& global_box) const;
override(AABBTreeBuilder) float GetSplittingValue(udword index, udword axis) const;
override(AABBTreeBuilder) float GetSplittingValue(const udword* primitives, udword nb_prims, const AABB& global_box, udword axis) const;
const Point* mVertexArray; //!< Shortcut to an app-controlled array of vertices.
};
class OPCODE_API AABBTreeOfAABBsBuilder : public AABBTreeBuilder
{
public:
//! Constructor
AABBTreeOfAABBsBuilder() : mAABBArray(null) {}
//! Destructor
virtual ~AABBTreeOfAABBsBuilder() {}
override(AABBTreeBuilder) bool ComputeGlobalBox(const udword* primitives, udword nb_prims, AABB& global_box) const;
override(AABBTreeBuilder) float GetSplittingValue(udword index, udword axis) const;
const AABB* mAABBArray; //!< Shortcut to an app-controlled array of AABBs.
};
class OPCODE_API AABBTreeOfTrianglesBuilder : public AABBTreeBuilder
{
public:
//! Constructor
AABBTreeOfTrianglesBuilder() : mIMesh(null) {}
//! Destructor
virtual ~AABBTreeOfTrianglesBuilder() {}
override(AABBTreeBuilder) bool ComputeGlobalBox(const udword* primitives, udword nb_prims, AABB& global_box) const;
override(AABBTreeBuilder) float GetSplittingValue(udword index, udword axis) const;
override(AABBTreeBuilder) float GetSplittingValue(const udword* primitives, udword nb_prims, const AABB& global_box, udword axis) const;
const MeshInterface* mIMesh; //!< Shortcut to an app-controlled mesh interface
};
#endif // __OPC_TREEBUILDERS_H__
|