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