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
|
<html>
<head>
<title>NVIDIA(R) Blast(R) SDK 1.1 API Reference: PhysX&tm; Extensions (NvBlastExtPhysX)</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<LINK HREF="NVIDIA.css" REL="stylesheet" TYPE="text/css">
</head>
<body bgcolor="#FFFFFF">
<div id="header">
<hr class="first">
<img alt="" src="blast_logo.png">
<br>
<center>
<a class="qindex" href="main.html">Main Page</a>
<!-- <a class="qindex" href="hierarchy.html">Class Hierarchy</a> //-->
<a class="qindex" href="annotated.html">Class List</a>
<a class="qindex" href="functions.html">Class Members</a>
</center>
<hr class="second">
</div>
<!-- Generated by Doxygen 1.5.8 -->
<div class="contents">
<h1><a class="anchor" name="pageextphysx">PhysX™ Extensions (NvBlastExtPhysX) </a></h1>NvBlastExtPhysX contains classes for easier use of Blast™ Toolkit with the PhysX™ SDK. There are three of them:<ul>
<li><a class="el" href="pageextphysx.html#ExtPxManager">ExtPxManager</a> - Manager to keep Blast™ actors in sync with PhysX™ actors.</li><li><a class="el" href="pageextphysx.html#ExtImpactDamageManager">ExtImpactDamageManager</a> - Manager to collect and apply impact damage caused by collision in PhysX™ scene.</li><li><a class="el" href="pageextphysx.html#ExtPxStressSolver">ExtPxStressSolver</a> - Stress Solver to propagate stress through support graph and apply it as damage to Blast™ actors.</li></ul>
<p>
This library also contains an extension for synchronizing Blast™ state:<ul>
<li><a class="el" href="pageextphysx.html#ExtSync">ExtSync</a> - Utility for writing Blast™ state to a buffer, to be read by a client. This may be used for networking, for example.</li></ul>
<p>
It also provides classes for utilizing PhysX™ SDK Foundation capabilities:<ul>
<li><a class="el" href="pageextphysx.html#ExtGroupTaskManager">ExtGroupTaskManager</a> - Multithreaded TkGroup processing using PxTask.</li><li><a class="el" href="pageextphysx.html#ExtCustomProfiler">ExtCustomProfiler</a> - Serves Blast™ profiling zones to PxFoundation profiler (e.g. PVD) and platform specific profilers.</li></ul>
<p>
<br>
<h2><a class="anchor" name="ExtPxManager">
ExtPxManager</a></h2>
<b>Physics Manager</b> - is a reference implementation for keeping Blast™ actors synced with PhysX™ actors. Its main job is to listen for TkFamily events and update <em>PxScene</em> (by adding and removing PxActors) accordingly.<p>
In order to use it, create an ExtPxManager. If we have a physx::PxPhysics object m_physics and a TkFramework m_tkFramework, use<p>
<div class="fragment"><pre class="fragment">ExtPxManager* pxManager = ExtPxManager::create(m_physics, m_tkFramework);
</pre></div><p>
For every <em>TkAsset</em> prepare <em>ExtPxAsset</em>, which contains <em>TkAsset</em> + collection of physics geometry for every chunk. Every chunk can contain any number of subchunks, where each subchunk is basically a PxConvexMeshGeometry with transform. Also every chunk can be marked as static (<em>isStatic</em> flag). If an actor contains at least one static chunk in its support graph, it makes that actor kinematic (static). Otherwise the actor is dynamic. Having zero subchunks makes the chunk invisible in the 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.<p>
To create an <em>ExtPxFamily</em> from an <em>ExtPxAsset:</em> <p>
<div class="fragment"><pre class="fragment">ExtPxFamilyDesc familyDesc;
familyDesc.pxAsset = pxAsset;
familyDesc.group = tkGroup;
familyDesc.actorDesc.initialBondHealths = <span class="keyword">nullptr</span>;
familyDesc.actorDesc.initialSupportChunkHealths = <span class="keyword">nullptr</span>;
familyDesc.actorDesc.uniformInitialBondHealth = BOND_HEALTH_MAX;
familyDesc.actorDesc.uniformInitialLowerSupportChunkHealth = 1.0f;
ExtPxFamily* family = pxManager->createFamily(desc);
</pre></div><p>
You can subscribe to family events in order to sync graphics (or anything else) with physics:<p>
<div class="fragment"><pre class="fragment">family->subscribe(listener);
</pre></div><p>
The listener will be notified with all physics actors added and removed.<p>
And finally spawn the family in some world position (the first actor/actors will be created and an event will be fired to the listener):<p>
<div class="fragment"><pre class="fragment">ExtPxSpawnSettings spawnSettings = {
&pxScene,
defaultPxMaterial,
RIGIDBODY_DENSITY
};
family->spawn(PxTransform(0, 0, 0), PxVec3(1, 1, 1), spawnSettings);
</pre></div><p>
You can get a family's actors either from listening to events or by calling <em>getActors()</em>. Every <em>ExtPxActor</em> matches 1 <-> 1 with TkActor (which matches <em><a class="el" href="struct_nv_blast_actor.html">NvBlastActor</a></em> accordingly).<p>
<div class="fragment"><pre class="fragment">ExtPxActor* actor = ....;
physx::PxRigidDynamic rigidDynamic = actor->getPxActor();
</pre></div><p>
An ExtPxActor remains internally unchanged throughout its lifetime. Use <em>ExtPxActor</em> <em>getChunkIndices()</em> and <em>getPxActor()</em> to update your graphics representation. Sample code:<p>
<div class="fragment"><pre class="fragment"><span class="keyword">const</span> uint32_t* chunkIndices;
<span class="keywordtype">size_t</span> chunkIndexCount;
actor.getChunkIndices(chunkIndices, chunkIndexCount);
<span class="keywordflow">for</span> (uint32_t i = 0; i < chunkIndexCount; i++)
{
uint32_t chunkIndex = chunkIndices[i];
<span class="keywordflow">for</span> (Renderable* r : m_chunks[chunkIndex].renderables)
{
r->setTransform(actor.getPxActor()->getGlobalPose() * pxAsset.chunks[chunkIndex].convexes[0].transform);
}
}
</pre></div><p>
In order to use joints set a joint creation function with <em>ExtPxManager::setCreateJointFunction</em>(...). It will be called when new TkJoints are being created. All the joint updates and removals will be handled by the manager internally.<p>
<br>
<h2><a class="anchor" name="ExtImpactDamageManager">
ExtImpactDamageManager</a></h2>
<b>Impact Damage Manager</b> - is a reference implementation for fast and easy impact damage support. It is built on top of ExtPxManager.<p>
In order to use it, create it as follows:<p>
<div class="fragment"><pre class="fragment">ExtImpactDamageManager* impactManager = ExtImpactDamageManager::create(pxManager);
</pre></div><p>
Call its onContact method on every <em>PxSimulationEventCallback</em> <em>onContact()</em> <p>
<div class="fragment"><pre class="fragment"><span class="keyword">class </span>EventCallback : <span class="keyword">public</span> PxSimulationEventCallback
{
<span class="keyword">public</span>:
EventCallback(ExtImpactDamageManager* manager) : m_manager(manager) {}
<span class="keyword">virtual</span> <span class="keywordtype">void</span> onContact(<span class="keyword">const</span> PxContactPairHeader& pairHeader, <span class="keyword">const</span> PxContactPair* pairs, uint32_t nbPairs)
{
m_manager->onContact(pairHeader, pairs, nbPairs);
}
<span class="keyword">private</span>:
ExtImpactDamageManager* m_manager;
};
</pre></div><p>
Call <em>applyDamage()</em> when you want the buffered damage to be applied:<p>
<div class="fragment"><pre class="fragment">impactManager->applyDamage();
</pre></div><p>
<b>N.B.</b> for impact damage to work, you must enable contact notification with custom filter shader for PxScene. <em>ExtImpactDamageManager</em> has a reference filter shader implementation which can be used for that:<p>
<div class="fragment"><pre class="fragment">PxSceneDesc sceneDesc;
sceneDesc.filterShader = ExtImpactDamageManager::FilterShader;
</pre></div><p>
<br>
<h2><a class="anchor" name="ExtPxStressSolver">
ExtPxStressSolver</a></h2>
<b>Stress Solver</b> - this wrapper class uses <a class="el" href="pageextstress.html">Stress Solver (NvBlastExtStress)</a> to apply stress calculations to an ExtPxFamily. See <a class="el" href="pageextstress.html">Stress Solver (NvBlastExtStress)</a> for the details of the underlying stress solver.<h3><a class="anchor" name="pxstresssolverusage">
Usage</a></h3>
In order to use it, instance an ExtPxStressSolver by providing <em>ExtPxFamily:</em> <p>
<div class="fragment"><pre class="fragment">ExtPxStressSolver* stressSolver = ExtPxStressSolver::create(family);
</pre></div><p>
And then call update() every frame:<p>
<div class="fragment"><pre class="fragment"><span class="keywordtype">bool</span> doDamage = <span class="keyword">true</span>; <span class="comment">// if you want to actually apply stress and damage actors</span>
stressSolver->update(doDamage);
</pre></div><p>
By default it will apply scene gravity on static actors and centrifugal force on dynamic actors.<p>
The underlying ExtStressSolver can be accessed using <em>ExtPxStressSolver::getSolver()</em>. For example, to apply impulse to a particular actor, <em>applyImpulse</em>(...) can be called for additional stress to apply:<p>
<div class="fragment"><pre class="fragment">stressSolver->getSolver().addForce(actor, position, impulse);
</pre></div><p>
Finally, the stress solver (and its underlying ExtStressSolver) may be released using<p>
<div class="fragment"><pre class="fragment">stressSolver->release();
</pre></div><p>
<br>
<h2><a class="anchor" name="ExtSync">
ExtSync</a></h2>
<b>Synchronization Extension (NvBlastExtSync)</b> - is a reference implementation for synchronizing Blast™ state.<p>
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.<p>
3 types of events are supported:<p>
<ul>
<li><b>ExtSyncEventType::Fracture</b>: Fracture event. Contains fracture commands information on particular TkFamily. Applied incrementally. Relatively small.</li><li><b>ExtSyncEventType::FamilySync</b>: Family sync event. Contains all necessary information to fully sync TkFamily state.</li><li><b>ExtSyncEventType::Physics</b>: Physics sync event. Contains all necessary information to fully sync ExtPxFamily state.</li></ul>
<p>
In order to use it, create ExtSync:<p>
<div class="fragment"><pre class="fragment">ExtSync* sync = ExtSync::create();
</pre></div><p>
Then let ExtSync instance listen to family fracture commands and write them to internal buffer:<p>
<div class="fragment"><pre class="fragment">TkFamily* family = ...;
family->addListener(*sync);
<span class="comment">// fracture family</span>
<span class="comment">// ....</span>
</pre></div><p>
You can fully record TkFamily state or ExtPxFamily state at any moment by calling:<p>
<div class="fragment"><pre class="fragment">sync->syncFamily(tkFamily);
<span class="comment">// or</span>
sync->syncFamily(pxFamily);
</pre></div><p>
Now you can take sync buffer:<p>
<div class="fragment"><pre class="fragment"><span class="keyword">const</span> ExtSyncEvent*<span class="keyword">const</span>* buffer;
uint32_t size;
sync->acquireSyncBuffer(buffer, size);
m_savedBuffer.resize(size);
<span class="keywordflow">for</span> (uint32_t i = 0; i < size; ++i)
{
m_savedBuffer[i] = buffer[i]->clone();
}
sync->releaseSyncBuffer();
</pre></div><p>
On the client you can then apply this buffer:<p>
<div class="fragment"><pre class="fragment">sync->applySyncBuffer(tkFramework, m_savedBuffer.data(), m_savedBuffer.size(), group, pxManager);
</pre></div><p>
ExtPxManager is required only if sync buffer contains ExtSyncEventType::Physics events.<p>
<br>
<h2><a class="anchor" name="ExtGroupTaskManager">
ExtGroupTaskManager</a></h2>
This class provides a basic implementation for multithreaded TkGroup processing using PxTask and a PxTaskManager from PxFoundation.<p>
In the simplest use case, all worker threads provided by PxTaskManager are used to process the group.<p>
<div class="fragment"><pre class="fragment"><span class="comment">// creating ExtGroupTaskManager from existing taskManager and tkGroup</span>
ExtGroupTaskManager* gtm = ExtGroupTaskManager::create(*taskManager, tkGroup);
<span class="keywordflow">while</span> (running)
{
<span class="comment">// ... add TkActors to TkGroup and damage ...</span>
<span class="comment">// start processing on all worker threads provided</span>
gtm->process();
<span class="comment">// ... do something else ...</span>
<span class="comment">// wait for the group processing to finish</span>
gtm->wait();
}
<span class="comment">// after use, release the ExtGroupTaskManager</span>
gtm->release();
</pre></div><p>
<br>
<p>
Groups can be processed concurrently as well as follows.<p>
<div class="fragment"><pre class="fragment"><span class="comment">// creating ExtGroupTaskManager from existing taskManager and groups</span>
ExtGroupTaskManager* gtm0 = ExtGroupTaskManager::create(*taskManager, tkGroup0);
ExtGroupTaskManager* gtm1 = ExtGroupTaskManager::create(*taskManager, tkGroup1);
</pre></div><p>
TkActors are added to TkGroups and damaged as usual.<p>
The PxTaskManager used in this example provides four worker threads of which each ExtGroupTaskManager uses two for its group.<p>
<div class="fragment"><pre class="fragment">uint32_t started = 0;
<span class="keywordflow">if</span> (gtm0->process(2) > 0) { started++; }
<span class="keywordflow">if</span> (gtm1->process(2) > 0) { started++; }
</pre></div><p>
Note that ExtGroupTaskManager::wait() never returns true if no processing has started, as reported by ExtGroupTaskManager::process(). The illustrative busy loop is not recomended for actual use.<p>
<div class="fragment"><pre class="fragment">uint32_t completed = 0;
<span class="keywordflow">while</span> (completed < started)
{
<span class="keywordflow">if</span> (gtm0->wait(<span class="keyword">false</span>)) { completed++; }
<span class="keywordflow">if</span> (gtm1->wait(<span class="keyword">false</span>)) { completed++; }
}
</pre></div><p>
<br>
<h2><a class="anchor" name="ExtCustomProfiler">
ExtCustomProfiler</a></h2>
This Nv::Blast::ProfileCallback implementation forwards Blast™ profile events to the PxProfilerCallback attached to PxFoundation, typically a PhysX™ Visual Debugger (PVD) instance. To use it, simply attach one to Blast™.<p>
<div class="fragment"><pre class="fragment"><span class="keyword">static</span> <a class="code" href="class_nv_1_1_blast_1_1_ext_custom_profiler.html">Nv::Blast::ExtCustomProfiler</a> gBlastProfiler;
<a class="code" href="_nv_blast_profiler_8h.html#fba345e0f5a9689ded425622ea9a659b">NvBlastProfilerSetCallback</a>(&gBlastProfiler);
</pre></div><p>
For convenience, it also provides sending profile events to platform specific profilers. These are disabled by default.<p>
<div class="fragment"><pre class="fragment">gBlastProfiler.<a class="code" href="class_nv_1_1_blast_1_1_ext_custom_profiler.html#326703192c1cef7196f271e6dd47bd94">setPlatformEnabled</a>(<span class="keyword">true</span>);
</pre></div><p>
<br>
</div>
<!-- start footer part -->
<div class="footer">
Copyright © 2015-2017 NVIDIA Corporation, 2701 San Tomas Expressway, Santa Clara, CA 95050 U.S.A. All rights reserved. <a href="http://www.nvidia.com ">www.nvidia.com</a>
</div>
</body>
</html>
|