RavEngine
Loading...
Searching...
No Matches
ScShapeInteraction.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 SC_SHAPE_INTERACTION_H
30#define SC_SHAPE_INTERACTION_H
31
32#include "ScElementSimInteraction.h"
33#include "ScShapeSim.h"
34#include "ScActorPair.h"
35#include "ScScene.h"
36#include "ScBodySim.h"
37#include "PxsContactManager.h"
38#include "PxsContext.h"
39#include "PxsSimpleIslandManager.h"
40
41#define INVALID_REPORT_PAIR_ID 0xffffffff
42
43namespace physx
44{
45class PxsContactManagerOutputIterator;
46namespace Sc
47{
48 class ContactReportAllocationManager;
49 /*
50 Description: A ShapeInteraction represents a pair of objects which _may_ have contacts. Created by the broadphase
51 and processed by the NPhaseCore.
52 */
54 {
55 friend class NPhaseCore;
56 ShapeInteraction& operator=(const ShapeInteraction&);
57 public:
58 enum SiFlag
59 {
60 PAIR_FLAGS_MASK = (PxPairFlag::eNEXT_FREE - 1), // Bits where the PxPairFlags get stored
61 NEXT_FREE = ((PAIR_FLAGS_MASK << 1) & ~PAIR_FLAGS_MASK),
62
63 HAS_TOUCH = (NEXT_FREE << 0), // Tracks the last know touch state
64 HAS_NO_TOUCH = (NEXT_FREE << 1), // Tracks the last know touch state
65 TOUCH_KNOWN = (HAS_TOUCH | HAS_NO_TOUCH), // If none of these flags is set, the touch state is not known (for example, this is true for pairs that never ran narrowphase
66
67 CONTACTS_COLLECT_POINTS = (NEXT_FREE << 2), // The user wants to get the contact points (includes debug rendering)
68 CONTACTS_RESPONSE_DISABLED = (NEXT_FREE << 3), // Collision response disabled (either by the user through PxPairFlag::eSOLVE_CONTACT or because the pair has two kinematics)
69
74
75 FORCE_THRESHOLD_EXCEEDED_NOW = (NEXT_FREE << 4),
76 FORCE_THRESHOLD_EXCEEDED_BEFORE = (NEXT_FREE << 5),
77 FORCE_THRESHOLD_EXCEEDED_FLAGS = FORCE_THRESHOLD_EXCEEDED_NOW | FORCE_THRESHOLD_EXCEEDED_BEFORE,
78
79 IS_IN_PERSISTENT_EVENT_LIST = (NEXT_FREE << 6), // The pair is in the list of persistent contact events
80 WAS_IN_PERSISTENT_EVENT_LIST = (NEXT_FREE << 7), // The pair is inactive but used to be in the list of persistent contact events
81 IN_PERSISTENT_EVENT_LIST = IS_IN_PERSISTENT_EVENT_LIST | WAS_IN_PERSISTENT_EVENT_LIST,
82 IS_IN_FORCE_THRESHOLD_EVENT_LIST= (NEXT_FREE << 8), // The pair is in the list of force threshold contact events
83 IS_IN_CONTACT_EVENT_LIST = IS_IN_PERSISTENT_EVENT_LIST | IS_IN_FORCE_THRESHOLD_EVENT_LIST,
84
85 LL_MANAGER_RECREATE_EVENT = CONTACT_REPORT_EVENTS | CONTACTS_COLLECT_POINTS |
86 CONTACTS_RESPONSE_DISABLED | PxU32(PxPairFlag::eMODIFY_CONTACTS)
87 };
88 ShapeInteraction(ShapeSimBase& s1, ShapeSimBase& s2, PxPairFlags pairFlags, PxsContactManager* contactManager);
90
91 // Submits to contact stream
92 void processUserNotification(PxU32 contactEvent, PxU16 infoFlags, bool touchLost, const PxU32 ccdPass, const bool useCurrentTransform,
93 PxsContactManagerOutputIterator& outputs); // ccdPass is 0 for discrete collision and then 1,2,... for the CCD passes
94
95 void processUserNotificationSync();
96
97 void processUserNotificationAsync(PxU32 contactEvent, PxU16 infoFlags, bool touchLost, const PxU32 ccdPass, const bool useCurrentTransform,
98 PxsContactManagerOutputIterator& outputs, ContactReportAllocationManager* alloc = NULL); // ccdPass is 0 for discrete collision and then 1,2,... for the CCD passes
99
101 float scale, float param_contactForce, float param_contactNormal, float param_contactError, float param_contactPoint
102 );
103
104 PxU32 getContactPointData(const void*& contactPatches, const void*& contactPoints, PxU32& contactDataSize, PxU32& contactPointCount, PxU32& patchCount, const PxReal*& impulses, PxU32 startOffset, PxsContactManagerOutputIterator& outputs);
105
106 bool managerLostTouch(const PxU32 ccdPass, bool adjustCounters, PxsContactManagerOutputIterator& outputs);
107 void managerNewTouch(const PxU32 ccdPass, bool adjustCounters, PxsContactManagerOutputIterator& outputs);
108
109 PX_FORCE_INLINE void adjustCountersOnLostTouch();
110 PX_FORCE_INLINE void adjustCountersOnNewTouch();
111
112 PX_FORCE_INLINE void sendCCDRetouch(const PxU32 ccdPass, PxsContactManagerOutputIterator& outputs);
113 void setContactReportPostSolverVelocity(ContactStreamManager& cs);
114 PX_FORCE_INLINE void sendLostTouchReport(bool shapeVolumeRemoved, const PxU32 ccdPass, PxsContactManagerOutputIterator& ouptuts);
115 void resetManagerCachedState() const;
116
117 PX_FORCE_INLINE ActorPair* getActorPair() const { return mActorPair; }
118 PX_FORCE_INLINE void setActorPair(ActorPair& aPair) { mActorPair = &aPair; }
119 PX_FORCE_INLINE void clearActorPair() { mActorPair = NULL; }
120 PX_FORCE_INLINE ActorPairReport& getActorPairReport() const { return ActorPairReport::cast(*mActorPair); }
121 PX_INLINE PxIntBool isReportPair() const { /*PX_ASSERT(!(PxIntBool(getPairFlags() & CONTACT_REPORT_EVENTS)) || mActorPair->isReportPair());*/ return PxIntBool(getPairFlags() & CONTACT_REPORT_EVENTS); }
122 PX_INLINE PxIntBool hasTouch() const { return readFlag(HAS_TOUCH); }
123 PX_INLINE PxIntBool hasCCDTouch() const { PX_ASSERT(mManager); return mManager->getHadCCDContact(); }
124 PX_INLINE void swapAndClearForceThresholdExceeded();
125
126 PX_FORCE_INLINE void raiseFlag(SiFlag flag) { mFlags |= flag; }
127 PX_FORCE_INLINE PxIntBool readFlag(SiFlag flag) const { return PxIntBool(mFlags & flag); }
128 PX_FORCE_INLINE PxU32 getPairFlags() const;
129
130 PX_FORCE_INLINE void removeFromReportPairList();
131
132 void onShapeChangeWhileSleeping(bool shapeOfDynamicChanged);
133
134 PX_FORCE_INLINE PxIntBool hasKnownTouchState() const;
135
136 bool onActivate_(void* data);
137 bool onDeactivate_();
138
139 void updateState(const PxU8 externalDirtyFlags);
140
141 const PxsContactManager* getContactManager() const { return mManager; }
142
143 void clearIslandGenData();
144
145 PX_FORCE_INLINE PxU32 getEdgeIndex() const { return mEdgeIndex; }
146
147 PX_FORCE_INLINE Sc::ShapeSimBase& getShape0() const { return static_cast<ShapeSimBase&>(getElement0()); }
148 PX_FORCE_INLINE Sc::ShapeSimBase& getShape1() const { return static_cast<ShapeSimBase&>(getElement1()); }
149
150 private:
151 ActorPair* mActorPair;
152 PxsContactManager* mManager;
153 PxU32 mContactReportStamp;
154 PxU32 mReportPairIndex; // Owned by NPhaseCore for its report pair list
155 PxU32 mEdgeIndex;
156 PxU16 mReportStreamIndex; // position of this pair in the contact report stream
157
158 void createManager(void* contactManager);
159 PX_INLINE bool updateManager(void* contactManager);
160 PX_INLINE void destroyManager();
161 PX_FORCE_INLINE bool activeManagerAllowed() const;
162 PX_FORCE_INLINE PxU32 getManagerContactState() const { return mFlags & LL_MANAGER_RECREATE_EVENT; }
163
164 PX_FORCE_INLINE void clearFlag(SiFlag flag) { mFlags &= ~flag; }
165 PX_INLINE void setFlag(SiFlag flag, bool value)
166 {
167 if (value)
168 raiseFlag(flag);
169 else
170 clearFlag(flag);
171 }
172 PX_FORCE_INLINE void setHasTouch() { clearFlag(HAS_NO_TOUCH); raiseFlag(HAS_TOUCH); }
173 PX_FORCE_INLINE void setHasNoTouch() { clearFlag(HAS_TOUCH); raiseFlag(HAS_NO_TOUCH); }
174
175 PX_FORCE_INLINE void setPairFlags(PxPairFlags flags);
176
177 PX_FORCE_INLINE void processReportPairOnActivate();
178 PX_FORCE_INLINE void processReportPairOnDeactivate();
179
180 // Certain SiFlag cache properties of the pair. If these properties change then the flags have to be updated.
181 // For example: is collision enabled for this pair? are contact points requested for this pair?
182 PX_FORCE_INLINE void updateFlags(const Sc::Scene&, const Sc::ActorSim&, const Sc::ActorSim&, const PxU32 pairFlags);
183
184 friend class Sc::Scene;
185 };
186
187} // namespace Sc
188
189// PT: TODO: is there a reason for force-inlining all that stuff?
190
191PX_FORCE_INLINE void Sc::ShapeInteraction::sendLostTouchReport(bool shapeVolumeRemoved, const PxU32 ccdPass, PxsContactManagerOutputIterator& outputs)
192{
193 PX_ASSERT(hasTouch());
194 PX_ASSERT(isReportPair());
195
196 const PxU32 pairFlags = getPairFlags();
197 const PxU32 notifyTouchLost = pairFlags & PxU32(PxPairFlag::eNOTIFY_TOUCH_LOST);
198 const PxIntBool thresholdExceeded = readFlag(ShapeInteraction::FORCE_THRESHOLD_EXCEEDED_NOW);
199 const PxU32 notifyThresholdLost = thresholdExceeded ? (pairFlags & PxU32(PxPairFlag::eNOTIFY_THRESHOLD_FORCE_LOST)) : 0;
200 if(!notifyTouchLost && !notifyThresholdLost)
201 return;
202
203 PxU16 infoFlag = 0;
204 if (mActorPair->getTouchCount() == 1) // this code assumes that the actor pair touch count does get decremented afterwards
205 {
207 }
208
209 //Lost touch is processed after solver, so we should use the previous transform to update the pose for objects if user request eCONTACT_EVENT_POSE
210 const bool useCurrentTransform = false;
211
212 const PxU32 triggeredFlags = notifyTouchLost | notifyThresholdLost;
213 PX_ASSERT(triggeredFlags);
214 processUserNotification(triggeredFlags, infoFlag, true, ccdPass, useCurrentTransform, outputs);
215
216 if(shapeVolumeRemoved)
217 {
218 ActorPairReport& apr = getActorPairReport();
219 ContactStreamManager& cs = apr.getContactStreamManager();
221 }
222}
223
224PX_FORCE_INLINE void Sc::ShapeInteraction::setPairFlags(PxPairFlags flags)
225{
226 PX_ASSERT(PxU32(flags) < PxPairFlag::eNEXT_FREE); // to find out if a new PxPairFlag has been added after eLAST instead of in front
227
228 PxU32 newFlags = mFlags;
229 PxU32 fl = PxU32(flags) & PAIR_FLAGS_MASK;
230 newFlags &= (~PAIR_FLAGS_MASK); // clear old flags
231 newFlags |= fl;
232
233 mFlags = newFlags;
234}
235
236// PT: returning PxU32 instead of PxPairFlags to remove LHS. Please do not undo this.
237PX_FORCE_INLINE PxU32 Sc::ShapeInteraction::getPairFlags() const
238{
239 return (mFlags & PAIR_FLAGS_MASK);
240}
241
242PX_INLINE void Sc::ShapeInteraction::swapAndClearForceThresholdExceeded()
243{
244 PxU32 flags = mFlags;
245
246 PX_COMPILE_TIME_ASSERT(FORCE_THRESHOLD_EXCEEDED_NOW == (FORCE_THRESHOLD_EXCEEDED_BEFORE >> 1));
247
248 PxU32 nowToBefore = (flags & FORCE_THRESHOLD_EXCEEDED_NOW) << 1;
249 flags &= ~(FORCE_THRESHOLD_EXCEEDED_NOW | FORCE_THRESHOLD_EXCEEDED_BEFORE);
250 flags |= nowToBefore;
251
252 mFlags = flags;
253}
254
255PX_FORCE_INLINE void Sc::ShapeInteraction::removeFromReportPairList()
256{
257 // this method should only get called if the pair is in the list for
258 // persistent or force based contact reports
259 PX_ASSERT(mReportPairIndex != INVALID_REPORT_PAIR_ID);
260 PX_ASSERT(readFlag(IS_IN_CONTACT_EVENT_LIST));
261
262 Scene& scene = getScene();
263
264 if (readFlag(IS_IN_FORCE_THRESHOLD_EVENT_LIST))
265 scene.getNPhaseCore()->removeFromForceThresholdContactEventPairs(this);
266 else
267 {
268 PX_ASSERT(readFlag(IS_IN_PERSISTENT_EVENT_LIST));
269 scene.getNPhaseCore()->removeFromPersistentContactEventPairs(this);
270 }
271}
272
273PX_INLINE bool Sc::ShapeInteraction::updateManager(void* contactManager)
274{
275 if (activeManagerAllowed())
276 {
277 if (mManager == 0)
278 createManager(contactManager);
279
280 return (mManager != NULL); // creation might fail (pool reached limit, mem allocation failed etc.)
281 }
282 else
283 return false;
284}
285
286PX_INLINE void Sc::ShapeInteraction::destroyManager()
287{
288 PX_ASSERT(mManager);
289
290 Scene& scene = getScene();
291
292 PxvNphaseImplementationContext* nphaseImplementationContext = scene.getLowLevelContext()->getNphaseImplementationContext();
293 PX_ASSERT(nphaseImplementationContext);
294 nphaseImplementationContext->unregisterContactManager(mManager);
295
296 /*if (mEdgeIndex != IG_INVALID_EDGE)
297 scene.getSimpleIslandManager()->clearEdgeRigidCM(mEdgeIndex);*/
298 scene.getLowLevelContext()->destroyContactManager(mManager);
299 mManager = 0;
300}
301
302PX_FORCE_INLINE bool Sc::ShapeInteraction::activeManagerAllowed() const
303{
304 ShapeSimBase& shape0 = getShape0();
305 ShapeSimBase& shape1 = getShape1();
306
307 ActorSim& bodySim0 = shape0.getActor();
308 ActorSim& bodySim1 = shape1.getActor();
309
310 // the first shape always belongs to a dynamic body or soft body
311 PX_ASSERT(bodySim0.isDynamicRigid() || bodySim0.isSoftBody() || bodySim0.isFEMCloth() || bodySim0.isParticleSystem() || bodySim0.isHairSystem());
312
313 const IG::IslandSim& islandSim = getScene().getSimpleIslandManager()->getSpeculativeIslandSim();
314
315 //check whether active in the speculative sim!
316
317 return (islandSim.getNode(bodySim0.getNodeIndex()).isActive() ||
318 (!bodySim1.isStaticRigid() && islandSim.getNode(bodySim1.getNodeIndex()).isActive()));
319}
320
321PX_FORCE_INLINE void Sc::ShapeInteraction::sendCCDRetouch(const PxU32 ccdPass, PxsContactManagerOutputIterator& outputs)
322{
323 const PxU32 pairFlags = getPairFlags();
324 if (pairFlags & PxPairFlag::eNOTIFY_TOUCH_CCD)
325 processUserNotification(PxPairFlag::eNOTIFY_TOUCH_CCD, 0, false, ccdPass, false, outputs);
326}
327
328PX_FORCE_INLINE void Sc::ShapeInteraction::adjustCountersOnLostTouch()
329{
330 PX_ASSERT(mActorPair->getTouchCount());
331
332 mActorPair->decTouchCount();
333}
334
335PX_FORCE_INLINE void Sc::ShapeInteraction::adjustCountersOnNewTouch()
336{
337 mActorPair->incTouchCount();
338}
339
340PX_FORCE_INLINE PxIntBool Sc::ShapeInteraction::hasKnownTouchState() const
341{
342 // For a pair where the bodies were added asleep, the touch state is not known until narrowphase runs on the pair for the first time.
343 // If such a pair looses AABB overlap before, the conservative approach is to wake the bodies up. This method provides an indicator that
344 // this is such a pair. Note: this might also wake up objects that do not touch but that's the price to pay (unless we want to run
345 // overlap tests on such pairs).
346 if (mManager)
347 return mManager->touchStatusKnown();
348 else
349 return readFlag(TOUCH_KNOWN);
350}
351
352}
353
354#endif
Definition PxRenderOutput.h:50
Definition PxvNphaseImplementationContext.h:81
Definition PxsContactManager.h:77
Class shared by all shape interactions for a pair of actors if contact reports are requested.
Definition ScActorPair.h:110
Class shared by all shape interactions for a pair of actors.
Definition ScActorPair.h:69
Definition ScActorSim.h:83
Definition ScNPhaseCore.h:152
Contact report logic and data management.
Definition ScContactStream.h:125
Definition ScElementSimInteraction.h:40
Definition ScNPhaseCore.h:193
Definition ScScene.h:240
Definition ScShapeInteraction.h:54
void processUserNotificationAsync(PxU32 contactEvent, PxU16 infoFlags, bool touchLost, const PxU32 ccdPass, const bool useCurrentTransform, PxsContactManagerOutputIterator &outputs, ContactReportAllocationManager *alloc=NULL)
Definition ScShapeInteraction.cpp:316
Definition ScShapeSimBase.h:54
#define PX_FORCE_INLINE
Definition PxPreprocessor.h:335
#define PX_COMPILE_TIME_ASSERT(exp)
Definition PxPreprocessor.h:428
#define PX_INLINE
Definition PxPreprocessor.h:320
Sorts an array of objects in ascending order, assuming that the predicate implements the < operator:
Definition PxBoxController.h:39
PxFlags< PxPairFlag::Enum, PxU16 > PxPairFlags
Bitfield that contains a set of raised flags defined in PxPairFlag.
Definition PxFiltering.h:277
@ eACTOR_PAIR_LOST_TOUCH
All contact between the actor pair was lost.
Definition PxSimulationEventCallback.h:430
@ eNEXT_FREE
For internal use only.
Definition PxFiltering.h:258
@ ePOST_SOLVER_VELOCITY
Provide post solver velocities in contact reports for this collision pair.
Definition PxFiltering.h:240
@ eCONTACT_EVENT_POSE
Provide rigid body poses in contact reports for this collision pair.
Definition PxFiltering.h:256
@ ePRE_SOLVER_VELOCITY
Provide pre solver velocities in contact reports for this collision pair.
Definition PxFiltering.h:230
@ eNOTIFY_TOUCH_CCD
Call contact report callback when this collision pair is in contact during CCD passes.
Definition PxFiltering.h:145
@ eNOTIFY_THRESHOLD_FORCE_LOST
Call contact report callback when the contact force between the actors of this collision pair falls b...
Definition PxFiltering.h:184
@ eNOTIFY_TOUCH_LOST
Call contact report callback or trigger callback when this collision pair stops to be in contact.
Definition PxFiltering.h:125
@ eMODIFY_CONTACTS
Call contact modification callback for this collision pair.
Definition PxFiltering.h:71
@ eNOTIFY_THRESHOLD_FORCE_FOUND
Call contact report callback when the contact force between the actors of this collision pair exceeds...
Definition PxFiltering.h:156
@ eNOTIFY_TOUCH_FOUND
Call contact report callback or trigger callback when this collision pair starts to be in contact.
Definition PxFiltering.h:87
@ eNOTIFY_TOUCH_PERSISTS
Call contact report callback while this collision pair is in contact.
Definition PxFiltering.h:107
@ eNOTIFY_THRESHOLD_FORCE_PERSISTS
Call contact report callback when the contact force between the actors of this collision pair continu...
Definition PxFiltering.h:170
@ eTEST_FOR_REMOVED_SHAPES
Need to test stream for shapes that were removed from the actor/scene.
Definition ScContactStream.h:85