aboutsummaryrefslogtreecommitdiff
path: root/PhysX_3.4/Source/SceneQuery/src/SqAABBPruner.h
blob: 07b6f119d3ca1c7cf7c3f3dcced7814d869a1d35 (plain) (blame)
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
257
258
259
260
261
262
263
264
265
266
267
268
269
//
// 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_AABB_PRUNER_H
#define SQ_AABB_PRUNER_H

#include "SqPruningPool.h"
#include "SqExtendedBucketPruner.h"
#include "SqAABBTreeUpdateMap.h"
#include "SqAABBTree.h"

namespace physx
{

namespace Sq
{
	// PT: we build the new tree over a number of frames/states, in order to limit perf spikes in 'updatePruningTrees'.
	// The states are as follows:
	//
	// BUILD_NOT_STARTED (1 frame, AABBPruner):
	//
	// This is the initial state, before the new (AABBTree) build even starts. In this frame/state, we perform the AABBPruner-related
	// memory allocations:
	// - the new AABB tree is allocated
	// - the array of cached bounding boxes is allocated and filled
	//
	// BUILD_INIT (1 frame, AABBTree):
	//
	// This is the first frame in which the new tree gets built. It deserves its own special state since various things happen in the
	// first frame, that do no happen in subsequent frames. Basically most initial AABBTree-related allocations happen here (but no
	// build step per se).
	//
	// BUILD_IN_PROGRESS (N frames, AABBTree):
	//
	// This is the core build function, actually building the tree. This should be mostly allocation-free, except here and there when
	// building non-complete trees, and during the last call when the tree is finally built.
	//
	// BUILD_NEW_MAPPING (1 frame, AABBPruner):
	//
	// After the new AABBTree is built, we recreate an AABBTreeUpdateMap for the new tree, and use it to invalidate nodes whose objects
	// have been removed during the build.
	//
	// We need to do that before doing a full refit in the next stage/frame. If we don't do that, the refit code will fetch a wrong box,
	// that may very well belong to an entirely new object.
	//
	// Note that this mapping/update map (mNewTreeMap) is temporary, and only needed for the next stage.
	//
	// BUILD_FULL_REFIT (1 frame, AABBPruner):
	//
	// Once the new update map is available, we fully refit the new tree. AABBs of moved objects get updated. AABBs of removed objects
	// become empty.
	//
	// BUILD_LAST_FRAME (1 frame, AABBPruner):
	//
	// This is an artificial frame used to delay the tree switching code. The switch happens as soon as we reach the BUILD_FINISHED
	// state, but we don't want to execute BUILD_FULL_REFIT and the switch in the same frame. This extra BUILD_LAST_FRAME stage buys
	// us one frame, i.e. we have one frame in which we do BUILD_FULL_REFIT, and in the next frame we'll do both BUILD_LAST_FRAME /
	// BUILD_FINISHED / the switch.
	//
	// BUILD_FINISHED (1 frame, AABBPruner):
	//
	// Several things happen in this 'finalization' frame/stage:
	// - We switch the trees (old one is deleted, cached boxes are deleted, new tree pointer is setup)
	// - A new (final) update map is created (mTreeMap). The map is used to invalidate objects that may have been removed during
	//   the BUILD_NEW_MAPPING and BUILD_FULL_REFIT frames. The nodes containing these removed objects are marked for refit.
	// - Nodes containing objects that have moved during the BUILD_NEW_MAPPING and BUILD_FULL_REFIT frames are marked for refit.
	// - We do a partial refit on the new tree, to take these final changes into account. This small partial refit is usually much
	//   cheaper than the full refit we previously performed here.
	// - We remove old objects from the bucket pruner
	//
	enum BuildStatus
	{
		BUILD_NOT_STARTED,
		BUILD_INIT,
		BUILD_IN_PROGRESS,
		BUILD_NEW_MAPPING,
		BUILD_FULL_REFIT,
		BUILD_LAST_FRAME,
		BUILD_FINISHED,

		BUILD_FORCE_DWORD	= 0xffffffff
	};

