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
20namespace 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*/
35struct PxContactHeader
36{
37 enum PxContactHeaderFlags
38 {
39 eHAS_FACE_INDICES = 1, //!< Indicates this contact stream has face indices.
40 eMODIFIABLE = 2, //!< Indicates this contact stream is modifiable.
41 eFORCE_NO_RESPONSE = 4, //!< Indicates this contact stream is notify-only (no contact response).
42 eHAS_MODIFIED_MASS_RATIOS = 8, //!< Indicates this contact stream has modified mass ratios
43 eHAS_TARGET_VELOCITY = 16, //!< Indicates this contact stream has target velocities set
44 eHAS_MAX_IMPULSE = 32 //!< Indicates this contact stream has max impulses set
45 };
46 /**
47 \brief Total contact count for entire compressed contact stream
48 */
49 PxU16 totalContactCount; //2
50 /**
51 \brief The flags
52 @see PxContactHeaderFlags
53 */
54 PxU16 flags; //4
55};
56
57/**
58\brief Extended header structure for modifiable contacts.
59*/
60struct PxModifyContactHeader : public PxContactHeader
61{
62 /**
63 \brief Inverse mass scale for body A.
64 */
65 PxReal invMassScale0; //8
66 /**
67 \brief Inverse mass scale for body B.
68 */
69 PxReal invMassScale1; //12
70 /**
71 \brief Inverse inertia scale for body A.
72 */
73 PxReal invInertiaScale0; //16
74 /**
75 \brief Inverse inertia scale for body B.
76 */
77 PxReal invInertiaScale1; //20
78};
79
80/**
81\brief Base header for a contact patch
82*/
83struct 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*/
98struct 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*/
129struct 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*/
144struct 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*/
160struct 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*/
203struct 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* header;
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 contactPatchHeaderSize;
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 patchHeaderSize = 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
574private:
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& getModifiableContactHeader() 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