/*---------------------------------------------------------------------------* Project: NintendoWare File: gfx_ParticleSet.h Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. 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. $Revision: 28677 $ *---------------------------------------------------------------------------*/ #ifndef NW_GFX_PARTICLESET_H_ #define NW_GFX_PARTICLESET_H_ #include #include #include #include #include #include namespace nw { namespace gfx { class ParticleCollection; class ParticleContext; class ParticleShape; //--------------------------------------------------------------------------- //! @brief パーティクル群を表すクラスです。 //--------------------------------------------------------------------------- class ParticleSet : public SceneNode { private: NW_DISALLOW_COPY_AND_ASSIGN(ParticleSet); public: NW_UT_RUNTIME_TYPEINFO; //! @brief 設定内容です。 struct Description : public SceneNode::Description { s32 maxInitializers; //!< ParticleInitializerのバッファの数です。 s32 maxUpdaters; //!< ParticleUpdaterのバッファの数です。 //! @brief コンストラクタです。 Description() : maxInitializers(0), maxUpdaters(0) {} }; //! @brief ランタイム用のイニシャライザの管理情報です。 struct Initializer { bool m_IsCopied; //!< コピーされたリソースであることを表すフラグです。 const ResParticleInitializerData *resource; //!< リソースへのポインタです。 u32 work; //!< ワークエリアです。 // 高速化のためのキャッシュ nw::ut::ResTypeInfo m_Type; void* m_TargetStreams[2]; //!< 変更対象のストリームへのポインタです。 }; //! @brief ランタイム用のイニシャライザの管理情報です。 struct Updater { bool m_IsCopied; //!< コピーされたリソースであることを表すフラグです。 const ResParticleUpdaterData *resource; //!< リソースへのポインタです。 u32 work; //!< ワークエリアです。 // 高速化のためのキャッシュ nw::ut::ResTypeInfo m_Type; void* m_TargetStreams[2]; //!< 変更対象のストリームへのポインタです。 u32 m_Flags; //!< フラグです。 enum Flag { FLAG_IS_HAS_CURVE_ANIM = 0x1 << 0 //!< カーブアニメーションを保持しているかのフラグです。 }; //! @brief 任意のフラグが有効になっているか取得します。 //! @param[in] flags 有効か調べるフラグです。 //! @return 有効な場合はtrueを返します。 inline bool IsEnabledFlags(bit32 flags) const { return ut::CheckFlag(m_Flags, flags); } //! @brief 任意のフラグを有効に設定します。 //!@param[in] flags 有効にするフラグです。 inline void EnableFlags(bit32 flags) { m_Flags = ut::EnableFlag(m_Flags, flags); } }; //---------------------------------------- //! @name 作成/破棄 //@{ //! @brief リソースからパーティクルセットを生成します。 //! //! @param[in] parent 親のノードです。 //! @param[in] resource リソースです。 //! @param[in] description 設定内容です。 //! @param[in] mainAllocator メインアロケータです。 //! @param[in] deviceAllocator デバイスアロケータです。 //! @param[in] shape シェイプです。 //! //! @return 生成されたトランスフォームノードです。 //! static ParticleSet* Create( SceneNode* parent, ResSceneObject resource, const ParticleSet::Description& description, os::IAllocator* mainAllocator, os::IAllocator* deviceAllocator, ParticleShape* shape); //! @brief 生成時に必要なメモリサイズを取得します。 //! @param[in] resource リソースです。 //! @param[in] description 設定内容です。 //! @param[in] alignment 計算に用いるアライメントです。2 のべき乗である必要があります。 //! @return 必要なメモリサイズです。 static size_t GetMemorySize( ResParticleSet resource, const ParticleSet::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, ResParticleSet resource, const ParticleSet::Description& description); //! @brief 生成時に必要なデバイスメモリサイズを取得します。 //! @param[in] resource リソースです。 //! @param[in] alignment 計算に用いるアライメントです。2 のべき乗である必要があります。 //! @return 必要なデバイスメモリサイズです。 static size_t GetDeviceMemorySize( ResParticleSet resource, size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT) { os::MemorySizeCalculator size(alignment); GetDeviceMemorySizeInternal(&size, resource); return size.GetSizeWithPadding(alignment); } //! @details :private static void GetDeviceMemorySizeInternal( os::MemorySizeCalculator* pSize, ResParticleSet resource); //@} //---------------------------------------- //! @name 更新 //@{ //! @brief ビジターを受け付けます。 //! //! @param[in] visitor ビジターです。 //! virtual void Accept(ISceneVisitor* visitor); //@} //---------------------------------------- //! @name 取得/設定 //@{ //! @brief リソースを取得します。 //! @return 設定されているリソースです。 ResParticleSet GetResParticleSet() { return ResDynamicCast( this->GetResSceneObject() ); } //! @brief リソースを取得します。 //! @return 設定されているリソースです。 const ResParticleSet GetResParticleSet() const { return ResDynamicCast( this->GetResSceneObject() ); } //! @brief パーティクルコレクションを設定します。 //! @param[in] node 設定するパーティクルコレクションです。 //! @return 既に設定されている場合は、falseを返します。 bool AttachParticleCollection(ParticleCollection* node) { if (this->m_ParticleCollection != NULL) { return false; } this->m_ParticleCollection = node; return true; } //! @brief パーティクルコレクションを取得します。 //! @return 設定されているパーティクルコレクションです。 ParticleCollection* GetParticleCollection() { return this->m_ParticleCollection; } //! @brief パーティクルコレクションを取得します。 //! @return 設定されているパーティクルコレクションです。 const ParticleCollection* GetParticleCollection() const { return this->m_ParticleCollection; } //! @brief イニシャライザの配列を取得します。 //! @return イニシャライザの配列へのポインタを返します。 ut::MoveArray* GetInitializers() { return &this->m_Initializers; } //! @brief イニシャライザの配列を取得します。 //! @return イニシャライザの配列へのポインタを返します。 const ut::MoveArray* GetInitializers() const { return &this->m_Initializers; } //! @brief アップデータの配列を取得します。 //! @return アップデータの配列へのポインタを返します。 ut::MoveArray* GetUpdaters() { return &this->m_Updaters; } //! @brief アップデータの配列を取得します。 //! @return アップデータの配列へのポインタを返します。 const ut::MoveArray* GetUpdaters() const { return &this->m_Updaters; } #ifdef NW_GFX_PARTICLE_COMPAT_1_1 //! @brief パーティクルを追加します。 //! @details :private void AddParticles( const nw::math::MTX34& emitterMatrix, const nw::math::VEC3* const positions, ParticleSet* parentParticleSet, const u16* const parentIndices, int count); #else //! @brief パーティクルを追加します。 //! @details :private //! パーティクルコレクションに新しくパーティクル粒子を追加します。 //! パラメータは重要なもの以外は未初期化です。 //! //! @param[in] count 追加する個数です。 //! @return 実際に追加できた個数です。 int AddParticles(int count); #endif //! @brief パーティクルの更新処理を行います。 //! @param[in] particleContext パーティクルコンテキストです。 void UpdateParticles(ParticleContext* particleContext); //! @brief パーティクルコレクションを空にします。 void ClearParticleCollection(); //! @details :private void Srand(u32 seed) { m_ParticleRandom.Srand(seed); } //! @brief スケールのオフセット値を取得します。 //! @return スケールのオフセット値を返します。 const nw::math::VEC3& GetScaleOffset() const { return this->m_ScaleOffset; } //! @brief スケールのオフセット値を設定します。 //! //! @param[in] offset 新しいオフセット値 void SetScaleOffset(const nw::math::VEC3& offset) { this->m_ScaleOffset = offset; } //! @brief 回転のオフセット値を取得します。 //! @return 回転のオフセット値を返します。 const nw::math::VEC3& GetRotateOffset() const { return this->m_RotateOffset; } //! @brief 回転のオフセット値を設定します。 //! //! @param[in] offset 新しいオフセット値 void SetRotateOffset(const nw::math::VEC3& offset) { this->m_RotateOffset = offset; } //! @details :private const nw::math::MTX34& WorldMatrix() { if (this->GetResParticleSet().GetIsForceWorld()) { return nw::math::MTX34::Identity(); } else { ParticleModel* model = static_cast(this->GetParent()); return model->WorldMatrix(); } } //! @details :private const nw::math::MTX34& InverseWorldMatrix() { if (this->GetResParticleSet().GetIsForceWorld()) { return nw::math::MTX34::Identity(); } else { ParticleModel* model = static_cast(this->GetParent()); return model->InverseWorldMatrix(); } } //! @brief 描画順を取得します。 //! @return 生成順の時にtrueを返します。 bool IsAscendingOrder() const { const ResParticleShapeBuilder& resShapeBuilder = this->GetResParticleSet().GetParticleShapeBuilder(); return (resShapeBuilder.IsValid()) ? resShapeBuilder.IsAscendingOrder() : true; } //@} //---------------------------------------- //! @name 初期化/更新 //@{ //! @brief 新しく追加したパーティクルを初期化します。 //! @details :private //! //! @param[in] startIndex 初期化を開始するパーティクルのストリーム上のインデックスです。 //! @param[in] count 初期化するパーティクルの数です。 //! @param[in] incrIndex インデックスの変化する方向を 1, または -1 で指定します。 //! @param[in] time 現在の時刻です。 void InitializeParticles( int startIndex, int count, int incrIndex, ParticleTime time); //@} protected: //---------------------------------------- //! @name コンストラクタ/デストラクタ //@{ //! コンストラクタです。 ParticleSet( os::IAllocator* allocator, ResParticleSet resObj, const ParticleSet::Description& description); //! デストラクタです。 virtual ~ParticleSet(); //@} private: ParticleCollection* m_ParticleCollection; ParticleRandom m_ParticleRandom; ut::MoveArray m_Initializers; ut::MoveArray m_Updaters; math::VEC3 m_ScaleOffset; math::VEC3 m_RotateOffset; }; } // namespace gfx } // namespace nw #endif // NW_GFX_PARTICLESET_H_