1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"[]> 2<html xml:lang="en-US" lang="en-US"> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 5 <meta http-equiv="Content-Style-Type" content="text/css" /> 6 <link rel="stylesheet" href="../../../css/document.css" type="text/css" /> 7 <title>Basic Particle Features</title> 8 </head> 9 <body> 10 <h1>Features Used in Particle Calculations</h1> 11 <div class="section"> 12 <h2><a name="animframe" id="animframe"></a>Animation Frame Control</h2> 13 <p><a href="../../../nw/gfx/ParticleModel/Overview.html"><CODE>ParticleModel</CODE></a> and <a href="../../../nw/gfx/ParticleEmitter/Overview.html"><CODE>ParticleEmitter</CODE></a> objects both have <a href="../../../nw/anim/AnimFrameController/Overview.html"><CODE>nw::anim::AnimFrameController</CODE></a> objects. <br /> Call the <CODE>ParticleAnimFrameController</CODE> function to get these <CODE>AnimFrameController</CODE> objects.</p> 14 <p>Time can be advanced by making a step setting (<a href="../../../nw/anim/AnimFrameController/SetStepFrame.html"><CODE>SetStepFrame</CODE></a>) or updating the frame (<a href="../../../nw/anim/AnimFrameController/UpdateFrame.html"><CODE>UpdateFrame</CODE></a>). Advance to a particular frame by applying an offset from the previous frame to the animation. Depending on the animation type, values may differ when advancing one frame at a time.</p> 15 <p>In addition, the emitter emits for the amount of time that has advanced since an update was last called. A large volume of particles is therefore emitted if many frames are suddenly advanced at once.</p> 16 <p>This is not supported for reverse playback (where frame numbers are decreased).</p> 17 <p><a href="../../../nw/gfx/ParticleSceneUpdater/Overview.html">ParticleSceneUpdater</a>::<a href="../../../nw/gfx/ParticleSceneUpdater/SetStepFrame.html">SetStepFrame</a> has been prepared as a function for making multiple particle models emitter step settings all at once.</p> 18 <h2><a name="deleteall" id="deleteall"></a>Deleting Particles</h2> 19 <p>Use the following methods to delete generated particles.<br /> <CODE>nw::gfx::ParticleCollection::KillParticle</CODE>: Delete a specific particle.<br /> <CODE>nw::gfx::ParticleCollection::KillParticles</CODE>: Kill all particles.<br /> If the deleted particle specifies child particle emission, then those child particles are emitted at the time of deletion.</p> 20 21<pre> 22Example: 23nw::gfx::ParticleSet* particleSet; 24// Get the ParticleCollection. 25particleCollection = particleSet->GetParticleCollection(); 26// Delete a specific particle (in this case, the fifth). 27{ 28 // Get an index to the active particles. 29 u16* activeIndex = (u16*)particleCollection->GetStreamPtr( 30 nw::gfx::PARTICLEUSAGE_ACTIVEINDEX,nw::gfx::PARTICLE_BUFFER_FRONT); 31 // Get the index. 32 s32 index = activeIndex[5]; 33 // Delete the particle at the specified index. 34 particleCollection->KillParticles(index); 35} 36// Delete all generated particles. 37{ 38 particleCollection->KillParticles(); 39} 40</pre> 41<h2><a name="changeresource" id="changeresource"></a>Changing Resource Parameters</h2> 42 <p>To apply an effect to all nodes created from the same resource, you can change them by obtaining the resource and directly accessing associated parameters.</p> 43 <p>To apply an effect to only one node out of all nodes created from the same resource, copy the resource for that node and manipulate the copied resource.<br /> Resources can be copied automatically at time of node creation. If the <CODE>IsResourceCopyEnable</CODE> flag inside a resource is set before node creation, that resource is copied and stored at the time of node creation.<br /> If the copied resource is for a given created node only and that node is destroyed, the copied resource is also destroyed. Consequently, be sure to pay attention to how long the node has been in existence when using a copied resource outside a node. In addition, since the original resource is also accessed even if it has been copied, be sure to manage resources as usual for the original resource. <br /> Flags can be set ahead of time in the CreativeStudio UI. Set the flags for the following resources appropriately when making changes after loading resources with an application.<br /> Resources that include <CODE>IsResourceCopyEnabled</CODE></p> 44 <ul> 45 <li><a href="../../../nw/gfx/res/ResParticleEmitter/Overview.html"><CODE>ResParticleEmitter</CODE></a></li> 46 <li><a href="../../../nw/gfx/res/ResParticleForm/Overview.html"><CODE>ResParticleForm</CODE></a></li> 47 <li><a href="../../../nw/gfx/res/ResParticleInitializer/Overview.html"><CODE>ResParticleInitializer</CODE></a></li> 48 <li><a href="../../../nw/gfx/res/ResParticleUpdater/Overview.html"><CODE>ResParticleUpdater</CODE></a></li> 49 </ul> 50 <p>APIs for getting copied resources</p> 51 <ul> 52 <li><a href="../../../nw/gfx/ParticleEmitter/GetResParticleEmitterParameterCopy.html"><CODE>ParticleEmitter::GetResParticleEmitterParameterCopy</CODE></a></li> 53 <li><a href="../../../nw/gfx/ParticleEmitter/GetResParticleFormCopy.html"><CODE>ParticleEmitter::GetResParticleFormCopy</CODE></a></li> 54 </ul> 55 <p>Specify <CODE>true</CODE> as an argument to these API functions to get resources that are only valid when being copied for use by a node. If there are only shared resources, <CODE>IsValid</CODE> returns <CODE>false</CODE>. The default argument value for these functions is <CODE>false</CODE>. Specify <CODE>false</CODE> to prioritize nodes when getting resources, but if there are none, the function returns the shared resources.</p> 56<p>Use the <a href="../../../nw/gfx/ParticleSet/GetInitializers.html"><CODE>GetInitializers</CODE></a> and <a href="../../../nw/gfx/ParticleSet/GetUpdaters.html"><CODE>GetUpdaters</CODE></a> functions of the <a href="../../../nw/gfx/ParticleSet/Overview.html"><CODE>ParticleSet</CODE></a> class to get a list of management information for initializers or updaters. </p> 57<h3>Notes on Changing Emission Volume, Lifespan, Etc.</h3> 58<p>Pay attention to possible memory shortages with <a href="../../../nw/gfx/ParticleCollection/Overview.html"><CODE>ParticleCollection</CODE></a> when making changes to parameters (such as the emission volume, emission interval, and lifespan) that will change the number of particles that exist simultaneously. You cannot change memory capacity after nodes are created. Be sure to make any changes to values in <CODE>ResParticleCollection</CODE> before creating nodes.</p> 59<p>In addition to changing memory capacity at run-time, you can also allocate the maximum number of bytes anticipated ahead of time using CreativeStudio.</p> 60<p>If there is a memory shortage, some particles that should have been emitted won't be. Once a particle has failed to be emitted it will no longer be generated at all, even if a spot opens for it due to another particle disappearing. A particle generated after the spot opens will be emitted. This can make it look like particles are being emitted intermittently.</p> 61<h2><a name="changestream" id="changestream"></a>Changing Particle Information</h2> 62 <p>Since most particle information is passed directly to the GPU shader, it's hard to manage a program built to reflect the internal implementation. An application must have some knowledge of the internal structure to change this information. Here's the explanation for this.</p> 63 <p>Included in particle information are streams that can include different values for each particle and fixed-value parameters in a <a href="../../../nw/gfx/ParticleSet/Overview.html"><CODE>ParticleSet</CODE></a>.</p> 64 <p>Whether particle information is a parameter or a stream is determined upon optimization of the binary output from CreativeStudio. </p> 65 <h3><a name="optimizestream" id="optimizestream"></a>Conditions for Optimizing Streams to Parameters</h3> 66 <p>If all of the following conditions are satisfied, the <CODE>Initializer</CODE> is deleted and the stream is also output as parameters (fixed-value).</p> 67 <ul> 68 <li>The type must be one of: <CODE>Color</CODE>, <CODE>Alpha</CODE>, <CODE>TextureScale0</CODE>, <CODE>TextureRotate0</CODE>,<CODE>TextureTranslate0</CODE>, <CODE>Scale</CODE>, <CODE>ScaleExt</CODE>, <CODE>Rotate</CODE>, or <CODE>Life</CODE>.</li> 69 <li>There must be no <CODE>updater</CODE> for the target stream.</li> 70 <li>Target stream <CODE>initializer</CODE> results must be a constant. </li> 71 </ul> 72 <p>In addition to the distinction between parameters and streams, there is also a distinction between information that is used only in calculations by the CPU and information (VBO and vertex parameters) that is directly handled by the shader. This information is divided up at run-time depending on the attribute type. A double buffer is used for vertex attributes. A single buffer is used for other information.</p> 73 <h3>Handling Attribute Types at Runtime</h3> 74 <table border="1"> 75 <tr> 76 <th scope="col">Type</th> 77 <th scope="col">Role</th> 78 <th scope="col">Type</th> 79 <th scope="col">Parameter Availability</th> 80 <th scope="col">Is Vertex Attribute?</th> 81 </tr> 82 <tr> 83 <td scope="row">TRANSLATE</td> 84 <td>Location (local coordinate system)</td> 85 <td><CODE>VEC3</CODE></td> 86 <td>Stream only</td> 87 <td>Vertex attribute</td> 88 </tr> 89 <tr> 90 <td scope="row">SCALE</td> 91 <td>Scale (local coordinate system)</td> 92 <td><CODE>VEC3</CODE></td> 93 <td>Stream/Parameter</td> 94 <td>Vertex attribute</td> 95 </tr> 96 <tr> 97 <td scope="row">ROTATE</td> 98 <td>Rotation (local coordinate system)</td> 99 <td><CODE>VEC3</CODE></td> 100 <td>Stream/Parameter</td> 101 <td>Vertex attribute</td> 102 </tr> 103 <tr> 104 <td scope="row">COLOR</td> 105 <td>RGB Color</td> 106 <td><CODE>VEC3</CODE></td> 107 <td>Stream/Parameter</td> 108 <td>Vertex attribute</td> 109 </tr> 110 <tr> 111 <td scope="row">ALPHA</td> 112 <td>Alpha</td> 113 <td>f32</td> 114 <td>Stream/Parameter</td> 115 <td>Vertex attribute</td> 116 </tr> 117 <tr> 118 <td scope="row">TEXTURETRANSLATE0</td> 119 <td>Texture coordinate translation.</td> 120 <td><CODE>VEC2</CODE></td> 121 <td>Stream/Parameter</td> 122 <td>Vertex attribute</td> 123 </tr> 124 <tr> 125 <td scope="row">TEXTURESCALE0</td> 126 <td>Texture coordinate scale.</td> 127 <td><CODE>VEC2</CODE></td> 128 <td>Stream/Parameter</td> 129 <td>Vertex attribute</td> 130 </tr> 131 <tr> 132 <td scope="row">TEXTUREROTATE0</td> 133 <td>Texture coordinate rotation.</td> 134 <td>f32</td> 135 <td>Stream/Parameter</td> 136 <td>Vertex attribute</td> 137 </tr> 138 <tr> 139 <td scope="row">SCALE_EXT</td> 140 <td>Scale (extended)</td> 141 <td><CODE>VEC3</CODE></td> 142 <td>Stream/Parameter</td> 143 <td>Vertex attribute</td> 144 </tr> 145 <tr> 146 <td scope="row">BIRTH</td> 147 <td>Date created.</td> 148 <td><CODE>ParticleTime</CODE></td> 149 <td>Stream only</td> 150 <td>-</td> 151 </tr> 152 <tr> 153 <td scope="row">LIFE</td> 154 <td>Lifetime</td> 155 <td><CODE>ParticleTime</CODE></td> 156 <td>Stream/Parameter</td> 157 <td>-</td> 158 </tr> 159 <tr> 160 <td scope="row">VELOCITY</td> 161 <td>Speed</td> 162 <td><CODE>VEC3</CODE></td> 163 <td>Stream only</td> 164 <td>-</td> 165 </tr> 166 <tr> 167 <td scope="row">ACTIVEINDEX</td> 168 <td>Indirect reference index to the element in use.</td> 169 <td>u16</td> 170 <td>Stream only</td> 171 <td>Vertex attribute</td> 172 </tr> 173 <tr> 174 <td scope="row">FREEINDEX</td> 175 <td>Indirect reference index to a usable element.</td> 176 <td>u16</td> 177 <td>Stream only</td> 178 <td>-</td> 179 </tr> 180 <tr> 181 <td scope="row">NGE_TIMELIMIT</td> 182 <td>Negative number (for speedup purposes) indicates the time when the particle should disappear.</td> 183 <td><CODE>ParticleTime</CODE></td> 184 <td>Stream only</td> 185 <td>-</td> 186 </tr> 187 </table> 188 <p> </p> 189 <h3>Changing Values</h3> 190<p>There are four methods for changing values. The one to use depends on whether information is a stream or a parameter and whether it's a vertex attribute or other information.</p> 191<p>For a sample implementation, see <a href="../demo/ParticleChangeVtxDemo.html"><CODE>ParticleChangeVtxDemo</CODE></a>.</p> 192<h4>Changing Parameters</h4> 193<p>Overwrite parameters using <CODE>ParticleCollection::SetParameter</CODE>. For <CODE>LIFE</CODE>, you can also overwrite using <CODE>ParticleCollection::SetLifeParameter</CODE> (Recommended).</p> 194<p>For non-vertex parameters (<CODE>LIFE</CODE> only), you can only rewrite the content of memory pointed to by the parameter pointer obtained by <CODE>ParticleCollection::GetParameterPtr</CODE>. Because a single-buffer is used, both <CODE>PARTICLE_BUFFER_FRONT</CODE> and <CODE>PARTICLE_BUFFER_BACK</CODE> have the same content.</p> 195<p>For vertex attribute parameters, you can also rewrite any commands that have already been created, in addition to the content of memory pointed to by the parameter pointer obtained by <a href="../../../nw/gfx/ParticleCollection/GetParameterPtr.html"><CODE>ParticleCollection::GetParameterPtr</CODE></a>. Because commands are double-buffered, only one the buffers can be rewritten per call. Note that a command that does not specify a buffer does not re-write anything. There may be some difference between the contents of the address obtained using <a href="../../../nw/gfx/ParticleCollection/GetParameterPtr.html">ParticleCollection::GetParameterPtr<br /> and command double-buffer status. Although you can specify <CODE>PARTICLE_BUFFER_FRONT</CODE>/<CODE>PARTICLE_BUFFER_BACK</CODE>, do not change <CODE>PARTICLE_BUFFER_BACK</CODE> at any time a command may be issued to the GPU. Essentially, you should not write to <CODE>PARTICLE_BUFFER_BACK</CODE> at all because this timing is difficult to ascertain.<BR> 196</p> 197<p>Moreover, parameters are never changed by the library after commands are created.<BR> 198</p> 199<h4>Changing Streams</h4> 200 <p>Use <CODE><a href="../../../nw/gfx/ParticleCollection/Overview.html">ParticleCollection</a>::<a href="../../../nw/gfx/ParticleCollection/GetStreamPtr.html">GetStreamPtr</a></CODE> to get streams. If the function returns <CODE>NULL</CODE>, either the arguments are wrong or the specified class is being used as a parameter.</p> 201 <p>In general, get the stream from <CODE>PARTICLE_BUFFER_FRONT</CODE>. </p> 202 <p>The obtained stream is an array of types determined based on the class. Use the <CODE><a href="../../../nw/gfx/ParticleCollection/Overview.html">ParticleCollection</a>::<a href="../../../nw/gfx/ParticleCollection/GetStreamPtr.html">GetStreamPtr</a></CODE> function to get the maximum number of entries that can be stored in the array. This stream is not necessarily used padded from the start. You must use an index that can be obtained by the <CODE>PARTICLEUSAGE_ACTIVEINDEX</CODE> class.</p> 203 <p>See <a href="../demo/ParticleUpdaterDemo.html"><CODE>ParticleUpdaterDemo</CODE></a> for a sample implementation of making changes using <CODE>UserUpdater</CODE>.</p> 204<h3>Getting <CODE>ACTIVEINDEX</CODE></h3> 205 <p>This section describes how to get <CODE>ACTIVEINDEX</CODE>, which is required to access streams.</p> 206 <p><CODE>ACTIVEINDEX</CODE> is used as the vertex index of <CODE>DrawElements</CODE> as a VBO. Applications cannot rewrite this value because it affects various internal elements.</p> 207 <p>Although <CODE>ACTIVEINDEX</CODE> is usually stored starting from the earliest in the order created, if the rendering order is reversed (<CODE>ResParticleShapeBuilder::IsAscendingOrder</CODE>), it is stored starting from the oldest. Use <CODE><a href="../../../nw/gfx/ParticleCollection/Overview.html">ParticleCollection</a>::<a href="../../../nw/gfx/ParticleCollection/GetCount.html">GetCount()</a></CODE> to get the number of valid instances.</p> 208<p>Basically, get streams from <CODE>PARTICLE_BUFFER_FRONT</CODE>, but get them from <CODE>PARTICLE_BUFFER_BACK</CODE> when getting <CODE>PARTICLEUSAGE_ACTIVEINDEX</CODE> inside <CODE>UserUpdater</CODE>. Even then, be sure to get all information other than <CODE>ACTIVEINDEX</CODE> from <CODE>FRONT</CODE>.</p> 209 <p>This requirement is due to the following process flow.</p> 210 <ol> 211 <li>Create particles (<CODE>AddParticles</CODE>/<CODE>InitializeParticles</CODE>). </li> 212 <ul> 213 <li>Create new particles in the available region of <CODE>FRONT</CODE>.</li> 214 </ul> 215 <li>Update (<CODE>UpdateParticles</CODE>). 216 </li> 217 </ol> 218 <ol> 219 <ol> 220 <li>Swap <CODE>FRONT</CODE> and <CODE>BACK</CODE> by swapping buffers. (This is not done when enableSwapBuffer is false.)</li> 221 <li>Copy the VBO stream other than <CODE>ACTIVEINDEX</CODE> from <CODE>BACK</CODE> to <CODE>FRONT</CODE>. (This is not done when enableSwapBuffer is false.)</li> 222 <li>Update (<CODE>UserUpdater</CODE> is called here).</li> 223 <li>When deleting particles that have finished their lifespans, delete unnecessary particles from <CODE>BACK</CODE> and arrange in <CODE>FRONT</CODE>. (Only FRONT is serialized if enable SwapBuffer is false.)</li> 224 </ol> 225 </ol> 226 <p>You must get the ACTIVEINDEX used by UserUpdater from the BACK because the deletion process overlaps stream copying. (Get from RONT if enableSwapBuffer is false)<BR>Do not overwrite BACK because rendering may be under way.</p> 227 <h2>Particle Memory Usage</h2> 228 <p>This section describes the memory used per particle as of NintendoWare 1.0.1.</p> 229 <p>Values are handled as floating point numbers because particles are drawn by passing memory that stores particle information directly to the GPU. (This is done because quantizing multiple attributes increases the processing load on the GPU.)</p> 230 <table border="1"> 231 <tr> 232 <th scope="col">Type</th> 233 <th scope="col">Role</th> 234 <th scope="col">Size</th> 235 <th scope="col">Omissibility</th> 236 <th scope="col">Number of Buffers</th> 237 </tr> 238 <tr> 239 <td scope="row">TRANSLATE</td> 240 <td>Location (local coordinate system)</td> 241 <td>12 bytes</td> 242 <td>×</td> 243 <td>2</td> 244 </tr> 245 <tr> 246 <td scope="row">SCALE</td> 247 <td>Scale (local coordinate system)</td> 248 <td>12 bytes</td> 249 <td>○</td> 250 <td>2</td> 251 </tr> 252 <tr> 253 <td scope="row">ROTATE</td> 254 <td>Rotation (local coordinate system)</td> 255 <td>12 bytes</td> 256 <td>○</td> 257 <td>2</td> 258 </tr> 259 <tr> 260 <td scope="row">COLOR</td> 261 <td>RGB Color</td> 262 <td>12 bytes</td> 263 <td>○</td> 264 <td>2</td> 265 </tr> 266 <tr> 267 <td scope="row">ALPHA</td> 268 <td>Alpha</td> 269 <td>4 bytes</td> 270 <td>○</td> 271 <td>2</td> 272 </tr> 273 <tr> 274 <td scope="row">TEXTURETRANSLATE0</td> 275 <td>Texture coordinate translation.</td> 276 <td>8 bytes</td> 277 <td>○</td> 278 <td>2</td> 279 </tr> 280 <tr> 281 <td scope="row">TEXTURESCALE0</td> 282 <td>Texture coordinate scale.</td> 283 <td>8 bytes</td> 284 <td>○</td> 285 <td>2</td> 286 </tr> 287 <tr> 288 <td scope="row">TEXTUREROTATE0</td> 289 <td>Texture coordinate rotation.</td> 290 <td>12 bytes</td> 291 <td>○</td> 292 <td>2</td> 293 </tr> 294 <tr> 295 <td scope="row">SCALE_EXT</td> 296 <td>Scale (extended)</td> 297 <td>12 bytes</td> 298 <td>○</td> 299 <td>2</td> 300 </tr> 301 <tr> 302 <td scope="row">BIRTH</td> 303 <td>Date created.</td> 304 <td>4 bytes</td> 305 <td>×</td> 306 <td>1</td> 307 </tr> 308 <tr> 309 <td scope="row">LIFE</td> 310 <td>Lifetime</td> 311 <td>4 bytes</td> 312 <td>○</td> 313 <td>1</td> 314 </tr> 315 <tr> 316 <td scope="row">VELOCITY</td> 317 <td>Speed</td> 318 <td>12 bytes</td> 319 <td>×</td> 320 <td>1</td> 321 </tr> 322 <tr> 323 <td scope="row">ACTIVEINDEX</td> 324 <td>Indirect reference index to the element in use.</td> 325 <td>2 bytes</td> 326 <td>×</td> 327 <td>2</td> 328 </tr> 329 <tr> 330 <td scope="row">FREEINDEX</td> 331 <td>Indirect reference index to a usable element.</td> 332 <td>2 bytes</td> 333 <td>×</td> 334 <td>1</td> 335 </tr> 336 <tr> 337 <td scope="row">NGE_TIMELIMIT</td> 338 <td>Negative number (for speedup purposes) indicates the time when the particle should disappear.</td> 339 <td>4 bytes</td> 340 <td>×</td> 341 <td>1</td> 342 </tr> 343 </table> 344 <p>50 bytes if all omissible items can be omitted. 210 bytes if they could not all be omitted.</p> 345 <p>The number of bytes specified for "work memory at runtime" under CreativeStudio is allocated per <CODE>ParticleSet</CODE>.</p> 346 <p>Memory used by main classes (main base classes are given in parentheses).</p> 347 <table border="1"> 348 <tr> 349 <th scope="col"></th> 350 <th scope="col"><CODE>sizeof</CODE> (values in parentheses are for version 1.1)</th> 351 </tr> 352 <tr> 353 <td scope="row"><CODE>ParticleModel</CODE></td> 354 <td>636 (564)</td> 355 </tr> 356 <tr> 357 <td scope="row"><CODE>ParticleSet</CODE></td> 358 <td>144 (136)</td> 359 </tr> 360 <tr> 361 <td scope="row"><CODE>ParticleCollection</CODE></td> 362 <td>444 (436)</td> 363 </tr> 364 <tr> 365 <td scope="row"><CODE>ParticleShape</CODE></td> 366 <td>528 (516)</td> 367 </tr> 368 <tr> 369 <td scope="row"><CODE>ParticleEmitter</CODE></td> 370 <td>400 (388)</td> 371 </tr> 372 <tr> 373 <td scope="row">(<CODE>SceneObject</CODE>)</td> 374 <td>12 (12)</td> 375 </tr> 376 <tr> 377 <td scope="row">(<CODE>SceneNode</CODE>)</td> 378 <td>80 (72)</td> 379 </tr> 380 <tr> 381 <td scope="row">(<CODE>TransformNode</CODE>)</td> 382 <td>336 (324)</td> 383 </tr> 384 <tr> 385 <td scope="row">(<CODE>Model</CODE>)</td> 386 <td>556 (508)</td> 387 </tr> 388 </table> 389 <p>In addition, memory for pointers such as to materials, the command cache, and children is also allocated.</p> 390 <p>1296 bytes per <CODE>ParticleShape</CODE> is allocated for the command cache to be used for particles.</p> 391 <p></p> 392<h2><a name="layer" id="layer"></a>Processing When Using Hierarchical Structures</h2> 393 <p>When a particle is generated, its position is determined by the emitter. However, the coordinates are converted so that its position does not shift when passed to the particle model. In other words, regardless of how the hierarchy is arranged, emitted particles appear in the emitter position at this point.</p> 394 <p>After emission, particles are drawn using the model coordinate system.</p> 395 <p>As an exceptional option for hierarchical structures, particle sets include an option for forcing the use of the world coordinate system. If this option is specified, the world coordinate system is used for the particle set regardless of the hierarchical structure. In other words, status is the same as if there was no hierarchical structure.</p> 396 <h2><a name="userupdater" id="userupdater"></a>User Updater</h2> 397 <p>An updater is a processing unit used to animate particles for a <a href="../../../nw/gfx/ParticleSet/Overview.html"><CODE>ParticleSet</CODE></a>. The library includes a means of adding user-defined updaters. Use this to provide an application with features not provided by the library.<br /> <a ref="../demo/ParticleUpdaterDemo.html"><CODE>ParticleUpdaterDemo</CODE></a> is a sample demo of a user-defined updater.</p> 398 <div> 399 <h3>Preparing Resources</h3> 400 </div> 401 <p>The library supports the <a href="../../../nw/gfx/res/ResParticleUserUpdater/Overview.html"><CODE>ResParticleUserUpdater</CODE></a> resource for user updaters. A user process is used as the callback when a <a href="../../../nw/gfx/ParticleSet/Overview.html"><CODE>ParticleSet</CODE></a> processes this resource.</p> 402 <p><a href="../../../nw/gfx/res/ResParticleUserUpdater/Overview.html"><CODE>ResParticleUserUpdater</CODE></a> does not currently support intermediate files created using CreativeStudio. To add a user-defined updater, add the following to the <CODE>ParticleUpdaters</CODE> list in the intermediate file: <br /> <CODE><ParticleUserUpdaterXml IsUpdaterEnabled="true" UserParameter="0"></CODE><br /> <CODE><ParticleAnimationData /></CODE><br /> <CODE><TargetStreams /></CODE><br /> <CODE></ParticleUserUpdaterXml></CODE><br /> Although CreativeStudio does not support the addition and deletion of user updaters, it does support intermediate file reading and writing, binary output, and content viewing. <CODE>ParticleUserUpdater</CODE> must be set for each <a href="../../../nw/gfx/ParticleSet/Overview.html"><CODE>ParticleSet</CODE></a>. The <CODE>ProcessPriority</CODE> value determines the updater process priority. Specify <CODE>0</CODE> to have the user updater run before all other updaters. Conversely, specify <CODE>1000</CODE> to run the user updater last. 403 </p> 404 <div> 405 <h3>Using User-defined Updaters with Applications</h3> 406 </div> 407 <p>Search for updaters supported by <a href="../../../nw/gfx/res/ResParticleUserUpdater/Overview.html"><CODE>ResParticleUserUpdater</CODE></a> from among updaters for the created <a href="../../../nw/gfx/ParticleSet/Overview.html"><CODE>ParticleSet</CODE></a>, and set a user-defined function pointer for <CODE>updater.work</CODE>.</p> 408 <p>For details, see how the <CODE>SetUserUpdater</CODE> function is used in <a href="../demo/ParticleUpdaterDemo.html"><CODE>ParticleUpdaterDemo</CODE></a>.</p> 409 <h2>Emission Volume from an Emitter</h2> 410 <p>This section gives an overview of parameters related to emitter emission and what they mean.</p> 411 <h3>Emission Timing</h3> 412 <p>First, the basic concept is summed up as follows:</p> 413 <ul> 414 <li>Emission is calculated for integral frames. </li> 415 <li>Particles are actually emitted at time of evaluation and treated as if generated at that time.</li> 416 </ul> 417<p>This is the fundamental concept.</p> 418<p>This timing provides an opportunity at the integral frame level to control emission based on whether the actual time has exceeded this timing.<BR> This is evaluated during actual calculations. Particles emitted between the last evaluation and the next are all treated as if generated at time of evaluation. For example, consider a particle set to be emitted each frame at a playback rate of 2.0. In this case, double emission will take place once every two frames. There is no need to consider the time difference of unevaluated frames.</p> 419<p>There is no opportunity for emission with an emission period of <CODE>0</CODE>. With an emission period of <CODE>1</CODE>, there is only one chance for generation (the first frame).</p> 420<p>The emitter stores the timing for the next emission and updates information during emission processing.<BR> Timing for the next emission is given by the following formula.</p> 421<p><CODE>(int)(emission_interval * (1.0f + emission_interval_random * random_number_between(-1.0f, +1.0f))</CODE></p> 422<p>This is calculated to find the time of next emission. However, <CODE>1</CODE> is used if the calculated value is less than <CODE>1</CODE>. This means there is no emission until the next frame even if a random number is included.</p> 423<h3>Emission Volume</h3> 424 <p>The following equation is calculated at each time of emission.</p> 425 <p><CODE>emission_volume * (1.0f + emission_volume_random * random_number_between(-1.0f, +1.0f))</CODE></p> 426 <p> The integer part of the accumulated value is the number of particles to be emitted at time of evaluation. </p> 427 <p>As an exception, an emission volume less than <CODE>1</CODE> is handled as <CODE>1</CODE> at time of first evaluation if the emitter's emission volume exceeds <CODE>0</CODE>. This is due to the fact that, even though it may take a long time to accumulate a value of <CODE>1</CODE> when given emission volume values less than <CODE>1</CODE>, there are many cases where you want to emit exactly one particle in the first frame.<BR> If this operation is a problem, either make it so that the emitter is not evaluated until actual time of emission or control things so the emission volume is <CODE>0</CODE>.</p> 428 <h2>Generating Particles in the Middle of a Scene</h2> 429 <p>There could be cases where you want to emit particles partway through a scene. For instance, when creating rain particles, you might want to generate particles that skip the beginning of the rain. Leave just the frames you want to skip as empty of particles to create this effect, thereby skipping the beginning of the rain and begin generating from the midst of a rain shower.</p> 430 <h3>Leave Just Specified Frames Empty</h3> 431 432 <p>Work with both the <CODE>ParticleModel</CODE> and the <CODE>ParticleEmitter</CODE> objects to leave certain frames empty. The example below leaves 100 frames empty of particles.</p> 433<pre> 434for (u32 k = 0; k < 100; ++k) 435{ 436 for (u32 i = 0; i > modelNodeArray.size(); ++i) 437 { 438 modelNodeArray[i]->ParticleAnimFrameController().SetStepFrame(1.0f); 439 modelNodeArray[i]->UpdateParticleFrame(); 440 } 441 for (u32 i = 0; i > emitterNodeArray.size(); ++i) 442 { 443 emitterNodeArray[i]->ParticleAnimFrameController().SetStepFrame(1.0f); 444 emitterNodeArray[i]->UpdateParticleFrame(); 445 emitterNodeArray[i]->Emission(s_ParticleContext); 446 } 447 for (u32 i = 0; i > modelNodeArray.size(); ++i) 448 { 449 for (u32 j = 0; j > modelNodeArray[i]->GetParticleSetsCount(); ++j) 450 { 451 modelNodeArray[i]->GetParticleSets(j)->UpdateParticles(s_ParticleContext); 452 } 453 } 454} 455</pre> 456 <h3>Precautions for No-Particle Frames</h3> 457 <p>Keep the following points in mind when leaving frames empty of particles.</p> 458 <ul> 459 <li>If using a double command buffer, refer to <a href="Attention.html#doublebuffer">Precautions when Calling ParticleSet::UpdateParticle Multiple Times</a>. The GPU may perform unexpected operations if updates are made in an inapproprie manner. </li> 460 </ul> 461 <h2>Forming Parent-Child Relationships Between Particles and Models</h2> 462 <p>Parent-child relationships between instances of ParticleModel and ParticleEmitter can be split into two types. </p> 463 <ul> 464 <li>Configuration where the ParticleEmitter is a child of the ParticleModel<BR></li> 465 <li>Configuration where the ParticleEmitter is the sibling of the ParticleModel<BR></li> 466 </ul> 467 <p>A bone matrix must be configured appropriately for the ParticleModel or ParticleEmitter depending ont the situation.</p> 468 <h3>3D Link (Viewer) Specifications</h3> 469 <p>The Viewer included in the NW4C package includes a feature called "3DLink." 3DLink is used to form parent-child relationships between models and particles and display them. Even with 3DLink, a bone matrix is set for the ParticleModel and ParticleEmitter based on the two relationship configurations mentioned above. Although tools can be used to configure a relationship where there are two particle emitters and each, respectively, is the child and sibling of a ParticleModel, 3DLink cannot link objects correctly under this configuration.</p> 470 <h3>Configuration where the ParticleEmitter is a child of the ParticleModel</h3> 471 <p> When using 3DLink, a bone matrix is set only for the ParticleModel.</p> 472 <h3>Configuration where the ParticleEmitter is the sibling of the ParticleModel</h3> 473 <p> When using 3DLink, a bone matrix is set for both the ParticleModel and the ParticleEmitter.</p> 474 </div> 475 <hr><p>CONFIDENTIAL</p></body> 476</html> 477