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
|
/*! \page pageextphysx PhysX Extensions (NvBlastExtPhysX)
NvBlastExtPhysX contains classes for easier use of Blast Toolkit with the PhysX SDK.
There are 3 of them:
- <b>ExtPxManager</b>: Manager to keep Blast Actors in sync with PhysX actors.
- <b>ExtImpactDamageManager</b>: Manager to collect and apply impact damage caused by collision in PhysX Scene.
- <b>ExtPxStressSolver</b>: Stress Solver to propagate stress through support graph and apply it as damage to Blast actors.
This library also contains an extension for synchronizing Blast state:
- <b>ExtSync</b> - Utility for writing Blast state to a buffer, to be read by a client. This may be used for networking, for example.
<br>
\section ExtPxManager
<b>Physics Manager</b> - is a reference implementation for keeping Blast Actors synced with PhysX actors. It's main job is to listen
for TkFamily events and update \a PxScene (by adding and removing PxActors) accordingly.
In order to use it create an ExtPxManager. If we have a physx::PxPhysics object m_physics and a TkFramework m_tkFramework, use
\code
ExtPxManager* pxManager = ExtPxManager::create(m_physics, m_tkFramework);
\endcode
For every \a TkAsset prepare \a ExtPxAsset. Which contains \a TkAsset + collection of physics geometry for every chunk. Every chunk can contain any number of subchunks.
Where each subchunk is basically PxConvexMeshGeometry with transform. Also every chunk can be marked as static (\a isStatic flag).
If actor contains at least one static chunks in it's support graph it makes an actor kinematic (static), otherwise it's dynamic.
Having zero subchunks makes chunk invisible in physics scene, it can be used for example to represent 'earth' as a special invisible static chunk and connect all near earth chunks to it.
To create a \a ExtPxFamily from an \a ExtPxAsset:
\code
ExtPxFamilyDesc familyDesc;
familyDesc.pxAsset = pxAsset;
familyDesc.group = tkGroup;
familyDesc.actorDesc.initialBondHealths = nullptr;
familyDesc.actorDesc.initialSupportChunkHealths = nullptr;
familyDesc.actorDesc.uniformInitialBondHealth = BOND_HEALTH_MAX;
familyDesc.actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f;
ExtPxFamily* family = pxManager->createFamily(desc);
\endcode
You can subscribe to family events in order to sync graphics (or anything else) with physics:
\code
family->subscribe(listener);
\endcode
The listener will be notified with all physics actors added and removed.
And finally spawn the family in some world position (the first actor/actors will be created and event will be fired to the listener):
\code
ExtPxSpawnSettings spawnSettings = {
&pxScene,
defaultPxMaterial,
RIGIDBODY_DENSITY
};
family->spawn(PxTransform(0, 0, 0), PxVec3(1, 1, 1), spawnSettings);
\endcode
You can get families actor's either from listening to events or by calling getActors().
Every \a ExtPxActor matches 1 <-> 1 with TkActor (which matches \a NvBlastActor accordingly).
\code
ExtPxActor* actor = ....;
physx::PxRigidDynamic rigidDynamic = actor->getPxActor(); //
\endcode
An ExtPxActor remains internally unchanged through its lifetime.
Use \a ExtPxActor \a getChunkIndices() and \a getPxActor() to update your graphics representation. Sample code:
\code
const uint32_t* chunkIndices;
size_t chunkIndexCount;
actor.getChunkIndices(chunkIndices, chunkIndexCount);
for (uint32_t i = 0; i < chunkIndexCount; i++)
{
uint32_t chunkIndex = chunkIndices[i];
for (Renderable* r : m_chunks[chunkIndex].renderables)
{
r->setTransform(actor.getPxActor()->getGlobalPose() * pxAsset.chunks[chunkIndex].convexes[0].transform);
}
}
\endcode
In order to use joints set joint create function with \a ExtPxManager::setCreateJointFunction(...). It will be called when new TkJoint's are
being created. All the joint updates and remove will be handled by manager internally.
<br>
\section ExtImpactDamageManager
<b>Impact Damage Manager</b> - is a reference implementation for fast and easy impact damage support. It's built on top of ExtPxManager.
In order to use it create it:
\code
ExtImpactDamageManager* impactManager = ExtImpactDamageManager::create(pxManager);
\endcode
Call its onContact method on every \a PxSimulationEventCallback \a onContact()
\code
class EventCallback : public PxSimulationEventCallback
{
public:
EventCallback(ExtImpactDamageManager* manager) : m_manager(manager) {}
virtual void onContact(const PxContactPairHeader& pairHeader, const PxContactPair* pairs, uint32_t nbPairs)
{
m_manager->onContact(pairHeader, pairs, nbPairs);
}
private:
ExtImpactDamageManager* m_manager;
};
\endcode
Call \a applyDamage() when you want the buffered damage to be applied:
\code
impactManager->applyDamage();
\endcode
<b>N.B.</b> for impact damage to work, you must enable contact notification with custom the filter shader for PxScene. \a ExtImpactDamageManager has a reference filter shader
implementation which can be used for that:
\code
PxSceneDesc sceneDesc;
sceneDesc.filterShader = ExtImpactDamageManager::FilterShader;
\endcode
<br>
\section extpxstresssolver ExtPxStressSolver
<b>Stress Solver</b> - this wrapper class uses \ref pageextstress to apply stress calculations to an ExtPxFamily. See \ref pageextstress for
the details of the underlying stress solver.
\subsection pxstresssolverusage Usage
In order to use it, instance an ExtPxStressSolver by providing \a ExtPxFamily:
\code
ExtPxStressSolver* stressSolver = ExtPxStressSolver::create(family);
\endcode
And then call update() every frame:
\code
bool doDamage = true; // if you want to actually apply stress and damage actors
stressSolver->update(doDamage);
\endcode
By default it will apply scene gravity on static actors and centrifugal force on dynamic actors.
The underlying ExtStressSolver can be accessed using ExtPxStressSolver::getSolver(). For example, to apply impulse to
a particular actor, use applyImpulse(...) can be called for additional stress to apply:
\code
stressSolver->getSolver().addForce(actor, position, impulse);
\endcode
Finally, the stress solver (and its underlying ExtStressSolver) may be released using
\code
stressSolver->release();
\endcode
<br>
\section ExtSync
<b>Synchronization Extension (NvBlastExtSync)</b> - is a reference implementation for synchronizing Blast state.
The idea is that you can use it to write synchronization events to the buffer (on server for example) and then apply this buffer on
a client. TkFamily ID should be properly set for that.
3 types of events are supported:
- <b>ExtSyncEventType::Fracture</b>: Fracture event. Contains fracture commands information on particular TkFamily. Applied incrementally. Relatively small.
- <b>ExtSyncEventType::FamilySync</b>: Family sync event. Contains all necessary information to fully sync TkFamily state.
- <b>ExtSyncEventType::Physics</b>: Physics sync event. Contains all necessary information to fully sync ExtPxFamily state.
In order to use it create ExtSync:
\code
ExtSync* sync = ExtSync::create();
\endcode
Then let ExtSync insatnce listen to family fracture commands and write them to internal buffer:
\code
TkFamily* family = ...;
family->addListener(*sync);
// fracture family
// ....
\endcode
You can fully record TkFamily state or ExtPxFamily state at any moment by calling:
\code
sync->syncFamily(tkFamily);
// or
sync->syncFamily(pxFamily);
\endcode
Now you can take sync buffer:
\code
const ExtSyncEvent*const* buffer;
uint32_t size;
sync->acquireSyncBuffer(buffer, size);
m_savedBuffer.resize(size);
for (uint32_t i = 0; i < size; ++i)
{
m_savedBuffer[i] = buffer[i]->clone();
}
sync->releaseSyncBuffer();
\endcode
On the client you can then apply this buffer:
\code
sync->applySyncBuffer(tkFramework, m_savedBuffer.data(), m_savedBuffer.size(), group, pxManager);
\endcode
ExtPxManager is required only if sync buffer contains ExtSyncEventType::Physics events.
<br>
*/
|