	// This class implements the Pruner interface for internal SQ use with some additional specialized functions
	// The underlying data structure is a binary AABB tree
	// AABBPruner supports insertions, removals and updates for dynamic objects
	// The tree is either entirely rebuilt in a single frame (static pruner) or progressively rebuilt over multiple frames (dynamic pruner)
	// The rebuild happens on a copy of the tree
	// the copy is then swapped with current tree at the time commit() is called (only if mBuildState is BUILD_FINISHED),
	// otherwise commit() will perform a refit operation applying any pending changes to the current tree
	// While the tree is being rebuilt a temporary data structure (BucketPruner) is also kept in sync and used to speed up
	// queries on updated objects that are not yet in either old or new tree.
	// The requirements on the order of calls:
	// commit() is required to be called before any queries to apply modifications
	// queries can be issued on multiple threads after commit is called
	// commit, buildStep, add/remove/update have to be called from the same thread or otherwise strictly serialized by external code
	// and cannot be issued while a query is running
	class AABBPruner : public IncrementalPruner
	{
		public:
												AABBPruner(bool incrementalRebuild, PxU64 contextID); // true is equivalent to former dynamic pruner
		virtual									~AABBPruner();

		// Pruner
		virtual			bool					addObjects(PrunerHandle* results, const PxBounds3* bounds, const PrunerPayload* userData, PxU32 count, bool hasPruningStructure);
		virtual			void					removeObjects(const PrunerHandle* handles, PxU32 count);
		virtual			void					updateObjectsAfterManualBoundsUpdates(const PrunerHandle* handles, PxU32 count);
		virtual			void					updateObjectsAndInflateBounds(const PrunerHandle* handles, const PxU32* indices, const PxBounds3* newBounds, PxU32 count);
		virtual			void					commit();
		virtual			PxAgain					raycast(const PxVec3& origin, const PxVec3& unitDir, PxReal& inOutDistance, PrunerCallback&)	const;
		virtual			PxAgain					overlap(const Gu::ShapeData& queryVolume, PrunerCallback&)	const;
		virtual			PxAgain					sweep(const Gu::ShapeData& queryVolume, const PxVec3& unitDir, PxReal& inOutDistance, PrunerCallback&)	const;
		virtual			const PrunerPayload&	getPayload(PrunerHandle handle)						const	{ return mPool.getPayload(handle);			}
		virtual			const PrunerPayload&	getPayload(PrunerHandle handle, PxBounds3*& bounds)	const	{ return mPool.getPayload(handle, bounds);	}
		virtual			void					preallocate(PxU32 entries)									{ mPool.preallocate(entries);				}
		virtual			void					shiftOrigin(const PxVec3& shift);
		virtual			void					visualize(Cm::RenderOutput& out, PxU32 color) const;		
		virtual			void					merge(const void* mergeParams);
		//~Pruner
		
		// IncrementalPruner
		virtual			void					purge();		// gets rid of internal accel struct
		virtual			void					setRebuildRateHint(PxU32 nbStepsForRebuild);	// Besides the actual rebuild steps, 3 additional steps are needed.
		virtual			bool					buildStep(bool synchronousCall = true);	// returns true if finished
		virtual			bool					prepareBuild();	// returns true if new tree is needed
		//~IncrementalPruner

		// direct access for test code

		PX_FORCE_INLINE	PxU32					getNbAddedObjects()	const		{ return mBucketPruner.getNbObjects();					}
		PX_FORCE_INLINE	const Sq::AABBTree*		getAABBTree()		const		{ PX_ASSERT(!mUncommittedChanges); return mAABBTree;	}
		PX_FORCE_INLINE	Sq::AABBTree*			getAABBTree()					{ PX_ASSERT(!mUncommittedChanges); return mAABBTree;	}
		PX_FORCE_INLINE	void					setAABBTree(Sq::AABBTree* tree)	{ mAABBTree = tree; }
		PX_FORCE_INLINE	const Sq::AABBTree*		hasAABBTree()		const		{ return mAABBTree;	}
		PX_FORCE_INLINE	BuildStatus				getBuildStatus()	const		{ return mProgress;	}
				
		// local functions
//		private:
						Sq::AABBTree*			mAABBTree; // current active tree
						Sq::AABBTreeBuildParams	mBuilder; // this class deals with the details of the actual tree building
						BuildStats				mBuildStats;

		// tree with build in progress, assigned to mAABBTree in commit, when mProgress is BUILD_FINISHED
		// created in buildStep(), BUILD_NOT_STARTED
		// This is non-null when there is a tree rebuild going on in progress
		// and thus also indicates that we have to start saving the fixups
						Sq::AABBTree*			mNewTree;

