aboutsummaryrefslogtreecommitdiff
path: root/PhysX_3.4/Source/LowLevelParticles/src/PtCollisionData.h
blob: 2b0ff96220ed301f4e761363e6b70233ac002e6c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//  * Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
//  * Neither the name of NVIDIA CORPORATION nor the names of its
//    contributors may be used to endorse or promote products derived
//    from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2018 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.

#ifndef PT_COLLISION_DATA_H
#define PT_COLLISION_DATA_H

#include "PxPhysXConfig.h"
#if PX_USE_PARTICLE_SYSTEM_API

#include "foundation/PxVec3.h"
#include "foundation/PxVec4.h"
#include "foundation/PxTransform.h"
#include "particles/PxParticleFlag.h"
#include "PtConfig.h"

namespace physx
{

struct PxsShapeCore;
struct PxsBodyCore;

namespace Pt
{

#define PT_CCD_PROJECT 0         // Ocational leaking at static interfaces
#define PT_CCD_STAY 1            // Seems to work for static
#define PT_CCD_IMPACT 2          // Doesn't work at all for static interfaces
#define PT_CDD_BACKTRACK_SMALL 3 // Seems to work for static
#define PT_CDD_BACKTRACK_LARGE 4 // Seems to work for static

#define PT_CDD_BACKTRACK_SMALL_EPS 1e-4f

#define PT_CCD_MEDTHOD PT_CCD_STAY // Maybe we'll need to do something else for dynamics

PX_FORCE_INLINE void computeContinuousTargetPosition(PxVec3& surfacePos, const PxVec3& localOldPos,
                                                     const PxVec3& relativePOSITION, const PxVec3& surfaceNormal,
                                                     const PxF32 restOffset)
{
	PX_UNUSED(restOffset);
	PX_UNUSED(surfaceNormal);
	PX_UNUSED(relativePOSITION);

#if PT_CCD_MEDTHOD == PT_CCD_PROJECT
	surfacePos = localOldPos + relativePOSITION + (surfaceNormal * restOffset);
#elif PT_CCD_MEDTHOD == PT_CCD_STAY
	surfacePos = localOldPos;
#elif PT_CCD_MEDTHOD == PT_CCD_IMPACT
	surfacePos = localOldPos + relativePOSITION;
#else
	const PxF32 backtrackLength = (PT_CCD_MEDTHOD == PT_CDD_BACKTRACK_SMALL) ? PT_CDD_BACKTRACK_SMALL_EPS : restOffset;
	PxF32 relImpactLength = relativePOSITION.magnitude();
	PxF32 backtrackParam = (relImpactLength > 0.0f) ? PxMax(0.0f, relImpactLength - backtrackLength) : 0.0f;
	surfacePos = localOldPos + relativePOSITION * (backtrackParam / relImpactLength);
#endif
}

/*!
Fluid particle collision constraint
*/
struct Constraint
{
	PxVec3 normal; // Contact surface normal
	PxF32 d;       // Contact point projected on contact normal
	               // 16

  public:
	Constraint()
	{
		// Do we want to initialize the constraints on creation?
		// setZero();
	}

	Constraint(const PxVec3& _normal, const PxVec3& _p)
	{
		normal = _normal;
		d = normal.dot(_p);
	}

	PX_FORCE_INLINE PxVec3 project(const PxVec3& p) const
	{
		return (p + (normal * (d - normal.dot(p))));
	}
};

/*!
Fluid particle collision constraint data for dynamic rigid body
*/
struct ConstraintDynamic
{
	PxVec3 velocity;
	const PxsBodyCore* twoWayBody; // weak reference to rigid body.

  public:
	PX_FORCE_INLINE void setEmpty()
	{
		velocity = PxVec3(0);
		twoWayBody = NULL;
	}
};

/*!
Fluid particle collision constraint buffers
*/
struct ConstraintBuffers
{
	Constraint* constraint0Buf;
	Constraint* constraint1Buf;
	ConstraintDynamic* constraint0DynamicBuf;
	ConstraintDynamic* constraint1DynamicBuf;
};

/*!
Different types of collision
*/
struct ParticleCollisionFlags
{
	enum Enum
	{
		// Global collision flags. Used to track the latest collision status of a particle when
		// testing against potentially colliding shapes
		DC            = (1 << 0), // Discrete collision
		CC            = (1 << 1), // Continuous collision
		RESET_SNORMAL = (1 << 2), // Saves one PxVec3 in the ParticleCollData

