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