1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_ParticleSet.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_PARTICLESET_H_
17 #define NW_GFX_PARTICLESET_H_
18 
19 #include <nw/gfx/gfx_TransformNode.h>
20 
21 #include <nw/gfx/gfx_ParticleModel.h>
22 #include <nw/gfx/res/gfx_ResParticleSet.h>
23 #include <nw/gfx/res/gfx_ResParticleAnimationOption.h>
24 #include <nw/gfx/gfx_ParticleRandom.h>
25 #include <nw/gfx/gfx_ParticleTime.h>
26 
27 namespace nw
28 {
29 namespace gfx
30 {
31 
32 class ParticleCollection;
33 class ParticleContext;
34 class ParticleShape;
35 
36 //---------------------------------------------------------------------------
37 //! @brief        パーティクル群を表すクラスです。
38 //---------------------------------------------------------------------------
39 class ParticleSet : public SceneNode
40 {
41 private:
42     NW_DISALLOW_COPY_AND_ASSIGN(ParticleSet);
43 
44 public:
45     NW_UT_RUNTIME_TYPEINFO;
46 
47     //! @brief 設定内容です。
48     struct Description : public SceneNode::Description
49     {
50         s32 maxInitializers;         //!< ParticleInitializerのバッファの数です。
51         s32 maxUpdaters;             //!< ParticleUpdaterのバッファの数です。
52 
53         //! @brief コンストラクタです。
DescriptionDescription54         Description() :
55             maxInitializers(0),
56             maxUpdaters(0)
57         {}
58     };
59 
60     //! @brief ランタイム用のイニシャライザの管理情報です。
61     struct Initializer
62     {
63         bool m_IsCopied; //!< コピーされたリソースであることを表すフラグです。
64         const ResParticleInitializerData *resource; //!< リソースへのポインタです。
65         u32 work; //!< ワークエリアです。
66 
67         // 高速化のためのキャッシュ
68         nw::ut::ResTypeInfo     m_Type;
69         void* m_TargetStreams[2]; //!< 変更対象のストリームへのポインタです。
70     };
71 
72     //! @brief ランタイム用のイニシャライザの管理情報です。
73     struct Updater
74     {
75         bool m_IsCopied; //!< コピーされたリソースであることを表すフラグです。
76         const ResParticleUpdaterData *resource; //!< リソースへのポインタです。
77         u32 work; //!< ワークエリアです。
78 
79         // 高速化のためのキャッシュ
80         nw::ut::ResTypeInfo     m_Type;
81         void* m_TargetStreams[2]; //!< 変更対象のストリームへのポインタです。
82 
83         u32                     m_Flags;        //!< フラグです。
84         enum Flag
85         {
86             FLAG_IS_HAS_CURVE_ANIM         = 0x1 << 0       //!< カーブアニメーションを保持しているかのフラグです。
87         };
88 
89         //! @brief 任意のフラグが有効になっているか取得します。
90         //! @param[in] flags 有効か調べるフラグです。
91         //! @return 有効な場合はtrueを返します。
IsEnabledFlagsUpdater92         inline bool IsEnabledFlags(bit32 flags) const
93         {
94             return ut::CheckFlag(m_Flags, flags);
95         }
96 
97         //! @brief 任意のフラグを有効に設定します。
98         //!@param[in] flags 有効にするフラグです。
EnableFlagsUpdater99         inline void EnableFlags(bit32 flags)
100         {
101             m_Flags = ut::EnableFlag(m_Flags, flags);
102         }
103     };
104 
105     //----------------------------------------
106     //! @name 作成/破棄
107     //@{
108 
109     //! @brief        リソースからパーティクルセットを生成します。
110     //!
111     //! @param[in]    parent 親のノードです。
112     //! @param[in]    resource リソースです。
113     //! @param[in]    description 設定内容です。
114     //! @param[in]    mainAllocator メインアロケータです。
115     //! @param[in]    deviceAllocator デバイスアロケータです。
116     //! @param[in]    shape シェイプです。
117     //!
118     //! @return       生成されたトランスフォームノードです。
119     //!
120     static ParticleSet* Create(
121         SceneNode* parent,
122         ResSceneObject resource,
123         const ParticleSet::Description& description,
124         os::IAllocator* mainAllocator,
125         os::IAllocator* deviceAllocator,
126         ParticleShape* shape);
127 
128     //! @brief        生成時に必要なメモリサイズを取得します。
129     //! @param[in]    resource リソースです。
130     //! @param[in]    description 設定内容です。
131     //! @param[in]    alignment 計算に用いるアライメントです。2 のべき乗である必要があります。
132     //! @return       必要なメモリサイズです。
133     static size_t GetMemorySize(
134         ResParticleSet resource,
135         const ParticleSet::Description& description,
136         size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT)
137     {
138         os::MemorySizeCalculator size(alignment);
139 
140         GetMemorySizeInternal(&size, resource, description);
141 
142         return size.GetSizeWithPadding(alignment);
143     }
144 
145     //! @details :private
146     static void GetMemorySizeInternal(
147         os::MemorySizeCalculator* pSize,
148         ResParticleSet resource,
149         const ParticleSet::Description& description);
150 
151     //! @brief        生成時に必要なデバイスメモリサイズを取得します。
152     //! @param[in]    resource リソースです。
153     //! @param[in]    alignment 計算に用いるアライメントです。2 のべき乗である必要があります。
154     //! @return       必要なデバイスメモリサイズです。
155     static size_t GetDeviceMemorySize(
156         ResParticleSet resource,
157         size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT)
158     {
159         os::MemorySizeCalculator size(alignment);
160 
161         GetDeviceMemorySizeInternal(&size, resource);
162 
163         return size.GetSizeWithPadding(alignment);
164     }
165 
166     //! @details :private
167     static void GetDeviceMemorySizeInternal(
168         os::MemorySizeCalculator* pSize,
169         ResParticleSet resource);
170 
171     //@}
172 
173     //----------------------------------------
174     //! @name 更新
175     //@{
176 
177     //! @brief        ビジターを受け付けます。
178     //!
179     //! @param[in]    visitor ビジターです。
180     //!
181     virtual void Accept(ISceneVisitor* visitor);
182 
183     //@}
184 
185     //----------------------------------------
186     //! @name 取得/設定
187     //@{
188 
189     //! @brief リソースを取得します。
190     //! @return 設定されているリソースです。
GetResParticleSet()191     ResParticleSet GetResParticleSet()
192     {
193         return ResDynamicCast<ResParticleSet>( this->GetResSceneObject() );
194     }
195 
196     //! @brief リソースを取得します。
197     //! @return 設定されているリソースです。
GetResParticleSet()198     const ResParticleSet GetResParticleSet() const
199     {
200         return ResDynamicCast<ResParticleSet>( this->GetResSceneObject() );
201     }
202 
203     //! @brief パーティクルコレクションを設定します。
204     //! @param[in] node 設定するパーティクルコレクションです。
205     //! @return 既に設定されている場合は、falseを返します。
AttachParticleCollection(ParticleCollection * node)206     bool AttachParticleCollection(ParticleCollection* node)
207     {
208         if (this->m_ParticleCollection != NULL)
209         {
210             return false;
211         }
212 
213         this->m_ParticleCollection = node;
214         return true;
215     }
216 
217     //! @brief パーティクルコレクションを取得します。
218     //! @return 設定されているパーティクルコレクションです。
GetParticleCollection()219     ParticleCollection* GetParticleCollection()
220     {
221         return this->m_ParticleCollection;
222     }
223 
224     //! @brief パーティクルコレクションを取得します。
225     //! @return 設定されているパーティクルコレクションです。
GetParticleCollection()226     const ParticleCollection* GetParticleCollection() const
227     {
228         return this->m_ParticleCollection;
229     }
230 
231     //! @brief イニシャライザの配列を取得します。
232     //! @return イニシャライザの配列へのポインタを返します。
GetInitializers()233     ut::MoveArray<Initializer>* GetInitializers()
234     {
235         return &this->m_Initializers;
236     }
237 
238     //! @brief イニシャライザの配列を取得します。
239     //! @return イニシャライザの配列へのポインタを返します。
GetInitializers()240     const ut::MoveArray<Initializer>* GetInitializers() const
241     {
242         return &this->m_Initializers;
243     }
244 
245     //! @brief アップデータの配列を取得します。
246     //! @return アップデータの配列へのポインタを返します。
GetUpdaters()247     ut::MoveArray<Updater>* GetUpdaters()
248     {
249         return &this->m_Updaters;
250     }
251 
252     //! @brief アップデータの配列を取得します。
253     //! @return アップデータの配列へのポインタを返します。
GetUpdaters()254     const ut::MoveArray<Updater>* GetUpdaters() const
255     {
256         return &this->m_Updaters;
257     }
258 
259 #ifdef NW_GFX_PARTICLE_COMPAT_1_1
260     //! @brief パーティクルを追加します。
261     //! @details :private
262     void AddParticles(
263         const nw::math::MTX34& emitterMatrix,
264         const nw::math::VEC3* const positions,
265         ParticleSet* parentParticleSet,
266         const u16* const parentIndices,
267         int count);
268 #else
269     //! @brief パーティクルを追加します。
270     //! @details :private
271     //! パーティクルコレクションに新しくパーティクル粒子を追加します。
272     //! パラメータは重要なもの以外は未初期化です。
273     //!
274     //! @param[in] count 追加する個数です。
275     //! @return 実際に追加できた個数です。
276     int AddParticles(int count);
277 #endif
278 
279     //! @brief パーティクルの更新処理を行います。
280     //! @param[in] particleContext パーティクルコンテキストです。
281     void UpdateParticles(ParticleContext* particleContext);
282 
283     //! @brief        パーティクルコレクションを空にします。
284     void ClearParticleCollection();
285 
286     //! @details :private
Srand(u32 seed)287     void Srand(u32 seed)
288     {
289         m_ParticleRandom.Srand(seed);
290     }
291 
292     //! @brief スケールのオフセット値を取得します。
293     //! @return スケールのオフセット値を返します。
GetScaleOffset()294     const nw::math::VEC3& GetScaleOffset() const
295     {
296         return this->m_ScaleOffset;
297     }
298 
299     //! @brief スケールのオフセット値を設定します。
300     //!
301     //! @param[in] offset 新しいオフセット値
SetScaleOffset(const nw::math::VEC3 & offset)302     void SetScaleOffset(const nw::math::VEC3& offset)
303     {
304         this->m_ScaleOffset = offset;
305     }
306 
307     //! @brief 回転のオフセット値を取得します。
308     //! @return 回転のオフセット値を返します。
GetRotateOffset()309     const nw::math::VEC3& GetRotateOffset() const
310     {
311         return this->m_RotateOffset;
312     }
313 
314     //! @brief 回転のオフセット値を設定します。
315     //!
316     //! @param[in] offset 新しいオフセット値
SetRotateOffset(const nw::math::VEC3 & offset)317     void SetRotateOffset(const nw::math::VEC3& offset)
318     {
319         this->m_RotateOffset = offset;
320     }
321 
322     //! @details :private
WorldMatrix()323     const nw::math::MTX34& WorldMatrix()
324     {
325         if (this->GetResParticleSet().GetIsForceWorld())
326         {
327             return nw::math::MTX34::Identity();
328         }
329         else
330         {
331             ParticleModel* model = static_cast<ParticleModel*>(this->GetParent());
332             return model->WorldMatrix();
333         }
334     }
335 
336     //! @details :private
InverseWorldMatrix()337     const nw::math::MTX34& InverseWorldMatrix()
338     {
339         if (this->GetResParticleSet().GetIsForceWorld())
340         {
341             return nw::math::MTX34::Identity();
342         }
343         else
344         {
345             ParticleModel* model = static_cast<ParticleModel*>(this->GetParent());
346             return model->InverseWorldMatrix();
347         }
348     }
349 
350     //! @brief 描画順を取得します。
351     //! @return 生成順の時にtrueを返します。
IsAscendingOrder()352     bool IsAscendingOrder() const
353     {
354         const ResParticleShapeBuilder& resShapeBuilder =
355             this->GetResParticleSet().GetParticleShapeBuilder();
356         return (resShapeBuilder.IsValid()) ? resShapeBuilder.IsAscendingOrder() : true;
357     }
358 
359     //@}
360 
361     //----------------------------------------
362     //! @name 初期化/更新
363     //@{
364 
365     //! @brief 新しく追加したパーティクルを初期化します。
366     //! @details :private
367     //!
368     //! @param[in] startIndex 初期化を開始するパーティクルのストリーム上のインデックスです。
369     //! @param[in] count      初期化するパーティクルの数です。
370     //! @param[in] incrIndex  インデックスの変化する方向を 1, または -1 で指定します。
371     //! @param[in] time       現在の時刻です。
372     void InitializeParticles(
373         int startIndex,
374         int count,
375         int incrIndex,
376         ParticleTime time);
377 
378     //@}
379 
380 protected:
381     //----------------------------------------
382     //! @name コンストラクタ/デストラクタ
383     //@{
384 
385     //! コンストラクタです。
386     ParticleSet(
387         os::IAllocator* allocator,
388         ResParticleSet resObj,
389         const ParticleSet::Description& description);
390 
391     //! デストラクタです。
392     virtual ~ParticleSet();
393 
394     //@}
395 
396 private:
397     ParticleCollection* m_ParticleCollection;
398 
399     ParticleRandom m_ParticleRandom;
400 
401     ut::MoveArray<Initializer> m_Initializers;
402     ut::MoveArray<Updater> m_Updaters;
403 
404     math::VEC3 m_ScaleOffset;
405     math::VEC3 m_RotateOffset;
406 
407 
408 };
409 
410 } // namespace gfx
411 } // namespace nw
412 
413 #endif // NW_GFX_PARTICLESET_H_
414