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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
|
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2018 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef SQ_PRUNER_H
#define SQ_PRUNER_H
#include "foundation/PxBounds3.h"
#include "PxGeometry.h"
#include "PxQueryReport.h"
#include "PsUserAllocated.h"
#include "SqPruningStructure.h"
#include "GuSphere.h"
#include "GuBox.h"
#include "GuCapsule.h"
namespace physx
{
namespace Gu
{
class ShapeData;
}
}
namespace physx
{
namespace Cm
{
class RenderOutput;
}
namespace Sq
{
typedef PxU32 PrunerHandle;
static const PrunerHandle INVALID_PRUNERHANDLE = 0xFFffFFff;
static const PxReal SQ_PRUNER_INFLATION = 1.01f; // pruner test shape inflation (not narrow phase shape)
struct PrunerPayload
{
size_t data[2];
PX_FORCE_INLINE bool operator == (const PrunerPayload& other) const
{
return (data[0] == other.data[0]) && (data[1] == other.data[1]);
}
};
struct PrunerCallback
{
virtual PxAgain invoke(PxReal& distance, const PrunerPayload& payload) = 0;
virtual ~PrunerCallback() {}
};
class Pruner : public Ps::UserAllocated
{
public:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* \brief Adds objects to the pruner.
* \param results [out] an array for resulting handles
* \param bounds [in] an array of bounds. These bounds are used as-is so they should be pre-inflated if inflation is needed.
* \param userData [in] an array of object data
* \param count [in] the number of objects in the arrays
* \param hasPruningStructure [in] if added objects have pruning structure. The structure will be merged later, adding the objects will not invalidate the pruner.
*
* \return true if success, false if internal allocation failed. The first failing add results in a INVALID_PRUNERHANDLE.
*
* Handles are usable as indices. Each handle is either be a recycled handle returned by the client via removeObjects(),
* or a fresh handle that is either zero, or one greater than the last fresh handle returned.
*
* Objects and bounds in the arrays have the same number of elements and ordering.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual bool addObjects(PrunerHandle* results, const PxBounds3* bounds, const PrunerPayload* userData, PxU32 count, bool hasPruningStructure) = 0;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Removes objects from the pruner.
* \param handles [in] the objects to remove
* \param count [in] the number of objects to remove
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual void removeObjects(const PrunerHandle* handles, PxU32 count) = 0;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Updates objects after manually updating their bounds via "getPayload" calls.
* \param handles [in] the objects to update
* \param count [in] the number of objects to update
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual void updateObjectsAfterManualBoundsUpdates(const PrunerHandle* handles, PxU32 count) = 0;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Updates objects with new indexed bounds.
* \param handles [in] the objects to update
* \param indices [in] the indices of the bounds in the bounds array
* \param newBounds [in] updated bounds array
* \param count [in] the number of objects to update
*
* \warning THESE BOUNDS WILL BE INFLATED ON-THE-FLY. So this is inconsistent with the "addObjects" behavior.
* \warning The inflation value is hardcoded in Sq::inflateBounds().
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual void updateObjectsAndInflateBounds(const PrunerHandle* handles, const PxU32* indices, const PxBounds3* newBounds, PxU32 count) = 0;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Makes the queries consistent with previous changes.
* This function must be called before starting queries on an updated Pruner and assert otherwise.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual void commit() = 0;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Merges pruning structure to current pruner, parameters may differ for each pruner implementation
* \param mergeParams [in] Pruning structure to merge.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual void merge(const void* mergeParams) = 0;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Query functions
*
* Note: return value may disappear if PrunerCallback contains the necessary information
* currently it is still used for the dynamic pruner internally (to decide if added objects must be queried)
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual PxAgain raycast(const PxVec3& origin, const PxVec3& unitDir, PxReal& inOutDistance, PrunerCallback&) const = 0;
virtual PxAgain overlap(const Gu::ShapeData& queryVolume, PrunerCallback&) const = 0;
virtual PxAgain sweep(const Gu::ShapeData& queryVolume, const PxVec3& unitDir, PxReal& inOutDistance, PrunerCallback&) const = 0;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Retrieve the object data associated with the handle
*
* \param handle The handle returned by addObjects()
*
* \return A reference to the object data
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual const PrunerPayload& getPayload(PrunerHandle handle) const = 0;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Retrieve the object data associated with the handle, plus the destination address for its matrix. The user is then expected to write the new AABB there.
*
* \param handle [in] The handle returned by addObjects()
* \param bounds [out] destination address for this object's bounds
*
* \return A reference to the object data
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual const PrunerPayload& getPayload(PrunerHandle handle, PxBounds3*& bounds) const = 0;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Preallocate space
*
* \param entries the number of entries to preallocate space for
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual void preallocate(PxU32 entries) = 0;
// shift the origin of the pruner objects
virtual void shiftOrigin(const PxVec3& shift) = 0;
virtual ~Pruner() {}
// additional 'internal' interface
virtual void visualize(Cm::RenderOutput&, PxU32) const {}
};
//////////////////////////////////////////////////////////////////////////
/**
* Pruner building accel structure over time base class
*/
//////////////////////////////////////////////////////////////////////////
class IncrementalPruner: public Pruner
{
public:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* gets rid of internal accel struct.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual void purge() = 0;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* sets the rebuild hint rate used for step building the accel structure.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual void setRebuildRateHint(PxU32 nbStepsForRebuild) = 0;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Steps the accel structure build.
* canDoInit specifies if initialization can happen. It should not initialize build when called from a different thread
* returns true if finished
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual bool buildStep(bool canDoInit = true) = 0;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Prepares new tree build
* returns true if new tree is needed
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual bool prepareBuild() = 0;
};
//////////////////////////////////////////////////////////////////////////
/**
* Creates AABBPruner
*/
//////////////////////////////////////////////////////////////////////////
IncrementalPruner* createAABBPruner(bool incrementalRebuild);
}
}
#endif // SQ_PRUNER_H
|