1//
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions
4// are met:
5// * Redistributions of source code must retain the above copyright
6// notice, this list of conditions and the following disclaimer.
7// * Redistributions in binary form must reproduce the above copyright
8// notice, this list of conditions and the following disclaimer in the
9// documentation and/or other materials provided with the distribution.
10// * Neither the name of NVIDIA CORPORATION nor the names of its
11// contributors may be used to endorse or promote products derived
12// from this software without specific prior written permission.
13//
14// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
15// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25//
26// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
27// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
28// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
29
30
31#ifndef PX_CONTACT_H
32#define PX_CONTACT_H
33
34#include "foundation/PxVec3.h"
35#include "foundation/PxAssert.h"
36
37#if !PX_DOXYGEN
38namespace physx
39{
40#endif
41
42#if PX_VC
43#pragma warning(push)
44#pragma warning(disable: 4324) // Padding was added at the end of a structure because of a __declspec(align) value.
45#endif
46
47#define PXC_CONTACT_NO_FACE_INDEX 0xffffffff
48
49PX_ALIGN_PREFIX(16)
50struct PxMassModificationProps
51{
52 PxReal mInvMassScale0;
53 PxReal mInvInertiaScale0;
54 PxReal mInvMassScale1;
55 PxReal mInvInertiaScale1;
56}
57PX_ALIGN_SUFFIX(16);
58
59/**
60\brief Header for contact patch where all points share same material and normal
61*/
62
63PX_ALIGN_PREFIX(16)
64struct PxContactPatch
65{
66 enum PxContactPatchFlags
67 {
68 eHAS_FACE_INDICES = 1, //!< Indicates this contact stream has face indices.
69 eMODIFIABLE = 2, //!< Indicates this contact stream is modifiable.
70 eFORCE_NO_RESPONSE = 4, //!< Indicates this contact stream is notify-only (no contact response).
71 eHAS_MODIFIED_MASS_RATIOS = 8, //!< Indicates this contact stream has modified mass ratios
72 eHAS_TARGET_VELOCITY = 16, //!< Indicates this contact stream has target velocities set
73 eHAS_MAX_IMPULSE = 32, //!< Indicates this contact stream has max impulses set
74 eREGENERATE_PATCHES = 64, //!< Indicates this contact stream needs patches re-generated.
75 //!< This is required if the application modified either the contact normal or the material properties
76 eCOMPRESSED_MODIFIED_CONTACT = 128
77 };
78
79 PX_ALIGN(16, PxMassModificationProps mMassModification); //16
80 /**
81 \brief Contact normal
82 */
83 PX_ALIGN(16, PxVec3 normal); //28
84 /**
85 \brief Restitution coefficient
86 */
87 PxReal restitution; //32
88
89 PxReal dynamicFriction; //36
90 PxReal staticFriction; //40
91 PxU8 startContactIndex; //41
92 PxU8 nbContacts; //42 //Can be a U8
93
94 PxU8 materialFlags; //43 //Can be a U16
95 PxU8 internalFlags; //44 //Can be a U16
96 PxU16 materialIndex0; //46 //Can be a U16
97 PxU16 materialIndex1; //48 //Can be a U16
98
99
100}
101PX_ALIGN_SUFFIX(16);
102
103/**
104\brief Contact point data including face (feature) indices
105*/
106
107PX_ALIGN_PREFIX(16)
108struct PxContact
109{
110 /**
111 \brief Contact point in world space
112 */
113 PxVec3 contact; //12
114 /**
115 \brief Separation value (negative implies penetration).
116 */
117 PxReal separation; //16
118}
119PX_ALIGN_SUFFIX(16);
120
121PX_ALIGN_PREFIX(16)
122struct PxExtendedContact : public PxContact
123{
124 /**
125 \brief Target velocity
126 */
127 PX_ALIGN(16, PxVec3 targetVelocity); //28
128 /**
129 \brief Maximum impulse
130 */
131 PxReal maxImpulse; //32
132}
133PX_ALIGN_SUFFIX(16);
134
135/**
136\brief A modifiable contact point. This has additional fields per-contact to permit modification by user.
137\note Not all fields are currently exposed to the user.
138*/
139PX_ALIGN_PREFIX(16)
140struct PxModifiableContact : public PxExtendedContact
141{
142 /**
143 \brief Contact normal
144 */
145 PX_ALIGN(16, PxVec3 normal); //44
146 /**
147 \brief Restitution coefficient
148 */
149 PxReal restitution; //48
150
151 /**
152 \brief Material Flags
153 */
154 PxU32 materialFlags; //52
155
156 /**
157 \brief Shape A's material index
158 */
159 PxU16 materialIndex0; //54
160 /**
161 \brief Shape B's material index
162 */
163 PxU16 materialIndex1; //56
164 /**
165 \brief static friction coefficient
166 */
167 PxReal staticFriction; //60
168 /**
169 \brief dynamic friction coefficient
170 */
171 PxReal dynamicFriction; //64
172}
173PX_ALIGN_SUFFIX(16);
174
175/**
176\brief A class to iterate over a compressed contact stream. This supports read-only access to the various contact formats.
177*/
178struct PxContactStreamIterator
179{
180 enum StreamFormat
181 {
182 eSIMPLE_STREAM,
183 eMODIFIABLE_STREAM,
184 eCOMPRESSED_MODIFIABLE_STREAM
185 };
186 /**
187 \brief Utility zero vector to optimize functions returning zero vectors when a certain flag isn't set.
188 \note This allows us to return by reference instead of having to return by value. Returning by value will go via memory (registers -> stack -> registers), which can
189 cause performance issues on certain platforms.
190 */
191 PxVec3 zero;
192 /**
193 \brief The patch headers.
194 */
195 const PxContactPatch* patch;
196
197 /**
198 \brief The contacts
199 */
200 const PxContact* contact;
201
202 /**
203 \brief The contact triangle face index
204 */
205 const PxU32* faceIndice;
206
207
208 /**
209 \brief The total number of patches in this contact stream
210 */
211 PxU32 totalPatches;
212
213 /**
214 \brief The total number of contact points in this stream
215 */
216 PxU32 totalContacts;
217
218 /**
219 \brief The current contact index
220 */
221 PxU32 nextContactIndex;
222
223 /**
224 \brief The current patch Index
225 */
226 PxU32 nextPatchIndex;
227
228 /*
229 \brief Size of contact patch header
230 \note This varies whether the patch is modifiable or not.
231 */
232 PxU32 contactPatchHeaderSize;
233 /**
234 \brief Contact point size
235 \note This varies whether the patch has feature indices or is modifiable.
236 */
237 PxU32 contactPointSize;
238 /**
239 \brief The stream format
240 */
241 StreamFormat mStreamFormat;
242 /**
243 \brief Indicates whether this stream is notify-only or not.
244 */
245 PxU32 forceNoResponse;
246
247 bool pointStepped;
248
249 PxU32 hasFaceIndices;
250
251 /**
252 \brief Constructor
253 */
254 PX_CUDA_CALLABLE PX_FORCE_INLINE PxContactStreamIterator(const PxU8* contactPatches, const PxU8* contactPoints, const PxU32* contactFaceIndices, PxU32 nbPatches, PxU32 nbContacts)
255 : zero(0.f)
256 {
257 bool modify = false;
258 bool compressedModify = false;
259 bool response = false;
260 bool indices = false;
261
262 PxU32 pointSize = 0;
263 PxU32 patchHeaderSize = sizeof(PxContactPatch);
264
265 const PxContactPatch* patches = reinterpret_cast<const PxContactPatch*>(contactPatches);
266
267 if(patches)
268 {
269 modify = (patches->internalFlags & PxContactPatch::eMODIFIABLE) != 0;
270 compressedModify = (patches->internalFlags & PxContactPatch::eCOMPRESSED_MODIFIED_CONTACT) != 0;
271 indices = (patches->internalFlags & PxContactPatch::eHAS_FACE_INDICES) != 0;
272
273 patch = patches;
274
275 contact = reinterpret_cast<const PxContact*>(contactPoints);
276
277 faceIndice = contactFaceIndices;
278
279 pointSize = compressedModify ? sizeof(PxExtendedContact) : modify ? sizeof(PxModifiableContact) : sizeof(PxContact);
280
281 response = (patch->internalFlags & PxContactPatch::eFORCE_NO_RESPONSE) == 0;
282 } else {
283 patch = nullptr;
284 contact = nullptr;
285 faceIndice = nullptr;
286 }
287
288 mStreamFormat = compressedModify ? eCOMPRESSED_MODIFIABLE_STREAM : modify ? eMODIFIABLE_STREAM : eSIMPLE_STREAM;
289 hasFaceIndices = PxU32(indices);
290 forceNoResponse = PxU32(!response);
291
292 contactPatchHeaderSize = patchHeaderSize;
293 contactPointSize = pointSize;
294 nextPatchIndex = 0;
295 nextContactIndex = 0;
296 totalContacts = nbContacts;
297 totalPatches = nbPatches;
298
299 pointStepped = false;
300 }
301
302 /**
303 \brief Returns whether there are more patches in this stream.
304 \return Whether there are more patches in this stream.
305 */
306 PX_CUDA_CALLABLE PX_FORCE_INLINE bool hasNextPatch() const
307 {
308 return nextPatchIndex < totalPatches;
309 }
310
311 /**
312 \brief Returns the total contact count.
313 \return Total contact count.
314 */
315 PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 getTotalContactCount() const
316 {
317 return totalContacts;
318 }
319
320 PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 getTotalPatchCount() const
321 {
322 return totalPatches;
323 }
324
325 /**
326 \brief Advances iterator to next contact patch.
327 */
328 PX_CUDA_CALLABLE PX_INLINE void nextPatch()
329 {
330 PX_ASSERT(nextPatchIndex < totalPatches);
331 if(nextPatchIndex)
332 {
333 if(nextContactIndex < patch->nbContacts)
334 {
335 PxU32 nbToStep = patch->nbContacts - this->nextContactIndex;
336 contact = reinterpret_cast<const PxContact*>(reinterpret_cast<const PxU8*>(contact) + contactPointSize * nbToStep);
337 }
338 patch = reinterpret_cast<const PxContactPatch*>(reinterpret_cast<const PxU8*>(patch) + contactPatchHeaderSize);
339 }
340 nextPatchIndex++;
341 nextContactIndex = 0;
342 }
343
344 /**
345 \brief Returns if the current patch has more contacts.
346 \return If there are more contacts in the current patch.
347 */
348 PX_CUDA_CALLABLE PX_FORCE_INLINE bool hasNextContact() const
349 {
350 return nextContactIndex < (patch->nbContacts);
351 }
352
353 /**
354 \brief Advances to the next contact in the patch.
355 */
356 PX_CUDA_CALLABLE PX_FORCE_INLINE void nextContact()
357 {
358 PX_ASSERT(nextContactIndex < patch->nbContacts);
359 if(pointStepped)
360 {
361 contact = reinterpret_cast<const PxContact*>(reinterpret_cast<const PxU8*>(contact) + contactPointSize);
362 faceIndice++;
363 }
364 nextContactIndex++;
365 pointStepped = true;
366 }
367
368
369 /**
370 \brief Gets the current contact's normal
371 \return The current contact's normal.
372 */
373 PX_CUDA_CALLABLE PX_FORCE_INLINE const PxVec3& getContactNormal() const
374 {
375 return getContactPatch().normal;
376 }
377
378 /**
379 \brief Gets the inverse mass scale for body 0.
380 \return The inverse mass scale for body 0.
381 */
382 PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getInvMassScale0() const
383 {
384 return patch->mMassModification.mInvMassScale0;
385 }
386
387 /**
388 \brief Gets the inverse mass scale for body 1.
389 \return The inverse mass scale for body 1.
390 */
391 PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getInvMassScale1() const
392 {
393 return patch->mMassModification.mInvMassScale1;
394 }
395
396 /**
397 \brief Gets the inverse inertia scale for body 0.
398 \return The inverse inertia scale for body 0.
399 */
400 PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getInvInertiaScale0() const
401 {
402 return patch->mMassModification.mInvInertiaScale0;
403 }
404
405 /**
406 \brief Gets the inverse inertia scale for body 1.
407 \return The inverse inertia scale for body 1.
408 */
409 PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getInvInertiaScale1() const
410 {
411 return patch->mMassModification.mInvInertiaScale1;
412 }
413
414 /**
415 \brief Gets the contact's max impulse.
416 \return The contact's max impulse.
417 */
418 PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getMaxImpulse() const
419 {
420 return mStreamFormat != eSIMPLE_STREAM ? getExtendedContact().maxImpulse : PX_MAX_REAL;
421 }
422
423 /**
424 \brief Gets the contact's target velocity.
425 \return The contact's target velocity.
426 */
427 PX_CUDA_CALLABLE PX_FORCE_INLINE const PxVec3& getTargetVel() const
428 {
429 return mStreamFormat != eSIMPLE_STREAM ? getExtendedContact().targetVelocity : zero;
430 }
431
432 /**
433 \brief Gets the contact's contact point.
434 \return The contact's contact point.
435 */
436 PX_CUDA_CALLABLE PX_FORCE_INLINE const PxVec3& getContactPoint() const
437 {
438 return contact->contact;
439 }
440
441 /**
442 \brief Gets the contact's separation.
443 \return The contact's separation.
444 */
445 PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getSeparation() const
446 {
447 return contact->separation;
448 }
449
450 /**
451 \brief Gets the contact's face index for shape 0.
452 \return The contact's face index for shape 0.
453 */
454 PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 getFaceIndex0() const
455 {
456 return PXC_CONTACT_NO_FACE_INDEX;
457 }
458
459 /**
460 \brief Gets the contact's face index for shape 1.
461 \return The contact's face index for shape 1.
462 */
463 PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 getFaceIndex1() const
464 {
465 return hasFaceIndices ? *faceIndice : PXC_CONTACT_NO_FACE_INDEX;
466 }
467
468 /**
469 \brief Gets the contact's static friction coefficient.
470 \return The contact's static friction coefficient.
471 */
472 PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getStaticFriction() const
473 {
474 return getContactPatch().staticFriction;
475 }
476
477 /**
478 \brief Gets the contact's static dynamic coefficient.
479 \return The contact's static dynamic coefficient.
480 */
481 PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getDynamicFriction() const
482 {
483 return getContactPatch().dynamicFriction;
484 }
485
486 /**
487 \brief Gets the contact's restitution coefficient.
488 \return The contact's restitution coefficient.
489 */
490 PX_CUDA_CALLABLE PX_FORCE_INLINE PxReal getRestitution() const
491 {
492 return getContactPatch().restitution;
493 }
494
495 /**
496 \brief Gets the contact's material flags.
497 \return The contact's material flags.
498 */
499 PX_CUDA_CALLABLE PX_FORCE_INLINE PxU32 getMaterialFlags() const
500 {
501 return getContactPatch().materialFlags;
502 }
503
504 /**
505 \brief Gets the contact's material index for shape 0.
506 \return The contact's material index for shape 0.
507 */
508 PX_CUDA_CALLABLE PX_FORCE_INLINE PxU16 getMaterialIndex0() const
509 {
510 return PxU16(getContactPatch().materialIndex0);
511 }
512
513 /**
514 \brief Gets the contact's material index for shape 1.
515 \return The contact's material index for shape 1.
516 */
517 PX_CUDA_CALLABLE PX_FORCE_INLINE PxU16 getMaterialIndex1() const
518 {
519 return PxU16(getContactPatch().materialIndex1);
520 }
521
522 /**
523 \brief Advances the contact stream iterator to a specific contact index.
524 */
525 bool advanceToIndex(const PxU32 initialIndex)
526 {
527 PX_ASSERT(this->nextPatchIndex == 0 && this->nextContactIndex == 0);
528
529 PxU32 numToAdvance = initialIndex;
530
531 if(numToAdvance == 0)
532 {
533 PX_ASSERT(hasNextPatch());
534 nextPatch();
535 return true;
536 }
537
538 while(numToAdvance)
539 {
540 while(hasNextPatch())
541 {
542 nextPatch();
543 PxU32 patchSize = patch->nbContacts;
544 if(numToAdvance <= patchSize)
545 {
546 contact = reinterpret_cast<const PxContact*>(reinterpret_cast<const PxU8*>(contact) + contactPointSize * numToAdvance);
547 nextContactIndex += numToAdvance;
548 return true;
549 }
550 else
551 {
552 numToAdvance -= patchSize;
553 }
554 }
555 }
556 return false;
557 }
558
559private:
560
561 /**
562 \brief Internal helper
563 */
564 PX_CUDA_CALLABLE PX_FORCE_INLINE const PxContactPatch& getContactPatch() const
565 {
566 return *static_cast<const PxContactPatch*>(patch);
567 }
568
569 PX_CUDA_CALLABLE PX_FORCE_INLINE const PxExtendedContact& getExtendedContact() const
570 {
571 PX_ASSERT(mStreamFormat == eMODIFIABLE_STREAM || mStreamFormat == eCOMPRESSED_MODIFIABLE_STREAM);
572 return *static_cast<const PxExtendedContact*>(contact);
573 }
574
575};
576
577
578#if PX_VC
579#pragma warning(pop)
580#endif
581
582#if !PX_DOXYGEN
583} // namespace physx
584#endif
585
586#endif
587

source code of qtquick3dphysics/src/3rdparty/PhysX/include/PxContact.h