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