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 |
38 | namespace 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 | |
49 | PX_ALIGN_PREFIX(16) |
50 | struct PxMassModificationProps |
51 | { |
52 | PxReal mInvMassScale0; |
53 | PxReal mInvInertiaScale0; |
54 | PxReal mInvMassScale1; |
55 | PxReal mInvInertiaScale1; |
56 | } |
57 | PX_ALIGN_SUFFIX(16); |
58 | |
59 | /** |
60 | \brief Header for contact patch where all points share same material and normal |
61 | */ |
62 | |
63 | PX_ALIGN_PREFIX(16) |
64 | struct 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 | } |
101 | PX_ALIGN_SUFFIX(16); |
102 | |
103 | /** |
104 | \brief Contact point data including face (feature) indices |
105 | */ |
106 | |
107 | PX_ALIGN_PREFIX(16) |
108 | struct 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 | } |
119 | PX_ALIGN_SUFFIX(16); |
120 | |
121 | PX_ALIGN_PREFIX(16) |
122 | struct 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 | } |
133 | PX_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 | */ |
139 | PX_ALIGN_PREFIX(16) |
140 | struct 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 | } |
173 | PX_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 | */ |
178 | struct 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 ; |
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 = 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 | |
559 | private: |
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 | |