		// When testing a particle against a shape, the following collision flags might be used
		L_CC          = (1 << 3), // Discrete collision: Predicted particle position inside discrete region of shape (shape
		// region + collision radius)
		L_DC          = (1 << 4), // Continuous collision: Predicted particle motion vector intersects shape region
		L_PROX        = (1 << 5), // Proximity collision: Predicted particle position inside proximity region of shape (shape
		// region + proximity radius)
		L_CC_PROX     = (L_CC | L_PROX),
		L_ANY         = (L_CC | L_DC | L_PROX)
	};
};

/*!
Structure to track collision data for a fluid particle
*/
struct ParticleCollData
{
	PxVec3 surfaceNormal; // Contact normal [world space]
	PxU32 flags;          // Latest collision status
	// 16

	PxVec3 surfacePos; // Contact point on shape surface [world space]
	PxF32 dcNum;       // Number of discrete collisions
	// 32

	PxVec3 surfaceVel; // Velocity of contact point on shape surface [world space]
	PxF32 ccTime;      // "Time of impact" for continuous collision
	// 48

	PxVec3 oldPos; // Old particle position
	ParticleFlags particleFlags;
	// 64

	PxVec3 newPos; // New particle position
	PxU32 origParticleIndex;
	// 80

	PxVec3 velocity; // Particle velocity
	PxF32 restOffset;
	// 96

	PxVec3 twoWayImpulse;
	const PxsBodyCore* twoWayBody; // Weak reference to colliding rigid body
	// 112

	PxVec3 localOldPos; // in
	PxU32 localFlags;   // in/out
	// 128

	PxVec3 localNewPos; // in
	Constraint* c0;     // in
	// 144

	PxVec3 localSurfaceNormal; // out
	Constraint* c1;            // in
	// 160

	PxVec3 localSurfacePos; // out
	PxF32 localDcNum;       // Number of discrete collisions
	                        // 176

  public:
	PX_FORCE_INLINE void init(const PxVec3& particlePos, const PxF32 particleRestOffset, const PxU32 particleIndex,
	                          const ParticleFlags _particleFlags)
	{
		// Initialize values

		surfaceNormal = PxVec3(0);
		flags = 0;

		surfacePos = PxVec3(0);
		dcNum = 0.0f;

		surfaceVel = PxVec3(0);
		ccTime = 1.0f; // No collision assumed.

		restOffset = particleRestOffset;

		oldPos = particlePos;

		// Remove collision flags from previous time step
		particleFlags.api = PxU16(_particleFlags.api & ((~PxU16(PxParticleFlag::eCOLLISION_WITH_STATIC)) &
		                                                (~PxU16(PxParticleFlag::eCOLLISION_WITH_DYNAMIC))));

		// Reduce cache bits
		// 11 -> 01
		// 01 -> 00
		// 00 -> 00
		PxU16 reducedCache = PxU16(((_particleFlags.low & InternalParticleFlag::eGEOM_CACHE_MASK) >> 1) &
		                           InternalParticleFlag::eGEOM_CACHE_MASK);
		particleFlags.low = PxU16((_particleFlags.low & ~PxU16(InternalParticleFlag::eGEOM_CACHE_MASK)) | reducedCache);

		origParticleIndex = particleIndex;

		twoWayBody = NULL;
		twoWayImpulse = PxVec3(0);
	}
};

struct PxVec3Pad
{
	PxVec3 v3;
	PxF32 pad;
};

struct ParticleCollDataV4
{
	ParticleCollData* collData[4];
	PX_ALIGN(16, PxVec3Pad localOldPos[4]);        // in
	PX_ALIGN(16, PxVec3Pad localNewPos[4]);        // in
	PX_ALIGN(16, PxF32 restOffset[4]);             // in
	PX_ALIGN(16, PxU32 localFlags[4]);             // in,out
	PX_ALIGN(16, PxF32 ccTime[4]);                 // out
	PX_ALIGN(16, PxVec3Pad localSurfaceNormal[4]); // out
	PX_ALIGN(16, PxVec3Pad localSurfacePos[4]);    // out
};

} // namespace Pt
} // namespace physx

#endif // PX_USE_PARTICLE_SYSTEM_API
#endif // PT_COLLISION_DATA_H