1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_ParticleModel.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_GFX_PARTICLEMODEL_H_
19 #define NW_GFX_PARTICLEMODEL_H_
20 
21 #include <nw/gfx/gfx_Model.h>
22 #include <nw/gfx/res/gfx_ResParticleModel.h>
23 #include <nw/gfx/gfx_ParticleShape.h>
24 #include <nw/anim/anim_AnimFrameController.h>
25 #include <nw/ut/ut_MoveArray.h>
26 
27 
28 namespace nw
29 {
30 namespace gfx
31 {
32 
33 class ParticleSet;
34 
35 //---------------------------------------------------------------------------
36 //! @brief        ParticleSetが空か調べる関数オブジェクトです。
37 //---------------------------------------------------------------------------
38 class ParticleSetsAreEmpty
39 {
40 public:
41     //! @brief コンストラクタです
42     //! @param[in] result 結果を返すポインタです。
ParticleSetsAreEmpty(bool * result)43     ParticleSetsAreEmpty(bool* result)
44     {
45         NW_NULL_ASSERT(result);
46         m_Result = result;
47         *m_Result = true;
48     }
49 
50     //! @brief ParticleSetが空か調べるオペレータです
51     //! @param[in] particleSet 調べるParticleSetです。
52     void operator()(const ParticleSet* particleSet);
53 
54 private:
55     bool* m_Result;
56 };
57 
58 //---------------------------------------------------------------------------
59 //! @brief        ParticleSetのデバッグ用のヒント情報をリセットする関数オブジェクトです。
60 //---------------------------------------------------------------------------
61 class ParticleSetsResetDebugHint
62 {
63 public:
64     //! @brief ParticleSetのデバッグ用のヒント情報をリセットするオペレータです
65     //! @param[in] particleSet 調べるParticleSetです。
66     void operator()(ParticleSet* particleSet);
67 };
68 
69 //---------------------------------------------------------------------------
70 //! @brief        ParticleSetを空にする関数オブジェクトです。
71 //---------------------------------------------------------------------------
72 class ParticleSetsClear
73 {
74 public:
75     //! @brief コンストラクタです
ParticleSetsClear()76     ParticleSetsClear() {}
77 
78     //! @brief ParticleSetを空にするオペレータです
79     //! @param[in] particleSet 空にするParticleSetです。
80     void operator()(ParticleSet* particleSet);
81 };
82 
83 //---------------------------------------------------------------------------
84 //! @brief        パーティクル用のモデルのクラスです。
85 //---------------------------------------------------------------------------
86 class ParticleModel : public Model
87 {
88 private:
89     NW_DISALLOW_COPY_AND_ASSIGN(ParticleModel);
90 
91 public:
92     NW_UT_RUNTIME_TYPEINFO;
93 
94     //! @brief 設定内容です。
95     struct Description : public Model::Description
96     {
97         //! @brief コンストラクタです。
DescriptionDescription98         Description() :
99             particleSetCount(0)
100         {}
101 
102         uint particleSetCount;
103     };
104 
105     //----------------------------------------
106     //! @name 作成/破棄
107     //@{
108 
109     //! @brief        モデルを生成します。
110     //!
111     //! @param[in]    parent 親のノードです。
112     //! @param[in]    resource リソースです。
113     //! @param[in]    modelDescription 設定内容です。
114     //! @param[in]    mainAllocator メインメモリのアロケータです。
115     //! @param[in]    deviceAllocator デバイスメモリのアロケータです。
116     //!
117     //! @return       生成されたモデルです。
118     //!
119     static ParticleModel* Create(
120         SceneNode* parent,
121         ResSceneObject resource,
122         const ParticleModel::Description& modelDescription,
123         os::IAllocator* mainAllocator,
124         os::IAllocator* deviceAllocator);
125 
126     //! @brief        生成時に必要なメモリサイズを取得します。
127     //! @param[in]    resource リソースです。
128     //! @param[in]    description 設定内容です。
129     //! @param[in]    alignment 計算に用いるアライメントです。2 のべき乗である必要があります。
130     //! @return       必要なメモリサイズです。
131     static size_t GetMemorySize(
132         ResParticleModel resource,
133         const ParticleModel::Description& modelDescription,
134         size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT)
135     {
136         os::MemorySizeCalculator size(alignment);
137 
138         GetMemorySizeInternal(&size, resource, modelDescription);
139 
140         return size.GetSizeWithPadding(alignment);
141     }
142 
143     //! @details :private
144     static void GetMemorySizeInternal(
145         os::MemorySizeCalculator* pSize,
146         ResParticleModel resource,
147         const ParticleModel::Description& modelDescription);
148 
149     //! @brief        生成時に必要なデバイスメモリサイズを取得します。
150     //! @param[in]    resource リソースです。
151     //! @param[in]    alignment 計算に用いるアライメントです。2 のべき乗である必要があります。
152     //! @return       必要なデバイスメモリサイズです。
153     static size_t GetDeviceMemorySize(
154         ResParticleModel resource,
155         const ParticleModel::Description& modelDescription,
156         size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT)
157     {
158         os::MemorySizeCalculator size(alignment);
159 
160         GetDeviceMemorySizeInternal(&size, resource, modelDescription);
161 
162         return size.GetSizeWithPadding(alignment);
163     }
164 
165     //! @details :private
166     static void GetDeviceMemorySizeInternal(
167         os::MemorySizeCalculator* pSize,
168         ResParticleModel resource,
169         const ParticleModel::Description& modelDescription);
170 
171     //@}
172 
173     //----------------------------------------
174     //! @name 更新
175     //@{
176 
177     //! @brief        ビジターを受け付けます。
178     //!
179     //! @param[in]    visitor ビジターです。
180     //!
181     virtual void Accept(ISceneVisitor* visitor);
182 
183     //! フレームを更新します。
UpdateParticleFrame()184     void UpdateParticleFrame()
185     {
186         m_ParticleAnimFrameController.UpdateFrame();
187     }
188 
189     //! @brief        ParticleModel 内の全ての ParticleSet を巡回して TFunction を適用します。
190     //!
191     //! @tparam       TFunction ParticleSet へのポインタを引数に取る関数(オブジェクト)の型です。
192     //! @param[in]    function 適応する関数(オブジェクト)です。
193     //!
194     template<typename TFunction>
ForeachParticleSet(TFunction function)195     void ForeachParticleSet(TFunction function)
196     {
197         for (int i = 0; i < (int)this->GetParticleSetsCount(); ++i)
198         {
199             ParticleSet* particleSet = this->GetParticleSets(i);
200 
201             function(particleSet);
202         }
203     }
204 
205     //! @brief        ParticleModel 内の全ての ParticleSet を巡回して TFunction を適用します。
206     //!
207     //! @tparam       TFunction ParticleSet へのポインタを引数に取る関数(オブジェクト)の型です。
208     //! @param[in]    function 適応する関数(オブジェクト)です。
209     //!
210     template<typename TFunction>
ForeachConstParticleSet(TFunction function)211     void ForeachConstParticleSet(TFunction function) const
212     {
213         for (int i = 0; i < (int)this->GetParticleSetsCount(); ++i)
214         {
215             const ParticleSet* particleSet = this->GetParticleSets(i);
216 
217             function(particleSet);
218         }
219     }
220 
221     //@}
222 
223     //----------------------------------------
224     //! @name リソース
225     //@{
226 
227     //! @brief リソースを取得します。
228     //! @return パーティクルモデルのリソースを返します。
GetResModel()229     ResParticleModel GetResModel()
230     {
231         return ResDynamicCast<ResParticleModel>(this->GetResSceneObject());
232     }
233 
234     //! @brief リソースを取得します。
235     //! @return パーティクルモデルのリソースを返します。
GetResModel()236     const ResParticleModel GetResModel() const
237     {
238         return ResDynamicCast<ResParticleModel>(this->GetResSceneObject());
239     }
240 
241     //@}
242 
243     //----------------------------------------
244     //! @name 取得/設定
245     //@{
246 
247     //! @brief ParticleSetを追加します。
248     //!
249     //! @param node 追加するパーティクルセットです。
250     //! @return 追加できた場合trueを返します。
AttachParticleSet(ParticleSet * node)251     bool AttachParticleSet(ParticleSet* node)
252     {
253         if (m_ParticleSetCount >= this->m_ParticleSets.size()) return false;
254 
255         this->m_ParticleSets[m_ParticleSetCount] = node;
256         ++m_ParticleSetCount;
257         return true;
258     }
259 
260     //! @brief パーティクルセットの数を取得します。
261     //! @return パーティクルセットの数を返します。
GetParticleSetsCount()262     u32 GetParticleSetsCount() const
263     {
264         return m_ParticleSetCount;
265     }
266 
267     //! @brief パーティクルセットを取得します。
268     //!
269     //! @param[in] index インデックスです。
270     //! @return パーティクルセットを返します。
GetParticleSets(int index)271     ParticleSet* GetParticleSets(int index)
272     {
273         NW_ASSERT(index >= 0 && index < m_ParticleSetCount);
274         return this->m_ParticleSets[index];
275     }
276 
277     //! @brief パーティクルセットを取得します。
278     //!
279     //! @param[in] index インデックスです。
280     //! @return パーティクルセットを返します。
GetParticleSets(int index)281     const ParticleSet* GetParticleSets(int index) const
282     {
283         NW_ASSERT(index >= 0 && index < m_ParticleSetCount);
284         return this->m_ParticleSets[index];
285     }
286 
287     //! @brief ParticleShapeを追加します。
288     //! @param[in] node 追加するParticleShapeです。
289     //! @return 追加できた場合trueを返します。
AttachParticleShape(ParticleShape * node)290     bool AttachParticleShape(ParticleShape* node)
291     {
292         if (m_ParticleShapeCount >= this->m_ParticleShapes.size()) return false;
293 
294         this->m_ParticleShapes[m_ParticleSetCount] = node;
295         ++m_ParticleShapeCount;
296         return true;
297     }
298 
299     //! @brief パーティクルシェイプの数を取得します。
300     //! @return パーティクルシェイプの数を返します。
GetParticleShapesCount()301     u32 GetParticleShapesCount() const
302     {
303         return m_ParticleShapeCount;
304     }
305 
306     //! @brief ParticleShapeを取得します。
307     //!
308     //! @param[in] index インデックスです。
309     //! @return ParticleShapeを返します。
GetParticleShapes(int index)310     ParticleShape* GetParticleShapes(int index)
311     {
312         NW_ASSERT(index >= 0 && index < m_ParticleShapeCount);
313         return this->m_ParticleShapes[index];
314     }
315 
316     //! @brief ParticleShapeを取得します。
317     //!
318     //! @param[in] index インデックスです。
319     //! @return ParticleShapeを返します。
GetParticleShapes(int index)320     const ParticleShape* GetParticleShapes(int index) const
321     {
322         NW_ASSERT(index >= 0 && index < m_ParticleShapeCount);
323         return this->m_ParticleShapes[index];
324     }
325 
326     //! @brief アニメーションフレーム制御情報を取得します。
327     //! @return アニメーションフレームコントローラを返します。
ParticleAnimFrameController()328     anim::AnimFrameController& ParticleAnimFrameController()
329     {
330         return m_ParticleAnimFrameController;
331     }
332 
333     //! @brief アニメーションフレーム制御情報を取得します。
334     //! @return アニメーションフレームコントローラを返します。
ParticleAnimFrameController()335     const anim::AnimFrameController& ParticleAnimFrameController() const
336     {
337         return m_ParticleAnimFrameController;
338     }
339 
340     //! @brief パーティクルの存在を取得します。
341     //! @return パーティクル粒子が存在すればtrueを返します。
HasParticle()342     bool HasParticle() const
343     {
344         bool result;
345         ParticleSetsAreEmpty function(&result);
346         this->ForeachConstParticleSet(function);
347         return !result;
348     }
349 
350     //! @brief 描画順序のデバッグ用のヒント情報を初期化します。
351     //! @details シーンからデタッチしたあとに再利用する場合などに呼び出してください。
ResetDebugHint()352     void ResetDebugHint()
353     {
354 #ifdef NW_CHECK_PARTICLE_PROCESS
355         ParticleSetsResetDebugHint function;
356         this->ForeachParticleSet(function);
357 #endif
358     }
359 
360     //@}
361 
362 protected:
363     virtual Result Initialize(os::IAllocator* allocator);
364 
365     //! @details :private
366     static void GetMemorySizeForInitialize(
367         os::MemorySizeCalculator* pSize,
368         ResParticleModel resource,
369         const ParticleModel::Description& modelDescription);
370 
371     //----------------------------------------
372     //! @name コンストラクタ/デストラクタ
373     //@{
374 
375     //! @brief コンストラクタです。
ParticleModel(os::IAllocator * allocator,ResTransformNode resource,const ParticleModel::Description & description)376     ParticleModel(
377         os::IAllocator* allocator,
378         ResTransformNode resource,
379         const ParticleModel::Description& description)
380     : Model(
381         allocator,
382         resource,
383         description),
384         m_MaximumParticleSet(description.particleSetCount),
385         m_ParticleSetCount(0),
386         m_ParticleShapeCount(0),
387         m_ParticleAnimFrameController(0, 16777215, anim::PlayPolicy_Loop)
388     {}
389 
390     //! @brief デストラクタです。
~ParticleModel()391     virtual ~ParticleModel()
392     {
393         for (int i = 0; i < m_ParticleShapes.size(); ++i) // TBD
394         {
395             SafeDestroy(m_ParticleShapes[i]);
396 
397             // m_ParticleSetはAttachChild()されているので、
398             // SceneNodeにより自動的に解放されます。
399         }
400     }
401 
402     //@}
403 
404 private:
405     uint m_MaximumParticleSet;
406 
407     int m_ParticleSetCount;
408     ut::MoveArray<ParticleSet*> m_ParticleSets;
409 
410     int m_ParticleShapeCount;
411     ut::MoveArray<ParticleShape*> m_ParticleShapes;
412 
413     anim::AnimFrameController m_ParticleAnimFrameController;
414 };
415 
416 
417 } // namespace gfx
418 } // namespace nw
419 
420 #endif // NW_GFX_PARTICLEMODEL_H_
421