RavEngine
Loading...
Searching...
No Matches
ScContactStream.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_CONTACT_STREAM_H
30#define SC_CONTACT_STREAM_H
31
32#include "foundation/Px.h"
33#include "PxSimulationEventCallback.h"
34#include "ScObjectIDTracker.h"
35#include "ScRigidSim.h"
36#include "ScStaticSim.h"
37#include "ScBodySim.h"
38
39namespace physx
40{
41 class PxShape;
42
43namespace Sc
44{
45 class ActorPair;
46
47
48 // Internal counterpart of PxContactPair
50 {
51 public:
52 PxShape* shapes[2];
53 const PxU8* contactPatches;
54 const PxU8* contactPoints;
55 const PxReal* contactForces;
56 PxU32 requiredBufferSize;
57 PxU8 contactCount;
58 PxU8 patchCount;
59 PxU16 constraintStreamSize;
60 PxU16 flags;
61 PxU16 events;
62 PxU32 shapeID[2];
63 //26 (or 38 on 64bit)
64 };
66
68 {
69 enum Enum
70 {
86
91
96
102
106 eNEXT_FREE_FLAG = (1<<4)
107 };
108 };
109
111 {
112 PxU16 contactPass; // marker for extra data to know when a new collison pass started (discrete collision -> CCD pass 1 -> CCD pass 2 -> ...)
113 PxU16 pad; // to keep the stream 4byte aligned
114 };
115
125 {
126 public:
127 PX_FORCE_INLINE ContactStreamManager() : maxPairCount(0), flags_and_maxExtraDataBlocks(0) {}
129
130 PX_FORCE_INLINE void reset();
131
132 PX_FORCE_INLINE PxU16 getFlags() const;
133 PX_FORCE_INLINE void raiseFlags(PxU16 flags);
134 PX_FORCE_INLINE void clearFlags(PxU16 flags);
135
136 PX_FORCE_INLINE PxU32 getMaxExtraDataSize() const;
137 PX_FORCE_INLINE void setMaxExtraDataSize(PxU32 size); // size in bytes (will translate into blocks internally)
138
139 PX_FORCE_INLINE Sc::ContactShapePair* getShapePairs(PxU8* contactReportPairData) const;
140
141 PX_FORCE_INLINE static void convertDeletedShapesInContactStream(ContactShapePair*, PxU32 pairCount, const ObjectIDTracker&);
142
143 PX_FORCE_INLINE static PxU32 computeExtraDataBlockCount(PxU32 extraDataSize);
144 PX_FORCE_INLINE static PxU32 computeExtraDataBlockSize(PxU32 extraDataSize);
145 PX_FORCE_INLINE static PxU16 computeContactReportExtraDataSize(PxU32 extraDataFlags, bool addHeader);
146 PX_FORCE_INLINE static void fillInContactReportExtraData(PxContactPairVelocity*, PxU32 index, const ActorSim&, bool isCCDPass);
147 PX_FORCE_INLINE static void fillInContactReportExtraData(PxContactPairPose*, PxU32 index, const ActorSim&, bool isCCDPass, const bool useCurrentTransform);
148 PX_FORCE_INLINE void fillInContactReportExtraData(PxU8* stream, PxU32 extraDataFlags, const ActorSim&, const ActorSim&, PxU32 ccdPass, const bool useCurrentTransform, PxU32 pairIndex, PxU32 sizeOffset);
149 PX_FORCE_INLINE void setContactReportPostSolverVelocity(PxU8* stream, const ActorSim&, const ActorSim&);
150
151 PxU32 bufferIndex; // marks the start of the shape pair stream of the actor pair (byte offset with respect to global contact buffer stream)
152 PxU16 maxPairCount; // used to reserve the same amount of memory as in the last frame (as an initial guess)
153 PxU16 currentPairCount; // number of shape pairs stored in the buffer
154 PxU16 extraDataSize; // size of the extra data section in the stream
155 private:
156 PxU16 flags_and_maxExtraDataBlocks; // used to reserve the same amount of memory as in the last frame (as an initial guess)
157
158 public:
159 static const PxU32 sExtraDataBlockSizePow2 = 4; // extra data gets allocated as a multiple of 2^sExtraDataBlockSizePow2 to keep memory low of this struct.
160 static const PxU32 sFlagMask = (ContactStreamManagerFlag::eNEXT_FREE_FLAG - 1);
161 static const PxU32 sMaxExtraDataShift = 4; // shift necessary to extract the maximum number of blocks allocated for extra data
162
163 PX_COMPILE_TIME_ASSERT(ContactStreamManagerFlag::eNEXT_FREE_FLAG == (1 << sMaxExtraDataShift));
164 };
165
166} // namespace Sc
167
168
169PX_FORCE_INLINE void Sc::ContactStreamManager::reset()
170{
171 currentPairCount = 0;
172 extraDataSize = 0;
173 flags_and_maxExtraDataBlocks &= ~sFlagMask;
174}
175
176
177PX_FORCE_INLINE PxU16 Sc::ContactStreamManager::getFlags() const
178{
179 return (flags_and_maxExtraDataBlocks & sFlagMask);
180}
181
182
183PX_FORCE_INLINE void Sc::ContactStreamManager::raiseFlags(PxU16 flags)
184{
186
187 flags_and_maxExtraDataBlocks |= flags;
188}
189
190
191PX_FORCE_INLINE void Sc::ContactStreamManager::clearFlags(PxU16 flags)
192{
194
195 PxU16 tmpFlags = getFlags();
196 tmpFlags &= ~flags;
197 flags_and_maxExtraDataBlocks &= ~sFlagMask;
198 raiseFlags(tmpFlags);
199}
200
201
202PX_FORCE_INLINE PxU32 Sc::ContactStreamManager::getMaxExtraDataSize() const
203{
204 return PxU32((flags_and_maxExtraDataBlocks >> sMaxExtraDataShift) << sExtraDataBlockSizePow2);
205}
206
207
208PX_FORCE_INLINE void Sc::ContactStreamManager::setMaxExtraDataSize(PxU32 size)
209{
210 PxU32 nbBlocks = computeExtraDataBlockCount(size);
211 flags_and_maxExtraDataBlocks = PxTo16((flags_and_maxExtraDataBlocks & sFlagMask) | (nbBlocks << sMaxExtraDataShift));
212}
213
214
215PX_FORCE_INLINE Sc::ContactShapePair* Sc::ContactStreamManager::getShapePairs(PxU8* contactReportPairData) const
216{
217 return reinterpret_cast<Sc::ContactShapePair*>(contactReportPairData + getMaxExtraDataSize());
218}
219
220
221PX_FORCE_INLINE void Sc::ContactStreamManager::convertDeletedShapesInContactStream(ContactShapePair* shapePairs, PxU32 pairCount, const ObjectIDTracker& tracker)
222{
223 for(PxU32 i=0; i < pairCount; i++)
224 {
225 ContactShapePair& csp = shapePairs[i];
226
227 PxU32 shape0ID = csp.shapeID[0];
228 PxU32 shape1ID = csp.shapeID[1];
229
230 PxU16 flags = csp.flags;
231 PX_COMPILE_TIME_ASSERT(sizeof(flags) == sizeof((reinterpret_cast<ContactShapePair*>(0))->flags));
232
233 if (tracker.isDeletedID(shape0ID))
235 if (tracker.isDeletedID(shape1ID))
237
238 csp.flags = flags;
239 }
240}
241
242
243PX_FORCE_INLINE PxU32 Sc::ContactStreamManager::computeExtraDataBlockCount(PxU32 extraDataSize_)
244{
245 PxU32 nbBlocks;
246 if (extraDataSize_ & ((1 << sExtraDataBlockSizePow2) - 1)) // not a multiple of block size -> need one block more
247 nbBlocks = (extraDataSize_ >> sExtraDataBlockSizePow2) + 1;
248 else
249 nbBlocks = (extraDataSize_ >> sExtraDataBlockSizePow2);
250
251 return nbBlocks;
252}
253
254
255PX_FORCE_INLINE PxU32 Sc::ContactStreamManager::computeExtraDataBlockSize(PxU32 extraDataSize_)
256{
257 return (computeExtraDataBlockCount(extraDataSize_) << sExtraDataBlockSizePow2);
258}
259
260
261PX_FORCE_INLINE PxU16 Sc::ContactStreamManager::computeContactReportExtraDataSize(PxU32 extraDataFlags, bool addHeader)
262{
263 PX_ASSERT(extraDataFlags);
264
265 PxU16 extraDataSize_ = sizeof(PxContactPairIndex);
266 if (extraDataFlags & PxPairFlag::ePRE_SOLVER_VELOCITY)
267 extraDataSize_ += sizeof(PxContactPairVelocity);
268 if (extraDataFlags & PxPairFlag::ePOST_SOLVER_VELOCITY)
269 extraDataSize_ += sizeof(PxContactPairVelocity);
270 if (extraDataFlags & PxPairFlag::eCONTACT_EVENT_POSE)
271 extraDataSize_ += sizeof(PxContactPairPose);
272 if (addHeader)
273 extraDataSize_ += sizeof(ContactStreamHeader);
274 return extraDataSize_;
275}
276
277
278PX_FORCE_INLINE void Sc::ContactStreamManager::fillInContactReportExtraData(PxContactPairVelocity* cpVel, PxU32 index, const ActorSim& rs, bool isCCDPass)
279{
280 if (rs.getActorType() != PxActorType::eRIGID_STATIC)
281 {
282 const BodySim& bs = static_cast<const BodySim&>(rs);
283 if ((!isCCDPass) || (cpVel->type == PxContactPairExtraDataType::ePOST_SOLVER_VELOCITY))
284 {
285 const BodyCore& bc = bs.getBodyCore();
286 cpVel->linearVelocity[index] = bc.getLinearVelocity();
287 cpVel->angularVelocity[index] = bc.getAngularVelocity();
288 }
289 else
290 {
291 PX_ASSERT(cpVel->type == PxContactPairExtraDataType::ePRE_SOLVER_VELOCITY);
292 const Cm::SpatialVector& vel = bs.getLowLevelBody().getPreSolverVelocities();
293 cpVel->linearVelocity[index] = vel.linear;
294 cpVel->angularVelocity[index] = vel.angular;
295 }
296 }
297 else
298 {
299 cpVel->linearVelocity[index] = PxVec3(0.0f);
300 cpVel->angularVelocity[index] = PxVec3(0.0f);
301 }
302}
303
304
305PX_FORCE_INLINE void Sc::ContactStreamManager::fillInContactReportExtraData(PxContactPairPose* cpPose, PxU32 index, const ActorSim& rs, bool isCCDPass, const bool useCurrentTransform)
306{
307 if(rs.getActorType() != PxActorType::eRIGID_STATIC)
308 {
309 const BodySim& bs = static_cast<const BodySim&>(rs);
310 const BodyCore& bc = bs.getBodyCore();
311 const PxTransform& src = (!isCCDPass && useCurrentTransform) ? bc.getBody2World() : bs.getLowLevelBody().getLastCCDTransform();
312 cpPose->globalPose[index] = src * bc.getBody2Actor().getInverse();
313 }
314 else
315 {
316 const StaticSim& ss = static_cast<const StaticSim&>(rs);
317 const StaticCore& sc = ss.getStaticCore();
318 cpPose->globalPose[index] = sc.getActor2World();
319 }
320}
321
322
323PX_FORCE_INLINE void Sc::ContactStreamManager::fillInContactReportExtraData(PxU8* stream, PxU32 extraDataFlags, const ActorSim& rs0, const ActorSim& rs1, PxU32 ccdPass, const bool useCurrentTransform,
324 PxU32 pairIndex, PxU32 sizeOffset)
325{
326 ContactStreamHeader* strHeader = reinterpret_cast<ContactStreamHeader*>(stream);
327 strHeader->contactPass = PxTo16(ccdPass);
328
329 stream += sizeOffset;
330 PxU8* edStream = stream;
331 bool isCCDPass = (ccdPass != 0);
332
333 {
334 PxContactPairIndex* cpIndex = reinterpret_cast<PxContactPairIndex*>(edStream);
336 cpIndex->index = PxTo16(pairIndex);
337 edStream += sizeof(PxContactPairIndex);
338
339 PX_ASSERT(edStream <= reinterpret_cast<PxU8*>(getShapePairs(stream)));
340 }
341
342 // Important: make sure this one is the first after the PxContactPairIndex item for discrete contacts as it needs to get filled in before the reports get sent
343 // (post solver velocity is not available when it gets created)
344 if (extraDataFlags & PxPairFlag::ePOST_SOLVER_VELOCITY)
345 {
346 PxContactPairVelocity* cpVel = reinterpret_cast<PxContactPairVelocity*>(edStream);
348 edStream += sizeof(PxContactPairVelocity);
349
350 if (!isCCDPass)
351 raiseFlags(ContactStreamManagerFlag::eNEEDS_POST_SOLVER_VELOCITY); // don't know the post solver velocity yet
352 else
353 {
354 ContactStreamManager::fillInContactReportExtraData(cpVel, 0, rs0, true);
355 ContactStreamManager::fillInContactReportExtraData(cpVel, 1, rs1, true);
356 }
357
358 PX_ASSERT(edStream <= reinterpret_cast<PxU8*>(getShapePairs(stream)));
359 }
360 if (extraDataFlags & PxPairFlag::ePRE_SOLVER_VELOCITY)
361 {
362 PxContactPairVelocity* cpVel = reinterpret_cast<PxContactPairVelocity*>(edStream);
364 ContactStreamManager::fillInContactReportExtraData(cpVel, 0, rs0, isCCDPass);
365 ContactStreamManager::fillInContactReportExtraData(cpVel, 1, rs1, isCCDPass);
366 edStream += sizeof(PxContactPairVelocity);
367
368 PX_ASSERT(edStream <= reinterpret_cast<PxU8*>(getShapePairs(stream)));
369 }
370 if (extraDataFlags & PxPairFlag::eCONTACT_EVENT_POSE)
371 {
372 PxContactPairPose* cpPose = reinterpret_cast<PxContactPairPose*>(edStream);
374 ContactStreamManager::fillInContactReportExtraData(cpPose, 0, rs0, isCCDPass, useCurrentTransform);
375 ContactStreamManager::fillInContactReportExtraData(cpPose, 1, rs1, isCCDPass, useCurrentTransform);
376 edStream += sizeof(PxContactPairPose);
377
378 PX_ASSERT(edStream <= reinterpret_cast<PxU8*>(getShapePairs(stream)));
379 }
380
381 extraDataSize = PxTo16(sizeOffset + PxU32(edStream - stream));
382}
383
384
385PX_FORCE_INLINE void Sc::ContactStreamManager::setContactReportPostSolverVelocity(PxU8* stream, const ActorSim& rs0, const ActorSim& rs1)
386{
387 PX_ASSERT(extraDataSize > (sizeof(ContactStreamHeader) + sizeof(PxContactPairIndex)));
388 PxContactPairVelocity* cpVel = reinterpret_cast<PxContactPairVelocity*>(stream + sizeof(ContactStreamHeader) + sizeof(PxContactPairIndex));
390
391 fillInContactReportExtraData(cpVel, 0, rs0, false);
392 fillInContactReportExtraData(cpVel, 1, rs1, false);
393
395}
396
397
398}
399
400#endif
Abstract class for collision shapes.
Definition PxShape.h:146
Definition ScActorSim.h:83
Contact report logic and data management.
Definition ScContactStream.h:125
Definition ScObjectIDTracker.h:42
#define PX_FORCE_INLINE
Definition PxPreprocessor.h:335
#define PX_COMPILE_TIME_ASSERT(exp)
Definition PxPreprocessor.h:428
Sorts an array of objects in ascending order, assuming that the predicate implements the < operator:
Definition PxBoxController.h:39
@ eRIGID_STATIC
A static rigid body.
Definition PxActor.h:126
@ eCONTACT_EVENT_POSE
see #PxContactPairPose
Definition PxSimulationEventCallback.h:65
@ ePRE_SOLVER_VELOCITY
see #PxContactPairVelocity
Definition PxSimulationEventCallback.h:63
@ eCONTACT_PAIR_INDEX
see #PxContactPairIndex
Definition PxSimulationEventCallback.h:66
@ ePOST_SOLVER_VELOCITY
see #PxContactPairVelocity
Definition PxSimulationEventCallback.h:64
@ eREMOVED_SHAPE_0
The shape with index 0 has been removed from the actor/scene.
Definition PxSimulationEventCallback.h:409
@ eREMOVED_SHAPE_1
The shape with index 1 has been removed from the actor/scene.
Definition PxSimulationEventCallback.h:414
World space actor poses of the contact pair rigid bodies.
Definition PxSimulationEventCallback.h:122
Velocities of the contact pair rigid bodies.
Definition PxSimulationEventCallback.h:100
Contact report pair information.
Definition PxSimulationEventCallback.h:504
@ 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
Definition ScContactStream.h:50
Definition ScContactStream.h:111
Definition ScContactStream.h:68
Enum
Definition ScContactStream.h:70
@ eTEST_FOR_REMOVED_SHAPES
Need to test stream for shapes that were removed from the actor/scene.
Definition ScContactStream.h:85
@ eINVALID_STREAM
Invalid stream memory not allocated.
Definition ScContactStream.h:90
@ eNEEDS_POST_SOLVER_VELOCITY
The stream contains extra data with PxContactPairVelocity items where the post solver velocity needs ...
Definition ScContactStream.h:101
@ eNEXT_FREE_FLAG
Marker for the next available free flag.
Definition ScContactStream.h:106
@ eINCOMPLETE_STREAM
Incomplete stream will be reported.
Definition ScContactStream.h:95