		// during rebuild the pool might change so we need a copy of boxes for the tree build
						PxBounds3*				mCachedBoxes;
						PxU32					mNbCachedBoxes;

		// incremented in commit(), serves as a progress counter for rebuild
						PxU32					mNbCalls;

		// PT: incremented each time we start building a new tree (i.e. effectively identifies a given tree)
		// Timestamp is passed to bucket pruner to mark objects added there, linking them to a specific tree.
		// When switching to the new tree, timestamp is used to remove old objects (now in the new tree) from
		// the bucket pruner.
						PxU32					mTimeStamp;

		// this pruner is used for queries on objects that are not in the current tree yet
		// includes both the objects in the tree being rebuilt and all the objects added later
						ExtendedBucketPruner	mBucketPruner;

						BuildStatus				mProgress;		// current state of second tree build progress

		// Fraction (as in 1/Nth) of the total number of primitives
		// that should be processed per step by the AABB builder
		// so if this value is 1, all primitives will be rebuilt, 2 => 1/2 of primitives per step etc.
		// see also mNbCalls, mNbCalls varies from 0 to mRebuildRateHint-1
						PxU32					mRebuildRateHint;

		// Estimate for how much work has to be done to rebuild the tree.
						PxU32					mTotalWorkUnits;

		// Term to correct the work unit estimate if the rebuild rate is not matched
						PxI32					mAdaptiveRebuildTerm;

						PruningPool				mPool; // Pool of AABBs

		// maps pruning pool indices to aabb tree indices
		// maps to INVALID_NODE_ID if the pool entry was removed or "pool index is outside input domain"
		// The map is the inverse of the tree mapping: (node[map[poolID]].primitive == poolID)
		// So:
		// treeNodeIndex = mTreeMap.operator[](poolIndex)
		// aabbTree->treeNodes[treeNodeIndex].primitives[0] == poolIndex
						AABBTreeUpdateMap		mTreeMap;
		// Temporary update map, see BuildStatus notes above for details
						AABBTreeUpdateMap		mNewTreeMap;

		// This is only set once in the constructor and is equivalent to isDynamicTree
		// if it set to false then a 1-shot rebuild is performed in commit()
		// bucket pruner is only used with incremental rebuild
						bool					mIncrementalRebuild;

		// A rebuild can be triggered even when the Pruner is not dirty
		// mUncommittedChanges is set to true in add, remove, update and buildStep
		// mUncommittedChanges is set to false in commit
		// mUncommittedChanges has to be false (commit() has to be called) in order to run a query as defined by the
		// mUncommittedChanges is not set to true in add, when pruning structure is provided. Scene query shapes
		// are merged to current AABB tree directly
		// Pruner higher level API
						bool					mUncommittedChanges;

		// A new AABB tree is built if an object was added, removed or updated
		// Changing objects during a build will trigger another rebuild right afterwards
		// this is set to true if a new tree has to be created again after the current rebuild is done
						bool					mNeedsNewTree;

		// This struct is used to record modifications made to the pruner state
		// while a tree is building in the background
		// this is so we can apply the modifications to the tree at the time of completion
		// the recorded fixup information is: removedIndex (in ::remove()) and 
		// lastIndexMoved which is the last index in the pruner array
		// (since the way we remove from PruningPool is by swapping last into removed slot,
		// we need to apply a fixup so that it syncs up that operation in the new tree)
						struct NewTreeFixup
						{
							PX_FORCE_INLINE NewTreeFixup(PxU32 removedIndex_, PxU32 relocatedLastIndex_)
								: removedIndex(removedIndex_), relocatedLastIndex(relocatedLastIndex_) {}
							PxU32 removedIndex;
							PxU32 relocatedLastIndex;
						};
						Ps::Array<NewTreeFixup>	mNewTreeFixups;

						Ps::Array<PoolIndex>	mToRefit;

						PxU64					mContextID;

		// Internal methods
						bool					fullRebuildAABBTree(); // full rebuild function, used with static pruner mode
						void					release();
						void					refitUpdatedAndRemoved();
						void					updateBucketPruner();
						PxBounds3				getAABB(PrunerHandle h);
	};

} // namespace Sq

}

#endif // SQ_AABB_PRUNER_H