RavEngine
Loading...
Searching...
No Matches
DyThresholdTable.h
1// Redistribution and use in source and binary forms, with or without
2// modification, are permitted provided that the following conditions
3// are met:
4// * Redistributions of source code must retain the above copyright
5// notice, this list of conditions and the following disclaimer.
6// * Redistributions in binary form must reproduce the above copyright
7// notice, this list of conditions and the following disclaimer in the
8// documentation and/or other materials provided with the distribution.
9// * Neither the name of NVIDIA CORPORATION nor the names of its
10// contributors may be used to endorse or promote products derived
11// from this software without specific prior written permission.
12//
13// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
14// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24//
25// Copyright (c) 2008-2022 NVIDIA Corporation. All rights reserved.
26// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
27// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
28
29#ifndef DY_THRESHOLD_TABLE_H
30#define DY_THRESHOLD_TABLE_H
31
32#include "foundation/PxPinnedArray.h"
33#include "foundation/PxUserAllocated.h"
34#include "foundation/PxHash.h"
35#include "foundation/PxMemory.h"
36#include "PxNodeIndex.h"
37
38namespace physx
39{
40
41class PxsRigidBody;
42
43namespace Sc
44{
45 class ShapeInteraction;
46}
47
48namespace Dy
49{
50
52{
53 Sc::ShapeInteraction* shapeInteraction; //4/8 4/8
54 PxReal normalForce; //4 8/12
55 PxReal threshold; //4 12/16
56 PxNodeIndex nodeIndexA; //8 24 This is the unique node index in island gen which corresonding to that body and it is persistent 16 20
57 PxNodeIndex nodeIndexB; //8 32 This is the unique node index in island gen which corresonding to that body and it is persistent 20 24
58 PxReal accumulatedForce; //4 36
59 PxU32 pad; //4 40
60
61 PX_CUDA_CALLABLE bool operator <= (const ThresholdStreamElement& otherPair) const
62 {
63 return ((nodeIndexA < otherPair.nodeIndexA) ||(nodeIndexA == otherPair.nodeIndexA && nodeIndexB <= otherPair.nodeIndexB));
64 }
65
66 PX_CUDA_CALLABLE bool operator < (const ThresholdStreamElement& otherPair) const
67 {
68 return ((nodeIndexA < otherPair.nodeIndexA) || (nodeIndexA == otherPair.nodeIndexA && nodeIndexB < otherPair.nodeIndexB));
69 }
70
71 PX_CUDA_CALLABLE bool operator == (const ThresholdStreamElement& otherPair) const
72 {
73 return ((nodeIndexA == otherPair.nodeIndexA && nodeIndexB == otherPair.nodeIndexB));
74 }
75
76};
77
79
81{
82public:
83 ThresholdStream(PxVirtualAllocatorCallback& allocatorCallback) : ThresholdArray(PxVirtualAllocator(&allocatorCallback))
84 {
85 }
86
87};
88
90{
91public:
92
94 : mBuffer(NULL),
95 mHash(NULL),
96 mHashSize(0),
97 mHashCapactiy(0),
98 mPairs(NULL),
99 mNexts(NULL),
100 mPairsSize(0),
101 mPairsCapacity(0)
102 {
103 }
104
106 {
107 PX_FREE(mBuffer);
108 }
109
110 void build(const ThresholdStream& stream);
111
112 bool check(const ThresholdStream& stream, const PxU32 nodexIndexA, const PxU32 nodexIndexB, PxReal dt);
113
114 bool check(const ThresholdStream& stream, const ThresholdStreamElement& elem, PxU32& thresholdIndex);
115
116//private:
117
118 static const PxU32 NO_INDEX = 0xffffffff;
119
120 struct Pair
121 {
122 PxU32 thresholdStreamIndex;
123 PxReal accumulatedForce;
124 //PxU32 next; // hash key & next ptr
125 };
126
127 PxU8* mBuffer;
128
129 PxU32* mHash;
130 PxU32 mHashSize;
131 PxU32 mHashCapactiy;
132
133 Pair* mPairs;
134 PxU32* mNexts;
135 PxU32 mPairsSize;
136 PxU32 mPairsCapacity;
137};
138
139namespace
140{
141 static PX_FORCE_INLINE PxU32 computeHashKey(const PxU32 nodeIndexA, const PxU32 nodeIndexB, const PxU32 hashCapacity)
142 {
143 return (PxComputeHash(PxU64(nodeIndexA)<<32 | PxU64(nodeIndexB)) % hashCapacity);
144 }
145}
146
147inline bool ThresholdTable::check(const ThresholdStream& stream, const ThresholdStreamElement& elem, PxU32& thresholdIndex)
148{
149 PxU32* PX_RESTRICT hashes = mHash;
150 PxU32* PX_RESTRICT nextIndices = mNexts;
151 Pair* PX_RESTRICT pairs = mPairs;
152
153 PX_ASSERT(elem.nodeIndexA < elem.nodeIndexB);
154 PxU32 hashKey = computeHashKey(elem.nodeIndexA.index(), elem.nodeIndexB.index(), mHashSize);
155
156 PxU32 pairIndex = hashes[hashKey];
157
158 while(NO_INDEX != pairIndex)
159 {
160 Pair& pair = pairs[pairIndex];
161 const PxU32 thresholdStreamIndex = pair.thresholdStreamIndex;
162 PX_ASSERT(thresholdStreamIndex < stream.size());
163 const ThresholdStreamElement& otherElement = stream[thresholdStreamIndex];
164 if(otherElement.nodeIndexA==elem.nodeIndexA && otherElement.nodeIndexB==elem.nodeIndexB && otherElement.shapeInteraction == elem.shapeInteraction)
165 {
166 thresholdIndex = thresholdStreamIndex;
167 return true;
168 }
169 pairIndex = nextIndices[pairIndex];
170 }
171
172 thresholdIndex = NO_INDEX;
173 return false;
174}
175
176
177inline void ThresholdTable::build(const ThresholdStream& stream)
178{
179 //Handle the case of an empty stream.
180 if(0==stream.size())
181 {
182 mPairsSize=0;
183 mPairsCapacity=0;
184 mHashSize=0;
185 mHashCapactiy=0;
186 PX_FREE(mBuffer);
187 return;
188 }
189
190 //Realloc/resize if necessary.
191 const PxU32 pairsCapacity = stream.size();
192 const PxU32 hashCapacity = pairsCapacity*2+1;
193 if((pairsCapacity > mPairsCapacity) || (pairsCapacity < (mPairsCapacity >> 2)))
194 {
195 PX_FREE(mBuffer);
196 const PxU32 pairsByteSize = sizeof(Pair)*pairsCapacity;
197 const PxU32 nextsByteSize = sizeof(PxU32)*pairsCapacity;
198 const PxU32 hashByteSize = sizeof(PxU32)*hashCapacity;
199 const PxU32 totalByteSize = pairsByteSize + nextsByteSize + hashByteSize;
200 mBuffer = reinterpret_cast<PxU8*>(PX_ALLOC(totalByteSize, "PxThresholdStream"));
201
202 PxU32 offset = 0;
203 mPairs = reinterpret_cast<Pair*>(mBuffer + offset);
204 offset += pairsByteSize;
205 mNexts = reinterpret_cast<PxU32*>(mBuffer + offset);
206 offset += nextsByteSize;
207 mHash = reinterpret_cast<PxU32*>(mBuffer + offset);
208 offset += hashByteSize;
209 PX_ASSERT(totalByteSize == offset);
210
211 mPairsCapacity = pairsCapacity;
212 mHashCapactiy = hashCapacity;
213 }
214
215
216 //Set each entry of the hash table to 0xffffffff
217 PxMemSet(mHash, 0xff, sizeof(PxU32)*hashCapacity);
218
219 //Init the sizes of the pairs array and hash array.
220 mPairsSize = 0;
221 mHashSize = hashCapacity;
222
223 PxU32* PX_RESTRICT hashes = mHash;
224 PxU32* PX_RESTRICT nextIndices = mNexts;
225 Pair* PX_RESTRICT pairs = mPairs;
226
227 //Add all the pairs from the stream.
228 PxU32 pairsSize = 0;
229 for(PxU32 i = 0; i < pairsCapacity; i++)
230 {
231 const ThresholdStreamElement& element = stream[i];
232 const PxNodeIndex nodeIndexA = element.nodeIndexA;
233 const PxNodeIndex nodeIndexB = element.nodeIndexB;
234
235 const PxF32 force = element.normalForce;
236
237 PX_ASSERT(nodeIndexA < nodeIndexB);
238
239 const PxU32 hashKey = computeHashKey(nodeIndexA.index(), nodeIndexB.index(), hashCapacity);
240
241 //Get the index of the first pair found that resulted in a hash that matched hashKey.
242 PxU32 prevPairIndex = hashKey;
243 PxU32 pairIndex = hashes[hashKey];
244
245 //Search through all pairs found that resulted in a hash that matched hashKey.
246 //Search until the exact same body pair is found.
247 //Increment the accumulated force if the exact same body pair is found.
248 while(NO_INDEX != pairIndex)
249 {
250 Pair& pair = pairs[pairIndex];
251 const PxU32 thresholdStreamIndex = pair.thresholdStreamIndex;
252 PX_ASSERT(thresholdStreamIndex < stream.size());
253 const ThresholdStreamElement& otherElement = stream[thresholdStreamIndex];
254 if(nodeIndexA == otherElement.nodeIndexA && nodeIndexB==otherElement.nodeIndexB)
255 {
256 pair.accumulatedForce += force;
257 prevPairIndex = NO_INDEX;
258 pairIndex = NO_INDEX;
259 break;
260 }
261 prevPairIndex = pairIndex;
262 pairIndex = nextIndices[pairIndex];
263 }
264
265 if(NO_INDEX != prevPairIndex)
266 {
267 nextIndices[pairsSize] = hashes[hashKey];
268 hashes[hashKey] = pairsSize;
269 Pair& newPair = pairs[pairsSize];
270 newPair.thresholdStreamIndex = i;
271 newPair.accumulatedForce = force;
272 pairsSize++;
273 }
274 }
275 mPairsSize = pairsSize;
276}
277
278}
279
280}
281
282#endif
A generic couple structure.
Definition GuCookingConvexPolygonsBuilder.cpp:76
Definition DyThresholdTable.h:81
Definition DyThresholdTable.h:90
Definition PxArray.h:53
PxNodeIndex.
Definition PxNodeIndex.h:51
Definition PxUserAllocated.h:43
Definition PxAllocator.h:140
Definition PxAllocator.h:158
Definition ScShapeInteraction.h:54
#define PX_RESTRICT
Definition PxPreprocessor.h:355
#define PX_FORCE_INLINE
Definition PxPreprocessor.h:335
Sorts an array of objects in ascending order, assuming that the predicate implements the < operator:
Definition PxBoxController.h:39
PX_FORCE_INLINE void * PxMemSet(void *dest, PxI32 c, PxU32 count)
Sets the bytes of the provided buffer to the specified value.
Definition PxMemory.h:67
Definition DyThresholdTable.h:52
Definition DyThresholdTable.h:121