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