1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_ParticleEmitter.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: 31311 $
16  *---------------------------------------------------------------------------*/
17 
18 #ifndef NW_GFX_PARTICLEEMITTER_H_
19 #define NW_GFX_PARTICLEEMITTER_H_
20 
21 #include <nw/gfx/gfx_TransformNode.h>
22 
23 #include <nw/gfx/res/gfx_ResParticleEmitter.h>
24 #include <nw/gfx/gfx_ParticleCollection.h>
25 #include <nw/gfx/gfx_ParticleRandom.h>
26 #include <nw/anim/anim_AnimFrameController.h>
27 
28 namespace nw
29 {
30 namespace gfx
31 {
32 class ParticleEmitter;
33 
34 //---------------------------------------------------------------------------
35 //! @brief        パーティクルエミッタを表すクラスです。
36 //---------------------------------------------------------------------------
37 class ParticleEmitter : public TransformNode
38 {
39 private:
40     NW_DISALLOW_COPY_AND_ASSIGN(ParticleEmitter);
41 
42 public:
43     NW_UT_RUNTIME_TYPEINFO;
44 
45     //! @brief 設定内容です。
46     struct Description : public TransformNode::Description
47     {
48         //! @brief コンストラクタです。
DescriptionDescription49         Description()
50         {}
51     };
52 
53     //----------------------------------------
54     //! @name 作成/破棄
55     //@{
56 
57     //! @brief        リソースからParticleEmitterノードを生成します。
58     //!
59     //! @param[in]    parent 親のノードです。
60     //! @param[in]    resource リソースです。
61     //! @param[in]    description 設定内容です。
62     //! @param[in]    allocator アロケータです。
63     //!
64     //! @return       生成されたParticleEmitterノードです。
65     //!
66     static ParticleEmitter* Create(
67         SceneNode* parent,
68         ResSceneObject resource,
69         const ParticleEmitter::Description& description,
70         os::IAllocator* allocator);
71 
72     //! @brief        生成時に必要なデバイスメモリサイズを取得します。
73     //! @param[in]    resource リソースです。
74     //! @param[in]    description 設定内容です。
75     //! @param[in]    alignment 計算に用いるアライメントです。2 のべき乗である必要があります。
76     //! @return       必要なデバイスメモリサイズです。
77     static size_t GetMemorySize(
78         ResParticleEmitter resource,
79         const ParticleEmitter::Description& description,
80         size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT)
81     {
82         os::MemorySizeCalculator size(alignment);
83 
84         GetMemorySizeInternal(&size, resource, description);
85 
86         return size.GetSizeWithPadding(alignment);
87     }
88 
89     //! @details :private
90     static void GetMemorySizeInternal(
91         os::MemorySizeCalculator* pSize,
92         ResParticleEmitter resource,
93         const ParticleEmitter::Description& description);
94 
95     //@}
96 
97     //----------------------------------------
98     //! @name 更新
99     //@{
100 
101     //! @brief        ビジターを受け付けます。
102     //!
103     //! @param[in]    visitor ビジターです。
104     //!
105     virtual void Accept(ISceneVisitor* visitor);
106 
107     //! @brief フレームを更新します。
108     //! @details パーティクル用のAnimFrameControllerの値を進めます。
109     //! 実際の放出処理に先行して実行してください。
UpdateParticleFrame()110     void UpdateParticleFrame()
111     {
112         m_ParticleAnimFrameController.UpdateFrame();
113     }
114 
115     //! @brief エミッタを初期状態に戻します。
116     //! @details 放出用の内部パラメータをリセットし、時間を0に戻します。
Reset()117     void Reset()
118     {
119         m_IsFirstEmission = true;
120         m_EmissionCount = 0;
121         m_NextEmissionTime = 0;
122 
123         // フレームコントローラはFrameを0にするだけです。
124         m_ParticleAnimFrameController.SetFrame(0);
125     }
126 
127     //@}
128 
129     //----------------------------------------
130     //! @name リソース
131     //@{
132 
133     //! @brief リソースを取得します。
134     //! @return リソースを返します。
GetResParticleEmitter()135     ResParticleEmitter GetResParticleEmitter()
136     {
137         return ResDynamicCast<ResParticleEmitter>( this->GetResSceneObject() );
138     }
139 
140     //! @brief リソースを取得します。
141     //! @return リソースを返します。
GetResParticleEmitter()142     const ResParticleEmitter GetResParticleEmitter() const
143     {
144         return ResDynamicCast<ResParticleEmitter>( this->GetResSceneObject() );
145     }
146 
147     //! @brief 放出パラメータのリソースを取得します。
148     // ここで取得したリソースは保持しないでください。
149     //! @param[in] copyOnly 複製の場合のみ取得します。
150     //! @return リソースを返します。
151     ResParticleEmitterParameter GetResParticleEmitterParameterCopy(bool copyOnly = false)
152     {
153         if (m_ResParameter.IsValid())
154         {
155             return m_ResParameter;
156         }
157 
158         if (!copyOnly && this->GetResParticleEmitter().IsValid())
159         {
160             return ResParticleEmitterParameter(&this->GetResParticleEmitter().ptr()->m_IsResourceCopyEnabled);
161         }
162 
163         return m_ResParameter; // invalid
164     }
165 
166     //! @brief 放出パラメータのリソースを取得します。
167     // ここで取得したリソースは保持しないでください。
168     //! @param[in] copyOnly 複製の場合のみ取得します。
169     //! @return リソースを返します。
170     const ResParticleEmitterParameter GetResParticleEmitterParameterCopy(bool copyOnly = false) const
171     {
172         if (m_ResParameter.IsValid())
173         {
174             return m_ResParameter;
175         }
176 
177         if (!copyOnly && this->GetResParticleEmitter().IsValid())
178         {
179             return ResParticleEmitterParameter(&this->GetResParticleEmitter().ptr()->m_IsResourceCopyEnabled);
180         }
181 
182         return m_ResParameter; // invalid
183     }
184 
185     //! @brief 形状のリソースを取得します。
186     // ここで取得したリソースは保持しないでください。
187     //! @param[in] copyOnly 複製の場合のみ取得します。
188     //! @return リソースを返します。
189     ResParticleForm GetResParticleFormCopy(bool copyOnly = false)
190     {
191         if (m_ResForm.IsValid())
192         {
193             return m_ResForm;
194         }
195 
196         if (!copyOnly && this->GetResParticleEmitter().IsValid())
197         {
198             return this->GetResParticleEmitter().GetParticleForm();
199         }
200 
201         return m_ResForm; // invalid
202     }
203 
204     //! @brief 形状のリソースを取得します。
205     // ここで取得したリソースは保持しないでください。
206     //! @param[in] copyOnly 複製の場合のみ取得します。
207     //! @return リソースを返します。
208     const ResParticleForm GetResParticleFormCopy(bool copyOnly = false) const
209     {
210         if (m_ResForm.IsValid())
211         {
212             return m_ResForm;
213         }
214 
215         if (!copyOnly && this->GetResParticleEmitter().IsValid())
216         {
217             return this->GetResParticleEmitter().GetParticleForm();
218         }
219 
220         return m_ResForm; // invalid
221     }
222 
223     //@}
224 
225     //----------------------------------------
226     //! @name 取得/設定
227     //@{
228 
229     //! @brief 放出量を計算します。
230     //!
231     //! @param[in]    prevTime 前回の時刻です。
232     //! @param[in]    time 現在の時刻です。
233     //!
234     //! @return       放出量を返します。
235     int GetEmissionCount(f32 prevTime, f32 time);
236 
237     //! @brief 放出先のParticleSetを設定します。
238     //!
239     //! @param[in]    particleSet 放出先のParticleSetです。
240     //!
SetParticleSet(ParticleSet * particleSet)241     void SetParticleSet(ParticleSet* particleSet)
242     {
243         this->m_ParticleSet = particleSet;
244     }
245 
246     //! @brief 放出先のParticleSetを取得します。
247     //! @return 放出先のParticleSetを返します。
GetParticleSet()248     ParticleSet* GetParticleSet()
249     {
250         return this->m_ParticleSet;
251     }
252 
253     //! @brief 放出先のParticleSetを取得します。
254     //! @return 放出先のParticleSetを返します。
GetParticleSet()255     const ParticleSet* GetParticleSet() const
256     {
257         return this->m_ParticleSet;
258     }
259 
260     //! @brief アニメーションフレーム制御情報を取得します。
261     //! @return アニメーションフレームコントローラを返します。
ParticleAnimFrameController()262     anim::AnimFrameController& ParticleAnimFrameController()
263     {
264         return m_ParticleAnimFrameController;
265     }
266 
267     //! @brief アニメーションフレーム制御情報を取得します。
268     //! @return アニメーションフレームコントローラを返します。
ParticleAnimFrameController()269     const anim::AnimFrameController& ParticleAnimFrameController() const
270     {
271         return m_ParticleAnimFrameController;
272     }
273 
274     //! @details :private
Srand(u32 seed)275     void Srand(u32 seed)
276     {
277         m_ParticleRandom.Srand(seed);
278     }
279 
280     //! @brief パーティクルの放出時間が終了していないことを調べます。
281     //! @return 放出が終了していなければtrueを返します。
IsAlive()282     bool IsAlive() const
283     {
284         const ResParticleEmitterParameter resource = this->GetResParticleEmitterParameterCopy(false);
285         if (!resource.IsValid())
286         {
287             return false;
288         }
289 
290         if (resource.GetEmissionRatio() == 0)
291         {
292             return false;
293         }
294 
295         if (resource.GetEmissionSpanInfinity())
296         {
297             return true;
298         }
299 
300         f32 time = m_ParticleAnimFrameController.GetFrame();
301         f32 cookedTime = time - resource.GetEmissionStart() - 1;
302         if (cookedTime >= resource.GetEmissionSpan())
303         {
304             return false;
305         }
306 
307         return true;
308     }
309 
310     //@}
311 
312     //----------------------------------------
313     //! @name 放出
314     //@{
315 
316     //! @brief 放出処理を行います。
317     //! @details 前回の放出から現在の時間までに放出されるはずのパーティクル粒子を放出します。
318     //! @param[in]    particleContext パーティクルコンテキストです。
319     //!
320     //! @return       放出量を返します。
321     int Emission(ParticleContext* particleContext);
322 
323     //@}
324 
325     //----------------------------------------
326     //! @name エミッタ形状
327     //@{
328 
329 #ifdef NW_GFX_PARTICLE_COMPAT_1_1
330     //! @details :private
331     static void CalcCubeForm(
332         const ResParticleCubeForm& cubeForm,
333         int emissionCount,
334         ParticleRandom* random,
335         nw::math::VEC3* positions);
336 
337     //! @details :private
338     static void CalcCylinderForm(
339         const ResParticleCylinderForm& cylinderForm,
340         int emissionCount,
341         ParticleRandom* random,
342         nw::math::VEC3* positions);
343 
344     //! @details :private
345     static void CalcDiscForm(
346         const ResParticleDiscForm& discForm,
347         int emissionCount,
348         ParticleRandom* random,
349         nw::math::VEC3* positions);
350 
351     //! @details :private
352     static void CalcPointForm(
353         const ResParticlePointForm& pointForm,
354         int emissionCount,
355         ParticleRandom* random,
356         nw::math::VEC3* positions);
357 
358     //! @details :private
359     static void CalcSphereForm(
360         const ResParticleSphereForm& sphereForm,
361         int emissionCount,
362         ParticleRandom* random,
363         nw::math::VEC3* positions);
364 
365     //! @details :private
366     static void CalcRectangleForm(
367         const ResParticleRectangleForm& rectangleForm,
368         int emissionCount,
369         ParticleRandom* random,
370         nw::math::VEC3* positions);
371 #else
372     //! @details :private
373     static void CalcCubeForm(
374         const ResParticleCubeForm& cubeForm,
375         int emissionCount,
376         ParticleRandom* random,
377         u16* activeIndex,
378         int incrIndex,
379         nw::math::VEC3* targetTranslate);
380 
381     //! @details :private
382     static void CalcCylinderForm(
383         const ResParticleCylinderForm& cylinderForm,
384         int emissionCount,
385         ParticleRandom* random,
386         u16* activeIndex,
387         int incrIndex,
388         nw::math::VEC3* targetTranslate);
389 
390     //! @details :private
391     static void CalcDiscForm(
392         const ResParticleDiscForm& discForm,
393         int emissionCount,
394         ParticleRandom* random,
395         u16* activeIndex,
396         int incrIndex,
397         nw::math::VEC3* targetTranslate);
398 
399     //! @details :private
400     static void CalcPointForm(
401         const ResParticlePointForm& pointForm,
402         int emissionCount,
403         ParticleRandom* random,
404         u16* activeIndex,
405         int incrIndex,
406         nw::math::VEC3* targetTranslate);
407 
408     //! @details :private
409     static void CalcSphereForm(
410         const ResParticleSphereForm& sphereForm,
411         int emissionCount,
412         ParticleRandom* random,
413         u16* activeIndex,
414         int incrIndex,
415         nw::math::VEC3* targetTranslate);
416 
417     //! @details :private
418     static void CalcRectangleForm(
419         const ResParticleRectangleForm& rectangleForm,
420         int emissionCount,
421         ParticleRandom* random,
422         u16* activeIndex,
423         int incrIndex,
424         nw::math::VEC3* targetTranslate);
425 #endif
426 
427     //@}
428 
429 protected:
430     //----------------------------------------
431     //! @name コンストラクタ/デストラクタ
432     //@{
433 
434     //! @brief コンストラクタです。
435     //! @param[in] allocator メモリアロケータです。
436     //! @param[in] resObj エミッタのリソースです。
437     //! @param[in] description ディスクリプションです。
438     //! @param[in] resParameterObj エミッタパラメータのリソースです。
439     //! @param[in] resFormObj 形状のリソースです。
440     ParticleEmitter(
441         os::IAllocator* allocator,
442         ResParticleEmitter resObj,
443         const ParticleEmitter::Description& description,
444         ResParticleEmitterParameter resParameterObj,
445         ResParticleForm resFormObj);
446 
447     //! @brief デストラクタです。
448     virtual ~ParticleEmitter();
449 
450     //@}
451 
452 private:
453     bool m_IsFirstEmission;
454     f32 m_EmissionCount;
455     s32 m_NextEmissionTime;
456     ParticleSet* m_ParticleSet;
457 
458     ParticleRandom m_ParticleRandom;
459     anim::AnimFrameController m_ParticleAnimFrameController;
460 
461     ResParticleEmitterParameter m_ResParameter;
462     ResParticleForm m_ResForm;
463 };
464 
465 } // namespace gfx
466 } // namespace nw
467 
468 #endif // NW_GFX_PARTICLEEMITTER_H_
469