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: 28677 $
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 計算に用いるアライメントです。2 のべき乗である必要があります。
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 計算に用いるアライメントです。2 のべき乗である必要があります。
139     //! @return       必要なデバイスメモリサイズです。
140     static size_t GetDeviceMemorySize(
141         ResParticleModel resource,
142         const ParticleModel::Description& modelDescription,
143         size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT)
144     {
145         os::MemorySizeCalculator size(alignment);
146 
147         GetDeviceMemorySizeInternal(&size, resource, modelDescription);
148 
149         return size.GetSizeWithPadding(alignment);
150     }
151 
152     //! @details :private
153     static void GetDeviceMemorySizeInternal(
154         os::MemorySizeCalculator* pSize,
155         ResParticleModel resource,
156         const ParticleModel::Description& modelDescription);
157 
158     //@}
159 
160     //----------------------------------------
161     //! @name 更新
162     //@{
163 
164     //! @brief        ビジターを受け付けます。
165     //!
166     //! @param[in]    visitor ビジターです。
167     //!
168     virtual void Accept(ISceneVisitor* visitor);
169 
170     //! フレームを更新します。
UpdateParticleFrame()171     void UpdateParticleFrame()
172     {
173         m_ParticleAnimFrameController.UpdateFrame();
174     }
175 
176     //! @brief        ParticleModel 内の全ての ParticleSet を巡回して TFunction を適用します。
177     //!
178     //! @tparam       TFunction ParticleSet へのポインタを引数に取る関数(オブジェクト)の型です。
179     //! @param[in]    function 適応する関数(オブジェクト)です。
180     //!
181     template<typename TFunction>
ForeachParticleSet(TFunction function)182     void ForeachParticleSet(TFunction function)
183     {
184         for (int i = 0; i < (int)this->GetParticleSetsCount(); ++i)
185         {
186             ParticleSet* particleSet = this->GetParticleSets(i);
187 
188             function(particleSet);
189         }
190     }
191 
192     //! @brief        ParticleModel 内の全ての ParticleSet を巡回して TFunction を適用します。
193     //!
194     //! @tparam       TFunction ParticleSet へのポインタを引数に取る関数(オブジェクト)の型です。
195     //! @param[in]    function 適応する関数(オブジェクト)です。
196     //!
197     template<typename TFunction>
ForeachConstParticleSet(TFunction function)198     void ForeachConstParticleSet(TFunction function) const
199     {
200         for (int i = 0; i < (int)this->GetParticleSetsCount(); ++i)
201         {
202             const ParticleSet* particleSet = this->GetParticleSets(i);
203 
204             function(particleSet);
205         }
206     }
207 
208     //@}
209 
210     //----------------------------------------
211     //! @name 取得/設定
212     //@{
213 
214     //! @brief リソースを取得します。
215     //! @return パーティクルモデルのリソースを返します。
GetResModel()216     ResParticleModel GetResModel()
217     {
218         return ResDynamicCast<ResParticleModel>(this->GetResSceneObject());
219     }
220 
221     //! @brief リソースを取得します。
222     //! @return パーティクルモデルのリソースを返します。
GetResModel()223     const ResParticleModel GetResModel() const
224     {
225         return ResDynamicCast<ResParticleModel>(this->GetResSceneObject());
226     }
227 
228     //! @brief ParticleSetを追加します。
229     //!
230     //! @param node 追加するパーティクルセットです。
231     //! @return 追加できた場合trueを返します。
AttachParticleSet(ParticleSet * node)232     bool AttachParticleSet(ParticleSet* node)
233     {
234         if (m_ParticleSetCount >= this->m_ParticleSets.size()) return false;
235 
236         this->m_ParticleSets[m_ParticleSetCount] = node;
237         ++m_ParticleSetCount;
238         return true;
239     }
240 
241     //! @brief パーティクルセットの数を取得します。
242     //! @return パーティクルセットの数を返します。
GetParticleSetsCount()243     u32 GetParticleSetsCount() const
244     {
245         return m_ParticleSetCount;
246     }
247 
248     //! @brief パーティクルセットを取得します。
249     //!
250     //! @param[in] index インデックスです。
251     //! @return パーティクルセットを返します。
GetParticleSets(int index)252     ParticleSet* GetParticleSets(int index)
253     {
254         NW_ASSERT(index >= 0 && index < m_ParticleSetCount);
255         return this->m_ParticleSets[index];
256     }
257 
258     //! @brief パーティクルセットを取得します。
259     //!
260     //! @param[in] index インデックスです。
261     //! @return パーティクルセットを返します。
GetParticleSets(int index)262     const ParticleSet* GetParticleSets(int index) const
263     {
264         NW_ASSERT(index >= 0 && index < m_ParticleSetCount);
265         return this->m_ParticleSets[index];
266     }
267 
268     //! @brief ParticleShapeを追加します。
269     //! @param[in] node 追加するParticleShapeです。
270     //! @return 追加できた場合trueを返します。
AttachParticleShape(ParticleShape * node)271     bool AttachParticleShape(ParticleShape* node)
272     {
273         if (m_ParticleShapeCount >= this->m_ParticleShapes.size()) return false;
274 
275         this->m_ParticleShapes[m_ParticleSetCount] = node;
276         ++m_ParticleShapeCount;
277         return true;
278     }
279 
280     //! @brief パーティクルシェイプの数を取得します。
281     //! @return パーティクルシェイプの数を返します。
GetParticleShapesCount()282     u32 GetParticleShapesCount() const
283     {
284         return m_ParticleShapeCount;
285     }
286 
287     //! @brief ParticleShapeを取得します。
288     //!
289     //! @param[in] index インデックスです。
290     //! @return ParticleShapeを返します。
GetParticleShapes(int index)291     ParticleShape* GetParticleShapes(int index)
292     {
293         NW_ASSERT(index >= 0 && index < m_ParticleShapeCount);
294         return this->m_ParticleShapes[index];
295     }
296 
297     //! @brief ParticleShapeを取得します。
298     //!
299     //! @param[in] index インデックスです。
300     //! @return ParticleShapeを返します。
GetParticleShapes(int index)301     const ParticleShape* GetParticleShapes(int index) const
302     {
303         NW_ASSERT(index >= 0 && index < m_ParticleShapeCount);
304         return this->m_ParticleShapes[index];
305     }
306 
307     //! @brief アニメーションフレーム制御情報を取得します。
308     //! @return アニメーションフレームコントローラを返します。
ParticleAnimFrameController()309     anim::AnimFrameController& ParticleAnimFrameController()
310     {
311         return m_ParticleAnimFrameController;
312     }
313 
314     //! @brief アニメーションフレーム制御情報を取得します。
315     //! @return アニメーションフレームコントローラを返します。
ParticleAnimFrameController()316     const anim::AnimFrameController& ParticleAnimFrameController() const
317     {
318         return m_ParticleAnimFrameController;
319     }
320 
321     //! @brief パーティクルの存在を取得します。
322     //! @return パーティクル粒子が存在すればtrueを返します。
HasParticle()323     bool HasParticle() const
324     {
325         bool result;
326         ParticleSetsAreEmpty function(&result);
327         this->ForeachConstParticleSet(function);
328         return !result;
329     }
330 
331     //@}
332 
333 protected:
334     virtual Result Initialize(os::IAllocator* allocator);
335 
336     //! @details :private
337     static void GetMemorySizeForInitialize(
338         os::MemorySizeCalculator* pSize,
339         ResParticleModel resource,
340         const ParticleModel::Description& modelDescription);
341 
342     //----------------------------------------
343     //! @name コンストラクタ/デストラクタ
344     //@{
345 
346     //! @brief コンストラクタです。
ParticleModel(os::IAllocator * allocator,ResTransformNode resource,const ParticleModel::Description & description)347     ParticleModel(
348         os::IAllocator* allocator,
349         ResTransformNode resource,
350         const ParticleModel::Description& description)
351     : Model(
352         allocator,
353         resource,
354         description),
355         m_MaximumParticleSet(description.particleSetCount),
356         m_ParticleSetCount(0),
357         m_ParticleShapeCount(0),
358         m_ParticleAnimFrameController(0, 16777215, anim::PlayPolicy_Loop)
359     {}
360 
361     //! @brief デストラクタです。
~ParticleModel()362     virtual ~ParticleModel()
363     {
364         for (int i = 0; i < m_ParticleShapes.size(); ++i) // TBD
365         {
366             SafeDestroy(m_ParticleShapes[i]);
367 
368             // m_ParticleSetはAttachChild()されているので、
369             // SceneNodeにより自動的に解放されます。
370         }
371     }
372 
373     //@}
374 
375 private:
376     uint m_MaximumParticleSet;
377 
378     int m_ParticleSetCount;
379     ut::MoveArray<ParticleSet*> m_ParticleSets;
380 
381     int m_ParticleShapeCount;
382     ut::MoveArray<ParticleShape*> m_ParticleShapes;
383 
384     anim::AnimFrameController m_ParticleAnimFrameController;
385 };
386 
387 
388 } // namespace gfx
389 } // namespace nw
390 
391 #endif // NW_GFX_PARTICLEMODEL_H_
392