1 | /* |
2 | * Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. |
3 | * |
4 | * NVIDIA CORPORATION and its licensors retain all intellectual property |
5 | * and proprietary rights in and to this software, related documentation |
6 | * and any modifications thereto. Any use, reproduction, disclosure or |
7 | * distribution of this software and related documentation without an express |
8 | * license agreement from NVIDIA CORPORATION is strictly prohibited. |
9 | */ |
10 | // Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. |
11 | // Copyright (c) 2001-2004 NovodeX AG. All rights reserved. |
12 | |
13 | |
14 | #ifndef PX_CONTACT_H |
15 | #define PX_CONTACT_H |
16 | |
17 | #include "foundation/PxVec3.h" |
18 | |
19 | #ifndef PX_DOXYGEN |
20 | namespace physx |
21 | { |
22 | #endif |
23 | |
24 | #ifdef PX_VC |
25 | #pragma warning(push) |
26 | #pragma warning(disable: 4324) // Padding was added at the end of a structure because of a __declspec(align) value. |
27 | #endif |
28 | |
29 | #define PXC_CONTACT_NO_FACE_INDEX 0xffffffff |
30 | |
31 | |
32 | /** |
33 | \brief Base header structure for compressed contact data. |
34 | */ |
35 | struct |
36 | { |
37 | enum |
38 | { |
39 | = 1, //!< Indicates this contact stream has face indices. |
40 | = 2, //!< Indicates this contact stream is modifiable. |
41 | = 4, //!< Indicates this contact stream is notify-only (no contact response). |
42 | = 8, //!< Indicates this contact stream has modified mass ratios |
43 | = 16, //!< Indicates this contact stream has target velocities set |
44 | = 32 //!< Indicates this contact stream has max impulses set |
45 | }; |
46 | /** |
47 | \brief Total contact count for entire compressed contact stream |
48 | */ |
49 | PxU16 ; //2 |
50 | /** |
51 | \brief The flags |
52 | @see PxContactHeaderFlags |
53 | */ |
54 | PxU16 ; //4 |
55 | }; |
56 | |
57 | /** |
58 | \brief Extended header structure for modifiable contacts. |
59 | */ |
60 | struct : public PxContactHeader |
61 | { |
62 | /** |
63 | \brief Inverse mass scale for body A. |
64 | */ |
65 | PxReal ; //8 |
66 | /** |
67 | \brief Inverse mass scale for body B. |
68 | */ |
69 | PxReal ; //12 |
70 | /** |
71 | \brief Inverse inertia scale for body A. |
72 | */ |
73 | PxReal ; //16 |
74 | /** |
75 | \brief Inverse inertia scale for body B. |
76 | */ |
77 | PxReal ; //20 |
78 | }; |
79 | |
80 | /** |
81 | \brief Base header for a contact patch |
82 | */ |
83 | struct PxContactPatchBase |
84 | { |
85 | /** |
86 | \brief Number of contacts in this patch. |
87 | */ |
88 | PxU16 nbContacts; //2 |
89 | /** |
90 | \brief Flags for this patch. |
91 | */ |
92 | PxU16 flags; //4 |
93 | }; |
94 | |
95 | /** |
96 | \brief Header for contact patch where all points share same material and normal |
97 | */ |
98 | struct PxContactPatch : public PxContactPatchBase |
99 | { |
100 | /** |
101 | \brief Contact normal |
102 | */ |
103 | PxVec3 normal; //16 |
104 | /** |
105 | \brief Static friction coefficient |
106 | */ |
107 | PxReal staticFriction; //20 |
108 | /** |
109 | \brief Dynamic friction coefficient |
110 | */ |
111 | PxReal dynamicFriction; //24 |
112 | /** |
113 | \brief Restitution coefficient |
114 | */ |
115 | PxReal restitution; //28 |
116 | /** |
117 | \brief Shape A's material index |
118 | */ |
119 | PxU16 materialIndex0; //30 |
120 | /** |
121 | \brief Shape B's material index |
122 | */ |
123 | PxU16 materialIndex1; //32 |
124 | }; |
125 | |
126 | /** |
127 | \brief Base contact point data |
128 | */ |
129 | struct PxSimpleContact |
130 | { |
131 | /** |
132 | \brief Contact point in world space |
133 | */ |
134 | PxVec3 contact; //12 |
135 | /** |
136 | \brief Separation value (negative implies penetration). |
137 | */ |
138 | PxReal separation; //16 |
139 | }; |
140 | |
141 | /** |
142 | \brief Extended contact point data including face (feature) indices |
143 | */ |
144 | struct PxFeatureContact : public PxSimpleContact |
145 | { |
146 | /** |
147 | \brief Face index on shape A. |
148 | */ |
149 | PxU32 internalFaceIndex0; //20 |
150 | /** |
151 | \brief Face index on shape B. |
152 | */ |
153 | PxU32 internalFaceIndex1; //24 |
154 | }; |
155 | |
156 | /** |
157 | \brief A modifiable contact point. This has additional fields per-contact to permit modification by user. |
158 | \note Not all fields are currently exposed to the user. |
159 | */ |
160 | struct PxModifiableContact : public PxFeatureContact |
161 | { |
162 | /** |
163 | \brief Contact normal |
164 | */ |
165 | PxVec3 normal; //36 |
166 | /** |
167 | \brief Target velocity |
168 | */ |
169 | PxVec3 targetVel; //48 |
170 | /** |
171 | \brief Maximum impulse |
172 | */ |
173 | PxReal maxImpulse; //52 |
174 | /** |
175 | \brief Static friction coefficient |
176 | */ |
177 | PxReal staticFriction; //56 |
178 | /** |
179 | \brief Dynamic friction coefficient |
180 | */ |
181 | PxReal dynamicFriction; //60 |
182 | /** |
183 | \brief Restitution coefficient |
184 | */ |
185 | PxReal restitution; //64 |
186 | /** |
187 | \brief Material index on shape A |
188 | */ |
189 | PxU16 materialIndex0; //66 |
190 | /** |
191 | \brief Material index on shape B |
192 | */ |
193 | PxU16 materialIndex1; //68 |
194 | /** |
195 | \brief Flags |
196 | */ |
197 | PxU32 flags; //72 |
198 | }; |
199 | |
200 | /** |
201 | \brief A class to iterate over a compressed contact stream. This supports read-only access to the various contact formats. |
202 | */ |
203 | struct PxContactStreamIterator |
204 | { |
205 | /** |
206 | \brief Utility zero vector to optimize functions returning zero vectors when a certain flag isn't set. |
207 | \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 |
208 | cause performance issues on certain platforms. |
209 | */ |
210 | PxVec3 zero; |
211 | /** |
212 | \brief The current contact header. |
213 | */ |
214 | const PxContactHeader* ; |
215 | /** |
216 | \brief Current pointer in the stream. |
217 | */ |
218 | const PxU8* currPtr; |
219 | /** |
220 | \brief Pointer to the end of the stream. |
221 | */ |
222 | const PxU8* endPtr; |
223 | /** |
224 | \brief Pointer to the start of the patch. |
225 | */ |
226 | const PxU8* patchStart; |
227 | /** |
228 | \brief Pointer to the end of the patch. |
229 | */ |
230 | const PxU8* patchEnd; |
231 | /** |
232 | \brief Pointer to the first contact in the patch. |
233 | */ |
234 | const PxSimpleContact* contactStart; |
235 | /** |
236 | \brief Size of the stream in bytes. |
237 | */ |
238 | PxU32 streamSize; |
239 | /** |
240 | \brief Total number of contacts in the patch. |
241 | */ |
242 | PxU32 nbContactsInPatch; |
243 | /** |
244 | \brief Current contact index in the patch |
245 | */ |
246 | PxU32 currentContact; |
247 | /** |
248 | \brief Size of contact patch header |
249 | \note This varies whether the patch is modifiable or not. |
250 | */ |
251 | PxU32 ; |
252 | /** |
253 | \brief Contact point size |
254 | \note This varies whether the patch has feature indices or is modifiable. |
255 | */ |
256 | PxU32 contactPointSize; |
257 | /** |
258 | \brief Indicates whether this stream carries face indices |
259 | */ |
260 | PxU32 hasFaceIndices; |
261 | /** |
262 | \brief Indicates whether this stream is created from modifiable contact (internal usage), the variables are still read-only |
263 | */ |
264 | PxU32 contactsWereModifiable; |
265 | /** |
266 | \brief Indicates whether this stream is notify-only or not. |
267 | */ |
268 | PxU32 forceNoResponse; |
269 | |
270 | /** |
271 | \brief Constructor |
272 | \param[in] stream Pointer to the start of the stream. |
273 | \param[in] size Size of the stream in bytes. |
274 | */ |
275 | PX_FORCE_INLINE PxContactStreamIterator(const PxU8* stream, PxU32 size) |
276 | : zero(0.f), streamSize(size), nbContactsInPatch(0), currentContact(0) |
277 | { |
278 | const PxContactHeader* h = reinterpret_cast<const PxContactHeader*>(stream); |
279 | header = h; |
280 | |
281 | bool modify = false; |
282 | bool faceIndices = false; |
283 | bool response = false; |
284 | |
285 | PxU32 pointSize = 0; |
286 | PxU32 = 0; |
287 | const PxU8* start = NULL; |
288 | |
289 | if(size > 0) |
290 | { |
291 | modify = (h->flags & PxContactHeader::eMODIFIABLE) != 0; |
292 | faceIndices = (h->flags & PxContactHeader::eHAS_FACE_INDICES) != 0; |
293 | |
294 | start = stream + (modify ? sizeof(PxModifyContactHeader) : sizeof(PxContactHeader)); |
295 | |
296 | |
297 | PX_ASSERT(((PxU32)(start - stream)) < size); |
298 | //if(((PxU32)(start - stream)) < size) |
299 | { |
300 | patchHeaderSize = modify ? sizeof(PxContactPatchBase) : sizeof(PxContactPatch); |
301 | pointSize = modify ? sizeof(PxModifiableContact) : faceIndices ? sizeof(PxFeatureContact) : sizeof(PxSimpleContact); |
302 | |
303 | response = (header->flags & PxContactHeader::eFORCE_NO_RESPONSE) == 0; |
304 | } |
305 | } |
306 | |
307 | contactsWereModifiable = (PxU32)modify; |
308 | hasFaceIndices = (PxU32)faceIndices; |
309 | forceNoResponse = (PxU32)!response; |
310 | |
311 | contactPatchHeaderSize = patchHeaderSize; |
312 | contactPointSize = pointSize; |
313 | |
314 | patchStart = start; |
315 | patchEnd = start; |
316 | currPtr = start; |
317 | } |
318 | |
319 | /** |
320 | \brief Returns whether there are more patches in this stream. |
321 | \return Whether there are more patches in this stream. |
322 | */ |
323 | PX_FORCE_INLINE bool hasNextPatch() const |
324 | { |
325 | return ((PxU32)(patchEnd - reinterpret_cast<const PxU8*>(header))) < streamSize; |
326 | } |
327 | |
328 | /** |
329 | \brief Returns the total contact count. |
330 | \return Total contact count. |
331 | */ |
332 | PX_FORCE_INLINE PxU32 getTotalContactCount() const |
333 | { |
334 | return header->totalContactCount; |
335 | } |
336 | |
337 | /** |
338 | \brief Advances iterator to next contact patch. |
339 | */ |
340 | PX_INLINE void nextPatch() |
341 | { |
342 | const PxU8* start = patchEnd; |
343 | patchStart = start; |
344 | |
345 | if(((PxU32)(start - (reinterpret_cast<const PxU8*>(header)))) < streamSize) |
346 | { |
347 | const PxU32 numContactsInPatch = *(reinterpret_cast<const PxU16*>(patchStart)); |
348 | nbContactsInPatch = numContactsInPatch; |
349 | |
350 | patchEnd = start + contactPatchHeaderSize + numContactsInPatch * contactPointSize; |
351 | currPtr = start + contactPatchHeaderSize; |
352 | currentContact = 0; |
353 | } |
354 | else |
355 | { |
356 | patchEnd = start; |
357 | } |
358 | } |
359 | |
360 | /** |
361 | \brief Returns if the current patch has more contacts. |
362 | \return If there are more contacts in the current patch. |
363 | */ |
364 | PX_FORCE_INLINE bool hasNextContact() const |
365 | { |
366 | return currentContact < nbContactsInPatch; |
367 | } |
368 | |
369 | /** |
370 | \brief Advances to the next contact in the patch. |
371 | */ |
372 | PX_FORCE_INLINE void nextContact() |
373 | { |
374 | PX_ASSERT(currentContact < nbContactsInPatch); |
375 | currentContact++; |
376 | contactStart = reinterpret_cast<const PxSimpleContact*>(currPtr); |
377 | currPtr += contactPointSize; |
378 | } |
379 | |
380 | /** |
381 | \brief Gets the current contact's normal |
382 | \return The current contact's normal. |
383 | */ |
384 | PX_FORCE_INLINE const PxVec3& getContactNormal() const |
385 | { |
386 | return contactsWereModifiable ? getModifiableContact().normal : getContactPatch().normal; |
387 | } |
388 | |
389 | /** |
390 | \brief Gets the inverse mass scale for body 0. |
391 | \return The inverse mass scale for body 0. |
392 | */ |
393 | PX_FORCE_INLINE PxReal getInvMassScale0() const |
394 | { |
395 | return contactsWereModifiable ? getModifiableContactHeader().invMassScale0 : 1.f; |
396 | } |
397 | |
398 | /** |
399 | \brief Gets the inverse mass scale for body 1. |
400 | \return The inverse mass scale for body 1. |
401 | */ |
402 | PX_FORCE_INLINE PxReal getInvMassScale1() const |
403 | { |
404 | return contactsWereModifiable ? getModifiableContactHeader().invMassScale1 : 1.f; |
405 | } |
406 | |
407 | /** |
408 | \brief Gets the inverse inertia scale for body 0. |
409 | \return The inverse inertia scale for body 0. |
410 | */ |
411 | PX_FORCE_INLINE PxReal getInvInertiaScale0() const |
412 | { |
413 | return contactsWereModifiable ? getModifiableContactHeader().invInertiaScale0 : 1.f; |
414 | } |
415 | |
416 | /** |
417 | \brief Gets the inverse inertia scale for body 1. |
418 | \return The inverse inertia scale for body 1. |
419 | */ |
420 | PX_FORCE_INLINE PxReal getInvInertiaScale1() const |
421 | { |
422 | return contactsWereModifiable ? getModifiableContactHeader().invInertiaScale1 : 1.f; |
423 | } |
424 | |
425 | /** |
426 | \brief Gets the contact's max impulse. |
427 | \return The contact's max impulse. |
428 | */ |
429 | PX_FORCE_INLINE PxReal getMaxImpulse() const |
430 | { |
431 | return contactsWereModifiable ? getModifiableContact().maxImpulse : PX_MAX_REAL; |
432 | } |
433 | |
434 | /** |
435 | \brief Gets the contact's target velocity. |
436 | \return The contact's target velocity. |
437 | */ |
438 | PX_FORCE_INLINE const PxVec3& getTargetVel() const |
439 | { |
440 | return contactsWereModifiable ? getModifiableContact().targetVel : zero; |
441 | } |
442 | |
443 | /** |
444 | \brief Gets the contact's contact point. |
445 | \return The contact's contact point. |
446 | */ |
447 | PX_FORCE_INLINE const PxVec3& getContactPoint() const |
448 | { |
449 | return contactStart->contact; |
450 | } |
451 | |
452 | /** |
453 | \brief Gets the contact's separation. |
454 | \return The contact's separation. |
455 | */ |
456 | PX_FORCE_INLINE PxReal getSeparation() const |
457 | { |
458 | return contactStart->separation; |
459 | } |
460 | |
461 | /** |
462 | \brief Gets the contact's face index for shape 0. |
463 | \return The contact's face index for shape 0. |
464 | */ |
465 | PX_FORCE_INLINE PxU32 getFaceIndex0() const |
466 | { |
467 | return hasFaceIndices ? (static_cast<const PxFeatureContact*>(contactStart))->internalFaceIndex0 : PXC_CONTACT_NO_FACE_INDEX; |
468 | } |
469 | |
470 | /** |
471 | \brief Gets the contact's face index for shape 1. |
472 | \return The contact's face index for shape 1. |
473 | */ |
474 | PX_FORCE_INLINE PxU32 getFaceIndex1() const |
475 | { |
476 | return hasFaceIndices ? (static_cast<const PxFeatureContact*>(contactStart))->internalFaceIndex1 : PXC_CONTACT_NO_FACE_INDEX; |
477 | } |
478 | |
479 | /** |
480 | \brief Gets the contact's static friction coefficient. |
481 | \return The contact's static friction coefficient. |
482 | */ |
483 | PX_FORCE_INLINE PxReal getStaticFriction() const |
484 | { |
485 | return contactsWereModifiable ? getModifiableContact().staticFriction : getContactPatch().staticFriction; |
486 | } |
487 | |
488 | /** |
489 | \brief Gets the contact's static dynamic coefficient. |
490 | \return The contact's static dynamic coefficient. |
491 | */ |
492 | PX_FORCE_INLINE PxReal getDynamicFriction() const |
493 | { |
494 | return contactsWereModifiable ? getModifiableContact().dynamicFriction : getContactPatch().dynamicFriction; |
495 | } |
496 | |
497 | /** |
498 | \brief Gets the contact's restitution coefficient. |
499 | \return The contact's restitution coefficient. |
500 | */ |
501 | PX_FORCE_INLINE PxReal getRestitution() const |
502 | { |
503 | return contactsWereModifiable ? getModifiableContact().restitution : getContactPatch().restitution; |
504 | } |
505 | |
506 | /** |
507 | \brief Gets the contact's material flags. |
508 | \return The contact's material flags. |
509 | */ |
510 | PX_FORCE_INLINE PxU32 getMaterialFlags() const |
511 | { |
512 | return contactsWereModifiable ? getModifiableContact().flags : getContactPatch().flags; |
513 | } |
514 | |
515 | /** |
516 | \brief Gets the contact's material index for shape 0. |
517 | \return The contact's material index for shape 0. |
518 | */ |
519 | PX_FORCE_INLINE PxU16 getMaterialIndex0() const |
520 | { |
521 | return contactsWereModifiable ? getModifiableContact().materialIndex0 : getContactPatch().materialIndex0; |
522 | } |
523 | |
524 | /** |
525 | \brief Gets the contact's material index for shape 1. |
526 | \return The contact's material index for shape 1. |
527 | */ |
528 | PX_FORCE_INLINE PxU16 getMaterialIndex1() const |
529 | { |
530 | return contactsWereModifiable ? getModifiableContact().materialIndex1 : getContactPatch().materialIndex1; |
531 | } |
532 | |
533 | /** |
534 | \brief Advances the contact stream iterator to a specific contact index. |
535 | */ |
536 | bool advanceToIndex(const PxU32 initialIndex) |
537 | { |
538 | PX_ASSERT(currPtr == (reinterpret_cast<const PxU8*>(header + 1))); |
539 | |
540 | PxU32 numToAdvance = initialIndex; |
541 | |
542 | if(numToAdvance == 0) |
543 | { |
544 | PX_ASSERT(hasNextPatch()); |
545 | nextPatch(); |
546 | return true; |
547 | } |
548 | |
549 | while(numToAdvance) |
550 | { |
551 | while(hasNextPatch()) |
552 | { |
553 | nextPatch(); |
554 | PxU32 patchSize = nbContactsInPatch; |
555 | if(numToAdvance <= patchSize) |
556 | { |
557 | while(hasNextContact()) |
558 | { |
559 | --numToAdvance; |
560 | if(numToAdvance == 0) |
561 | return true; |
562 | nextContact(); |
563 | } |
564 | } |
565 | else |
566 | { |
567 | numToAdvance -= patchSize; |
568 | } |
569 | } |
570 | } |
571 | return false; |
572 | } |
573 | |
574 | private: |
575 | |
576 | /** |
577 | \brief Internal helper |
578 | */ |
579 | PX_FORCE_INLINE const PxContactPatch& getContactPatch() const |
580 | { |
581 | PX_ASSERT(!contactsWereModifiable); |
582 | return *reinterpret_cast<const PxContactPatch*>(patchStart); |
583 | } |
584 | |
585 | /** |
586 | \brief Internal helper |
587 | */ |
588 | PX_FORCE_INLINE const PxModifiableContact& getModifiableContact() const |
589 | { |
590 | PX_ASSERT(contactsWereModifiable); |
591 | return *static_cast<const PxModifiableContact*>(contactStart); |
592 | } |
593 | |
594 | /** |
595 | \brief Internal helper |
596 | */ |
597 | PX_FORCE_INLINE const PxModifyContactHeader& () const |
598 | { |
599 | PX_ASSERT(contactsWereModifiable); |
600 | return *static_cast<const PxModifyContactHeader*>(header); |
601 | } |
602 | |
603 | }; |
604 | |
605 | |
606 | #ifdef PX_VC |
607 | #pragma warning(pop) |
608 | #endif |
609 | |
610 | #ifndef PX_DOXYGEN |
611 | } // namespace physx |
612 | #endif |
613 | |
614 | #endif |
615 | |