/*---------------------------------------------------------------------------* Project: NintendoWare File: gfx_ParticleEmitter.h Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo and/or its licensed developers and are protected by national and international copyright laws. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. The content herein is highly confidential and should be handled accordingly. $Revision: 31311 $ *---------------------------------------------------------------------------*/ #ifndef NW_GFX_PARTICLEEMITTER_H_ #define NW_GFX_PARTICLEEMITTER_H_ #include #include #include #include #include namespace nw { namespace gfx { class ParticleEmitter; //--------------------------------------------------------------------------- //! @brief パーティクルエミッタを表すクラスです。 //--------------------------------------------------------------------------- class ParticleEmitter : public TransformNode { private: NW_DISALLOW_COPY_AND_ASSIGN(ParticleEmitter); public: NW_UT_RUNTIME_TYPEINFO; //! @brief 設定内容です。 struct Description : public TransformNode::Description { //! @brief コンストラクタです。 Description() {} }; //---------------------------------------- //! @name 作成/破棄 //@{ //! @brief リソースからParticleEmitterノードを生成します。 //! //! @param[in] parent 親のノードです。 //! @param[in] resource リソースです。 //! @param[in] description 設定内容です。 //! @param[in] allocator アロケータです。 //! //! @return 生成されたParticleEmitterノードです。 //! static ParticleEmitter* Create( SceneNode* parent, ResSceneObject resource, const ParticleEmitter::Description& description, os::IAllocator* allocator); //! @brief 生成時に必要なデバイスメモリサイズを取得します。 //! @param[in] resource リソースです。 //! @param[in] description 設定内容です。 //! @param[in] alignment 計算に用いるアライメントです。2 のべき乗である必要があります。 //! @return 必要なデバイスメモリサイズです。 static size_t GetMemorySize( ResParticleEmitter resource, const ParticleEmitter::Description& description, size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) { os::MemorySizeCalculator size(alignment); GetMemorySizeInternal(&size, resource, description); return size.GetSizeWithPadding(alignment); } //! @details :private static void GetMemorySizeInternal( os::MemorySizeCalculator* pSize, ResParticleEmitter resource, const ParticleEmitter::Description& description); //@} //---------------------------------------- //! @name 更新 //@{ //! @brief ビジターを受け付けます。 //! //! @param[in] visitor ビジターです。 //! virtual void Accept(ISceneVisitor* visitor); //! @brief フレームを更新します。 //! @details パーティクル用のAnimFrameControllerの値を進めます。 //! 実際の放出処理に先行して実行してください。 void UpdateParticleFrame() { m_ParticleAnimFrameController.UpdateFrame(); } //! @brief エミッタを初期状態に戻します。 //! @details 放出用の内部パラメータをリセットし、時間を0に戻します。 void Reset() { m_IsFirstEmission = true; m_EmissionCount = 0; m_NextEmissionTime = 0; // フレームコントローラはFrameを0にするだけです。 m_ParticleAnimFrameController.SetFrame(0); } //@} //---------------------------------------- //! @name リソース //@{ //! @brief リソースを取得します。 //! @return リソースを返します。 ResParticleEmitter GetResParticleEmitter() { return ResDynamicCast( this->GetResSceneObject() ); } //! @brief リソースを取得します。 //! @return リソースを返します。 const ResParticleEmitter GetResParticleEmitter() const { return ResDynamicCast( this->GetResSceneObject() ); } //! @brief 放出パラメータのリソースを取得します。 // ここで取得したリソースは保持しないでください。 //! @param[in] copyOnly 複製の場合のみ取得します。 //! @return リソースを返します。 ResParticleEmitterParameter GetResParticleEmitterParameterCopy(bool copyOnly = false) { if (m_ResParameter.IsValid()) { return m_ResParameter; } if (!copyOnly && this->GetResParticleEmitter().IsValid()) { return ResParticleEmitterParameter(&this->GetResParticleEmitter().ptr()->m_IsResourceCopyEnabled); } return m_ResParameter; // invalid } //! @brief 放出パラメータのリソースを取得します。 // ここで取得したリソースは保持しないでください。 //! @param[in] copyOnly 複製の場合のみ取得します。 //! @return リソースを返します。 const ResParticleEmitterParameter GetResParticleEmitterParameterCopy(bool copyOnly = false) const { if (m_ResParameter.IsValid()) { return m_ResParameter; } if (!copyOnly && this->GetResParticleEmitter().IsValid()) { return ResParticleEmitterParameter(&this->GetResParticleEmitter().ptr()->m_IsResourceCopyEnabled); } return m_ResParameter; // invalid } //! @brief 形状のリソースを取得します。 // ここで取得したリソースは保持しないでください。 //! @param[in] copyOnly 複製の場合のみ取得します。 //! @return リソースを返します。 ResParticleForm GetResParticleFormCopy(bool copyOnly = false) { if (m_ResForm.IsValid()) { return m_ResForm; } if (!copyOnly && this->GetResParticleEmitter().IsValid()) { return this->GetResParticleEmitter().GetParticleForm(); } return m_ResForm; // invalid } //! @brief 形状のリソースを取得します。 // ここで取得したリソースは保持しないでください。 //! @param[in] copyOnly 複製の場合のみ取得します。 //! @return リソースを返します。 const ResParticleForm GetResParticleFormCopy(bool copyOnly = false) const { if (m_ResForm.IsValid()) { return m_ResForm; } if (!copyOnly && this->GetResParticleEmitter().IsValid()) { return this->GetResParticleEmitter().GetParticleForm(); } return m_ResForm; // invalid } //@} //---------------------------------------- //! @name 取得/設定 //@{ //! @brief 放出量を計算します。 //! //! @param[in] prevTime 前回の時刻です。 //! @param[in] time 現在の時刻です。 //! //! @return 放出量を返します。 int GetEmissionCount(f32 prevTime, f32 time); //! @brief 放出先のParticleSetを設定します。 //! //! @param[in] particleSet 放出先のParticleSetです。 //! void SetParticleSet(ParticleSet* particleSet) { this->m_ParticleSet = particleSet; } //! @brief 放出先のParticleSetを取得します。 //! @return 放出先のParticleSetを返します。 ParticleSet* GetParticleSet() { return this->m_ParticleSet; } //! @brief 放出先のParticleSetを取得します。 //! @return 放出先のParticleSetを返します。 const ParticleSet* GetParticleSet() const { return this->m_ParticleSet; } //! @brief アニメーションフレーム制御情報を取得します。 //! @return アニメーションフレームコントローラを返します。 anim::AnimFrameController& ParticleAnimFrameController() { return m_ParticleAnimFrameController; } //! @brief アニメーションフレーム制御情報を取得します。 //! @return アニメーションフレームコントローラを返します。 const anim::AnimFrameController& ParticleAnimFrameController() const { return m_ParticleAnimFrameController; } //! @details :private void Srand(u32 seed) { m_ParticleRandom.Srand(seed); } //! @brief パーティクルの放出時間が終了していないことを調べます。 //! @return 放出が終了していなければtrueを返します。 bool IsAlive() const { const ResParticleEmitterParameter resource = this->GetResParticleEmitterParameterCopy(false); if (!resource.IsValid()) { return false; } if (resource.GetEmissionRatio() == 0) { return false; } if (resource.GetEmissionSpanInfinity()) { return true; } f32 time = m_ParticleAnimFrameController.GetFrame(); f32 cookedTime = time - resource.GetEmissionStart() - 1; if (cookedTime >= resource.GetEmissionSpan()) { return false; } return true; } //@} //---------------------------------------- //! @name 放出 //@{ //! @brief 放出処理を行います。 //! @details 前回の放出から現在の時間までに放出されるはずのパーティクル粒子を放出します。 //! @param[in] particleContext パーティクルコンテキストです。 //! //! @return 放出量を返します。 int Emission(ParticleContext* particleContext); //@} //---------------------------------------- //! @name エミッタ形状 //@{ #ifdef NW_GFX_PARTICLE_COMPAT_1_1 //! @details :private static void CalcCubeForm( const ResParticleCubeForm& cubeForm, int emissionCount, ParticleRandom* random, nw::math::VEC3* positions); //! @details :private static void CalcCylinderForm( const ResParticleCylinderForm& cylinderForm, int emissionCount, ParticleRandom* random, nw::math::VEC3* positions); //! @details :private static void CalcDiscForm( const ResParticleDiscForm& discForm, int emissionCount, ParticleRandom* random, nw::math::VEC3* positions); //! @details :private static void CalcPointForm( const ResParticlePointForm& pointForm, int emissionCount, ParticleRandom* random, nw::math::VEC3* positions); //! @details :private static void CalcSphereForm( const ResParticleSphereForm& sphereForm, int emissionCount, ParticleRandom* random, nw::math::VEC3* positions); //! @details :private static void CalcRectangleForm( const ResParticleRectangleForm& rectangleForm, int emissionCount, ParticleRandom* random, nw::math::VEC3* positions); #else //! @details :private static void CalcCubeForm( const ResParticleCubeForm& cubeForm, int emissionCount, ParticleRandom* random, u16* activeIndex, int incrIndex, nw::math::VEC3* targetTranslate); //! @details :private static void CalcCylinderForm( const ResParticleCylinderForm& cylinderForm, int emissionCount, ParticleRandom* random, u16* activeIndex, int incrIndex, nw::math::VEC3* targetTranslate); //! @details :private static void CalcDiscForm( const ResParticleDiscForm& discForm, int emissionCount, ParticleRandom* random, u16* activeIndex, int incrIndex, nw::math::VEC3* targetTranslate); //! @details :private static void CalcPointForm( const ResParticlePointForm& pointForm, int emissionCount, ParticleRandom* random, u16* activeIndex, int incrIndex, nw::math::VEC3* targetTranslate); //! @details :private static void CalcSphereForm( const ResParticleSphereForm& sphereForm, int emissionCount, ParticleRandom* random, u16* activeIndex, int incrIndex, nw::math::VEC3* targetTranslate); //! @details :private static void CalcRectangleForm( const ResParticleRectangleForm& rectangleForm, int emissionCount, ParticleRandom* random, u16* activeIndex, int incrIndex, nw::math::VEC3* targetTranslate); #endif //@} protected: //---------------------------------------- //! @name コンストラクタ/デストラクタ //@{ //! @brief コンストラクタです。 //! @param[in] allocator メモリアロケータです。 //! @param[in] resObj エミッタのリソースです。 //! @param[in] description ディスクリプションです。 //! @param[in] resParameterObj エミッタパラメータのリソースです。 //! @param[in] resFormObj 形状のリソースです。 ParticleEmitter( os::IAllocator* allocator, ResParticleEmitter resObj, const ParticleEmitter::Description& description, ResParticleEmitterParameter resParameterObj, ResParticleForm resFormObj); //! @brief デストラクタです。 virtual ~ParticleEmitter(); //@} private: bool m_IsFirstEmission; f32 m_EmissionCount; s32 m_NextEmissionTime; ParticleSet* m_ParticleSet; ParticleRandom m_ParticleRandom; anim::AnimFrameController m_ParticleAnimFrameController; ResParticleEmitterParameter m_ResParameter; ResParticleForm m_ResForm; }; } // namespace gfx } // namespace nw #endif // NW_GFX_PARTICLEEMITTER_H_