1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     demo_Particle.h
4 
5   Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain proprietary
8   information of Nintendo and/or its licensed developers and are protected by
9   national and international copyright laws. They may not be disclosed to third
10   parties or copied or duplicated in any form, in whole or in part, without the
11   prior written consent of Nintendo.
12 
13   The content herein is highly confidential and should be handled accordingly.
14 
15   $Revision: 31829 $
16  *---------------------------------------------------------------------------*/
17 
18 #ifndef NW_DEMO_PARTICLE_H_
19 #define NW_DEMO_PARTICLE_H_
20 
21 #include <nw/gfx.h>
22 #include <nw/ut.h>
23 #include <nw/demo/demo_GraphicsSystem.h>
24 
25 namespace nw
26 {
27 
28 namespace demo
29 {
30 
31 //! @brief パーティクル管理用のクラスです。
32 //! Transformノードに管理用の情報を付加しています。
33 class ParticleHandle : public gfx::TransformNode
34 {
35 private:
36     NW_DISALLOW_COPY_AND_ASSIGN(ParticleHandle);
37 
38 public:
39     NW_UT_RUNTIME_TYPEINFO;
40 
41     //----------------------------------------
42     //! @name 作成/破棄
43     //@{
44 
45     //! @brief シーンノードを動的に構築するためのクラスです。
46     //!
47     //! IsFixedSizeMemory の初期値は true です。false に変更すると、各種最大数の設定は無視されます。
48     class DynamicBuilder
49     {
50     public:
51         //! コンストラクタです。
DynamicBuilder()52         DynamicBuilder() {}
53         //! デストラクタです。
~DynamicBuilder()54         ~DynamicBuilder() {}
55 
56         //! @brief 生成時以外にもメモリを確保するかどうかのフラグを設定します。
57         //!
58         //!        true を指定すると、生成時のみ固定サイズのメモリ確保を行います。
59         //!
60         //!        false を指定すると、生成時以外にも必要に応じて動的にメモリ確保が行われます。
IsFixedSizeMemory(bool isFixedSizeMemory)61         DynamicBuilder& IsFixedSizeMemory(bool isFixedSizeMemory)
62         {
63             m_Description.isFixedSizeMemory = isFixedSizeMemory;
64             return *this;
65         }
66 
67         //! 子の最大数を設定します。
MaxChildren(int maxChildren)68         DynamicBuilder& MaxChildren(int maxChildren)
69         {
70             m_Description.maxChildren = maxChildren;
71             return *this;
72         }
73 
74         //! 管理できるコールバックの最大数を設定します。
MaxCallbacks(int maxCallbacks)75         DynamicBuilder& MaxCallbacks(int maxCallbacks)
76         {
77             m_Description.maxCallbacks = maxCallbacks;
78             return *this;
79         }
80 
81         //! @brief        シーンノードを生成します。
82         //!
83         //! @param[in]    allocator アロケータです。
84         //!
85         //! @return       生成したシーンノードを返します。
86         //!
87         ParticleHandle* Create(os::IAllocator* allocator);
88 
89     private:
90         gfx::TransformNode::Description m_Description;
91     };
92 
93     //@}
94 
95     //----------------------------------------
96     //! @name パーティクル操作
97     //@{
98 
99     //! @brief IDを取得します。
100     //!
101     //! @return IDです。
GetID()102     int GetID() const
103     {
104         return m_Id;
105     }
106 
107     //! @brief IDを設定します。
108     //!
109     //! @param[in] id 設定するIDです。
SetID(int id)110     void SetID(int id)
111     {
112         m_Id = id;
113     }
114 
115     //! @brief 位置を設定します。
116     //!
117     //! @param[in] x 設定する位置Xです。
118     //! @param[in] y 設定する位置Yです。
119     //! @param[in] z 設定する位置Zです。
SetTranslate(f32 x,f32 y,f32 z)120     void SetTranslate(f32 x, f32 y, f32 z)
121     {
122         this->Transform().SetTranslate(x, y, z);
123     }
124 
125     //! @brief 位置を設定します。
126     //!
127     //! @param[in] translate 設定する位置です。
SetTranslate(const nw::math::VEC3 & translate)128     void SetTranslate(const nw::math::VEC3& translate)
129     {
130         this->Transform().SetTranslate(translate);
131     }
132 
133     //! @brief 位置を取得します。
GetTranslate(nw::math::VEC3 * translate)134     void GetTranslate(nw::math::VEC3* translate) const
135     {
136         this->Transform().GetTranslate(translate);
137     }
138 
139     //! @brief 回転を設定します。
140     //!
141     //! @param[in] x 設定する回転値X(ラジアン)です。
142     //! @param[in] y 設定する回転値Y(ラジアン)です。
143     //! @param[in] z 設定する回転値Z(ラジアン)です。
SetRotate(f32 radX,f32 radY,f32 radZ)144     void SetRotate(f32 radX, f32 radY, f32 radZ)
145     {
146         this->Transform().SetRotateXYZ(radX, radY, radZ );
147     }
148 
149     //! @brief 拡縮を設定します。
150     //!
151     //! @param[in] x 設定する拡縮値Xです。
152     //! @param[in] y 設定する拡縮値Yです。
153     //! @param[in] z 設定する拡縮値Zです。
SetScale(f32 x,f32 y,f32 z)154     void SetScale(f32 x, f32 y, f32 z)
155     {
156         this->Transform().SetScale(x, y, z);
157     }
158 
159     //! @brief ステップフレームを設定します。
160     //!
161     //! @param[in] 設定するステップフレームです。
SetStepFrame(f32 stepFrame)162     void SetStepFrame(f32 stepFrame)
163     {
164         u32 emitterNum = this->GetParticleEmitterSize();
165         for (u32 i = 0; i < emitterNum; ++i)
166         {
167             nw::gfx::ParticleEmitter* emitter = this->GetParticleEmitter(i);
168             emitter->ParticleAnimFrameController().SetStepFrame(stepFrame);
169         }
170 
171         u32 modelNum = this->GetParticleModelSize();
172 
173         for (u32 i = 0; i < modelNum; ++i)
174         {
175             nw::gfx::ParticleModel* model = this->GetParticleModel(i);
176             model->ParticleAnimFrameController().SetStepFrame(stepFrame);
177         }
178     }
179 
180     //! @brief フレームを設定します。
181     //!
182     //! @param[in] 設定するフレームです。
SetFrame(f32 frame)183     void SetFrame(f32 frame)
184     {
185         u32 emitterNum = this->GetParticleEmitterSize();
186         for (u32 i = 0; i < emitterNum; ++i)
187         {
188             nw::gfx::ParticleEmitter* emitter = this->GetParticleEmitter(i);
189             emitter->ParticleAnimFrameController().SetFrame(frame);
190         }
191 
192         u32 modelNum = this->GetParticleModelSize();
193 
194         for (u32 i = 0; i < modelNum; ++i)
195         {
196             nw::gfx::ParticleModel* model = this->GetParticleModel(i);
197             model->ParticleAnimFrameController().SetFrame(frame);
198         }
199     }
200 
201     //! @brief 指定数だけフレームを回します。
202     //!
203     //! @param[in] times フレームを回す回数です。
204     //! @param[in] addFrame 進めるフレーム数です。
205     //! @param[in] particleContext パーティクルコンテキストです。
AddTimes(uint times,gfx::ParticleContext * particleContext)206     void AddTimes(uint times, gfx::ParticleContext* particleContext)
207     {
208         for (u32 k = 0; k < times; ++k)
209         {
210             for (u32 i = 0; i < this->GetParticleModelSize(); ++i)
211             {
212                 this->GetParticleModel(i)->UpdateParticleFrame();
213             }
214 
215             for (u32 i = 0; i < this->GetParticleEmitterSize(); ++i)
216             {
217                 this->GetParticleEmitter(i)->UpdateParticleFrame();
218                 this->GetParticleEmitter(i)->Emission(particleContext);
219             }
220 
221             for (u32 i = 0; i < this->GetParticleModelSize(); ++i)
222             {
223                 for (u32 j = 0; j < this->GetParticleModel(i)->GetParticleSetsCount(); ++j)
224                 {
225                     this->GetParticleModel(i)->GetParticleSets(j)->UpdateParticles(particleContext);
226                 }
227             }
228         }
229     }
230 
231     //! @brief リセットします。
232     //!        GPU処理中はコールできません。
233     //!
234     //! @param[in] リセットを行い、初期状態に戻します。
Reset()235     void Reset()
236     {
237         u32 emitterNum = this->GetParticleEmitterSize();
238         for (u32 i = 0; i < emitterNum; ++i)
239         {
240             nw::gfx::ParticleEmitter* emitter = this->GetParticleEmitter(i);
241             emitter->Reset();
242         }
243 
244         u32 modelNum = this->GetParticleModelSize();
245 
246         for (u32 i = 0; i < modelNum; ++i)
247         {
248             nw::gfx::ParticleModel* model = this->GetParticleModel(i);
249             model->ForeachParticleSet(nw::gfx::ParticleSetsClear());
250             model->ParticleAnimFrameController().SetFrame(0.f);
251             // 処理順序の検査のためのヒント情報をリセットします
252             model->ResetDebugHint();
253         }
254     }
255 
256     //! @brief 放出量をセットします。
257     //!
258     //! @param[in] ratio 設定する放出量です。
SetEmissionRatio(f32 ratio)259     void SetEmissionRatio(f32 ratio)
260     {
261         u32 emitterNum = this->GetParticleEmitterSize();
262         for (u32 i = 0; i < emitterNum; ++i)
263         {
264             nw::gfx::ParticleEmitter* emitter = this->GetParticleEmitter(i);
265             nw::gfx::ResParticleEmitterParameter resParameter = emitter->GetResParticleEmitterParameterCopy();
266             NW_ASSERT(resParameter.IsValid());
267 
268             resParameter.SetEmissionRatio(ratio);
269         }
270     }
271 
272     //! @brief 現在のパーティクルの個数を取得します。
273     //!
274     //! @return 現在のパーティクルの個数です。
GetParticleSize()275     u32 GetParticleSize()
276     {
277         u32 particleNum = 0;
278 
279         u32 modelNum = this->GetParticleModelSize();
280 
281         for (u32 i = 0; i < modelNum; ++i)
282         {
283             nw::gfx::ParticleModel* model = this->GetParticleModel(i);
284             for (u32 j = 0; j < model->GetParticleSetsCount(); ++j )
285             {
286                 nw::gfx::ParticleSet* particleSet = model->GetParticleSets(j);
287                 particleNum += particleSet->GetParticleCollection()->GetCount();
288             }
289         }
290 
291         return particleNum;
292     }
293 
294     //! @brief 終了状態かどうかを取得します。
295     //!
296     //! @return 終了状態であれば、trueが返ります。
IsDone()297     bool IsDone()
298     {
299         u32 modelNum = this->GetParticleModelSize();
300         for (u32 i = 0; i < modelNum; ++i)
301         {
302             nw::gfx::ParticleModel* model = this->GetParticleModel(i);
303             if (model->HasParticle())
304             {
305                 return false;
306             }
307         }
308 
309         u32 emitterNum = this->GetParticleEmitterSize();
310         for (u32 i = 0; i < emitterNum; ++i)
311         {
312             nw::gfx::ParticleEmitter* emitter = this->GetParticleEmitter(i);
313             if (emitter->IsAlive())
314             {
315                 return false;
316             }
317         }
318 
319         return true;
320     }
321 
322     //! @brief 再生中のエフェクトがループエフェクト(無限ループ)かどうかを取得します。
323     //!
324     //! @return ループエフェクト(無限ループ)であれば、trueが返ります。
IsInfinity()325     bool IsInfinity()
326     {
327         bool isInfinity = false;
328 
329         u32 emitterNum = this->GetParticleEmitterSize();
330         for (u32 i = 0; i < emitterNum; ++i)
331         {
332             nw::gfx::ParticleEmitter* emitter = this->GetParticleEmitter(i);
333             const nw::gfx::ResParticleEmitterParameter resource = emitter->GetResParticleEmitterParameterCopy(false);
334             NW_ASSERT(resource.IsValid());
335 
336             if (resource.GetEmissionSpanInfinity())
337             {
338                 isInfinity = true;
339             }
340         }
341 
342         return isInfinity;
343     }
344 
345     //! @brief 粒子のスケールのオフセット値設定します。
346     //!
347     //! @param[in] particleOffset 設定する粒子のスケールのオフセットです。
SetParticleScaleOffset(f32 particleOffset)348     void SetParticleScaleOffset( f32 particleOffset )
349     {
350         u32 modelNum = this->GetParticleModelSize();
351 
352         for (u32 i = 0; i < modelNum; ++i)
353         {
354             nw::gfx::ParticleModel* model = this->GetParticleModel(i);
355 
356             for (int j = 0; j < (int)model->GetParticleSetsCount(); ++j)
357             {
358                 nw::gfx::ParticleSet* particleSet = model->GetParticleSets(j);
359                 particleSet->SetScaleOffset(nw::math::VEC3(particleOffset, particleOffset, particleOffset));
360             }
361         }
362     }
363 
364     //! @brief 粒子のスケールのオフセット値設定します。
365     //!
366     //! @param[in] particleOffsetX 設定する粒子のスケールのオフセットXです。
367     //! @param[in] particleOffsetY 設定する粒子のスケールのオフセットYです。
368     //! @param[in] particleOffsetZ 設定する粒子のスケールのオフセットZです。
369     void SetParticleScaleOffset( f32 particleOffsetX, f32 particleOffsetY, f32 particleOffsetZ = 1.f )
370     {
371         u32 modelNum = this->GetParticleModelSize();
372 
373         for (u32 i = 0; i < modelNum; ++i)
374         {
375             nw::gfx::ParticleModel* model = this->GetParticleModel(i);
376 
377             for (int j = 0; j < (int)model->GetParticleSetsCount(); ++j)
378             {
379                 nw::gfx::ParticleSet* particleSet = model->GetParticleSets(j);
380                 particleSet->SetScaleOffset(nw::math::VEC3(particleOffsetX, particleOffsetY, particleOffsetZ));
381             }
382         }
383     }
384 
385     //! @brief 放出処理を行います。
386     //!
387     //! @param[in] particleContext パーティクルコンテキストです。
Emission(gfx::ParticleContext * particleContext)388     void Emission(gfx::ParticleContext* particleContext)
389     {
390         for (u32 i = 0; i < this->GetParticleEmitterSize(); ++i)
391         {
392             nw::gfx::ParticleEmitter* emitter = this->GetParticleEmitter(i);
393             emitter->UpdateParticleFrame();
394             emitter->Emission(particleContext);
395             emitter->Reset();
396         }
397     }
398 
399     //@}
400 
401     //----------------------------------------
402     //! @name インスタンス管理
403     //@{
404 
405     //! @brief パーティクルモデルのインスタンスを登録します。
406     //!
407     //! @param[in] 登録するパーティクルモデルのインスタンスです。
RegisterParticleModel(nw::gfx::ParticleModel * model)408     void RegisterParticleModel( nw::gfx::ParticleModel* model )
409     {
410         m_ModelInstances.PushBack(model);
411     }
412 
413     //! @brief パーティクルエミッタのインスタンスを登録します。
414     //!
415     //! @param[in] 登録するパーティクルエミッタのインスタンスです。
RegisterParticleEmitter(nw::gfx::ParticleEmitter * emitter)416     void RegisterParticleEmitter( nw::gfx::ParticleEmitter* emitter )
417     {
418         m_EmitterInstances.PushBack(emitter);
419     }
420 
421     //! @brief 保持しているパーティクルモデル数を取得します。
422     //!
423     //! @return 保持しているパーティクルモデル数です。
GetParticleModelSize()424     u32 GetParticleModelSize() const
425     {
426         return m_ModelInstances.size();
427     }
428 
429     //! @brief 保持しているパーティクルエミッタ数を取得します。
430     //!
431     //! @return 保持しているパーティクルエミッタ数です。
GetParticleEmitterSize()432     u32 GetParticleEmitterSize() const
433     {
434         return m_EmitterInstances.size();
435     }
436 
437     //! @brief 保持しているパーティクルモデルインスタンスを取得します。
438     //!
439     //! @return パーティクルモデルのインスタンスです。
GetParticleModel(u32 index)440     nw::gfx::ParticleModel* GetParticleModel(u32 index)
441     {
442         if (this->GetParticleModelSize() > index)
443         {
444             return m_ModelInstances[index];
445         }
446         return NULL;
447     }
448 
449     //! @brief 保持しているパーティクルエミッタインスタンスを取得します。
450     //!
451     //! @return パーティクルエミッタのインスタンスです。
GetParticleEmitter(u32 index)452     nw::gfx::ParticleEmitter* GetParticleEmitter(u32 index)
453     {
454         if (this->GetParticleEmitterSize() > index)
455         {
456             return m_EmitterInstances[index];
457         }
458         return NULL;
459     }
460 
461     //! @brief パーティクルセットを取得します。
462     //!
463     //! @param[in] name パーティクルセットの名前です。
464     //! @return パーティクルセットを返します。
GetParticleSet(const char * name)465     nw::gfx::ParticleSet* GetParticleSet(const char* name)
466     {
467         u32 modelNum = this->GetParticleModelSize();
468 
469         for (u32 i = 0; i < modelNum; ++i)
470         {
471             nw::gfx::ParticleModel* model = this->GetParticleModel(i);
472 
473             for (int j = 0; j < (int)model->GetParticleSetsCount(); ++j)
474             {
475                 nw::gfx::ParticleSet* particleSet = model->GetParticleSets(j);
476                 const char* particleSetName = particleSet->GetResParticleSet().GetName();
477 
478                 if (std::strcmp(particleSetName, name) == 0)
479                 {
480                     return particleSet;
481                 }
482             }
483         }
484 
485         return NULL;
486     }
487 
488     //@}
489 
490 protected:
491     //----------------------------------------
492     //! @name コンストラクタ/デストラクタ
493     //@{
494 
495     //! コンストラクタです。
496     ParticleHandle(
497         os::IAllocator* allocator,
498         gfx::ResTransformNode resObj,
499         const gfx::TransformNode::Description& description);
500 
501     //! デストラクタです。
~ParticleHandle()502     virtual ~ParticleHandle()
503     {
504 
505     }
506 
507     //@}
508 
509 private:
510     int m_Id;
511     ut::MoveArray<nw::gfx::ParticleModel*>      m_ModelInstances;
512     ut::MoveArray<nw::gfx::ParticleEmitter*>    m_EmitterInstances;
513 };
514 
515 
516 // NW4C1.2.0との互換性維持の為。
517 typedef ParticleHandle ParticleNode;
518 
519 
520 
521 //! @brief 一表現のためのパーティクル一式です
522 // パーティクルを管理する機能はアプリケーション毎の実装になります。
523 // このクラスは参考のための実装例です。
524 // パフォーマンスよりも簡便性を重視した実装です。
525 class ParticleEffect
526 {
527 public:
528     //----------------------------------------
529     //! @name 初期化・終了処理
530     //@{
531 
532     //! @brief ParticleEffectクラスを生成します。
533     //!
534     //! @return 生成したParticleEffectクラスを返します。
535     //!
536     static ParticleEffect* Create(os::IAllocator* mainAllocator,
537                                   os::IAllocator* deviceAllocator,
538                                   bool autoAlocate,
539                                   gfx::ParticleContext* particleContext);
540 
541     //! @brief ParticleEffectクラスを破棄します。
542     //!
543     void Destroy();
544 
545 private:
546     //! @brief コンストラクタです。
547     //!
548     //! @param[in] mainAllocator メインメモリのアロケータです。
549     //! @param[in] deviceAllocator デバイスメモリのアロケータです。
550     //! @param[in] autoAlocate 足りない時に自動でアロケートすることを許可するフラグです。
551     //! @param[in] particleContext パーティクルコンテキストです。
552     //!
ParticleEffect(os::IAllocator * mainAllocator,os::IAllocator * deviceAllocator,bool autoAlocate,gfx::ParticleContext * particleContext)553     ParticleEffect(
554         os::IAllocator* mainAllocator,
555         os::IAllocator* deviceAllocator,
556         bool autoAlocate,
557         gfx::ParticleContext* particleContext
558         )
559         : m_NextId(0),
560         m_MainAllocator(mainAllocator),
561         m_DeviceAllocator(deviceAllocator),
562         m_AutoAlocate(autoAlocate),
563         m_ResModels(mainAllocator),
564         m_ResEmitters(mainAllocator),
565         m_FreeInstances(mainAllocator),
566         m_ActiveInstances(mainAllocator),
567         m_ParticleContext(particleContext)
568     {
569     }
570 
571     //! デストラクタです。
~ParticleEffect()572     ~ParticleEffect()
573     {
574         NW_ASSERT(this->GetActiveSize() == 0);
575         this->FreePool();
576     }
577 public:
578     //! @brief リソースのセットアップを行います。
579     //!
580     //! @param[in] useParticleMaterial パーティクルマテリアルを使用する場合はtrueを指定します。
581     void Setup(gfx::ResGraphicsFile resource, bool useParticleMaterial = false);
582 
583     //! @brief リソースから指定された名前のノードを管理対象として登録します。
584     //!
585     //! @param[in] resource グラフィックスリソースです。
586     //! @param[in] nodeNames 登録するノード一覧です。
587     void Register(gfx::ResGraphicsFile resource, const char** nodeNames);
588 
589     //! @brief 全てのリソースを管理対象として登録します。
590     //!
591     //! @param[in] resource グラフィックスリソースです。
592     void Register(gfx::ResGraphicsFile resource);
593 
594     //@}
595 
596     //----------------------------------------
597     //! @name 生成・破棄
598     //@{
599 
600     //! @brief  ParticleHandleを生成します。
601     //! @return 生成されたParticleHandleインスタンスを返します。
602     ParticleHandle* CreateMultiEmitterParticleHandle(u32 particleEmitterNum);
603 
604     //! @brief  生成済みのParticleHandleをリース(レンタル)します。
605     //! @return 生成済みのParticleHandleインスタンスを返します。
LeaseInstance()606     ParticleHandle* LeaseInstance()
607     {
608         if (this->GetFreeSize() == 0)
609         {
610             if (this->m_AutoAlocate)
611             {
612                 this->AddPool(1);
613             }
614             else
615             {
616                 return NULL;
617             }
618         }
619 
620         ParticleHandle* node = this->m_FreeInstances.Back();
621         this->m_FreeInstances.PopBack();
622         this->m_ActiveInstances.PushBack(node);
623 
624         this->ResetParticle(node);
625 
626         return node;
627     }
628 
629     //! @brief リース済みのParticleHandleを返却します。
630     //! @param[in] node 開放するトップノードです。
ReleaseInstance(gfx::SceneNode * node)631     void ReleaseInstance(gfx::SceneNode* node)
632     {
633         ParticleHandle* topNode = ut::DynamicCast<ParticleHandle*>(node);
634 
635         if (topNode != NULL)
636         {
637             int activeCount = this->GetActiveSize();
638             this->m_ActiveInstances.EraseFind(topNode);
639             NW_ASSERT(this->GetActiveSize() == activeCount - 1);
640 
641             this->m_FreeInstances.PushBack(topNode);
642         }
643     }
644 
645     //! @details :private
646     void DestroyParticleHandle(ParticleHandle* node);
DestroyParticleNode(ParticleHandle * node)647     void DestroyParticleNode(ParticleHandle* node)
648     {
649         return DestroyParticleHandle(node);
650     }
651 
652     //@}
653 
654     //----------------------------------------
655     //! @name 取得
656     //@{
657 
658     //! @brief インデックスでリース中のエフェクトを取得します。
659     //! @param[in] index インデックスです。
660     //! @return 該当するトップノードです。
GetActiveEffect(int index)661     ParticleHandle* GetActiveEffect(int index)
662     {
663         if (index < 0 || index >= this->GetActiveSize())
664         {
665             return NULL;
666         }
667 
668         return this->m_ActiveInstances[index];
669     }
670 
671     //! @brief ノードを初期化します。
672     //! @param[in] topNode 初期化するエフェクトをトップノードで指定します。
ResetParticle(nw::gfx::SceneNode * topNode)673     void ResetParticle(nw::gfx::SceneNode* topNode)
674     {
675         if (nw::ut::IsTypeOf<nw::gfx::ParticleModel>(topNode))
676         {
677             nw::gfx::ParticleModel* particleModel =
678                 nw::ut::DynamicCast<nw::gfx::ParticleModel*>(topNode);
679 
680             particleModel->ForeachParticleSet(nw::gfx::ParticleSetsClear());
681             particleModel->ParticleAnimFrameController().SetFrame(0);
682         }
683         else if (nw::ut::IsTypeOf<nw::gfx::ParticleEmitter>(topNode))
684         {
685             nw::gfx::ParticleEmitter* emitter =
686                 nw::ut::DynamicCast<nw::gfx::ParticleEmitter*>(topNode);
687 
688             emitter->Reset();
689         }
690 
691         nw::gfx::SceneNodeChildren::iterator end = topNode->GetChildEnd();
692         for (nw::gfx::SceneNodeChildren::iterator child = topNode->GetChildBegin();
693             child != end;
694             ++child)
695         {
696             ResetParticle(*child);
697         }
698     }
699 
700     //@}
701 
702     //----------------------------------------
703     //! @name インスタンスプール
704     //@{
705 
706     //! @brief リース中を含む確保済みのインスタンスの総数を取得します。
GetPoolSize()707     int GetPoolSize() const
708     {
709         return this->GetFreeSize() + this->GetActiveSize();
710     }
711 
712     //! @brief リース中のでないフリーのインスタンスの数を取得します。
GetFreeSize()713     int GetFreeSize() const
714     {
715         return this->m_FreeInstances.Size();
716     }
717 
718     //! @brief リース中のインスタンスの数を取得します。
GetActiveSize()719     int GetActiveSize() const
720     {
721         return this->m_ActiveInstances.Size();
722     }
723 
724     //! @brief 指定数のインスタンスを新しくプールします。
AddPool(int num)725     void AddPool(int num)
726     {
727         for (int i = 0 ; i < num ; ++i)
728         {
729             ParticleHandle* node = this->Allocate();
730             this->m_FreeInstances.push_back(node);
731         }
732     }
733 
734     //! @brief リース中以外の全てのインスタンスを破棄します。
FreePool()735     void FreePool()
736     {
737         while (this->m_FreeInstances.Size() > 0)
738         {
739             ParticleHandle* node = this->m_FreeInstances.Back();
740             this->m_FreeInstances.PopBack();
741             DestroyParticleHandle(node);
742         }
743     }
744 
745     //@}
746 
747 
748     //----------------------------------------
749     //! @name シェーダバイナリ管理
750     //@{
751 
752     //! @brief 外部シェーダファイルをロードします。
753     static void InitializeShaderBinary(const wchar_t* shaderFilePath, os::IAllocator* deviceAllocator);
754 
755     //! @brief ロードした外部シェーダファイルを破棄します。
756     static void FinalizeShaderBinary();
757 
758     //@}
759 
760 private:
761     //! @details :private
762     ParticleHandle* Allocate();
763 
764     int m_NextId;
765 
766     os::IAllocator* m_MainAllocator;
767     os::IAllocator* m_DeviceAllocator;
768 
769 
770     bool m_AutoAlocate;
771 
772     ut::MoveArray<gfx::ResParticleModel> m_ResModels;
773     ut::MoveArray<gfx::ResParticleEmitter> m_ResEmitters;
774 
775     ut::MoveArray<ParticleHandle*> m_FreeInstances;
776     ut::MoveArray<ParticleHandle*> m_ActiveInstances;
777 
778     gfx::ParticleContext* m_ParticleContext;
779 
780     static nw::demo::ResourceSet* m_ShaderResource;
781     static os::IAllocator* m_ShaderAllocator;
782 };
783 
784 
785 } // namespace demo
786 
787 } // namespace nw
788 
789 #endif // NW_DEMO_PARTICLE_H_
790