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