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