RavEngine
Loading...
Searching...
No Matches
GuPCMContactConvexCommon.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 GU_PCM_CONTACT_CONVEX_COMMON_H
30#define GU_PCM_CONTACT_CONVEX_COMMON_H
31
32#define PCM_MAX_CONTACTPATCH_SIZE 32
33
34#include "geomutils/PxContactBuffer.h"
35#include "GuVecCapsule.h"
36#include "GuPCMTriangleContactGen.h"
37#include "GuTriangleCache.h"
38#include "foundation/PxInlineArray.h"
39
40namespace physx
41{
42
43namespace Gu
44{
45
46#define MAX_CACHE_SIZE 128
47
48//sizeof(PCMDeferredPolyData)/sizeof(PxU32) = 15, 960/15 = 64 triangles in the local array
49#define LOCAL_PCM_CONTACTS_SIZE 960
50
52{
54public:
55 PCMContactPatch mContactPatch[PCM_MAX_CONTACTPATCH_SIZE];
56 PCMContactPatch* mContactPatchPtr[PCM_MAX_CONTACTPATCH_SIZE];
57 const aos::FloatV mContactDist;
58 const aos::FloatV mReplaceBreakingThreshold;
59 const aos::PxTransformV& mConvexTransform;
60 const aos::PxTransformV& mMeshTransform;
62 PxContactBuffer& mContactBuffer;
63
64 aos::FloatV mAcceptanceEpsilon;
65 aos::FloatV mSqReplaceBreakingThreshold;
66 aos::PxMatTransformV mMeshToConvex;
67 Gu::MeshPersistentContact* mManifoldContacts;
68 PxU32 mNumContacts;
69 PxU32 mNumContactPatch;
70 PxU32 mNumCalls;
74 PxRenderOutput* mRenderOutput;
75
77 const aos::FloatVArg contactDist,
78 const aos::FloatVArg replaceBreakingThreshold,
79 const aos::PxTransformV& convexTransform,
80 const aos::PxTransformV& meshTransform,
82 PxContactBuffer& contactBuffer,
84 PxRenderOutput* renderOutput
85
86 ) :
87 mContactDist(contactDist),
88 mReplaceBreakingThreshold(replaceBreakingThreshold),
89 mConvexTransform(convexTransform),
90 mMeshTransform(meshTransform),
91 mMultiManifold(multiManifold),
92 mContactBuffer(contactBuffer),
93 mDeferredContacts(deferredContacts),
94 mRenderOutput(renderOutput)
95
96 {
97 using namespace aos;
98 mNumContactPatch = 0;
99 mNumContacts = 0;
100 mNumCalls = 0;
101
102 mMeshToConvex = mConvexTransform.transformInv(mMeshTransform);
103
104 //Assign the PCMContactPatch to the PCMContactPathPtr
105 for(PxU32 i=0; i<PCM_MAX_CONTACTPATCH_SIZE; ++i)
106 {
107 mContactPatchPtr[i] = &mContactPatch[i];
108 }
109 mManifoldContacts = PX_CP_TO_MPCP(contactBuffer.contacts);
110
111 mSqReplaceBreakingThreshold = FMul(replaceBreakingThreshold, replaceBreakingThreshold);
112
113 mAcceptanceEpsilon = FLoad(0.996f);//5 degree
114 //mAcceptanceEpsilon = FloatV_From_F32(0.9999);//5 degree
115 }
116
117 template <PxU32 TriangleCount, typename Derived>
118 bool processTriangleCache(Gu::TriangleCache<TriangleCount>& cache)
119 {
120 PxU32 count = cache.mNumTriangles;
121 PxVec3* verts = cache.mVertices;
122 PxU32* vertInds = cache.mIndices;
123 PxU32* triInds = cache.mTriangleIndex;
124 PxU8* edgeFlags = cache.mEdgeFlags;
125 while(count--)
126 {
127 (static_cast<Derived*>(this))->processTriangle(verts, *triInds, *edgeFlags, vertInds);
128 verts += 3;
129 vertInds += 3;
130 triInds++;
131 edgeFlags++;
132 }
133 return true;
134 }
135 void prioritizeContactPatches();
136 void addManifoldPointToPatch(const aos::Vec3VArg currentPatchNormal, const aos::FloatVArg maxPen, const PxU32 previousNumContacts);
137 void processContacts(const PxU8 maxContactPerManifold, const bool isNotLastPatch = true);
138};
139
140/*
141 This function is based on the current patch normal to either create a new patch or merge the manifold contacts in this patch with the manifold contacts in the last existing
142 patch. This means there might be more than GU_SINGLE_MANIFOLD_CACHE_SIZE in a SinglePersistentContactManifold.
143*/
144PX_FORCE_INLINE void PCMMeshContactGeneration::addManifoldPointToPatch(const aos::Vec3VArg currentPatchNormal, const aos::FloatVArg maxPen, const PxU32 previousNumContacts)
145{
146 using namespace aos;
147
148 bool foundPatch = false;
149 //we have existing patch
150 if(mNumContactPatch > 0)
151 {
152 //if the direction between the last existing patch normal and the current patch normal are within acceptance epsilon, which means we will be
153 //able to merge the last patch's contacts with the current patch's contacts. This is just to avoid to create an extra patch. We have some logic
154 //later to refine the patch again
155 if(FAllGrtr(V3Dot(mContactPatch[mNumContactPatch-1].mPatchNormal, currentPatchNormal), mAcceptanceEpsilon))
156 {
157 //get the last patch
158 PCMContactPatch& patch = mContactPatch[mNumContactPatch-1];
159
160 //remove duplicate contacts
161 for(PxU32 i = patch.mStartIndex; i<patch.mEndIndex; ++i)
162 {
163 for(PxU32 j = previousNumContacts; j<mNumContacts; ++j)
164 {
165 Vec3V dif = V3Sub(mManifoldContacts[j].mLocalPointB, mManifoldContacts[i].mLocalPointB);
166 FloatV d = V3Dot(dif, dif);
167 if(FAllGrtr(mSqReplaceBreakingThreshold, d))
168 {
169 if(FAllGrtr(V4GetW(mManifoldContacts[i].mLocalNormalPen), V4GetW(mManifoldContacts[j].mLocalNormalPen)))
170 {
171 //The new contact is deeper than the old contact so we keep the deeper contact
172 mManifoldContacts[i] = mManifoldContacts[j];
173 }
174 mManifoldContacts[j] = mManifoldContacts[mNumContacts-1];
175 mNumContacts--;
176 j--;
177 }
178 }
179 }
180 patch.mEndIndex = mNumContacts;
181 patch.mPatchMaxPen = FMin(patch.mPatchMaxPen, maxPen);
182 foundPatch = true;
183 }
184 }
185
186 //If there are no existing patch which match the currentPatchNormal, we will create a new patch
187 if(!foundPatch)
188 {
189 mContactPatch[mNumContactPatch].mStartIndex = previousNumContacts;
190 mContactPatch[mNumContactPatch].mEndIndex = mNumContacts;
191 mContactPatch[mNumContactPatch].mPatchMaxPen = maxPen;
192 mContactPatch[mNumContactPatch++].mPatchNormal = currentPatchNormal;
193 }
194}
195
196/*
197 This function sort the contact patch based on the max penetration so that deepest penetration contact patch will be in front of the less penetration contact
198 patch
199*/
200PX_FORCE_INLINE void PCMMeshContactGeneration::prioritizeContactPatches()
201{
202 //we are using insertion sort to prioritize contact patchs
203 using namespace aos;
204 //sort the contact patch based on the max penetration
205 for(PxU32 i=1; i<mNumContactPatch; ++i)
206 {
207 const PxU32 indexi = i-1;
208 if(FAllGrtr(mContactPatchPtr[indexi]->mPatchMaxPen, mContactPatchPtr[i]->mPatchMaxPen))
209 {
210 //swap
211 PCMContactPatch* tmp = mContactPatchPtr[indexi];
212 mContactPatchPtr[indexi] = mContactPatchPtr[i];
213 mContactPatchPtr[i] = tmp;
214
215 for(PxI32 j=PxI32(i-2); j>=0; j--)
216 {
217 const PxU32 indexj = PxU32(j+1);
218 if(FAllGrtrOrEq(mContactPatchPtr[indexj]->mPatchMaxPen, mContactPatchPtr[j]->mPatchMaxPen))
219 break;
220 //swap
221 PCMContactPatch* temp = mContactPatchPtr[indexj];
222 mContactPatchPtr[indexj] = mContactPatchPtr[j];
223 mContactPatchPtr[j] = temp;
224 }
225 }
226 }
227}
228
229
230PX_FORCE_INLINE void PCMMeshContactGeneration::processContacts(const PxU8 maxContactPerManifold, bool isNotLastPatch)
231{
232 using namespace aos;
233
234 if(mNumContacts != 0)
235 {
236 //reorder the contact patches based on the max penetration
237 prioritizeContactPatches();
238 //connect the patches which's angle between patch normals are within 5 degree
239 mMultiManifold.refineContactPatchConnective(mContactPatchPtr, mNumContactPatch, mManifoldContacts, mAcceptanceEpsilon);
240 //get rid of duplicate manifold contacts in connected contact patches
241 mMultiManifold.reduceManifoldContactsInDifferentPatches(mContactPatchPtr, mNumContactPatch, mManifoldContacts, mNumContacts, mSqReplaceBreakingThreshold);
242 //add the manifold contact to the corresponding manifold
243 mMultiManifold.addManifoldContactPoints(mManifoldContacts, mNumContacts, mContactPatchPtr, mNumContactPatch, mSqReplaceBreakingThreshold, mAcceptanceEpsilon, maxContactPerManifold);
244
245 mNumContacts = 0;
246 mNumContactPatch = 0;
247
248 if(isNotLastPatch)
249 {
250 //remap the contact patch pointer to contact patch
251 for(PxU32 i=0; i<PCM_MAX_CONTACTPATCH_SIZE; ++i)
252 {
253 mContactPatchPtr[i] = &mContactPatch[i];
254 }
255 }
256 }
257}
258
260{
261public:
262 PxVec3 mVerts[3]; //36
263 PxU32 mInds[3]; //48
264 PxU32 mTriangleIndex; //52
265 PxU32 mFeatureIndex; //56
266 PxU32 triFlags32; //60
267};
268
269#if PX_VC
270 #pragma warning(push)
271 #pragma warning( disable : 4324 ) // Padding was added at the end of a structure because of a __declspec(align) value.
272#endif
273
275{
277
278public:
279 aos::Vec3V mHullCenterMesh;
280
281 const Gu::PolygonalData& mPolyData;
282 SupportLocal* mPolyMap;
283 const Cm::FastVertex2ShapeScaling& mConvexScaling;
284 bool mIdtConvexScale;
285 bool mSilhouetteEdgesAreActive;
286
288 const aos::FloatVArg contactDistance,
289 const aos::FloatVArg replaceBreakingThreshold,
290 const aos::PxTransformV& convexTransform,
291 const aos::PxTransformV& meshTransform,
293 PxContactBuffer& contactBuffer,
294
295 const Gu::PolygonalData& polyData,
296 SupportLocal* polyMap,
298 const Cm::FastVertex2ShapeScaling& convexScaling,
299 bool idtConvexScale,
300 bool silhouetteEdgesAreActive,
301 PxRenderOutput* renderOutput
302
303 ) : PCMMeshContactGeneration(contactDistance, replaceBreakingThreshold, convexTransform, meshTransform, multiManifold, contactBuffer,
304 delayedContacts, renderOutput),
305 mPolyData(polyData),
306 mPolyMap(polyMap),
307 mConvexScaling(convexScaling),
308 mIdtConvexScale(idtConvexScale),
309 mSilhouetteEdgesAreActive(silhouetteEdgesAreActive)
310 {
311 using namespace aos;
312
313 // Hull center in local space
314 const Vec3V hullCenterLocal = V3LoadU(mPolyData.mCenter);
315 // Hull center in mesh space
316 mHullCenterMesh = mMeshToConvex.transformInv(hullCenterLocal);
317 }
318
319 bool generateTriangleFullContactManifold(Gu::TriangleV& localTriangle, const PxU32 triangleIndex, const PxU32* triIndices, const PxU8 triFlags, const Gu::PolygonalData& polyData, Gu::SupportLocalImpl<Gu::TriangleV>* localTriMap, Gu::SupportLocal* polyMap, Gu::MeshPersistentContact* manifoldContacts, PxU32& numContacts,
320 const aos::FloatVArg contactDist, aos::Vec3V& patchNormal);
321
322 bool generatePolyDataContactManifold(Gu::TriangleV& localTriangle, const PxU32 featureIndex, const PxU32 triangleIndex, const PxU8 triFlags, Gu::MeshPersistentContact* manifoldContacts, PxU32& numContacts, const aos::FloatVArg contactDist, aos::Vec3V& patchNormal);
323 void generateLastContacts();
324 void addContactsToPatch(const aos::Vec3VArg patchNormal, const PxU32 previousNumContacts);
325
326 bool processTriangle(const PxVec3* verts, PxU32 triangleIndex, PxU8 triFlags, const PxU32* vertInds);
327
328 static bool generateTriangleFullContactManifold(Gu::TriangleV& localTriangle, const PxU32 triangleIndex, const PxU8 triFlags, const Gu::PolygonalData& polyData, Gu::SupportLocalImpl<Gu::TriangleV>* localTriMap, Gu::SupportLocal* polyMap, Gu::MeshPersistentContact* manifoldContacts, PxU32& numContacts,
329 const aos::FloatVArg contactDist, aos::Vec3V& patchNormal, PxRenderOutput* renderOutput = NULL);
330
331 static bool processTriangle(const Gu::PolygonalData& polyData, SupportLocal* polyMap, const PxVec3* verts, const PxU32 triangleIndex, PxU8 triFlags, const aos::FloatVArg inflation, const bool isDoubleSided,
332 const aos::PxTransformV& convexTransform, const aos::PxMatTransformV& meshToConvex, Gu::MeshPersistentContact* manifoldContact, PxU32& numContacts);
333};
334
335#if PX_VC
336 #pragma warning(pop)
337#endif
338
340{
341 aos::FloatV mSquareDist;
342 PxU32 mIndex;
343
344 PX_FORCE_INLINE bool operator < (const SortedTriangle& data) const
345 {
346 return aos::FAllGrtrOrEq(mSquareDist, data.mSquareDist) ==0;
347 }
348};
349
351{
352public:
353 aos::Vec3V mSphereCenter;
354 aos::FloatV mSphereRadius;
355 aos::FloatV mSqInflatedSphereRadius;
356 PxInlineArray<SortedTriangle, 64> mSortedTriangle;
357
359 const aos::Vec3VArg sphereCenter,
360 const aos::FloatVArg sphereRadius,
361 const aos::FloatVArg contactDist,
362 const aos::FloatVArg replaceBreakingThreshold,
363 const aos::PxTransformV& sphereTransform,
364 const aos::PxTransformV& meshTransform,
366 PxContactBuffer& contactBuffer,
368 PxRenderOutput* renderOutput = NULL
369
370 ) : PCMMeshContactGeneration(contactDist, replaceBreakingThreshold, sphereTransform, meshTransform, multiManifold,
371 contactBuffer, deferredContacts, renderOutput),
372 mSphereCenter(sphereCenter),
373 mSphereRadius(sphereRadius)
374 {
375 using namespace aos;
376 const FloatV inflatedSphereRadius = FAdd(sphereRadius, contactDist);
377 mSqInflatedSphereRadius = FMul(inflatedSphereRadius, inflatedSphereRadius);
378 }
379
380 bool processTriangle(const PxVec3* verts, PxU32 triangleIndex, PxU8 triFlags, const PxU32* vertInds);
381 void generateLastContacts();
382 void addToPatch(const aos::Vec3VArg contactP, const aos::Vec3VArg patchNormal,
383 const aos::FloatV pen, const PxU32 triangleIndex);
384};
385
387{
389public:
390 aos::FloatV mInflatedRadius;
391 aos::FloatV mSqInflatedRadius;
392 const CapsuleV& mCapsule;
393
394
396 const CapsuleV& capsule,
397 const aos::FloatVArg contactDist,
398 const aos::FloatVArg replaceBreakingThreshold,
399 const aos::PxTransformV& sphereTransform,
400 const aos::PxTransformV& meshTransform,
402 PxContactBuffer& contactBuffer,
404 PxRenderOutput* renderOutput = NULL
405
406 ) : PCMMeshContactGeneration(contactDist, replaceBreakingThreshold, sphereTransform, meshTransform, multiManifold, contactBuffer,
407 deferredContacts, renderOutput),
408 mCapsule(capsule)
409 {
410 using namespace aos;
411 mInflatedRadius = FAdd(capsule.radius, contactDist);
412 mSqInflatedRadius = FMul(mInflatedRadius, mInflatedRadius);
413 }
414
415 void generateEEContacts(const aos::Vec3VArg a, const aos::Vec3VArg b,const aos::Vec3VArg c, const aos::Vec3VArg normal, const PxU32 triangleIndex,
416 const aos::Vec3VArg p, const aos::Vec3VArg q, const aos::FloatVArg sqInflatedRadius, const PxU32 previousNumContacts, Gu::MeshPersistentContact* manifoldContacts, PxU32& numContacts);
417
418 void generateEE(const aos::Vec3VArg p, const aos::Vec3VArg q, const aos::FloatVArg sqInflatedRadius, const aos::Vec3VArg normal, const PxU32 triangleIndex,
419 const aos::Vec3VArg a, const aos::Vec3VArg b, Gu::MeshPersistentContact* manifoldContacts, PxU32& numContacts);
420
421 static void generateContacts(const aos::Vec3VArg a, const aos::Vec3VArg b,const aos::Vec3VArg c, const aos::Vec3VArg planeNormal, const aos::Vec3VArg normal,
422 const PxU32 triangleIndex, const aos::Vec3VArg p, const aos::Vec3VArg q, const aos::FloatVArg inflatedRadius, Gu::MeshPersistentContact* manifoldContacts, PxU32& numContacts);
423
424 static void generateEEContactsMTD(const aos::Vec3VArg a, const aos::Vec3VArg b,const aos::Vec3VArg c, const aos::Vec3VArg normal, const PxU32 triangleIndex,
425 const aos::Vec3VArg p, const aos::Vec3VArg q, const aos::FloatVArg inflatedRadius, Gu::MeshPersistentContact* manifoldContacts, PxU32& numContacts);
426
427 static void generateEEMTD(const aos::Vec3VArg p, const aos::Vec3VArg q, const aos::FloatVArg inflatedRadius, const aos::Vec3VArg normal, const PxU32 trianlgeIndex,
428 const aos::Vec3VArg a, const aos::Vec3VArg b, Gu::MeshPersistentContact* manifoldContacts, PxU32& numContacts);
429
430 bool processTriangle(const PxVec3* verts, const PxU32 triangleIndex, PxU8 triFlags, const PxU32* vertInds);
431
432 static bool processTriangle(const TriangleV& triangle, const PxU32 triangleIndex, const CapsuleV& capsule, const aos::FloatVArg inflatedRadius, const PxU8 triFlag, Gu::MeshPersistentContact* manifoldContacts, PxU32& numContacts);
433};
434
435}
436}
437
438#endif
Definition CmScaling.h:61
Definition GuVecCapsule.h:53
Definition GuPersistentContactManifold.h:97
Definition GuPersistentContactManifold.h:532
Definition GuPCMContactConvexCommon.h:387
Definition GuPCMContactConvexCommon.h:275
Definition GuPCMContactConvexCommon.h:52
Definition GuPCMContactConvexCommon.h:351
Definition GuConvexSupportTable.h:83
Definition GuConvexSupportTable.h:52
Definition GuVecTriangle.h:46
Definition PxContactBuffer.h:42
Definition PxInlineArray.h:43
Definition PxRenderOutput.h:50
3 Element vector class.
Definition PxVec3.h:50
Definition PxVecTransform.h:200
Definition PxVecTransform.h:43
#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
Definition GuTriangleCache.h:96
Definition GuPersistentContactManifold.h:123
Definition GuPCMContactConvexCommon.h:260
Definition GuShapeConvex.h:45
Definition GuPCMContactConvexCommon.h:340
Definition GuTriangleCache.h:172
Definition PxVecMathAoSScalar.h:52
Definition PxVecMathAoSScalar.h:77